Repository navigation
refactor(core, plugin-auth, plugin-security, service-settings): one definition each for the admin_full_access anchor rule and the organization-reach rule, exported from core security - #25352
Conversation
…r the anchor predicate and the organization-reach rule (WIP) Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
…each rules Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
…t the reach rule Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
…-design difference at its call site Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
…chor rule Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
…tions Claude-Session: https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 4 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 48 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 5f3f70cf433a4880b14993344b190dde6d0c976b && git checkout 5f3f70cf433a4880b14993344b190dde6d0c976b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 54df640b388c66153ba1e52c9ccc0082293358fa 264c7ef59f163b75c02659b09e719298c059b0e8 && git checkout -B drift-repro 54df640b388c66153ba1e52c9ccc0082293358fa && git merge --no-ff 264c7ef59f163b75c02659b09e719298c059b0e8
node scripts/docs-audit/affected-docs.mjs --json 54df640b388c66153ba1e52c9ccc0082293358fa
|
Contract reviewServed-tier: Seat read on the declaration face. The PR declares ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
|
Seat ACCEPT · epic PM Seat check
|
Fixes #25315
Part of #15212. This card carries the #15212 ledger items 6348725929 and 6353870843. Claim: 6354363886, amended in 6354903470 to add
bootstrap-platform-admin.ts.Measurement first
The measurement is in comment 6354428826 on #25315. The seat's ruling on it was: fold; keep R-1 and R-2; keep A-1.
Anchor rule (ADR-0131 D5): one rule, spelled three times.
grantAnchorsPlatformStanding;anchorOwnerTest;isAnchorHumanHolder. This third copy was found during the measurement.organization_id.organization_idraw (===), and reads noorganizationId.'', so no differing input reaches an answer. The rule takes the organization already normalized, and each reader keeps its own normalizer.Reach rule (ADR-0131 D8/D9): one rule over different facts.
SettingsService.unowned; the service propagates it.What changes
New in core security (
packages/core/src/security/):platform-standing-anchor.ts:organizationAnchorsPlatformStanding(grantOrganizationId, { walled, defaultOrganizationId }).organization-reach.ts:resolveOrganizationReach({ callerOrganizationId, wallStands, deriveOrganization }), which asks each fact lazily and in order;organizationReachAdmits,organizationReachRowOwnerandorganizationIdOf;UNOWNED_ORGANIZATION_REACHand theOrganizationReachtype.Readers now calling them:
resolve-authz-context.ts: §6b's anchor, andlocalizationFallbackReachplus its row filter.settingRowOrganizationOfis removed.last-admin-guard.ts:anchorOwnerTest, over the simulated Default Organization.bootstrap-platform-admin.ts:findPlatformAdminGrantHoldertakes the anchor facts.isAnchorHumanHoldercalls the rule and keeps its system-user exclusion.settings-service.ts:organizationReachOf,withinReach,loadScopedRowsand the write owner. The localOrganizationReachtype andcallerOrganizationIdOfare removed.Grep: no restatement of either rule is left. The ownership checks that remain in plugin-security's
suggested-audience-bindings.tsandorganization-ownership-plan.tsdecide record ownership and attribution, not standing or reach.The memoised
sys_organizationprobe was skipped. The fallback is bounded already, and a memo would add a cache keyed on an outage path.Clause-②: yes (widening)
Metadata-protocol: none
The diff adds core exports and narrows no accept set. No behaviour change: every existing pin is unchanged and green.
Tests and ablations
New tests:
platform-standing-anchor.test.ts: 12 rows over posture, Default Organization and grant owner.organization-reach.test.ts: 26 cases. They cover caller × wall × D9 decision with the facts each row asks, row-owner and admits tables, and throw propagation.resolve-localization-fallback-row-reach.pin.test.ts: a filter-dropping engine with the NULL row stored first;settings-organization-reach-memory.pin.test.ts: the in-memory store, with no query to filter.Ablations. Each mutation ran through
scripts/ablation-replace.mjswith an anchor that must hit. Each was restored to the HEAD blob withgit diff HEADempty. For the anchor ablation, core was rebuilt andablation-dist-preflightproved the marker leftdist/and came back.derivedread asunownedProof (head
264c7ef59f, which is40ac96aamerged withorigin/main54df640b38)src/security/: 1080 pass; plus the new row-reach pin, 3/3.pnpm build: 76 / 76.node scripts/pm/dispatch-gates.mjs --commands: 74 derived, each exit code captured before any pipe. All 74 exit 0 at40ac96aa, aftergit fetch --unshallowand a full build. The re-run on the merged head is reported in the os-dev-report on refactor(core, plugin-auth, service-settings): one definition each for the admin_full_access anchor predicate and the organization-reach rule, exported from core security and called by every reader that spells them today #25315.check-governed-merges --branch: NOT governed, 0 of 12 paths. 814 changed lines (+694 / −120), not Tier H/S.upgrade-18x-harness.dogfood.test.ts): 16 / 16. That covers thefixture-18.0ceremony leg and thefixture-18.0.0GA leg.os serveof the showcase on an empty store undersingle:me/localization200 (UTC/en-US);me/permissions: the first user holdsplatform_admin/admin_full_access, so the promotion and the anchor work end to end.os serve(NODE_ENV=production,OS_PLATFORM_OWNER_EMAIL, invite-only, a 32-byteOS_SECRET_KEY), on an empty store:isolatedandgroup: each ready in 8 s, health 200, sign-up 200, sign-in 200,me/localization200. The configured owner holdsplatform_admin.isolated:PUT /api/settings/localizationwithAsia/Tokyoanswered 200, and the nextme/localizationread answeredAsia/Tokyo.@objectstack/organizationswas added to the showcase locally.package.jsonand the lockfile were restored afterwards, and none of it is in the diff.Acceptance notes
origin/main(54df640b38, which brings plugin-security, plugin-sharing: at boot, the administrator is told when an upgrade renamed, removed or collided with an access choice (#24446 U1) #25311) was merged in at the seat's request as264c7ef59f, a clean merge with no overlap. After it, I rebuilt plugin-security, plugin-sharing, runtime and cli. plugin-security re-ran 4442 pass / 45 skipped, and its typecheck exited 0. R1, R4 and the harness were re-measured on this head; the figures above are this head's.[security] audience-binding suggestion sync failed (non-fatal)appears once at boot. It comes fromsuggested-audience-bindings.ts, which this diff does not touch. Noted, not filed.🤖 Generated with Claude Code
https://claude.ai/code/session_01W6m1VLhu6og8R1ACfCKJ6D