You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Four server-side readers derive platform authority from the NAME in ExecutionContext.positions — same species as #15948's blocked escalation, and already reachable on main #15981
⚠️These are pre-existing and reachable on main today. They were not introduced by PR #15948 and are not fixed by it — the resolver section that populates ExecutionContext.positions is untouched by that PR. ⇒ Do not read this as fallout from that change; read it as the same defect, found while looking at that change.
Why this is the same species as a blocked escalation
PR #15948 was failed in Clause-② review for deriving isPlatformAdmin as an array-name read. The reason that was blocking, measured on the real pipeline: sys_user_position is apiEnabled and its names are unconstrained, so a tenant can mint an ADR-0057 D4 row spelling platform_admin. A plain org member holding such a row passed the /admin/* mount gate while the capability rung said false.
Core's own resolver states the rule, at resolve-authz-context.ts:1125-1129:
Read the RUNG — never positions.includes(...); an ADR-0057 D4 sys_user_position row may spell that very name.
⛔ That is a comment, not a gate. It did not stop the one PR #15948 nearly shipped, and it has not stopped these four.
⭐ ctx.posture is already carried on the same context for these sites to read instead, so the correct value is present at every one of them — this is a wrong read of available data, not missing data.
What the taker owes, in order
Drive each of the four, don't read them. For each: does a sys_user_position row spelling the built-in name actually change that site's decision? ⚠️ A site may be unreachable for other reasons, or may already be gated upstream — that would be a finding, not a failure, and it must be measured per site rather than assumed from the shape.
Pin each site with a mutated three-way-agreement test — the payload alias, the site's own gate, and the rung must agree with the D4 row present — and state each pin's population. ⭐ Round 1 of fix(plugin-auth)!: session payload positions[] is the security axis, not the better-auth role scalar #15948 got through the author's own check because a green pin (platform-admin-standing.consolidation.test.ts PIN 6) was cited as "the mechanical proof that the derivation agrees with both gates shape for shape" while having no case where a D4 row spells the built-in name.
Scope note
⚠️Four packages, and this seat is domain:services.runtime/src/domains/activation-gate.ts may belong to another lane; split if so. ⛔ Do not let a lane boundary leave one of the four unfixed while the other three land — a single remaining name-read reopens the hole.
Dedup
Checked by the reviewer that found them: no existing card matches. The nearest, #11978, is a different census.
The four sites
Each derives platform-admin authority from a name in
ExecutionContext.positionsrather than from the capability rung:packages/plugins/plugin-sharing/src/sharing-rule-service.ts:254packages/plugins/plugin-approvals/src/approval-service.ts:976packages/runtime/src/domains/activation-gate.ts:149packages/plugins/plugin-security/src/explain-engine.ts:117maintoday. They were not introduced by PR #15948 and are not fixed by it — the resolver section that populatesExecutionContext.positionsis untouched by that PR. ⇒ Do not read this as fallout from that change; read it as the same defect, found while looking at that change.Why this is the same species as a blocked escalation
PR #15948 was failed in Clause-② review for deriving
isPlatformAdminas an array-name read. The reason that was blocking, measured on the real pipeline:sys_user_positionisapiEnabledand its names are unconstrained, so a tenant can mint an ADR-0057 D4 row spellingplatform_admin. A plain org member holding such a row passed the/admin/*mount gate while the capability rung saidfalse.Core's own resolver states the rule, at
resolve-authz-context.ts:1125-1129:⛔ That is a comment, not a gate. It did not stop the one PR #15948 nearly shipped, and it has not stopped these four.
⭐
ctx.postureis already carried on the same context for these sites to read instead, so the correct value is present at every one of them — this is a wrong read of available data, not missing data.What the taker owes, in order
sys_user_positionrow spelling the built-in name actually change that site's decision?positions[]is the security axis, not the better-auth role scalar #15948's instance was written through the constantBUILTIN_IDENTITY_PLATFORM_ADMIN, so a grep for the string literal returned zero on both the broken and the fixed head. I made exactly that mistake; a failing control is what caught it. Read the assignment, or drive it.positions[]is the security axis, not the better-auth role scalar #15948 landed:grants.posture === 'PLATFORM_ADMIN', which is byte-for-byte whathasPlatformAdminStandingreturns.positions[]is the security axis, not the better-auth role scalar #15948 got through the author's own check because a green pin (platform-admin-standing.consolidation.test.tsPIN 6) was cited as "the mechanical proof that the derivation agrees with both gates shape for shape" while having no case where a D4 row spells the built-in name.Scope note
domain:services.runtime/src/domains/activation-gate.tsmay belong to another lane; split if so. ⛔ Do not let a lane boundary leave one of the four unfixed while the other three land — a single remaining name-read reopens the hole.Dedup
Checked by the reviewer that found them: no existing card matches. The nearest, #11978, is a different census.
Related
sys_user_positionrow spelling any built-in identity name — PR #15948 closed every reader, nothing stops the row #15972 — the class at its source: nothing stops a tenant minting the colliding row in the first place. These four are readers; that card is about the write path, and closing it would make readers like these harmless rather than merely correct.positions[]is the security axis, not the better-auth role scalar #15948 — the instance that surfaced the rule, the ruling that made it live, and the three-way-agreement pin shape to copy.'admin' in current_user.positions收敛选项,而admin从来不在服务端的 positions 轴上(membershipadmin被映射成org_admin) #15943 — the same confusion in the opposite direction, in a showcase object.