Repository navigation
fix(verify): provision the RLS probe persona through the registry, not a set row (#15204 stage 4) - #22807
Conversation
…t a set row provisionRlsProbePersona no longer mints a sys_permission_set row. It asks the security catalog, the same read the authorization resolver uses, whether the probe set is registered (rlsProbeSecurity registers it at boot). It reads the id of the row the boot seeds for that registered set, because sys_user_permission_set.permission_set_id is still required, and writes the one grant. A probe set the catalog does not serve, or a missing boot-seeded row, refuses and writes nothing. Claude-Session: https://claude.ai/code/session_01M5baMwzrfukawVWc496yxD Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also name something this change touched. These are read-only:
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 9b6205a393c5738ab2b9c27d8d04267788eebead && git checkout 9b6205a393c5738ab2b9c27d8d04267788eebead
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 14f4912390d7761a4b91a6e2ed1f1ca1fb95adfe ca4b3380b8d9e6ce50f59bb14bef6618fc36a6e4 && git checkout -B drift-repro 14f4912390d7761a4b91a6e2ed1f1ca1fb95adfe && git merge --no-ff ca4b3380b8d9e6ce50f59bb14bef6618fc36a6e4
node scripts/docs-audit/affected-docs.mjs --json 14f4912390d7761a4b91a6e2ed1f1ca1fb95adfe
|
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>
Stage 4 (#22807): merge round checked; queued · epic PM
|
Part of #15204
Clause-②: no
Stage 4 of #15204 (stage plan 6094501866):
verifyprovisions its RLS probe persona through the registry, not a set row. Claimed in the amendment 6106681412. The card stays open; its other stages are untouched here.What changes
packages/verify/src/rls.ts,provisionRlsProbePersona:sys_permission_setrow namedverify_rls_probe. When the row was missing, it minted one with the probe's object permissions and RLS serialized into row columns, then granted it.securityCatalogReaderOf(ql).resolve('permission', 'verify_rls_probe'). That is the read the authorization resolver itself uses (ADR-0131 D3/D4).rlsProbeSecurity(config)registers the set at boot. A stack booted without it now fails here, loudly, instead of granting a name that resolves to nothing.sys_permission_setrow the boot already seeded for that registered set.sys_user_permission_set.permission_set_idis still a required column (it goes in stage 8 or C7b), and the platform derives the grant's name from it and refuses a disagreement (grant-permission-set-name.ts). This is no transition piece: no new read or write is added for an intermediate state. It is the one remaining existing read, narrowed from find-or-create to find.objectstack verify --rlsalready turns any provisioning failure intoprobe.degradedplus a hard failure, so neither case can pass as a weaker persona.Measured before building (
origin/main9f5eca52b)SecurityPluginpassesoptions.defaultPermissionSets(whichrlsProbeSecurityextends with the probe set) asbootstrapPermissionSetstobootstrapPlatformAdminatkernel:ready. That function inserts a row for every bootstrap set it does not find (bootstrap-platform-admin.tsaround line 873).bootStack(showcase, { security: rlsProbeSecurity(config) })held exactly oneverify_rls_proberow afterwards: organization null,managed_by: platform.securityCatalogReaderOf(ql).resolve('permission', 'verify_rls_probe')answered an entry with 24 objects and 24rowLevelSecurityrules. The control, an unregistered name, answered undefined.@objectstack/organizationspackage, which this repository cannot load. The PR's CI is not shown to cover it either: no test drivesverify --rlsend to end.Verification
All at
72cc4a67c8:pnpm --filter '@objectstack/example-showcase^...' --filter '@objectstack/cli...' buildexited 0, as did the@objectstack/dogfood^...build.pnpm --filter @objectstack/verify testpassed 29 files, 236 tests.pnpm --filter @objectstack/verify typecheckwas clean, includingcheck:test-typecheck.rls-persona-grant.test.ts, rewritten. It pins four cases: the registered set is granted by name with the seeded row's id and no set row is inserted; no seeded row refuses and writes nothing; a row with no catalog entry refuses and writes nothing; no catalog bound refuses and writes nothing.main'srls.tswas restored under the new test withgit restore --source=9f5eca52b. The mutant heldgenId('ps')once andsecurityCatalogReaderOfzero times. The result was 3 failed, 1 passed: every refusal case went red, and the seeded-row case stays green becausemainalso reuses a found row.git checkout HEAD. Blobedefdfbc2589matched HEAD, andgit diff HEADwas empty.objectstack verify --app ./objectstack.config.ts --rls --jsonwas run onexamples/app-showcase, twice onmain's code and twice on this branch.hardFailures: 0and a probe that was not degraded (grantedObjects: 24).showcase_invoice, adopted rather than created after an admin create answered 400. The second run on this branch created it again, so this is run-to-run noise.pnpm --filter @objectstack/dogfood test; its files import@objectstack/verify): 245 files passed, 1 skipped; 1977 tests passed, 9 skipped; exit 0.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILEderived 61; 60 ran green and 1 is NOT MEASURED. That one ischeck:dual-build-cjs-loads, which exited 3 (PREREQUISITE NOT MET: it needs a whole-repo build) and is left to CI.Landing order with S5c
#22802 (#15196 S5c, comments only) edits the comment this PR replaces. Branching rules forbid stacked series, so this branch is cut from
main, not from S5c. Whichever of the two lands second takes one textual conflict inprovisionRlsProbePersona's comment block, resolved by keeping this PR's text. #22802 also correctsrlsProbeSecurity's docblock, which this PR leaves untouched for that reason.Acceptance notes
sys_permission_setrow for every registered bootstrap set (bootstrapPlatformAdmin). Stage 6b deletes "platform-admin materialization". If 6b-2 lands before stage 8 or C7b drops thepermission_set_idrequirement, it must carry this read along with the other grant writers that read a seeded id. Otherwiseverify --rlsreports a degraded persona, loudly, which is the failure mode this PR chose over minting.Generated by Claude Code