docs: hierarchy schema contract revision 3 (terra r2 residuals F4, F7)
ci/woodpecker/pr/ci Pipeline is pending

This commit is contained in:
fred
2026-08-26 18:43:00 -05:00
parent ee8c593858
commit f5e3165ea5
+27 -6
View File
@@ -20,6 +20,16 @@ guarantees with deletion-safe linkage (§5.2); roll-up never-a-write restored
to full A1 strength (§5.4); §6 rebuilt with bounded observables for every to full A1 strength (§5.4); §6 rebuilt with bounded observables for every
MUST (allowlist, command surface, audit, corrected cardinality witness). MUST (allowlist, command surface, audit, corrected cardinality witness).
Revision 3 (terra re-review residuals): §4.3 transfer write inventory
reconciled with §5.2 — the transaction's writes are the single class-row
mutation plus that mutation's §5.2 audit writes (event + outbox record),
not "exactly two writes"; §6.3 extended with a closed writer-coverage
witness so an unregistered internal writer cannot pass a registered-route
inventory. (Terra's finding-8 residual — a stale contract 2 §7.8 backlink
to contract 1 §6.2 — was already fixed in contract 2 revision 2, which
cites §6.5; measured against `origin/contract/rbac-grants` head
`501112d2`.)
Scope: the tenancy/authorization structure record class — companies, Scope: the tenancy/authorization structure record class — companies,
estates, platform-projects, workspaces, hierarchy grants, their parentage, estates, platform-projects, workspaces, hierarchy grants, their parentage,
and constraints. Out of scope: the RBAC grant vocabulary and evaluation and constraints. Out of scope: the RBAC grant vocabulary and evaluation
@@ -143,8 +153,11 @@ shape contract 2 attaches to:
introduced by this contract pair** (D2/A1 do not state it); its introduced by this contract pair** (D2/A1 do not state it); its
evaluation semantics are contract 2 §5. The structural half — that the evaluation semantics are contract 2 §5. The structural half — that the
transfer command evaluates it before mutating — binds here. transfer command evaluates it before mutating — binds here.
3. A transfer transaction contains exactly two writes: the single-row 3. A transfer transaction mutates exactly one class-table row — the
parent-FK update and its audit event (§5.2). There are no multi-row single-row parent-FK update and contains, beyond that, only the
§5.2 audit writes for that mutation (the audit event and its
hierarchy-outbox record, committing in the same transaction). No other
class, business, or orchestration row changes. There are no multi-row
transfer batches at the schema level; bulk moves are N audited transfer batches at the schema level; bulk moves are N audited
transfers. transfers.
4. Hierarchy records have no `owner_id`. Ownership in the hierarchy IS the 4. Hierarchy records have no `owner_id`. Ownership in the hierarchy IS the
@@ -213,10 +226,18 @@ Binding on the implementing PRs (extends A1 §8.3):
2. Column allowlist: an information_schema assertion that each class 2. Column allowlist: an information_schema assertion that each class
table's column set is exactly the set declared in §2/§3 — the bounded table's column set is exactly the set declared in §2/§3 — the bounded
observable for no-payload (§2.7) and no-`owner_id` (§4.4). observable for no-payload (§2.7) and no-`owner_id` (§4.4).
3. Command surface: an inventory assertion over the Gateway's registered 3. Command surface: two witnesses, both required (§5.1). (a) Route
hierarchy routes/commands proving the mutation surface is exactly the inventory: an assertion over the Gateway's registered hierarchy
declared hierarchy command family — no generic CRUD endpoint and no routes/commands proving the registered mutation surface is exactly the
non-command write path touches class tables (§5.1). declared hierarchy command family — no generic CRUD endpoint. (b)
Writer coverage — the closed allowlist a route inventory cannot
provide: a static CI assertion over the Gateway and package sources
that write references to the class-table schema symbols (insert,
update, delete) occur only in an explicitly enumerated allowlist of
hierarchy command/repository modules. The allowlist is closed: a new
writer anywhere else fails the assertion until the allowlist is
extended in the same PR, so an unregistered internal or raw-SQL write
path is surfaced in CI and review rather than passing unnoticed.
4. Audit witnesses: for each mutation class (create, rename, transfer, 4. Audit witnesses: for each mutation class (create, rename, transfer,
grant create/change/revoke, delete) — the event exists after commit grant create/change/revoke, delete) — the event exists after commit
with actor/verb/target and same-transaction atomicity; a rolled-back with actor/verb/target and same-transaction atomicity; a rolled-back