Document Type: Standard
Status: Active
Authority: Affiliate Brain (Audience Infrastructure Layer)
Applies To: Audience Engine table protection, event integrity, and derived-state access control
Parent: Audience Events SQL
Version: v1.1
Last Reviewed: 2026-03-15
Purpose
This document defines Row Level Security (RLS) and append-only enforcement for Audience Engine tables.
Its purpose is to:
• prevent event tampering
• preserve audit trail integrity
• allow inserts only for approved actors
• restrict state-table updates to controlled service-role processes
• keep schema protection compatible with MWMS governance standards
Execution remains deferred until approved.
Scope
This standard applies to:
• public.audience_events
• public.audience_state
• RLS configuration for audience event capture
• append-only protection for raw event tables
• derived-state protection for audience state records
• access-control decisions affecting Audience Engine integrity
This document governs database protection rules for Audience Engine event and state tables.
It does not govern:
• event taxonomy by itself
• state-derivation logic by itself
• frontend tracking implementation by itself
• Supabase cron scheduling by itself
• anonymous traffic policy decisions outside this table context
• general MWMS database policy outside Audience Engine scope
Those remain governed by Audience Events SQL, Audience Event Validation Contract, Audience State Derivation Job Spec, and related Audience Engine documents.
Definition / Rules
Assumptions
Supabase is using standard roles:
• anon
• authenticated
• service_role (bypasses RLS)
Public reading of raw events is not required.
audience_state is a derived table and must not be user-editable.
Policy Model
audience_events
• INSERT allowed (controlled)
• SELECT denied by default
• UPDATE denied
• DELETE denied
audience_state
• SELECT allowed only for authenticated user on their own row (optional)
• INSERT denied for anon and authenticated
• UPDATE denied for anon and authenticated
• DELETE denied for anon and authenticated
• service_role only for controlled derivation processes
SQL – Enable RLS and Define Policies
-- ======================================================
-- Enable RLS
-- ======================================================
alter table public.audience_events enable row level security;
alter table public.audience_state enable row level security;-- ======================================================
-- audience_events: append-only enforcement
-- ======================================================-- Deny by default: no select for anon/authenticated
-- (No SELECT policies created = SELECT blocked)-- Allow INSERT for authenticated users (if you capture user_id)
create policy "audience_events_insert_authenticated"
on public.audience_events
for insert
to authenticated
with check (
-- user_id can be null for anonymous sessions, but if present must match auth.uid()
user_id is null or user_id = auth.uid()
);-- Optionally allow INSERT for anon (if you accept anonymous logging)
-- NOTE: Only enable this if you have server-side validation to prevent abuse.
-- create policy "audience_events_insert_anon"
-- on public.audience_events
-- for insert
-- to anon
-- with check (true);-- Explicitly block UPDATE for everyone except service_role (service_role bypasses RLS)
create policy "audience_events_no_update"
on public.audience_events
for update
to anon, authenticated
using (false);-- Explicitly block DELETE for everyone except service_role
create policy "audience_events_no_delete"
on public.audience_events
for delete
to anon, authenticated
using (false);-- ======================================================
-- audience_state: derived table protections
-- ======================================================-- Optional: allow user to read only their own state row
create policy "audience_state_select_own"
on public.audience_state
for select
to authenticated
using (user_id = auth.uid());-- Block inserts/updates/deletes for anon/authenticated (service_role bypasses RLS)
create policy "audience_state_no_insert"
on public.audience_state
for insert
to anon, authenticated
with check (false);create policy "audience_state_no_update"
on public.audience_state
for update
to anon, authenticated
using (false);create policy "audience_state_no_delete"
on public.audience_state
for delete
to anon, authenticated
using (false);
Optional Hard Append-Only Trigger (Extra Safety)
If strict database-level enforcement is desired even for privileged non-service roles, an append-only trigger may be added.
Note: service_role can still bypass by design.
-- ======================================================
-- Append-only trigger (blocks UPDATE/DELETE)
-- ======================================================
create or replace function public.audience_events_append_only()
returns trigger
language plpgsql
as $$
begin
raise exception 'audience_events is append-only: % not permitted', tg_op;
end;
$$;drop trigger if exists trg_audience_events_append_only on public.audience_events;create trigger trg_audience_events_append_only
before update or delete
on public.audience_events
for each row
execute function public.audience_events_append_only();
Operational Notes
If anonymous event capture is required, server-side inserts via Edge Function or WordPress backend using the service_role key are preferred over allowing direct anon inserts.
If anon inserts are enabled, rate limiting and validation must also be implemented.
audience_state should only be updated by controlled processes such as:
• Edge Function
• cron job
• worker process
Drift Protection
The system must block:
• human editing of raw events
• deletion of events
• state inflation via manual edits
• public exposure of raw event table
• anonymous spam without validation
Final Rule
Raw audience events are append-only records, not editable business data.
If event history can be casually changed, Audience Engine intelligence becomes untrustworthy.
Architectural Intent
MWMS – RLS and Append Only Enforcement exists to protect the integrity of Audience Engine data at the database level.
Its role is to ensure that raw event history remains durable, derived state remains controlled, and audience intelligence can be trusted as a governed signal layer rather than a mutable reporting surface.
Change Log
Version: v1.1
Date: 2026-03-15
Author: MWMS HeadOffice / Affiliate Brain
Change: Rebuilt page to align with the locked MWMS document standard for this cleanup pass. Preserved the original purpose, assumptions, policy model, SQL policy definitions, optional append-only trigger, operational notes, and drift-protection intent. Added Document Type, Parent, Scope, Definition / Rules structure, Final Rule, and Architectural Intent sections.
Version: v1.0
Date: 2026-02-25
Author: Affiliate Brain
Change: Initial creation of RLS and append-only enforcement rules for Audience Engine tables.
END – MWMS – RLS AND APPEND ONLY ENFORCEMENT v1.1