docs: record DWH auth implementation evidence
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user