docs(03-01): complete foundation-scaffold plan
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
---
|
||||
phase: 03-event-write-back-pwa-install
|
||||
plan: 01
|
||||
subsystem: database, testing, infra
|
||||
tags: [drizzle, mariadb, vitest, vite-plugin-pwa, caldav, outbox]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 02-calendar-read-display
|
||||
provides: calendarEvents table, sync.ts upsert loop, existing test infrastructure
|
||||
|
||||
provides:
|
||||
- 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)
|
||||
|
||||
affects: [03-02, 03-03, 03-04, 03-05, 03-06, 03-07, 03-08]
|
||||
|
||||
# Tech tracking
|
||||
tech-stack:
|
||||
added: [vite-plugin-pwa@1.3.0]
|
||||
patterns:
|
||||
- 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
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- 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
|
||||
modified:
|
||||
- apps/api/src/db/schema.ts
|
||||
- apps/api/src/broker/sync.ts
|
||||
- apps/api/tests/routes/events.test.ts
|
||||
- apps/pwa/package.json
|
||||
|
||||
key-decisions:
|
||||
- "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)."
|
||||
|
||||
patterns-established:
|
||||
- "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"
|
||||
|
||||
requirements-completed: [CAL-04, CAL-05, CAL-06, CAL-07, PWA-01, PWA-02]
|
||||
|
||||
# Metrics
|
||||
duration: ~45min
|
||||
completed: 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-pwa** — `78f0dee` (feat)
|
||||
3. **Task 3: Populate calendarEvents.objectUrl in sync.ts** — `0c0bcef` (feat)
|
||||
4. **Task 4: Wave 0 RED test scaffold** — `bbfccda` (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 1–4 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*
|
||||
Reference in New Issue
Block a user