diff --git a/CHANGELOG.md b/CHANGELOG.md index 03b31ad7..1e04a346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ # Changelog +## Sprint 35 Docker runtime secret hygiene (2026-06-17) + +- Removed embedded PostGIS database name/user/password defaults from `deploy/unraid/Dockerfile.all-in-one` image metadata. +- Kept database credentials as runtime configuration through `.env`, the Unraid template, Compose or `docker run -e`. +- Added regression coverage so `GEOINTEL_POSTGRES_PASSWORD` is not baked into the all-in-one Dockerfile again. +- Updated Unraid runtime documentation to clarify that credentials are runtime config, not image metadata. +- No API contracts, migrations, product features, provider fetching or AI behavior were introduced. + ## Sprint 34 browser-facing golden QA demo hardening (2026-06-17) - Hardened `scripts/verify_demo_export_workflow.sh` so the browser-facing demo/export smoke compares persisted QA/QC metrics against `fixtures/golden/expected_qa_metrics.json`. diff --git a/backend/tests/test_sprint31_unraid_template.py b/backend/tests/test_sprint31_unraid_template.py index aefb65ba..1dff17e7 100644 --- a/backend/tests/test_sprint31_unraid_template.py +++ b/backend/tests/test_sprint31_unraid_template.py @@ -83,6 +83,11 @@ def test_unraid_all_in_one_runtime_starts_embedded_postgis_backend_and_nginx() - assert "python3-venv" in dockerfile assert "COPY --from=frontend-build /frontend/dist/ /usr/share/nginx/html/" in dockerfile assert "rm -f /etc/nginx/sites-enabled/default" in dockerfile + assert "GEOINTEL_POSTGRES_PASSWORD=" not in dockerfile + assert "GEOINTEL_POSTGRES_DB=" not in dockerfile + assert "GEOINTEL_POSTGRES_USER=" not in dockerfile + assert 'GEOINTEL_POSTGRES_PASSWORD="${GEOINTEL_POSTGRES_PASSWORD:-geointel}"' not in start_script + assert 'POSTGRES_PASSWORD="${GEOINTEL_POSTGRES_PASSWORD:-${POSTGRES_PASSWORD:-geointel}}"' in start_script assert 'CMD ["/usr/local/bin/geointel-all-in-one-start"]' in dockerfile assert "/usr/local/bin/docker-entrypoint.sh postgres &" in start_script assert "python -m alembic upgrade head" in start_script diff --git a/deploy/unraid/Dockerfile.all-in-one b/deploy/unraid/Dockerfile.all-in-one index ea7a189f..4da69976 100644 --- a/deploy/unraid/Dockerfile.all-in-one +++ b/deploy/unraid/Dockerfile.all-in-one @@ -12,9 +12,6 @@ ENV GEOINTEL_ENV=production \ GEOINTEL_API_PREFIX=/api/v1 \ GEOINTEL_STORAGE_ROOT=/app/storage \ STORAGE_ROOT=/app/storage \ - GEOINTEL_POSTGRES_DB=geointel \ - GEOINTEL_POSTGRES_USER=geointel \ - GEOINTEL_POSTGRES_PASSWORD=geointel \ GEOINTEL_ALL_IN_ONE=1 \ PATH="/opt/geointel/venv/bin:${PATH}" diff --git a/deploy/unraid/README.md b/deploy/unraid/README.md index 4b9bc0cf..be700c6e 100644 --- a/deploy/unraid/README.md +++ b/deploy/unraid/README.md @@ -78,6 +78,10 @@ bash deploy/unraid/run-dockerman-container.sh The repository deploy scripts run the same flow automatically. They validate the Compose reference, build the image with plain `docker build`, install the DockerMan template/icon, remove any old Compose-owned `geointel` container, preserve/migrate the PostGIS data path and start the final container with DockerMan labels. +Database credentials are runtime configuration, not image metadata. The +all-in-one image does not bake `GEOINTEL_POSTGRES_PASSWORD` into the Dockerfile; +set it through `.env`, the Unraid template or `docker run -e`. + Validate: ```bash diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index ac450b64..6c41e6ea 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -1594,3 +1594,32 @@ Limitations: Next recommended pass: - Run the full release-readiness gate and then rebuild/deploy to Tower for browser-facing verification. + +## Sprint 35 Docker runtime secret hygiene (2026-06-17) + +Changed: +- Removed embedded PostGIS database name/user/password defaults from `deploy/unraid/Dockerfile.all-in-one` image metadata. +- Kept database credentials as runtime configuration supplied by `.env`, the Unraid template, Compose or `docker run -e`. +- Added regression coverage so `GEOINTEL_POSTGRES_PASSWORD` is not baked into the all-in-one Dockerfile again. +- Updated Unraid runtime documentation and changelog. + +Tested: +- `cd backend && python -m pytest tests/test_sprint31_unraid_template.py tests/test_docker_runtime_config.py -q` +- `bash -n deploy/unraid/all-in-one-start.sh` +- `bash -n deploy/unraid/run-dockerman-container.sh` +- `python -m compileall backend/app` +- `cd backend && python -m pytest -W error::DeprecationWarning` +- `cd frontend && npm run typecheck` +- `cd frontend && npm run build` +- `bash scripts/run_readiness_check.sh` +- `cd backend && python -m alembic heads && python -m alembic upgrade head --sql` + +Open: +- Local Windows shell has no `docker` command in PATH, so Docker build/config verification must run on Tower during deploy. +- Rebuild the Tower image and confirm the Docker BuildKit `SecretsUsedInArgOrEnv` warning is gone. + +Limitations: +- The start script still has safe local defaults for standalone/dev startup. Shared deployments should set `GEOINTEL_POSTGRES_PASSWORD` via runtime configuration. + +Next recommended pass: +- Run release readiness, rebuild/deploy Tower and verify browser/GIS/demo smoke again. diff --git a/docs/TODO.md b/docs/TODO.md index 39dac79e..a72fa776 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -12,6 +12,7 @@ This file now starts with the current implementation status. Older preparation/b - [x] Run Docker/PostGIS live validation on Tower/Unraid. - [x] Add Unraid Compose template assets with editable ports, storage path and app icon. - [x] Add single-container Unraid runtime with embedded PostGIS, backend and frontend. +- [x] Remove embedded PostGIS password defaults from all-in-one Docker image metadata. ## Current implementation status