diff --git a/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-VALIDATION.md b/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-VALIDATION.md new file mode 100644 index 0000000..ad2baf0 --- /dev/null +++ b/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-VALIDATION.md @@ -0,0 +1,80 @@ +--- +phase: 24 +slug: aws-route-53-dns-sync-track-changes-crud-operations-full-aud +status: draft +nyquist_compliant: false +wave_0_complete: false +created: 2026-08-05 +--- + +# Phase 24 — 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` (`include: ['lib/**/*.test.ts']`, `environment: 'node'`) | +| **Quick run command** | `npx vitest run lib/services/route53-sync-service.test.ts` (once created) | +| **Full suite command** | `npm test` | +| **Estimated runtime** | ~10 seconds (small existing suite) | + +--- + +## Sampling Rate + +- **After every task commit:** Run `npx vitest run ` +- **After every plan wave:** Run `npm test` +- **Before `/gsd:verify-work`:** Full suite must be green +- **Max feedback latency:** 15 seconds + +--- + +## Per-Task Verification Map + +| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status | +|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------| +| TBD | TBD | TBD | SC-3/SC-4 (audit + history correctness) | — | `route53_record_history` gets a row with correct `source` tag (pulse_crud vs sync_detected_drift) for CRUD vs. drift | unit | `npx vitest run lib/services/route53-sync-service.test.ts` | ❌ W0 | ⬜ pending | +| TBD | TBD | TBD | D-12 (NS delegation health check) | — | NS-list normalization (case, trailing dot) and mismatch detection classify correctly | unit | `npx vitest run lib/services/integration-health.test.ts` | ❌ W0 | ⬜ pending | +| TBD | TBD | TBD | D-01 (write-type allowlist) | T-24-01 | Server-side rejection of NS/SOA record writes with 400, before constructing `ChangeResourceRecordSetsCommand` | unit | `npx vitest run lib/services/route53-sync-service.test.ts` | ❌ W0 | ⬜ pending | +| TBD | TBD | TBD | SC-2 (CRUD write-back auth gating) | T-24-02 | `requireAdmin()` returns 401/403 for non-admin sessions on write routes | manual / smoke | none automated — matches existing project convention (see `22-VERIFICATION.md` precedent) | ❌ — manual by convention | ⬜ pending | + +*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* + +*Plan/Wave/Task IDs are TBD — the planner has not yet assigned plan numbers. Update this table's Task ID/Plan/Wave columns once `PLAN.md` files exist (or leave for `gsd-plan-checker` to cross-reference against actual plan task IDs).* + +--- + +## Wave 0 Requirements + +- [ ] `lib/services/route53-sync-service.test.ts` — record-set key derivation, before/after diff classification (CREATE/UPSERT/DELETE → history row shape), NS-list normalization +- [ ] `lib/services/integration-health.test.ts` — first test file for any integration's health check; cover the new Route 53 NS-delegation mismatch detection logic (no existing precedent — this is a new test file, not an extension) +- [ ] `lib/services/route53-factory.test.ts` — `isRoute53Configured()` true/false branches (optional, low priority; mirrors that `veeam-factory.ts` has no test file today, but this is the first AWS-credential-shaped factory in the codebase) +- [ ] No framework install needed — vitest is already configured project-wide + +--- + +## Manual-Only Verifications + +| Behavior | Requirement | Why Manual | Test Instructions | +|----------|-------------|------------|--------------------| +| Write-route auth gating (401/403 for non-admin) | SC-2 / D-04 | `requireAdmin()`/`requirePermission()` are Better Auth session-dependent; this codebase has no precedent for testing route auth gating in isolation — historically verified by manual click-through (see `22-VERIFICATION.md`) | Sign in as a `user`-role account, hit `POST /api/route53/records` directly (curl or browser devtools) with a valid record payload, confirm 403. Repeat as `admin` and confirm success. | +| Live AWS write-back round-trip (create/update/delete a real record) | SC-2 | Cannot be safely automated against a real AWS account/hosted zone in CI; requires a real Route 53 zone and live credentials | Using a disposable test record in a real (or sandbox) hosted zone: create via Pulse UI, confirm it appears in the AWS console within the `GetChange` poll window; update it; delete it; confirm `route53_audit_log` has 3 rows with correct before/after values. | +| DNS-egress-in-production assumption (D-12 health check) | D-12 | Whether outbound UDP/53 to public resolvers is permitted from the production container network is unverifiable from the repo (flagged as Open Question 3 in `24-RESEARCH.md`) | Deploy to production/staging, trigger the Route 53 health check, confirm the live NS lookup resolves rather than timing out. If it times out, the health check needs a fallback (DoH) per the research's open question. | + +--- + +## Validation Sign-Off + +- [ ] All tasks have `` 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 < 15s +- [ ] `nyquist_compliant: true` set in frontmatter + +**Approval:** pending