Files
familysync/.planning/phases/03-event-write-back-pwa-install/03-01-SUMMARY.md
T

7.6 KiB
Raw Blame History

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
03-event-write-back-pwa-install 01 database, testing, infra
drizzle
mariadb
vitest
vite-plugin-pwa
caldav
outbox
phase provides
02-calendar-read-display calendarEvents table, sync.ts upsert loop, existing test infrastructure
calendarOutbox table live in MariaDB (calendar_outbox, 3 indexes)
calendarEvents.objectUrl column live in MariaDB (object_url varchar 1024)
vite-plugin-pwa installed in apps/pwa
Five Wave 0 RED test files covering all Phase 3 behaviors (vevent, write, outboxWorker, events routes, InstallPrompt)
03-02
03-03
03-04
03-05
03-06
03-07
03-08
added patterns
vite-plugin-pwa@1.3.0
mysqlEnum for outbox status/operation columns in Drizzle schema
objectUrl stored on calendarEvents from obj.url during sync upsert
Wave 0 RED scaffold
import not-yet-existing modules so test suite fails before implementation
created modified
apps/api/tests/broker/vevent.test.ts
apps/api/tests/broker/write.test.ts
apps/api/tests/broker/outboxWorker.test.ts
apps/pwa/src/components/InstallPrompt.test.tsx
apps/api/src/db/schema.ts
apps/api/src/broker/sync.ts
apps/api/tests/routes/events.test.ts
apps/pwa/package.json
D-Task5-DDL: drizzle-kit push is unsafe on MariaDB 11 with mysql dialect — misreads metadata and schedules truncate on populated tables. Additive DDL (calendar_outbox CREATE + object_url ALTER) was hand-applied and verified. Adopt drizzle-kit generate+migrate workflow before next schema change (tracked in todos/pending/adopt-drizzle-migrations-workflow.md).
Outbox pattern: calendar_outbox table with status enum (pending/done/failed/dead), groupId for edit-as-move pairing, nextAttemptAt for exponential backoff
objectUrl stored from tsdav obj.url on every sync upsert — enables If-Match header on CalDAV update/delete
Wave 0 RED scaffold: all phase test files created before any implementation so GREEN gate is explicit
CAL-04
CAL-05
CAL-06
CAL-07
PWA-01
PWA-02
~45min 2026-06-05

Phase 03 Plan 01: Foundation Scaffold Summary

calendarOutbox table + calendarEvents.objectUrl pushed live to MariaDB, vite-plugin-pwa installed, and five Wave 0 RED test files covering all Phase 3 write-back and PWA behaviors

Performance

  • Duration: ~45 min
  • Started: 2026-06-05T21:18Z
  • Completed: 2026-06-05T22:10Z
  • Tasks: 5 (Tasks 1-5; Task 1 was human-verify gate, Task 5 was human-action gate)
  • Files modified: 8

Accomplishments

  • Extended Drizzle schema with calendarOutbox table (12 columns, 3 indexes: idx_outbox_user_status, idx_outbox_next_attempt, idx_outbox_uid) and calendarEvents.objectUrl column; both live in MariaDB
  • Populated objectUrl: obj.url ?? null in both .values() and .onDuplicateKeyUpdate() blocks of the calendarEvents upsert in sync.ts — enables If-Match writes (D-08)
  • Installed vite-plugin-pwa (legitimacy-gated via Task 1 supply-chain checkpoint T-03-SC)
  • Created five Wave 0 RED test files covering every Phase 3 behavior: VEVENT builder, CalDAV write layer, outbox state machine, events API routes, and PWA InstallPrompt

Task Commits

  1. Task 1: Supply-chain gate T-03-SC — no commit (verification-only checkpoint)
  2. Task 2: Extend Drizzle schema + install vite-plugin-pwa78f0dee (feat)
  3. Task 3: Populate calendarEvents.objectUrl in sync.ts0c0bcef (feat)
  4. Task 4: Wave 0 RED test scaffoldbbfccda (test)
  5. Task 5: Push schema to MariaDB — hand-applied DDL by orchestrator (no code commit; DB verified)

