5f7b3b6b7a
Security: shipping admin@local / workout123 as a default that the
operator was supposed-to-rotate-but-might-not is the kind of footgun
that turns into "default-credential exposure" headlines. Eliminated.
prisma/seed.ts now ONLY seeds the InstanceSettings singleton — no
admin user, no UserPreferences, no exercises in the build-time
fallback DB. The image still ships with prisma/exercises.seed.json
(curated 164-exercise library) but those rows aren't inserted until
an admin is created via the StartOS Action.
The change-admin-credentials Action now does INSERT-or-UPDATE in one
shot. CREATE mode (no admin exists) inserts the User row, inserts
UserPreferences with sensible defaults, and runs
ensureExerciseLibrary.cjs for the new admin so they don't have to
wait for the next service start to see the curated library. UPDATE
mode (admin exists) keeps the v1.0.0:1-3 rotation behavior. The
mode is auto-detected by counting `WHERE isAdmin = 1`.
The login page is now a server component that reads the admin count
upfront. Zero admins -> renders a "needs setup" panel pointing at
the StartOS Action ("Services -> Proof of Work -> Actions -> Set
admin credentials"). Otherwise renders the existing LoginForm
(extracted to LoginForm.tsx). Eliminates the
"I tried admin@local/workout123 and it failed, what's wrong"
fresh-installer confusion.
Backward compatible for upgrades from v1.0.0:1-3:
- /data already has an admin user; the no-admin detection never
triggers; login behaves identically to before.
- The Action's UPDATE mode still works for rotation.
Version graph: v1.0.0:4 promoted to current; v1.0.0:1, :2, :3 all
listed as `other` for in-place upgrade paths.
README updated to call out the explicit no-default-account design
and how to bootstrap an admin in local dev (Prisma Studio, since
the StartOS action isn't available off-StartOS).
92 lines
3.2 KiB
Markdown
92 lines
3.2 KiB
Markdown
# Proof of Work
|
|
|
|
Self-hosted multi-user workout planner and logger. Plan training cycles,
|
|
log daily workouts, search your history, and curate a shared exercise
|
|
library across everyone on the instance. Distributed as a StartOS 0.4
|
|
sideload package.
|
|
|
|
## Repo layout
|
|
|
|
```
|
|
proof-of-work/ Next.js app (TypeScript, Prisma + SQLite, Tailwind, PWA)
|
|
start9/0.4/ StartOS 0.4 package wrapper (manifest, Dockerfile,
|
|
entrypoint, version graph, change-credentials action)
|
|
```
|
|
|
|
Everything else is generated at build time.
|
|
|
|
## Local development
|
|
|
|
```sh
|
|
cd proof-of-work
|
|
npm install
|
|
npx prisma generate # important after schema changes
|
|
npx prisma db push # create the dev DB at prisma/data/app.db
|
|
npm run db:seed # ONLY seeds the InstanceSettings singleton — no admin
|
|
npm run dev # http://localhost:3000
|
|
```
|
|
|
|
For local dev you'll need to create an admin manually since the
|
|
StartOS action isn't available — easiest is `npx tsx` a one-off
|
|
script, or just open Prisma Studio (`npm run db:studio`) and add a
|
|
User row with `isAdmin: true` + a bcrypt hash you generate with
|
|
`node -e 'require("bcrypt").hash("yourpassword", 10).then(console.log)'`.
|
|
|
|
## Multi-user
|
|
|
|
**Fresh installs ship with no admin user on purpose** — the operator
|
|
must run the StartOS Action `Set admin credentials` (Services → Proof
|
|
of Work → Actions) before anyone can log in. This eliminates the
|
|
default-credentials footgun.
|
|
|
|
Once the admin exists, they can open sign-ups for additional users:
|
|
|
|
- In-app: log in as admin -> **Settings -> Instance Settings ->
|
|
Allow new sign-ups**.
|
|
- StartOS: **Services -> Proof of Work -> Actions -> Set new signups**.
|
|
|
|
Both write to the same `InstanceSettings` row; either path works.
|
|
|
|
When sign-ups are open, anyone reaching the URL can create an account at
|
|
`/auth/signup`. New users start with no admin privileges and are
|
|
automatically seeded the full curated exercise library.
|
|
|
|
## Building the StartOS package
|
|
|
|
See **[start9/0.4/DEPLOY_040.md](start9/0.4/DEPLOY_040.md)** for the full
|
|
deployment / cutover guide. Short version:
|
|
|
|
```sh
|
|
cd start9/0.4
|
|
npm ci
|
|
make clean
|
|
make x86 # produces proof-of-work_x86_64.s9pk
|
|
make install # sideload to the host in ~/.startos/config.yaml
|
|
```
|
|
|
|
## Curated exercise library
|
|
|
|
`proof-of-work/prisma/exercises.seed.json` is the canonical library
|
|
shipped to every install. It seeds fresh installs (via `prisma/seed.ts`)
|
|
and is re-applied on every boot to existing installs (via
|
|
`docker_entrypoint.sh` + `ensureExerciseLibrary.cjs`) so updates flow to
|
|
all users on package upgrade.
|
|
|
|
Refresh the JSON from the maintainer's live host:
|
|
|
|
```sh
|
|
./start9/0.4/refresh_seed.sh <ssh-target> # pull a fresh /data snapshot
|
|
cd proof-of-work && npm run sync-library # extract Exercise table -> JSON
|
|
git diff prisma/exercises.seed.json
|
|
```
|
|
|
|
The system is additive only — removing an exercise from the JSON does
|
|
not delete it from existing installs (users may have logged sets against
|
|
it). Users' own custom exercises (`isCustom = true`) are never touched.
|
|
|
|
## Privacy
|
|
|
|
`start9/0.4/seed/data/app.db` is your live `/data` snapshot. It contains
|
|
real workout history and a bcrypt'd password hash. The top-level
|
|
`.gitignore` keeps it out of git; do NOT commit it to any public repo.
|