docs: mark Phase 0 done, record D19 (auto-update, deferred)
docs/PLAN.md's Phase 0 section and its "Done when"/Verification entries still described the original Postgres+RLS, docker-compose, auto-redeploying design — none of which is what actually got built and deployed. Marks it done, states the two deliberate deviations plainly (SQLite not Postgres+RLS, manual redeploy not automatic), and separates what's actually verified (login persists a session, checked by scripts/smoke-test.sh after a real bug) from what nobody has tried yet (PWA home-screen install). docs/DECISIONS.md D19 records the auto-update investigation: the real fix for Unraid's own "not available" update-check badge (a third, independent place the D17 self-signed cert needed trusting — Unraid's PHP update checker doesn't share Docker's own certs.d), the structural reason "up to date" can't be fully trusted on this host even after that fix (CI builds on the same dockerd the app runs on, so the local :latest tag is always fresh regardless of whether the container was recreated from it), the failed first Watchtower attempt (stale image, wrong Docker API version) and why CI-triggers-a-redeploy was rejected again rather than reconsidered. "Deliberately deferred" gets three new entries: finishing Watchtower, migrating Gitea/CI to a dedicated VM (raised as the real fix for the root cause D19 kept running into), and persisting the accumulated host-local trust files across a reboot. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R2ZKeWkZV7ehf7fivrAkkG
This commit is contained in:
+32
-9
@@ -529,13 +529,31 @@ These are the payoff for self-hosting — things Strava structurally cannot do.
|
||||
|
||||
Estimates assume one developer working evenings and weekends.
|
||||
|
||||
**Phase 0 — Scaffolding (2 weeks).** Monorepo, `uv`/`ruff`/`mypy --strict`, FastAPI skeleton with
|
||||
`/healthz` and OpenAPI, Alembic baseline (users/invites/sessions **with RLS policies from the first
|
||||
migration**), SvelteKit static SPA shell with login, manifest + service worker + precache passing
|
||||
Lighthouse installability, VAPID keypair, Caddy, compose, Gitea Actions green, image in the registry,
|
||||
deployed.
|
||||
*Done when:* you log in at the real URL, add it to your iPhone home screen, it launches standalone —
|
||||
and a push to `main` rebuilds and redeploys it.
|
||||
**Phase 0 — Scaffolding.** ✅ **Done, with two deliberate deviations from this original description —
|
||||
both recorded in `docs/DECISIONS.md`, not silent drift.** Monorepo, `uv`/`ruff`/`mypy --strict`,
|
||||
FastAPI skeleton with `/healthz` and OpenAPI, Alembic baseline (users/invites/sessions), SvelteKit
|
||||
static SPA shell with login, manifest + service worker, Caddy, Gitea Actions green, image in the
|
||||
registry, deployed to a real Unraid host behind real HTTPS.
|
||||
|
||||
- **SQLite, not Postgres+RLS.** D15 reversed D4 mid-Phase-0, after the RLS version was already
|
||||
shipped and merged. Isolation is now enforced entirely at the repository layer (`db.py`'s
|
||||
`Scope`), not database RLS. See D15 for the full cost/benefit record.
|
||||
- **CI builds and pushes on every push to `main`, but does not auto-redeploy the running
|
||||
container.** D16/D17 made this deliberate: the runner shares this Unraid host's own `dockerd`
|
||||
(DooD), and an unattended redeploy of a container on a personal server with no human gate was
|
||||
judged the wrong default. A push to `main` gets you a new image in the registry within minutes;
|
||||
getting it onto the running container is still a manual step (`deploy/README.md`). An
|
||||
auto-updater (Watchtower or similar) was attempted and deferred — see "Deliberately deferred"
|
||||
in `docs/DECISIONS.md`.
|
||||
- **VAPID/push notifications were never started.** Correctly so — per this doc's own PWA-decision
|
||||
table, that's gated behind standalone-mode detection and belongs to a later phase, not Phase 0.
|
||||
|
||||
*Done when — status:* Logging in at the real URL (`https://bike.bbergle.com`) and seeing an
|
||||
authenticated view of your own account is **verified**, including the session actually persisting
|
||||
(`scripts/smoke-test.sh`, added after a real Secure-cookie-over-HTTP bug on the first deploy — see
|
||||
that script's header comment). **Not yet tried:** adding it to an iPhone home screen and confirming
|
||||
a standalone launch — nobody has actually done this yet, so it isn't checked off, even though the
|
||||
manifest and service worker are in place.
|
||||
|
||||
**Phase 1 — Zero-touch ride history (6–8 weeks).** Ingestion core (all three dedupe layers, course
|
||||
discrimination, quarantine); **the Bryton cloud poller as the primary path**, polling every 15 min with
|
||||
@@ -654,8 +672,13 @@ because if the project stalls right after it, it has still succeeded.
|
||||
activity reaches Bryton's cloud with the phone switched off. Then plug it in over USB and `ls -R` the
|
||||
mounted volume to confirm the actual `.fit` path.
|
||||
|
||||
**Phase 0:** `curl https://host/healthz` returns 200; push to `main` produces a new registry image and
|
||||
a redeployed container; `docker compose logs` shows migrations applied.
|
||||
**Phase 0 — done, verified for real, not just assumed from CI going green:** `curl https://host/healthz`
|
||||
returns 200; a push to `main` produces a new registry image (`docs/DECISIONS.md` D17's release
|
||||
workflow) — redeploying the running container from it is a manual step (D16/D17), not automatic;
|
||||
`docker exec velodrome velodrome create-admin` bootstraps the first user (D18); logging in at the
|
||||
real HTTPS URL and staying logged in on the next request is checked by `scripts/smoke-test.sh`, not
|
||||
eyeballed in a browser, after that exact failure mode (a `Secure` cookie silently dropped when
|
||||
tested over plain HTTP) actually happened on the first deploy.
|
||||
|
||||
**Phase 1 — ingestion:**
|
||||
- Upload a real Rider 650 `.fit` → activity appears with correct distance, elevation, and map track.
|
||||
|
||||
Reference in New Issue
Block a user