Repository navigation
Commit cb074ec
feat(cli): os secret orphans also reports sys_secret handles more than one holder names, or a column other than their own holds (#27792)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DECWEobVDFstMHroz5Kem8z)_
Fixes #27721
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:`os secret orphans` 的报告模式在原有孤儿报告之外,新增一节「被命名的
handle」:列出被多于一个持有记录命名的 `sys_secret` handle(shared),以及持有它的列不是其
`(namespace, key)` 所指列的
handle(misplaced),带计数与每个持有者的对象/字段/记录;谓词更新造成的同列共享单独列出、不作判定。
- **为什么改**:非系统写入现在只能保留本记录自己的引用,但此前已存的值没有被重新检查;原报告只回答「谁都不引用的行」,回答不了「一个
handle 被几处引用、是否在自己的列里」。
- **风险与回滚**:只读、只报告;不进入 `--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`** — every `SecretReference` now carries
`column`: the holding object, field and record, and the `(namespace,
key)` its producer records on a handle it mints for that column (`null`
for the datasource binder, which records the pair its caller passes).
Collected at the same read; the settings read now also selects `id` to
name the record. The printable `holder` string is unchanged, and the
module still contains no classification.
- **`sys-secret-holder-report.ts`** (new, pure) — a report-only pass
over the `sys_secret` snapshots 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 an `object-field`
row 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.
- Datasource holders are not judged for placement (counted, with a
note). An incomplete union is reported on what was enumerated and names
the missing family.
- **`os secret orphans`** — report mode prints the section and `--json`
carries it as a new top-level `holders` key beside `plan`. `--delete` is
untouched; the section never feeds the deletion plan. No new flag.
- **Docs** — the `os secret orphans` section of
`content/docs/deployment/cli.mdx` describes the section. Changeset:
`@objectstack/cli` patch.
On the additive `--json` key: no shipped consumer parses the `os secret
orphans --json` document. In this repository it is read only by tests
(`orphans.driver-contract.test.ts`,
`data-commands.absent-database.integration.test.ts`, both via
`toMatchObject` on `mode` and `plan`), and the docs call it "the same
report, machine-readable" without stating a closed shape.
## Why
The orphan report answers which `sys_secret` rows 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 (real `ObjectQL` write path including a real
predicate update, real `LocalCryptoProvider`, real datasource binder),
read back by the real union collector. Pins: a handle two settings rows
name is `shared` with both holders' coordinates; a handle copied onto
another column is `shared` and `misplaced`, naming which holder is out
of place; a handle whose only holder is out of place is `misplaced`; the
share the engine's predicate update wrote is in `sharedInOwnColumn` and
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 its
`column` coordinates.
- `orphans.driver-contract.test.ts` (real SQLite, the command's own
boot): the `--json` report lists a handle two seeded settings rows name
under `holders.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.
- Ablations (each restored, blob equal to HEAD and `git diff HEAD`
empty, via `scripts/ablation-replace.mjs`):
- own-column predicate forced `false` → 3 red (the predicate-update pin,
the settings-not-exempt pin, counts);
- placement forced `in_place` → 7 red (both misplaced pins, the
cross-column share, the control, counts, the incomplete-union pin, the
settings-not-exempt pin);
- single-holder skip forced for every handle → 6 red (both shared pins,
the predicate-update pin, counts, the incomplete-union pin, the
settings-not-exempt pin);
- `holders` dropped from the command's `--json` → the command-level pin
red.
## Acceptance notes
- `sys-secret-orphan-sweep.test.ts` changes one fixture literal only
(the new required `column` member); no assertion moved.
- A reference that names a handle with no `sys_secret` row is not
listed: the card asks about `sys_secret` handles, and a dangling
reference is a different question.
## Verification
All readings on head `2569bd1ae2` (this branch with `main` at
`6d8372a8cd` merged in), after `pnpm 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 --noEmit`
and `check:test-typecheck: OK`, debt unchanged at 3 files / 28 errors /
6 pinned signatures).
- Touched suites, `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.
- The whole `unit` project of `@objectstack/cli` ran once before the
merge (head `48a9b65dd2`): 349 of 351 files passed, 5055 tests passed.
The two files that failed (`published-subpath-console.pin`,
`published-subpath-hook-body.pin`) refused because `packages/cli` itself
was not built yet; after the full build they pass on the final head (2
files, 29 tests).
- ESLint with the repo config and `--no-inline-config` over the seven
touched TypeScript files — exit 0. The repo-wide `pnpm lint` is CI's
`Lint & Repo Gates`.
- Dogfood battery: n/a — no `!` in the title and no `(narrowing)` arm.
<details>
<summary>Derived gate families and exit codes (93)</summary>
```text
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-doc-route-spelling.mjs --advisory :: exit 0
node scripts/check-doc-route-spelling.mjs --self-test :: exit 0
node scripts/check-docs-section-name.mjs :: exit 0
node scripts/check-docs-section-name.mjs --self-test :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/check-section-landing-index.mjs :: exit 0
node scripts/check-section-landing-index.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0
pnpm --filter @objectstack/spec run check:docs :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm --filter @objectstack/spec run check:empty-state :: exit 0
pnpm --filter @objectstack/spec run check:liveness :: exit 0
pnpm --filter @objectstack/spec run check:skill-examples :: exit 0
pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0
pnpm --filter @objectstack/spec run check:variant-docs :: exit 0
pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-examples-parity :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:corpus-claim-drift :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-anchors :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:doc-frontmatter :: exit 0
pnpm check:docs-audit-scope :: exit 0
pnpm check:docs-redirects :: exit 0
pnpm check:docs-single-h1 :: exit 0
pnpm check:docs-spec-enumerations :: exit 0
pnpm check:docs-transcript-drift :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:error-status-conformance :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:i18n :: exit 0
pnpm check:i18n-coverage :: exit 0
pnpm check:i18n-walk-parity :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:pm-changeset-deadline-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:published-readme-links :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:react-page-adapter-contract :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:role-word :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:vendor-version-stamps :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(`packages/spec` untouched.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (ESLint over the touched
files locally; the repo-wide run is CI's `Lint & Repo Gates`.)
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (Not touched.)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_016WV4cw9cC8mhpZX1HgeLg5
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cw9cC8mhpZX1HgeLg5)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent a3014cb commit cb074ec
9 files changed
Lines changed: 851 additions & 18 deletions
File tree
- .changeset
- content/docs/deployment
- packages/cli/src
- commands/secret
- utils
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
664 | 664 | | |
665 | 665 | | |
666 | 666 | | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
667 | 680 | | |
668 | 681 | | |
669 | 682 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
44 | 50 | | |
45 | 51 | | |
46 | 52 | | |
| |||
96 | 102 | | |
97 | 103 | | |
98 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
99 | 142 | | |
100 | 143 | | |
101 | 144 | | |
| |||
153 | 196 | | |
154 | 197 | | |
155 | 198 | | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
156 | 203 | | |
157 | 204 | | |
158 | 205 | | |
| |||
230 | 277 | | |
231 | 278 | | |
232 | 279 | | |
233 | | - | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
234 | 286 | | |
235 | 287 | | |
236 | 288 | | |
| |||
252 | 304 | | |
253 | 305 | | |
254 | 306 | | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
264 | 314 | | |
265 | 315 | | |
266 | 316 | | |
| |||
278 | 328 | | |
279 | 329 | | |
280 | 330 | | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
281 | 351 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
93 | 94 | | |
94 | 95 | | |
95 | 96 | | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
96 | 105 | | |
97 | 106 | | |
98 | 107 | | |
99 | 108 | | |
100 | | - | |
| 109 | + | |
| 110 | + | |
101 | 111 | | |
102 | 112 | | |
103 | 113 | | |
| |||
200 | 210 | | |
201 | 211 | | |
202 | 212 | | |
| 213 | + | |
203 | 214 | | |
204 | 215 | | |
205 | 216 | | |
| |||
340 | 351 | | |
341 | 352 | | |
342 | 353 | | |
343 | | - | |
| 354 | + | |
| 355 | + | |
344 | 356 | | |
| 357 | + | |
345 | 358 | | |
346 | 359 | | |
347 | 360 | | |
| |||
583 | 596 | | |
584 | 597 | | |
585 | 598 | | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
348 | 348 | | |
349 | 349 | | |
350 | 350 | | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
351 | 355 | | |
352 | 356 | | |
353 | 357 | | |
| |||
394 | 398 | | |
395 | 399 | | |
396 | 400 | | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
397 | 404 | | |
398 | 405 | | |
399 | 406 | | |
| |||
419 | 426 | | |
420 | 427 | | |
421 | 428 | | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
422 | 433 | | |
423 | 434 | | |
424 | 435 | | |
| |||
492 | 503 | | |
493 | 504 | | |
494 | 505 | | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
495 | 510 | | |
496 | 511 | | |
497 | 512 | | |
| |||
500 | 515 | | |
501 | 516 | | |
502 | 517 | | |
503 | | - | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
504 | 524 | | |
505 | 525 | | |
506 | 526 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
136 | 165 | | |
137 | 166 | | |
138 | 167 | | |
| |||
380 | 409 | | |
381 | 410 | | |
382 | 411 | | |
383 | | - | |
| 412 | + | |
384 | 413 | | |
385 | | - | |
386 | | - | |
| 414 | + | |
| 415 | + | |
387 | 416 | | |
388 | 417 | | |
389 | 418 | | |
| |||
405 | 434 | | |
406 | 435 | | |
407 | 436 | | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
408 | 443 | | |
409 | 444 | | |
410 | 445 | | |
| |||
481 | 516 | | |
482 | 517 | | |
483 | 518 | | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
484 | 525 | | |
485 | 526 | | |
486 | 527 | | |
| |||
535 | 576 | | |
536 | 577 | | |
537 | 578 | | |
538 | | - | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
539 | 590 | | |
540 | 591 | | |
541 | 592 | | |
| |||
0 commit comments