docs(ruling-4b): round-3 review fixes — SOT Amendment A2, §6.4 outbox predicate
ci/woodpecker/pr/ci Pipeline was canceled

- native-kanban-sot.md gains §9 Amendment A2: expressly extends A1 §8.1.2
  (class data admits companies.visibility) and A1 §8.1.3 (company directory
  as an express, narrow read-only disclosure function; sole existence-oracle
  carve-out to §8.3), grounded on Ruling 4b. §9.2 pins what stays unchanged.
- hierarchy-schema.md §1.1 and the Amendment 1 note now cite A2 instead of
  reinterpreting A1; §6.7 acceptance cites A2 §9.1.2.
- §6.4 gains the explicit outbox predicate (state/event/outbox one
  transaction, rollback leaves neither event nor outbox record, REQ-AUD-001);
  §6.9's cross-reference corrected to match.
- §2.8: 'Ruling 4 §5.2' reference corrected to contract 3 §5.2.
This commit is contained in:
fred
2026-08-28 14:47:53 -05:00
parent df1e65abc2
commit 9819666b9d
2 changed files with 73 additions and 14 deletions
+22 -14
View File
@@ -84,7 +84,10 @@ definition is a follow-up amendment to contract 2 — until it ratifies,
admin-only); §6.1 and §6.9 add the witnesses; §6.7's existence-oracle admin-only); §6.1 and §6.9 add the witnesses; §6.7's existence-oracle
rule is scoped around the ratified directory carve-out. Top-level rule is scoped around the ratified directory carve-out. Top-level
creation (contract 3 §5.2) is unchanged and always yields a private creation (contract 3 §5.2) is unchanged and always yields a private
company. company. Upstream, SOT Amendment A2 (native-kanban-sot.md §9, this PR)
expressly extends A1 §8.1.2 to admit the visibility column and A1
§8.1.3 to admit the directory function — this contract relies on that
amendment, not on a reinterpretation of A1.
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,
@@ -102,12 +105,11 @@ legacy flat data (future work; see §1.3).
(payload prohibition, mutation path, audit) binds all five tables. Class (payload prohibition, mutation path, audit) binds all five tables. Class
rows carry parentage, naming, grant, audit-linkage, and visibility-class rows carry parentage, naming, grant, audit-linkage, and visibility-class
data only — never task, plan, or any business/orchestration payload. data only — never task, plan, or any business/orchestration payload.
Visibility (`companies.visibility`, §2.8) is ratified by Amendment 1 as Visibility (`companies.visibility`, §2.8) is admitted into that
authorization/disclosure data: it controls what the class discloses enumeration by SOT Amendment A2 §9.1.1, which expressly extends A1
about its own nodes, which sits inside A1 §8.1.2's §8.1.2 for exactly this one column: it is disclosure data about the
tenancy/authorization purpose for the class — it is not a payload class's own nodes — not a payload field, carries no business content,
field, carries no business content, and widens the payload prohibition and widens the payload prohibition for nothing else.
for nothing else.
References from business/orchestration rows into the class are limited References from business/orchestration rows into the class are limited
to exactly one form: the canonical `workspace_id` tenancy column that to exactly one form: the canonical `workspace_id` tenancy column that
REQ-TEN-001 requires on every canonical row, referencing REQ-TEN-001 requires on every canonical row, referencing
@@ -168,8 +170,8 @@ decision under A1; this contract pins only that they stay distinct tables.)
one of two classes, carried by `visibility`: one of two classes, carried by `visibility`:
- `private` (the default): the company is disclosed only to subjects - `private` (the default): the company is disclosed only to subjects
holding a grant on it or on a descendant — the resting state every holding a grant on it or on a descendant — the resting state every
company is created in. Ruling 4 §5.2 open creation survives company is created in. Open creation under contract 3 §5.2
unchanged: it creates private companies. (Ruling 4) survives unchanged: it creates private companies.
- `directory`: the company is listed in the deployment-wide company - `directory`: the company is listed in the deployment-wide company
directory. Directory listing discloses **existence, name, and slug directory. Directory listing discloses **existence, name, and slug
to every authenticated user — nothing else**: no subtree structure, to every authenticated user — nothing else**: no subtree structure,
@@ -415,8 +417,12 @@ Binding on the implementing PRs (extends A1 §8.3):
4. Audit witnesses: for each mutation class (create, rename, transfer, 4. Audit witnesses: for each mutation class (create, rename, transfer,
visibility change, grant create/change/revoke, delete) — the event visibility change, grant create/change/revoke, delete) — the event
exists after commit exists after commit
with actor/verb/target and same-transaction atomicity; a rolled-back with actor/verb/target and same-transaction atomicity, and the
mutation leaves no event (rollback witness); a node delete's cascaded event's outbox record exists after the same commit — state row,
audit event, and outbox record are witnessed as one transaction
(REQ-AUD-001); a rolled-back
mutation leaves no event and no outbox record (rollback witness); a
node delete's cascaded
grant deletions are each covered by events; events survive deletion of grant deletions are each covered by events; events survive deletion of
their target (query the events of a deleted node). their target (query the events of a deleted node).
5. Transfer tests: parent-FK update moves the subtree resolution and 5. Transfer tests: parent-FK update moves the subtree resolution and
@@ -436,7 +442,8 @@ Binding on the implementing PRs (extends A1 §8.3):
endpoints mutate no canonical state anywhere (assert zero writes across endpoints mutate no canonical state anywhere (assert zero writes across
hierarchy AND workspace tables, not hierarchy only); readers see hierarchy AND workspace tables, not hierarchy only); readers see
aggregates only over workspaces they are authorized on, with no aggregates only over workspaces they are authorized on, with no
cross-tenant existence oracles (A1 §8.3 acceptance 3) beyond the one cross-tenant existence oracles (A1 §8.3 acceptance 3, as narrowed by
A2 §9.1.2) beyond the one
ratified carve-out — the §2.8 company directory, witnessed in §6.9. ratified carve-out — the §2.8 company directory, witnessed in §6.9.
8. Real-PostgreSQL coverage for every constraint witness (unique/CHECK/ 8. Real-PostgreSQL coverage for every constraint witness (unique/CHECK/
RESTRICT/NULLS NOT DISTINCT behavior), using the `ci-postgres` service RESTRICT/NULLS NOT DISTINCT behavior), using the `ci-postgres` service
@@ -454,8 +461,9 @@ Binding on the implementing PRs (extends A1 §8.3):
yields `visibility = 'private'` and accepts no visibility argument; yields `visibility = 'private'` and accepts no visibility argument;
each visibility change emits its §5.2 audit event carrying old and each visibility change emits its §5.2 audit event carrying old and
new values — the full audit pattern for the mutation class new values — the full audit pattern for the mutation class
(same-transaction atomicity, rollback leaving no event, (same-transaction atomicity of state row, audit event, and outbox
actor/verb/target, outbox delivery) is §6.4's, which enumerates record; rollback leaving no event and no outbox record;
actor/verb/target) is §6.4's, which enumerates
visibility change; this item adds only the old/new-value payload visibility change; this item adds only the old/new-value payload
assertion. assertion.
+51
View File
@@ -456,3 +456,54 @@ this line is weakened.
- Negative tests prove roll-up endpoints cannot mutate state and that a - Negative tests prove roll-up endpoints cannot mutate state and that a
reader sees aggregates only over workspaces they are authorized on reader sees aggregates only over workspaces they are authorized on
(no cross-tenant existence oracles). (no cross-tenant existence oracles).
## 9. Amendment A2 — company visibility classes and the company directory
**Status:** amendment to Amendment A1, added by reviewed PR under Ruling 4b
(operator ruling, 2026-08-27; decision owner Jason; recorded in the webui-audit
lane RULINGS.md). Everything in §§18 remains binding verbatim, with exactly
the two express modifications below. Nothing else is weakened. The detailed
contract text lives in the hierarchy schema contract
(`hierarchy-schema.md` §2.8, §5.5, §6.9); this amendment changes only what A1
itself permits, so that contract does not stretch A1 by interpretation.
### 9.1 What A2 modifies in A1
1. **Class data (extends §8.1.2's first constraint).** The tenancy/authorization
structure record class additionally carries **visibility-class data**: the
single column `companies.visibility`, values `private` | `directory`
(hierarchy schema §2.8). Visibility is disclosure data about the class's own
nodes — what a company row reveals about its own existence — and is part of
the class's tenancy/authorization purpose. It is not business or
orchestration payload. §8.1.2's payload prohibition is widened for nothing
else: hierarchy tables still MUST NOT carry task, plan, or any other
business/orchestration payload, and this amendment admits exactly this one
column.
2. **The company directory (extends §8.1.3's function enumeration).** The
hierarchy serves one additional, express, narrow runtime function: the
**company directory** — a read-only disclosure listing of exactly the
companies whose `visibility = 'directory'`, revealing existence, name, and
slug to every authenticated user of the deployment and nothing else. It
mutates nothing, confers no authority, evaluates no grant down the chain,
and aggregates nothing (it is not a roll-up). §8.3's
no-cross-tenant-existence-oracle acceptance is narrowed by exactly this one
ratified carve-out: the directory is the sole permitted existence
disclosure, and it discloses only directory-class companies (witnessed in
hierarchy schema §6.7 and §6.9). Private companies remain undisclosed to
non-granted subjects everywhere, including the directory.
### 9.2 What A2 explicitly does not change
1. Content access stays grant-only under the RBAC grant model contract:
directory listing discloses existence, never content, membership, or any
authority (Ruling 3 unchanged; hierarchy schema §2.8).
2. Visibility changes are hierarchy mutations on the existing §8.2.3 audited
mutation path — audited maintenance of the class's own structure in
§8.1.3's sense, not a further runtime function. Authorization for them is
defined in hierarchy schema §5.5 (platform admins plus the future
company-CRUD capability; owner-as-such cannot publish).
3. Company creation is unchanged and always yields `visibility = 'private'`
(onboarding wizard §5.2); this amendment adds no creation path and no
default-open disclosure.
4. Every other constraint of A1 — §8.1.2's remaining bullets, §8.2 in full,
and §8.3's other acceptance criteria — is untouched.