Architecture Decision Records
Reading the two fields
Section titled “Reading the two fields”Status is about the decision. Implementation is about the code. They shared one word until
now, and one word could not carry both — which is how this directory got read two opposite ways in
a single day: once as “nine Proposed ADRs, all with shipped code — the field is stale metadata,
ignore it”, and once as “0012 is Proposed, so that surface shipped ahead of ratification and the
conservative catalog entry is right”. Both readings survive contact with the same files. That is
the defect.
Implementation was filled by reading the code, one ADR at a time:
| Value | Means |
|---|---|
shipped |
Implementing code and tests exist and are wired into a path that runs |
partial |
Part of the decision is implemented; the row says what is missing |
not-implemented |
No implementing code found |
Status values are unchanged, deliberately. Ratification is an act someone performs, not a
property inferred from code existing — inferring it is the precise error this change exists to
prevent, so nothing here promotes an ADR.
The convention exists, and this set never adopted it
Section titled “The convention exists, and this set never adopted it”It is written down once, in the root ADR set — specs/adr/README.md:
A record is only binding once its Status reads
accepted. Treatproposedrows as under discussion — in particular, do not implement against a proposed record’s interfaces or assume they exist.
Nothing says it governs this directory, and this directory does not look like it does: the root set
writes lowercase accepted / proposed on a single **Status:** proposed 2026-08-06 line, while
these use capitalised Accepted / Proposed split across - **Status:** and - **Date:**. This
README defined nothing until now, and ../README.md describes this directory as
“one record per settled decision” — which reads against nine of the twelve saying Proposed.
Two facts decide how much weight the field can bear:
- No status here has ever changed. Measured across all fifteen ADRs in both sets
(
git log -G '\*\*Status:\*\*'), the only commit that has ever touched aStatus:line is the commit that created the file. Zero transitions. The root convention is consistent with that — it says records are “never edited after acceptance” — but it names no act that reaches acceptance, so nothing ever has. - Status does not track implementation. Seven
Proposedrecords areshipped— including ADR-0004 and ADR-0005, the ticket gate and the egress floor, both wired and heavily tested. If the root convention governed here, “do not implement against a proposed record’s interfaces” would have been broken seven times. It ran the other way too, until ADR-0002’s promised lint rule was written:Acceptedandpartialat the same time. Both records stillpartialareProposed, so today the divergence runs one way — a fact about the current code, not something the field guarantees.
This is left open, not settled here. If Proposed is meant to be a real gate, someone has to
define the act that clears it — who ratifies, on what signal, recorded where — and either extend the
root convention to this set or write one for it. If it is not meant to be a gate, the honest fix is
to drop the field rather than keep a word that reads like one. Either is the substrate owners’ call;
this change only stops the two facts sharing one word in the meantime.
| ADR | Decision | Status | Implementation |
|---|---|---|---|
| 0001 | The execution substrate is its own component | Accepted | shipped |
| 0002 | Inside the flare-dispatch monorepo, no name of its own | Accepted | shipped — .oxlintrc.json forbids reaching substrate internals by path or by workspace package, repo-wide with the substrate exempted; its shape is held by src/facade-boundary.test.ts |
| 0003 | Consumers reach the substrate only through a service-binding facade | Proposed | shipped |
| 0004 | Admission enforced by ticket; the substrate alone owns the ceiling | Proposed | shipped |
| 0005 | Deny-all egress with named grant profiles | Proposed | shipped |
| 0006 | No long-lived credential reachable from inside a container | Proposed | partial — machinery shipped, adoption pending per ../credential-boundary.md |
| 0007 | Irreversible commands require an approval attestation at exec | Proposed | shipped |
| 0008 | Verdict-neutral — execution facts only | Accepted | shipped — a negative decision, enforced by the contract carrying no verdict field |
| 0009 | Two-tier budgets: per-execution metering + per-consumer ceiling | Proposed | partial — both tiers are pure logic with no caller; nothing outside budget/ imports it and no metered proxy route exists |
| 0010 | Named image classes, selected by policy | Proposed | shipped |
| 0011 | The sandbox SDK pin is a security surface | Proposed | shipped — literal pins on both halves, the transitive one walked through the apps/substrate lockfile edge; scoped to the substrate, so the dispatcher’s own @cloudflare/sandbox 0.10.1 is unasserted |
| 0012 | A process that outlives the exec fence holds no grant | Proposed | shipped — selective teardown and the killAllProcesses fallback both real |
How the controls compose
Section titled “How the controls compose”One execUnderGrant call crosses these controls in order; budgets (0009) have no caller
yet, and the SDK pin (0011) gates deploys rather than calls.
Diagram source
flowchart TB accTitle: Controls on one exec c["**consumer Worker**<br/>dispatcher or fractalbot"] -->|service binding| f["**facade** · 0003<br/>consumer id fixed by the entrypoint"] f --> p["**pool selection** · 0010<br/>policy picks the image class"] p --> a["**admission ticket** · 0004<br/>pool cap in D1, HMAC ticket to the DO"] a --> ap{"**approval floor** · 0007<br/>attested if irreversible?"} ap -->|no| r["typed refusal"] ap -->|yes, or not a floor command| fence["**exec fence** · 0005<br/>ensure behind the ticket, apply grant,<br/>run, kill, revoke"] fence -.->|container requests| eg["**egress handler** · 0005, 0006<br/>deny-all floor, profile rules,<br/>credential injection"] fence --> o["**execution facts** · 0008<br/>receipt, granted hosts, kill count"] class r danger class eg accent