From e32d77e5a14ff5b3285435779f6d99b5f21e22af Mon Sep 17 00:00:00 2001 From: fred Date: Wed, 26 Aug 2026 18:55:08 -0500 Subject: [PATCH] =?UTF-8?q?docs:=20hierarchy=20contract=20revision=205=20?= =?UTF-8?q?=E2=80=94=20raw-execution=20prong=20closes=20dynamic-identifier?= =?UTF-8?q?=20evasion=20(terra=20r4=20F7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/requirements/hierarchy-schema.md | 31 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/docs/requirements/hierarchy-schema.md b/docs/requirements/hierarchy-schema.md index e18a817a..a1332b30 100644 --- a/docs/requirements/hierarchy-schema.md +++ b/docs/requirements/hierarchy-schema.md @@ -35,6 +35,13 @@ extended to raw SQL — it now also fails on class-table name literals inside SQL strings or tagged SQL templates outside the allowlist, so a raw-SQL writer that touches no schema symbol is still caught. +Revision 5 (terra r4 residual F7): §6.3(b) gains a third prong — any +raw-SQL execution primitive outside the allowlist fails the assertion +regardless of its SQL content, closing the evasion where a +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. + 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 @@ -243,13 +250,23 @@ Binding on the implementing PRs (extends A1 §8.3): occur only in allowlisted modules. (ii) Literal prong: a class-table name appearing inside a SQL string or tagged SQL template outside the allowlist fails the assertion — this is what catches a raw-SQL writer - that references no schema symbol. 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) is resolved by - extending the allowlist in the same PR, never by weakening the - assertion. The allowlist is closed: any new writer, ORM or raw, - fails CI until the allowlist names it, so the write path is surfaced - in review rather than passing unnoticed. + that references no schema symbol. (iii) Raw-execution prong: any call + to a raw-SQL execution primitive (the ORM's raw/unsafe constructors, + driver-level query/execute) outside the allowlist fails the + assertion, regardless of what the SQL string contains or how it is + 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. 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