C1 (Critical): the profiles_update RLS policy gates only on user_id,
leaving account_role/account_id — the source of truth for
is_account_member() — freely writable by the row's own user. A
browser-client UPDATE could self-promote a viewer to owner or move
into another tenant. Add a BEFORE UPDATE trigger that rejects changes
to those columns when current_user = 'authenticated'; the SECURITY
DEFINER member/invitation RPCs (postgres) and the service_role backend
are unaffected.
H2 (High): match_ai_knowledge_fts/_semantic were SECURITY DEFINER,
filtered only on the caller-supplied p_account_id with no membership
check, and were granted to authenticated — letting any logged-in user
read another account's knowledge base via a foreign p_account_id.
Recreate both as SECURITY INVOKER so the existing
ai_knowledge_chunks_select RLS policy applies; the service_role
auto-reply bot still bypasses RLS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>