6. Storage in the product's Postgres, `access` schema, NOTIFY for invalidation
Tables live in an access schema in the product's own database.
Decision
Tables live in an access schema in the product's own database: permissions (catalog), roles (soft-deleted, is_system, break_glass), role_permissions, assignments (revoked, never deleted; validity window), group_mappings, change_log (append-only, enforced by triggers), schema_migrations. Triggers publish access_changed with {org, user?}; listeners invalidate caches.
Consequences
- No extra service to run besides the Cerbos sidecar; backups and transactions are the product's.
- Admin writes and their change log entries commit together; per-org advisory locks serialise them (last-admin checks rely on it).
- A dropped listener connection clears the whole cache; the TTL (60 s) bounds staleness if no listener runs.
5. Our own plan-to-SQL translator, identical in Go and TS
sqlfilter.Translate (Go) and planToSql / drizzleFilter (TS) translate exactly the operators generated policies produce (and, or, not, comparisons, in, startsWith/endsWith/contains, null checks),...
7. No escalation; `access.delegation:any` for administrators
Granting or revoking needs the actor to cover every effective grant (global covers all; self needs self or global; prefix needs the same scope with the target inside the actor's path; set needs...