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
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,
estates, platform-projects, workspaces, hierarchy grants, their parentage,
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)
Writer coverage — the closed allowlist a route inventory cannot
provide: a static CI assertion over the Gateway and package sources
with two prongs, both bound to one explicitly enumerated allowlist of
hierarchy command/repository modules. (i) Symbol prong: write
with three prongs, each bound to one explicitly enumerated allowlist
of hierarchy command/repository modules. (i) Symbol prong: write
references to the class-table schema symbols (insert, update, delete)
occur only in allowlisted modules. (ii) Literal prong: a class-table
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
dynamically assembled table name is not, so a raw writer with a
runtime-built identifier is caught by its primitive, not its
payload. Schema definitions 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: a symbol
writer fails prong (i), a raw writer naming a class table fails
prong (ii), and any raw execution at all outside the allowlist fails
prong (iii), so every new writer — ORM, raw-literal, or
dynamically constructed — fails CI until the allowlist names it and
the write path is surfaced in review rather than passing unnoticed.
payload. Two composition rules keep prong (iii) meaningful: the
allowlist names hierarchy command/repository modules only — a
generic raw-SQL helper or database-utility module is never
allowlisted; and an allowlisted module MUST NOT export a function
that executes caller-supplied SQL (such an export is itself a
raw-execution primitive, and the exporting module is treated as
unallowlisted for prong (iii) if it does). Runtime code-construction
primitives (`eval`, `new Function`) anywhere in the scanned sources
fail the assertion outright, allowlist or not. Schema definitions
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,
grant create/change/revoke, delete) — the event exists after commit
with actor/verb/target and same-transaction atomicity; a rolled-back