diff --git a/CLAUDE.md b/CLAUDE.md index 4322458..7418696 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,7 +11,6 @@ FamilySync is a self-hosted, Dockerized family organization hub for a two-person ### Constraints - **Tech stack**: MariaDB for the database — PostgreSQL is not available in the stack -- **Tech stack**: Redis available (optional, for live list sync / push) - **Infrastructure**: Unraid host running Docker + Docker Compose - **Auth**: Authelia (already deployed) + Local Auth — OIDC/OAuth2 for the custom app; all members authenticate through it - **Calendar backend**: Fastmail (paid, existing) is the single source for all calendars via JMAP/CalDAV @@ -50,7 +49,6 @@ FamilySync is a self-hosted, Dockerized family organization hub for a two-person | web-push | 3.6.7 | Server-side VAPID push | Generate VAPID keys, sign and dispatch push messages to browser push services (APNs for iOS, FCM for Android) | | @hono/oidc-auth | 1.8.3 | OIDC session middleware for Hono | Storage-less JWT session cookies; authorization-code + PKCE flow; works with any RFC-compliant OIDC provider including Authelia | | openid-client | 6.8.4 | Low-level OIDC primitives | If `@hono/oidc-auth` proves insufficient (e.g., custom token introspection), use this as the lower-level escape hatch | -| ioredis | 5.11.0 | Redis client | Pub/sub for broadcasting list-change events to SSE connections across Node processes | | zod | 3.24.x | Schema validation | Validate API request bodies and CalDAV event payloads before writing back to Fastmail | | @hono/zod-validator | 0.8.0 | Hono middleware for Zod | Validate request body/query in route handlers with Zod schemas | | @tanstack/react-query | 5.101.0 | Server state + caching | Manages calendar and list data fetching, background refetch, stale-while-revalidate; pairs with SSE for live list updates | @@ -199,7 +197,7 @@ The backend handles two auth paths: local username/password (scrypt + HS256 JWT Calendar data lives exclusively in Fastmail CalDAV. The broker layer (`apps/api/src/broker/`) uses `tsdav` for PROPFIND/REPORT/PUT/DELETE, `ical.js` for VCALENDAR parsing, and `rrule` for server-side recurrence expansion. Writes are enqueued in a `calendarOutbox` table and drained asynchronously every 15 seconds; a ctag-based poller re-syncs calendars every 5 minutes. -Lists are persisted in MariaDB. Live list updates flow over SSE (`text/event-stream`) via an in-process Node.js `EventEmitter`; a 30-second polling fallback is always active. Push notifications (reminders + calendar change alerts) are dispatched via `web-push` (VAPID) to APNs/FCM. Redis is present in the stack but not yet used at runtime (reserved for future multi-process pub/sub). +Lists are persisted in MariaDB. Live list updates flow over SSE (`text/event-stream`) via an in-process Node.js `EventEmitter`; a 30-second polling fallback is always active. Push notifications (reminders + calendar change alerts) are dispatched via `web-push` (VAPID) to APNs/FCM. The PWA uses TanStack Query for all server state (events, lists, user, sync status, auth mode) and Zustand for UI-only state (selected date, open panels, active tab). @@ -221,7 +219,7 @@ familysync/ │ ├── hooks/ # useListSSE, usePushSubscription │ ├── store/ # Zustand stores (calendarStore, listsStore) │ └── sw.ts # Custom Workbox service worker -├── docker-compose.yml # Production stack (api + mariadb + redis) +├── docker-compose.yml # Production stack (api + mariadb) └── docker-compose.dev.yml # Dev overrides ``` diff --git a/README.md b/README.md index 18f6f52..cd17238 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ A self-hosted family organization hub for a two-person household. One color-code - Node.js 22 LTS - pnpm 11.5.1 (`corepack enable pnpm`) -- Docker + Docker Compose (for MariaDB, Redis, and production deployment) +- Docker + Docker Compose (for MariaDB and production deployment) ## Installation @@ -53,7 +53,7 @@ Required environment variables (set in `.env` or your Docker host): ```bash # Start backing services -docker compose -f docker-compose.yml -f docker-compose.dev.yml up mariadb redis +docker compose -f docker-compose.yml -f docker-compose.dev.yml up mariadb # Run migrations pnpm --filter @familysync/api db:migrate @@ -79,8 +79,8 @@ The API listens on port 3000. The PWA build is served separately (Vite `preview` apps/ api/ Hono backend — CalDAV sync, OIDC auth, lists API, push notifications pwa/ React 19 PWA — calendar view, lists UI, service worker -docker-compose.yml Production services (API, MariaDB 11, Redis 7) -docker-compose.dev.yml Dev overrides (bind-mount src/, expose DB/Redis ports) +docker-compose.yml Production services (API, MariaDB 11) +docker-compose.dev.yml Dev overrides (bind-mount src/, expose DB ports) ``` ## Commands @@ -110,7 +110,7 @@ docker-compose.dev.yml Dev overrides (bind-mount src/, expose DB/Redis ports) | Auth | `@hono/oidc-auth` 1.8.3 — authorization code + PKCE against Authelia | | Calendar | tsdav 2.2.2 (CalDAV) + ical.js 2.2.1 against Fastmail | | Push | web-push 3.6.7 (VAPID) | -| Live sync | Server-Sent Events + Redis 7 pub/sub | +| Live sync | Server-Sent Events (in-process EventEmitter) | | Frontend | React 19, Vite 8, vite-plugin-pwa 1.3, TanStack Query 5, Zustand 5 | | Calendar UI | Schedule-X 4.6 | diff --git a/apps/pwa/e2e/README.md b/apps/pwa/e2e/README.md index 18ec683..0733820 100644 --- a/apps/pwa/e2e/README.md +++ b/apps/pwa/e2e/README.md @@ -15,7 +15,6 @@ The stack must include: - API on `:3000` started with `DEV_AUTH_BYPASS=true` (see Security Guardrail below) - PWA dev server on `:5173` (`pnpm --filter @familysync/pwa dev`) - Dev MariaDB on `:3306` (exposed via `docker-compose.dev.yml`) -- Redis on `:6379` **`DEV_AUTH_BYPASS=true` MUST be set in the API's environment BEFORE the API process starts.** The harness cannot inject it at runtime — the API reads the env var once at startup. If the API is running without it, all `/api/*` requests return an auth redirect and every spec fails. diff --git a/apps/pwa/playwright.config.ts b/apps/pwa/playwright.config.ts index 7a194ba..35666f3 100644 --- a/apps/pwa/playwright.config.ts +++ b/apps/pwa/playwright.config.ts @@ -5,7 +5,7 @@ * Auth: DEV_AUTH_BYPASS=true on the API (never storageState — D-01/Pitfall 14) * SW: serviceWorkers: 'block' on all profiles (D-02/Pitfall 15) * baseURL: env-driven PLAYWRIGHT_BASE_URL (D-08/Rule 8) - * webServer: manages Vite only — API+MariaDB+Redis stay compose-managed (D-10) + * webServer: manages Vite only — API+MariaDB stay compose-managed (D-10) * * Run: * pnpm --filter @familysync/pwa test:e2e @@ -63,7 +63,7 @@ export default defineConfig({ }, ], - // D-10: manage Vite only; API+MariaDB+Redis are compose-managed + // D-10: manage Vite only; API+MariaDB are compose-managed // reuseExistingServer: reuse operator's pnpm dev locally; start fresh in CI webServer: { command: 'pnpm --filter @familysync/pwa dev', diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 804fcb9..88b8551 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -248,7 +248,6 @@ routes/setup.ts ──→ db (app_config) | Local auth storage | scrypt PHC hash in `local_credentials.password_hash`; session signed with `LOCAL_SESSION_SECRET` env var | | Push notifications | `web-push` (VAPID) → APNs (iOS) / FCM (Android) | | Live list sync | In-process Node.js `EventEmitter` → SSE (`text/event-stream`) | -| Redis | Present in stack (image: `redis:7-alpine`); not used in current runtime (reserved for future multi-process pub/sub) | | PWA | React 19 + Vite 8 + `vite-plugin-pwa` (Workbox `injectManifest` mode) | | Networking | Pangolin/Newt tunnel — no open ports; split-DNS internal domain | | Deployment | Docker Compose on Unraid; single `api` container serves both the API and the PWA static build | diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 82d0b24..a312df8 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -163,7 +163,7 @@ VAPID_SUBJECT=mailto:admin@example.com ### Local Development (host-side) -The dev Docker Compose override (`docker-compose.dev.yml`) exposes MariaDB on `localhost:3306` and Redis on `localhost:6379`. To run the API and PWA directly on the host: +The dev Docker Compose override (`docker-compose.dev.yml`) exposes MariaDB on `localhost:3306`. To run the API and PWA directly on the host: ```bash # Build the API first (dev script runs compiled output) diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index be8be82..9198982 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -35,7 +35,7 @@ src/ - **Node.js 22 LTS** — the Dockerfile base is `node:22-alpine`; match this locally - **pnpm 11.5.1** — managed via corepack (`corepack enable pnpm`) -- **Docker + Docker Compose** — for MariaDB and Redis in dev +- **Docker + Docker Compose** — for MariaDB in dev - **TypeScript 5.x** — installed per-workspace as a dev dependency ## Local Setup @@ -48,13 +48,13 @@ pnpm install This installs all workspace packages (`apps/api` and `apps/pwa`) in a single pass. -### 2. Start the dev database and Redis +### 2. Start the dev database ```bash -docker compose -f docker-compose.yml -f docker-compose.dev.yml up mariadb redis -d +docker compose -f docker-compose.yml -f docker-compose.dev.yml up mariadb -d ``` -The dev override (`docker-compose.dev.yml`) exposes MariaDB on `localhost:3306` and Redis on `localhost:6379`. +The dev override (`docker-compose.dev.yml`) exposes MariaDB on `localhost:3306`. ### 3. Configure environment variables @@ -238,17 +238,16 @@ Migration files live in `apps/api/src/db/migrations/` and are committed to versi ## Docker Compose Dev Stack ```bash -# Bring up the full dev stack (API in Docker + MariaDB + Redis, with ports exposed) +# Bring up the full dev stack (API in Docker + MariaDB, with ports exposed) docker compose -f docker-compose.yml -f docker-compose.dev.yml up # Bring up only backing services (run API on host for faster iteration) -docker compose -f docker-compose.yml -f docker-compose.dev.yml up mariadb redis -d +docker compose -f docker-compose.yml -f docker-compose.dev.yml up mariadb -d ``` The dev override: - Exposes MariaDB on `localhost:3306` -- Exposes Redis on `localhost:6379` - Mounts `apps/api/src` into the container for live source access - Sets `NODE_ENV=development` diff --git a/docs/GETTING-STARTED.md b/docs/GETTING-STARTED.md index d444c5d..66aeab4 100644 --- a/docs/GETTING-STARTED.md +++ b/docs/GETTING-STARTED.md @@ -12,7 +12,7 @@ This guide walks from a fresh clone to a running local development environment. | ----------------------- | ------------------ | ---------------------------------------------------------------------------------- | | Node.js | `22 LTS` | Matches the `node:22-alpine` base in `apps/api/Dockerfile` | | pnpm | `11.5.1` | Pinned in `package.json` `packageManager` field; enable via `corepack enable pnpm` | -| Docker + Docker Compose | Any recent version | Used to run MariaDB and Redis locally | +| Docker + Docker Compose | Any recent version | Used to run MariaDB locally | **Node version management:** If you use nvm or fnm, install Node 22 LTS and set it as the default before continuing. There is no `.nvmrc` in the repo; the target version comes from the Dockerfile. @@ -72,10 +72,10 @@ Open `.env` and fill in the required values. See [docs/CONFIGURATION.md](CONFIGU ### 5. Start the database services ```bash -docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d mariadb redis +docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d mariadb ``` -This starts MariaDB (bound to `localhost:3306`) and Redis (`localhost:6379`) using the dev override. Wait for MariaDB to pass its health check before proceeding. +This starts MariaDB (bound to `localhost:3306`) using the dev override. Wait for MariaDB to pass its health check before proceeding. ### 6. Run database migrations diff --git a/docs/TESTING.md b/docs/TESTING.md index df4f737..dc875ea 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -89,7 +89,7 @@ pnpm --filter @familysync/pwa test:e2e:ui pnpm --filter @familysync/pwa test:e2e:headed ``` -The `baseURL` is driven by `PLAYWRIGHT_BASE_URL` (default: `http://localhost:5173`). In local mode the config reuses a running Vite dev server; in CI it starts Vite itself. The API, MariaDB, and Redis must already be running via Docker Compose before launching e2e tests locally — see `docs/DEVELOPMENT.md`. +The `baseURL` is driven by `PLAYWRIGHT_BASE_URL` (default: `http://localhost:5173`). In local mode the config reuses a running Vite dev server; in CI it starts Vite itself. The API and MariaDB must already be running via Docker Compose before launching e2e tests locally — see `docs/DEVELOPMENT.md`. ### Type checking (separate from tests — required) diff --git a/docs/deployment.md b/docs/deployment.md index dbdfa7d..4d720ee 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -16,11 +16,10 @@ Self-hosted Docker deployment on Unraid behind Authelia OIDC and a Pangolin/Newt The production compose file brings up three services: -| Service | Image | Purpose | -| --------- | ---------------------------------------------------- | ---------------------------------------------------------- | -| `api` | Built from `apps/api/Dockerfile` target `production` | Hono API + compiled React PWA, listens on port 3000 | -| `mariadb` | `mariadb:11` | Persistent MariaDB database | -| `redis` | `redis:7-alpine` | Present for live list sync (pub/sub); unused until Phase 4 | +| Service | Image | Purpose | +| --------- | ---------------------------------------------------- | --------------------------------------------------- | +| `api` | Built from `apps/api/Dockerfile` target `production` | Hono API + compiled React PWA, listens on port 3000 | +| `mariadb` | `mariadb:11` | Persistent MariaDB database | ---