All PolicyCodex tables live in the Postgres schema codex (never public) in the Supabase project gcfhhymqqlbmomkxrxuj. Direct reads via PostgREST require the headers Accept-Profile: codex (reads) / Content-Profile: codex (writes).

The four invariants

These are enforced by the database itself. Support procedures never work around them.
codex.audit_log rejects UPDATE, DELETE and TRUNCATE via trigger. Each row’s entry_hash = sha256(prev_hash || canonical_json(entry)), computed by a before-insert trigger with a per-org advisory lock. Deleting an org would cascade into the log, so orgs are never truly deleted — they are retired (children removed, husk row + audit rows kept). Verify any export with pnpm verify:audit.
codex.rfc_versions rejects UPDATE. A new revision is a new row. Rows can be deleted (the demo reset uses this), but anything referencing them — statements.extracted_from_version — must be handled first. body_md stores the full composed document, YAML frontmatter block included; the editor re-parses frontmatter from it on save, so a version seeded without the --- block breaks saving.
codex.statements slugs never change once assigned. Re-extraction reuses slugs for materially unchanged statements and marks removed ones status='retired' rather than deleting them. Agents, CI findings and hrefs all key on the slug.
No tenant table ships without an org_id column and a row-level-security policy. The web app reads through RLS with the user’s Clerk JWT; Edge Functions and the worker use the service role but must filter by org explicitly.

Table inventory

Governance core

Enforcement and integrations

Growth

Identity in SQL

  • codex.current_user_id() returns the Clerk user id (user_…) from the JWT sub. auth.uid() is retired — it errors on Clerk tokens (Supabase Auth was fully removed 2026-08-12/13).
  • Plan gating: codex.has_entitlement(org_id, feature) reads org_subscriptions (features like github_scanning, llm_extraction). Feature slugs come from Clerk Billing at webhook time — there is deliberately no hardcoded plan→feature map.

Ad-hoc queries (support)

Use PostgREST with the secret key from .env.local, always filtering by an explicit org id (a bare limit 1 probe once picked the wrong org and caused a zero-row backfill):
Migrations are additive only and applied with supabase db push --db-url "$SUPABASE_DB_URL" — there is no local Docker stack.