Architectural Decision Records · Governance · Team alignment

ADR Generator for
AI-Built Software

Capture architecture decisions before they turn into Slack archaeology. ADRs generated from your scaffold tell the next developer — or the next AI agent — why choices were made.

Context + decision + consequences Alternatives considered Threat model cross-refs Markdown in .ai/ Machine-readable constraints Deterministic

The problem with undocumented decisions

AI agents make architectural decisions constantly and silently.

When you use Cursor, Claude Code, or Copilot to build features, the agent makes dozens of architectural micro-decisions during every session. It picks JWT over session cookies because it's seen more JWT examples in its training data. It chooses Redis-style KV access patterns when you're actually on D1, because the pattern feels familiar. It swaps your error handling strategy because the current approach looks "inconsistent" to it — without knowing that the inconsistency was intentional.

Human developers do this too, but humans can at least be asked. AI agents leave no trace of the reasoning behind the choices they make — or unmake. When something breaks three months later and you're trying to understand why your session management is half-cookie and half-JWT, there's no Slack message, no PR comment, no document that explains the reasoning. There's just the current state of the codebase, which might be the result of two or three agents working at cross-purposes.

This problem is worse for undocumented decisions that had non-obvious reasons. You chose SQLite over Redis not because you didn't know about Redis — because you're on Cloudflare Workers and Redis requires a network hop that adds 20ms at the edge. You chose cookie sessions not because JWT is bad — because your edge runtime can't verify JWTs without a round-trip to the key server. These aren't obvious to someone reading the code. They certainly aren't obvious to an agent that's been handed the codebase with no context.

The next agent to touch your code will make confident, unsubstantiated choices that violate constraints you established for good reasons. ADRs are how you give that agent — and the next human — the context to work within your architecture instead of against it.

Stackbilder generates ADRs from your scaffold — the non-obvious decisions are documented before the first line of implementation is written.

Decisions that typically go undocumented — and get reversed

Cookie sessions over JWT

Edge runtime JWT verification requires a network call. Cookies + D1 session store are faster and revocable.

D1 over KV for relational data

KV has no query predicates. D1 enables JOINs, transactions, and RLS — necessary for multi-tenant isolation.

Error message sanitization

Verbose D1 errors expose schema to clients. Mapped to threat T-004 — suppressed intentionally, not a bug.

Per-session DO naming

Global DO namespace causes hotspot failures under burst. Per-session instances scale horizontally.

Webhook idempotency key check

Stripe can deliver the same event twice. Without idempotency, double-upgrades and double-charges occur.

R2 presigned URLs, not direct proxy

Direct proxy routes every byte through the worker — saturates CPU and egress. Presigned bypasses the worker for data transfer.

What Stackbilder generates

ADRs that carry enough context to be useful six months later.

What an ADR contains

Each generated ADR covers the five things that matter: the context that forced the decision (what constraint or requirement made the choice necessary), the decision itself (short and unambiguous), the status (Accepted, Proposed, Deprecated), the alternatives that were evaluated and why they were rejected, and the consequences — both the benefits you gained and the tradeoffs you accepted. An ADR that doesn't acknowledge the tradeoffs is a rationalization document, not a decision record.

Context — what made this decision necessary
Decision — short, unambiguous statement
Status — Accepted / Proposed / Deprecated
Alternatives — what was rejected and why
Consequences — benefits gained + tradeoffs accepted
Threat refs — linked T-IDs when applicable

Machine-readable constraints

ADRs are markdown files, readable by humans and AI tools alike. The scaffold also generates a .ai/constraints.yaml file that distills the ADR decisions into machine-readable guardrails — the format that well-configured AI coding tools can read from your project root and treat as constraints on code generation. When your ADR says "no JWTs," the constraint file says it too, in the format your agent can parse before generating auth code.

# .ai/constraints.yaml
auth:
strategy: cookie-session
no_jwt: true # ADR-001
data:
primary_store: d1
tenant_isolation: row_level # ADR-002
errors:
sanitize_db_errors: true # ADR-003, T-004
durable_objects:
naming: per_session # ADR-004, T-007

Example output

A real ADR — context, decision, alternatives, consequences.

