docs(phase-14): add validation strategy

This commit is contained in:
lorentz 2026-07-11 12:19:26 -04:00
parent 64b30a623b
commit cd33955417

View file

@ -0,0 +1,76 @@
---
phase: 14
slug: pax8-ui-surface
status: draft
nyquist_compliant: false
wave_0_complete: false
created: 2026-07-11
---
# Phase 14 — Validation Strategy
> Per-phase validation contract for feedback sampling during execution.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | vitest 4.1.5 |
| **Config file** | `vitest.config.ts``test.include: ['lib/**/*.test.ts']` (page components and `app/api/**` route handlers are structurally excluded from `npm test` today) |
| **Quick run command** | `npx tsc --noEmit --pretty` (the only automated gate that actually covers `app/pax8/**` and `app/api/pax8/**`) |
| **Full suite command** | `npm test` (covers `lib/services/analyzer/**`, `lib/services/rmm/**`, `lib/services/b2/**` only — won't exercise this phase's new files unless logic is extracted into `lib/services/`) |
| **Estimated runtime** | ~2 seconds (`npm test`) |
---
## Sampling Rate
- **After every task commit:** Run `npx tsc --noEmit --pretty`
- **After every plan wave:** Run `npm test`
- **Before `/gsd:verify-work`:** Full suite must be green + manual click-through of both tabs (list, drill-down, resolve-with-candidate, resolve-via-manual-search, empty-state for zero-candidate row)
- **Max feedback latency:** ~2 seconds
---
## Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 14-01-01 | 01 | 1 | PAX8-13 | — | Company list renders with subscription/cost data | manual | `npx tsc --noEmit --pretty` (type-check only) | ❌ W0 | ⬜ pending |
| 14-02-01 | 02 | 2 | PAX8-12, PAX8-14 | T-14-01, T-14-02 | Resolve action writes both `pax8_companies` and `pax8_company_match_review`, admin-gated, validates target company exists | unit (if resolve logic extracted to `lib/services/`) or manual | `npx vitest run lib/services/pax8-company-match-resolver.test.ts` (if extracted) | ❌ W0 | ⬜ pending |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
---
## Wave 0 Requirements
- [ ] Decide whether to extract resolve/cost-breakdown SQL into `lib/services/` for unit-test coverage, or accept manual-only verification — matches `device-link-conflicts`'s existing precedent, which also has zero automated tests today
- [ ] If extracted: `lib/services/pax8-company-match-resolver.test.ts` — mock `postgresClient.query`, following `pax8-company-matcher.test.ts`'s existing convention (`vi.mock('@/lib/services/postgres-client', ...)`)
- [ ] No new test framework/config needed — vitest is already configured project-wide
---
## Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| `/pax8` company list renders with cost breakdown | PAX8-13 | Page components are outside vitest's `lib/**/*.test.ts` glob; no test file planned, matching `device-link-conflicts` precedent | Open `/pax8` as an authenticated non-admin user; confirm company rows render with subscription/cost data via DetailModal drill-down |
| Review section shows flagged/ambiguous matches distinctly | PAX8-14 | Same as above — UI rendering, not covered by current test glob | Open the "Needs Review" tab; confirm the 38 known open review rows appear, distinct from the main company list |
| Resolve persists and survives future syncs | PAX8-12 | End-to-end DB + sync-service interaction; covered functionally by unit test only if resolve logic is extracted (see Wave 0) | Resolve a flagged company, confirm `pax8_companies.autotask_company_id` + `pax8_company_match_review.resolved_at` are set, then trigger a manual PAX8 sync and confirm the resolution is not overwritten (`resolved_at IS NOT NULL` rows are excluded from re-scoring per Phase 12's D-05) |
| View/resolve permission split | D-07/D-08 | Requires two distinct authenticated sessions (regular user vs admin) to exercise both branches | As a non-admin authenticated user, confirm `/pax8` view loads but the resolve action is rejected (403/hidden); as admin, confirm resolve succeeds |
---
## Validation Sign-Off
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
- [ ] Wave 0 covers all MISSING references
- [ ] No watch-mode flags
- [ ] Feedback latency < 5s
- [ ] `nyquist_compliant: true` set in frontmatter
**Approval:** pending