style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
@@ -3,7 +3,7 @@ phase: 06-ux-polish
plan: 06
type: execute
wave: 2
depends_on: ["06-01", "06-02", "06-03", "06-05"]
depends_on: ['06-01', '06-02', '06-03', '06-05']
files_modified:
- apps/pwa/src/components/EventForm.tsx
- apps/pwa/src/components/SeriesEditPrompt.tsx
@@ -12,31 +12,31 @@ autonomous: false
requirements: []
must_haves:
truths:
- "Scope fence (D-01/D-02): this phase delivers only the six promoted polish items (999.2/3/6/7/8/9); 999.4 reminders/VALARM, 999.5 provider setup, and 999.1 provider abstraction are NOT built here (deferred to milestone 1.1)"
- 'Scope fence (D-01/D-02): this phase delivers only the six promoted polish items (999.2/3/6/7/8/9); 999.4 reminders/VALARM, 999.5 provider setup, and 999.1 provider abstraction are NOT built here (deferred to milestone 1.1)'
- "Moving an event's start moves its end with it, preserving duration; the end never strands behind the start (D-03/D-04, success criterion 2)"
- "A recurring event can be bounded in the form via 'Ends: Never / On date / After N times' (D-06, success criterion 2)"
- "Editing a recurring occurrence prompts 'Edit recurring series' before saving the whole-series change (D-08/D-09, success criterion 3)"
- "The all-day-edit off-by-one stays fixed — re-editing an all-day event does not grow it by a day (D-05 verify, success criterion 2)"
- "All-day events are visually distinct from timed events at a glance (999.6/D-12, success criterion 1)"
- 'The all-day-edit off-by-one stays fixed — re-editing an all-day event does not grow it by a day (D-05 verify, success criterion 2)'
- 'All-day events are visually distinct from timed events at a glance (999.6/D-12, success criterion 1)'
artifacts:
- path: "apps/pwa/src/components/EventForm.tsx"
provides: "start onChange handlers that call computeNewTimedEnd/computeNewAllDayEnd; recurrence-bound control; hasRrule-gated series-edit confirmation"
contains: "computeNewTimedEnd"
- path: "apps/pwa/src/components/SeriesEditPrompt.tsx"
provides: "whole-series edit confirmation sheet/dialog (focus trap, Escape=cancel)"
contains: "Update series"
- path: "apps/pwa/src/styles/index.css"
provides: "Schedule-X all-day chip override (full-width filled pill)"
contains: "sx__all-day-event"
- path: 'apps/pwa/src/components/EventForm.tsx'
provides: 'start onChange handlers that call computeNewTimedEnd/computeNewAllDayEnd; recurrence-bound control; hasRrule-gated series-edit confirmation'
contains: 'computeNewTimedEnd'
- path: 'apps/pwa/src/components/SeriesEditPrompt.tsx'
provides: 'whole-series edit confirmation sheet/dialog (focus trap, Escape=cancel)'
contains: 'Update series'
- path: 'apps/pwa/src/styles/index.css'
provides: 'Schedule-X all-day chip override (full-width filled pill)'
contains: 'sx__all-day-event'
key_links:
- from: "apps/pwa/src/components/EventForm.tsx"
to: "apps/pwa/src/lib/eventDateTime.ts"
via: "start onChange → computeNewTimedEnd / computeNewAllDayEnd"
pattern: "computeNewTimedEnd|computeNewAllDayEnd"
- from: "apps/pwa/src/components/EventForm.tsx"
to: "apps/pwa/src/api/client.ts"
via: "payload carries recurrenceUntil/recurrenceCount; occurrence.hasRrule gates the prompt"
pattern: "recurrenceUntil|recurrenceCount|hasRrule"
- from: 'apps/pwa/src/components/EventForm.tsx'
to: 'apps/pwa/src/lib/eventDateTime.ts'
via: 'start onChange → computeNewTimedEnd / computeNewAllDayEnd'
pattern: 'computeNewTimedEnd|computeNewAllDayEnd'
- from: 'apps/pwa/src/components/EventForm.tsx'
to: 'apps/pwa/src/api/client.ts'
via: 'payload carries recurrenceUntil/recurrenceCount; occurrence.hasRrule gates the prompt'
pattern: 'recurrenceUntil|recurrenceCount|hasRrule'
---
<objective>
@@ -67,12 +67,13 @@ Output: EventForm end-tracking handlers + recurrence-bound control + series-edit
<artifacts_this_plan_produces>
NEW symbols introduced here (exclude from drift/convergence checks):
- Start `onChange` handlers in `EventForm.tsx` that call `computeNewTimedEnd`/`computeNewAllDayEnd`
- `recurrenceBound: 'never'|'until'|'count'`, `recurrenceUntil: string`, `recurrenceCount: number` state + the "Ends" control in `EventForm.tsx`
- `SeriesEditPrompt` component (`apps/pwa/src/components/SeriesEditPrompt.tsx`)
- `.sx__all-day-event` CSS override block in `apps/pwa/src/styles/index.css`
NOTE: `computeNewTimedEnd`, `computeNewAllDayEnd`, `recurrenceUntil`/`recurrenceCount` payload fields, and `hasRrule` are NOT new here — they are consumed from Plans 01/05.
</artifacts_this_plan_produces>
NOTE: `computeNewTimedEnd`, `computeNewAllDayEnd`, `recurrenceUntil`/`recurrenceCount` payload fields, and `hasRrule` are NOT new here — they are consumed from Plans 01/05.
</artifacts_this_plan_produces>
<tasks>
@@ -193,21 +194,23 @@ NOTE: `computeNewTimedEnd`, `computeNewAllDayEnd`, `recurrenceUntil`/`recurrence
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Boundary | Description |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| client → API (PATCH /api/events/:uid/edit) | Whole-series edit PUTs the master VEVENT back to Fastmail; the new `recurrenceUntil`/`recurrenceCount` cross here (validated server-side in Plan 02). |
| user input → form state | Recurrence bound date/count are user inputs shaped in the form before submit. |
| user input → form state | Recurrence bound date/count are user inputs shaped in the form before submit. |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-06-06-input | Tampering | recurrence bound inputs (EventForm) | mitigate | Form-side validation (count ≥ 1, until ≥ start) plus the authoritative server-side Zod validation from Plan 02 (`recurrenceUntil` max-10, `recurrenceCount` int≥1) — the client check is UX, the server check is the enforcement boundary. Defense in depth; no raw passthrough. (ASVS V5.) |
| T-06-06-series | Tampering | whole-series edit PUT (EventForm → existing /edit route) | mitigate | Reuses the existing edit route's ownership + objectUrl/etag lookup (unchanged from Phase 3) — the prompt only gates the UX; it adds no new privilege. The PUT replaces the master VEVENT for the caller's own event only; access scope is the existing per-user filter. |
| T-06-06-xss | Tampering / XSS | all-day pill label, prompt copy | accept | All-day labels and prompt text render as plain-text JSX children (existing EventForm XSS posture, T-03-15) — no `dangerouslySetInnerHTML`; the CSS override sets presentation only. No new injection surface. |
| T-06-06-SC | Tampering | npm installs | accept | No package installs (zero new deps). |
| Threat ID | Category | Component | Disposition | Mitigation Plan |
| -------------- | --------------- | -------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| T-06-06-input | Tampering | recurrence bound inputs (EventForm) | mitigate | Form-side validation (count ≥ 1, until ≥ start) plus the authoritative server-side Zod validation from Plan 02 (`recurrenceUntil` max-10, `recurrenceCount` int≥1) — the client check is UX, the server check is the enforcement boundary. Defense in depth; no raw passthrough. (ASVS V5.) |
| T-06-06-series | Tampering | whole-series edit PUT (EventForm → existing /edit route) | mitigate | Reuses the existing edit route's ownership + objectUrl/etag lookup (unchanged from Phase 3) — the prompt only gates the UX; it adds no new privilege. The PUT replaces the master VEVENT for the caller's own event only; access scope is the existing per-user filter. |
| T-06-06-xss | Tampering / XSS | all-day pill label, prompt copy | accept | All-day labels and prompt text render as plain-text JSX children (existing EventForm XSS posture, T-03-15) — no `dangerouslySetInnerHTML`; the CSS override sets presentation only. No new injection surface. |
| T-06-06-SC | Tampering | npm installs | accept | No package installs (zero new deps). |
</threat_model>
<verification>
@@ -218,12 +221,13 @@ NOTE: `computeNewTimedEnd`, `computeNewAllDayEnd`, `recurrenceUntil`/`recurrence
</verification>
<success_criteria>
- D-03/D-04 (criterion 2): end follows start with a floor.
- D-06 (criterion 2): recurrence is boundable; D-07: FREQ persists.
- D-08/D-09 (criterion 3): whole-series edit behind a confirmation prompt.
- D-05 (criterion 2): all-day edit off-by-one stays fixed.
- 999.6/D-12 (criterion 1): all-day events visually distinct.
</success_criteria>
</success_criteria>
<output>
Create `.planning/phases/06-ux-polish/06-06-SUMMARY.md` when done (note playwright-cli observations for each behavior).