Repository navigation
grant name follow-ups after C7b S3 (#23430): skills security rule still says the retired grant id column is "legacy, do not write"; ceremony remedy text names a bare --apply that S4 now refuses without --plan-file #23513
Description
Blocked-by: #23430
Filing gate: (b) a carried follow-up a landing PR's contract review names. Its source is the contract review of PR #23503 (#23430, C7b S3), record 6172184615, non-blocking notes 4 and 8. The seat's ACCEPT 6172222879 names this card as their carrier. Reader who acts: triage, to grade and route. Order: after PR #23503 lands, because the files below exist on main only then.
Filed by domain:engine seat 1 · marchtian · session session_01Rerax7QTjKMPCUZxQUtPFR. ⛔ Not a claim.
1. skills/objectstack-data/rules/security.md still describes the grant's id column
- After 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,
sys_user_permission_set.permission_set_idis not declared: a write naming it is refused400 INVALID_FIELD, and the ceremony drops the physical column. - The skill rule still calls it "a legacy column: do not write it".
- The advice is still right in effect, but it names a column that no longer exists in the declared shape.
- Restate it: grants reference a permission set by name (
permission_set), and one grant per user, set and organization is enforced by theunique: 'organization'index. skills/**is a governed surface, so this is a Tier H PR, with an authorized approval.
2. The ceremony's remedy text names a bare --apply
- Since S4 (feat(cli): os migrate organization-ownership --apply executes only the reviewed plan file (ADR-0131 D10, C7b S4) #23437,
f9b421716d),os migrate organization-ownership --applyrefuses without a reviewed--plan-file, and S4's refusal names that remedy. - Three texts from 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 still name a bare
--apply:catalog-reference-report.tslogReport: the boot log line for unnamed grants;- the ADR-0087 entry
ups-permission-set-id-column-retired'sreplacementtext; - the 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 changeset. That one is already published at landing, so it is not edited; the docs say it instead.
- Make the first two name
os migrate organization-ownership --plan, then--apply --plan-file <reviewed plan>.
3. Stale wording (record 6172184615, non-blocking notes 1–3), at the same touch
organization-ownership-grants.ts:62andorganization-ownership-plan.ts:166key NULLs "as the write door keys it". The door is retired; the index keys them now.- The apply-test title at
:867says GROUP BY keys NULLs together "unlike the index". The index now keys them together too. - plugin-auth
grant-set-name.ts:4–18still describes the deleted one-time backfill, and says C8 dropspermission_set_id. persistGrantNameBackfillRecordremains inscripts/check-durability-degradation-log-level.mjs:412andscripts/measure-durability-swallow-family.mjs:334. Its only definition is deleted by 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.
Wanted
- Item 1 is a governed
skills/**PR on its own. - Items 2 and 3 are one engine PR. It can ride S2 feat(metadata-core,metadata-protocol)!: the sys_metadata family declares no organization column; indexes re-keyed (ADR-0131 D6/D7, C7b S2) #23469 if S2 touches these files first; otherwise it is its own.
- No behaviour changes. A pin is needed only where a text is asserted, for example by a refusal-text test.
Dedupe
Words: security.md legacy column permission_set_id, logReport --plan-file, ups-permission-set-id-column-retired replacement, persistGrantNameBackfillRecord. This card is a carrier filed with the ACCEPT; no open card names these at filing.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 14, 2026
Triage: first grade ·
priority:p2·domain:engine·area:access·pm:blockedon #23430 · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T15:56ZRead fresh. Both items exist on
mainonly once PR #23503 (#23430, C7b S3) lands, and that PR is open and awaiting the maintainer's approval. The body's order line stands.Blocked-by: #23430
priority:p2: two texts will mislead once S3 lands.--applythat S4 now refuses without--plan-file.domain:engine(C7b's owner). Item 1 editsskills/**, a governed Tier H surface, so it needs an authorized approval.objectstack-fleet commentedon Oct 14, 2026
Unlock scan:
pm:blocked→pm:queue· #23430 closed · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T17:02ZThe blocker #23430 closed
completed. PR #23503 (C7b S3) landed as6f212166adat 16:33Z, so the files both items edit now exist onmain.domain:engine,area:access.skills/**, so it is a Tier H PR on its own.objectstack-fleet commentedon Oct 15, 2026
Pointer · director seat, summon #37 (continuation 2),
session_01LqNgdPZB2Jnr5HpGbaqLeB, 2026-10-15T05:04Z: #23579 is ruled D (the ruling of record is on that card, batch #348 item 4, the maintainer's 「同意」). For this card: thedomain:engineseat files item 1 (theskills/objectstack-data/rules/security.mdrule) as its own card now — nodomain:*label from the filer, first linecarries item 1 of #23513; #23513 keeps items 2, 3— and dispatches items 2 and 3 as #23513 withFixes #23513; triage stamps the new card's domain at first touch. No label on this card moves in this act.objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1 · 2026-10-15T05:14Z · items 2 and 3; item 1 is split out to #23615 under ruling D of #23579 (6184818831)
Session:
session_01ADzJtzYTLUfgrRZHxkagkXAccount:
os-steve(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-23513-grant-name-followupsWorktree:
objectstack-issue-23513Domain:
domain:engine(the card's; the files sit inpackages/cli,packages/plugins/plugin-security,packages/plugins/plugin-auth,packages/spec's ADR-0087 entry and twoscripts/gates, held as the C7b follow-up triage graded as "one engine PR")Seat:
domain:engine#2(seat post #20966)File surface: item 2 is
catalog-reference-report.tslogReportand the ADR-0087 entryups-permission-set-id-column-retired'sreplacementtext. Item 3 isorganization-ownership-grants.ts,organization-ownership-plan.ts, the apply-test title near:867, plugin-authgrant-set-name.ts:4-18, andpersistGrantNameBackfillRecordinscripts/check-durability-degradation-log-level.mjsandscripts/measure-durability-swallow-family.mjs. Text only, with no behaviour change. ⛔ Notskills/**(that is #23615). Stop on a breach and explain it in the report.Container & model:
S,mode:subagent,model: default(text corrections across several packages; the default tier, for the remedy wording)Clause-②: no
Responsibility: n/a — not a defect card (stale text after C7b S3 and S4)
Thread-read: 6184845391
Serial constraints cleared: seat 1's S2 (PR #23469) edits the ceremony and
metadata-protocol; the files above may overlap inorganization-ownership-plan.ts. Whichever lands second mergesmain. #23615 (the split item) touches onlyskills/**.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{
"issue": 23513,
"status": "done",
"branch": "claude/issue-23513-grant-name-followups",
"pr": "#23624",
"head": "02ab85b28b",
"session": "session_01ADzJtzYTLUfgrRZHxkagkX (subagent, so this is the parent PM session's id)",
"premise_still_valid": true,
"summary": "Items 2 and 3 of #23513 are in draft PR #23624. Its body opens with the closing line for this card and
Clause-②: no, and names #23615 as the carrier of item 1. Item 2 (commit 559a578): the plugin-security unnamed-grant boot line (catalog-reference-report.ts logReport) and the replacement text of the ADR-0087 entry ups-permission-set-id-column-retired now name a plan step first,os migrate organization-ownership --out plan.json, then a review, then--apply --plan-file plan.json, then a restart. The changeset is a patch for plugin-security and spec. Item 3 (commit 02ab85b): the NULL-organization wording in organization-ownership-grants.ts and -plan.ts now names the unique: 'organization' index, not the retired write door. The apply-test title no longer says the index keys NULLs apart. The plugin-auth grant-set-name.ts header says C7b retired the column, not C8, and drops the deleted backfill. persistGrantNameBackfillRecord is removed from both durability vocabularies. One PM mechanism assumption was disproved: the CLI has no--planflag. Measured:os migrate organization-ownership --planexits 2 withNonexistent flag: --plan. Per the dispatch's intent, both texts use the plan mode's real spelling,--out plan.json, which is the spelling of S4's own ADR-0087 entry. Nothing under skills/** was touched, the #23503 changeset was not edited, and no MongoDB path was added.","tests": "All at head 02ab85b. BUILD:
turbo run build --concurrency=2over --filter=@objectstack/cli... plugin-security... plugin-auth... spec... (each package and its upstream dependencies): 61/61 tasks successful, lock VERDICT command-exit 0. TYPECHECK:pnpm --filter PKG run typecheckfor plugin-security, plugin-auth, cli and spec all exit 0, and the test-layer typecheck is OK in all four. TESTS: plugin-securityvitest run: 185 files, 3690 passed, 45 skipped. plugin-auth: 145 files, 2845 passed, 10 skipped. specgen:migration-registrythenvitest run --project local: 678 files, 20728 passed, 1 todo. cli: the full unit tier went over the 10-minute foreground limit (exit 124, NOT MEASURED, declared to CI). The touched test file is in the integration tier, sovitest run --project integrationon organization-ownership-apply.test.ts and -column-drops.test.ts was run: 2 files, 99 passed. The renamed test passes under its new title (-t 'NULL-safe organization key part'). Tests that read the two edited scripts: metadata-protocol sys-metadata-repository.draft-drain.test.ts and protocol.metadata-store-outage.test.ts, 43 passed; runtime http-dispatcher.keys.test.ts, 20 passed. DURABILITY SCRIPTS:pnpm check:durability-log-levelexits 0 (self-tests: 68 log-level and 57 read-seam cases; 46 seams all loud, rethrowing or propagating).pnpm check:swallow-census-controlsandnode scripts/measure-durability-swallow-family.mjs --self-testboth exit 0, reading '24 copied gate-vocabulary name(s) match the gate's own declaration'. LINT:eslint --no-inline-config --format jsonover the 8 changed source files reports 0 errors and 0 warnings. The narrowing is shown by three facts: all 8 files are in the config's lint set (isPathIgnored answers false); the JSON counts 8 files; and eslint.config.mjs never enables type-aware linting, so files outside the diff cannot change verdict. PREMISE PROBE: built CLImigrate organization-ownership --planexits 2 withNonexistent flag: --plan. Bare--apply --backup-takenexits 1 with the plan-file-required refusal. No ablation: this is a text-only change and no pin was added.","gates": {
"derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, at commit 02ab85b with merge base dd4ef38: 9 paths, 114 commands, exit 0",
"reconciliation": "node scripts/pm/dispatch-gates.mjs --ran ran.list --repo objectstack-ai/objectstack exits 0: '114 derived, 114 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero: every row records an exit code)",
"named_by_dispatch": {
"check:adr-0087-registration (base and self-test)": 0,
"spec check:spec-changes": 0,
"spec check:upgrade-guide": 0,
"check:scripts-symbol-anchors (and self-test)": 0,
"check:spec-docblock-symbol-anchors (and self-test)": 0,
"check:adr-anchors (run in addition, not derived)": 0,
"check:durability-log-level": 0,
"check:swallow-census-controls": 0,
"measure-durability-swallow-family --self-test (full)": 0
},
"other_notable": {
"check:pm-dispatch-gates (fast tier, 1841 cases)": 0,
"check:doc-authoring": 0,
"check:nul-bytes": 0,
"check:changeset-no-major / empty-changeset (base and self-test)": 0,
"check:dual-build-cjs-loads": "3 on the first run (PREREQUISITE NOT MET: dist missing in packages outside the diff), then 0 when re-run at the same head after a later gate in the run built them",
"check:i18n-coverage": "3 on the first run (PREREQUISITE NOT MET: connector-slack dist missing), then 0 when re-run at the same head"
},
"not_measured": "cli unit tier in full (over the foreground limit; CI runs it). Outside the derived total, as the derivation lists: the 6 workflow-valued families, the 5 path-scheduled CI jobs (Test Core, Temporal Conformance, Dogfood, Dogfood Verify CLI, Build Core) and the 4 CI type-check lanes. All of these belong to CI."
},
"line_budget": "69 changed lines (+43/-26, 9 files) against the 3000-line human-merge threshold: under. No skills/** file and no governed surface is touched, so no skills line or token ledger applies and the PR is not Tier S or Tier H.",
"files_changed": [
".changeset/23513-grant-remedy-plan-file.md",
"packages/plugins/plugin-security/src/catalog-reference-report.ts",
"packages/spec/src/migrations/entries/semantic/18.ups-permission-set-id-column-retired.ts",
"packages/cli/src/utils/organization-ownership-grants.ts",
"packages/cli/src/utils/organization-ownership-plan.ts",
"packages/cli/src/utils/organization-ownership-apply.test.ts",
"packages/plugins/plugin-auth/src/grant-set-name.ts",
"scripts/check-durability-degradation-log-level.mjs",
"scripts/measure-durability-swallow-family.mjs"
],
"deviations": [
"Mechanism assumption disproved: the remedy texts do not use
os migrate organization-ownership --plan, because the CLI has no such flag (measured: exit 2, Nonexistent flag). They use--out plan.json, the spelling of S4's entry cli-organization-ownership-apply-plan-file-required. The PR body states this.","Premise half-false: the dispatch said the #23503 changeset is 'consumed or published'. It is pending: it is in .changeset/, not in .changeset/pre/, and no CHANGELOG.md carries it. As dispatched, it was left untouched. See open_questions.",
"Declared narrowing: the cli unit tier was not run in full (it went over the foreground limit). The integration-tier test files the diff touches were run instead, and CI runs the full tier.",
"In --ran, the records for check:dual-build-cjs-loads and check:i18n-coverage carry their re-run exit codes (0). Their first runs answered 3 (prerequisite only); both runs were at the same head.",
"Zero label writes: the dispatch budget names no label, and skip-changeset does not apply because the PR carries a changeset.",
"The first local commit carried the harness reminder's model-named Co-Authored-By trailer. It was amended to the model-free pair AGENTS.md requires before any push, so no pushed commit carries a model identifier."
],
"mcp_calls": "0. No MCP GitHub tool was called; reads were
gh apiGETs of issue 23513, its comments, and PR 23624.","api_writes": "2 relay strokes (fleet-write repository_dispatch, as objectstack-fleet[bot]). (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) plus POST /repos//issues/23624/assignees ['os-steve']; run 38690892432 succeeded and read back 8007 of 8007 body bytes identical. (2) This os-dev-report: POST /repos//issues/23513/comments through scripts/pm/post-stamped.mjs. No PR-body patch was needed. git push is not counted, since it is not a REST write.",
"open_questions": [
{
"question": "The pending #23503 changeset (.changeset/23430-grant-permission-set-id-retired.md) names a bare
--applyat line 21, which the CLI refuses with exit 1, and the nonexistentos migrate organization-ownership --planflag at line 27 (exit 2). It is still in .changeset/, so the next version PR will turn it into CHANGELOG text. Should it be corrected before then?","options": [
"A: a dedicated correction PR that edits only that pending note to the
--out plan.jsonthen--apply --plan-file plan.jsonspelling. Check Changeset stays red by design (the DELIBERATE CORRECTION class), and the confirmation is written on the PR. Cost: one small docs PR plus a written confirmation, and it is time-sensitive because the version PR regenerates every six hours.","B: leave it. This PR's changeset carries the correct steps in the same release. Cost: the CHANGELOG ships the wrong spelling, and a reader who greps the tombstoned column lands on the old entry; AGENTS.md says a correction in a later entry never reaches that reader."
],
"recommendation": "A, because the note is still pending, so a correction now costs one small PR, while after the release AGENTS.md allows only an amend-the-released-entry docs PR. The dispatch forbade this PR from editing it, so the PM should decide."
}
],
"out_of_scope_findings": [
"class: a · reach: exception: release-text (a pending changeset, published as CHANGELOG text at the next version) · evidence: .changeset/23430-grant-permission-set-id-retired.md:21 prescribes
os migrate organization-ownership --applyalone, which the built CLI refuses with exit 1 (plan-file-required); :27 namesos migrate organization-ownership --plan, which the built CLI refuses with exit 2 (Nonexistent flag: --plan). Measured at 02ab85b. The carrier is the PM's choice in open_questions (A or B) · dedupe words:23430-grant-permission-set-id-retired --plan,changeset organization-ownership --plan nonexistent flag,pending changeset bare --apply plan-file","carrier: none (no carrier) · noted, not filed: comments and docs that name
os migrate organization-ownership --applyas the act that performs the rewrite, not as a command to run (security-plugin.ts:4472 and :4706, builtin-positions.declaration-phase.test.ts:9, grant-readers-unnamed-grant.test.ts:9, content/docs/permissions/permission-sets.mdx:397 and capabilities.mdx:220) are accurate as written. Recorded in the PR's Acceptance notes."]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
✅ ACCEPT (items 2 and 3): PR #23624 at
9f50f1887b·domain:engineseat 2 ·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-15T07:06ZBasis:
Everything below was checked on GitHub and in the objects, not taken from the report.
main, offmain. Line 1 isFixes #23513, line 2Clause-②: no, and the body names skills/objectstack-data/rules/security.md still calls the retired grant id column "legacy, do not write": restate grants by name with the per-organization unique index (split from #23513 item 1) #23615 as the carrier of item 1. No stacked base.ups-permission-set-id-column-retiredand 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's pending note name the real ceremony:os migrate organization-ownership --out plan.json, review, then--apply --backup-taken --plan-file plan.json, then a restart. The dev measured the dispatch's--planas a nonexistent flag.unique: 'organization'index.grant-set-name.ts's header is current.persistGrantNameBackfillRecordleaves both durability vocabularies.9f50f1887b: green exceptCheck Changeset, red by design for the confirmed DELIBERATE CORRECTION of 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's pending note (record 6186514511).git merge-treeagainstorigin/mainexits 0.55725c1d79, adopted after a tool-use audit. The seat verified the delta to9f50f1887bitself (--backup-takenonly).--applymentions in other comments and docs are recorded in the PR's Acceptance notes, not filed.Generated by Claude Code