§9 prod compose secrets (todo §9); the base compose.yml was already the full prod stack (web + Postgres + Kratos/Keto/Hydra + migrations + bootstrap, no source mount) but set REQUIRE_SECURE_SECRETS=true without ever passing CSRF_SECRET into web, so docker compose -f compose.yml up couldn't boot. Wired CSRF_SECRET: ${CSRF_SECRET:-dev-insecure-csrf-secret} — env-supplied with the throwaway as the only fallback; config.ts's existing REQUIRE_SECURE_SECRETS logic rejects that throwaway so a forgotten prod secret fails loud (verified prod-unset→reject, prod-set→real, dev→throwaway+toggle-off→boots). Used :- not :? because compose interpolates the base per-file before merging the dev override (confirmed empirically), so :? would also break the zero-config dev up. Tests-first: compose.test.ts guards secret-via-env + no-source-mount + prod/dev toggle split + postgres-creds-via-env. README prod section corrected (dropped the stale planned note). typecheck + 310 units green.

This commit is contained in:
2026-06-20 01:05:15 +02:00
parent 56047815a0
commit b3b51db52b
4 changed files with 23 additions and 3 deletions

View File

@@ -6,9 +6,11 @@ services:
ports:
- "3000:3000"
# Explicit behaviour toggles (the app is environment-agnostic — see AGENTS.md).
# Supply CSRF_SECRET via env; REQUIRE_SECURE_SECRETS refuses the dev throwaway.
# Supply CSRF_SECRET via env; the dev-throwaway fallback boots a clean clone but
# REQUIRE_SECURE_SECRETS refuses it in prod (config.ts), so a forgotten secret fails loud.
environment:
CACHE_TEMPLATES: "true"
CSRF_SECRET: ${CSRF_SECRET:-dev-insecure-csrf-secret}
REQUIRE_SECURE_SECRETS: "true"
SECURE_COOKIES: "true" # prod serves https — mark session/CSRF cookies Secure
# Wait for the services the app talks to (kratos + keto + hydra for the §6 OAuth2 login/