Repository navigation
feat(cli): os secret orphans also reports sys_secret handles more than one holder names, or a column other than their own holds - #27792
Conversation
…es, or a column other than their own holds The orphan report answered which sys_secret rows nothing names. Its report mode now also lists, from the same reference union, each handle more than one holder record names (shared), each handle a column other than the one its (namespace, key) names holds (misplaced), and, apart from both, a share whose every holder is a row of the handle's own minting column, the shape a predicate update writes. Report-only: nothing feeds the deletion plan and nothing is repaired. The union now carries each holder's coordinates as data. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cw9cC8mhpZX1HgeLg5
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 4 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 35 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 a34e48edc5ace98a01d31da4d35fe4d1cfb11ea1 && git checkout a34e48edc5ace98a01d31da4d35fe4d1cfb11ea1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ca64f6f9ea9e23a1c444d01faa09ea648aa32b21 2569bd1ae2ebd1b0fecd368f6043e4ff4fdcc886 && git checkout -B drift-repro ca64f6f9ea9e23a1c444d01faa09ea648aa32b21 && git merge --no-ff 2569bd1ae2ebd1b0fecd368f6043e4ff4fdcc886
node scripts/docs-audit/affected-docs.mjs --json ca64f6f9ea9e23a1c444d01faa09ea648aa32b21
|
|
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia Seat ACCEPT · PR #27792 · head
|
Requested by Elon · project thread
Fixes #27721
Clause-②: no
Metadata-protocol: none
维护者速读
os secret orphans的报告模式在原有孤儿报告之外,新增一节「被命名的 handle」:列出被多于一个持有记录命名的sys_secrethandle(shared),以及持有它的列不是其(namespace, key)所指列的 handle(misplaced),带计数与每个持有者的对象/字段/记录;谓词更新造成的同列共享单独列出、不作判定。--delete的删除计划,不修复任何东西,不打印任何密文或明文。--json多出一个顶层键holders(增量)。回滚即整 PR revert。packages/cli/src/utils/sys-secret-holder-report.ts(分类规则与谓词更新的区分)、packages/cli/src/utils/secret-reference-union.ts(每个引用新增的结构化持有坐标)、packages/cli/src/commands/secret/orphans.ts(只在报告模式输出)。pnpm --filter @objectstack/cli exec vitest run --project integration src/utils/sys-secret-holder-report.test.ts,预期 14 个用例全绿,其中谓词更新那条由真实引擎写出共享 handle。What changes
secret-reference-union.ts— everySecretReferencenow carriescolumn: the holding object, field and record, and the(namespace, key)its producer records on a handle it mints for that column (nullfor the datasource binder, which records the pair its caller passes). Collected at the same read; the settings read now also selectsidto name the record. The printableholderstring is unchanged, and the module still contains no classification.sys-secret-holder-report.ts(new, pure) — a report-only pass over thesys_secretsnapshots and the union:shared: a handle more than one holder record names;misplaced: a handle at least one holder of which is not the column its(namespace, key)names;sharedInOwnColumn, listed apart: every holder is anobject-fieldrow of the handle's own minting column. That is the shape a predicate update writes; stored rows cannot tell it from a reference copied between rows of the same column, so it is listed, not judged. A share across settings rows never gets this exemption: settings seals one handle per row write.os secret orphans— report mode prints the section and--jsoncarries it as a new top-levelholderskey besideplan.--deleteis untouched; the section never feeds the deletion plan. No new flag.os secret orphanssection ofcontent/docs/deployment/cli.mdxdescribes the section. Changeset:@objectstack/clipatch.On the additive
--jsonkey: no shipped consumer parses theos secret orphans --jsondocument. In this repository it is read only by tests (orphans.driver-contract.test.ts,data-commands.absent-database.integration.test.ts, both viatoMatchObjectonmodeandplan), and the docs call it "the same report, machine-readable" without stating a closed shape.Why
The orphan report answers which
sys_secretrows nothing names. It did not answer whether a handle something does name is named by more than one holder, or held by a column other than the one its pair names, which is the question the engine's release asks before it removes a handle. Values stored before writes were limited to their own record's reference were never re-examined. Whether a repair path follows is a later decision; this PR builds none.Tests
sys-secret-holder-report.test.ts(new, 14 cases): fixtures minted by the real producers (realObjectQLwrite path including a real predicate update, realLocalCryptoProvider, real datasource binder), read back by the real union collector. Pins: a handle two settings rows name issharedwith both holders' coordinates; a handle copied onto another column issharedandmisplaced, naming which holder is out of place; a handle whose only holder is out of place ismisplaced; the share the engine's predicate update wrote is insharedInOwnColumnand in neither other class; a settings share is not exempted; datasource placement is not judged; counts per class; no plaintext and no cipher material anywhere in the serialized report (with an anti-vacuity check), and the store is unchanged; an incomplete union names its missing family.secret-reference-union.test.ts: each family's reference carries itscolumncoordinates.orphans.driver-contract.test.ts(real SQLite, the command's own boot): the--jsonreport lists a handle two seeded settings rows name underholders.shared, and the command's whole stdout carries none of the seeded cipher material. The command is run once and memoized across the two end-to-end cases.git diff HEADempty, viascripts/ablation-replace.mjs):false→ 3 red (the predicate-update pin, the settings-not-exempt pin, counts);in_place→ 7 red (both misplaced pins, the cross-column share, the control, counts, the incomplete-union pin, the settings-not-exempt pin);holdersdropped from the command's--json→ the command-level pin red.Acceptance notes
sys-secret-orphan-sweep.test.tschanges one fixture literal only (the new requiredcolumnmember); no assertion moved.sys_secretrow is not listed: the card asks aboutsys_secrethandles, and a dangling reference is a different question.Verification
All readings on head
2569bd1ae2(this branch withmainat6d8372a8cdmerged in), afterpnpm install --frozen-lockfile && pnpm build.node scripts/pm/dispatch-gates.mjs --ran—93 derived, 93 run, 0 NOT-MEASURED, 0 UNRUN(exit 0). Every derived family exited 0.pnpm --filter @objectstack/cli typecheck— exit 0 (tsc --noEmitandcheck:test-typecheck: OK, debt unchanged at 3 files / 28 errors / 6 pinned signatures).vitest run --project integration:sys-secret-holder-report,secret-reference-union,sys-secret-orphan-sweep,orphans.guards,orphans.driver-contract,orphans.journal-mode,data-commands.absent-database— Test Files 7 passed, Tests 136 passed.unitproject of@objectstack/cliran once before the merge (head48a9b65dd2): 349 of 351 files passed, 5055 tests passed. The two files that failed (published-subpath-console.pin,published-subpath-hook-body.pin) refused becausepackages/cliitself was not built yet; after the full build they pass on the final head (2 files, 29 tests).--no-inline-configover the seven touched TypeScript files — exit 0. The repo-widepnpm lintis CI'sLint & Repo Gates.!in the title and no(narrowing)arm.Derived gate families and exit codes (93)
Human Minimum
packages/specholds no runtime logic. (packages/specuntouched.)pnpm lintpasses. (ESLint over the touched files locally; the repo-wide run is CI'sLint & Repo Gates.)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cw9cC8mhpZX1HgeLg5
Generated by Claude Code