# Changelog All notable changes to Proof of Work and its StartOS package wrapper. The format roughly follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions track the StartOS package release rev (`upstream:rev` per ExVer). ## [Unreleased] This is everything in `master` since the last published `.s9pk`. Will ship as v1.0.0:1 once the maintainer drops a fresh `/data` snapshot into `start9/0.4/seed/data/app.db` and runs `make x86 && make install`. ### Added - **Multi-user support.** Every install starts with one admin (`admin@local`) and sign-ups closed. The admin opens sign-ups via Settings -> Instance Settings or via the new StartOS package action "Set new signups". New users start with no admin privileges and the full curated exercise library auto-seeded. - **Curated exercise library** at `proof-of-work/prisma/exercises.seed.json`. Used by `prisma/seed.ts` for fresh installs and by `ensureExerciseLibrary.cjs` (run from `docker_entrypoint.sh` on every boot) so library updates flow to existing installs additively, never overwriting users' own custom exercises. - `npm run sync-library` regenerates the JSON from the live snapshot. - **In-app password change** at Settings -> Change password. Verifies current password, requires 8+ char new password, auto-revokes every other session for the user. - **Admin user management** at `/main/admin/users`. List / promote / demote / reset-password / delete with last-admin guard and self-delete guard. Admin-initiated password reset force-revokes all the target's sessions. - **Self-serve account deletion** at Settings -> Danger Zone. Requires current password AND typing the literal phrase "delete my account". Refused for the last admin. Cascades through Prisma onDelete. - **Last-login tracking** (`User.lastLoginAt`). Stamped on every session creation, displayed as a relative-age cell in the admin Users table. - **Export my data** at Settings -> Export my data. Downloads a JSON with every workout, set, exercise, program tied to the user. Password hash and sessions excluded. - **Rate limits** on `/auth/login` (10/IP/15min) and `/auth/signup` (5/IP/15min). In-process sliding window, no deps. - **Security headers**: Content-Security-Policy (with frame-ancestors 'none', form-action 'self', object-src 'none'), Strict-Transport-Security, Referrer-Policy, Permissions-Policy. - **SQLite WAL mode** + `synchronous=NORMAL` enabled in entrypoint. Keeps readers from blocking on a concurrent backup-time writer. - **StartOS Package Action** `change-admin-credentials` now keys on `WHERE isAdmin = 1 ORDER BY createdAt ASC LIMIT 1` (previously oldest user regardless of role). - **StartOS Package Action** `toggle-signups`: same setter as the in-app admin toggle, accessible from the StartOS UI without an admin login. Asserts read-back matches written value. - **Test suite** (Vitest, 34 tests, ~2s): rate limit, hashing, curated-library multi-user idempotency, admin actions including last-admin guard, signup gate + email-enumeration leak check, password-change, account deletion. - **GitHub Actions CI**: app job runs prisma validate + prisma generate + tsc + lint + tests; startos job runs the package's `npm run check` (tsc --noEmit). Both on push and PR to master/main. - **ESLint config** (`.eslintrc.json` extending `next/core-web-vitals`). Wired into CI. - **Enriched `/api/health`** reports DB connection, journal mode (WAL status), library JSON availability, instance signup state, and user count. 503 if DB is unreachable; warnings field for non-fatal issues (e.g. journal_mode != wal). ### Changed - **Rebranded `workout-log` -> `proof-of-work`** end-to-end. Folder, npm package name, StartOS package id. StartOS treats this as a brand new service; cutover from the legacy package is via baked seed in v1.0.0:1, not in-place upgrade. - **Session tokens** now 256-bit `crypto.randomBytes` hex. Were derived from `Math.random() + Date.now()` — predictable enough that a determined attacker could enumerate other users' tokens. **Existing sessions invalidate on upgrade by design** — token format/length changed, old tokens won't validate. - **Version graph reset** to `1.0.0:1` (was on the legacy `workout-log` v0.1.0:18 / :19 / :20 line). ### Removed - Legacy `start9/0.3.5/` package (StartOS 0.3.5 wrapper, 65MB image artifacts, no longer the deploy target). - `start9-example-packaging/` template from another project. - Workout-planner standalone Dockerfile + docker-compose.yml (replaced by the StartOS package's own Dockerfile). - Various planning docs replaced by `start9/0.4/DEPLOY_040.md` and the root `README.md`. ### Compat notes for cutover The boot-time entrypoint runs idempotent ALTERs that: - Add `User.isAdmin` and auto-promote the oldest user to admin if no admin exists (preserves admin functionality across the cutover). - Add `User.lastLoginAt`. - Create the `InstanceSettings` table + singleton row (signupsOpen=0). - Switch SQLite to WAL mode (persists in DB header thereafter). So a snapshot pulled off the legacy `workout-log` host comes up as a working multi-user `proof-of-work` install with no manual SQL. --- ## v0.1.0:17 and earlier (legacy `workout-log` package) Out of scope for this changelog. The legacy package's history lives in the git log; nothing in this repo references it after v1.0.0:1 ships.