From 4e643e0d0f1b56964075fd80f6d9a958c4e8e8aa Mon Sep 17 00:00:00 2001 From: fred Date: Fri, 28 Aug 2026 14:16:17 -0500 Subject: [PATCH 1/4] docs: company visibility classes (Ruling 4b amendment, contracts 1+3) --- docs/requirements/hierarchy-schema.md | 83 ++++++++++++++++++++++++-- docs/requirements/onboarding-wizard.md | 17 +++++- 2 files changed, 93 insertions(+), 7 deletions(-) diff --git a/docs/requirements/hierarchy-schema.md b/docs/requirements/hierarchy-schema.md index 5287133d..f66240c4 100644 --- a/docs/requirements/hierarchy-schema.md +++ b/docs/requirements/hierarchy-schema.md @@ -72,6 +72,20 @@ example now lists the complete measured set, and the import analysis is extended to resolve literal dynamic `import()` routes, which two of the four members use. +Amendment 1 (Ruling 4b, 2026-08-28): company visibility classes. The +directory exists so one shared company can serve many users instead of +each user creating a duplicate private company (Ruling 4b, webui-audit +lane, ruled 2026-08-27). §2.1 gains a `visibility` column; §2.8 defines +the two classes (`private`/`directory`), the directory's existence-only +disclosure, and the see-and-ask-to-join invariants; §5.2's mutation +enumeration gains the visibility change; §5.5 defines who may change +visibility (platform admins, plus a company-CRUD capability whose +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 +rule is scoped around the ratified directory carve-out. Top-level +creation (contract 3 §5.2) is unchanged and always yields a private +company. + 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 @@ -116,7 +130,9 @@ MUST NOT merge the two. (A rename of either remains an implementation-PR decision under A1; this contract pins only that they stay distinct tables.) 1. `companies` — id (uuid pk), name, slug (unique per deployment), - created_at, updated_at. N per deployment (D2). + `visibility` (text NOT NULL, DEFAULT `private`, CHECK constrained to + exactly `private` | `directory`; semantics §2.8), created_at, + updated_at. N per deployment (D2). 2. `estates` — id, name, slug, `company_id` NOT NULL → `companies.id` ON DELETE RESTRICT. Exactly one company per estate; a company holds any number of estates. @@ -142,6 +158,28 @@ decision under A1; this contract pins only that they stay distinct tables.) free-form payload field. The columns declared in this section and §3 are exhaustive: a class table's column set is exactly its declared set (verified per §6.2) — nothing else (A1 §8.1.2). +8. **Company visibility classes (Ruling 4b).** Every company is exactly + one of two classes, carried by `visibility`: + - `private` (the default): the company is disclosed only to subjects + holding a grant on it or on a descendant — the resting state every + company is created in. Ruling 4 §5.2 open creation survives + unchanged: it creates private companies. + - `directory`: the company is listed in the deployment-wide company + directory. Directory listing discloses **existence, name, and slug + to every authenticated user — nothing else**: no subtree structure, + no roll-up aggregates, no workspace content, no grant or membership + information. + Visibility is disclosure, not authority. Content and structure access + to a directory-listed company still require explicit grants — + contract 2 §3.1 deny-by-default is unchanged, and the ownership model + (§4.4, contract 2 §4.3) is unchanged. The directory supports a + see-and-ask-to-join flow (Ruling 4b decision 5): an authenticated + user may request to join a directory-listed company. Two invariants + bind any implementation of that flow now, ahead of its own contract: + a join request confers no authority of any kind, and approval is + ordinary grant creation by an effective `owner` under contract 2 §4.1 + — there is no other acceptance path. The flow's transport, storage, + and request lifecycle are a follow-up contract. ## 3. Grant attachment points @@ -223,7 +261,8 @@ shape contract 2 attaches to: 2. **Audit parity.** A1 §8.2 leaves every pre-existing REQ binding, so hierarchy mutations get REQ-AUD-001's guarantees, not a weakened substitute. Concretely: - - Every create, rename, transfer, grant create/change/revoke, and + - Every create, rename, transfer, visibility change (§5.5), grant + create/change/revoke, and delete — including every grant deletion cascaded by a node delete — emits a semantic audit event carrying actor, verb, target, and (for transfers) source and destination parents, with the correlation, @@ -248,6 +287,25 @@ shape contract 2 attaches to: workspace work. Contract 8 owns projection details but cannot narrow this rule. This contract additionally guarantees the chain roll-ups aggregate over is unique and non-null (§2.5). +5. **Visibility administration (Ruling 4b decisions 2–3).** Changing + `companies.visibility` is a hierarchy mutation through the §5.1 + command path, audited per §5.2 (the event carries the old and new + visibility values as its semantic content). It is authorized for + exactly two actor classes: platform admins (`users.role = 'admin'`) + and subjects holding the company-CRUD capability that a follow-up + amendment to contract 2 will define — until that amendment ratifies, + the capability class is empty and the command is admin-only. + A company `owner` as such may NOT change visibility: standard users + cannot publish a company into the directory. This is the one + hierarchy mutation a platform admin performs without holding a + hierarchy grant, and it is ratified here as instance administration + (directory curation) in contract 2 §1.1's sense, not tenant access: + the command mutates the single `visibility` column, reads no tenant + content, and confers no grant — contract 2 §1.1's + no-implicit-tenant-access rule is otherwise untouched. Top-level + company creation (contract 3 §5.2) always creates + `visibility = 'private'`; the creation command cannot set or change + visibility. ## 6. Verification requirements @@ -264,7 +322,10 @@ Binding on the implementing PRs (extends A1 §8.3): witnessed (zero and two set → refused). Grant uniqueness: a duplicate (subject, target, role) row refused for each of the six subject×target forms, proving NULLS-NOT-DISTINCT semantics; NOT NULL on `role`, - `granted_by`, and all `name`/`slug` columns witnessed. + `granted_by`, and all `name`/`slug` columns witnessed. Company + visibility (§2.8): a value outside `private`/`directory` refused with + both valid values accepted as the control; an insert omitting the + column defaults to `private`. 2. Column allowlist: an information_schema assertion that each class 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). @@ -368,10 +429,24 @@ Binding on the implementing PRs (extends A1 §8.3): endpoints mutate no canonical state anywhere (assert zero writes across hierarchy AND workspace tables, not hierarchy only); readers see aggregates only over workspaces they are authorized on, with no - cross-tenant existence oracles (A1 §8.3 acceptance 3). + cross-tenant existence oracles (A1 §8.3 acceptance 3) beyond the one + ratified carve-out — the §2.8 company directory, witnessed in §6.9. 8. Real-PostgreSQL coverage for every constraint witness (unique/CHECK/ RESTRICT/NULLS NOT DISTINCT behavior), using the `ci-postgres` service in the `test` CI step; mocked specs cannot witness database constraints. +9. Visibility witnesses (§2.8, §5.5): the directory read returns exactly + the `visibility = 'directory'` companies to any authenticated user, + disclosing existence, name, and slug only (closed-field assertion on + the response shape); a private company never appears in the directory + for a reader without a grant on it (with the control: it appears in + that reader's granted-structure reads); a directory-listed company's + subtree, aggregates, and content remain refused for a non-granted + reader (disclosure ≠ authority); the visibility command is refused + for a non-admin actor — including an effective `owner` of the target + company — with the platform-admin accept control; top-level creation + yields `visibility = 'private'` and accepts no visibility argument; + each visibility change emits its §5.2 audit event carrying old and + new values. ## Ruling request diff --git a/docs/requirements/onboarding-wizard.md b/docs/requirements/onboarding-wizard.md index 67153aa2..2ec0fd39 100644 --- a/docs/requirements/onboarding-wizard.md +++ b/docs/requirements/onboarding-wizard.md @@ -397,6 +397,14 @@ seed-workspace-scoped mutant, correctly refusing outside the seed set, passes branch (c), so the two branches detect distinct mutants. No other change. +Amendment 1 (Ruling 4b, 2026-08-28): §5.2's embedded decision was RULED +AGREED (Jason, 2026-08-27), and Ruling 4b adds company visibility +classes (hierarchy schema §2.8): open top-level creation always yields +a **private** company; publishing a company into the deployment-wide +directory is a separate, gated visibility mutation (hierarchy schema +§5.5) that is never part of the creation command. §5.2 is amended to +state both. + Scope: the Gateway-backed product onboarding wizard. Out of scope: the host-local install wizard (`mosaic wizard`, which drives host install and gateway bootstrap and is not this artifact — audit REPORT.md layer 3); @@ -1169,15 +1177,18 @@ collects no sensitive category, so v1 ships no custody surface. party, service actor, or wizard-privileged writer exists in this flow. 2. **Post-bootstrap top-level company creation** — the "N companies" flow - — is decided by the ruling below: any **eligible platform user** MAY + — RULED AGREED (Jason, 2026-08-27): any **eligible platform user** MAY create a top-level company and MUST name an initial `owner` grant in the same audited operation (contract 2 §4.3); the creator naming themselves is the default. Eligible means, in identity-contract terms: an authenticated account (identity §2) that is not banned (identity §7.1 — deactivation on this platform IS the better-auth ban; no separate deactivated state exists). No further role or grant - is required. Until that ruling, deny-by-default holds (contract 2 - §3.1): no implicit creation authority exists. + is required. Creation always yields a **private** company + (`visibility = 'private'`, hierarchy schema §2.8, Ruling 4b): the + creation command accepts no visibility argument, and publishing into + the deployment-wide directory is a separate, gated mutation + (hierarchy schema §5.5) that standard users cannot perform. 3. Child-node creation inside the wizard (estate, project, workspace under the seeded company) follows contract 2 §4.3: parent `owner` authority, no automatic grant needed — for canonical seed -- 2.54.0 From df1e65abc2ef5f697176202e3c50cc0aa82074c7 Mon Sep 17 00:00:00 2001 From: fred Date: Fri, 28 Aug 2026 14:31:37 -0500 Subject: [PATCH 2/4] docs: address terra round-1 findings on 4b amendment (class-data classification, visibility audit witness, ruled request annotation) --- docs/requirements/hierarchy-schema.md | 19 +++++++++++++++---- docs/requirements/onboarding-wizard.md | 8 +++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/requirements/hierarchy-schema.md b/docs/requirements/hierarchy-schema.md index f66240c4..389fda16 100644 --- a/docs/requirements/hierarchy-schema.md +++ b/docs/requirements/hierarchy-schema.md @@ -100,8 +100,14 @@ legacy flat data (future work; see §1.3). AND `hierarchy_grants` (§3) — A1 includes hierarchy-level access grants in the class. Every rule addressed to "the class" in this contract (payload prohibition, mutation path, audit) binds all five tables. Class - rows carry parentage, naming, grant, and audit-linkage data only — never - task, plan, or any business/orchestration payload. + rows carry parentage, naming, grant, audit-linkage, and visibility-class + data only — never task, plan, or any business/orchestration payload. + Visibility (`companies.visibility`, §2.8) is ratified by Amendment 1 as + authorization/disclosure data: it controls what the class discloses + about its own nodes, which sits inside A1 §8.1.2's + tenancy/authorization purpose for the class — it is not a payload + field, carries no business content, and widens the payload prohibition + for nothing else. References from business/orchestration rows into the class are limited to exactly one form: the canonical `workspace_id` tenancy column that REQ-TEN-001 requires on every canonical row, referencing @@ -407,7 +413,8 @@ Binding on the implementing PRs (extends A1 §8.3): 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 + visibility change, grant create/change/revoke, delete) — the event + exists after commit with actor/verb/target and same-transaction atomicity; a rolled-back mutation leaves no event (rollback witness); a node delete's cascaded grant deletions are each covered by events; events survive deletion of @@ -446,7 +453,11 @@ Binding on the implementing PRs (extends A1 §8.3): company — with the platform-admin accept control; top-level creation yields `visibility = 'private'` and accepts no visibility argument; each visibility change emits its §5.2 audit event carrying old and - new values. + new values — the full audit pattern for the mutation class + (same-transaction atomicity, rollback leaving no event, + actor/verb/target, outbox delivery) is §6.4's, which enumerates + visibility change; this item adds only the old/new-value payload + assertion. ## Ruling request diff --git a/docs/requirements/onboarding-wizard.md b/docs/requirements/onboarding-wizard.md index 2ec0fd39..b50fb8e4 100644 --- a/docs/requirements/onboarding-wizard.md +++ b/docs/requirements/onboarding-wizard.md @@ -1943,7 +1943,13 @@ contracts and are not additions: suffix at all — each contradicting PRD D4's no-lock-in requirement (§4.4). -## Ruling request +## Ruling request — RULED AGREED (Jason, 2026-08-27; Amendment 1) + +The §5.2 decision below was ruled agreed: open eligible-user creation +stands (yielding private companies per Amendment 1), and the +"alternative if rejected" did not take effect. The request is retained +below as historical record of what was put to ruling; it is no longer +live. Ratify sections 1–7 as written, with one decision embedded: -- 2.54.0 From 9819666b9d1f6dddb7cf88e696bf98e4e5648c44 Mon Sep 17 00:00:00 2001 From: fred Date: Fri, 28 Aug 2026 14:47:53 -0500 Subject: [PATCH 3/4] =?UTF-8?q?docs(ruling-4b):=20round-3=20review=20fixes?= =?UTF-8?q?=20=E2=80=94=20SOT=20Amendment=20A2,=20=C2=A76.4=20outbox=20pre?= =?UTF-8?q?dicate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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. --- docs/requirements/hierarchy-schema.md | 36 +++++++++++------- docs/requirements/native-kanban-sot.md | 51 ++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/docs/requirements/hierarchy-schema.md b/docs/requirements/hierarchy-schema.md index 389fda16..b7af38d0 100644 --- a/docs/requirements/hierarchy-schema.md +++ b/docs/requirements/hierarchy-schema.md @@ -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 rule is scoped around the ratified directory carve-out. Top-level 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, 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 rows carry parentage, naming, grant, audit-linkage, and visibility-class data only — never task, plan, or any business/orchestration payload. - Visibility (`companies.visibility`, §2.8) is ratified by Amendment 1 as - authorization/disclosure data: it controls what the class discloses - about its own nodes, which sits inside A1 §8.1.2's - tenancy/authorization purpose for the class — it is not a payload - field, carries no business content, and widens the payload prohibition - for nothing else. + Visibility (`companies.visibility`, §2.8) is admitted into that + enumeration by SOT Amendment A2 §9.1.1, which expressly extends A1 + §8.1.2 for exactly this one column: it is disclosure data about the + class's own nodes — not a payload field, carries no business content, + and widens the payload prohibition for nothing else. References from business/orchestration rows into the class are limited to exactly one form: the canonical `workspace_id` tenancy column that 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`: - `private` (the default): the company is disclosed only to subjects holding a grant on it or on a descendant — the resting state every - company is created in. Ruling 4 §5.2 open creation survives - unchanged: it creates private companies. + company is created in. Open creation under contract 3 §5.2 + (Ruling 4) survives unchanged: it creates private companies. - `directory`: the company is listed in the deployment-wide company directory. Directory listing discloses **existence, name, and slug 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, visibility change, grant create/change/revoke, delete) — the event exists after commit - with actor/verb/target and same-transaction atomicity; a rolled-back - mutation leaves no event (rollback witness); a node delete's cascaded + with actor/verb/target and same-transaction atomicity, and the + 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 their target (query the events of a deleted node). 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 hierarchy AND workspace tables, not hierarchy only); readers see 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. 8. Real-PostgreSQL coverage for every constraint witness (unique/CHECK/ 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; each visibility change emits its §5.2 audit event carrying old and new values — the full audit pattern for the mutation class - (same-transaction atomicity, rollback leaving no event, - actor/verb/target, outbox delivery) is §6.4's, which enumerates + (same-transaction atomicity of state row, audit event, and outbox + 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 assertion. diff --git a/docs/requirements/native-kanban-sot.md b/docs/requirements/native-kanban-sot.md index 9ba524fe..63738e4d 100644 --- a/docs/requirements/native-kanban-sot.md +++ b/docs/requirements/native-kanban-sot.md @@ -456,3 +456,54 @@ this line is weakened. - Negative tests prove roll-up endpoints cannot mutate state and that a reader sees aggregates only over workspaces they are authorized on (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 §§1–8 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. -- 2.54.0 From 146304d1b017b625310ddc897fae8da13d49b871 Mon Sep 17 00:00:00 2001 From: fred Date: Fri, 28 Aug 2026 14:58:35 -0500 Subject: [PATCH 4/4] =?UTF-8?q?docs(ruling-4b):=20round-4=20review=20fixes?= =?UTF-8?q?=20=E2=80=94=20rollback=20state=20predicate,=20join=20flow=20de?= =?UTF-8?q?ferred?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §6.4 rollback witness now requires no state effect on rollback (create leaves no row; rename/transfer/visibility change leave prior values; delete/revoke leave the row present) alongside no event and no outbox record — all three REQ-AUD-001 legs; §6.9 cross-ref mirrors it. - §2.8 no longer authorizes a join-request runtime surface: the see-and-ask-to-join flow (Ruling 4b decision 5) is deferred in its entirety to its follow-up contract, with §2.8's invariants pre-binding it; A2 §9.2 gains the matching express exclusion (that contract must amend A2's enumeration before any join-request surface exists). --- docs/requirements/hierarchy-schema.md | 30 +++++++++++++++++--------- docs/requirements/native-kanban-sot.md | 13 ++++++++--- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/docs/requirements/hierarchy-schema.md b/docs/requirements/hierarchy-schema.md index b7af38d0..e5525bbf 100644 --- a/docs/requirements/hierarchy-schema.md +++ b/docs/requirements/hierarchy-schema.md @@ -77,7 +77,9 @@ directory exists so one shared company can serve many users instead of each user creating a duplicate private company (Ruling 4b, webui-audit lane, ruled 2026-08-27). §2.1 gains a `visibility` column; §2.8 defines the two classes (`private`/`directory`), the directory's existence-only -disclosure, and the see-and-ask-to-join invariants; §5.2's mutation +disclosure, and the pre-binding invariants for the deferred +see-and-ask-to-join flow (no join-request surface is authorized here — +its flow is a follow-up contract); §5.2's mutation enumeration gains the visibility change; §5.5 defines who may change visibility (platform admins, plus a company-CRUD capability whose definition is a follow-up amendment to contract 2 — until it ratifies, @@ -180,14 +182,17 @@ decision under A1; this contract pins only that they stay distinct tables.) Visibility is disclosure, not authority. Content and structure access to a directory-listed company still require explicit grants — contract 2 §3.1 deny-by-default is unchanged, and the ownership model - (§4.4, contract 2 §4.3) is unchanged. The directory supports a - see-and-ask-to-join flow (Ruling 4b decision 5): an authenticated - user may request to join a directory-listed company. Two invariants - bind any implementation of that flow now, ahead of its own contract: + (§4.4, contract 2 §4.3) is unchanged. Ruling 4b decision 5 wants a + see-and-ask-to-join flow for directory-listed companies. **This + contract authorizes no join-request runtime surface**: the flow in + its entirety — the ability to submit a request, its transport, + storage, and request lifecycle — is a follow-up contract, and until + that contract ratifies, the directory's only function is the + read-only listing above (A2 §9.1.2 admits nothing more). Two + invariants pre-bind that future contract now: a join request confers no authority of any kind, and approval is ordinary grant creation by an effective `owner` under contract 2 §4.1 - — there is no other acceptance path. The flow's transport, storage, - and request lifecycle are a follow-up contract. + — there is no other acceptance path. ## 3. Grant attachment points @@ -421,7 +426,12 @@ Binding on the implementing PRs (extends A1 §8.3): 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 + mutation leaves no event, no outbox record, AND no state effect — + a rolled-back create leaves no row, a rolled-back rename, transfer, + or visibility change leaves the prior values in place, and a + rolled-back delete or grant revoke leaves the row present + (rollback witness on all three legs, per REQ-AUD-001's + commit-or-roll-back-together acceptance); a node delete's cascaded grant deletions are each covered by events; events survive deletion of their target (query the events of a deleted node). @@ -462,8 +472,8 @@ Binding on the implementing PRs (extends A1 §8.3): each visibility change emits its §5.2 audit event carrying old and new values — the full audit pattern for the mutation class (same-transaction atomicity of state row, audit event, and outbox - record; rollback leaving no event and no outbox record; - actor/verb/target) is §6.4's, which enumerates + record; rollback leaving no state effect, 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 assertion. diff --git a/docs/requirements/native-kanban-sot.md b/docs/requirements/native-kanban-sot.md index 63738e4d..ea99a50b 100644 --- a/docs/requirements/native-kanban-sot.md +++ b/docs/requirements/native-kanban-sot.md @@ -497,13 +497,20 @@ itself permits, so that contract does not stretch A1 by interpretation. 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 +2. **No join-request surface is authorized.** Ruling 4b decision 5's + see-and-ask-to-join flow is a follow-up contract in its entirety — + including the ability to submit a request. A2 admits exactly the + read-only listing of §9.1.2 and nothing more; hierarchy schema §2.8 + states the invariants that pre-bind the future flow contract, and that + contract must itself amend this enumeration before any join-request + runtime surface exists. +3. 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'` +4. 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, +5. Every other constraint of A1 — §8.1.2's remaining bullets, §8.2 in full, and §8.3's other acceptance criteria — is untouched. -- 2.54.0