fix(rls): members_update WITH CHECK mirrors USING (D8)

UPDATE policy was USING-only: a privileged caller could mutate a member
row into a space they don't administer (no post-image re-check).
Migration 043 adds the mirrored WITH CHECK. Self column escalation
(space_id/role/status) remains blocked by the trigger (D9). Schema +
DB maps updated.
This commit is contained in:
Moheeb Zara
2026-05-18 18:39:53 -07:00
parent 7b0948ddd6
commit 26e54f1fcb
4 changed files with 29 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
-- =============================================================================
-- 043: space_members UPDATE — add WITH CHECK (defense-in-depth)
-- =============================================================================
-- members_update had only a USING clause: a privileged caller could mutate a
-- member row into a space where they hold no role (cross-space move) because
-- the post-image was never re-checked. Add a WITH CHECK mirroring the USING
-- so the resulting row must still satisfy the same predicate. (Self column
-- escalation -- space_id/role/status -- is separately blocked by the
-- prevent_member_self_role_change trigger; see scripts/044.)
--
-- Idempotent: DROP POLICY IF EXISTS then CREATE.
-- =============================================================================
DROP POLICY IF EXISTS members_update ON public.space_members;
CREATE POLICY members_update ON public.space_members FOR UPDATE
USING (
user_id = auth.uid()
OR public.user_has_role_in_space(auth.uid(), space_id, ARRAY['admin','board','treasurer'])
)
WITH CHECK (
user_id = auth.uid()
OR public.user_has_role_in_space(auth.uid(), space_id, ARRAY['admin','board','treasurer'])
);