docs(03): finalize phase plan (8 plans, verified)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
phase: 3
|
||||
slug: event-write-back-pwa-install
|
||||
status: draft
|
||||
nyquist_compliant: false
|
||||
nyquist_compliant: true
|
||||
wave_0_complete: false
|
||||
created: 2026-06-05
|
||||
---
|
||||
@@ -10,6 +10,7 @@ created: 2026-06-05
|
||||
# Phase 3 — Validation Strategy
|
||||
|
||||
> Per-phase validation contract for feedback sampling during execution.
|
||||
> Sourced from 03-RESEARCH.md §Validation Architecture.
|
||||
|
||||
---
|
||||
|
||||
@@ -17,28 +18,46 @@ created: 2026-06-05
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Framework** | {pytest 7.x / jest 29.x / vitest / go test / other} |
|
||||
| **Config file** | {path or "none — Wave 0 installs"} |
|
||||
| **Quick run command** | `{quick command}` |
|
||||
| **Full suite command** | `{full command}` |
|
||||
| **Estimated runtime** | ~{N} seconds |
|
||||
| **Framework (API)** | Vitest 4.x, environment: `node` |
|
||||
| **Framework (PWA)** | Vitest 4.x + `jsdom` + `@testing-library/react` |
|
||||
| **Config (API)** | `apps/api/vitest.config.ts` |
|
||||
| **Config (PWA)** | `apps/pwa/vitest.config.ts` |
|
||||
| **Quick run (API)** | `pnpm --filter @familysync/api test` |
|
||||
| **Quick run (PWA)** | `pnpm --filter @familysync/pwa test` |
|
||||
| **Full suite** | `pnpm test` (from repo root — runs both apps) |
|
||||
| **Estimated runtime** | ~20-40 seconds (mocked DB + CalDAV; no network) |
|
||||
|
||||
---
|
||||
|
||||
## Sampling Rate
|
||||
|
||||
- **After every task commit:** Run `{quick run command}`
|
||||
- **After every plan wave:** Run `{full suite command}`
|
||||
- **Before `/gsd-verify-work`:** Full suite must be green
|
||||
- **Max feedback latency:** {N} seconds
|
||||
- **After every task commit:** Run the filtered quick command for the app touched
|
||||
(`pnpm --filter @familysync/api test -- <path>` or `pnpm --filter @familysync/pwa test -- <name>`).
|
||||
- **After every plan wave:** Run `pnpm test` (full suite, both apps).
|
||||
- **Before `/gsd-verify-work`:** Full suite must be green.
|
||||
- **Max feedback latency:** ~40 seconds (full suite).
|
||||
|
||||
---
|
||||
|
||||
## Per-Task Verification Map
|
||||
|
||||
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|
||||
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
|
||||
| {N}-01-01 | 01 | 1 | REQ-{XX} | T-{N}-01 / — | {expected secure behavior or "N/A"} | unit | `{command}` | ✅ / ❌ W0 | ⬜ pending |
|
||||
| Req ID | Behavior | Plan | Wave | Test Type | Automated Command | File Exists | Status |
|
||||
|--------|----------|------|------|-----------|-------------------|-------------|--------|
|
||||
| CAL-04 | `buildVeventString` → VCALENDAR for a timed event (DTSTART UTC) | 02 | 2 | unit | `pnpm --filter @familysync/api test -- broker/vevent` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-04 | `buildVeventString` → all-day event uses DATE not DATETIME (D-13) | 02 | 2 | unit | same | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-04 | POST /api/events/create → 202 + inserts pending outbox row | 03 | 2 | unit (mocked DB) | `pnpm --filter @familysync/api test -- routes/events` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-05 | PATCH /api/events/:uid/edit → 202 + inserts row with etag | 03 | 2 | unit | same | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-06 | DELETE /api/events/:uid → 202 + inserts delete row | 03 | 2 | unit | same | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-07 | `buildVeventString` with `rruleString` → RRULE property | 02 | 2 | unit | `pnpm --filter @familysync/api test -- broker/vevent` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-04/05/06 | Outbox worker: pending→done (204), pending→failed (412), pending→backoff (500), pending→dead (max attempts) | 02/04 | 2 | unit | `pnpm --filter @familysync/api test -- broker/outboxWorker` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-04/05/06 | GET /api/events/sync-status returns outbox status (D-09) | 03 | 2 | unit | `pnpm --filter @familysync/api test -- routes/events` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| CAL-04/05/07 | GET /api/events/writable-calendars returns D-03 set; never another member's read-only personal (V4) | 03 | 2 | unit | `pnpm --filter @familysync/api test -- routes/events` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| D-08 | 412 → conflict (not retry), mark failed, trigger re-sync | 04 | 2 | unit | `pnpm --filter @familysync/api test -- broker/outboxWorker` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| D-04 | Edit-as-move emits DELETE+CREATE pair; create runs first | 04 | 2 | unit | same | ❌ W0 (03-01) | ⬜ pending |
|
||||
| D-03/V4 | create rejects write to non-owned/non-shared calendar (403) | 03 | 2 | unit | `pnpm --filter @familysync/api test -- routes/events` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| PWA-01 | `vite.config.ts` produces valid `manifest.webmanifest` with required fields | 06 | 3 | smoke (build output) | `pnpm --filter @familysync/pwa build` + manifest field check | ❌ W0 (03-01) | ⬜ pending |
|
||||
| PWA-02 | `isIOSSafariNonStandalone()` true on mock iOS Safari non-standalone UA | 06 | 3 | unit | `pnpm --filter @familysync/pwa test -- InstallPrompt` | ❌ W0 (03-01) | ⬜ pending |
|
||||
| PWA-02 | `useAndroidInstallPrompt` sets `canInstall=true` on `beforeinstallprompt` | 06 | 3 | unit (mock event) | same | ❌ W0 (03-01) | ⬜ pending |
|
||||
|
||||
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
|
||||
|
||||
@@ -46,11 +65,16 @@ created: 2026-06-05
|
||||
|
||||
## Wave 0 Requirements
|
||||
|
||||
- [ ] `{tests/test_file.py}` — stubs for REQ-{XX}
|
||||
- [ ] `{tests/conftest.py}` — shared fixtures
|
||||
- [ ] `{framework install}` — if no framework detected
|
||||
The Wave 0 RED test scaffold is created in **plan 03-01 Task 4** (these files import
|
||||
not-yet-existing modules so they fail RED until later waves implement them):
|
||||
|
||||
*If none: "Existing infrastructure covers all phase requirements."*
|
||||
- [ ] `apps/api/tests/broker/vevent.test.ts` — CAL-04, CAL-07 (VEVENT builder, DATE/DATETIME split, RRULE)
|
||||
- [ ] `apps/api/tests/broker/write.test.ts` — tsdav call shapes, etag/If-Match, response interpretation
|
||||
- [ ] `apps/api/tests/broker/outboxWorker.test.ts` — outbox state machine (done/failed/backoff/dead), edit-as-move ordering (D-04/D-07/D-08)
|
||||
- [ ] `apps/api/tests/routes/events.test.ts` — EXTEND existing: POST /create, PATCH /edit, DELETE /:uid, GET /sync-status, GET /writable-calendars, 403 ownership (preserve existing GET /api/events block)
|
||||
- [ ] `apps/pwa/src/components/InstallPrompt.test.tsx` — iOS detection, Android `beforeinstallprompt` capture (PWA-02)
|
||||
|
||||
Existing test files (`broker/sync`, `routes/events` GET block, `auth/devBypass`) remain in place.
|
||||
|
||||
---
|
||||
|
||||
@@ -58,19 +82,18 @@ created: 2026-06-05
|
||||
|
||||
| Behavior | Requirement | Why Manual | Test Instructions |
|
||||
|----------|-------------|------------|-------------------|
|
||||
| {behavior} | REQ-{XX} | {reason} | {steps} |
|
||||
|
||||
*If none: "All phase behaviors have automated verification."*
|
||||
| SW `navigateFallbackDenylist` excludes `/callback` | PWA-01 | Requires a real production build + SW registration over HTTPS | Verify against prod build; confirm `/callback` not intercepted by SW |
|
||||
| iOS standalone PWA login completes without leaving standalone | Gate 2 | Requires a physical iPhone, installed PWA, Authelia OIDC round-trip | Follow `docs/deployment.md` Gate 2 checklist (Plan 07) |
|
||||
|
||||
---
|
||||
|
||||
## 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 < {N}s
|
||||
- [ ] `nyquist_compliant: true` set in frontmatter
|
||||
- [x] All tasks have `<automated>` verify or a Wave 0 RED dependency (created in 03-01 Task 4)
|
||||
- [x] Sampling continuity: no 3 consecutive tasks without automated verify
|
||||
- [x] Wave 0 covers all MISSING references (five RED files in 03-01)
|
||||
- [x] No watch-mode flags
|
||||
- [x] Feedback latency < 40s
|
||||
- [x] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** {pending / approved YYYY-MM-DD}
|
||||
**Approval:** approved 2026-06-05
|
||||
|
||||
Reference in New Issue
Block a user