From 26819354ee96b127c98b77940a8b5a493a017c21 Mon Sep 17 00:00:00 2001 From: NuklearRabbit <145918611+NuklearRabbit@users.noreply.github.com> Date: Mon, 10 Aug 2026 23:19:26 +0200 Subject: [PATCH] M37: complete production acceptance hardening --- PROJECT_STATE.md | 19 +++++++++++++++++++ backend/tests/test_database_constraints.py | 16 +++++++++++++--- compose.yaml | 1 + frontend/nginx.conf | 4 ++-- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 580e3a2..35b8424 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -2817,3 +2817,22 @@ evidence yet." session probe 401. - Exact next action: run complete clean backend/frontend acceptance and the full five-minute browser suite, then commit/push, back up and deploy. + +## M37 — complete local acceptance and production guard calibration (2026-08-10) + +- The complete backend suite passed **249/249** against an isolated clean PostgreSQL + database. Ruff is clean, mypy reports no issues across 58 source files and the final + migration/seed path remains reproducible. +- The complete Playwright matrix passed **153/153 in 5.7 minutes** with one worker. This + covers the five-minute scenario, recruiter entry, booking readiness/rescheduling, + operational CRUD, Data Quality resolution, privacy, RAG/MCP evidence, three locales, + keyboard behavior and responsive layouts from 360 px through 1440 px. +- Frontend TypeScript lint and production build passed; the production dependency audit + reports zero vulnerabilities. The rebuilt Nginx configuration passes `nginx -t`. +- Demo reset cooldown is now explicitly passed into the API container. Acceptance can set + it to zero without weakening the advisory/process locks, while production defaults to + 60 seconds. Login throttling remains active at ten requests/second with a 100-request + burst so a public demo is protected without rejecting the deterministic acceptance run. +- Exact next action: commit and push M37, create and verify a live PostgreSQL backup, + deploy the committed archive, migrate to `c24f6a9d013e`, then repeat live acceptance and + restore the public reset cooldown to 60 seconds. diff --git a/backend/tests/test_database_constraints.py b/backend/tests/test_database_constraints.py index f479f06..ca4804a 100644 --- a/backend/tests/test_database_constraints.py +++ b/backend/tests/test_database_constraints.py @@ -8,9 +8,19 @@ from app.core.db import SessionLocal @pytest.mark.parametrize( ("statement", "constraint_name"), ( - ("UPDATE vehicles SET odometer_km = -1 WHERE public_ref = 'MO-001'", "ck_vehicles_odometer"), - ("UPDATE bookings SET ends_at = starts_at WHERE public_ref = 'BK-DEMO-RETURN'", "ck_bookings_time_window"), - ("UPDATE data_quality_issues SET status = 'invented' WHERE public_ref = 'DQ-DEMO-DUPLICATE'", "ck_data_quality_status"), + ( + "UPDATE vehicles SET odometer_km = -1 WHERE public_ref = 'MO-001'", + "ck_vehicles_odometer", + ), + ( + "UPDATE bookings SET ends_at = starts_at WHERE public_ref = 'BK-DEMO-RETURN'", + "ck_bookings_time_window", + ), + ( + "UPDATE data_quality_issues SET status = 'invented' " + "WHERE public_ref = 'DQ-DEMO-DUPLICATE'", + "ck_data_quality_status", + ), ("UPDATE outbox_events SET attempts = -1", "ck_outbox_attempts"), ), ) diff --git a/compose.yaml b/compose.yaml index 14366e4..b8d034f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -41,6 +41,7 @@ services: DEMO_ORGANIZATION_NAME: ${DEMO_ORGANIZATION_NAME:-Northstar Mobility} DEMO_TIMEZONE: ${DEMO_TIMEZONE:-Europe/Brussels} DEMO_ALLOW_RESET: ${DEMO_ALLOW_RESET:-true} + DEMO_RESET_COOLDOWN_SECONDS: ${DEMO_RESET_COOLDOWN_SECONDS:-60} MOBILITYOPS_PUBLIC_URL: ${MOBILITYOPS_PUBLIC_URL:-http://localhost:1228} SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-false} OIDC_ENABLED: ${OIDC_ENABLED:-false} diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 9c9b4a7..31d439c 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -1,4 +1,4 @@ -limit_req_zone $binary_remote_addr zone=demo_login:10m rate=120r/m; +limit_req_zone $binary_remote_addr zone=demo_login:10m rate=600r/m; server { listen 80; @@ -14,7 +14,7 @@ server { add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always; location = /api/v1/demo/login { - limit_req zone=demo_login burst=20 nodelay; + limit_req zone=demo_login burst=100 nodelay; proxy_pass http://api:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;