Repository navigation
fix(plugin-security,spec): the grant remedy texts name the reviewed-plan ceremony; C7b wording follow-ups in cli, plugin-auth and the durability vocabularies (#23513) - #23624
Conversation
…rmission-set-id-column-retired entry name the reviewed-plan ceremony, not a bare --apply `os migrate organization-ownership --apply` refuses without `--plan-file`. The catalog reference report's unnamed-grant error line and the ADR-0087 entry's `replacement` now name the plan step (`--out plan.json`), the review, then `--apply --plan-file plan.json`. Text only. Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
…he unique index's, the plugin-auth reader header drops the retired backfill, and the deleted backfill's callee leaves both durability vocabularies - organization-ownership-grants.ts / -plan.ts: a NULL organization is keyed as the `unique: 'organization'` index keys it (NULL-safe, ADR-0120 D3); the write door these comments named is retired. - organization-ownership-apply.test.ts: the NULL-organization duplicate test's title no longer says the index keys NULLs apart. - plugin-auth grant-set-name.ts: C7b, not C8, retired `permission_set_id`; no boot names a grant, the v18 ceremony's rewrite does. - check-durability-degradation-log-level.mjs and measure-durability-swallow-family.mjs: `persistGrantNameBackfillRecord` is removed from both vocabularies; its only definition was deleted with the boot backfill. The census's copied-vocabulary cross-check reads 24 names matching the gate's declaration. Comments, a test title and two script vocabularies only; no behaviour change. Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check1 anchor(s) derived from 4 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 154 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 c8260f80f9cbfa722821af20316009fe4263ec37 && git checkout c8260f80f9cbfa722821af20316009fe4263ec37
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin dd29bbe60df87727664424521c3a0b9eed37e985 9f50f1887b0f47ed778b3bff7f261d23831569a2 && git checkout -B drift-repro dd29bbe60df87727664424521c3a0b9eed37e985 && git merge --no-ff 9f50f1887b0f47ed778b3bff7f261d23831569a2
node scripts/docs-audit/affected-docs.mjs --json dd29bbe60df87727664424521c3a0b9eed37e985 |
…mony, not a bare --apply and a --plan flag the CLI does not have `.changeset/23430-grant-permission-set-id-retired.md` is still pending (in `.changeset/`, not `.changeset/pre/`), so it is corrected before the next version consumes it. Two sentences only: - the backfill's FROM -> TO now names `--out plan.json`, the review, then `--apply --plan-file plan.json` (bare `--apply` is refused: plan-file-required); - the grants block is reported by the plan run, `--out plan.json` (the CLI answers `--plan` with exit 2, Nonexistent flag). Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
…dy texts carries --backup-taken, as S4's entry, note and CLI examples spell it Without a TTY `--apply` refuses with backup-unacknowledged unless `--backup-taken` is passed. The unnamed-grant boot line, the ups-permission-set-id-column-retired entry's replacement and the pending C7b S3 note now write `os migrate organization-ownership --apply --backup-taken --plan-file plan.json`. One flag inserted in each; nothing else changes. Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
…aken, as the three texts it describes now do The title line and the "Both now name the two steps" sentence of .changeset/23513-grant-remedy-plan-file.md now give `--apply --backup-taken --plan-file plan.json`. One flag inserted in each. Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: PR #23624 at the head the brief named (it has not moved): merge base ① Derived judgmentsItem 2: the remedy texts.
The pending-note correction.
Item 3: is each reworded comment true on main plus this PR?
No behaviour change: confirmed. The only executable changes are:
Everything else is comments and changesets. Nothing under ② Semver level
③ Boundary flagsFrom 6185759753 and the patch round (55725c1):
New from this review:
CI on this head: 55 check-runs, read at 2026-10-15T06:49Z: 42 success, 10 skipped, 3 failure, none running. The only failures are the three Seat adoption (2026-10-15T07:05Z). Adopted after an audit of the reviewer transcript: one Write, to this record; 52 Bash calls, all reads ( The head moved after this record, and the seat verified the delta itself.
This aligns the apply step with S4's entry, S4's note and the CLI's examples, so a non-TTY caller is not refused The landing prechecks on
The seat confirms the DELIBERATE CORRECTION. #23503's note is still pending (it is not in Implemented-by: VERDICT: PASS |
Fixes #23513
Clause-②: no
Item 1 of the card, the
skills/objectstack-data/rules/security.mdrule, is carried by #23615 under ruling D of #23579 (ruling of record 6184818831). #23615 remains open, and this PR touches nothing underskills/**. This PR carries items 2 and 3. Text only: no behaviour changes.Item 2: the remedy texts name the reviewed-plan ceremony (commit 559a578)
Since S4 (
f9b421716d),os migrate organization-ownership --applyrefuses a run without--plan-file. Two texts from #23503 still told the operator to run--applyalone:packages/plugins/plugin-security/src/catalog-reference-report.ts,logReport: the boot error line for grants that name no permission set.packages/spec/src/migrations/entries/semantic/18.ups-permission-set-id-column-retired.ts: the entry'sreplacement, the row the upgrade guide prints.Both now name the two steps. First plan,
os migrate organization-ownership --out plan.json, and review the file it writes. Then runos migrate organization-ownership --apply --backup-taken --plan-file plan.json, which executes that plan, and restart. The line's level, its fields, and the entry'sid,surface,reasonandacceptanceCriteriaare unchanged..changeset/23513-grant-remedy-plan-file.mdreleases both packages as apatch. Under the WHICH LEVEL rule this changes no public surface.Spelling: the plan step is not
--plan. The card and the dispatch spelled the plan stepos migrate organization-ownership --plan. The CLI has no--planflag. ADR-0131 calls the bare run "--plan", and the command's flags are--out,--json,--apply,--plan-fileand the rest. Measured against the built CLI at this head:os migrate organization-ownership --planexits 2 withNonexistent flag: --plan. The command never ran.os migrate organization-ownership --apply --backup-takenexits 1 withRefused: --apply executes only a plan you reviewed. Run the plan first (os migrate organization-ownership, ...), review the file it writes, then re-run --apply with --plan-file FILE.So both texts use
--out plan.jsonfor the plan step. That is the spelling of S4's own ADR-0087 entry,cli-organization-ownership-apply-plan-file-required. The dispatch's intent is kept: a plan step, then--apply --plan-filewith the reviewed file.Item 3: stale wording (commit 02ab85b)
packages/cli/src/utils/organization-ownership-grants.ts(grantKey) andorganization-ownership-plan.ts(GrantKeyPlan): these comments said a NULL organization is keyed "as the write door keys it". The write door is retired. The text now says it is keyed as the grant'sunique: 'organization'index keys it, because the index's organization key part is NULL-safe (ADR-0120 D3).packages/cli/src/utils/organization-ownership-apply.test.ts: one test title said GROUP BY keys NULLs together "unlike the index". It now says "as the index's NULL-safe organization key part does". Only the title changes; the assertions are the same.packages/plugins/plugin-auth/src/grant-set-name.ts: the module header said C8 dropspermission_set_id, and that a one-time boot backfill names legacy grants. It now says C7b retired the column, that no boot names a grant, and that the v18 ceremony's verified rewrite names one or lists it with its reason.scripts/check-durability-degradation-log-level.mjs(DURABILITY_CRITICAL_CALLEES) andscripts/measure-durability-swallow-family.mjs(WRITE_SHAPED_CALLEES):persistGrantNameBackfillRecordis removed from both. feat(plugin-security,cli,spec)!: retire sys_user_permission_set.permission_set_id; the grant key is unique per organization; the boot grant-name backfill is deleted (C7b S3) #23503 deleted its only definition. The two lists must change together, because the census cross-checks its copy against the gate's declaration.Verification at head 02ab85b
turbo run build --concurrency=2over@objectstack/cli...,@objectstack/plugin-security...,@objectstack/plugin-auth...and@objectstack/spec...(the packages and their upstream dependencies): 61 of 61 tasks passed.pnpm --filter PKG run typecheckfor plugin-security, plugin-auth, cli and spec all exit 0. The test-layer typecheck is OK in all four.--project local, aftergen:migration-registry): 678 files, 20728 passed, 1 todo.organization-ownership-apply.test.tsand-column-drops.test.tsrun under--project integration, the tier they belong to and the tier the edited test file is in: 2 files, 99 passed. The renamed test passes under its new title (-t 'NULL-safe organization key part', verbose). The cliunittier was not run in full here: it went over the 10-minute foreground limit on a shared box, and CI runs it.sys-metadata-repository.draft-drain.test.tsandprotocol.metadata-store-outage.test.ts(43 passed), and runtimehttp-dispatcher.keys.test.ts(20 passed).pnpm check:durability-log-levelexits 0. Its self-tests pass: 68 log-level cases and 57 read-seam cases. Verdict: 46 durability-critical catch seams, all loud, rethrowing or propagating.pnpm check:swallow-census-controls(--self-test=gated) andnode scripts/measure-durability-swallow-family.mjs --self-testboth exit 0, with "24 copied gate-vocabulary name(s) match the gate's own declaration".node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderives 114 commands. All 114 were run, each exit code was recorded, and--ranreports: "114 run, 0 NOT-MEASURED (a DERIVED zero)".check:adr-0087-registration,check:spec-changes,check:upgrade-guide,check:scripts-symbol-anchors,check:spec-docblock-symbol-anchors,check:doc-authoring,check:nul-bytesandcheck:pm-dispatch-gates(1841 cases).check:dual-build-cjs-loadsandcheck:i18n-coveragefirst answered exit 3, PREREQUISITE NOT MET: some packages outside this diff had nodist. A later gate in the same run built those packages. Both were re-run at this head and exit 0. The recorded codes are from the re-runs.pnpm check:adr-anchors, which the derivation does not place, was also run: exit 0.pnpm exec eslint --no-inline-config --format jsonreports 0 errors and 0 warnings. Three facts show the narrowing leaves nothing out:ESLint.isPathIgnoredanswers false.eslint.config.mjsnever enables type-aware linting (noparserOptions.project), so this diff cannot change the verdict on any file it does not touch.Acceptance notes
.changeset/23430-grant-permission-set-id-retired.md, is corrected in commits 55725c1 and a618e17 (the PM's answer A). It is still pending in.changeset/, not.changeset/pre/. Exactly two sentences change. In the FROM → TO list, "→os migrate organization-ownership --apply." becomes "→ the v18 ceremony: plan it withos migrate organization-ownership --out plan.json, review the file it writes, then runos migrate organization-ownership --apply --backup-taken --plan-file plan.json." Under "What else changes", "os migrate organization-ownership --planreports agrantsblock" becomes "The plan run,os migrate organization-ownership --out plan.json, reports agrantsblock".Check Changesetstays red by design: this is a DELIBERATE CORRECTION of a pending note that another PR changed, and the seat confirms it at ACCEPT. Changeset checks at a618e17:check-empty-changeset --base origin/mainexits 1 (expected), and its--self-testexits 0.check-changeset-no-major --base origin/mainand its--self-testboth exit 0.os migrate organization-ownership --applyas the step that performs the rewrite, not as a command to run:security-plugin.ts, two plugin-security test headers, the plugin-auth reader header, andcontent/docs/permissions/{permission-sets,capabilities}.mdx.acceptanceCriteria, which says what is true after--applyhas run.replacement, so the dispatch's rule (pin only a text that a test asserts) adds none.organization-ownership-plan.ts. This PR changes only theGrantKeyPlandoc comment there, andmainwas not merged.🤖 Generated with Claude Code
https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX