docs(adr): anchor the multi-org entitlement to ADR-0105 D12 (#8531 claim D) - #9069
Conversation
…aim D) "Multi-organization operation is a commercial ENTITLEMENT" was cited in 15 places as "ADR-0081 D2". ADR-0081 in this repo is the trusted `kind:'react'` page tier; its Decision section is numbered 1-4, so "D2" names nothing in it. The label is inherited from a pre-repo decision record whose number now collides -- the same collision ADR-0093 D9 named for the "ADR-0081 D1" half. ADR-0105 D12 (Edition split, as amended 2026-07-27 by the founder ruling in #3570) already IS this decision: posture activation is entitled, both walled postures probe `@objectstack/organizations` to activate, and without it the tenancy service resolves to single + degraded. No anchor is invented here. The repo had already converged on that anchor everywhere else -- auth-plugin.ts, harness.posture-only.test.ts, harness.host-resolution.test.ts, the serve e2e test and content/docs/deployment/tenancy-modes.mdx all cite ADR-0105 D12 for this exact claim. These 15 were the stragglers. Re-points 13 sites to ADR-0105 D12. The 2 sites inside ADR-0105 itself cannot cite ADR-0105 D12 -- they ARE D12 -- and both sentences refer to the inherited prior line D12 affirms, so they are de-numbered descriptively instead, matching the language ADR-0093 already uses for the same pre-repo record. D12 gains a citation note (hygiene, explicitly not a decision) warning that the anchor is D12, not this ADR's own D2 (`accessible_org_ids`). Claims B and C of #8531 (`ensureDefaultOrganization` bootstrap, the org capability gate) are untouched -- all 22 `ADR-0081 D1` sites remain as they are, including those in files edited here. Both need a new owning record, which is a maintainer act. Behaviour unchanged: 10 comments, 3 documentation strings, no logic. Part of #8531 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011RB4waLuNbdruCo6X9oobm
📓 Docs Drift CheckThis PR changes 6 package(s): 116 hand-written doc(s) reference the affected code — list omitted above 15 rows. Re-derive: ⛔ 8 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.
|
|
CI note from the dispatching PM seat (#6023): the red This PR carries claim D of #8531, whose sites include Two things a reviewer should check first, both of which the dispatch made binding:
I will review the substance against Generated by Claude Code |
|
PM follow-up (#6023). Two things: a label repair, and my read on the two judgment calls a reviewer should look at. 1.
|
Part of #8531
Claim D only — "multi-organization operation is a commercial ENTITLEMENT",
carried in code as
ADR-0081 D2. Claims B and C are deliberately untouched;#8531 stays open for them.
The determination this PR rests on
The dispatch made this a fork: re-anchor only if ADR-0105 already owns the
decision; otherwise stop and report, because inventing an anchor is what
produced this whole defect family.
ADR-0105 D12 already owns it. D12 ("Edition split, per the cloud ADR-0016
iron rule") decides, verbatim:
That is claim D, stated as an accepted repo-local decision and settled by a
founder ruling (the 2026-07-27 D12 Amendment, #3570). No anchor is invented
here.
The evidence that made this unambiguous
The repo had already converged on
ADR-0105 D12for this exact claimeverywhere else. These cite it today and were never touched by this PR:
packages/plugins/plugin-auth/src/auth-plugin.ts:498—[ADR-0105 D12], posture entitlementpackages/verify/src/harness.posture-only.test.ts:114— "sogroupis entitled"packages/verify/src/harness.host-resolution.test.ts:40packages/cli/test/serve-organizations-host-resolution.e2e.test.ts:61content/docs/deployment/tenancy-modes.mdx:62— "multi-organization posture is a commercial capability (ADR-0105 D12)"Strongest signal: three of the files edited here already cited
ADR-0105 D12on other lines while the lines below still said
ADR-0081 D2— same file, sameclaim, two different anchors.
tenancy-service.ts(lines 57/75/120 vs 36/189),tenancy-posture.ts(line 85 vs 28),harness.ts(line 57 vs 448/496). These 15sites were stragglers, not a live disagreement.
Why the citation was unusable
docs/adr/0081-trusted-react-page-tier.mdis the trustedkind:'react'pagetier. Its Decision section is numbered 1-4, so "D2" names nothing in it. The
label is inherited from a decision record predating this repo's ADR series — the
same pre-repo record whose "ADR-0081 D1" half ADR-0093 D9 named and re-anchored
in #8529.
Changes — 15 sites
13 re-pointed to
ADR-0105 D12:tenancy-service.ts(x2),tenancy-service.test.ts,tenancy-posture.ts,serve.ts,dev-plugin.ts,harness.ts(x2),enterprise-organizations.ts(x3),rls-multitenant.dogfood.test.ts,authz-conformance.matrix.ts.2 inside ADR-0105 itself — handled differently, and this is the one judgment
call worth reviewing. The dispatch expected these to be re-pointed too, but
they cannot be: they are D12, and both sentences refer to the inherited
prior line that D12 affirms (
:334) and that the rejected proposal inverted(
:348). Re-pointing them atADR-0105 D12would be circular. So the phantomnumber is removed and the referent described instead — matching the language
ADR-0093 already uses for the same pre-repo record. I did not identify it as
any specific external record.
D12 also gains a short citation note, explicitly marked hygiene and not a
decision, recording that D12 is the anchor and warning that it is D12, not
this ADR's own D2 (
accessible_org_ids) — a one-character slip there wouldreproduce the exact defect being closed.
Deliberately NOT here
All 22
ADR-0081 D1sites (claims B and C) are untouched, including those infiles edited here —
harness.tskeeps 5,tenancy-service.test.ts'sneighbourhood is unchanged. Both need a new owning record established first,
which is a maintainer act.
CHANGELOG.md,.changeset/*.mdandcontent/docs/releases/**are untouched per "keep history as history".Re-derived census (the card's list was measured 2026-08-13)
Re-enumerated on
origin/main@c0525b2b9rather than copied:ADR-0081 D2)ADR-0081 D1)The card's header says 17, but its own enumerated list totals 15, and that
list matches current
mainfile-for-file. So 15 is the real number and the cardhas an internal arithmetic slip, not drift. Cross-check: #8529 measured 34 D1
sites and re-pointed 12, leaving 22 — exactly what is in the tree.
Verification — all at
73d96a8, the final commitBuild closure first (
turbo run build, 70 tasks, all green).pnpm check:adr-anchors— OK (121 decision numbers, 25782 citations across 3212 files)node scripts/check-adr-links.mjs— OK, 543 destinations resolvepnpm check:nul-bytes— OK, 5957 files, no raw control bytescheck:cross-package-test-inputs·check:spec-parsed-alias·check:test-source-alias·check:type-source-resolution·check:merge-driver— OKcheck:doc-formula-expressions·check:dev-prereqs— OK (both needed the full build)check:engine-double-contract(305 pinned) ·check:where-matcher(244 matchers, none new) ·check:query-options-erasure(none new) ·check:type-check-coverage— OKcheck:type-check-debt --re-measure— OK, 33 ledger entries, 1926 errors, none above its recorded numbervitest run src/tenancy-service.test.ts— 24 passedspec,plugin-auth,plugin-dev,cli,verify,dogfood— all Donecheck:adr-anchorsis green before AND after — and that proves nothingReverse-verified deliberately: I restored the phantom
ADR-0081 D2anchors tothree files and re-ran the gate. It returned byte-identical output —
OK (49 anchored file(s) … 121 decision number(s) … 25782 citation(s) across 3212 file(s) resolve).The gate verifies a cited ADR exists, and 0081 does. A wrong-but-existing
number sits in the blind spot between its two audits, and is worse than a
dangling reference: the reader lands on a real, accepted, plausible-looking
record with no signal they are in the wrong document. No gate in the repo can
catch this class — which is why this needed a human determination.
Changeset
None,
skip-changesetapplied. This releases nothing: 10 comments, ADRprose, and 3 documentation strings whose only change is which ADR number they
cite (
harness.ts'smultiTenant=truethrow,enterprise-organizations.ts'sprobe throw, and the
authz-conformance.matrix.tsnotefield). No logic, noAPI, no behaviour — verified by grep that nothing asserts on those strings. Same
call as #8529, which shipped comment-only edits to published
plugin-authandplugin-sharingsource under this label. Flagged explicitly so a reviewer whodisagrees can say so.
Merge path
docs/adr/**is in the diff (Prime Directive #14).Opened as a draft; no auto-merge, no merge queue. First line is
Part of,not a closing keyword, so #8531 survives for claims B and C.
Generated by Claude Code