Repository navigation
refactor(plugin-security)!: delete the permission-set projection, the seed-name lookup and the refusal sink (C3 stage 7a) - #23368
Conversation
…seed-name lookup and the refusal sink with the suites that pin only them (ADR-0131 D3, C3 stage 7a; held) Carried over from the C3 build-ahead onto main after stage 8. Stage 8 stopped registering the sys_permission_set row object, the permission mutation projector and the data-door write-through, so these modules have no live caller left: - permission-set-projection.ts, seed-name-lookup.ts and seed-refusal-sink.ts are deleted, with their index exports and the projection's ADR anchor; - tryFind becomes a private helper of the overlay reading, its one live caller, and the reading's logger option asks only for warn; - the security middleware loses the writesExecutedByDataDoor stand-down, which only the retired data door could arm; - the suites that pin only the deleted modules go, and the packaged-set lock's pins move onto the metadata door's lock gate. Held, not ready for review: permission-set-echo-package-owner.test.ts still imports the projection. It is the only pin of the owner-carrying echo, which lets a runtime package's default permission set keep its owner and record its everyone suggestion on an environment kernel; stage 8 unwired that behaviour with the projector. How that behaviour is carried is a decision owed before this deletion lands. The census, ledgers, liveness registry and the epic's zero-row acceptance are not done yet. Claude-Session: https://claude.ai/code/session_01287UbjvrigpWwNfGDmdwpS Co-authored-by: Claude <noreply@anthropic.com>
…ssue-22975-7a-recut # Conflicts: # content/docs/permissions/system-context.mdx # packages/plugins/plugin-security/src/permission-set-projection.ts # scripts/tenant-audit-census.mjs
…rs and liveness row follow the projector's deletion A CLI integration test pins the C3 epic's zero-row acceptance on both kernel shapes: on a fresh database, a package-door publish, a writable base's direct publish and a boot over the stored definitions leave no sys_permission_set row, counted from the file through the test's own connection; a control proves the counter sees a row a writer leaves. The tenant-audit census and its counts are regenerated with the census script, with the prose figures it holds to the census updated; the engine-double ledger is regenerated, and the two baselines drop the entries of the deleted suites. The liveness README's unbound permission-set-projection proof row retires with the invariant, and the uninstall dogfood header no longer describes a projector row. Claude-Session: https://claude.ai/code/session_01287UbjvrigpWwNfGDmdwpS Co-authored-by: Claude <noreply@anthropic.com>
…ssue-22975-7a-recut # Conflicts: # content/docs/permissions/tenant-audit-census.mdx # docs/audits/2026-08-tenant-audit-write-call-sites.counts.md
📓 Docs Drift CheckThis PR changes 2 package(s): 19 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 12 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 145 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 c9223036787f188bf64d25bddffd880644d17942 && git checkout c9223036787f188bf64d25bddffd880644d17942
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e4ec6ec1a5eff818d69e5bdf1ae031f37fec64bd 31262798277b1394e4be1401e6a6f5fad974f67c && git checkout -B drift-repro e4ec6ec1a5eff818d69e5bdf1ae031f37fec64bd && git merge --no-ff 31262798277b1394e4be1401e6a6f5fad974f67c
node scripts/docs-audit/affected-docs.mjs --json e4ec6ec1a5eff818d69e5bdf1ae031f37fec64bd
|
…ssue-22975-7a-recut
Contract reviewServed-tier: PR #23368 ( ① Derived judgmentsDead before deletion — holds. On The package entry — disposition present and right; level right. The entry loses 7 runtime exports ( The deletion clause — holds for the five deleted suites; two sub-cases of still-live code are left without a direct pin (noted, not blocking).
The zero-row acceptance — pinned; the ablation is a measurement on another tree, reported only in the body. The liveness registry — NOT retired. This is the blocking finding. The entry Q3 → B retires at 7a (seat review 6124054616: "the liveness registry's D's transitional text — removed; known-limitation item 3 is stated nowhere in the repo after this PR. Regenerated files — consistent with the diff, and CI-verified on the merge tree. Census: the three Published text the change makes false. Corrected here: The 维护者速读(草稿), statement by statement. True: the scope and size (28 files, +336 / −6,516; about 6,500 lines); the new integration test and its three legs on a fresh database; "stage 8 left the projector without a caller" (true of the code; the one live behaviour, the echo, is correctly attributed to #23308); "no behaviour change for a running deployment" (the stand-down removal is unreachable code, the three modules unwired); 11 exports removed, compile failure for a direct importer, a FROM → TO per name; whole-PR revert with no data migration; Tier H by line count; the seat-opinion part empty. Not true in the body outside the 速读: (1) "objectui pinned sibling … CI's Console Pin Gate covers it" — the Check-runs on the head (the gate verdicts). 41, all completed by 2026-10-14T02:56Z; none running. 36 success: the six ② Semver level
③ Boundary flags
Adopted by
Implemented-by: VERDICT: FAIL |
…ry entry retires with its README row; the lock's non-list registry answer keeps a pin The proof registry still carried the permission-set-projection HIGH_RISK_CLASSES entry, pointing at a dogfood file that no longer exists; only its README mirror row had been removed. The entry is removed, so the README matches its source. The classifier's refusal of a SchemaRegistry that answers with a non-list lost its only direct pin with the projection suite. It is re-pinned on the metadata door beside the throwing-registry case, and measured red with the branch ablated. The #23233 changeset no longer says the set keeps an admin sys_permission_set row: no row is written once the projector is gone. Claude-Session: https://claude.ai/code/session_01287UbjvrigpWwNfGDmdwpS Co-authored-by: Claude <noreply@anthropic.com>
…ssue-22975-7a-recut
Contract reviewServed-tier: Delta review of PR #23368 ( The delta on the PR's own surface is the round commit alone. Restricted to the PR's 30 files, ① Derived judgments1. Item 1, the liveness registry — retired, with nothing dangling. 2. Item 6, the non-list registry pin — re-homed, and it would go red with the branch gone. 3. Item 4 in-repo, the pending-note correction — exact, true, red by design, advisory. The diff of 4. Item 2 and the body — stated as asked; one stale figure. The body now reads "objectui pinned sibling: NOT MEASURED. It is not checked out here, and the Console Pin Gate runs only in the full battery (#22998), so it is skipped on a PR", and lists the 11 retired names and that no package here imports them; 5. What the previous record judged right still holds at this head.
6. The round's os-dev-report is on the head. 6161002759 names 7. Check-runs on the head. 48, all completed by 2026-10-14T05:05Z (the last, the ② Semver levelUnchanged and right. ③ Boundary flags
Adopted by
Implemented-by: VERDICT: PASS |
维护者速读 · PR #23368(7a,C3 第 7 阶段的前半)·
|
…ssue-22975-7a-recut # Conflicts: # content/docs/permissions/tenant-audit-census.mdx # docs/audits/2026-08-tenant-audit-write-call-sites.counts.md
Refs #22975
Clause-②: no (narrowing)
C3 (#15204) stage 7a. It deletes the permission-set projection, the seed-name lookup and the seed refusal sink, with the suites that pin only them. Stage 8 left all three without a live caller, and #23308 (PR #23334) moved the one live behaviour the projection still carried, the environment kernel's security-catalog echo, into its own module. It is the first half of the stage-7 pair; 7b (#23302) has landed, and 8-post follows. #22975 stays open.
维护者速读(草稿)
改了什么
删除权限集「投影器」及其两个配套模块(种子名称查找、种子拒绝汇报),以及只测试它们的旧测试,共约 6,500 行(30 个文件,+350 / −6,539)。新增一个集成测试,证明「发布权限集不会再写出任何
sys_permission_set行」。同时撤下 liveness 登记里指向已删文件的那一条,并为仍在使用的「权限集锁」补回一个被旧测试顺带覆盖的用例。为什么改
投影器原本把每个权限集定义复制成一行
sys_permission_set记录。阶段 8 已经下线了这张表,投影器从此没有调用方,只是死代码。它身上唯一还在用的功能(环境内核上让安全目录找到元数据门写入的权限集和岗位)已由 #23308 搬到独立模块。所以现在可以干净地删掉。风险与代价(含回滚)
@objectstack/plugin-security去掉了 11 个导出(函数与类型)。如有人直接导入它们,升级时会编译失败。changeset 逐个写明了替代方案(大多是「直接删掉调用」)。席位意见
你要做的
用
os-zhuang或hotlong批准本 PR(Tier H,按行数超过 3,000)。批准同时确认:本 PR 改写了 #23258 尚未发布的更新说明.changeset/23233-permission-echo-names-runtime-package.md里的一句(「仍是managed_by: 'admin'的sys_permission_set行」改为「不再写任何sys_permission_set行」),因此Check Changeset按设计保持红(它不在合并队列的五个必查项里)。What this changes
Deleted modules:
permission-set-projection.ts(the ADR-0094 projector, its data-door write-through and its boot reconcile),seed-name-lookup.tsandseed-refusal-sink.ts, with their exports from the package entry and the projection's ADR-anchor JSON.Deleted suites, each pinning only deleted code:
permission-set-projection.test.tspermission-set-projection-heal-by-id.test.tspackaged-permission-set-restore-leg.test.tspermission-set-duplicate-name-refusal.test.tsseed-name-lookup-degradation-audible.test.tsThe plugin-security: permission sets an org owns (or that live in a writable runtime package) are reported and enforced as "locked by the code package" — the lock reads the package id without the row's provenance #21789 echo-stamp cases of the old projection suite are not kept here: they already live in
security-catalog-echo.test.ts(fix(plugin-security): an environment kernel's security catalog serves permission sets and positions saved through the metadata door again (S8 regression) #23308), which pins the echo where it now lives.Re-pinned:
packaged-permission-set-lock.test.tsmoves onto the metadata door's lock gate. That includes the classifier's refusal of a SchemaRegistry that answers with a non-list (packaged-permission-set-lock.ts, theArray.isArraybranch). The old pin 5 was its only direct pin; it now sits beside the throwing-registry case, and it measured red with the branch ablated.Re-homed:
tryFindbecomes a private helper ofpackaged-permission-set-overlay-detection.ts, its one live caller, and that reading's logger option asks only forwarn.The security middleware loses the
writesExecutedByDataDoorstand-down, which only the retired data door could arm.The epic's zero-row acceptance (6129253247):
packages/cli/test/permission-set-zero-row.integration.test.ts. On a fresh SQLite file, on both the host kernel and an environment kernel, it runs:publishPackageDrafts);The rows are counted from the file through the test's own connection, so a table that does not exist counts as zero. A control writes one row and reads it back as one.
Liveness (Q3 → B): the
permission-set-projectionHIGH_RISK_CLASSESentry inpackages/spec/scripts/liveness/proof-registry.mtsis removed, together with its README mirror row. ItsproofRefpointed at a dogfood file that no longer exists, and no@prooftag carries it. Thepermission.tabPermissionsentry no longer cites the deleted file.A pending changeset this PR makes false:
.changeset/23233-permission-echo-names-runtime-package.mdno longer says the set keeps amanaged_by: 'admin'row. No row is written once the projector is gone.D's transitional text: the header of
package-uninstall-revokes-named-grants.dogfood.test.tsno longer describes a projector row. Theauthorization.mdxsentences were already removed onmainby docs(permissions): the hand-written pages describe the security catalog main serves, not the four retired row objects #23322, so nothing is left to change there.Generated, regenerated with the repo's own tools:
node scripts/tenant-audit-census.mjs --write;main226 → 223 sites), with the prose figures the gate holds to the census updated;scripts/engine-double-contract.pinned.json(--write);engine-double-contract.baseline.jsonandobjectql-double-limit.baseline.json. Both gates name that removal; neither has a write flag.Changeset:
@objectstack/plugin-securityminor (a narrowing on the v18 prerelease line). The ADR-0087 marker isnot-required (runtime-export-retired …)for the 11 retired exports, each with its FROM → TO.@objectstack/specpatch.Acceptance notes
The zero-row result already held on
mainafter S8. On S8's parent99e944daf2, measured with this same test file, every leg goes red on both kernels:expected 2 to be +0(the projector'sadminrows);expected 2 to be +0after the boot).That tree is the writer put back.
Not here:
check:adr-symbol-anchorsexit 0), so no ADR line anchors into a deleted file and no anchor fix was needed.permission.zod.ts:824,metadata-plugin.zod.ts:1166anderror-code-ledger.zod.ts:1270;scripts/check-durability-degradation-log-level.mjs:156;sourceofdocs/qa/platform-checklist/areas/access-security.json:2649;plugin-security.A deliberate correction of a pending release note, for confirmation:
.changeset/23233-permission-echo-names-runtime-package.md(added by fix(plugin-security): the permission-set echo names its runtime package, so an isDefault set records its everyone suggestion #23258, not by this PR). Its "Unchanged" item said the set keeps asys_permission_setrow (managed_by: 'admin', nopackage_id). After this PR no row is written, so that sentence would publish a false statement. The seat's patch round (6160244399, item 3) asks for the correction.check-empty-changesetstays red on it by design, and this note is the human path that gate names.Verification
Full battery, on
accde78fe6(main18cd410dc4merged in). Since then the code has changed only bymainmerges and this round's patch, which touches no runtime code path.plugin-securitytypecheck: exit 0.plugin-securitysuite: 185/185 files, 3,772 passed.--ranreconciles with 0 UNRUN and 1 NOT-MEASURED:check:platform-checklist, exit 1 with the same 8 reds asmain.check:pm-dispatch-gates: exit 0.The patch round, scoped, on
ddcdb46bd4(main6eb6f7d65bmerged in once, just before the push):check:liveness: exit 0.plugin-securitylock suites (packaged-permission-set-lock*.test.ts): 2 files, 15 passed. The new non-list pin measured red with the branch ablated.plugin-securityand spec typecheck: exit 0.--ranreconciles with 0 NOT-MEASURED and 0 UNRUN. 71 exit 0.check-empty-changesetexits 1, deliberately: see the next point.The ablation: see Acceptance notes (S8's parent
99e944daf2, red on both kernels).objectui pinned sibling: NOT MEASURED. It is not checked out here, and the Console Pin Gate runs only in the full battery (#22998), so it is skipped on a PR. Nothing the console imports should move: the entry loses only the 11 projector names (
permissionSetRowFields,permissionSetBodyFromRow,upsertEnvPermissionSet,projectPermissionMutation,registerPermissionSetProjection,createPermissionSetWriteThrough,reconcilePermissionSetProjection, and the typesPermissionSeedOutcome,ProjectionDeps,ProjectionReconcileOutcome,WriteThroughDeps), and no package in this repository imports any of them.Generated by Claude Code