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:
@@ -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.
|
||||
Reference in New Issue
Block a user