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:
@@ -5,6 +5,7 @@
|
||||
## APIs & External Services
|
||||
|
||||
**CalDAV (Fastmail):**
|
||||
|
||||
- Fastmail CalDAV endpoint - Calendar read/write for all household calendars
|
||||
- SDK/Client: tsdav 2.2.2 (`apps/api/src/broker/client.ts`)
|
||||
- Auth: Basic auth with Fastmail app password (per-member, stored encrypted in `member_credentials` table)
|
||||
@@ -14,6 +15,7 @@
|
||||
- Parse responses via ical.js; expand recurrence with rrule
|
||||
|
||||
**OIDC (Authelia):**
|
||||
|
||||
- Authelia OIDC identity provider - User authentication and session management
|
||||
- SDK/Client: @hono/oidc-auth 1.8.3 (`apps/api/src/auth/middleware.ts`)
|
||||
- Auth method: Authorization-code flow with PKCE (S256 challenge method)
|
||||
@@ -27,6 +29,7 @@
|
||||
## Data Storage
|
||||
|
||||
**Databases:**
|
||||
|
||||
- MariaDB 11 - Primary relational database (required; PostgreSQL not available)
|
||||
- Connection: Environment vars (DB_HOST, DB_PORT 3306, DB_USER, DB_PASSWORD, DB_NAME)
|
||||
- Client: mysql2 3.22.4 (native driver via Drizzle ORM)
|
||||
@@ -37,12 +40,14 @@
|
||||
- Local dev: Docker service `mariadb` with healthcheck; data persisted to `mariadb_data` volume
|
||||
|
||||
**File Storage:**
|
||||
|
||||
- Local filesystem only - PWA static assets built by Vite
|
||||
- Location: Built output copied to `apps/api/dist/public` (Dockerfile pwa-builder stage)
|
||||
- Served by Hono via serveStatic middleware on the same :3000 port
|
||||
- No external cloud storage (S3, GCS, etc.)
|
||||
|
||||
**Caching:**
|
||||
|
||||
- Redis 7-Alpine - Declared in docker-compose.yml but unused in Phase 1
|
||||
- Reserved for Phase 4 live list sync (pub/sub for broadcasting list-change events across Node processes)
|
||||
- Local dev: Docker service `redis` on port 6379
|
||||
@@ -51,6 +56,7 @@
|
||||
## Authentication & Identity
|
||||
|
||||
**Auth Provider:**
|
||||
|
||||
- Authelia (self-hosted, pre-deployed on Unraid host)
|
||||
- Implementation: RFC-compliant OIDC provider
|
||||
- User identity: Composite key of oidc_iss + oidc_sub (never email, per D-10 in schema)
|
||||
@@ -59,6 +65,7 @@
|
||||
- Claims policy: Authelia 4.39+ required for name/email/preferred_username in ID token (otherwise defaults to "Member" display name)
|
||||
|
||||
**Dev Bypass (non-production only):**
|
||||
|
||||
- DEV_AUTH_BYPASS environment variable (NODE_ENV !== 'production')
|
||||
- When enabled: Skips @hono/oidc-auth middleware; injects DEV_USER into context
|
||||
- Allows local development without live Authelia instance
|
||||
@@ -67,14 +74,17 @@
|
||||
## Monitoring & Observability
|
||||
|
||||
**Error Tracking:**
|
||||
|
||||
- Not detected - Errors logged to console; no external service integration
|
||||
|
||||
**Logs:**
|
||||
|
||||
- Console-based - Events logged to stdout/stderr
|
||||
- Backend (Hono): Startup message, CalDAV poller errors (per-credential logging, T-03-04), outbox worker status
|
||||
- Frontend: React error boundaries catch component errors
|
||||
|
||||
**Health Check:**
|
||||
|
||||
- GET /health endpoint (unauthenticated)
|
||||
- Endpoint: `apps/api/src/routes/health.ts`
|
||||
- Used by Docker Compose healthcheck for mariadb service
|
||||
@@ -83,15 +93,18 @@
|
||||
## CI/CD & Deployment
|
||||
|
||||
**Hosting:**
|
||||
|
||||
- Docker on Unraid host (self-hosted)
|
||||
- Container image: Single production image from Dockerfile (API + PWA on port :3000)
|
||||
- Orchestration: Docker Compose (docker-compose.yml + docker-compose.dev.yml overrides)
|
||||
- Environment: Split-DNS internal domain; private IPs internally; external access via Pangolin/Newt tunnel
|
||||
|
||||
**CI Pipeline:**
|
||||
|
||||
- Not detected - No GitHub Actions, GitLab CI, or similar configured
|
||||
|
||||
**Build Output:**
|
||||
|
||||
- Docker multi-stage build:
|
||||
- API: TypeScript compiled to `apps/api/dist/` by tsc
|
||||
- PWA: Vite bundles to `apps/pwa/dist/`; copied to `apps/api/dist/public` in production image
|
||||
@@ -100,6 +113,7 @@
|
||||
## Environment Configuration
|
||||
|
||||
**Required env vars (Backend):**
|
||||
|
||||
- Database: DB_HOST, DB_PORT (default 3306), DB_USER, DB_PASSWORD, DB_NAME, DB_ROOT_PASSWORD
|
||||
- OIDC: OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_REDIRECT_URI, OIDC_AUTH_EXTERNAL_URL (mandatory for Pangolin redirects)
|
||||
- Session: OIDC_AUTH_SECRET (32+ chars for JWT cookie signing)
|
||||
@@ -109,18 +123,21 @@
|
||||
- Dev override: DEV_AUTH_BYPASS (set to 'true' to disable OIDC; dev-only, NODE_ENV !== 'production')
|
||||
|
||||
**Secrets location:**
|
||||
|
||||
- `.env` file (local development) — not committed; pattern documented in docker-compose.yml
|
||||
- Docker Compose environment variables — injected at runtime from `.env` or deployment config
|
||||
- Member app passwords: Encrypted in DB (member_credentials.encryptedPassword) using APP_PASSWORD_ENCRYPTION_KEY
|
||||
- OIDC client secret: Plain text in env var (NOT the pbkdf2 hash from Authelia config)
|
||||
|
||||
**Optional env vars:**
|
||||
|
||||
- OIDC_AUTH_EXTERNAL_URL - MANDATORY behind Pangolin for correct redirect_uri construction (Pitfall 1)
|
||||
- DEV_AUTH_BYPASS - Dev-only; local testing without Authelia
|
||||
|
||||
## Webhooks & Callbacks
|
||||
|
||||
**Incoming:**
|
||||
|
||||
- /callback - OIDC authorization-code exchange endpoint
|
||||
- Mounted in `apps/api/src/index.ts` before oidcAuthMiddleware
|
||||
- Receives POST from Authelia after user login; exchanges code for tokens
|
||||
@@ -128,6 +145,7 @@
|
||||
- Critical: Must not be intercepted by service worker (navigateFallbackDenylist in vite.config.ts)
|
||||
|
||||
**Outgoing:**
|
||||
|
||||
- None detected - No third-party webhooks triggered by the app
|
||||
- Fastmail CalDAV: Changes are POLLED (5-min cron poller), not webhook-driven
|
||||
- List sync (Phase 4): Will use SSE (server-sent events) for client push, not webhooks
|
||||
@@ -135,12 +153,14 @@
|
||||
## Network & Transport
|
||||
|
||||
**HTTPS/TLS:**
|
||||
|
||||
- Mandatory for OIDC flows
|
||||
- Pangolin/Newt tunnel provides HTTPS reverse proxy
|
||||
- Internal domain: Split-DNS routes internal requests directly to private IP
|
||||
- External requests: Routed through Pangolin tunnel
|
||||
|
||||
**Server-Sent Events (SSE):**
|
||||
|
||||
- GET /api/sse/heartbeat - Test endpoint for Pangolin compatibility
|
||||
- Endpoint: `apps/api/src/routes/sse.ts`
|
||||
- Uses Hono's streamSSE helper
|
||||
@@ -148,9 +168,10 @@
|
||||
- Phase 4 will extend this for live list sync
|
||||
|
||||
**CORS:**
|
||||
|
||||
- Credentials: 'include' for all fetch calls (session cookie sent cross-origin in dev proxy)
|
||||
- redirect: 'manual' for /api/me to detect OIDC redirect (prevents fetch hang on cross-origin 302 to Authelia)
|
||||
|
||||
---
|
||||
|
||||
*Integration audit: 2026-06-09*
|
||||
_Integration audit: 2026-06-09_
|
||||
|
||||
Reference in New Issue
Block a user