-- Bootstrap SQL for local-dev Postgres, applied on FIRST boot only -- (Postgres image runs files in /docker-entrypoint-initdb.d once, -- when the data volume is empty). -- -- Implements the role + schema layout from ADR-0013 (Audit trail, -- separated Postgres schema, append-only by Postgres role grants). -- Production deployment manifests (future infrastructure ADR) will -- replicate the same layout with real service accounts; in dev the -- default `portal` user (created automatically from POSTGRES_USER) -- is the schema owner, and the audit roles are granted to it for -- testing role-based access patterns locally. -- ---------------------------------------------------------------- Audit roles -- NOLOGIN: these are permission containers, not login users. The BFF -- connects as a login user that has been GRANTed the role. CREATE ROLE audit_owner NOLOGIN; CREATE ROLE audit_writer NOLOGIN; CREATE ROLE audit_reader NOLOGIN; CREATE ROLE audit_archiver NOLOGIN; -- ---------------------------------------------------------------- Audit schema -- Owned by audit_owner so DEFAULT PRIVILEGES below take effect for -- every future table created under the schema (Prisma migration etc.). CREATE SCHEMA audit AUTHORIZATION audit_owner; GRANT USAGE ON SCHEMA audit TO audit_writer, audit_reader, audit_archiver; -- ---------------------------------------------------------------- Append-only contract -- ADR-0013 §"Append-only by role grants": -- audit_writer → INSERT only -- audit_reader → SELECT only -- audit_archiver → DELETE only (used to prune past retention) -- nobody → UPDATE, TRUNCATE ALTER DEFAULT PRIVILEGES FOR ROLE audit_owner IN SCHEMA audit GRANT INSERT ON TABLES TO audit_writer; ALTER DEFAULT PRIVILEGES FOR ROLE audit_owner IN SCHEMA audit GRANT SELECT ON TABLES TO audit_reader; ALTER DEFAULT PRIVILEGES FOR ROLE audit_owner IN SCHEMA audit GRANT DELETE ON TABLES TO audit_archiver; -- ---------------------------------------------------------------- Dev convenience -- The default `portal` superuser bypasses these grants anyway, but -- granting the audit roles explicitly lets us test role-based access -- with `SET ROLE audit_writer;` etc. from a psql session against the -- dev DB. Production never grants all four to one user. GRANT audit_owner, audit_writer, audit_reader, audit_archiver TO portal;