Architecture Decision Records
One file per irreversible decision, numbered, never rewritten.
Index
| ADR | decision | status |
|---|---|---|
| ADR-0001 | Shared-schema multi-tenancy (tenant_id + RLS) | accepted, amended (tenant inventory) |
| ADR-0002 | NATS JetStream as the change bus (with a local mode) | accepted |
| ADR-0003 | WebSocket binding deferred out of v1 | accepted |
| ADR-0004 | Store ladder, redb as the file-mode durability shadow | accepted |
| ADR-0005 | AnyStore enum + synchronous Pg facade | accepted · enum seam superseded by ADR-0013, sync facade by ADR-0022 |
| ADR-0006 | RLS and Timescale compression collide on attr_instances | accepted |
| ADR-0007 | temporal auto-recording stays in the write path | accepted (reverses the earlier bus-consumer design) |
| ADR-0008 | The browser build: one crate, the same router, no fourth backend | accepted |
| ADR-0009 | Temporal read cutover: attr_instances becomes the read path | accepted, implemented |
| ADR-0010 | Private-range egress allowed by default | accepted, implemented |
| ADR-0011 | The Via pseudonym identifies a (Context Source, Tenant) pair | accepted, implemented |
| ADR-0012 | Internal broker state lives in the store as doc kinds, keyed under reserved tenants | accepted, implemented |
| ADR-0013 | storage drivers — current-state and temporal as separate traits | accepted; supersedes the enum half of ADR-0005; the driver-identity consequence superseded by ADR-0017 |
| ADR-0014 | extension hooks — fixed phases, batch granularity | accepted; sink paragraph superseded by ADR-0016; two phases given a named user, and rule 1 an exception, by ADR-0020 |
| ADR-0015 | Notification delivery policy: one attempt by default, retries as transport, dead letters in the store | accepted, implemented |
| ADR-0016 | Notification bindings behind the sink registry | accepted, implemented |
| ADR-0017 | A driver is identified by its name, not by an enum value | accepted, implemented |
| ADR-0018 | CI actions are pinned by tag, third-party binaries by version | accepted, implemented |
| ADR-0019 | The distributed-subscription notification receiver lives outside the ETSI namespace | accepted, implemented |
| ADR-0020 | The policy seam: one trait, one built-in engine, every engine an addon | accepted, amended (the narrowing marker header) |
| ADR-0021 | A stored @context belongs to the Tenant that stored it, a Cached copy to none | accepted, implemented |
| ADR-0022 | The storage drivers are async; nothing blocks on a store call | accepted, implemented; supersedes the sync-facade half of ADR-0005 |
Format
Nygard's fields — Title, Status, Context, Decision, Consequences — plus one borrowed from MADR:
- Confirmation: how compliance with the decision can be checked — a named test, a CI job, a grep, or an explicit "manual review only". Every new ADR names its own fitness check; a decision nobody can verify drifts silently.
Shorter ADRs fold Context/Decision/Consequences into prose sections, as the existing files do; the five concerns must all be answerable from the text either way.
Immutability policy
Append-with-status. An accepted ADR's body is frozen; when a decision
changes, a NEW ADR supersedes it and the old one's Status line gains
superseded by ADR-00XX (see ADR-0005/ADR-0013 and the reversal recorded
in ADR-0007). Never edit an old ADR's Decision to match new reality —
the record of what was believed, and when it stopped being true, is the
point of keeping them.