| Finding ID | Milestone | Description | Severity | Status |
|---|---|---|---|---|
| P0-01 | M2 | Offline mode was a stub (IndexedDB + sync queue now implemented) | P0 | ✓ Resolved |
| P0-02 | M3 | Drizzle ORM quotes schema reconciled with database columns | P0 | ✓ Resolved |
| P0-03 | M3 | acceptQuote() wrapped in transaction with FOR UPDATE row lock | P0 | ✓ Resolved |
| P0-04 | M3 | Admin fee default unified: R500 at trigger and application layer | P0 | ✓ Resolved |
| P0-05 | M5 | Support ticket backend implemented (routes, schema, CRUD, email) | P0 | ✓ Resolved |
| P0-06 | M5 | Deployment runbook fully rewritten for Azure (zero AWS references) | P0 | ✓ Resolved |
| P0-07 | M5 | Rate card RLS: company-scoped, no cross-company data leakage | P0 | ✓ Resolved |
| P0-08 | M6 | Backup restore test conducted against Azure PostgreSQL (row count verified) | P0 | ✓ Resolved |
| P0-09 | M6 | Hardcoded password removed; SVG XSS patched; 0 HIGH findings on scan | P0 | ✓ Resolved |
| P0-10 | M7 | Public API wired at /api-v1/ with key auth and rate limiting | P0 | ✓ Resolved |
| P0-11 | M7 | OpenAPI spec covers 4 entities: Surveys, Quotes, Valuations, Risk | P0 | ✓ Resolved |
| P0-12 | M7 | API key hash server-side only (client-side pepper removed) | P0 | ✓ Resolved |
| P1-01 | M1 | Dedicated password reset page (/forgot-password) implemented | P1 | ✓ Resolved |
| P1-02 | M1 | Support role mapping unified across frontend and backend | P1 | ✓ Resolved |
| P1-03 | M2 | TemplateWizard scope confirmed out-of-contract — code removed | P1 | ✓ Resolved |
| P1-04 | M3 | Surveyor markup columns stripped server-side from quote responses | P1 | ✓ Resolved |
| P1-05 | M3 | Quote status column unified (quote_status_enum throughout) | P1 | ✓ Resolved |
| P1-06 | M3 | Surveyor notifications on quote request (template + recipients) | P1 | ✓ Resolved |
| P1-07 | M3 | valuator_id stored in typed column (not JSONB) | P1 | ✓ Resolved |
| P1-08 | M3 | Elite flow sets status to 'assigned' on creation | P1 | ✓ Resolved |
| P1-09 | M4 | SANS date range filter wired in backend (not a UI stub) | P1 | ✓ Resolved |
| P1-10 | M4 | Finance Dashboard built with real KPIs (revenue, margin, insurer table) | P1 | ✓ Resolved |
| P1-11 | M4 | Risk address activity log: table, endpoint, audit trail | P1 | ✓ Resolved |
| P1-12 | M4 | PI expiry Drizzle schema aligned; cron verified against UAT | P1 | ✓ Resolved |
| P1-13 | M4 | SLA breach events wired to notification dispatcher (15-min scheduler) | P1 | ✓ Resolved |
| P1-14 | M6 | Azure Monitor action group: email receivers configured and tested | P1 | ✓ Resolved |
| P1-15 | M7 | hotfix-process.md created (Azure-native, reviewed by DevOps) | P1 | ✓ Resolved |
| P1-16 | M7 | Auth header standardised: Authorization: Bearer across all middleware | P1 | ✓ Resolved |
| P1-17 | M8 | All 7 operational docs rewritten for Azure (zero AWS/Supabase references) | P1 | ✓ Resolved |
| P1-18 | M8 | Standalone TROUBLESHOOTING.md created and reviewed | P1 | ✓ Resolved |
| P1-19 | M8 | Training materials complete — sessions to be scheduled (Tess + Mike Cannon) | P1 | ⚠ Scheduling |
| P1-20 | M8 | Handover index updated to point to handbook/ paths | P1 | ✓ Resolved |
| P2-01–09 | Mixed | All 9 medium findings resolved (favicon, OG image, Yes/No/NA, duplicate routes, dashboard indicators, bulk rollback, KPI queries, role permissions, stale docs) | P2 | ✓ All Resolved |
| Test Scenario | Result | Notes |
|---|---|---|
| Login and role redirect to Admin Dashboard | ✓ Pass | MSAL flow, token validated |
| User management (create, edit, deactivate) | ✓ Pass | All 4 role types created |
| Company management and multi-tenant isolation | ✓ Pass | Cross-company data separation verified |
| Rate card CRUD — company-scoped RLS | ✓ Pass | No cross-company leakage |
| API key management (create, scope, validate) | ✓ Pass | Server-side HMAC only |
| Feature flags and audit logs | ✓ Pass | All authenticated routes logged |
| Password reset flow (end-to-end) | ✓ Pass | Entra self-service reset confirmed |
| Finance Dashboard — Admin view (platform-wide KPIs) | ✓ Pass | Real data; margin calculation verified |
| Azure Monitor alert delivery | ✓ Pass | Email to inbox confirmed on test trigger |
| Support ticket system — admin response flow | ✓ Pass | Full CRUD + email notification |
| Test Scenario | Result | Notes |
|---|---|---|
| Login and redirect to Insurer Dashboard | ✓ Pass | Role-conditional navigation confirmed |
| Create assessment and assign surveyor | ✓ Pass | All 5 sector templates available |
| Request quotes from multiple surveyors | ✓ Pass | Notification dispatched on request |
| View full pricing breakdown (insurer view) | ✓ Pass | Surveyor markup not visible to surveyor |
| Accept quote — race-condition protection | ✓ Pass | FOR UPDATE lock confirmed via concurrent test |
| Quotes at risk dashboard indicator | ✓ Pass | Panel live on Admin Dashboard |
| Elite valuation appointment flow | ✓ Pass | status → assigned on creation |
| Finance report — insurer-scoped data only | ✓ Pass | Role gate: insurer sees own data only |
| SANS date range filter (backend honoured) | ✓ Pass | Verified with date-range query |
| Risk address management and activity log | ✓ Pass | Audit trail captured per status change |
| Test Scenario | Result | Notes |
|---|---|---|
| Login and redirect to Surveyor Surveys list | ✓ Pass | |
| Complete survey — all 22 sections, all question types | ✓ Pass | Yes/No/NA, text, numeric, date, file, rating |
| Offline survey capture (airplane mode) | ✓ Pass | IndexedDB storage; sync on reconnect |
| Autosave every 30 seconds | ✓ Pass | No data loss on session interruption |
| AI SANS compliance review | ✓ Pass | Findings with severity + SANS code refs |
| Survey export (JSON, CSV, HTML/PDF) | ✓ Pass | Answered-only filter working |
| Quote submission — surveyor price only (no markup) | ✓ Pass | Admin fee and surcharge stripped from response |
| Notification on quote request | ✓ Pass | Email + in-app; recipients resolved |
| PI expiry tracking — cron alert | ✓ Pass | piExpiryDate column, Drizzle schema aligned |
| SLA breach notification on overdue quote | ✓ Pass | sla.breach event → dispatcher → email |
| Test Scenario | Result | Notes |
|---|---|---|
| Login and redirect to QC queue | ✓ Pass | |
| Review submitted survey — AI SANS findings visible | ✓ Pass | |
| Approve / request revision on survey | ✓ Pass | Status transitions correctly |
| QC completion notification dispatched | ✓ Pass | |
| QC-scoped data: own queue only | ✓ Pass | Role gate enforced |
| Suite | Tests | Status | Coverage |
|---|---|---|---|
| Unit tests (Vitest) | 187 | ✓ All Passing | Routes, schema, auth middleware, notification dispatcher |
| Integration tests | 89 | ✓ All Passing | Quote lifecycle, survey submission, API key flow, RLS |
| Contract tests (API) | 52 | ✓ All Passing | All public /api-v1/ endpoints vs. OpenAPI spec |
| Concurrent acceptance test | 1 | ✓ Pass | 10 parallel acceptQuote() calls — only 1 succeeds |
| Total | 328 + 1 concurrent | ✓ All Pass |
| Category | Status | Details |
|---|---|---|
| OWASP Top 10 scan | ✓ 0 HIGH findings | Run by Sable (Jude's security specialist) |
| Hardcoded credentials | ✓ Resolved | P0-09: removed. Key Vault references only. |
| SVG XSS vulnerability | ✓ Patched | P0-09: sanitised on upload |
| Cross-tenant data leak (support messages) | ✓ Closed | NEW-03: tenant isolation enforced on GET /:id/messages |
| Client-side API key pepper | ✓ Removed | P0-12: server-side HMAC only |
| Audit logger blind spot (API key auth) | ✓ Fixed | NEW-05: all authenticated routes now produce audit trail |
| Row-level security (RLS) | ✓ All tables | Company-scoped on all user/org data |
| Check | Status | Details |
|---|---|---|
| Production environment live on Azure | ✓ Live | SWA (thankful-sea), Container Apps API, PostgreSQL, ACR |
| SSL certificates valid | ✓ Valid | Cloudflare CDN + HTTPS enforced |
| Automated daily backups | ✓ Configured | Azure PostgreSQL automated backup; retention 35 days |
| Backup restore test | ✓ Tested | P0-08: restored to staging, row count verified |
| Azure Monitor alerting | ✓ Active | P1-14: email receivers configured; test alert delivered |
| Performance baseline (page load) | ✓ Within target | 1.4–2.6s (target: <3s) |
| API response time (p95) | ✓ Within target | 187–445ms (target: <500ms) |
| Deploy pipeline documented and tested | ✓ Operational | scripts/deploy.sh — Azure CLI. GitHub Actions to be decommissioned post sign-off. |
| Item | Milestone | Status | Impact |
|---|---|---|---|
| Training sessions with Mike Cannon's team | M8 | ⚠ Pending scheduling | Training materials complete. Tess to coordinate timing with Mike. |
| M7 formal sign-off (stability period) | M7 | ⚠ Conditional | 0 Critical/High incidents recorded. 2-week observation period per Schedule E §2.7. |