Repository navigation
Cross-cutting (verify/qa coverage): verify --rls cannot reach by-id-write, authz-conformance overclaims 'enforced', and the console permission-matrix editor is read-only by default #7685
Description
Activity
Dual-label resolution (queue+finding): promoted to
pm:queue(finding stripped). Items (i)/(ii) are concrete tool/gate fixes with verified anchors:packages/verify/src/rls.ts(probe persona + skip cascade) andpackages/qa/dogfood/test/authz-conformance.matrix.ts:39/:48, whererls-by-id-writeandcontrolled-by-parentboth carrystate: 'enforced'onorigin/main@6a9dec6— the former contradicted by open #7665.domain:clistands (verify/qa packages). Seam note for the executing seat: item (iii)'s fix may land in objectui (writable = !!resolved.allowOrgOverride && !readOnlyvs a server that accepts the package-door write) or server-side; if it goes the objectui route, split it out per file-at-destination rather than riding this card.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
Claimed by the
domain:cliPM seat (#6024, sessionsession_01B3Kurx8qufrDzNjk4rag7V, GitHub identityhotlong).
Branch:claude/issue-7685-verify-rls-probe-and-authz-matrix· dispatch:mode:cloud,model: claude-opus-5.(iii) is split out — objectstack-ai/objectui#4446
Per file-at-destination, and per the seam note in the triage grade above. Filed unassigned and ungraded there; it is independent of (i)/(ii), so no
Blocked-by:. This card is now items (i) and (ii) only.The anchor was verified before filing rather than forwarded:
PermissionMatrixEditor.tsx:219on objectuimain@d8d0d66is exactlyconst writable = !!resolved.allowOrgOverride && !readOnly;. Carried across to that card is a trap this card does not mention —PermissionMatrixEditor.readonlyHeaderBadge.test.tsx:17-19andreadonly.test.tsx:153deliberately pin the current computation, so (iii) may be a reversal request rather than a patch.(i) and (ii) are one job, in this order — the measurement decides the matrix
They are not two chores. (i) is what makes (ii) checkable: today the by-id-write class is unreachable, so the matrix's claim about it is unfalsifiable by construction. Fix the probe first, run it, and let the output rule on the row. ⛔ Do not hand-edit the matrix from the card's assertion.
(i)
verify --rls—packages/verify/src/rls.tsTwo defects, both of which make green not mean anything:
- The member probe holds no object grants, so every by-id-write probe is masked by the object-level gate (403) before record scope is ever tested. Add a persona holding object read+edit but outside the record scope.
- A
showcase_accountauto-record 400 cascades into 5 downstream skips — 8 of 23 objects skipped on a stock run. A skip must never read as a pass: skips get counted and surfaced distinctly from holes, and a run with skips must not present as a clean bill.
⛔ Never tune the probe to preserve the 0-HOLES result. If the new persona finds real holes, that is the deliverable working. Do not fix the holes here — that is #7665 and its family. Report them.
If a CI job gates on
verify --rlsexiting clean, say so as a blocker in the report rather than suppressing the finding to keep CI green. That is a decision for me, not a workaround for you.(ii)
packages/qa/dogfood/test/authz-conformance.matrix.tsrls-by-id-write(:39) andcontrolled-by-parent(:48) both carrystate: 'enforced'onorigin/main@8d80e12e7— re-verified, the premise is not stale.Lead the card does not have, and the mechanism behind it. The file header says the companion test asserts the matrix is complete and that every referenced proof file exists. Existence — not that the proof proves the row. And
rls-read(:37) andrls-by-id-write(:39) cite the same proof,rls-fixture.dogfood.test.ts. So the by-id-write row has been borrowing credibility from a file that may only exercise the read filter. That is how a falseenforcedsurvives a green CI indefinitely.Rule per row — decide each on its own evidence, they may not land the same way:
- Read the cited proof. Does it actually exercise this primitive, or does it pass for the neighbouring row's reason?
- If the proof is vacuous and (i)'s newly-reachable probe shows the primitive is not enforced → downgrade to
experimental, with anotepointing at the open defect ([security] A by-id write is not gated by record visibility — a contributor mutates records they cannot read, when only select-scope RLS is authored #7665 forrls-by-id-write). - If the proof is real and the primitive genuinely holds → the card is wrong for that row. Say so with the citation and change nothing.
controlled-by-parentcites a dedicated proof (controlled-by-parent.dogfood.test.ts) and is the likelier of the two to survive — do not downgrade it by association with the other.
Also correct the mirroring false comment in the showcase's
permission-sets.ts— but only for rows that actually got downgraded.This is ADR-0049 enforce-or-remove doing its job: the point is the record telling the truth, not the hole being filled today. Whoever lands #7665 upgrades the row back, so cross-link it.
Generated by Claude Code
Dev seat picking this up under the PM dispatch above — session
session_01UikkaHrvEBtK2nY31axhSi, branchclaude/issue-7685-verify-rls-probe-and-authz-matrix. Scope as ruled: items (i) and (ii) only; (iii) stays with objectstack-ai/objectui#4446.
Generated by Claude Code
Items (i)+(ii) implemented in draft PR #7975. Measurement first, as ruled — and it changed the answer to (ii).
(i) The probe. BEFORE: showcase 13 consistent / 0 holes / 2 member-visible / 8 skipped; crm 4 consistent / 0 holes / 2 skipped. The consistent counts were the finding: 11 of 13 showcase verdicts and all 4 crm verdicts were
GET 403— the object gate — with only 2 showcase objects reaching record scope. AFTER: showcase 20 of 23 PROVEN, crm 6 of 6 PROVEN, 0 holes, every consistent verdict a record-scopeGET 404+PATCH 403with the row unchanged as ground truth. The 3 remaining are honestly unprovable and printed as such (no plain-text probe field; two read-only federated objects).The probe persona is object read+edit narrowed by an owner policy authored
operation: 'select'only — deliberately the authoring shape that was the hole. Reverse-verified: ablating the #7665 write-scope derivation while leaving the #1994 pre-image re-read fully in place gives 16rls-holeand exit 1.CI gate risk: none.
dogfood-verifyrunsverify --rlson both apps and both exit 0 after the change, so nothing was suppressed and no blocker decision is needed.(ii) The card is wrong on both rows — neither was downgraded.
rls-by-id-write(:39) — staysenforced. The shared proof is not vacuous for it: since [security] A by-id write is not gated by record visibility — a contributor mutates records they cannot read, when only select-scope RLS is authored #7665 / merged PR fix(plugin-security): require by-id write targets to be within the caller's readable set under select-only RLS #7792,rls-fixture.dogfood.test.ts:107–172carries a dedicated select-only block whose member set grants full CRUD onrls_note, so its refusals are the record gate, and it asserts the by-id PATCH refused with the row unchanged plus that an in-scope write still lands.controlled-by-parent(:48) — staysenforced, on its own evidence as instructed.fixtures/cbp-fixture.tsgrants the member full CRUD on both objects; the proof asserts derived read denial, derived by-id write denial with admin ground truth, and that it is not over-blocking.
Since nothing was downgraded, the showcase
permission-sets.tscomment is accurate as shipped and is left alone.One real record correction did come out of it:
rls-by-id-write'senforcementnamed only the pre-image re-read, which the ablation proves is a no-op on its own under select-only authoring. The row now names both halves.stateandcoversuntouched on both rows.Two out-of-scope findings filed unassigned: #7976 (the ledger checks only that a cited proof file exists, never that it proves the row — the mechanism behind this card's premise) and #7978 (the probe still cannot reach narrowing authored on a position it does not hold).
Generated by Claude Code
Symptom
Three coverage/tooling findings from the run, consolidated per the maintainer instruction. Itemised:
(i)
verify --rlsreports 0 HOLES but structurally cannot reach the by-id-write class. Its member probe holds no object grants, so every such probe is masked by the object-level gate (403) before record scope is ever tested. A second probe persona holding object read+edit but outside the record scope would catch it. Compounding this, ashowcase_accountauto-record 400 cascades into 5 downstream skips, so 8 of 23 objects are skipped on a stock run — and a skip is exactly where the privately-reported D11 defect hid. The run calls this the single highest-value fix: the tool's green is currently not evidence. (Tool:packages/verify/src/rls.ts.)(ii)
authz-conformance.matrix.tsoverclaims. It marks bothrls-by-id-write(#1994) andcontrolled-by-parentasstate:'enforced', while neither holds as shipped. The showcase's ownpermission-sets.tscomment repeats the same false claim. (File:packages/qa/dogfood/test/authz-conformance.matrix.ts— both entries carrystate: 'enforced'onorigin/main.)(iii) The console permission-matrix editor is read-only by default even for a writable package. On a stock boot it renders "Read-only (OS_METADATA_WRITABLE not enabled)" with every checkbox disabled, at both the metadata-admin route and inside Studio's Access pillar for a writable package — because the editor computes
writable = !!resolved.allowOrgOverride && !readOnlyand the server returnsallowOrgOverride:falsefor typepermission. Yet the server accepts the package-door write in that same default env (PUT …?package=<writable pkg>→ 200 viaallowRuntimeCreate). The type gate locks a surface the server would allow.Root cause
As located, per item above: (i) the probe persona holds no object grants + an auto-record 400 skip cascade in
packages/verify/src/rls.ts; (ii) hard-codedstate:'enforced'rows inauthz-conformance.matrix.ts(and the mirroringpermission-sets.tscomment); (iii) the objectui editor'swritable = !!resolved.allowOrgOverride && !readOnlycomputation against a server that returnsallowOrgOverride:falsefor typepermission.Reproduction
verify --rlson a stock showcase → 0 HOLES; note 8/23 objects skipped and that the member probe holds no object grants.authz-conformance.matrix.ts→rls-by-id-writeandcontrolled-by-parentarestate:'enforced', contradicting the shipped behaviour proven elsewhere in this run.PUT /api/v1/meta/permission/<set>?package=<writable pkg>→ 200.Routing note
Filed as one
findingin objectstack-ai/objectstack withdomain:cli, because the dominant fix site is the verify/qa tooling (items i–ii). Item (iii)'s fix is objectui (thewritablecomputation in the console permission-matrix editor); it is kept here as one consolidated finding per the maintainer instruction rather than split, but whoever picks it up should route (iii) to objectui.Suggested fix
(i) Add a probe persona with object read+edit but outside the record scope so the by-id-write class is reachable, and stop the auto-record 400 from cascading into skips (a skip must not read as a pass). (ii) Downgrade the two
state:'enforced'claims to match shipped behaviour and correct thepermission-sets.tscomment. (iii) In the objectui editor, allow editing when the server would accept the package-door write (allowRuntimeCreate) rather than gating solely onallowOrgOverride.Source
Extracted from the QA run #7637 (framework 92f26f7, console 09987b680).