- Add calendarEvents.hasRrule boolean + idx_calendar_events_has_rrule index (Phase 2 pre-filter)
- Add calendars.isShared boolean for shared-family calendar identification
- Create apps/pwa/vitest.config.ts with jsdom environment
- Add vitest, @testing-library/react, jsdom, @testing-library/jest-dom to PWA devDependencies
- Add "test": "vitest run" script to apps/pwa/package.json
- Create three ICS fixtures: weekly-dst.ics (DST spanning), allday-birthday.ics, exdate-series.ics
- Create RED test stub expand.test.ts with concrete DST wall-clock assertions (10:00 local both sides of March 2026 boundary)
- Create RED test stub events.test.ts with 400 validation and color/isShared field contracts
- Create RED test stub hydrateEvents.test.ts with Temporal type and calendarId routing contracts (shared→"shared", personal→String(ownerUserId))
- Create RED test stub calendarConfig.test.ts with firstDayOfWeek 0→7 translation contract
- 5 tests: skip on unchanged ctag, sync on changed ctag, first-sync (null ctag), decrypt failure handled, all credentials processed
- Mocks db.select, createFastmailClient, syncCalendar, decryptPassword at module level
- RED gate: all fail (src/broker/poller.ts does not exist yet)
- Use separate mock functions for insert/select chain to enable per-test assertions
- Reset mock implementations in beforeEach after vi.clearAllMocks
- Mock returns {id:42} from select (calendar ID for event upsert)
- 6 tests: all-day DATE vs timed TIMESTAMP, allDay flag, upsert on dup UID, rawVevent blob, ctag update
- Mocks db singleton at module level with vi.mock hoisting pattern
- Uses SAMPLE_VEVENT_TIMED/ALLDAY fixtures from tests/helpers/db.ts
- RED gate: all fail (src/broker/sync.ts does not exist yet)
- 5 tests covering roundtrip, IV uniqueness, tamper detection, payload shape
- Dynamic import with env key set in beforeAll for module-level KEY eval
- RED gate: all fail (src/broker/crypto.ts does not exist yet)
- Replace it.todo stubs with real failing tests (RED gate)
- Tests cover palette[0] first user, palette[1] second user, idempotent
re-upsert, iss+sub identity key, full row shape
- Tests fail: src/auth/user.ts does not exist yet