Roadmap
What has been decided and what has been built are two different
questions, and a decision record answers only the first. Every record therefore carries an
implementation field recording what exists, and this page is derived from those
fields and from nothing else — there is no second list to fall out of step with the records.
A record is routinely accepted and none at the same time, and that is
not a contradiction: the decision is settled, and not a line of it is written. Marque is a design
with a scaffolding milestone behind it, so most of the 42 records below are exactly that.
The implementation plan is the order they
get built in.
Implementation: none35 of 42
Nothing implements it.
- 0001
Broker production data access as reviewed, signed, expiring grants Status: accepted
What exists: The three binaries do M1's flow in skeleton form: marque submits, approves and reads; harbourmaster serves and stores; pilot runs one approved statement and reports it. None of this record's own substance is built — no analysis, no rehearsal, no marque, no signing, no logbook — so every job in the component table is still unfilled, and this stays `none` rather than `partial`.
- 0002
One bootstrap URL is the only client configuration Status: accepted
- 0003
Every principal is federated, and every token is bound to a key Status: accepted
- 0004
A marque is a doubly-signed lease, verified by computation Status: accepted
- 0005
The control plane never holds a target credential Status: accepted
What exists: The Harbourmaster serves and links a PostgreSQL driver for its OWN store, and cmd/pilot links one to reach a target — the two homes EDR-0042 permits, and no others. The Harbourmaster opens no target connection and holds no target credential: the Pilot takes --target-dsn and the control plane never sees it. What is absent is everything the relay half needs — there is no Tender, no operator signature on a read, and no quota.
- 0006
Every statement names a role, and the role is the real limit Status: accepted
- 0007
- 0008
Approve routine work once, as a parameterised standing order Status: accepted
- 0009
The Leadsman advises and can never decide Status: accepted
- 0010
Rehearse the statement in a transaction that never commits Status: accepted
- 0011
Execution is idempotent, fenced, and budgeted Status: accepted
What exists: M1's executions table, RecordExecution and cmd/pilot carry a nonce, and it makes the REPORT idempotent: repeating a recorded one returns the stored outcome instead of writing a second row, and a fresh one against a terminal request is refused. It does NOT make the execution idempotent — if the first report never lands, the request is still approved and running the Pilot again executes the statement before anything looks at the nonce. Nothing claims a nonce BEFORE running, accounts for a budget, or carries an incarnation, so a crash loses the attempt and the count alike; the ledger this record decides does not exist (issue #34). The Pilot does honour the no-transparent-retry rule and reports a lost commit as indeterminate.
- 0012
The logbook is an append-only hash-chained journal Status: accepted
- 0013
Async work rides the write-ahead log, not a job table Status: accepted
- 0014
Reach isolated targets through a relay the Pilot dials out to Status: accepted
- 0015
- 0016
- 0017
A model may choose a route, never widen a bound Status: accepted
What exists: .golangci.yml enables the exhaustive linter and cites this record's two outcomes as the reason, so the guard is ready for the enum. There is no Surveyor, no panel and no enum.
- 0018
An agent's authority is the intersection of three scopes, including its own Status: accepted
What exists: The only mention in code is .golangci.yml, which anchors its gen/ exclusion so that a future agent package will not be silenced by it. No agent surface, no scope intersection, and not the test asserting an agent cannot approve.
- 0019
Escalation is a chain of named stages, and every stage is a person Status: accepted
What exists: A stage exists and is recorded: approvals is keyed on (tenant, request, stage, approver), and the service refuses any stage but 1 because M1 has no chain to define a second. The record's substance is absent — no chain, no per-stage thresholds, no timers, and nothing that treats a stage as escalation rather than as a column.
- 0022
- 0023
- 0024
The console is for deciding, and it has no bulk approve Status: accepted
- 0026
- 0027
Be psql first, then be better than psql Status: accepted
- 0028
- 0029
- 0030
- 0031
- 0032
Bind the executor, the tenant and the Pilot into the marque Status: accepted
- 0033
- 0034
Give the whole Pilot API an authorisation model, not just Execute Status: accepted
- 0035
- 0036
Anchor what is signed and what it claims, not only who may sign Status: accepted
- 0037
- 0039
The checkable grammar is parsed by PostgreSQL's own parser Status: accepted
What exists: The consequences are staged for it — the Makefile exports CGO_ENABLED=1 for every target, CI builds on four platforms, and the conformance corpus at testdata/conformance/ has its format, its validator and its subset_version field, though it holds no vectors yet. Nothing that decides anything exists: libpg_query is not linked in, there is no internal/grammar, and nothing reads a statement.
Implementation: partial6 of 42
Some of it runs, some does not.
- 0020
One schema generates every client, and annotates what may be retried Status: accepted
What exists: Built: the schema, the annotation extension, the build failure for an unannotated method (internal/schema/annotations.go), committed Go and Connect stubs, and the `buf breaking` check on every pull request. All five methods are served, and four of them are called: cmd/marque is the generated client for Submit, GetRequest and Approve, and cmd/pilot calls GetRequest and RecordExecution. GetVersion is served and has no caller — the binaries print their own build information locally. Not built: clients/ts/, the Pilot, Surveyor and relay schemas, typed errors, streams, and an interceptor that honours keyed and unsafe. Five methods exist — GetVersion, Submit, GetRequest, Approve and RecordExecution.
- 0021
Connect as the operator where the database can, and never let a driver retry a write Status: accepted
What exists: One rule of this record is built and tested: transparent retry is OFF for writes, so a commit whose answer never arrives is reported as indeterminate rather than replayed — internal/pilot, with the classification that tells a refused commit from a lost one. Nothing else is: no connection identity, no read routing, no pooling policy, and no session settings pinned on a target.
- 0025
Partition every tenant from day one, including its logbook chain and its signing key Status: accepted
What exists: The schema half exists from migration one: a tenants table, tenant_id NOT NULL on every domain table, composite foreign keys so a row cannot reference another tenant's parent, and tenant_id leading both indexes (EDR-0042). Every query is tenant-scoped — but to a CONFIGURED CONSTANT rather than to anyone's identity, because M1 has none, and no request field can reach it. Nothing structurally stops a query that omits the scope: issue #43.
- 0038
A request is a shareable, watchable object with a live status Status: accepted
What exists: The `req_…` reference exists, is randomly generated so it cannot be enumerated, and resolves through GetRequest — where an unknown one and another tenant's are the same NotFound, never a PermissionDenied that would confirm it. All seven states are in the schema and the proto, and M1 produces four of them. There is no status block, no chain, no watch and no notification; and the entitlement the 404 rule protects has nothing to enforce it against, because M1 has no identity.
- 0041
Spell a scope the same way in every artefact Status: accepted
What exists: The vector half exists: `internal/conformance` already decodes `operation`, `schema` and `relation` in this spelling and rejects anything else. The artefact half — delegations, compiled delegations, grants, marque payloads — is prose in records, because nothing parses one yet.
- 0042
Give the control plane's store a schema, a migrator, and a driver rule that survives PostgreSQL Status: accepted
What exists: The schema, the migrator, the confinement test and the depguard block exist, in the same change as store.Open. `harbourmaster migrate` is an explicit command and `harbourmaster serve` verifies and refuses rather than migrating. CI runs the loader offline and the whole store against a real PostgreSQL behind a build tag, including M1's steps end to end.
Implementation: shipped1 of 42
Built and running — the whole decision, not the easy half.
- 0040
Declare a method's behaviour in one annotation, and never weaken it Status: accepted
What exists: The one MethodBehaviour extension, the strengthen-only comparison (internal/schema/compat.go) and the idempotency_level agreement check all run in CI, via make lint and make breaking. The absent retry interceptor is not a missing half: this record's Scope section puts client-side retry behaviour outside it and leaves that obligation with EDR-0020.