Repository navigation
docs(verify): the RLS probe grant holds its set by name, not by row id (#15196 S5c) - #22802
Conversation
Two comments in rls.ts still described the grant resolution that ADR-0131 D3/D4 replaced: that the grant is keyed by row id and the resolver reads the set row to learn its name, and that resolvePermissionSets falls back to a sys_permission_set row that drops rowLevelSecurity. On main the resolver reads the grant's permission_set column and every definition source is the registry. The row is read only for the id the still-required permission_set_id column takes. Claude-Session: https://claude.ai/code/session_01M5baMwzrfukawVWc496yxD Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 3 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 f9dbbc4eafcc73911f559b45ce151be3f269f671 && git checkout f9dbbc4eafcc73911f559b45ce151be3f269f671
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 680a86b4c55dcb6255151d9a038a32208400f66c 740affb09843c796f3e37eccabbef55215d146bc && git checkout -B drift-repro 680a86b4c55dcb6255151d9a038a32208400f66c && git merge --no-ff 740affb09843c796f3e37eccabbef55215d146bc
node scripts/docs-audit/affected-docs.mjs --json 680a86b4c55dcb6255151d9a038a32208400f66c |
Brings in #22802 (S5c of #15196). One conflict, in provisionRlsProbePersona's comment block: kept this branch's text (the find-or-create block it annotated is gone here). rlsProbeSecurity's docblock correction from #22802 is kept as merged. Claude-Session: https://claude.ai/code/session_01M5baMwzrfukawVWc496yxD Co-authored-by: Claude <noreply@anthropic.com>
Part of #15196
Clause-②: no
Stage S5c of #15196:
verifyreads the name column. Claimed by the epic PM lane in 6106687498 (the maintainer folded S5c in with 「并进来(推荐)」, recorded in #15204's amendment 6106681412). The card stays open; its other stages (S8a / S8b / S9) are untouched here.What was left of S5c on
mainMeasured on
origin/main9f5eca52b:verifyread keys a grant by row id.verifywrites the probe grant and reads nothing back from grants. The writer already sends both columns (permission_set_idand the name columnpermission_set) since S4a (feat(plugin-security,plugin-auth,verify): sys_user_permission_set gains the permission-set name column, written by every grant writer (ADR-0131 C2 S4a) #22100).resolveUserAuthzGrants(packages/core/src/security/resolve-authz-context.ts, section 6) collectsgrantSetNameOf(grant), which readspermission_setalone, and takes each definition from the security catalog. Its comment states that "The grant'spermission_set_idis not read".PermissionEvaluator.resolvePermissionSetsreads metadata, then the bootstrap list, then thedbLoaderthe security plugin passes. That loader iscatalogSetLoader(security-plugin.tsaround line 1984), which callssecurityCatalogReaderOf(ql).resolve('permission', name), the registry, notsys_permission_set.So what S5c still owed was two comments in
packages/verify/src/rls.tsthat described the pre-ADR-0131 model as current:rlsProbeSecurity's docblock said the evaluator falls back to "the DB row only as a last resort", and that this loader dropsrowLevelSecurity. Neither holds. The corrected text says why the probe set must be registered: a row-only set resolves nowhere and grants nothing.provisionRlsProbePersonasaid "The grant is keyed by ROW ID, andresolveUserAuthzGrantsreads the row only to learn its NAME". The corrected text says the grant holds its set by name. The set row is read only for the id that the still-requiredpermission_set_idcolumn takes. The platform derives the grant's name from that id and refuses a disagreement (grant-permission-set-name.ts).The code is unchanged. Retiring the set-row read and mint is #15204 stage 4, which is its own PR.
Changeset
Comments only, with no behaviour change, so this takes
skip-changesetunder the repo's comment fast lane.Verification
All at
740affb:pnpm --filter '@objectstack/verify...' build: exit 0.pnpm --filter @objectstack/verify test: 29 files, 234 tests passed.pnpm --filter @objectstack/verify typecheck:tsc --noEmitclean, andcheck:test-typecheckOK.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE: 47 derived, 46 run, 1 NOT MEASURED.check:dual-build-cjs-loads, which exited 3 (PREREQUISITE NOT MET). It needs a whole-repopnpm build, which is left to CI.check-plugin-teardown-shape --self-test(shallow clone) andcheck:dts-closure(dist trees not yet built) refused their prerequisites. Aftergit fetch --unshallowand the build, both re-ran at exit 0.Acceptance notes
packages/plugins/plugin-security/src/objects/sys-user-permission-set.object.tsstill says, on thepermission_setfield, that "the resolver in @objectstack/core still reads the id until its own stage switches it". S5a switched it, so that sentence is now false too. It is outside this lane'spackages/verifyfile surface, so it is left for the next PR that touches that file. The grant door'spermission_set_idgoes in refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write undersingleand refused under a wall (ADR-0131 D2/D3/D5/D13) #15204 stage 8 or C7b.Generated by Claude Code