Files Created/Modified

  • apps/api/src/db/schema.ts — added mysqlEnum import, calendarOutbox table definition, groupId column, 3 indexes; added objectUrl column to calendarEvents
  • apps/api/src/broker/sync.ts — set objectUrl: obj.url ?? null in values and onDuplicateKeyUpdate blocks
  • apps/api/tests/broker/vevent.test.ts — RED: VCALENDAR/VEVENT builder tests (timed, all-day D-13, RRULE)
  • apps/api/tests/broker/write.test.ts — RED: createCalendarEvent, updateCalendarEvent (If-Match), deleteCalendarEvent
  • apps/api/tests/broker/outboxWorker.test.ts — RED: outbox state machine (pending→done/failed/backoff/dead), edit-as-move ordering (D-04)
  • apps/api/tests/routes/events.test.ts — extended with POST create, PATCH edit, DELETE, sync-status, writable-calendars, D-03 access control
  • apps/pwa/src/components/InstallPrompt.test.tsx — RED: isIOSSafariNonStandalone(), useAndroidInstallPrompt
  • apps/pwa/package.json — added vite-plugin-pwa dependency

Decisions Made

  • D-Task5-DDL: drizzle-kit push with the mysql dialect against a live MariaDB 11 instance produces a FALSE destructive diff — it misreads MariaDB-11 metadata and schedules truncate table on calendars, calendar_events, and users (503 events at risk). The two genuinely additive statements were hand-applied by the orchestrator and verified. A follow-up todo (.planning/todos/pending/adopt-drizzle-migrations-workflow.md) tracks migrating to drizzle-kit generate + drizzle-kit migrate before any future schema change. No drizzle-kit push should be run against this instance again.

Deviations from Plan

Task 5: drizzle-kit push replaced by hand-applied additive DDL

Category: Orchestrator-resolved deviation (not a Rule 14 auto-fix; resolved by human operator per gate instructions)

  • Found during: Task 5 (blocking human-action gate)
  • Issue: drizzle-kit push with the Drizzle mysql dialect against MariaDB 11 misread database metadata and reported a destructive plan including truncate table on calendars, calendar_events, and users. This is a known incompatibility — drizzle-kit 0.31.10 has no mariadb dialect; the mysql dialect misinterprets MariaDB-11 server metadata.
  • Fix: Orchestrator manually ran only the two additive statements: CREATE TABLE calendar_outbox (...) matching schema.ts exactly, and ALTER TABLE calendar_events ADD COLUMN object_url varchar(1024). Data verified intact (calendars=1, calendar_events=503).
  • Files modified: None (DB DDL only; schema.ts was already correct)
  • Verification: SHOW TABLES LIKE 'calendar_outbox' → 1 row; SHOW COLUMNS FROM calendar_events LIKE 'object_url' → 1 row
  • Follow-up: .planning/todos/pending/adopt-drizzle-migrations-workflow.md created to track migrating to generate+migrate workflow

Total deviations: 1 (Task 5 DDL approach replaced; resolved by operator at the blocking gate) Impact on plan: No scope creep. Schema is correct. Must-haves fully satisfied. Follow-up todo prevents recurrence.

Issues Encountered

None beyond the Task 5 drizzle-kit deviation documented above.

User Setup Required

None — no external service configuration required for this plan. The schema push was a one-time operation handled by the orchestrator at the Task 5 gate.

Next Phase Readiness

  • Wave 0 RED scaffold is in place — plans 03-02 through 03-08 can proceed to GREEN implementation
  • calendarOutbox and calendarEvents.objectUrl are live; outbox worker and write routes can reference them immediately
  • vite-plugin-pwa is installed; PWA manifest configuration (Plan 03-06) can proceed
  • Action before next schema change: Adopt drizzle-kit generate + drizzle-kit migrate (see pending todo) — do NOT run drizzle-kit push again

Phase: 03-event-write-back-pwa-install Completed: 2026-06-05