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
+50 -48
View File
@@ -1,4 +1,5 @@
<!-- generated-by: gsd-doc-writer -->
# FamilySync — Configuration Reference
All runtime configuration is supplied via environment variables. There are no JSON or YAML config files beyond Docker Compose. Copy `.env.example` to `.env` at the repo root and fill in the values before starting any service.
@@ -9,14 +10,14 @@ All runtime configuration is supplied via environment variables. There are no JS
### Database
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `DB_HOST` | Yes | `localhost` | MariaDB hostname. Use `mariadb` inside Docker Compose; use `localhost` (or `127.0.0.1`) for host-side dev runs. |
| `DB_PORT` | No | `3306` | MariaDB port. |
| `DB_USER` | No | `familysync` | Database user. |
| `DB_PASSWORD` | **Required** | _(none)_ | Database password. Also used by the `mariadb` service as `MARIADB_PASSWORD`. |
| `DB_NAME` | No | `familysync` | Database name. |
| `DB_ROOT_PASSWORD` | **Required** | _(none)_ | MariaDB root password. Used only by the `mariadb` Docker service (`MARIADB_ROOT_PASSWORD`). Not read by the API process. |
| Variable | Required | Default | Description |
| ------------------ | ------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `DB_HOST` | Yes | `localhost` | MariaDB hostname. Use `mariadb` inside Docker Compose; use `localhost` (or `127.0.0.1`) for host-side dev runs. |
| `DB_PORT` | No | `3306` | MariaDB port. |
| `DB_USER` | No | `familysync` | Database user. |
| `DB_PASSWORD` | **Required** | _(none)_ | Database password. Also used by the `mariadb` service as `MARIADB_PASSWORD`. |
| `DB_NAME` | No | `familysync` | Database name. |
| `DB_ROOT_PASSWORD` | **Required** | _(none)_ | MariaDB root password. Used only by the `mariadb` Docker service (`MARIADB_ROOT_PASSWORD`). Not read by the API process. |
Five of these variables — `DB_HOST`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`, `DB_PORT` — are read by `drizzle.config.ts` when running migrations (`db:generate` / `db:migrate`) and by the API process to build its connection pool. `DB_ROOT_PASSWORD` is **not** read by either; it is consumed only by the `mariadb` Docker service.
@@ -26,21 +27,22 @@ Five of these variables — `DB_HOST`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`, `DB_
### OIDC / Authelia Authentication
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `OIDC_AUTH_SECRET` | **Required** | `placeholder_change_me` (Docker default) | 32+ character random string used to sign the `oidc-auth` session JWT cookie. Generate with `openssl rand -base64 32`. |
| `OIDC_ISSUER` | **Required** | _(none)_ | Authelia base URL, e.g. `https://auth.DOMAIN`. The middleware fetches `/.well-known/openid-configuration` from this URL. |
| `OIDC_CLIENT_ID` | No | `familysync` | Registered client ID in Authelia. |
| `OIDC_CLIENT_SECRET` | **Required** | _(none)_ | Plaintext client secret matching the pbkdf2 hash stored in Authelia's `configuration.yml`. Do **not** use the hash here. |
| `OIDC_REDIRECT_URI` | **Required** | _(none)_ | Full callback URL registered in Authelia, e.g. `https://familysync.DOMAIN/callback`. |
| `OIDC_AUTH_EXTERNAL_URL` | **Required** | _(none)_ | Public-facing base URL of the app, e.g. `https://familysync.DOMAIN`. **Mandatory behind the Pangolin/Newt tunnel.** Without it, `@hono/oidc-auth` builds the redirect URI from the internal container hostname, which will not match the registered URI and breaks the OIDC flow. |
| `OIDC_SCOPES` | No | `openid profile email offline_access` | Space-separated list of OIDC scopes to request. `offline_access` is required for refresh-token session persistence. Authelia rejects unknown scopes, so do not add scopes that are not configured on the Authelia client. |
| `OIDC_AUTH_EXPIRES` | No | `86400` | Session cookie `Max-Age` in seconds (default 1 day). Governs the persistent session cookie set by `persistSessionCookie` middleware. |
| `OIDC_COOKIE_NAME` | No | `oidc-auth` | Name of the session cookie. Override only if you need to run multiple instances under the same domain. |
| `OIDC_COOKIE_PATH` | No | `/` | Cookie `Path` attribute. |
| `OIDC_COOKIE_DOMAIN` | No | _(not set)_ | Cookie `Domain` attribute. Set this when the API and PWA are served from different subdomains under the same apex domain. Must match the Authelia and app domains (same-parent-domain requirement). |
| Variable | Required | Default | Description |
| ------------------------ | ------------ | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OIDC_AUTH_SECRET` | **Required** | `placeholder_change_me` (Docker default) | 32+ character random string used to sign the `oidc-auth` session JWT cookie. Generate with `openssl rand -base64 32`. |
| `OIDC_ISSUER` | **Required** | _(none)_ | Authelia base URL, e.g. `https://auth.DOMAIN`. The middleware fetches `/.well-known/openid-configuration` from this URL. |
| `OIDC_CLIENT_ID` | No | `familysync` | Registered client ID in Authelia. |
| `OIDC_CLIENT_SECRET` | **Required** | _(none)_ | Plaintext client secret matching the pbkdf2 hash stored in Authelia's `configuration.yml`. Do **not** use the hash here. |
| `OIDC_REDIRECT_URI` | **Required** | _(none)_ | Full callback URL registered in Authelia, e.g. `https://familysync.DOMAIN/callback`. |
| `OIDC_AUTH_EXTERNAL_URL` | **Required** | _(none)_ | Public-facing base URL of the app, e.g. `https://familysync.DOMAIN`. **Mandatory behind the Pangolin/Newt tunnel.** Without it, `@hono/oidc-auth` builds the redirect URI from the internal container hostname, which will not match the registered URI and breaks the OIDC flow. |
| `OIDC_SCOPES` | No | `openid profile email offline_access` | Space-separated list of OIDC scopes to request. `offline_access` is required for refresh-token session persistence. Authelia rejects unknown scopes, so do not add scopes that are not configured on the Authelia client. |
| `OIDC_AUTH_EXPIRES` | No | `86400` | Session cookie `Max-Age` in seconds (default 1 day). Governs the persistent session cookie set by `persistSessionCookie` middleware. |
| `OIDC_COOKIE_NAME` | No | `oidc-auth` | Name of the session cookie. Override only if you need to run multiple instances under the same domain. |
| `OIDC_COOKIE_PATH` | No | `/` | Cookie `Path` attribute. |
| `OIDC_COOKIE_DOMAIN` | No | _(not set)_ | Cookie `Domain` attribute. Set this when the API and PWA are served from different subdomains under the same apex domain. Must match the Authelia and app domains (same-parent-domain requirement). |
**Locked Authelia client parameters** (these are fixed by the project; do not change):
- `response_types: [code]`
- `grant_types: [authorization_code, refresh_token]`
- `require_pkce: true`, `pkce_challenge_method: S256`
@@ -50,21 +52,21 @@ Five of these variables — `DB_HOST`, `DB_USER`, `DB_PASSWORD`, `DB_NAME`, `DB_
### Broker Encryption
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| Variable | Required | Default | Description |
| ----------------------------- | ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `APP_PASSWORD_ENCRYPTION_KEY` | **Required** | _(none)_ | 64-character hex string (32 bytes) used as the AES-256-GCM key for encrypting Fastmail app passwords at rest. Generate with: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`. Startup throws if this is missing or the wrong length. |
---
### Web Push (VAPID)
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `VAPID_PUBLIC_KEY` | No* | _(none)_ | URL-safe base64 VAPID public key. Served to the PWA via `GET /api/push/vapid-public-key`. Non-secret. |
| `VAPID_PRIVATE_KEY` | No* | _(none)_ | URL-safe base64 VAPID private key. Used server-side to sign push requests. **Never expose to clients.** |
| `VAPID_SUBJECT` | No* | _(none)_ | Contact URI identifying the operator, e.g. `mailto:admin@example.com` or `https://familysync.DOMAIN`. Must be a `mailto:` or `https:` URL. |
| Variable | Required | Default | Description |
| ------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `VAPID_PUBLIC_KEY` | No\* | _(none)_ | URL-safe base64 VAPID public key. Served to the PWA via `GET /api/push/vapid-public-key`. Non-secret. |
| `VAPID_PRIVATE_KEY` | No\* | _(none)_ | URL-safe base64 VAPID private key. Used server-side to sign push requests. **Never expose to clients.** |
| `VAPID_SUBJECT` | No\* | _(none)_ | Contact URI identifying the operator, e.g. `mailto:admin@example.com` or `https://familysync.DOMAIN`. Must be a `mailto:` or `https:` URL. |
*All three VAPID variables are optional in the sense that the server starts without them, but push notifications will not function. A startup warning is logged if any are missing. Generate a key pair with:
\*All three VAPID variables are optional in the sense that the server starts without them, but push notifications will not function. A startup warning is logged if any are missing. Generate a key pair with:
```bash
npx web-push generate-vapid-keys --json
@@ -74,10 +76,10 @@ npx web-push generate-vapid-keys --json
### Runtime Mode
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `NODE_ENV` | No | _(not set)_ | Set to `production` in the production Docker Compose. When `production`, the dev-auth bypass is unconditionally disabled regardless of `DEV_AUTH_BYPASS`. |
| `DEV_AUTH_BYPASS` | No | _(not set)_ | Set to `true` to bypass OIDC authentication for local development without a live Authelia instance. **Only active when `NODE_ENV !== 'production'`.** The production `docker-compose.yml` must never include this variable. |
| Variable | Required | Default | Description |
| ----------------- | -------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NODE_ENV` | No | _(not set)_ | Set to `production` in the production Docker Compose. When `production`, the dev-auth bypass is unconditionally disabled regardless of `DEV_AUTH_BYPASS`. |
| `DEV_AUTH_BYPASS` | No | _(not set)_ | Set to `true` to bypass OIDC authentication for local development without a live Authelia instance. **Only active when `NODE_ENV !== 'production'`.** The production `docker-compose.yml` must never include this variable. |
---
@@ -85,17 +87,17 @@ npx web-push generate-vapid-keys --json
Variables with non-empty defaults do not cause startup failure if absent, but should be reviewed for production:
| Variable | Default | Source |
|----------|---------|--------|
| `DB_HOST` | `localhost` | `apps/api/src/db/client.ts` |
| `DB_PORT` | `3306` | `apps/api/src/db/client.ts` |
| `DB_USER` | `familysync` | `apps/api/src/db/client.ts` |
| `DB_NAME` | `familysync` | `apps/api/src/db/client.ts` |
| `OIDC_CLIENT_ID` | `familysync` | `docker-compose.yml` |
| `OIDC_SCOPES` | `openid profile email offline_access` | `docker-compose.yml` |
| `OIDC_AUTH_EXPIRES` | `86400` | `apps/api/src/auth/persistSessionCookie.ts` |
| `OIDC_COOKIE_NAME` | `oidc-auth` | `apps/api/src/auth/persistSessionCookie.ts` |
| `OIDC_COOKIE_PATH` | `/` | `apps/api/src/auth/persistSessionCookie.ts` |
| Variable | Default | Source |
| ------------------- | ------------------------------------- | ------------------------------------------- |
| `DB_HOST` | `localhost` | `apps/api/src/db/client.ts` |
| `DB_PORT` | `3306` | `apps/api/src/db/client.ts` |
| `DB_USER` | `familysync` | `apps/api/src/db/client.ts` |
| `DB_NAME` | `familysync` | `apps/api/src/db/client.ts` |
| `OIDC_CLIENT_ID` | `familysync` | `docker-compose.yml` |
| `OIDC_SCOPES` | `openid profile email offline_access` | `docker-compose.yml` |
| `OIDC_AUTH_EXPIRES` | `86400` | `apps/api/src/auth/persistSessionCookie.ts` |
| `OIDC_COOKIE_NAME` | `oidc-auth` | `apps/api/src/auth/persistSessionCookie.ts` |
| `OIDC_COOKIE_PATH` | `/` | `apps/api/src/auth/persistSessionCookie.ts` |
---
@@ -165,9 +167,9 @@ See `docs/deployment.md` for the full `drizzle-kit migrate` command used to prep
There are no application-level JSON/YAML config files. The two config files that read environment variables at dev/build time are:
| File | Purpose |
|------|---------|
| `apps/api/drizzle.config.ts` | Drizzle Kit migration config — reads `DB_*` variables |
| `apps/pwa/vite.config.ts` | Vite build config — no env var reads; proxy rules for dev server |
| File | Purpose |
| ---------------------------- | ---------------------------------------------------------------- |
| `apps/api/drizzle.config.ts` | Drizzle Kit migration config — reads `DB_*` variables |
| `apps/pwa/vite.config.ts` | Vite build config — no env var reads; proxy rules for dev server |
The PWA Vite dev server proxies `/health`, `/api`, and `/callback` to `http://localhost:3000` so the frontend and API can be developed without CORS configuration.