From 582136c120a857b3d35151d289ae882134602c70 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Thu, 4 Jun 2026 19:00:19 +0200 Subject: [PATCH] test(06): complete UAT - 8 passed, 0 issues Co-Authored-By: Claude Sonnet 4.6 --- .../06-UAT.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .planning/phases/06-performance-production-hardening/06-UAT.md diff --git a/.planning/phases/06-performance-production-hardening/06-UAT.md b/.planning/phases/06-performance-production-hardening/06-UAT.md new file mode 100644 index 0000000..e96ba2c --- /dev/null +++ b/.planning/phases/06-performance-production-hardening/06-UAT.md @@ -0,0 +1,58 @@ +--- +status: complete +phase: 06-performance-production-hardening +source: 06-01-SUMMARY.md, 06-02-SUMMARY.md, 06-03-SUMMARY.md, 06-04-SUMMARY.md, 06-05-SUMMARY.md +started: 2026-06-04T00:00:00Z +updated: 2026-06-04T19:05:00Z +--- + +## Current Test + +[testing complete] + +## Tests + +### 1. Cold Start Smoke Test +expected: Stop any running services. Run `docker compose up -d --build`. All services (backend, celery-worker, celery-beat, postgres, minio, redis, loki, promtail, grafana) start without errors. `curl -sf http://localhost:8000/health` returns a 200 response. +result: pass + +### 2. X-Correlation-ID response header +expected: Make any authenticated API request (e.g. `curl -si http://localhost:8000/health`). The response headers include `x-correlation-id: `. Make a second request — the header value is different (new UUID per request). +result: pass + +### 3. JSON structured logging +expected: Set LOG_JSON=true in the backend service (or `.env`), restart backend. Then call an endpoint and check `docker compose logs backend`. Log lines should be valid JSON objects containing an "event" key (e.g. `{"event": "...", "level": "info", "correlation_id": "...", ...}`). +result: pass + +### 4. Grafana accessible +expected: After `docker compose up`, navigate to http://localhost:3000 in a browser (or run `curl -sf http://localhost:3000/api/health`). Grafana loads and the health endpoint returns JSON with `"database": "ok"`. +result: pass + +### 5. Loki ready +expected: Run `curl -sf http://localhost:3100/ready`. Response body is `ready` and the command exits 0. +result: pass + +### 6. Container runs as non-root (appuser) +expected: Run `docker compose exec backend id`. Output shows `uid=1000(appuser)` — NOT uid=0 (root). The multi-stage hardened Dockerfile creates appuser with uid=1000. +result: pass + +### 7. Read-only rootfs + writable /tmp +expected: Run `docker compose exec backend sh -c 'touch /readonly_probe 2>&1 || echo "rootfs is read-only"'`. Output contains "read-only". Then run `docker compose exec backend sh -c 'touch /tmp/ok && echo "tmp writable"'`. Output contains "tmp writable" (the tmpfs mount works). +result: pass + +### 8. Per-account rate limiting (429 after 100 req/min) +expected: Log in as a regular user. Send 101+ rapid requests to `GET /api/documents/` (e.g. with a loop or ab/curl). The 101st request (or shortly after) returns HTTP 429 with a rate-limit error. A different user account is NOT affected by the first user hitting the limit. +result: pass + +## Summary + +total: 8 +passed: 8 +issues: 0 +pending: 0 +skipped: 0 +blocked: 0 + +## Gaps + +[none yet]