Files
familysync/.planning/phases/03-event-write-back-pwa-install/03-DISCUSSION-LOG.md
T

112 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 3: Event Write-Back + PWA Install - Discussion Log
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
**Date:** 2026-06-05
**Phase:** 3-Event Write-Back + PWA Install
**Areas discussed:** Target calendar pick, Write feedback & sync
Areas offered but not selected (left to Claude's discretion): Event form & fields, iOS install onboarding.
---
## Target calendar pick
### Default target calendar for a new event
| Option | Description | Selected |
|--------|-------------|----------|
| Their own personal | New events default to the creator's own personal calendar | |
| Shared Family | Default to the shared Family calendar; personal is opt-out (needs fallback, may not exist) | |
| Remember last-used | Default to whatever calendar they last wrote to, persisted per member | ✓ |
**User's choice:** Remember last-used
**Notes:** Seed/first-time default set to creator's own personal (always exists; shared may not, per D-16).
### Calendar selector visibility
| Option | Description | Selected |
|--------|-------------|----------|
| Only when >1 writable | Hide picker when only one writable calendar exists; show once shared Family exists | ✓ |
| Always show | Always render the selector with default pre-selected | |
**User's choice:** Only when >1 writable
### Move event between calendars on edit
| Option | Description | Selected |
|--------|-------------|----------|
| Lock calendar on edit | Calendar fixed once created; defer cross-calendar move to v1.x | |
| Allow move | Edit may change target calendar (CalDAV delete-old + create-new) | ✓ |
**User's choice:** Allow move
**Notes:** Researcher/planner must handle UID/etag and partial-failure safety.
### Writable calendar set
| Option | Description | Selected |
|--------|-------------|----------|
| Own personal + shared Family | Write to own personal + shared Family; other member's personal is read-only overlay | ✓ |
| Any visible calendar | Allow writing to any aggregated calendar incl. other member's personal | |
**User's choice:** Own personal + shared Family
---
## Write feedback & sync
### How the member sees their own change after save (poll-based cache)
| Option | Description | Selected |
|--------|-------------|----------|
| Optimistic + forced re-sync | Optimistic UI update + background targeted re-sync of that calendar | (evolved into) |
| Forced re-sync, then show | Synchronously re-sync that calendar, then refresh; ~0.51s spinner | ✓ (initial) |
| Wait for poll | Let the ctag poller pick it up next cycle; visibly laggy | |
**User's choice:** Forced re-sync, then show — subsequently evolved (via the failure-handling answer) into optimistic-accept + queued write + re-sync on confirm. Same authoritative-cache guarantee, async instead of blocking.
### Behavior when the CalDAV write fails
| Option | Description | Selected |
|--------|-------------|----------|
| Inline error + retry, keep form | Keep form + input, show inline error, manual retry | |
| Toast + silent rollback | Close form, roll back optimistic change, transient toast | |
**User's choice:** Free-text — "accept the edit, queue it, keep a toast showing it isn't sync'd yet and keep retrying. Transient failures should be short; anything beyond that is a hard fail that won't auto-resolve."
**Notes:** Reframed the save path into an optimistic-accept + queued-write-with-retry model (outbox).
### Edit-conflict (etag mismatch / 412) handling
| Option | Description | Selected |
|--------|-------------|----------|
| Detect + warn, reload latest | If-Match cached etag; on 412 abort, re-sync, warn before retry | ✓ |
| Last-write-wins | No If-Match; overwrite whatever is on Fastmail | |
**User's choice:** Detect + warn, reload latest
### Pending-write queue location
| Option | Description | Selected |
|--------|-------------|----------|
| Server-side outbox (MariaDB) | API persists pending row; backend worker drains with backoff; survives app close | ✓ |
| Client-side queue (PWA) | PWA holds + retries; stops when app closed unless persisted | |
**User's choice:** Server-side outbox (MariaDB)
### Transient vs hard-failure classification
| Option | Description | Selected |
|--------|-------------|----------|
| Backoff transient; fail-fast hard errors | Network/5xx/timeout → bounded backoff; 401/403/400/412 → stop/surface | ✓ |
| Let me refine the thresholds | Operator specifies retry window/backoff/status codes | |
**User's choice:** Backoff transient; fail-fast hard errors (412 routed to the conflict-reload flow)
---
## Claude's Discretion
- Event form & fields (field set, layout) — build into / alongside the reused `EventDetailPopover`.
- Recurrence creation UX (presets vs custom builder) — whole-series only for v1.
- iOS install onboarding (trigger + annotated walkthrough) and Android `beforeinstallprompt`.
- `vite-plugin-pwa` manifest + service worker config (keep SW conservative re: OIDC/iOS login).
- Outbox worker mechanics (interval/trigger, idempotency key, max attempts, dead-letter).
## Deferred Ideas
- Single-occurrence / "this-and-following" recurring edits (CAL-09/CAL-10) — v1.x.
- Writing to the other member's personal calendar — out (read-only overlay in v1).
- SSE-based live sync-state push — after the Phase 4 SSE-over-Pangolin gate; Phase 3 uses polling.