No homeowner PII, ever
The properties table is schema-locked against owner names, owner mailing addresses, and phone numbers. The TCAD bulk parser drops those fields at parse stage; they never reach the database. A CI test (tests/test_no_owner_pii.sql) blocks any deploy that tries to add one back.
Tenancy isolation via RLS
Every customer-scoped table — subscribers, alerts, territories, webhook deliveries — has Postgres Row Level Security policies that reduce the trust boundary to the database engine itself. A bug in the application layer cannot leak another tenant's data.
Append-only TCPA consent log
Every opt-in is written to an append-only ledger with the exact consent text version, IP, user agent, timestamp, and the phone number consenting. We can produce the exact record any regulator or carrier might ask for, including the consent text shown at the time.
Defense-in-depth synthetic isolation
The 15-minute synthetic monitoring probe is kept out of real customer territories by four independent guards: origin flag on the incident row, geofenced bbox the territory tool refuses to overlap, phone allowlist on the Twilio wrapper, and a routing assertion that quarantines any cross-leak.
Encryption at rest and in transit
All data is encrypted at rest in Supabase (AES-256) and in transit (TLS 1.2+). Static assets are served over HTTPS with HSTS. Database credentials are scoped per environment; no shared service-role keys.
Webhook delivery is signed
Outbound webhooks are signed with HMAC-SHA256 over the request body. Signatures are tied to a rotatable per-destination secret you control. We retry with exponential backoff and surface every delivery attempt in the dashboard.