Live engine output
What a Governed Scaffold Looks Like
This page is rendered at deploy time by running buildScaffold() —
the exact function behind the hero. What you see here is exactly what ships in the ZIP.
Project structure
The governed scaffold file tree
Every scaffold ships with the project structure and the .ai/ governance directory in the same ZIP.
The application files give you the correct layout; the governance files give your AI agents the rules.
my-saas-api/ ├── .ai/ │ ├── adr-001.md │ ├── adr-002.md │ ├── constraints.yaml │ ├── core.adf │ ├── manifest.adf │ ├── state.adf │ ├── test-plan.md │ └── threat-model.md ├── .github/ │ └── workflows/ │ └── ci.yml ├── migrations/ │ └── 0001_initial.sql ├── src/ │ ├── contracts/ │ │ └── my-saas-api.contract.ts │ ├── db/ │ │ └── schema.sql │ ├── lib/ │ │ ├── http-error.ts │ │ ├── kv.ts │ │ └── security.ts │ ├── middleware/ │ │ ├── auth.ts │ │ └── tenant.ts │ ├── types/ │ │ └── env.ts │ └── worker.ts ├── tests/ │ └── security.test.ts ├── README.md ├── package.json ├── schema.sql ├── tsconfig.json └── wrangler.toml
.ai/threat-model.md
STRIDE threat model
8 threats identified for this architecture. Each has an ID, STRIDE category, severity, and a concrete mitigation. Generated deterministically — no LLM involved.
+ 4 more threats in the full .ai/threat-model.md
.ai/adr-001.md
Architectural Decision Record
Architectural decision records document the non-obvious choices — with the alternatives considered, the constraints that ruled them out, and the consequences your team accepts. When an AI agent or new developer tries to change this decision, the ADR explains exactly why it was made.
# ADR-001: Pattern Selection — my-saas-api **Status**: Accepted ## Context This service is a multi-tenant SaaS backend on Workers. Trust boundary: every request must carry a verified tenant scope before touching D1. Tenant isolation is the load-bearing security property and must be enforced in middleware, not per-handler. ## Decision - Use Hono with auth middleware → tenant middleware → handler in that order. - Tenant ID is resolved from `x-tenant-id` header (or JWT claim) and pinned to `c.var.tenantId` for the request lifetime. - Every D1 query MUST include `WHERE tenant_id = ?` — enforced by a thin helper, not by convention. - Centralized error handler maps `HttpError` to stable JSON and never leaks internals. ## Consequences - Inherits standard workers-saas file layout and binding conventions - Authentication layer is required on all protected routes - Structured logging and trace IDs are required ## Traits - `rest` - `jwt-auth` - `resource-router` - `fetch-trigger`
.ai/test-plan.md
Integration test plan
Test requirements derived from the threat model and architectural decisions. The plan is structured so you can hand it directly to Vitest or a QA engineer without translation. Pro LLM polish expands this into runnable test stubs.
# Test Plan — my-saas-api **Testing level**: Standard (unit + integration) **Pattern**: `workers-saas` ## Required Coverage - [ ] All exported functions have unit tests - [ ] Error paths return correct HTTP status codes - [ ] Trace IDs present in all log lines ## Trait-Specific Tests ### REST Routes - [ ] 200 OK on valid request - [ ] 400 on malformed body - [ ] 401 on missing/invalid token - [ ] 404 on unknown resource - [ ] 429 on rate limit exceeded ### Authentication - [ ] Valid JWT accepted - [ ] Expired JWT rejected - [ ] Missing Authorization header → 401 ## Bindings Under Test - [ ] `DB` (D1) integration verified - [ ] `CACHE` (KV) integration verified
src/middleware/auth.ts
Actual generated TypeScript
Phase 1 ships runnable stubs — typed, wired to your bindings, zero dead imports. Pro polish fills in the implementation bodies guided by the threat model.
import type { Context } from "hono";
import { HttpError } from "../lib/http-error";
export async function requireBearerAuth(c: Context): Promise<void> {
const auth = c.req.header("authorization") ?? "";
if (!auth.startsWith("Bearer ")) throw new HttpError(401, "missing bearer token");
const token = auth.slice(7).trim();
if (!token) throw new HttpError(401, "empty bearer token");
const expected = c.env.AUTH_BEARER_TOKEN;
if (expected && token !== expected) throw new HttpError(403, "invalid bearer token");
}
import { Hono } from "hono";
import type { Env } from "./types/env";
import { HttpError } from "./lib/http-error";
const app = new Hono<{ Bindings: Env }>();
app.onError((err, c) => {
if (err instanceof HttpError) {
return c.json({ error: err.message }, err.status);
}
console.error(err);
return c.json({ error: "internal_error" }, 500);
});
export default app;
wrangler.toml
Bindings, pre-configured
D1 and KV bindings wired to the correct names your code expects. Replace the REPLACE_ME values
with the IDs from your Cloudflare dashboard after creating the resources, then wrangler deploy works.
name = "stackbilder-generated" main = "src/worker.ts" compatibility_date = "2026-05-24" [[d1_databases]] binding = "DB" database_name = "app-db" database_id = "REPLACE_ME" [[kv_namespaces]] binding = "CACHE" id = "REPLACE_ME"
.ai/constraints.yaml
Agent guardrails
Machine-readable constraints your AI coding agents read before modifying the codebase. Prevents architectural drift — the next Cursor session cannot accidentally disable auth without violating a constraint.
runtime: cloudflare-workers framework: hono enforcement: - authentication on protected routes - tenant scoping on data queries - typed env bindings - centralized HttpError mapping
Questions about scaffold output
Is this real scaffold output or a mock?
This page is rendered at deploy time by running buildScaffold() — the exact same zero-inference function triggered when you generate a scaffold from the hero. No editorial formatting. No aspirational content. The file tree, threat IDs, ADR text, test plan, and source files shown here are byte-for-byte what ships in the ZIP.
How do I deploy after downloading the scaffold?
Create your D1 database and KV namespace in the Cloudflare dashboard, then paste the generated IDs into wrangler.toml replacing the REPLACE_ME placeholders. Add secrets via `wrangler secret put`. After that, wrangler deploy works.
Does it work for stacks other than Cloudflare Workers?
Cloudflare Workers — with D1, KV, R2, and service bindings — is fully supported today. The governance artifacts (threat model, ADRs, test plan, constraints) are substantially stack-agnostic and useful regardless of what you're building on. Additional stacks are on the roadmap.
What does Pro add?
Free tier includes the full governance suite — threat model, ADRs, test plan, project scaffold — for up to 3 scaffolds per month. Pro ($29/mo) removes the monthly limit and adds LLM polish mode: idiomatic implementation code for route handlers, middleware bodies, migration SQL, and runnable test stubs, guided by the deterministic governance constraints.
Generate your own governed scaffold
Your architecture. Your threat model. Your ADRs.
Describe your app. Get the full governance suite in under 20ms. Free tier includes 3 scaffolds per month — no credit card.
Related pages