This is what Stackbilder generates for the auth strategy decision in a Cloudflare Workers app. Not a stub — a document with enough context to explain the decision to someone who wasn't in the room.

.ai/adr-001-auth-strategy.md

# ADR-001: Authentication Strategy

Status: Accepted

Date: 2025-05-24

Threat refs: T-001 (session brute-force), T-009 (EoP via role bypass)


## Context

This app runs on Cloudflare Workers at the edge. The runtime has no persistent

memory between requests and limited CPU budget per invocation. We need to

authenticate every request with minimal latency overhead. We also require

immediate session revocation — a user who changes their password or is banned

must lose access on the next request, not at token expiry.


## Decision

Use HttpOnly, Secure, SameSite=Strict cookie with a server-side session token

backed by D1. Session lookup on every authenticated request. Token is a

256-bit random value generated via crypto.getRandomValues().


## Alternatives considered

1. Stateless JWT (RS256) — rejected. Public key verification at the edge requires

fetching the JWKS endpoint, adding a network round-trip per request.

Worse: revocation requires a blocklist (same problem as session store).

No latency benefit over sessions; more attack surface (algorithm confusion).

2. HS256 JWT with shared secret — rejected. Immediate revocation impossible

without a revocation list. Adds no benefit over sessions for this use case.

3. Auth via service binding RPC — acceptable for later phases. Adds a hop.

Document as allowed upgrade path if Auth Service is introduced.


## Consequences

+ Immediate revocation: delete session row, access is cut off on next request.

+ No client-side token storage — eliminates XSS token theft via localStorage.

+ CSRF protection required: SameSite=Strict is defense-in-depth; add double-submit.

- D1 read on every request: adds ~2ms. Acceptable at edge; cache session row in KV

(TTL 60s) if request volume makes this a hotspot. See ADR-005.

- Token rotation required on sensitive operations (password change, role change).

How it works

Describe your app. Get ADRs for every non-obvious decision.

1

Describe your architecture

Tell Stackbilder what you're building: the data store, auth method, stateful components, external integrations. The engine identifies which decisions in that architecture have non-obvious reasons — the ones that will get reversed by the next agent.

2

ADRs generated in 20ms

The TarotScript engine maps your architecture to its decision points and generates a full ADR for each one — context, decision, alternatives considered, and consequences. Every ADR that links to a threat item in your model gets the cross-reference. No inference, same output every time.

3

Architecture stays coherent

ADRs live in .ai/ alongside the threat model, test plan, and constraints.yaml. AI tools and team members alike have access to the reasoning behind every non-obvious choice. Future changes go through the ADR layer — decisions are updated, not silently reversed.

Common questions

What is an Architectural Decision Record (ADR)?

An ADR is a short document that captures a significant architectural choice: the context that made it necessary, the decision itself, alternatives considered and rejected, and the consequences. It answers 'why did we do it this way?' — the question that becomes critical when the original author is unavailable, or when an AI agent is about to confidently undo the decision.

Do I need to write the ADRs myself or does Stackbilder generate them?

Stackbilder generates them from your scaffold. The engine identifies non-obvious decisions in your architecture and generates a full ADR for each — you don't write them manually. You can add custom ADRs afterward for decisions that happen after the initial scaffold.

How many ADRs does a typical scaffold include?

A Cloudflare Workers SaaS scaffold typically generates 4–8 ADRs covering auth strategy, data store selection, session management, error handling philosophy, and binding-specific patterns. More complex architectures — multiple service bindings, Stripe integration, DO concurrency — generate more because there are more non-obvious decisions.

Can I add custom ADRs after the initial scaffold?

Yes. ADRs are markdown files in the .ai/ directory, version-controlled with your code. Add new ones, update existing statuses (Accepted, Superseded, Deprecated), and link them to threat items or test plan sections. The format is open — you own the documents.

How do ADRs help when I'm using AI coding tools?

AI agents have no memory of why choices were made — they see the current code state and optimize from there. ADRs in .ai/ give well-configured agents the architectural context they'd otherwise invent. When the constraint file says 'no_jwt: true — ADR-001,' an agent reading your project root won't swap in JWT auth on the next refactor.

Related pages

Give your AI agents architectural memory.

Free tier includes 3 scaffolds per month — ADRs, threat model, and test plan with every one. No credit card.