46 lines
3.5 KiB
Markdown
46 lines
3.5 KiB
Markdown
|
|
# Production Deploy Checklist
|
||
|
|
|
||
|
|
The environment/config items that are **not** enforced by code or CI and must be
|
||
|
|
verified on the production instance itself. Each has a boot-time warning or a
|
||
|
|
QA-plan pointer; this list is the single place they live (previously they only
|
||
|
|
existed in session notes).
|
||
|
|
|
||
|
|
## Required environment (production)
|
||
|
|
|
||
|
|
| Variable | Why | Symptom if missing |
|
||
|
|
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
||
|
|
| `TOKEN_ENCRYPTION_KEY` | At-rest secrets (SimpleFIN token, SMTP/OIDC secrets, login IP/UA) otherwise fall back to a key stored **inside the database** — anyone with DB/backup read access can decrypt. On first boot with the key set, stored `v2:` ciphertexts migrate to env-keyed `e2:`. | Boot warning: `TOKEN_ENCRYPTION_KEY is not set in production` |
|
||
|
|
| `WEBAUTHN_RP_ID` | Passkeys bind cryptographically to this hostname; the `localhost` default silently breaks all passkey sign-ins behind a real domain. Bare hostname, no scheme/port (e.g. `bills.example.com`). Changing it later invalidates registered keys. | Boot warning: `WEBAUTHN_RP_ID is not set in production` |
|
||
|
|
| `WEBAUTHN_ORIGIN` (optional) | Pin the exact expected origin for WebAuthn ceremonies when the app is served from a non-default origin. When unset, the API origin plus any request origin whose hostname equals the RP ID is accepted. | Passkey enroll/sign-in fails origin verification |
|
||
|
|
|
||
|
|
## One-time settings (Admin panel / DB)
|
||
|
|
|
||
|
|
- [ ] **Turn OFF `simplefin_debug_logging`** on the production instance
|
||
|
|
(Admin → bank sync config). It is a debugging aid; leaving it on logs
|
||
|
|
more sync detail than production needs.
|
||
|
|
|
||
|
|
## Build/runtime infrastructure
|
||
|
|
|
||
|
|
- [ ] **`cdn.sheetjs.com` egress** — the lockfile pins `xlsx` to the official
|
||
|
|
SheetJS dist tarball (the npm registry line is abandoned with unfixed
|
||
|
|
high CVEs). CI runners and Docker builds must be able to reach it for
|
||
|
|
`npm ci`.
|
||
|
|
- [ ] **Node version alignment** — `package.json` engines, the Dockerfile base
|
||
|
|
image, and the CI image must agree (all `node:22` today). Bump all three
|
||
|
|
together.
|
||
|
|
- [ ] Volumes/permissions/migrations: handled by `docker-entrypoint.sh`
|
||
|
|
(`chmod 700` data dirs, non-root `bill` user, `RUN_DB_MIGRATIONS=true`)
|
||
|
|
— covered by QA batch B16.
|
||
|
|
|
||
|
|
## Standing dependency guard
|
||
|
|
|
||
|
|
- `renovate.json` is in the repo — enable Renovate on the Forgejo instance for
|
||
|
|
grouped weekly update PRs.
|
||
|
|
- Until then, `.forgejo/workflows/deps-audit.yml` runs weekly: it fails on any
|
||
|
|
high+ vulnerability (`npm audit --omit=dev --audit-level=high`) and prints
|
||
|
|
`npm outdated`, so dependency rot surfaces as a red scheduled run instead of
|
||
|
|
waiting for the next manual audit.
|
||
|
|
- Deferred upgrade, tracked: **TypeScript 7** typechecks this codebase clean but
|
||
|
|
`typescript-eslint` (peer `<6.1.0`) cannot parse under it yet — revisit when
|
||
|
|
typescript-eslint ships TS 7 support.
|