Symptom
After #7685 / PR #7975, objectstack verify --rls reaches the #1994 by-id-write class: its probe persona holds object read+edit plus a verifier-authored owner narrowing, so a refusal is attributable to the record gate and the run is falsifiable (ablating the #7665 write-scope derivation turns 16 of 20 probed showcase objects red).
One class is still out of reach, and it is stated in the module header rather than left to be discovered:
an object whose narrowing is authored on a POSITION the probe does not hold is unnarrowed for this persona
The probe holds no positions by design (it must own nothing, so the admin-created target is outside its scope by construction). An app-authored RLS policy carrying positions: [...] is filtered out by getApplicablePolicies for that persona, so the runner never exercises the app's own narrowing — only the platform gate underneath it.
Why it matters
This is the exact authoring shape of the defect the tooling was fixed for. #7665's persona was the ordinary showcase_contributor — a contributor position plus the matching set — and the showcase's narrowing is authored that way:
// examples/app-showcase/src/security/permission-sets.ts
{ name: 'task_own_rows', object: 'showcase_task', operation: 'select', using: 'assignee == current_user.email', positions: ['contributor'] }
{ name: 'invoice_own_rows', object: 'showcase_invoice', operation: 'select', using: 'owner == current_user.email', positions: ['contributor'] }
Measured during PR #7975, with an object-granted but un-narrowed probe (before the verifier-authored owner policy was added): every such object reported member-visible — the probe read every row, so no cross-owner scenario existed and nothing was proven. The current probe covers the platform half by authoring its own narrowing; the app-authored, position-gated half is still unexercised.
Suggested direction (not prescriptive)
The generalization is app-agnostic and derivable from metadata, which is this tool's whole premise: for each position the app declares, provision a persona holding that position (and its bound sets) and run the same invariant. That reproduces #7665's persona exactly, for every app, without the verifier inventing a policy.
Two things to size before doing it:
- Cost. ~4 HTTP calls × objects × positions. The showcase declares 9 positions and 23 objects; today's whole
dogfood-verify job is ~4½ minutes against a 20-minute timeout, so this needs measuring rather than assuming.
- Over-privilege. Some declared positions are bound to VAMA-carrying sets (
showcase_auditor, showcase_ops). Those personas see everything and would report member-visible — correct, but it means the fan-out must report per-position coverage honestly rather than claiming N× the reach.
Both are the reason this was not folded into PR #7975: it is a different-shaped change from the probe fix, and shipping it as a rider would have made that PR's before/after measurement unreadable.
Source
Recorded while executing #7685 item (i) (PR #7975), which cross-links it in the runner's module header. Filed unassigned — recording a finding, not claiming it.
Symptom
After #7685 / PR #7975,
objectstack verify --rlsreaches the #1994 by-id-write class: its probe persona holds object read+edit plus a verifier-authored owner narrowing, so a refusal is attributable to the record gate and the run is falsifiable (ablating the #7665 write-scope derivation turns 16 of 20 probed showcase objects red).One class is still out of reach, and it is stated in the module header rather than left to be discovered:
The probe holds no positions by design (it must own nothing, so the admin-created target is outside its scope by construction). An app-authored RLS policy carrying
positions: [...]is filtered out bygetApplicablePoliciesfor that persona, so the runner never exercises the app's own narrowing — only the platform gate underneath it.Why it matters
This is the exact authoring shape of the defect the tooling was fixed for. #7665's persona was the ordinary
showcase_contributor— acontributorposition plus the matching set — and the showcase's narrowing is authored that way:Measured during PR #7975, with an object-granted but un-narrowed probe (before the verifier-authored owner policy was added): every such object reported
member-visible— the probe read every row, so no cross-owner scenario existed and nothing was proven. The current probe covers the platform half by authoring its own narrowing; the app-authored, position-gated half is still unexercised.Suggested direction (not prescriptive)
The generalization is app-agnostic and derivable from metadata, which is this tool's whole premise: for each position the app declares, provision a persona holding that position (and its bound sets) and run the same invariant. That reproduces #7665's persona exactly, for every app, without the verifier inventing a policy.
Two things to size before doing it:
dogfood-verifyjob is ~4½ minutes against a 20-minute timeout, so this needs measuring rather than assuming.showcase_auditor,showcase_ops). Those personas see everything and would reportmember-visible— correct, but it means the fan-out must report per-position coverage honestly rather than claiming N× the reach.Both are the reason this was not folded into PR #7975: it is a different-shaped change from the probe fix, and shipping it as a rider would have made that PR's before/after measurement unreadable.
Source
Recorded while executing #7685 item (i) (PR #7975), which cross-links it in the runner's module header. Filed unassigned — recording a finding, not claiming it.