Status: Compensating controls in place. Scanner findingDocumentation Index
Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
Use this file to discover all available pages before exploring further.
realtime_messages_no_rls ignored by policy.
Last Updated: 2026-04-29
Why we don’t add RLS to realtime.messages
Lovable’s security scanner periodically flags realtime.messages (used by Supabase Realtime to authorize Channel subscriptions) as having no RLS, allowing any authenticated user to subscribe to any channel topic. The literal remediation it proposes — adding RLS policies to realtime.messages — is forbidden by project policy. Modifying any reserved Supabase schema (realtime, auth, storage, vault, supabase_functions) can cause service degradation or outages.
See: workspace AGENTS.md (reserved-schema rule) and mem://constraints/realtime-schema-security-policy.
Compensating controls
- Table-level RLS on every published table. All tables exposed to Realtime via
postgres_changes(hr_employees,pf_messages,ce_sms_messages,pf_conversations,pf_conversation_members,gr_contracts, etc.) have RLS policies that filter byorganization_id. A subscriber from another org receives zero rows, even if they manage to attach to the topic. - Centralized realtime layer (
@/platform/realtime). All client-side Realtime usage is routed throughuseRealtimeSubscription,useRealtimeBroadcast,useRealtimePresence,sendBroadcast, and theChannelManager. Directsupabase.channel(...)calls outside this layer are disallowed (PF-66 migration is complete). - Org-scoped topic names for broadcast and presence.
buildChannelNameautomatically prefixes broadcast and presence channel names withorg:{orgId}:when an org id is available. The hooks (useRealtimeBroadcast,useRealtimePresence) read the active org fromuseCurrentOrganizationId()and stay disabled until it is known. The standalonesendBroadcastutility requires anorganizationIdargument. Result: a user from Org A and a user from Org B subscribing to logical channelhr_eventsare placed on physically distinct topics (org:A:broadcast:hr_eventsvsorg:B:broadcast:hr_events). - DB channels are unprefixed by design.
db:channels rely onpostgres_changesfilters plus table RLS for isolation; renaming them would force a full audit with no security benefit.
Adding a new broadcast or presence channel
- React: use
useRealtimeBroadcast({ channel: 'my_channel', ... })oruseRealtimePresence({ channel: 'my_channel', ... }). The org prefix is applied automatically. - Non-React: call
sendBroadcast(organizationId, 'my_channel', 'event_name', payload). Always thread the active org id through. - Do not call
supabase.channel(...)directly. If you have a use case the platform layer doesn’t cover, extend the platform layer.
Scanner finding handling
The Lovable security findingrealtime_messages_no_rls (scanner: supabase_lov) is marked as ignored with a reference to this document. If the scanner re-raises it after a future scan, re-apply the ignore — do not attempt to add RLS to realtime.messages.
Re-ignore log:
- 2026-04-29 — Finding re-raised by
supabase_lov. Re-ignored; no code or schema changes. Compensating controls verified: org-scoped broadcast/presence topics viabuildChannelName, table-level RLS on all 28 published tables, centralized realtime layer (PF-66).