docs: hierarchy contract revision 6 — three-prong wording, allowlist composition rules, honest detection scope (terra r5 F7/F8)
ci/woodpecker/pr/ci Pipeline is pending

This commit is contained in:
fred
2026-08-26 19:02:11 -05:00
parent e32d77e5a1
commit 5c1e8d290e
+31 -12
View File
@@ -42,6 +42,14 @@ dynamically constructed table name carries neither a schema symbol nor
a class-table literal. The detection claim is now coextensive with a class-table literal. The detection claim is now coextensive with
what the three prongs statically see. what the three prongs statically see.
Revision 6 (terra r5 residual F7 + new F8): the "two prongs" wording
corrected to three (F8); §6.3(b) gains the allowlist composition rules
(no generic raw-SQL helper is allowlisted; an allowlisted module may
not export caller-supplied-SQL execution) and fails outright on
runtime code-construction primitives; the detection claim is scoped
honestly to the stated syntactic forms, with evasions beyond static
reach assigned to §5.1 review/audit rather than claimed for CI.
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
@@ -244,8 +252,8 @@ Binding on the implementing PRs (extends A1 §8.3):
declared hierarchy command family — no generic CRUD endpoint. (b) declared hierarchy command family — no generic CRUD endpoint. (b)
Writer coverage — the closed allowlist a route inventory cannot Writer coverage — the closed allowlist a route inventory cannot
provide: a static CI assertion over the Gateway and package sources provide: a static CI assertion over the Gateway and package sources
with two prongs, both bound to one explicitly enumerated allowlist of with three prongs, each bound to one explicitly enumerated allowlist
hierarchy command/repository modules. (i) Symbol prong: write of hierarchy command/repository modules. (i) Symbol prong: write
references to the class-table schema symbols (insert, update, delete) references to the class-table schema symbols (insert, update, delete)
occur only in allowlisted modules. (ii) Literal prong: a class-table occur only in allowlisted modules. (ii) Literal prong: a class-table
name appearing inside a SQL string or tagged SQL template outside the name appearing inside a SQL string or tagged SQL template outside the
@@ -257,16 +265,27 @@ Binding on the implementing PRs (extends A1 §8.3):
constructed — the call site is statically detectable even when a constructed — the call site is statically detectable even when a
dynamically assembled table name is not, so a raw writer with a dynamically assembled table name is not, so a raw writer with a
runtime-built identifier is caught by its primitive, not its runtime-built identifier is caught by its primitive, not its
payload. Schema definitions and generated migrations are excluded payload. Two composition rules keep prong (iii) meaningful: the
from the literal prong; a false positive (e.g. a table name in a allowlist names hierarchy command/repository modules only — a
non-write query string, or a legitimate raw query elsewhere in the generic raw-SQL helper or database-utility module is never
codebase) is resolved by extending the allowlist in the same PR, allowlisted; and an allowlisted module MUST NOT export a function
never by weakening the assertion. The allowlist is closed: a symbol that executes caller-supplied SQL (such an export is itself a
writer fails prong (i), a raw writer naming a class table fails raw-execution primitive, and the exporting module is treated as
prong (ii), and any raw execution at all outside the allowlist fails unallowlisted for prong (iii) if it does). Runtime code-construction
prong (iii), so every new writer — ORM, raw-literal, or primitives (`eval`, `new Function`) anywhere in the scanned sources
dynamically constructed — fails CI until the allowlist names it and fail the assertion outright, allowlist or not. Schema definitions
the write path is surfaced in review rather than passing unnoticed. and generated migrations are excluded from the literal prong; a
false positive (e.g. a table name in a non-write query string, or a
legitimate raw query elsewhere in the codebase) is resolved by
extending the allowlist in the same PR, never by weakening the
assertion. The allowlist is closed, and the assertion's detection
claim is exactly its prongs: it statically surfaces every writer
expressed as a schema-symbol reference, a class-table SQL literal, a
raw-execution call site, or runtime code construction. An evasion
engineered outside those syntactic forms is a §5.1 violation that
review and audit own — the witness does not claim to catch what
static analysis cannot see, and any such evasion found later is
corrected as a conformance defect, not grandfathered.
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