# FamChore v2 — Rules ## Auth - Every collection query includes `famId = @request.auth.famId` filter - Super admin bypasses famId filter (access via PB admin API) - `deviceToken` stored as SHA-256 hash; never log raw tokens ## Config - **SvelteKit must never import `config.ts`.** `config.ts` at root owns the three service **ports** for the Hono proxy (`FRONTEND_PORT`/`PROXY_PORT`/`PB_PORT` = `2080`/`3456`/`8090`). - SvelteKit env vars are declared in `frontend/src/env.ts` via `defineEnvVars`, read with `$app/env/public` / `$app/env/private`. Loopback URLs are code constants; the only real env vars are the PB creds and `SERVER_IP`. - Runtime env values live in `.env` at root (symlinked to `frontend/.env`; loaded by the proxy dev via `tsx --env-file=../.env`). `.env.example` is the committed template. Never commit `.env`. - `.env` currently holds only: `PB_EMAIL`, `PB_PASSWORD`, `SERVER_IP`. Ports come from `config.ts`, not `.env`. ## Ports - Frontend: `2080` - Proxy: `3456` - Container external: `3001` (port `3000` is reserved) — chosen at deploy via compose `PORT` - Must not use port `3000` for anything. ## Docker - Prod: `docker/Dockerfile` (multi-stage + nginx, bundles internal PB) - Dev PB: `docker/Dockerfile.dev` (standalone PocketBase) - Nginx routes: `/api/*` → Hono (`:3456`), `/pb/api/*` → PB (`:8090`), `/pb/` → 404 (admin UI kept internal), `/*` → SvelteKit (`:2080`) - `docker-compose.yaml`: public port is `${PORT:-3001}:3001`; internal PB published loopback-only as `127.0.0.1:8091:8090`. ## ⚠️ Dev vs Prod PocketBase data (READ BEFORE TOUCHING CONTAINERS) - **Permanent dev PB** = container **`pb-dev`**, publishes **`:8090`**, data in host **`./pb_data`** (root-owned). This is what `pnpm dev` talks to (via `SERVER_IP:8090`). - **Docker app** (`famchamp-app-1`) has its **own internal PB**, published **`:8091`** (loopback), and it **also bind-mounts `./pb_data` → `/app/pb_data`**. So `pb-dev` and the docker app currently **share the same host data dir** — two PB processes on one store. Keep this in mind; the docker version is not the dev target. - **NEVER `docker rm`/recreate `pb-dev` with a fresh volume** — that wipes the permanent dev PB. To restore it, recreate with its data intact: ``` docker rm -f pb-dev docker run -d --name pb-dev \ -v "$PWD/pb_data:/pb_data" \ -p 8090:8090 \ pb-dev \ pocketbase serve --http=0.0.0.0:8090 --dir=/pb_data ``` - Superuser creds: `debug@famchamp.dev` / `debug123` (fallback baked in code). If superuser auth returns HTTP 500, the container is almost certainly serving an **empty store** (broken/missing mount) — restore the mount, don't reseed a new store. - `SERVER_IP`: same LAN = `192.168.1.225`, away = your Tailscale IP (e.g. `100.103.22.104`). Both hit the same `pb-dev:8090`. Update `.env` when your IP changes. ## Monorepo - SvelteKit in `frontend/`, Hono in `proxy/` - `pnpm dev` / `pnpm build` at root runs both in parallel - Decisions tracked in `MEMORY.md` ## Environment Variables - `SERVER_IP` — dev machine IP where PB + proxy run (browser `pocketbase.ts`, `pb-admin`, proxy all read it). Dev only; prod ignores it. - `PB_EMAIL` / `PB_PASSWORD` — PB superuser (fallback `debug@famchamp.dev`/`debug123`) - `PROXY_URL` — public env in `env.ts` (default `http://127.0.0.1:3456`); SSR → proxy - Compose/deploy: `PORT` (public port, default `3001`), `PB_DATA` (host data dir) - Not currently wired (future): `STRIPE_SECRET_KEY`, `DONATION_MODAL_INTERVAL`