Repository navigation
docs(comments): retire the present-tense platform-admin elevation gate at the sites #13903 scoped - #14049
Conversation
…sites #13903 scoped Comment-only. The #11663 platform-admin re-anchor (leg L4) retired the walled platform-admin elevation gate: `bootstrapPlatformAdmin` writes no grant row under a walled posture and elevates nobody, it reports. Standing is derived per request at `resolve-authz-context.ts` §6b-config. Each site is corrected on its own reading, not by a sweep: two named a mechanism that no longer runs, one was stale only in its NAME (the reasoning it carries is still correct and survives verbatim in substance), and the two already-past-tense sites in `platform-admin-service.ts` are deliberately untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZC5rNQj3WEet5HAmmAkMs
…evation-gate-present-tense
📓 Docs Drift CheckThis PR changes 3 package(s): 4 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 — 32 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 7a336e4e4f4961318cbaa234dd5e75e3ed4fc6da && git checkout 7a336e4e4f4961318cbaa234dd5e75e3ed4fc6da
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 836a29c27aa9dbac27cc643106e5b2bf68cc96c1 312a60d221e7e7e47221c0cd7ffd75bd451f8c03 && git checkout -B drift-repro 836a29c27aa9dbac27cc643106e5b2bf68cc96c1 && git merge --no-ff 312a60d221e7e7e47221c0cd7ffd75bd451f8c03
node scripts/docs-audit/affected-docs.mjs --json 836a29c27aa9dbac27cc643106e5b2bf68cc96c1
|
Part of #13903 — deliberately not a closing keyword. Six of the card's seven rows are complete; the seventh is complete except for one listed line that turns out to be an
it()title rather than a comment, which this PR's tier cannot take. See "The one row left half-taken" below. The PM re-grades.Comment-only. Zero behaviour change. The #11663 platform-admin re-anchor (legs L2 and L4, both landed) retired the walled platform-admin elevation gate: under a walled posture
bootstrapPlatformAdminwrites no grant row and elevates nobody — it reports. Standing is derived per request atresolve-authz-context.ts§6b-config, from a config-anchored verified email or the legacy unscoped grant row.Premise re-verified against today's
origin/main, not the card's transcriptionThe card measured at
46b53a25b; this branch is cut from9b18c0475. Every quoted line was re-read in the tree before editing and every one is still there, at line numbers that moved by at most a few. Two premise details did not survive, and both are recorded rather than papered over:platform-admin.ts:287is stale only in its NAME, but the supporting detail is stale too.bootstrap-platform-admin.tsno longer emitswalled_owner_not_registered/walled_owner_not_verified. Its walled arm returnsreason: 'walled_owner_email_undeclared'or'walled_config_derived'(grep -n "reason: '"on that file lists exactly seven reasons and neither of those two is among them;walled-bootstrap-stops-granting.mdrecords the replacement, andbootstrap-platform-admin-walled-owner.test.ts:161says "formerlywalled_owner_not_registered"). The reasoning survives and is kept, as the card requires: the two halves are still separate answers, now as theregisteredandverifiedfields ofPlatformAdminStandingEntry, which is what lets the boot log print "not registered yet" apart from "registered, NOT verified". The corrected comment names that, and names the retired pair as its ancestor.env.ts:169is now:165-175and reads "the elevation refusal in plugin-security'sbootstrapPlatformAdmin". What that site actually holds today is the fail-closed backstop for an undeclared or refused config (:424) plus the config-derived standing log (:457) — neither is an elevation refusal.The seven rows, one at a time
The card filed itself to prevent a global search-and-replace, so each row got its own reading.
packages/types/src/env.ts(docblock over the exportedPLATFORM_OWNER_EMAIL_ENV, ships in@objectstack/types'.d.ts) — wrong about the mechanism. The parenthetical now names what those two message sites really are, and a⚠️paragraph states the retirement and where standing comes from instead.packages/core/src/security/platform-admin.ts:117(declaredSpellings) — the referent moved, not the fact. The two-spellingsys_userlookup is real and lives inresolvePlatformAdminStanding(plugin-security/platform-admin-service.ts, verified by reading it: it queriesnew Set([email, declaredSpelling])and then matches bynormalizePlatformAdminEmail). The comment now names that function and says it inherited the discipline from the retired gate.packages/core/src/security/platform-admin.ts:287—registered/verifiedas independent per-entry fields, and the operator log that depends on them), with the retired reason-code pair named as history.packages/plugins/plugin-security/src/platform-owner-wall-bypass.ts:37-39— "the gate must elevate" described an action nothing performs. The third site is now the derivation (resolve-authz-context.ts§6b-config, throughmatchesConfiguredPlatformAdmin), and the MUST-agree requirement is restated unchanged. This also removes a self-contradiction::10-14of the same docblock already said the elevation twin is retired.packages/plugins/plugin-security/src/security-plugin.ts:5822— "the elevation gate's twin" was the twin of a retired thing. Now: the shared predicate inplatform-owner-wall-bypass.ts, extracted as that twin, whose opposite number since the re-anchor is the per-request derivation.packages/plugins/plugin-auth/src/last-admin-guard.test.ts:1613— "un-makes every platform admin in one write" is true for the GRANT anchor only. Corrected the way docs(comments): correct four docblock sites describing the retired platform-admin elevation gate #13907 corrected the same sentence in the source file, and it now points atlast-admin-guard.re-pricing.test.ts, which pins both directions. The added sentence also says why this block's refusals are still live: the file declares no owner emails (git grep OS_PLATFORM_OWNER_EMAILin it returns only the new comment line), so the grant anchor is the whole population here.packages/plugins/plugin-auth/src/walled-owner-operator-stamp.test.ts— seven of the eight listed lines. The three-layer docblock now names the derivation rather than the gate, and carries an explicit retirement note quoting the implementation file's own[#11973]parenthetical — that file already said this and only its test had not caught up. The:91note now states today's consequence (born unverified, so the per-request derivation resolves it non-admin and the boot log reports "registered, NOT verified"), and the two inline comments at:395/:443follow.The reverse control the card named
packages/plugins/plugin-security/src/platform-admin-service.ts:21("the retired elevation gate") and:99("the elevation gate used") are already correct and are the card's control: a correct edit does not touch them.The file is not in the diff at all. Same for
security-plugin.ts:6351-6367, the fenced face of #13722: the only hunk in that file is@@ -5822,2 +5822,5 @@.The one row left half-taken, and why
Row 7 lists eight lines. Line 257 (now
:270) is not a comment:A test title is a string literal. It survives
removeComments, so editing it breaks this PR's own acceptance criterion (non-comment diff empty) and theClause-②: nograde that rests on "the whole diff is comments". The corroboration is in this PR's own measurement run: the identical comment filter applied to an unrelated real code commit (c54d4d3d7) left 279 non-comment lines, and the first of them is anit(...)title rename.So the line is left untouched, the docblock above it says so in terms, and the title family is filed as #14046 together with two comment sites the card's table did not scope.
Zero-behaviour-change measurements
All taken at head
312a60d22. Every exit code captured before any pipe.Non-comment diff is empty, measured rather than asserted: each of the six files, before and after, run through
ts.transpileModulewithremoveComments: true.diff -uis 0 lines for all six, and the sha256 of the stripped output is unchanged in every case:Every zero above is a reading, with a same-shaped control that comes back non-zero:
diff -uover the source pairs of the same six files: 22, 42, 20, 16, 26 and 77 lines. So a zero on the stripped pair is a measurement, not a blind spot.env.tscarries 3throwin source and 1 in the stripped output;security-plugin.ts47 and 35. The stripped text is demonstrably not the source.A cruder second reading agrees. Over
git diff -U0of the six paths: 113 changed lines, and filtering out every line whose content begins with a JSDoc or//marker leaves 0. Control for that filter: the same pipeline over an unrelated real code commit (git show -U0 c54d4d3d7 -- '*.ts') reports 507 changed lines and 279 non-comment residue.throwcensus, both directions — counted with\bthrow\bover source and over the comment-stripped output:packages/types/src/env.tspackages/core/src/security/platform-admin.tspackages/plugins/plugin-security/src/platform-owner-wall-bypass.tspackages/plugins/plugin-security/src/security-plugin.tspackages/plugins/plugin-auth/src/last-admin-guard.test.tspackages/plugins/plugin-auth/src/walled-owner-operator-stamp.test.tsCensus of the dead premise,
git grep -n -i 'elevation gate\|elevation refusal' -- packages, merge base9b18c0475to head312a60d22: 20 hits to 14. All fourteen survivors were read: ten are correct (retired / past tense / the corrections this PR and #13907 wrote) and four are #14046's subject.Control-byte self-scan over the six files:
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'matches nothing (exit 1). Control: the same grep over a file holding one control byte matches (exit 0), so the clean result is a reading.Gates
Re-derived from the actual diff, not from the dispatch list:
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackat312a60d22— 6 paths, 24 path-matched families plus 7 more from three convention triggers (edits a test file; edits a file in a package owning ani18n-extract.config.ts; carries an ADR-0112 code). Both output sections were read whole; the 31 distinct commands were harvested with--commandsso neither invocation spelling could be dropped. A first derivation printed a STALE TREE warning (scripts/import-prerequisite.mjshad moved onorigin/main);origin/mainwas merged in and the derivation re-run, which is the reading above.27 green.
check:cross-package-test-inputs,check:dispatcher-error-vocabulary,check:doc-authoring,check:engine-double-contract,check:i18n-stale-fill,check:kernel-hook-pairs,check:logger-receiver-detach,check:objectql-double-limit,check:page-declaration-shape,check:published-files,check:query-options-erasure,check:slot-lookup,check:test-source-alias,check:type-check-coverage,check:type-source-resolution,check:where-matcher,check-ci-filter-parity,check-comment-mask-adoption,check-cross-package-test-inputs,check-keyed-text-bounds,check-plugin-teardown-shape,check-shard-attestation,check-system-context-census,check-tenant-audit-census,check-undeclared-dep-imports,check-affected-docs,check-drift-comment.4 NOT MEASURED — neither a pass nor a red. Each quoted from the gate's own verdict line, not from a bare exit code:
check-test-completeness(exit 3) — "Nothing was measured: this gate exited before parsing a single summary line". It grades a savedturbo run testlog and none was named.check:dual-build-cjs-loads(exit 3) — "PREREQUISITE NOT MET — this gate reads built output, and some package has nodist/". Needs a whole-workspace build.check:type-check-debt(exit 3) — "--re-measurecannot run: 56 workspace dependenc(ies) of the ledgered packages have no built type entry point on disk". Same prerequisite. Its structural half,check:type-check-coverage, is green.check:i18n(exit 1, and the exit code is the trap here) — its own text is "PREREQUISITE NOT MET — the workspace CLI is not built ... Nothing was checked: no bundle was compared and no config was parsed". Read as NOT MEASURED on the verdict line, never as a red on the code. Its self-test passed.check:i18n-stale-fill, which needs no build, is green.All four want the same thing: a full workspace build. One was attempted under
scripts/pm/os-verify-lock.shand completed 31 of 32 turbo tasks in 7m34s before the container's ~10-minute foreground cap killed it (exit 143); three further lock acquisitions returnedVERDICT queue-timeout (exit 99)against a queue that held five other agents' builds and test runs throughout. Declared narrowing: these four are left to CI, which builds the workspace as a matter of course. Nothing in this diff can move them — the stripped output is byte-identical, so nodist/, no emitted bundle and no ledgered type count can differ.Beyond the derived family:
pnpm lint(eslint . --no-inline-config, the whole repo, the unconditional CI step) — green, 2m50s. Not narrowed.typecheckand the two touched test files are the other half of that same narrowing: they need@objectstack/plugin-authand@objectstack/plugin-securitybuilt, which is the lock turn that did not come. Recorded as NOT MEASURED rather than claimed. What a comment edit could plausibly break — an unterminated block comment taking the rest of a file with it — is measured twice over regardless: all six files were parsed byts.transpileModule(that is where the byte-identical stripped output comes from) and by ESLint in the green whole-repo run.Changeset:
skip-changeset, deliberatelyThe label is applied.
skip-changesetis this repo's exemption for a PR that publishes nothing, and a comments-only diff is on its closed list — the same judgment #13907 made for the same card family. The nuance is real and worth naming:packages/typesdocblocks do ship, in.d.ts. But what ships there is comment text, not type shape — no type, no exported name, no runtime, no contract moves, and the byte-identical stripped output above is exactly that statement. A changeset here would force a patch release of four packages whose CHANGELOG row could only say "an internal docblock now describes the current mechanism".Out of scope, filed
#14046 — four more sites naming the retired gate: two comment sites the card's table did not scope (
platform-admin.ts:19-21, the module header of a file this PR does edit elsewhere, andwalled-platform-bucket-diagnostic.test.ts:105), and the two test TITLES described above, one of which is #13903's own unfinished line. Filed unassigned and unlabelled for triage.Generated by Claude Code