diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 6168027..5fe8c1e 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -18,6 +18,7 @@ | workplan | TEN-WP-0007 | finished | — | workplans/TEN-WP-0007-guardrail-production-rollout.md | | workplan | TEN-WP-0008 | ready | — | workplans/TEN-WP-0008-staged-promotion-onboarding.md | | workplan | TEN-WP-0009 | ready | — | workplans/TEN-WP-0009-postgres-production-store.md | +| workplan | TEN-WP-0010 | ready | — | workplans/TEN-WP-0010-mutable-grouping.md | | task | ADHOC-2026-07-24-T01 | done | — | workplans/ADHOC-2026-07-24.md | | task | TEN-WP-0001-T01 | done | — | workplans/TEN-WP-0001-statehub-bootstrap.md | | task | TEN-WP-0001-T02 | done | — | workplans/TEN-WP-0001-statehub-bootstrap.md | @@ -60,3 +61,8 @@ | task | TEN-WP-0009-T04 | todo | — | workplans/TEN-WP-0009-postgres-production-store.md | | task | TEN-WP-0009-T05 | todo | — | workplans/TEN-WP-0009-postgres-production-store.md | | task | TEN-WP-0009-T06 | todo | — | workplans/TEN-WP-0009-postgres-production-store.md | +| task | TEN-WP-0010-T01 | todo | — | workplans/TEN-WP-0010-mutable-grouping.md | +| task | TEN-WP-0010-T02 | todo | — | workplans/TEN-WP-0010-mutable-grouping.md | +| task | TEN-WP-0010-T03 | todo | — | workplans/TEN-WP-0010-mutable-grouping.md | +| task | TEN-WP-0010-T04 | todo | — | workplans/TEN-WP-0010-mutable-grouping.md | +| task | TEN-WP-0010-T05 | todo | — | workplans/TEN-WP-0010-mutable-grouping.md | diff --git a/workplans/TEN-WP-0010-mutable-grouping.md b/workplans/TEN-WP-0010-mutable-grouping.md index 813c098..fb090c5 100644 --- a/workplans/TEN-WP-0010-mutable-grouping.md +++ b/workplans/TEN-WP-0010-mutable-grouping.md @@ -12,6 +12,7 @@ updated: "2026-08-17" depends_on: - TEN-WP-0006 unblocks: [] +state_hub_workstream_id: "956d202f-e69d-4786-9525-6acf6e93116c" --- # TEN-WP-0010 - Mutable grouping @@ -72,6 +73,7 @@ about to start going stale, and does not know it.** id: TEN-WP-0010-T01 status: todo priority: high +state_hub_task_id: "374626c0-5dad-458f-a595-e4e06fe47017" ``` The identifier format is canon's, not ours. Propose rather than decide. @@ -93,12 +95,22 @@ here. **Implementation may proceed in parallel** — the field already exists an making our own record mutable does not require canon's permission — but the prohibition in point 4 is not fleet-binding until ratified. +Status 2026-08-17: **proposed to `net-kingdom`, awaiting ratification.** +Argued for the current-classification reading, with the guardrail consequence +stated plainly so the alternative is chosen knowingly rather than inherited. +Carried T02's survey as evidence that the prohibition breaks nothing on day +one, and its limits so the evidence is not overread. Offered the frozen reading +as a real option, with the exception path it would then require. + +Implementation proceeds in parallel per the note above. + ## T02 - Find out who parses the grouping segment ```task id: TEN-WP-0010-T02 -status: todo +status: done priority: high +state_hub_task_id: "d98353d6-3116-4dc8-927a-8951889169cb" ``` Survey the estate for consumers that split the identifier and read @@ -121,12 +133,43 @@ for a live decision needs to call us instead. Done when the list is complete and each parser has either confirmed onboarding-time semantics or been given the read API to use instead. +Done 2026-08-17. **Nobody parses the grouping segment. The list is empty.** + +Swept every local checkout for identifier splitting, `parts[1]` indexing, +`GROUPINGS`-style vocabularies, and literal `tenant::` strings, across +Python, Go, TypeScript, Rust and Rego. Findings: + +| Consumer | Verdict | +|---|---| +| `key-cape` | opaque. `Tenant` is a plain `string` field on the domain model; no `strings.Split` touches it. The two hits are doc comments citing the format. | +| `user-engine` | opaque. The one `parts[1]` is **URL path** splitting in `_tenant_lifecycle_route`, matching `retire`/`reactivate` — not identifier splitting. Checked because it was the most likely false positive, and it was one. | +| `flex-auth` | no hits at all. Consistent with treating the tenant as an opaque subject. | +| `adaptive-pricing` | no hits. Plan eligibility by grouping was the obvious risk and it does not exist. | +| `audit-core`, `net-kingdom` configs | whole identifiers used as opaque values in allowlists and fixtures. | +| `rapp-postgres` | confirmed unaffected by them; ADR-0001 forbids parsing. | + +**OpenBao paths use the *name* segment, not grouping** — `ops-warden`'s +delegation register shows custody at `tenants/binky/company-email/imap`. The +name segment is stable under this change, so those paths are unaffected. + +Consequence for T01: the amendment **codifies existing behaviour** rather than +requiring anyone to change. That materially lowers its risk and should be said +plainly when proposing it — a prohibition nobody is currently violating is far +easier to ratify than one that breaks a live consumer. + +Honest limit on this evidence: it covers repos checked out on this workstation +and searched by source pattern. It would not catch a consumer that reconstructs +the grouping from a stored copy, one whose repo is not present here, or one +written since. The prohibition in T01 is what makes the guarantee durable; +this survey only establishes that nothing breaks on day one. + ## T03 - Implement the audited grouping mutation ```task id: TEN-WP-0010-T03 status: todo priority: high +state_hub_task_id: "b6c0c54f-a961-412b-b2a8-c39e7a6d48c1" ``` Add `POST /tenants/{tenant_id}/grouping` — deliberately **not** an addition to @@ -168,6 +211,7 @@ audited, with the reserved-identifier and retired-tenant cases tested. id: TEN-WP-0010-T04 status: todo priority: high +state_hub_task_id: "807c34ab-2c04-4276-a872-e89b5b064967" ``` Two places where grouping is load-bearing beyond the ceiling table. @@ -199,6 +243,7 @@ backends. id: TEN-WP-0010-T05 status: todo priority: medium +state_hub_task_id: "072cddc6-762a-4efc-8176-31176b9fded6" ``` Contract documentation, then the handoff: `flex-auth` needs