Skip to content

SCRUM-241 — Deploy: admin_auth database provisioning

Plan ref: OPS-2 (docs/11-admin-plane-plan.md).

What exists

Piece Notes
deploy/postgres/init/01-provision.sh now idempotent: roles created if missing, else ALTER ROLE … PASSWORD (converge to .env); databases created if missing; grants re-applied. Adds role admin_auth_rw owning database admin_auth, CONNECT revoked from PUBLIC
deploy/scripts/provision-upgrade.sh for hosts whose data directory already exists: runs the same file inside the running postgres container. Passwords come from the container's own environment (never on the command line); run up.sh first so the container has the current .env
generate-secrets.sh new hosts get ADMIN_AUTH_RW_PASSWORD; an existing .env without it gets one added, nothing else touched
compose.yaml, .env.example, README the new key; an "existing host" section
deploy/scripts/test-provision.sh throwaway local cluster: fresh, rerun, pre-241 → upgrade, isolation

Order on an existing host: generate-secrets.sh → up.sh → provision-upgrade.sh. (The shared test VM still runs the hand-built stack; this applies after the cutover, SCRUM-244, which needs the team's sign-off.)

How to verify

cd deploy
export PATH=$HOME/pgroot/usr/lib/postgresql/16/bin:$PATH \
  LD_LIBRARY_PATH=$HOME/pgroot/usr/lib/x86_64-linux-gnu:$HOME/pgroot/usr/lib/postgresql/16/lib
sh scripts/test-provision.sh

Results at time of writing

  • test-provision.sh: PASS — fresh cluster, second run creates nothing, pre-SCRUM-241 cluster gains admin_auth/admin_auth_rw with the others untouched, admin_auth_rw owns its DB (table + citext), cannot reach config; config_rw cannot reach admin_auth; patch_ro still reads config.
  • sh -n on every script. (No docker on the dev box; the in-container path is the same file the test runs.)

How it was built

DeepSeek run scoped (Landlock) to deploy (144 s, ~26k output tokens, reasoning effort low). Claude review: provision-upgrade.sh passed every role password as a docker compose exec -e KEY=value argument, visible in the host's process list; it now relies on the container's environment and checks .env for missing keys.