Rebrand to Proof of Work; multi-user 0.4 package with curated library sync

Repo cleanup
- Add top-level .gitignore (was missing; node_modules, .next, *.s9pk,
  image.tar, seed/data/*.db, log files, etc.) and a root README.
- Delete legacy start9/0.3.5/ package (StartOS 0.3.5 wrapper, no longer
  the deploy target).
- Delete start9-example-packaging/ (template from another project).
- Delete planning docs (START9_PACKAGING_LOG.md, VERSIONING.md,
  STARTOS_0.4_UPGRADE_PROMPT.md, ICON_FILES_INDEX.md, etc.) — info now
  lives in the deploy guide and code comments.
- Drop the standalone Dockerfile, docker-compose.yml, ICON_*, and dev
  log/build artifacts from the app dir.
- Drop the v0.1.0:18/19/20 version files (they belonged to the legacy
  workout-log package and don't apply to the new id).

Rename + new package
- Rename app dir workout-planner/ -> proof-of-work/.
- Rename StartOS package id workout-log -> proof-of-work; the new id
  makes this a brand new StartOS service (clean cutover from the old
  one rather than in-place upgrade).
- Reset version graph; v1.0.0:1 is the seeded cutover release. The
  Dockerfile bakes a one-time /data snapshot and docker_entrypoint.sh
  copies it into the new volume on truly-fresh first boot only (both
  /data/app.db missing AND /data/.seeded absent).
- Move start9/0.4-migration/ -> start9/0.4/; the old start9/0.4/ stub
  is gone.

Curated exercise library (multi-user-aware)
- proof-of-work/prisma/exercises.seed.json is the canonical library
  shipped to every install (164 exercises today, dumped from the live
  snapshot).
- proof-of-work/scripts/sync-library.cjs (npm run sync-library) refreshes
  the JSON from start9/0.4/seed/data/app.db after refresh_seed.sh.
- proof-of-work/prisma/seed.ts now reads from the JSON instead of a
  hardcoded 52-exercise array; runs at Docker build time to seed the
  fallback DB and on first boot for fresh installs.
- proof-of-work/prisma/ensureExerciseLibrary.cjs runs on every container
  boot (from docker_entrypoint.sh) and INSERT OR IGNOREs every library
  entry for every user, keyed on (userId, name). Library updates flow
  to existing installs on package upgrade; user-custom exercises
  (isCustom=true) and any colliding names are never overwritten;
  removed exercises stay on existing installs (additive-only).

Deploy guide (start9/0.4/DEPLOY_040.md)
- Rewritten end-to-end for the workout-log -> proof-of-work cutover:
  refresh_seed, sync-library, build, sideload, verify, rotate creds,
  stop the old service, then post-cutover cleanup release v1.0.0:2.
This commit is contained in:
Keysat
2026-05-08 20:12:25 -05:00
parent 1b64c45c52
commit aa407b5f67
184 changed files with 8314 additions and 3286 deletions
+264
View File
@@ -0,0 +1,264 @@
# Deploy Proof of Work on StartOS 0.4 (sideload)
This guide walks the maintainer through cutting over from the legacy
`workout-log` package to the new `proof-of-work` package. They share the
same upstream code and on-disk schema, but `proof-of-work` is a brand new
StartOS service (different package id), so StartOS treats it as a fresh
install. Data preservation is handled by baking a one-time snapshot of
your live `workout-log` `/data` volume into the `proof-of-work` v1.0.0:1
image and copying it into the new volume on first boot.
Your existing `workout-log` install stays running and untouched the whole
time. The cutover is one-way only after you stop and uninstall it; until
then you can fall back to it.
> NEVER click Uninstall on either package mid-cutover. Uninstall destroys
> the volume. Use Stop instead. Only Uninstall after you've verified
> proof-of-work is happy.
---
## 0) Prereqs on your build machine
You need:
- Node.js >= 20 and npm
- Docker with `buildx`
- `start-cli` from Start9 (SDK):
<https://docs.start9.com/packaging/0.4.0.x/environment-setup.html>
- `jq`, `make`, `git`, `sqlite3`, `rsync`, `ssh`
- Reachable SSH access to your existing `workout-log` host
One-time `start-cli` key setup:
```sh
start-cli init-key
```
`~/.startos/config.yaml` should contain at least:
```yaml
host: http://<your-04-host>.local
```
`make install` uses this to push the `.s9pk` to the target.
---
## 1) Refresh the seed snapshot from your live `workout-log` host
The repo includes `start9/0.4/seed/data/app.db` as a placeholder so the
build works without network access, but for an actual cutover you should
pull a fresh snapshot from your live host first.
```sh
./start9/0.4/refresh_seed.sh embassy@embassy.local
```
For a 0.3.5 host this auto-detects
`/embassy-data/package-data/volumes/workout-log/data/main/`. For a 0.4
host pass the volume path explicitly as arg 2 — get it from
`start-cli package shell workout-log` and `df` inside the container, or
from the StartOS docs.
Refresh prints expected row counts and runs `PRAGMA integrity_check`. If
anything looks off, fix the source before proceeding.
---
## 2) (Optional) Refresh the curated exercise library JSON
The shared library that ships with the package is generated from the same
snapshot. After `refresh_seed.sh`, regenerate the JSON if you've added
new exercises in the running app:
```sh
cd proof-of-work
npm run sync-library
git diff prisma/exercises.seed.json # eyeball the new rows
```
Commit the JSON change before building so it's baked into the image.
---
## 3) Build the package
```sh
cd start9/0.4
npm ci
make clean
make x86
```
On success you'll get an artifact at:
```
start9/0.4/proof-of-work_x86_64.s9pk
```
---
## 4) Sideload on the 0.4 host
### Option A — `make install` (fastest)
```sh
make install
```
### Option B — StartOS web UI
1. Open the StartOS 0.4 web UI on the target host.
2. **System -> Sideload Service**.
3. Upload `start9/0.4/proof-of-work_x86_64.s9pk`.
4. Click **Install**, then **Start**.
`workout-log` and `proof-of-work` will appear as two separate services in
the UI. Both can be running simultaneously — they have different volumes,
different ports the SDK assigns, and no shared state.
---
## 5) First-boot verification
### 5a. Confirm the seed branch ran
In **Services -> Proof of Work -> Logs**, or via CLI:
```sh
start-cli package logs proof-of-work | grep '\[entrypoint\]'
```
On the very first boot you should see:
```
[entrypoint] no /data/app.db and no .seeded marker; copying baked cutover seed from /app/seed/data/app.db
[entrypoint] ensuring curated exercise library is present for every user
[ensure-library] processed 1 user(s) x 164 exercise(s) (164 INSERT OR IGNORE statements)
[entrypoint] launching Next.js on :3000 with DATABASE_URL=file:/data/app.db
```
Subsequent boots:
```
[entrypoint] /data/app.db already present; live data is the source of truth
[entrypoint] found .seeded: seeded from baked cutover snapshot at 2026-...
[ensure-library] processed N user(s) x 164 exercise(s)
```
### 5b. Log into the app
Open the web UI from the StartOS service page and log in with the same
credentials you used on the legacy `workout-log` install (the bcrypt hash
came over with the snapshot, so existing passwords keep working).
Default seed credentials (only on a brand-new install with no baked
seed): `admin@local` / `workout123` — change immediately via the action
in section 6.
### 5c. Spot-check the data
- Workouts count matches your old install (run-counts in the
`refresh_seed.sh` output were the source of truth).
- Exercise library shows your 164 exercises.
- Open a recent workout and confirm set logs match.
### 5d. Run a StartOS backup
**Services -> Proof of Work -> Backup -> Create Backup**. Confirm it
completes. This validates `Backups.ofVolumes('main')` wiring on the new
package.
---
## 6) Rotate admin credentials
Stop the service first (action is gated on `allowedStatuses: only-stopped`):
1. **Services -> Proof of Work -> Stop**
2. **Actions -> Change admin credentials**
3. Fill in new email, new password, confirm. Submit.
4. **Start** the service and log in with the new credentials.
---
## 7) Stop the legacy `workout-log` service
Once you've used `proof-of-work` for at least a session and confirmed
nothing's missing:
1. **Services -> Workout Log -> Stop**
DO NOT Uninstall yet. Keeping the old service installed (just stopped)
preserves its `/data` volume in case you need to re-pull the snapshot or
roll back. Once you're confident (a week is plenty), Uninstall to free
the volume.
---
## 8) Post-cutover cleanup release (v1.0.0:2)
After a few days running on `proof-of-work` with no surprises, ship a
cleanup release that:
- Strips `COPY start9/0.4/seed/data /app/seed/data` from the Dockerfile.
- Strips the seed-copy branch out of `docker_entrypoint.sh` (keep the
fallback DB branch and the ensure-library step).
- Leaves `seed/` and `refresh_seed.sh` on disk as historical artifacts.
- Adds `startos/versions/v1.0.0.2.ts` (empty `up`/`down` migrations) and
promotes it to `current` in the version graph; v1.0.0:1 moves to `other`.
Reason: once `/data` is the sole source of truth, a baked seed in the
image becomes a foot-gun — removing it eliminates any chance of a future
upgrade accidentally stomping live data.
---
## 9) Library updates after cutover (steady state)
```
# add new exercises in the running app, then:
./start9/0.4/refresh_seed.sh embassy@embassy.local
cd proof-of-work && npm run sync-library
git add prisma/exercises.seed.json
# bump the build rev in start9/0.4/startos/versions, add a new version file,
# commit, then:
cd start9/0.4 && make clean && make x86 && make install
```
On every upgrade, every user on the instance picks up the new exercises
on first boot via the `INSERT OR IGNORE` step. Custom exercises a user
added themselves are never overwritten.
---
## 10) Troubleshooting
| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Login fails with your `workout-log` password | Snapshot was pulled from a stale source | Re-run `refresh_seed.sh` against your live host and rebuild. |
| Workouts missing after cutover | Same | Same. |
| `/data/app.db` is empty after first boot | `.seeded` marker present without the DB (corrupted prior boot) | `start-cli package shell proof-of-work`, `rm /data/.seeded`, restart. |
| Service never reaches Ready | Port 3000 not listening | Check logs: Prisma or Next.js threw at boot. Verify the DB file isn't zero bytes. |
| `[ensure-library] WARNING` | sqlite3 failed to apply the curated library | Inspect `/data/app.db` and the JSON. Boot continues; library updates skipped this cycle. |
| Container exits immediately | Build context wrong — `proof-of-work/` not visible to Docker | Run `make` from `start9/0.4/`, not the repo root. |
| `make x86` fails with `No rule to make target .git/HEAD` | s9pk.mk's awk grabbed two `id:` matches and concatenated BASE_NAME | Confirm `manifest/index.ts` has only one `id:` line. The shipped s9pk.mk uses `{print $$2; exit}` which already guards this. |
| Docker fails with `ERROR: failed to build: resolve : lstat start9: no such file or directory` | `dockerBuild.dockerfile` was set to a path including `start9/0.4/` | The shipped manifest sets `dockerfile: './Dockerfile'`. The `dockerfile` field is resolved relative to the package dir, not relative to `workdir`. |
---
## 11) Data-preservation summary
- Volume name (`main`), mount path (`/data`), DB path (`/data/app.db`),
internal port (`3000`): identical to the legacy `workout-log` package.
- Package id changed: `workout-log` -> `proof-of-work`. StartOS treats
this as a brand new service. Migration is via the baked seed in
v1.0.0:1, not via in-place upgrade.
- Seed only writes to `/data` on truly-fresh first boot (both `app.db`
missing AND `.seeded` marker absent).
- Library updates (new exercises) flow to every user on every upgrade
via additive `INSERT OR IGNORE`. Never deletes; never overwrites a
user's own custom exercises.
- StartOS Backup captures `/data` in full.
- Uninstall destroys `/data`. The `alertUpdate` copy reminds users.