Files
proof-of-work/start9/START9_PACKAGING_LOG.md
T
2026-02-28 09:27:26 -06:00

236 lines
6.2 KiB
Markdown

# Start9 Packaging Log: Workout Log (from example to working 0.3.5 wrapper)
This file records exactly what was adapted from `start9-example-packaging` to package `workout-planner` for a Start9 server on StartOS `0.3.5` (Raspberry Pi / ARM64).
It is written as reusable documentation so you can repeat this process for future apps.
## 0) Goal and constraints
- Target now: StartOS `0.3.5` on Raspberry Pi.
- Future target: StartOS `0.4.0` when stable.
- Priority: package should work now, while keeping data layout and wrapper structure easy to migrate later.
## 1) What was reviewed first
Reviewed the existing example wrapper in `start9-example-packaging/0.3.5`:
- `manifest.yaml`
- `Makefile`
- `Dockerfile`
- `docker_entrypoint.sh`
- `healthcheck.sh`
- `instructions.md`
- `README.md`
- `DEPLOY_035.md`
Then reviewed the app in `workout-planner`:
- App Docker build/runtime behavior (`workout-planner/Dockerfile`)
- DB shape + config (`prisma/schema.prisma`, `DATABASE_URL` usage)
- Health endpoint (`/api/health`)
- Seed/default user (`prisma/seed.ts`)
## 2) New Start9 wrapper scaffold created
Created a **new** folder (separate from your example):
- `start9/0.3.5/`
- `start9/0.4/` (planning placeholder)
Files created in `start9/0.3.5`:
- `manifest.yaml`
- `Dockerfile`
- `docker_entrypoint.sh`
- `healthcheck.sh`
- `Makefile`
- `instructions.md`
- `README.md`
- `DEPLOY_035.md`
- `LICENSE`
- `icon.png` (copied from app icon assets)
Also created:
- `start9/0.4/README.md` (migration intent notes)
## 3) Key packaging design decisions
### 3.1 Keep persistent data in `/data`
To make upgrades/migrations safer, wrapper mounts Start9 volume at `/data` and stores SQLite DB at:
- `/data/app.db`
This is the most important continuity contract for migration to a future wrapper.
### 3.2 Keep runtime app files out of persistent volume
App code/binaries stay in image layers; only state goes in `/data`. This prevents app updates from overwriting user data.
### 3.3 Health checks use app endpoint
Wrapper health check calls:
- `http://127.0.0.1:${PORT}/api/health`
This checks both server and DB connectivity (as implemented by your app).
### 3.4 Backup/restore copies whole `/data`
Manifest backup/restore actions copy `/data` <-> `/backup` to align with Start9 expectations and keep DB safe.
### 3.5 Future 0.4.0 migration posture
Added explicit notes to preserve:
- package id (`workout-log`) where compatible
- DB path contract (`/data/app.db`)
- backup semantics
## 4) Runtime wiring added for first boot
In `docker_entrypoint.sh`:
- Ensures `/data` exists.
- Uses `/data/app.db` as `DATABASE_URL` target.
- If `/data/app.db` does not exist on first run, copies a seeded template DB from image (`/app/prisma/data/app.db`).
- Starts app with `node /app/server.js`.
Why this matters:
- First launch has a ready DB + default user.
- Subsequent restarts/upgrades keep existing `/data/app.db` untouched.
## 5) Build issues discovered and fixes applied
## Issue A: Prisma/OpenSSL runtime failure on ARM musl
Observed error during ARM container validation:
- Prisma engine expected OpenSSL compatibility; DB access failed.
Fix applied in wrapper `Dockerfile`:
- Install `openssl` in **builder** stage.
- Install `openssl` in **runner** stage.
Result:
- Prisma client loads correctly at runtime.
## Issue B: First-run DB missing tables (`main.User` does not exist)
Root cause:
- Repo `.dockerignore` excludes local `.db` files, so no seeded DB was copied from source tree.
Fix applied in wrapper `Dockerfile` build stage:
1. Generate Prisma client.
2. Create temporary DB: `DATABASE_URL=file:/tmp-seed/app.db npx prisma db push --skip-generate`
3. Seed it: `DATABASE_URL=file:/tmp-seed/app.db npm run db:seed`
4. Copy seeded DB into image: `/app/prisma/data/app.db`
Result:
- First boot can copy seeded DB into `/data/app.db`.
- Health endpoint reports DB connected.
## 6) Validation steps run
Successfully validated:
1. ARM image build from wrapper:
- `make -C start9/0.3.5 image-arm`
2. Local smoke run from built image tar:
- `docker load -i start9/0.3.5/image.tar`
- run container and query `/api/health`
Final smoke result:
- HTTP `200`
- JSON contained `status: ok` and `database: connected`
## 7) Why `start-sdk pack` failed on this machine
`start-sdk pack` failed with:
- `fatal: not a git repository (or any of the parent directories): .git`
Meaning:
- `start-sdk` expects to run from inside a Git repository so it can compute metadata (commit/hash).
This is unrelated to your app logic; it is a packaging environment requirement.
## 8) What “Step 1” means (plain English)
When I said “initialize under git,” I meant:
- The folder where you run `start-sdk pack` must be inside a Git repo.
If your `Workout-log` folder is just a normal folder today, do this once:
```bash
cd /Users/macpro/Projects/Workout-log
git init
git add .
git commit -m "Initial commit for Start9 packaging"
```
After that, this should work:
```bash
make -C start9/0.3.5 package
```
You do **not** need your local dev server on port `3000` running for packaging. Packaging builds a Docker image and `.s9pk` artifact separately.
## 9) Install flow on StartOS 0.3.5
1. Build package:
```bash
cd /Users/macpro/Projects/Workout-log
make -C start9/0.3.5 package
```
2. In StartOS UI (0.3.5), sideload:
- `start9/0.3.5/workout-log.s9pk`
3. Install + start service.
4. Open service UI and login:
- `admin@local` / `workout123`
5. Change password immediately.
6. Run a manual backup.
## 10) Reusable checklist for your next app
Use this sequence next time:
1. Copy known-good wrapper structure (`manifest`, `Dockerfile`, `entrypoint`, `healthcheck`, docs, makefile).
2. Define persistent data contract first (`/data/...`).
3. Ensure first boot initializes DB/schema (migration or seeded template).
4. Verify health endpoint checks both app + DB.
5. Build ARM image and smoke-test locally before Start9 sideload.
6. Ensure repo is a Git repo before `start-sdk pack`.
7. Document migration invariants for future StartOS versions (ID, DB path, backup format).
## 11) Files to edit before publishing/distributing
In `start9/0.3.5/manifest.yaml`, replace placeholder values:
- `wrapper-repo`
- `upstream-repo`
- `support-site`
- `marketing-site`
- `license` (if you choose MIT or another license)