docs: record DWH auth implementation evidence

This commit is contained in:
User
2026-08-21 13:34:36 +02:00
parent 0c4ff3750d
commit 7118950416
6 changed files with 807 additions and 322 deletions
+72 -61
View File
@@ -1,79 +1,90 @@
# Task 7 report — deployment contract and user-owned-session cutover
# Task 7 — report
## Scope
## RED
Implemented the deployment contract only. No Supabase migration, portal change, live-stack
restart, session archive, or deletion was run.
- Creato `scripts/test-verify-dwh-auth-docs.sh` con fixture positiva e fixture negative per
credenziale/digest sintetici, TLS insicuro, segreto in env/argv, mode world-readable, cattura
Nginx e coupling Compose.
- Eseguito `bash scripts/test-verify-dwh-auth-docs.sh` prima del verificatore: `case=verifier_missing status=FAIL`.
- `backend/src/config.ts` now makes the session-store deployment mode explicit. `local` is the
default and cannot be publicly exposed. `postgres` requires `AUTH_MODE=upstream`, direct DB
host/name/runtime user, an absolute runtime-password file, `verify-ca` or `verify-full`, and an
absolute CA path.
- `docker-compose.dev.yml` now publishes only loopback ports and explicitly selects local
session storage rooted at `/data/local-home`.
- `deploy/compose.session-server.yaml.example` separates the runtime and one-shot migrator
secrets. The core gets only `session_runtime_password` and the CA; the profile-gated
`session-migrate` service gets only `session_migrator_password` and the CA.
- `deploy/workspaces/server-sessions.yaml.example` binds the runtime repository to the
TLS-verified direct PostgreSQL configuration. The runtime password remains a file reference.
- `docker/cutover-legacy-sessions.sh` archives/checksums exactly three reviewed legacy sessions
and requires an explicit `--delete` rerun before deleting them.
- README, secret guidance, environment examples, and PROJECT_STATE describe the maintenance
sequence, Task 4+5 coordinated rollout, liveness vs storage 503 behavior, and the no-dual-write
rollback rule.
## GREEN
## TDD evidence
- Aggiunti manuali server, client, TLS, runbook PSD, collaudo ed evidenza sanitizzata; collegati
manuali locali/server, setup PSD, guida, indice e nav MkDocs.
- Eseguiti: `bash -n scripts/verify-dwh-auth-docs.sh scripts/test-verify-dwh-auth-docs.sh`,
`bash scripts/test-verify-dwh-auth-docs.sh`, `bash scripts/verify-dwh-auth-docs.sh`,
`bash scripts/test-verify-workspace-install-docs.sh`, `bash scripts/auth-docs-smoke.sh`.
- Tutti gli output finali sono PASS; il nuovo gate esercita una fixture positiva e nove negative.
RED was established with:
## Self-review
```sh
cd backend && npx vitest run test/config.test.ts
```
- Verificati path/owner/mode: registry 2750, lock/record 0640, socket 0660.
- Verificata separazione: chiavi solo `rest_api`; PSD server `postgres_direct`; Mac/remoti REST;
nessun lifecycle Compose per `dwh-auth`.
- Verificati TLS `.it`/SAN, `.com` non coperto, `TLS_CA_FILE`, fingerprint fuori banda, rinnovo e
assenza di bypass.
- Verificati due gate Task 9–10, evidenze solo metadati e nessuna migrazione di sessioni/index/cache legacy.
The new tests failed because `sessionStorage` did not exist and public/local and unauthenticated
server combinations were accepted. After implementing the minimal configuration contract, the
same focused suite passed (7 tests). Updating the existing upstream-health fixture to supply the
now-required server inputs confirmed that `/health` remains an unauthenticated `200` liveness
endpoint under the valid server contract.
## Concern
## Verification
- Nessuna mutazione PSD/Nginx/systemd/registry o lettura di segreti è stata eseguita. I comandi del
runbook restano condizionati alle autorizzazioni separate dei Task 9 e 10.
```text
cd harness && .venv/bin/pytest -q
826 passed, 5 deselected, 67 warnings in 63.01s
cd backend && npx vitest run && npx tsc --noEmit -p . && npm run build
22 files / 215 tests passed; TypeScript check and production build passed
## Review fix — RED/GREEN
cd frontend && npx vitest run && npx tsc -b && npm run build
full Vitest suite, TypeScript build, and Vite production build passed
```
### RED review
The frontend gate retained its pre-existing React-ref/MSW/act warnings and Vite chunk-size warning;
none caused a test or build failure.
- La fixture `sudo nginx -T` ha prodotto il rifiuto `case=sudo_raw_nginx_capture status=FAIL` prima della correzione del gate.
- La fixture header legacy opaco ha prodotto `case=opaque_legacy_header_literal status=FAIL` prima della correzione del gate.
- Dopo avere riallineato le label UI nei manuali, `bash scripts/test-verify-workspace-install-docs.sh` ha prodotto `server-workspace-registry.md: curator flow missing registry rule`: il verifier cercava ancora le due label precedenti. Il test sulla base HEAD e il diff hanno confermato la causa.
Additional static validation passed:
### GREEN review
```text
docker compose config --quiet (base plus copied session-server overlay with temporary empty secrets)
bash -n docker/cutover-legacy-sessions.sh
git diff --check
```
- Il gate DWH ora rifiuta anche header opaco, digest JSON quotato, `export` di API key, `curl --header` e `-H`, `sudo nginx -T`, raw diff e Compose; le mutation fixture coprono label, PSD direct/Mac REST/CA, socket e flag REST.
- Il runbook non prescrive raw diff o dump: solo checker strutturale e secret scan con metadati e PASS/FAIL. Il piano Task 10 adotta la stessa regola.
- Il template `psd-local` resta `rest_api` solo Mac/local/remota; il server PSD Project A resta `postgres_direct` con binding separato. La CA privata e `TLS_CA_FILE` sono obbligatori salvo trust approvato equivalente.
- Le procedure server ora coprono backup manifest protetto, restore, curl config 0600 senza segreto in argv/env/output, Unix 204/401, HTTPS 2xx/401, 503 bounded con trap, journal PASS/FAIL e retention alla disinstallazione.
- Il verifier workspace-install e entrambi i manuali registry usano ora le quattro label effettive: `Validate workspace source`, `Test workspace connections`, `Save entered secrets`, `Forget stored value`.
## Manual gate remaining
### Final verification review
An operator must still choose the three reviewed legacy IDs, materialize real runtime/migrator/CA
secrets, deploy Task 4 and Task 5 together in a maintenance window, apply the one-shot migrator,
and run the documented authenticated smoke. The guarded helper has not been invoked with
`--delete`.
- PASS: `bash scripts/test-verify-dwh-auth-docs.sh`.
- PASS: `bash scripts/verify-dwh-auth-docs.sh`.
- PASS: `bash scripts/test-verify-workspace-install-docs.sh` (fixture complete).
- PASS: `bash scripts/auth-docs-smoke.sh`.
- PASS: `bash -n scripts/verify-dwh-auth-docs.sh scripts/test-verify-dwh-auth-docs.sh` e `git diff --check`.
## P1 correction — migrator TLS validation
### Review concern
The original migrator Compose command interpolated `THT_SESSION_DB_SSLMODE` into its URL without
checking it. `docker/session-migrate.sh` now rejects every value except `verify-ca` and
`verify-full` before reading the password file or building that URL; the Compose service invokes
this helper. `docker/session-migrate.test.sh` first established RED because the helper did not
exist, then verified that `prefer` is rejected before `tht` can run and that `verify-full` reaches
a fake `tht` binary with the expected TLS URL. The helper and test pass `bash -n`; the focused
backend config/health suite remains green, and the base-plus-overlay Compose configuration renders
with temporary empty secret files.
- Nessuna mutazione runtime e nessun segreto reale sono stati letti. I soli comandi server documentati restano soggetti ai gate autorizzativi Task 9 e Task 10.
## Review fix wave 2 — RED/GREEN
### RED wave 2
- Prima della correzione del proxy, `bash scripts/test-dwh-auth-build-contract.sh` ha fallito il contratto di preservazione path e `bash scripts/test-dwh-auth-nginx-integration.sh` ha chiuso con `case=header_and_path_isolation status=FAIL`: il prefisso `/dwh` arrivava a PostgREST invece di essere rimosso.
- Prima delle procedure finali, il gate docs ha rifiutato il path chiave non deterministico e la fixture curl con header legacy opaco ha dato `case=header_file_curl_synthetic status=FAIL` perché il valore non veniva confrontato esattamente.
- Le mutation fixture hanno catturato l'estrazione tar sul registro attivo e i rename non protetti. Dopo l'inasprimento finale del gate, la sorgente ha dato `dwh-auth docs: restore must stage/check then use guarded same-filesystem renames` finché mancava il controllo fail-closed del candidato.
- Il RED finale dello scanner journal è stato `dwh-auth docs: docs/install/dwh-auth-server.md lacks required topic: sys.argv[2:]`: il gate esige la lettura byte-esatta di v1 e legacy e un `journalctl` che fallisca chiuso.
### GREEN wave 2
- Commit `f616aab fix: preserve PostgREST RPC path through DWH proxy`: `proxy_pass` termina con `/`; il contratto e l'integrazione verificano `/dwh/rpc/ping?x` verso `/rpc/ping?x`.
- Il runbook usa un singolo file chiave v1, header file `0600` passati solo con `curl --header @file`, socket 204 dual-key, HTTPS 2xx pre/post per v1 e 401 post-revoca per legacy `legacy-shared`.
- Restore protetto: staging sul filesystem `/var/lib`, check candidato, `mv -T --` guardato per ogni publish/rollback e pre-restore conservato. Backup/manifest restano root-only `0600` su storage cifrato approvato.
- Lo scanner journal esegue `journalctl` in un unico processo Python root, sopprime stderr, controlla return code e bytes esatti di entrambe le chiavi senza emettere journal o segreti; la shell mostra solo PASS/FAIL.
- Il verifier rifiuta `curl --config`, header in argv, raw Nginx/diff, TLS insicuro, segreti env, mode insicuri e Compose. Le fixture mutano path chiave, ID legacy, header/legacy probes, restore, journal, codici HTTPS e label UI.
### Final verification wave 2
- PASS: `bash scripts/test-dwh-auth-build-contract.sh`.
- PASS: `bash scripts/test-dwh-auth-nginx-contract.sh`.
- PASS: `bash scripts/test-dwh-auth-nginx-integration.sh`.
- PASS: `bash scripts/test-verify-dwh-auth-docs.sh` e `bash scripts/verify-dwh-auth-docs.sh`.
- PASS: `bash scripts/test-verify-workspace-install-docs.sh` e `bash scripts/auth-docs-smoke.sh`.
- PASS: `bash -n` sugli otto gate shell e `git diff --check`.
### Review concern wave 2
- Nessuna configurazione protetta, chiave reale, Nginx, systemd o stack PSD è stata letta o mutata. Le procedure privilegiate restano istruzioni condizionate ai Gate 9–10; la verifica degli owner/mode reali è un'attività del rollout autorizzato, non di questo task documentale.