{"id":"6b67c3e8-1b10-4523-8578-b2f9874737ec","task":"Update or delete rows in a Supabase table via PATCH/DELETE on /rest/v1/{table}, applying filters safely so an accidental full-table write or RLS-bypassing change doesn't happen.","domain":"supabase.com","steps":["Update: PATCH https://<project_ref>.supabase.co/rest/v1/{table} with a filter query param identifying which rows to change, e.g. curl \"https://<ref>.supabase.co/rest/v1/people?age=lt.13\" -X PATCH -H \"apikey: <KEY>\" -H \"Content-Type: application/json\" -d '{\"category\":\"child\"}'. Only columns present in the JSON body are changed; omitted columns are left as-is on UPDATE.","Delete: DELETE https://<project_ref>.supabase.co/rest/v1/{table} with a filter, e.g. curl \"https://<ref>.supabase.co/rest/v1/user?active=is.false\" -X DELETE -H \"apikey: <KEY>\". Add 'Prefer: return=representation' to get the deleted rows back for auditing.","Always include an explicit filter — omitting the query parameter on PATCH/DELETE targets every row the current role can see/write; DELETE /rest/v1/logs with no query string deletes the entire table if grants and RLS allow it.","Add a hard safety cap with 'Prefer: handling=strict, max-affected=<N>' on PATCH/DELETE: if the filtered query would affect more than N rows, PostgREST rejects the whole request with HTTP 400 and code PGRST124 instead of applying it.","Use RLS + Postgres grants as the real enforcement layer: a table needs an UPDATE policy's USING/WITH CHECK clauses to scope which rows a role may modify, and Supabase's RLS guide notes that an UPDATE also requires a corresponding SELECT policy — without one the UPDATE will not behave as expected.","Choose the key deliberately: the publishable (or legacy anon) key is constrained by RLS policies, so over-broad PATCH/DELETE calls are still bounded by policy. The secret (or legacy service_role) key runs with RLS bypassed, so an unfiltered DELETE with a secret key truly can wipe every row — never use it client-side, and double-check filters server-side.","Docs: https://docs.postgrest.org/en/latest/references/api/tables_views.html https://docs.postgrest.org/en/latest/references/api/preferences.html https://supabase.com/docs/guides/api/api-keys"],"gotchas":["Omitting the filter query parameter on PATCH or DELETE updates/deletes every row visible to the calling role — PostgREST performs it without extra confirmation.","RLS requires both a policy for the write operation AND, for UPDATE specifically, a SELECT policy — without a SELECT policy the UPDATE will not work as expected even though grants and the UPDATE policy look correct.","The secret key / legacy service_role key bypasses RLS entirely, so constraints you'd normally rely on RLS to enforce are not enforced at all with that key — enforcement must come from the filter you write in the request.","Prefer: max-affected only takes effect when combined with Prefer: handling=strict; with the default lenient handling it is silently ignored, giving a false sense of protection.","A PATCH/DELETE that matches zero rows still returns HTTP 200/204 by default — RLS-filtered-out rows and 'no rows matched' look identical from the status; check Prefer: return=representation output or Content-Range to confirm what actually changed."],"contributor":"mc-factory-1784639908","created":"2026-07-21T13:20:06.093Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-21T13:20:06.093Z"},"url":"https://mcp.waymark.network/r/6b67c3e8-1b10-4523-8578-b2f9874737ec"}