diff --git a/.env.example b/.env.example index 0005541..ec15807 100644 --- a/.env.example +++ b/.env.example @@ -7,7 +7,7 @@ CORS_ORIGINS=https://your-approved-web-origin.example DATA_DIR=/data # Required in production; generate at least 32 random characters outside this file. SESSION_SECRET= -# Optional first-run admin bootstrap. Remove both immediately after provisioning. +# Mandatory for first-run administrator provisioning. Remove both after bootstrap. BOOTSTRAP_ADMIN_EMAIL= BOOTSTRAP_ADMIN_PASSWORD= # Hard safety default; this release has no delivery capability. diff --git a/README.md b/README.md index c75cd84..6cf0bb5 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ curl -fsS http://localhost:8080/healthz docker compose down ``` -Compose passes the optional `BOOTSTRAP_ADMIN_EMAIL` and `BOOTSTRAP_ADMIN_PASSWORD` values to the API. Set both in an untracked `.env` only when provisioning a fresh instance, then remove them and rotate the password after the bootstrap admin is created. No credentials belong in this repository. +Compose passes the one-time `BOOTSTRAP_ADMIN_EMAIL` and `BOOTSTRAP_ADMIN_PASSWORD` values to the API. **Set both before the first startup to create the initial administrator**; if both are blank, no login account is created. Use them only for a fresh instance, then remove them and rotate the password after the bootstrap admin is created. No credentials belong in this repository. Authenticated browser requests use a server-side session cookie; login creates a session and logout invalidates it. The liveness endpoints (`GET /api/v1/health/live` and `GET /healthz`) intentionally remain unauthenticated so Docker, ingress, and monitoring health checks can use them. Authentication is not a substitute for tenant/authorization checks: protected routes must enforce the session and organization boundary server-side. diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 32ed9ab..bc97518 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -1,5 +1,18 @@ # Portable deployment and recovery runbook (Phase 15) +## Initial administrator is mandatory + +Before the **first** API startup, you must choose one administrator-provisioning method. The simplest method is to set both values in the untracked `.env` file: + +```dotenv +BOOTSTRAP_ADMIN_EMAIL=admin@example.com +BOOTSTRAP_ADMIN_PASSWORD= +``` + +These are not application defaults; they are one-time provisioning inputs. If both values are blank, the API starts without creating an administrator and login cannot succeed. Existing users are never overwritten by changing these values later. + +After the first successful login, remove both values from `.env`, restart the API, and rotate the administrator password through the supported account-management process. Never commit or share the password. + ## Configuration Copy `.env.example` to an untracked deployment environment file. Production requires a secret-manager supplied `SESSION_SECRET` of at least 32 characters and refuses `AUTOMATED_OUTREACH_ENABLED=true`. Keep bootstrap credentials one-time only; remove and rotate them after provisioning. Never place secrets in images, Compose YAML, logs, backups, or public web roots.