Skip to content

docs(adr): anchor the default-active-org session hook to ADR-0093 D9 (#8474) - #8529

Open
qq9340100 wants to merge 1 commit into
mainfrom
claude/issue-8474-defaultactiveorg-anchor
Open

docs(adr): anchor the default-active-org session hook to ADR-0093 D9 (#8474)#8529
qq9340100 wants to merge 1 commit into
mainfrom
claude/issue-8474-defaultactiveorg-anchor

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Part of #8474

What was wrong

session.create.beforedefaultActiveOrg (the hook that stamps a session's
activeOrganizationId from the caller's sys_member row) was cited across
plugin-auth, plugin-sharing and the dogfood suite as "ADR-0081 D1".

Two independent facts make that citation unusable:

  • docs/adr/0081-trusted-react-page-tier.md is the trusted kind:'react' page
    tier. It says nothing about organizations.
  • It has no D-numbered decisions at all — its Decision section is numbered
    1–4. So "D1" names nothing even within the record.

pnpm check:adr-anchors cannot catch this: it verifies a cited ADR exists,
and 0081 does. A reader following the citation lands on a real, accepted,
plausible-looking record with no signal they are in the wrong document.

Where the decision actually belongs

The card offered two options; the answer turned out to be a refinement of the
second — the decision was never recorded in this repo's ADR series, and
ADR-0093 already knew why. Its Relates to line says the label is inherited
from a decision record that "predates this repo's ADR series". That pre-repo
number now collides with this repo's ADR-0081.

Three independent signals put the record at ADR-0093:

  1. scripts/adr-anchors/packages__plugins__plugin-auth__src__auth-manager.ts.json
    already lists ADR-0093 (not 0081) as that file's governing record, and its
    invariant text already describes the session.create.before seam.
  2. ADR-0123 (accepted today, out of [Decision] What is an authenticated session with NO active organization? Three subsystems answered it three contradictory ways in one shift (fail-open / fail-closed / permanently-invisible ledger rows) #8247) already anchors the hook to ADR-0093
    twice — including the explicit composeDatabaseHooksdefaultActiveOrg
    pointer.
  3. The stamp is a read of the invariant ADR-0093 D1 states and D2 owns: it can
    only resolve an organization when a sys_member row exists, and which row
    exists is decided entirely by D1's policy and D2's reconciler.

But ADR-0093's existing D1/D2 do not decide the stamp — D1 is the membership
invariant, D2 is the user.create.after reconciler; the hook appears only as
background in Context. Re-pointing the sites at "ADR-0093 D2" would have swapped
one wrong-but-existing anchor for another — the same defect class as #8386.

So per triage's ruling, this records the shipped behaviour as ADR-0093 D9
and points every site there.

Changes

Behaviour is unchanged. The TypeScript diff is provably comment-only — zero
non-comment lines changed.

Why one PR and not the two-PR split

The split shape (#8290/#8291, #8384/#8385, #8437/#8440) needs the two halves to
be independent. Here they are not: the code half's new citations point at
ADR-0093 D9, which only exists in the ADR half. Landing the code half first
would re-point six sites at a decision number that does not exist — reproducing
exactly the defect this card exists to close, with a different number. So this is
a single maintainer-merged draft.

Deliberately NOT in this PR

Re-deriving the census found 34 ADR-0081 D1 sites carrying four distinct
claims
. Only claim A — the active-org stamp, this card's subject — is fixed
here. The other three claims (the ensureDefaultOrganization bootstrap, the org
capability gate, the posture/entitlement wall), plus the separate ADR-0081 D2
family, are a different set of decisions sharing the same inherited label. They
are filed separately and are not addressed here; #8474 covers claim A only.

Historical records were left untouched per the "keep history as history" rule
(#8291 / #8385 / #8440): two .changeset/*.md files and four published
CHANGELOG.md files carry the old label and are not rewritten.

Verification

  • pnpm check:adr-anchors — OK. 121 decision numbers, 23726 citations across
    4016 files resolve; D9 accepted as a decision number.
  • node scripts/check-adr-links.mjs — OK, 540 link destinations resolve.
  • pnpm check:nul-bytes · check:docs-audit-scope · check:test-source-alias ·
    check:type-source-resolution · check:i18n — all OK.
  • node scripts/check-adr-merge-approval.mjs — HTTP 401 locally (no token);
    CI judges it.
  • vitest run src/auth-manager.test.ts -t "active-org" — 9 passed.

⚠️ Maintainer-merged: docs/adr/** is in the diff (Prime Directive #14). No
auto-merge, no enqueue.


Generated by Claude Code

…8474)

`session.create.before` -> `defaultActiveOrg` was cited across plugin-auth,
plugin-sharing and the dogfood suite as "ADR-0081 D1". ADR-0081 in this repo
is the trusted `kind:'react'` page tier and has no D-numbered decisions at
all, so the citation resolved to a real, accepted, plausible-looking record
that says nothing about active organizations.

Record the shipped behaviour as ADR-0093 D9 (seam, selection, only-when-absent,
best-effort, opt-out, and the #8245/#8247 ordering) and re-point every
active-org-stamp citation at it. ADR-0093 already owns `sys_member` and the
membership lifecycle the stamp reads, ADR-0123 already anchors the hook there,
and `scripts/adr-anchors/...auth-manager.ts.json` already lists ADR-0093 as
that file's governing record.

Behaviour is unchanged — comments and prose only.

Part of #8474

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jqe56GnYFddggeAyfkZFVz
@vercel

vercel Bot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 13, 2026 5:30pm

Request Review

@qq9340100 qq9340100 added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/s labels Aug 13, 2026 — with Claude
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/plugin-auth, @objectstack/plugin-sharing.

13 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/deployment/cli.mdx (via @objectstack/plugin-auth)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/plugin-auth)
  • content/docs/kernel/contracts/cache-service.mdx (via @objectstack/plugin-auth)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/plugin-sharing)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/plugin-sharing)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/plugin-auth, @objectstack/plugin-sharing)
  • content/docs/permissions/authentication.mdx (via @objectstack/plugin-auth)
  • content/docs/permissions/authorization.mdx (via packages/plugins/plugin-sharing)
  • content/docs/permissions/permissions-matrix.mdx (via packages/plugins/plugin-sharing)
  • content/docs/permissions/sso.mdx (via @objectstack/plugin-auth)
  • content/docs/plugins/index.mdx (via @objectstack/plugin-auth)
  • content/docs/plugins/packages.mdx (via @objectstack/plugin-auth, @objectstack/plugin-sharing)
  • content/docs/protocol/objectql/security.mdx (via packages/plugins/plugin-sharing)

2 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/implementation-status.mdx (via @objectstack/plugin-auth, @objectstack/plugin-sharing)
  • content/docs/releases/v9.mdx (via @objectstack/plugin-auth)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Copy link
Copy Markdown
Collaborator Author

The red ADR maintainer approval is by design — no fix is coming, and none is needed

Job log read rather than inferred (check-adr-merge-approval, run 31726034790):

❌  This change touches docs/adr/ and this PR is not in a mergeable state under the ADR rules.
      • docs/adr/0093-tenancy-mode-and-membership-lifecycle.md
    No state-setting review (APPROVED / CHANGES_REQUESTED / DISMISSED) has been submitted at all.
    Fix: anyone with review rights on this repo approves the PR …

That is the gate working exactly as intended: the PR touches docs/adr/**, so it is unmergeable until a human approves. Nothing about the diff is wrong, and pushing another commit would not change it. This check stays red until the maintainer acts, and that is the desired state.

⚠️ Recording something the log makes explicit, because it is the hazard #8012 documented. The gate now says, in its own output, "This gate does NOT check who approved" — the #8161 relaxation (maintainer, 2026-08-12: 「门禁改成只要求「APPROVED review 存在」」/「不要指定具体的人」). So this seat could satisfy this gate right now by submitting an approving review, and is deliberately not doing so. The standing ruling is 「adr 只能由维护者自己确认,人工合并」 — confirming is precisely what an approving review is, and that half is no longer enforced mechanically. It is enforced by the seat declining to use access it holds, which is the condition #8012 was filed about. Stated out loud rather than left as a silent non-action.

⛔ Nothing is armed on this PR: no auto-merge, not enqueued. (Per PR #8302, landed today, arming auto-merge here would itself turn this gate red regardless of approval.)

Docs Drift Check — advisory, and answered

The bot flags 13 hand-written docs via @objectstack/plugin-auth / @objectstack/plugin-sharing. No re-verification is needed: the TypeScript diff is provably comment-only — zero non-comment lines changed — so no described behaviour moved. The drift check fires on package-level change detection, which cannot see that distinction. The two release-owned pages it lists are read-only and were not touched.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Ready for the maintainer to merge. Flipped out of draft by the domain:devx PM seat (#6023) at ~18:0xZ — nothing else changed, head SHA is unchanged at 8b7b5e7.

Why the flip, stated explicitly so it is not mistaken for a step toward AI-merging this:

This PR was parked as a draft "awaiting a human merge". That was a mistake on this seat's part — GitHub will not merge a draft PR for anyone, the maintainer included. Parking an ADR PR as draft does not wait for a human, it blocks the human. Flipping to ready-for-review is not merging, not enqueueing, and not arming auto-merge; it is the minimum required for the maintainer to be able to act.

What this seat has deliberately not done, and will not do:

On merge, #8474 needs closing by hand — this PR says Part of, so nothing closes automatically. Per the 17:5xZ ruling: claim A (the active-org stamp) is the whole of #8474; the remaining three claims and the ADR-0081 D2 family are residue and belong to #8531.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant