Vibecode Cloudcraft
track this build4 phases, 12 steps, beginner friendly0%The visible cloud architecture diagrams loop is buildable, but a credible replacement needs more than the first screen. Cloudcraft earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope.
You are building a lean indie version of Cloudcraft. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Cloudcraft · indie build A diagramming tool that draws what is actually deployed by reading a cloud account read only, where the engineering is turning a flat list of resources into a readable topology and the discipline is knowing that a diagram is stale the moment it is drawn. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Collection | Read-only credentials enumerating resources and relationships | the relationships are the diagram; the resource list alone is a spreadsheet | | Topology | A graph built from real references between resources | inferred relationships are guesses and should be labelled as such | | Layout | Hierarchical grouping by account, region and network boundary | a flat graph of four hundred resources is not a diagram | | Freshness | Every element carries the time it was observed | a diagram of live infrastructure is a snapshot and should say so | | Runtime | TypeScript with SQLite and a local renderer | the collected inventory is sensitive and does not need a server | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the scanner and the renderer. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Read-only credentials for a real account** · free - Why: The whole build depends on enumerating real infrastructure, and the read-only constraint has to be true of the credentials rather than of your intentions. - Get it: Create a role or key with a read-only policy, scoped to the account you will scan, and verify a write is denied before scanning. - Verify: A write attempt with these credentials is denied - [ ] **An account with at least a hundred resources** · free to scan; the account itself costs what it costs - Why: Layout, collapsing and readability are all uninteresting on a small account and become the entire problem on a real one. - Get it: A real account you have permission to scan, ideally one with several regions and networks. - Verify: A scan returns at least a hundred resources across more than one region - [ ] **What you will not collect** · free - Why: Secret-bearing fields are excluded at collection, which means deciding which they are before the first scan rather than after they are in the database. - Get it: List the fields that can contain credentials, connection strings or keys for the resource types you will scan, and exclude them explicitly. - Verify: A written exclusion list exists and is applied in the collector - [ ] **Your redaction default and sharing rules** · free - Why: An architecture diagram is a map of your estate for anyone attacking you, and the default matters more than the option. - Get it: Decide what is redacted by default and who may produce an unredacted export. - Verify: A written note states the default redaction and who may override it ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. - presentation and enterprise controls - multiplayer cursors and comments - large template libraries - high-fidelity import and export If one of those is essential to you, that is the reason to keep paying for Cloudcraft, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Cloudcraft The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me architecture diagrams generated from the infrastructure that actually exists to replace Cloudcraft. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero This build reads a cloud account, which means it holds credentials that can enumerate every resource you own. Two rules follow and both are structural rather than advisory. The credentials are read only. Not read-mostly, not read plus a tagging call for convenience. A diagramming tool with write access is a diagramming tool that can delete a production database because of a bug in a layout algorithm, and there is no benefit that justifies it. The output is sensitive. An architecture diagram names your services, shows what is exposed to the internet, and often carries resource identifiers and address ranges. It is a map for anyone attacking you. So exports are redacted by default, sharing is deliberate, and any field that could carry a secret is excluded at collection rather than filtered at display. ### Stack (fixed, do not substitute) - Collection: Read-only credentials enumerating resources and relationships · the relationships are the diagram; the resource list alone is a spreadsheet - Topology: A graph built from real references between resources · inferred relationships are guesses and should be labelled as such - Layout: Hierarchical grouping by account, region and network boundary · a flat graph of four hundred resources is not a diagram - Freshness: Every element carries the time it was observed · a diagram of live infrastructure is a snapshot and should say so - Runtime: TypeScript with SQLite and a local renderer · the collected inventory is sensitive and does not need a server ### Data model (create this before Phase 1) - scans(id, account_ref, regions_json, started_at, finished_at, resource_count, partial_reason) - resources(id, scan_id, kind, identifier, name, region, tags_json, config_summary_json, observed_at) - edges(from_resource_id, to_resource_id, kind, confidence, evidence) · kind is contains, connects, permits or infers - boundaries(id, scan_id, kind, identifier, parent_id) · accounts, networks and subnets as nesting - diagrams(id, scan_id, layout_json, redaction_level, generated_at) - drifts(id, from_scan_id, to_scan_id, resource_identifier, change_kind, detail) · what changed between scans - An edge records its evidence, because a connection read from a configuration and one inferred from a naming convention are different claims. ### Phase 1 · Reading an account without being able to change it Build: Enumerate resources across regions with read-only credentials. Handle pagination, throttling and permissions you do not have. Record a partial scan as partial rather than presenting it as complete. Trap: A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. Done when: A scan runs with credentials that have no write permissions, verified by attempting a write and confirming it is denied. Missing permissions produce a recorded gap rather than a silent omission. Throttling is handled with backoff rather than failing the scan. A partial scan is marked partial everywhere its output appears. Do not build yet: No topology, layout or diagrams. ### Phase 2 · Relationships, and how sure you are Build: Build edges from real configuration references. Where a relationship is inferred from naming or convention, record it as inferred with its evidence. Render the two differently. Trap: Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. Done when: Edges record whether they came from configuration or inference, with evidence. Inferred edges render distinctly from read ones. A resource with no discoverable relationships appears isolated rather than being connected by guesswork. Security group and routing relationships are read from configuration rather than inferred. Do not build yet: No layout or diagrams yet. ### Phase 3 · Making four hundred resources legible Build: Group by account, region and network boundary as nested containers. Collapse repeated identical resources into a count. Let the viewer expand and filter rather than showing everything at once. Trap: Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. Done when: A four hundred resource account produces a readable diagram through nesting and collapsing. Repeated identical resources collapse into a labelled count rather than being hidden. Expanding a group reveals its contents in place. Nothing is omitted from the diagram, only folded, verified by comparing counts against the scan. Do not build yet: No drift or export yet. ### Phase 4 · Saying how old the picture is Build: Show the scan time prominently on every diagram and per element. Compare consecutive scans and report drift. Mark a diagram as stale past a configured age rather than displaying it unchanged. Trap: A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. Done when: Every diagram shows its scan time prominently. A diagram past the staleness threshold is visibly marked wherever it appears including in exports. Drift between two scans is reported by resource. A resource that disappeared between scans is distinguished from one that was unreadable due to permissions. Do not build yet: No export or sharing yet. ### Phase 5 · Exporting a map of your estate carefully Build: Redact identifiers, addresses and account references by default on export. Require a deliberate action to include them. Exclude anything that could carry a secret at collection time rather than filtering it on export. Trap: Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. Done when: Fields that could carry secrets are excluded during collection, verified by inspecting the stored scan. Exports redact identifiers and addresses by default. Including them requires a deliberate action that is recorded. An export carries its scan time and redaction level visibly. Do not build yet: Nothing after this. ### Out of scope (and why) - Cost estimation from the diagram, which needs pricing data and usage patterns rather than topology. - Multi-cloud coverage, which is an adapter per provider and a taxonomy problem on top. - Any write access, including tagging, which is excluded on principle rather than by omission. - Security assessment, which is a different discipline and where a diagramming tool's confidence would be misleading. ### README must contain - That the credentials are read only and a write attempt is verified to fail in the test suite - That inferred relationships are recorded with evidence and drawn differently from read ones - That a partial scan is marked partial, because absence must not look like emptiness - That the scan time appears on the diagram itself and stale diagrams are visibly degraded - That secret-bearing fields are excluded at collection rather than filtered at export ===== AGENTS.md ===== # Agent instructions · Cloudcraft indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Read-only credentials enumerating resources and relationships, A graph built from real references between resources, Hierarchical grouping by account, region and network boundary, Every element carries the time it was observed, TypeScript with SQLite and a local renderer. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ===== BUILD_PLAN.md ===== # Build plan · Cloudcraft A diagramming tool that draws what is actually deployed by reading a cloud account read only, where the engineering is turning a flat list of resources into a readable topology and the discipline is knowing that a diagram is stale the moment it is drawn. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Reading an account without being able to change it A scan enumerates resources using credentials that cannot write. ### Steps 1. Use read-only credentials Verify by attempting a write and expecting denial. Files: `src/credentials.ts`, `tests/readonly.test.ts` 2. Record what could not be read Absence must not look like emptiness. Files: `src/scan.ts` 3. Back off on throttling Enumerating a large account will hit limits. Files: `src/scan.ts` ### Done when - [ ] Write attempts are denied by the credentials - [ ] Missing permissions produce recorded gaps - [ ] Throttling is handled with backoff - [ ] Partial scans are marked partial ### Watch out - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. ## Phase 2 · Relationships, and how sure you are The graph distinguishes what you read from what you inferred. ### Steps 1. Read relationships from configuration The references that actually exist, not the ones that seem likely. Files: `src/topology.ts` 2. Record evidence per edge So a reader can tell a fact from a guess. Files: `src/edges.ts` 3. Render inference differently A dashed line and a solid line are different claims. Files: `src/render.ts` ### Done when - [ ] Edges record configuration or inference with evidence - [ ] Inferred edges render distinctly - [ ] Unconnected resources appear isolated - [ ] Security and routing edges come from configuration ### Watch out - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. ## Phase 3 · Making four hundred resources legible A real account produces a diagram someone can read. ### Steps 1. Nest by real boundaries Account, region, network. The nesting is the structure people think in. Files: `src/layout.ts` 2. Collapse repetition into counts Twenty identical instances is one shape and a number. Files: `src/collapse.ts` 3. Fold rather than filter Filtering hides things silently. Folding keeps the count visible. Files: `src/layout.ts` ### Done when - [ ] Four hundred resources produce a readable diagram - [ ] Repetition collapses into labelled counts - [ ] Groups expand in place - [ ] Counts reconcile against the scan ### Watch out - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. ## Phase 4 · Saying how old the picture is Nobody mistakes a snapshot for the current state. ### Steps 1. Put the scan time on the diagram On the image, not in a menu. Exports get separated from their context. Files: `src/render.ts` 2. Report drift between scans What appeared, disappeared and changed. Files: `src/drift.ts` 3. Distinguish gone from unreadable A permissions gap is not a deletion. Files: `src/drift.ts` ### Done when - [ ] Scan time appears on every diagram - [ ] Stale diagrams are visibly marked, including exports - [ ] Drift is reported per resource - [ ] Disappeared and unreadable are distinguished ### Watch out - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ## Not in this build - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. ## After v1, if you want it - Scheduled scans with drift alerting, which is where this becomes operationally useful - Diagram diffs between two scans as a visual, since the list form is hard to read - Annotation layers that survive rescanning, so human context is not lost each time ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Collected inventory. Sensitive, since it describes your entire estate. DB_PATH=./scans.db # Required · secret. Read only. A write attempt must fail. CLOUD_CREDENTIALS=a read-only profile name # Required. Which regions to enumerate. Omissions are recorded rather than silent. SCAN_REGIONS=eu-west-1,eu-west-2 # Required. Past this a diagram is visibly marked stale, including in exports. STALE_AFTER_HOURS=72 # Required. A diagram is a map for an attacker. The default matters. EXPORT_REDACTION_DEFAULT=full # Required. Applied at collection so secrets are never stored rather than filtered later. EXCLUDED_FIELDS_PATH=./config/excluded-fields.txt
You are building a lean indie version of Cloudcraft. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Cloudcraft · indie build A diagramming tool that draws what is actually deployed by reading a cloud account read only, where the engineering is turning a flat list of resources into a readable topology and the discipline is knowing that a diagram is stale the moment it is drawn. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Collection | Read-only credentials enumerating resources and relationships | the relationships are the diagram; the resource list alone is a spreadsheet | | Topology | A graph built from real references between resources | inferred relationships are guesses and should be labelled as such | | Layout | Hierarchical grouping by account, region and network boundary | a flat graph of four hundred resources is not a diagram | | Freshness | Every element carries the time it was observed | a diagram of live infrastructure is a snapshot and should say so | | Runtime | TypeScript with SQLite and a local renderer | the collected inventory is sensitive and does not need a server | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the scanner and the renderer. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Read-only credentials for a real account** · free - Why: The whole build depends on enumerating real infrastructure, and the read-only constraint has to be true of the credentials rather than of your intentions. - Get it: Create a role or key with a read-only policy, scoped to the account you will scan, and verify a write is denied before scanning. - Verify: A write attempt with these credentials is denied - [ ] **An account with at least a hundred resources** · free to scan; the account itself costs what it costs - Why: Layout, collapsing and readability are all uninteresting on a small account and become the entire problem on a real one. - Get it: A real account you have permission to scan, ideally one with several regions and networks. - Verify: A scan returns at least a hundred resources across more than one region - [ ] **What you will not collect** · free - Why: Secret-bearing fields are excluded at collection, which means deciding which they are before the first scan rather than after they are in the database. - Get it: List the fields that can contain credentials, connection strings or keys for the resource types you will scan, and exclude them explicitly. - Verify: A written exclusion list exists and is applied in the collector - [ ] **Your redaction default and sharing rules** · free - Why: An architecture diagram is a map of your estate for anyone attacking you, and the default matters more than the option. - Get it: Decide what is redacted by default and who may produce an unredacted export. - Verify: A written note states the default redaction and who may override it ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. - presentation and enterprise controls - multiplayer cursors and comments - large template libraries - high-fidelity import and export If one of those is essential to you, that is the reason to keep paying for Cloudcraft, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Cloudcraft The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me architecture diagrams generated from the infrastructure that actually exists to replace Cloudcraft. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero This build reads a cloud account, which means it holds credentials that can enumerate every resource you own. Two rules follow and both are structural rather than advisory. The credentials are read only. Not read-mostly, not read plus a tagging call for convenience. A diagramming tool with write access is a diagramming tool that can delete a production database because of a bug in a layout algorithm, and there is no benefit that justifies it. The output is sensitive. An architecture diagram names your services, shows what is exposed to the internet, and often carries resource identifiers and address ranges. It is a map for anyone attacking you. So exports are redacted by default, sharing is deliberate, and any field that could carry a secret is excluded at collection rather than filtered at display. ### Stack (fixed, do not substitute) - Collection: Read-only credentials enumerating resources and relationships · the relationships are the diagram; the resource list alone is a spreadsheet - Topology: A graph built from real references between resources · inferred relationships are guesses and should be labelled as such - Layout: Hierarchical grouping by account, region and network boundary · a flat graph of four hundred resources is not a diagram - Freshness: Every element carries the time it was observed · a diagram of live infrastructure is a snapshot and should say so - Runtime: TypeScript with SQLite and a local renderer · the collected inventory is sensitive and does not need a server ### Data model (create this before Phase 1) - scans(id, account_ref, regions_json, started_at, finished_at, resource_count, partial_reason) - resources(id, scan_id, kind, identifier, name, region, tags_json, config_summary_json, observed_at) - edges(from_resource_id, to_resource_id, kind, confidence, evidence) · kind is contains, connects, permits or infers - boundaries(id, scan_id, kind, identifier, parent_id) · accounts, networks and subnets as nesting - diagrams(id, scan_id, layout_json, redaction_level, generated_at) - drifts(id, from_scan_id, to_scan_id, resource_identifier, change_kind, detail) · what changed between scans - An edge records its evidence, because a connection read from a configuration and one inferred from a naming convention are different claims. ### Phase 1 · Reading an account without being able to change it Build: Enumerate resources across regions with read-only credentials. Handle pagination, throttling and permissions you do not have. Record a partial scan as partial rather than presenting it as complete. Trap: A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. Done when: A scan runs with credentials that have no write permissions, verified by attempting a write and confirming it is denied. Missing permissions produce a recorded gap rather than a silent omission. Throttling is handled with backoff rather than failing the scan. A partial scan is marked partial everywhere its output appears. Do not build yet: No topology, layout or diagrams. ### Phase 2 · Relationships, and how sure you are Build: Build edges from real configuration references. Where a relationship is inferred from naming or convention, record it as inferred with its evidence. Render the two differently. Trap: Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. Done when: Edges record whether they came from configuration or inference, with evidence. Inferred edges render distinctly from read ones. A resource with no discoverable relationships appears isolated rather than being connected by guesswork. Security group and routing relationships are read from configuration rather than inferred. Do not build yet: No layout or diagrams yet. ### Phase 3 · Making four hundred resources legible Build: Group by account, region and network boundary as nested containers. Collapse repeated identical resources into a count. Let the viewer expand and filter rather than showing everything at once. Trap: Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. Done when: A four hundred resource account produces a readable diagram through nesting and collapsing. Repeated identical resources collapse into a labelled count rather than being hidden. Expanding a group reveals its contents in place. Nothing is omitted from the diagram, only folded, verified by comparing counts against the scan. Do not build yet: No drift or export yet. ### Phase 4 · Saying how old the picture is Build: Show the scan time prominently on every diagram and per element. Compare consecutive scans and report drift. Mark a diagram as stale past a configured age rather than displaying it unchanged. Trap: A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. Done when: Every diagram shows its scan time prominently. A diagram past the staleness threshold is visibly marked wherever it appears including in exports. Drift between two scans is reported by resource. A resource that disappeared between scans is distinguished from one that was unreadable due to permissions. Do not build yet: No export or sharing yet. ### Phase 5 · Exporting a map of your estate carefully Build: Redact identifiers, addresses and account references by default on export. Require a deliberate action to include them. Exclude anything that could carry a secret at collection time rather than filtering it on export. Trap: Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. Done when: Fields that could carry secrets are excluded during collection, verified by inspecting the stored scan. Exports redact identifiers and addresses by default. Including them requires a deliberate action that is recorded. An export carries its scan time and redaction level visibly. Do not build yet: Nothing after this. ### Out of scope (and why) - Cost estimation from the diagram, which needs pricing data and usage patterns rather than topology. - Multi-cloud coverage, which is an adapter per provider and a taxonomy problem on top. - Any write access, including tagging, which is excluded on principle rather than by omission. - Security assessment, which is a different discipline and where a diagramming tool's confidence would be misleading. ### README must contain - That the credentials are read only and a write attempt is verified to fail in the test suite - That inferred relationships are recorded with evidence and drawn differently from read ones - That a partial scan is marked partial, because absence must not look like emptiness - That the scan time appears on the diagram itself and stale diagrams are visibly degraded - That secret-bearing fields are excluded at collection rather than filtered at export ===== AGENTS.md ===== # Agent instructions · Cloudcraft indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Read-only credentials enumerating resources and relationships, A graph built from real references between resources, Hierarchical grouping by account, region and network boundary, Every element carries the time it was observed, TypeScript with SQLite and a local renderer. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ===== BUILD_PLAN.md ===== # Build plan · Cloudcraft A diagramming tool that draws what is actually deployed by reading a cloud account read only, where the engineering is turning a flat list of resources into a readable topology and the discipline is knowing that a diagram is stale the moment it is drawn. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Reading an account without being able to change it A scan enumerates resources using credentials that cannot write. ### Steps 1. Use read-only credentials Verify by attempting a write and expecting denial. Files: `src/credentials.ts`, `tests/readonly.test.ts` 2. Record what could not be read Absence must not look like emptiness. Files: `src/scan.ts` 3. Back off on throttling Enumerating a large account will hit limits. Files: `src/scan.ts` ### Done when - [ ] Write attempts are denied by the credentials - [ ] Missing permissions produce recorded gaps - [ ] Throttling is handled with backoff - [ ] Partial scans are marked partial ### Watch out - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. ## Phase 2 · Relationships, and how sure you are The graph distinguishes what you read from what you inferred. ### Steps 1. Read relationships from configuration The references that actually exist, not the ones that seem likely. Files: `src/topology.ts` 2. Record evidence per edge So a reader can tell a fact from a guess. Files: `src/edges.ts` 3. Render inference differently A dashed line and a solid line are different claims. Files: `src/render.ts` ### Done when - [ ] Edges record configuration or inference with evidence - [ ] Inferred edges render distinctly - [ ] Unconnected resources appear isolated - [ ] Security and routing edges come from configuration ### Watch out - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. ## Phase 3 · Making four hundred resources legible A real account produces a diagram someone can read. ### Steps 1. Nest by real boundaries Account, region, network. The nesting is the structure people think in. Files: `src/layout.ts` 2. Collapse repetition into counts Twenty identical instances is one shape and a number. Files: `src/collapse.ts` 3. Fold rather than filter Filtering hides things silently. Folding keeps the count visible. Files: `src/layout.ts` ### Done when - [ ] Four hundred resources produce a readable diagram - [ ] Repetition collapses into labelled counts - [ ] Groups expand in place - [ ] Counts reconcile against the scan ### Watch out - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. ## Phase 4 · Saying how old the picture is Nobody mistakes a snapshot for the current state. ### Steps 1. Put the scan time on the diagram On the image, not in a menu. Exports get separated from their context. Files: `src/render.ts` 2. Report drift between scans What appeared, disappeared and changed. Files: `src/drift.ts` 3. Distinguish gone from unreadable A permissions gap is not a deletion. Files: `src/drift.ts` ### Done when - [ ] Scan time appears on every diagram - [ ] Stale diagrams are visibly marked, including exports - [ ] Drift is reported per resource - [ ] Disappeared and unreadable are distinguished ### Watch out - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ## Not in this build - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. ## After v1, if you want it - Scheduled scans with drift alerting, which is where this becomes operationally useful - Diagram diffs between two scans as a visual, since the list form is hard to read - Annotation layers that survive rescanning, so human context is not lost each time ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Collected inventory. Sensitive, since it describes your entire estate. DB_PATH=./scans.db # Required · secret. Read only. A write attempt must fail. CLOUD_CREDENTIALS=a read-only profile name # Required. Which regions to enumerate. Omissions are recorded rather than silent. SCAN_REGIONS=eu-west-1,eu-west-2 # Required. Past this a diagram is visibly marked stale, including in exports. STALE_AFTER_HOURS=72 # Required. A diagram is a map for an attacker. The default matters. EXPORT_REDACTION_DEFAULT=full # Required. Applied at collection so secrets are never stored rather than filtered later. EXCLUDED_FIELDS_PATH=./config/excluded-fields.txt
You are building a production product version of Cloudcraft. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Cloudcraft · product brief ## Problem The visible cloud architecture diagrams loop is buildable, but a credible replacement needs more than the first screen. Cloudcraft earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A diagram of what is actually deployed, that says how old it is, distinguishes facts from guesses, and cannot change anything in the account it read. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. - presentation and enterprise controls - multiplayer cursors and comments - large template libraries - high-fidelity import and export ## Success criteria - A write attempt with the scan credentials is confirmed denied - Missing permissions are confirmed to produce recorded gaps - Inferred edges are confirmed to render distinctly - Scan time is confirmed present on every export - Secret-bearing fields are confirmed excluded at collection ===== BRIEF.md ===== # Build brief · Cloudcraft The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me architecture diagrams generated from the infrastructure that actually exists to replace Cloudcraft. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero This build reads a cloud account, which means it holds credentials that can enumerate every resource you own. Two rules follow and both are structural rather than advisory. The credentials are read only. Not read-mostly, not read plus a tagging call for convenience. A diagramming tool with write access is a diagramming tool that can delete a production database because of a bug in a layout algorithm, and there is no benefit that justifies it. The output is sensitive. An architecture diagram names your services, shows what is exposed to the internet, and often carries resource identifiers and address ranges. It is a map for anyone attacking you. So exports are redacted by default, sharing is deliberate, and any field that could carry a secret is excluded at collection rather than filtered at display. ### Stack (fixed, do not substitute) - Collection: Read-only credentials enumerating resources and relationships · the relationships are the diagram; the resource list alone is a spreadsheet - Topology: A graph built from real references between resources · inferred relationships are guesses and should be labelled as such - Layout: Hierarchical grouping by account, region and network boundary · a flat graph of four hundred resources is not a diagram - Freshness: Every element carries the time it was observed · a diagram of live infrastructure is a snapshot and should say so - Runtime: TypeScript with SQLite and a local renderer · the collected inventory is sensitive and does not need a server ### Data model (create this before Phase 1) - scans(id, account_ref, regions_json, started_at, finished_at, resource_count, partial_reason) - resources(id, scan_id, kind, identifier, name, region, tags_json, config_summary_json, observed_at) - edges(from_resource_id, to_resource_id, kind, confidence, evidence) · kind is contains, connects, permits or infers - boundaries(id, scan_id, kind, identifier, parent_id) · accounts, networks and subnets as nesting - diagrams(id, scan_id, layout_json, redaction_level, generated_at) - drifts(id, from_scan_id, to_scan_id, resource_identifier, change_kind, detail) · what changed between scans - An edge records its evidence, because a connection read from a configuration and one inferred from a naming convention are different claims. ### Phase 1 · Reading an account without being able to change it Build: Enumerate resources across regions with read-only credentials. Handle pagination, throttling and permissions you do not have. Record a partial scan as partial rather than presenting it as complete. Trap: A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. Done when: A scan runs with credentials that have no write permissions, verified by attempting a write and confirming it is denied. Missing permissions produce a recorded gap rather than a silent omission. Throttling is handled with backoff rather than failing the scan. A partial scan is marked partial everywhere its output appears. Do not build yet: No topology, layout or diagrams. ### Phase 2 · Relationships, and how sure you are Build: Build edges from real configuration references. Where a relationship is inferred from naming or convention, record it as inferred with its evidence. Render the two differently. Trap: Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. Done when: Edges record whether they came from configuration or inference, with evidence. Inferred edges render distinctly from read ones. A resource with no discoverable relationships appears isolated rather than being connected by guesswork. Security group and routing relationships are read from configuration rather than inferred. Do not build yet: No layout or diagrams yet. ### Phase 3 · Making four hundred resources legible Build: Group by account, region and network boundary as nested containers. Collapse repeated identical resources into a count. Let the viewer expand and filter rather than showing everything at once. Trap: Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. Done when: A four hundred resource account produces a readable diagram through nesting and collapsing. Repeated identical resources collapse into a labelled count rather than being hidden. Expanding a group reveals its contents in place. Nothing is omitted from the diagram, only folded, verified by comparing counts against the scan. Do not build yet: No drift or export yet. ### Phase 4 · Saying how old the picture is Build: Show the scan time prominently on every diagram and per element. Compare consecutive scans and report drift. Mark a diagram as stale past a configured age rather than displaying it unchanged. Trap: A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. Done when: Every diagram shows its scan time prominently. A diagram past the staleness threshold is visibly marked wherever it appears including in exports. Drift between two scans is reported by resource. A resource that disappeared between scans is distinguished from one that was unreadable due to permissions. Do not build yet: No export or sharing yet. ### Phase 5 · Exporting a map of your estate carefully Build: Redact identifiers, addresses and account references by default on export. Require a deliberate action to include them. Exclude anything that could carry a secret at collection time rather than filtering it on export. Trap: Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. Done when: Fields that could carry secrets are excluded during collection, verified by inspecting the stored scan. Exports redact identifiers and addresses by default. Including them requires a deliberate action that is recorded. An export carries its scan time and redaction level visibly. Do not build yet: Nothing after this. ### Out of scope (and why) - Cost estimation from the diagram, which needs pricing data and usage patterns rather than topology. - Multi-cloud coverage, which is an adapter per provider and a taxonomy problem on top. - Any write access, including tagging, which is excluded on principle rather than by omission. - Security assessment, which is a different discipline and where a diagramming tool's confidence would be misleading. ### README must contain - That the credentials are read only and a write attempt is verified to fail in the test suite - That inferred relationships are recorded with evidence and drawn differently from read ones - That a partial scan is marked partial, because absence must not look like emptiness - That the scan time appears on the diagram itself and stale diagrams are visibly degraded - That secret-bearing fields are excluded at collection rather than filtered at export ===== ARCHITECTURE.md ===== # Architecture · Cloudcraft ## Stack | Part | Choice | Why | | --- | --- | --- | | Collection | Read-only credentials enumerating resources and relationships | the relationships are the diagram; the resource list alone is a spreadsheet | | Topology | A graph built from real references between resources | inferred relationships are guesses and should be labelled as such | | Layout | Hierarchical grouping by account, region and network boundary | a flat graph of four hundred resources is not a diagram | | Freshness | Every element carries the time it was observed | a diagram of live infrastructure is a snapshot and should say so | | Runtime | TypeScript with SQLite and a local renderer | the collected inventory is sensitive and does not need a server | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Collection | Read-only enumeration with recorded gaps. | Any provider adapter, provided the credentials cannot write and gaps are recorded. | | Topology | Edges with evidence. | Any implementation, provided inference stays distinguishable from configuration. | | Layout | Nesting and collapsing at scale. | Any algorithm, provided it folds rather than filters. | | Freshness | Scan time and drift. | Any presentation, provided the time is on the diagram itself. | | Redaction | Exclusion at collection and export defaults. | Not swappable for export-time filtering, which means the data was stored. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DB_PATH` · required · Collected inventory. Sensitive, since it describes your entire estate. - `CLOUD_CREDENTIALS` · required, secret · Read only. A write attempt must fail. - `SCAN_REGIONS` · required · Which regions to enumerate. Omissions are recorded rather than silent. - `STALE_AFTER_HOURS` · required · Past this a diagram is visibly marked stale, including in exports. - `EXPORT_REDACTION_DEFAULT` · required · A diagram is a map for an attacker. The default matters. - `EXCLUDED_FIELDS_PATH` · required · Applied at collection so secrets are never stored rather than filtered later. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Cloudcraft product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: Read-only credentials enumerating resources and relationships, A graph built from real references between resources, Hierarchical grouping by account, region and network boundary, Every element carries the time it was observed, TypeScript with SQLite and a local renderer. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. - Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. ===== MILESTONES.md ===== # Delivery milestones · Cloudcraft Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Reading an account without being able to change it A scan enumerates resources using credentials that cannot write. ### Steps 1. Use read-only credentials Verify by attempting a write and expecting denial. Files: `src/credentials.ts`, `tests/readonly.test.ts` 2. Record what could not be read Absence must not look like emptiness. Files: `src/scan.ts` 3. Back off on throttling Enumerating a large account will hit limits. Files: `src/scan.ts` ### Done when - [ ] Write attempts are denied by the credentials - [ ] Missing permissions produce recorded gaps - [ ] Throttling is handled with backoff - [ ] Partial scans are marked partial ### Watch out - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. ## M2 · Relationships, and how sure you are The graph distinguishes what you read from what you inferred. ### Steps 1. Read relationships from configuration The references that actually exist, not the ones that seem likely. Files: `src/topology.ts` 2. Record evidence per edge So a reader can tell a fact from a guess. Files: `src/edges.ts` 3. Render inference differently A dashed line and a solid line are different claims. Files: `src/render.ts` ### Done when - [ ] Edges record configuration or inference with evidence - [ ] Inferred edges render distinctly - [ ] Unconnected resources appear isolated - [ ] Security and routing edges come from configuration ### Watch out - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. ## M3 · Making four hundred resources legible A real account produces a diagram someone can read. ### Steps 1. Nest by real boundaries Account, region, network. The nesting is the structure people think in. Files: `src/layout.ts` 2. Collapse repetition into counts Twenty identical instances is one shape and a number. Files: `src/collapse.ts` 3. Fold rather than filter Filtering hides things silently. Folding keeps the count visible. Files: `src/layout.ts` ### Done when - [ ] Four hundred resources produce a readable diagram - [ ] Repetition collapses into labelled counts - [ ] Groups expand in place - [ ] Counts reconcile against the scan ### Watch out - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. ## M4 · Saying how old the picture is Nobody mistakes a snapshot for the current state. ### Steps 1. Put the scan time on the diagram On the image, not in a menu. Exports get separated from their context. Files: `src/render.ts` 2. Report drift between scans What appeared, disappeared and changed. Files: `src/drift.ts` 3. Distinguish gone from unreadable A permissions gap is not a deletion. Files: `src/drift.ts` ### Done when - [ ] Scan time appears on every diagram - [ ] Stale diagrams are visibly marked, including exports - [ ] Drift is reported per resource - [ ] Disappeared and unreadable are distinguished ### Watch out - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ## M5 · Exporting a map of your estate carefully (production only) A shared diagram does not hand an attacker your topology. ### Steps 1. Exclude secret-bearing fields at collection Not at export. Collected means stored, backed up and in crash reports. Files: `src/collect.ts`, `tests/no-secrets.test.ts` 2. Redact by default on export A diagram is a map for whoever is attacking you. Files: `src/export.ts` 3. Record deliberate unredacted exports Possible, deliberate, and logged. Files: `src/export.ts` ### Done when - [ ] Secret-bearing fields are excluded at collection - [ ] Exports redact identifiers by default - [ ] Unredacted export requires a recorded action - [ ] Exports carry scan time and redaction level ### Watch out - Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. ===== OPERATIONS.md ===== # Operations · Cloudcraft ## Backup The scan database describes your entire estate and is more sensitive than most application data. Consider whether you need to back it up at all, since a scan regenerates, and an old inventory is mostly a liability. ## Restore Restore and confirm the exclusion list is applied to restored data as well, and prefer rescanning to restoring, since an old inventory presented as current is the failure mode this build is organised against. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Scan completeness is the metric: a scan whose recorded gaps are growing means permissions have changed, and the diagram is quietly describing less of the estate than it did last month. ## Incident checklist A diagram used as current when it was months old is the failure with consequences, and it happens when an export gets separated from its context. That is why the scan time is rendered into the image rather than displayed beside it. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] A write attempt with the scan credentials is confirmed denied - [ ] Missing permissions are confirmed to produce recorded gaps - [ ] Inferred edges are confirmed to render distinctly - [ ] Scan time is confirmed present on every export - [ ] Secret-bearing fields are confirmed excluded at collection ## Launch constraint Do not market omitted Cloudcraft capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. Collected inventory. Sensitive, since it describes your entire estate. DB_PATH=./scans.db # Required · secret. Read only. A write attempt must fail. CLOUD_CREDENTIALS=a read-only profile name # Required. Which regions to enumerate. Omissions are recorded rather than silent. SCAN_REGIONS=eu-west-1,eu-west-2 # Required. Past this a diagram is visibly marked stale, including in exports. STALE_AFTER_HOURS=72 # Required. A diagram is a map for an attacker. The default matters. EXPORT_REDACTION_DEFAULT=full # Required. Applied at collection so secrets are never stored rather than filtered later. EXCLUDED_FIELDS_PATH=./config/excluded-fields.txt
# Cloudcraft · indie build A diagramming tool that draws what is actually deployed by reading a cloud account read only, where the engineering is turning a flat list of resources into a readable topology and the discipline is knowing that a diagram is stale the moment it is drawn. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Collection | Read-only credentials enumerating resources and relationships | the relationships are the diagram; the resource list alone is a spreadsheet | | Topology | A graph built from real references between resources | inferred relationships are guesses and should be labelled as such | | Layout | Hierarchical grouping by account, region and network boundary | a flat graph of four hundred resources is not a diagram | | Freshness | Every element carries the time it was observed | a diagram of live infrastructure is a snapshot and should say so | | Runtime | TypeScript with SQLite and a local renderer | the collected inventory is sensitive and does not need a server | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the scanner and the renderer. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **Read-only credentials for a real account** · free - Why: The whole build depends on enumerating real infrastructure, and the read-only constraint has to be true of the credentials rather than of your intentions. - Get it: Create a role or key with a read-only policy, scoped to the account you will scan, and verify a write is denied before scanning. - Verify: A write attempt with these credentials is denied - [ ] **An account with at least a hundred resources** · free to scan; the account itself costs what it costs - Why: Layout, collapsing and readability are all uninteresting on a small account and become the entire problem on a real one. - Get it: A real account you have permission to scan, ideally one with several regions and networks. - Verify: A scan returns at least a hundred resources across more than one region - [ ] **What you will not collect** · free - Why: Secret-bearing fields are excluded at collection, which means deciding which they are before the first scan rather than after they are in the database. - Get it: List the fields that can contain credentials, connection strings or keys for the resource types you will scan, and exclude them explicitly. - Verify: A written exclusion list exists and is applied in the collector - [ ] **Your redaction default and sharing rules** · free - Why: An architecture diagram is a map of your estate for anyone attacking you, and the default matters more than the option. - Get it: Decide what is redacted by default and who may produce an unredacted export. - Verify: A written note states the default redaction and who may override it ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. - presentation and enterprise controls - multiplayer cursors and comments - large template libraries - high-fidelity import and export If one of those is essential to you, that is the reason to keep paying for Cloudcraft, and the README should say so rather than pretend.
# Build brief · Cloudcraft The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me architecture diagrams generated from the infrastructure that actually exists to replace Cloudcraft. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero This build reads a cloud account, which means it holds credentials that can enumerate every resource you own. Two rules follow and both are structural rather than advisory. The credentials are read only. Not read-mostly, not read plus a tagging call for convenience. A diagramming tool with write access is a diagramming tool that can delete a production database because of a bug in a layout algorithm, and there is no benefit that justifies it. The output is sensitive. An architecture diagram names your services, shows what is exposed to the internet, and often carries resource identifiers and address ranges. It is a map for anyone attacking you. So exports are redacted by default, sharing is deliberate, and any field that could carry a secret is excluded at collection rather than filtered at display. ### Stack (fixed, do not substitute) - Collection: Read-only credentials enumerating resources and relationships · the relationships are the diagram; the resource list alone is a spreadsheet - Topology: A graph built from real references between resources · inferred relationships are guesses and should be labelled as such - Layout: Hierarchical grouping by account, region and network boundary · a flat graph of four hundred resources is not a diagram - Freshness: Every element carries the time it was observed · a diagram of live infrastructure is a snapshot and should say so - Runtime: TypeScript with SQLite and a local renderer · the collected inventory is sensitive and does not need a server ### Data model (create this before Phase 1) - scans(id, account_ref, regions_json, started_at, finished_at, resource_count, partial_reason) - resources(id, scan_id, kind, identifier, name, region, tags_json, config_summary_json, observed_at) - edges(from_resource_id, to_resource_id, kind, confidence, evidence) · kind is contains, connects, permits or infers - boundaries(id, scan_id, kind, identifier, parent_id) · accounts, networks and subnets as nesting - diagrams(id, scan_id, layout_json, redaction_level, generated_at) - drifts(id, from_scan_id, to_scan_id, resource_identifier, change_kind, detail) · what changed between scans - An edge records its evidence, because a connection read from a configuration and one inferred from a naming convention are different claims. ### Phase 1 · Reading an account without being able to change it Build: Enumerate resources across regions with read-only credentials. Handle pagination, throttling and permissions you do not have. Record a partial scan as partial rather than presenting it as complete. Trap: A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. Done when: A scan runs with credentials that have no write permissions, verified by attempting a write and confirming it is denied. Missing permissions produce a recorded gap rather than a silent omission. Throttling is handled with backoff rather than failing the scan. A partial scan is marked partial everywhere its output appears. Do not build yet: No topology, layout or diagrams. ### Phase 2 · Relationships, and how sure you are Build: Build edges from real configuration references. Where a relationship is inferred from naming or convention, record it as inferred with its evidence. Render the two differently. Trap: Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. Done when: Edges record whether they came from configuration or inference, with evidence. Inferred edges render distinctly from read ones. A resource with no discoverable relationships appears isolated rather than being connected by guesswork. Security group and routing relationships are read from configuration rather than inferred. Do not build yet: No layout or diagrams yet. ### Phase 3 · Making four hundred resources legible Build: Group by account, region and network boundary as nested containers. Collapse repeated identical resources into a count. Let the viewer expand and filter rather than showing everything at once. Trap: Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. Done when: A four hundred resource account produces a readable diagram through nesting and collapsing. Repeated identical resources collapse into a labelled count rather than being hidden. Expanding a group reveals its contents in place. Nothing is omitted from the diagram, only folded, verified by comparing counts against the scan. Do not build yet: No drift or export yet. ### Phase 4 · Saying how old the picture is Build: Show the scan time prominently on every diagram and per element. Compare consecutive scans and report drift. Mark a diagram as stale past a configured age rather than displaying it unchanged. Trap: A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. Done when: Every diagram shows its scan time prominently. A diagram past the staleness threshold is visibly marked wherever it appears including in exports. Drift between two scans is reported by resource. A resource that disappeared between scans is distinguished from one that was unreadable due to permissions. Do not build yet: No export or sharing yet. ### Phase 5 · Exporting a map of your estate carefully Build: Redact identifiers, addresses and account references by default on export. Require a deliberate action to include them. Exclude anything that could carry a secret at collection time rather than filtering it on export. Trap: Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. Done when: Fields that could carry secrets are excluded during collection, verified by inspecting the stored scan. Exports redact identifiers and addresses by default. Including them requires a deliberate action that is recorded. An export carries its scan time and redaction level visibly. Do not build yet: Nothing after this. ### Out of scope (and why) - Cost estimation from the diagram, which needs pricing data and usage patterns rather than topology. - Multi-cloud coverage, which is an adapter per provider and a taxonomy problem on top. - Any write access, including tagging, which is excluded on principle rather than by omission. - Security assessment, which is a different discipline and where a diagramming tool's confidence would be misleading. ### README must contain - That the credentials are read only and a write attempt is verified to fail in the test suite - That inferred relationships are recorded with evidence and drawn differently from read ones - That a partial scan is marked partial, because absence must not look like emptiness - That the scan time appears on the diagram itself and stale diagrams are visibly degraded - That secret-bearing fields are excluded at collection rather than filtered at export
# Agent instructions · Cloudcraft indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: Read-only credentials enumerating resources and relationships, A graph built from real references between resources, Hierarchical grouping by account, region and network boundary, Every element carries the time it was observed, TypeScript with SQLite and a local renderer. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold.
# Build plan · Cloudcraft A diagramming tool that draws what is actually deployed by reading a cloud account read only, where the engineering is turning a flat list of resources into a readable topology and the discipline is knowing that a diagram is stale the moment it is drawn. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Reading an account without being able to change it A scan enumerates resources using credentials that cannot write. ### Steps 1. Use read-only credentials Verify by attempting a write and expecting denial. Files: `src/credentials.ts`, `tests/readonly.test.ts` 2. Record what could not be read Absence must not look like emptiness. Files: `src/scan.ts` 3. Back off on throttling Enumerating a large account will hit limits. Files: `src/scan.ts` ### Done when - [ ] Write attempts are denied by the credentials - [ ] Missing permissions produce recorded gaps - [ ] Throttling is handled with backoff - [ ] Partial scans are marked partial ### Watch out - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. ## Phase 2 · Relationships, and how sure you are The graph distinguishes what you read from what you inferred. ### Steps 1. Read relationships from configuration The references that actually exist, not the ones that seem likely. Files: `src/topology.ts` 2. Record evidence per edge So a reader can tell a fact from a guess. Files: `src/edges.ts` 3. Render inference differently A dashed line and a solid line are different claims. Files: `src/render.ts` ### Done when - [ ] Edges record configuration or inference with evidence - [ ] Inferred edges render distinctly - [ ] Unconnected resources appear isolated - [ ] Security and routing edges come from configuration ### Watch out - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. ## Phase 3 · Making four hundred resources legible A real account produces a diagram someone can read. ### Steps 1. Nest by real boundaries Account, region, network. The nesting is the structure people think in. Files: `src/layout.ts` 2. Collapse repetition into counts Twenty identical instances is one shape and a number. Files: `src/collapse.ts` 3. Fold rather than filter Filtering hides things silently. Folding keeps the count visible. Files: `src/layout.ts` ### Done when - [ ] Four hundred resources produce a readable diagram - [ ] Repetition collapses into labelled counts - [ ] Groups expand in place - [ ] Counts reconcile against the scan ### Watch out - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. ## Phase 4 · Saying how old the picture is Nobody mistakes a snapshot for the current state. ### Steps 1. Put the scan time on the diagram On the image, not in a menu. Exports get separated from their context. Files: `src/render.ts` 2. Report drift between scans What appeared, disappeared and changed. Files: `src/drift.ts` 3. Distinguish gone from unreadable A permissions gap is not a deletion. Files: `src/drift.ts` ### Done when - [ ] Scan time appears on every diagram - [ ] Stale diagrams are visibly marked, including exports - [ ] Drift is reported per resource - [ ] Disappeared and unreadable are distinguished ### Watch out - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ## Not in this build - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. ## After v1, if you want it - Scheduled scans with drift alerting, which is where this becomes operationally useful - Diagram diffs between two scans as a visual, since the list form is hard to read - Annotation layers that survive rescanning, so human context is not lost each time
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Collected inventory. Sensitive, since it describes your entire estate. DB_PATH=./scans.db # Required · secret. Read only. A write attempt must fail. CLOUD_CREDENTIALS=a read-only profile name # Required. Which regions to enumerate. Omissions are recorded rather than silent. SCAN_REGIONS=eu-west-1,eu-west-2 # Required. Past this a diagram is visibly marked stale, including in exports. STALE_AFTER_HOURS=72 # Required. A diagram is a map for an attacker. The default matters. EXPORT_REDACTION_DEFAULT=full # Required. Applied at collection so secrets are never stored rather than filtered later. EXCLUDED_FIELDS_PATH=./config/excluded-fields.txt
# Cloudcraft · product brief ## Problem The visible cloud architecture diagrams loop is buildable, but a credible replacement needs more than the first screen. Cloudcraft earns its keep through interaction polish, collaboration, so expect a weekend or multi-day build and a narrower personal scope. ## Product outcome A diagram of what is actually deployed, that says how old it is, distinguishes facts from guesses, and cannot change anything in the account it read. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - Node.js 22 - modern browser - no account required ## Explicit non-goals for v1 - Cost estimation. - Multi-cloud coverage. - Any write access, including tagging. - Security assessment. - presentation and enterprise controls - multiplayer cursors and comments - large template libraries - high-fidelity import and export ## Success criteria - A write attempt with the scan credentials is confirmed denied - Missing permissions are confirmed to produce recorded gaps - Inferred edges are confirmed to render distinctly - Scan time is confirmed present on every export - Secret-bearing fields are confirmed excluded at collection
# Build brief · Cloudcraft The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me architecture diagrams generated from the infrastructure that actually exists to replace Cloudcraft. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero This build reads a cloud account, which means it holds credentials that can enumerate every resource you own. Two rules follow and both are structural rather than advisory. The credentials are read only. Not read-mostly, not read plus a tagging call for convenience. A diagramming tool with write access is a diagramming tool that can delete a production database because of a bug in a layout algorithm, and there is no benefit that justifies it. The output is sensitive. An architecture diagram names your services, shows what is exposed to the internet, and often carries resource identifiers and address ranges. It is a map for anyone attacking you. So exports are redacted by default, sharing is deliberate, and any field that could carry a secret is excluded at collection rather than filtered at display. ### Stack (fixed, do not substitute) - Collection: Read-only credentials enumerating resources and relationships · the relationships are the diagram; the resource list alone is a spreadsheet - Topology: A graph built from real references between resources · inferred relationships are guesses and should be labelled as such - Layout: Hierarchical grouping by account, region and network boundary · a flat graph of four hundred resources is not a diagram - Freshness: Every element carries the time it was observed · a diagram of live infrastructure is a snapshot and should say so - Runtime: TypeScript with SQLite and a local renderer · the collected inventory is sensitive and does not need a server ### Data model (create this before Phase 1) - scans(id, account_ref, regions_json, started_at, finished_at, resource_count, partial_reason) - resources(id, scan_id, kind, identifier, name, region, tags_json, config_summary_json, observed_at) - edges(from_resource_id, to_resource_id, kind, confidence, evidence) · kind is contains, connects, permits or infers - boundaries(id, scan_id, kind, identifier, parent_id) · accounts, networks and subnets as nesting - diagrams(id, scan_id, layout_json, redaction_level, generated_at) - drifts(id, from_scan_id, to_scan_id, resource_identifier, change_kind, detail) · what changed between scans - An edge records its evidence, because a connection read from a configuration and one inferred from a naming convention are different claims. ### Phase 1 · Reading an account without being able to change it Build: Enumerate resources across regions with read-only credentials. Handle pagination, throttling and permissions you do not have. Record a partial scan as partial rather than presenting it as complete. Trap: A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. Done when: A scan runs with credentials that have no write permissions, verified by attempting a write and confirming it is denied. Missing permissions produce a recorded gap rather than a silent omission. Throttling is handled with backoff rather than failing the scan. A partial scan is marked partial everywhere its output appears. Do not build yet: No topology, layout or diagrams. ### Phase 2 · Relationships, and how sure you are Build: Build edges from real configuration references. Where a relationship is inferred from naming or convention, record it as inferred with its evidence. Render the two differently. Trap: Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. Done when: Edges record whether they came from configuration or inference, with evidence. Inferred edges render distinctly from read ones. A resource with no discoverable relationships appears isolated rather than being connected by guesswork. Security group and routing relationships are read from configuration rather than inferred. Do not build yet: No layout or diagrams yet. ### Phase 3 · Making four hundred resources legible Build: Group by account, region and network boundary as nested containers. Collapse repeated identical resources into a count. Let the viewer expand and filter rather than showing everything at once. Trap: Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. Done when: A four hundred resource account produces a readable diagram through nesting and collapsing. Repeated identical resources collapse into a labelled count rather than being hidden. Expanding a group reveals its contents in place. Nothing is omitted from the diagram, only folded, verified by comparing counts against the scan. Do not build yet: No drift or export yet. ### Phase 4 · Saying how old the picture is Build: Show the scan time prominently on every diagram and per element. Compare consecutive scans and report drift. Mark a diagram as stale past a configured age rather than displaying it unchanged. Trap: A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. Done when: Every diagram shows its scan time prominently. A diagram past the staleness threshold is visibly marked wherever it appears including in exports. Drift between two scans is reported by resource. A resource that disappeared between scans is distinguished from one that was unreadable due to permissions. Do not build yet: No export or sharing yet. ### Phase 5 · Exporting a map of your estate carefully Build: Redact identifiers, addresses and account references by default on export. Require a deliberate action to include them. Exclude anything that could carry a secret at collection time rather than filtering it on export. Trap: Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter. Done when: Fields that could carry secrets are excluded during collection, verified by inspecting the stored scan. Exports redact identifiers and addresses by default. Including them requires a deliberate action that is recorded. An export carries its scan time and redaction level visibly. Do not build yet: Nothing after this. ### Out of scope (and why) - Cost estimation from the diagram, which needs pricing data and usage patterns rather than topology. - Multi-cloud coverage, which is an adapter per provider and a taxonomy problem on top. - Any write access, including tagging, which is excluded on principle rather than by omission. - Security assessment, which is a different discipline and where a diagramming tool's confidence would be misleading. ### README must contain - That the credentials are read only and a write attempt is verified to fail in the test suite - That inferred relationships are recorded with evidence and drawn differently from read ones - That a partial scan is marked partial, because absence must not look like emptiness - That the scan time appears on the diagram itself and stale diagrams are visibly degraded - That secret-bearing fields are excluded at collection rather than filtered at export
# Architecture · Cloudcraft ## Stack | Part | Choice | Why | | --- | --- | --- | | Collection | Read-only credentials enumerating resources and relationships | the relationships are the diagram; the resource list alone is a spreadsheet | | Topology | A graph built from real references between resources | inferred relationships are guesses and should be labelled as such | | Layout | Hierarchical grouping by account, region and network boundary | a flat graph of four hundred resources is not a diagram | | Freshness | Every element carries the time it was observed | a diagram of live infrastructure is a snapshot and should say so | | Runtime | TypeScript with SQLite and a local renderer | the collected inventory is sensitive and does not need a server | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Collection | Read-only enumeration with recorded gaps. | Any provider adapter, provided the credentials cannot write and gaps are recorded. | | Topology | Edges with evidence. | Any implementation, provided inference stays distinguishable from configuration. | | Layout | Nesting and collapsing at scale. | Any algorithm, provided it folds rather than filters. | | Freshness | Scan time and drift. | Any presentation, provided the time is on the diagram itself. | | Redaction | Exclusion at collection and export defaults. | Not swappable for export-time filtering, which means the data was stored. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DB_PATH` · required · Collected inventory. Sensitive, since it describes your entire estate. - `CLOUD_CREDENTIALS` · required, secret · Read only. A write attempt must fail. - `SCAN_REGIONS` · required · Which regions to enumerate. Omissions are recorded rather than silent. - `STALE_AFTER_HOURS` · required · Past this a diagram is visibly marked stale, including in exports. - `EXPORT_REDACTION_DEFAULT` · required · A diagram is a map for an attacker. The default matters. - `EXCLUDED_FIELDS_PATH` · required · Applied at collection so secrets are never stored rather than filtered later. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Cloudcraft product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: Read-only credentials enumerating resources and relationships, A graph built from real references between resources, Hierarchical grouping by account, region and network boundary, Every element carries the time it was observed, TypeScript with SQLite and a local renderer. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. - Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter.
# Delivery milestones · Cloudcraft Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Reading an account without being able to change it A scan enumerates resources using credentials that cannot write. ### Steps 1. Use read-only credentials Verify by attempting a write and expecting denial. Files: `src/credentials.ts`, `tests/readonly.test.ts` 2. Record what could not be read Absence must not look like emptiness. Files: `src/scan.ts` 3. Back off on throttling Enumerating a large account will hit limits. Files: `src/scan.ts` ### Done when - [ ] Write attempts are denied by the credentials - [ ] Missing permissions produce recorded gaps - [ ] Throttling is handled with backoff - [ ] Partial scans are marked partial ### Watch out - A scan that silently skips a region where permissions were missing produces a diagram with a whole part of the estate absent, and the person looking at it has no way to know. Record what could not be read and why, and mark the diagram partial rather than letting absence look like emptiness. ## M2 · Relationships, and how sure you are The graph distinguishes what you read from what you inferred. ### Steps 1. Read relationships from configuration The references that actually exist, not the ones that seem likely. Files: `src/topology.ts` 2. Record evidence per edge So a reader can tell a fact from a guess. Files: `src/edges.ts` 3. Render inference differently A dashed line and a solid line are different claims. Files: `src/render.ts` ### Done when - [ ] Edges record configuration or inference with evidence - [ ] Inferred edges render distinctly - [ ] Unconnected resources appear isolated - [ ] Security and routing edges come from configuration ### Watch out - Inferring connections from naming conventions produces a diagram that looks complete and contains relationships that do not exist, which is worse than a sparse diagram because people make decisions from it. Record the evidence per edge, and draw inferred edges differently so a reader can weigh them. ## M3 · Making four hundred resources legible A real account produces a diagram someone can read. ### Steps 1. Nest by real boundaries Account, region, network. The nesting is the structure people think in. Files: `src/layout.ts` 2. Collapse repetition into counts Twenty identical instances is one shape and a number. Files: `src/collapse.ts` 3. Fold rather than filter Filtering hides things silently. Folding keeps the count visible. Files: `src/layout.ts` ### Done when - [ ] Four hundred resources produce a readable diagram - [ ] Repetition collapses into labelled counts - [ ] Groups expand in place - [ ] Counts reconcile against the scan ### Watch out - Drawing every resource at once produces an unreadable mess at real scale, and the temptation is to filter down to a subset, which produces a diagram that omits something important without saying so. Collapse and nest rather than filtering, so nothing is hidden, only folded, and the counts remain visible. ## M4 · Saying how old the picture is Nobody mistakes a snapshot for the current state. ### Steps 1. Put the scan time on the diagram On the image, not in a menu. Exports get separated from their context. Files: `src/render.ts` 2. Report drift between scans What appeared, disappeared and changed. Files: `src/drift.ts` 3. Distinguish gone from unreadable A permissions gap is not a deletion. Files: `src/drift.ts` ### Done when - [ ] Scan time appears on every diagram - [ ] Stale diagrams are visibly marked, including exports - [ ] Drift is reported per resource - [ ] Disappeared and unreadable are distinguished ### Watch out - A diagram with no timestamp is used for six months as though it were current, and infrastructure changes weekly, so decisions get made from a picture of an estate that no longer exists. Put the observation time on the diagram itself, not in a menu, and visibly degrade it past a threshold. ## M5 · Exporting a map of your estate carefully (production only) A shared diagram does not hand an attacker your topology. ### Steps 1. Exclude secret-bearing fields at collection Not at export. Collected means stored, backed up and in crash reports. Files: `src/collect.ts`, `tests/no-secrets.test.ts` 2. Redact by default on export A diagram is a map for whoever is attacking you. Files: `src/export.ts` 3. Record deliberate unredacted exports Possible, deliberate, and logged. Files: `src/export.ts` ### Done when - [ ] Secret-bearing fields are excluded at collection - [ ] Exports redact identifiers by default - [ ] Unredacted export requires a recorded action - [ ] Exports carry scan time and redaction level ### Watch out - Filtering secrets at export means they were collected and stored, so they are in the local database, in backups and in any crash report, and a single unredacted export path exposes them. Exclude the fields at collection, so there is nothing to filter.
# Operations · Cloudcraft ## Backup The scan database describes your entire estate and is more sensitive than most application data. Consider whether you need to back it up at all, since a scan regenerates, and an old inventory is mostly a liability. ## Restore Restore and confirm the exclusion list is applied to restored data as well, and prefer rescanning to restoring, since an old inventory presented as current is the failure mode this build is organised against. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Scan completeness is the metric: a scan whose recorded gaps are growing means permissions have changed, and the diagram is quietly describing less of the estate than it did last month. ## Incident checklist A diagram used as current when it was months old is the failure with consequences, and it happens when an export gets separated from its context. That is why the scan time is rendered into the image rather than displayed beside it. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] A write attempt with the scan credentials is confirmed denied - [ ] Missing permissions are confirmed to produce recorded gaps - [ ] Inferred edges are confirmed to render distinctly - [ ] Scan time is confirmed present on every export - [ ] Secret-bearing fields are confirmed excluded at collection ## Launch constraint Do not market omitted Cloudcraft capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. Collected inventory. Sensitive, since it describes your entire estate. DB_PATH=./scans.db # Required · secret. Read only. A write attempt must fail. CLOUD_CREDENTIALS=a read-only profile name # Required. Which regions to enumerate. Omissions are recorded rather than silent. SCAN_REGIONS=eu-west-1,eu-west-2 # Required. Past this a diagram is visibly marked stale, including in exports. STALE_AFTER_HOURS=72 # Required. A diagram is a map for an attacker. The default matters. EXPORT_REDACTION_DEFAULT=full # Required. Applied at collection so secrets are never stored rather than filtered later. EXCLUDED_FIELDS_PATH=./config/excluded-fields.txt
$ choose a build depth, inspect the files, then open the complete pack in your agent
Cloudcraft: The shapes are easy; customers pay for low-friction editing, reliable exports, collaboration, and a canvas that never fights them.
xpresentation and enterprise controls
xmultiplayer cursors and comments
xlarge template libraries
xhigh-fidelity import and export
Cloudcraft pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| free | $0/user | $0/user | 1 user; manual diagrams; maximum drawing size 12 × 15 components; all designer components |
| pro | $99/user | $40.83/user | 1 team; live AWS/Azure scanning; unlimited diagram size; 30-day version history |
| enterprise | $120/user | $100/user | Multiple teams; unlimited diagram size; 90-day version history |
free tier1 user; manual diagrams; maximum 12 × 15 components per drawing
billingmonthly + annual; 14-day Pro trial and 30-day money-back guarantee
hidden costsUsers added to an annual account are prorated. Enterprise volume discounts begin at 15 users; GovCloud is quote-based. Existing Datadog customers may receive SSO without the normal Enterprise upgrade.
verified 2026-08-12 · source ↗
Vibecode Cloudcraft
Kinda. The core of Cloudcraft is buildable in a weekend with the prompt on this page, but there are real gaps: presentation and enterprise controls, multiplayer cursors and comments. Read the honest list above before committing.
How much does Cloudcraft cost?
Cloudcraft's pricing is usage-based or varies by plan · The official pricing URL is recorded, but a stable current amount was not safely recoverable in this pass. Do not publish a number until rechecked..
What do I lose by replacing Cloudcraft?
Honestly: presentation and enterprise controls; multiplayer cursors and comments; large template libraries; high-fidelity import and export. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Cloudcraft?
Yes: Excalidraw (Open-source diagram canvas with an approachable interaction model.). Using prior art is also vibecoding; the prompt is for when you want it exactly your way.