feat(deploy): db-init one-shot service — paste-and-go bootstrap for the runtime role

The role split previously required a one-time manual script run on
existing volumes (initdb.d only fires on fresh ones). This folds the
bootstrap into the compose file the way split-account deployments
standardly do it: a one-shot db-init service runs z_rls_role.sh
(idempotent, network mode via PGHOST=db + PGPASSWORD from DBPASS) on
every 'compose up', and the app gates on
db-init: condition: service_completed_successfully.

- Zero manual steps for fresh AND existing deployments: update compose,
  add DBSRVPASS to .env, 'compose pull && up -d'.
- Security posture improves: the superuser password is now held ONLY by
  the init service — the app container connects exclusively as the
  non-superuser runtime role.
- z_rls_role.sh gains dual connection modes (local socket for docker
  exec, network for the init service) with the DBPASS requirement
  enforced only in network mode.
- Verified on the dev stack: init runs and exits clean, app gates on it
  and comes up healthy, second 'up' re-converges idempotently, invariant
  test passes through the new dependency chain.

The initdb.d mount stays as-is (harmless double coverage on fresh
volumes; both paths are idempotent).
This commit is contained in:
John O'Keefe committed 2026-10-29 11:17:42 -04:00
1 parent 1457dc7289
commit 313268a7ae
3 files changed
+41 -13

No files matched your search

+2 -3
View File
@@ -13,9 +13,8 @@ DBPASS=your-secure-database-password-here
# Runtime database role password (bookhoard_srv — the non-superuser
# account the app connects as; subject to RLS). Required for the app to
# start. On a fresh volume it is consumed by database/schema/z_rls_role.sh
# during first initialization; on an existing volume, run that script once
# (see its header) BEFORE starting the app with DATABASE_USER=bookhoard_srv.
# start. Consumed by the one-shot db-init service on every startup
# (idempotent — creates/refreshes the role and its privileges).
# Generate with: openssl rand -hex 16
DBSRVPASS=your-secure-runtime-role-password-here