Split out of #5493 by the maintainer's 2026-08-08 ruling (Q2 = A1: the by-id half ships a verdict-shaped surface; the bulk half is deliberately priced separately — filed here so it cannot sink inside a ruled thread, the #6216-documented failure mode of decision text dying with its issue).
Mechanism (code-read by the #5493 round-2 dev; not yet probed end-to-end)
The bulk write path (update({multi}) / delete({multi})) ANDs SharingService.buildWriteFilter into the query AST. An app-authored RLS update-widener therefore cannot widen the row set there either — the same defect family as #5493, but silent: the statement touches fewer rows than the declaration admits, with no error, no 403, nothing in any envelope. The by-id half at least refuses loudly (FORBIDDEN), which is how HotCRM's sweep caught it; this half is invisible to a status-code sweep by construction.
Relationship to the ruled fix
What acceptance would need (when priced in)
An end-to-end probe first (the mechanism above is a code read): member with an authored update-widener runs update({multi}) spanning admitted-by-declaration rows they don't own → count today vs count declared. Then the design question above.
Filed by the identity seat (PM loop round 2). Routing labels left to the triage seat.
Split out of #5493 by the maintainer's 2026-08-08 ruling (Q2 = A1: the by-id half ships a verdict-shaped surface; the bulk half is deliberately priced separately — filed here so it cannot sink inside a ruled thread, the #6216-documented failure mode of decision text dying with its issue).
Mechanism (code-read by the #5493 round-2 dev; not yet probed end-to-end)
The bulk write path (
update({multi})/delete({multi})) ANDsSharingService.buildWriteFilterinto the query AST. An app-authored RLS update-widener therefore cannot widen the row set there either — the same defect family as #5493, but silent: the statement touches fewer rows than the declaration admits, with no error, no 403, nothing in any envelope. The by-id half at least refuses loudly (FORBIDDEN), which is how HotCRM's sweep caught it; this half is invisible to a status-code sweep by construction.Relationship to the ruled fix
checkAuthoredRowWrite, verdict-shaped, by-id — see ISecurityService gains a fail-closed authored-row-write verdict (contract + plugin-security implementation) — #5493 ruling, step 1 #6735) cannot reach this path: a per-row verdict has no seat in AST composition.FilterCondition, OR-composed into the bulk write filter, pre-image-matched for by-id) was considered and deferred by the ruling: no measured pull (HotCRM's probes are single-record PATCH), and shipping a second composition site ahead of demand is what the startup-focus principle defers. If bulk pull materializes, that decision must specify the bulk composition semantics explicitly in the ruling — not leave them to whoever implements.What acceptance would need (when priced in)
An end-to-end probe first (the mechanism above is a code read): member with an authored update-widener runs
update({multi})spanning admitted-by-declaration rows they don't own → count today vs count declared. Then the design question above.Filed by the identity seat (PM loop round 2). Routing labels left to the triage seat.