Merge pull request 'docs: correct file references and the dev reachability claim' (#156) from fix/doc-accuracy into dev
All checks were successful
Validate observability stack / validate (push) Successful in 12s
Sync infra to hosts / sync-beta (push) Has been skipped
Build + push images (Forgejo registry) / build-push (frontend) (push) Successful in 8s
Sync infra to hosts / sync-prod (push) Has been skipped
Sync infra to hosts / sync-centralis (push) Has been skipped
Deploy / deploy (frontend) (push) Successful in 8s
Sync infra to hosts / sync-dev (push) Successful in 8s
secrets-guard / encrypted (push) Successful in 5s
Build + push images (Forgejo registry) / build-push (backend) (push) Successful in 29s
shell-lint / shellcheck (push) Successful in 19s
Deploy / deploy (backend) (push) Successful in 50s

This commit is contained in:
admin_emi 2026-08-01 18:51:08 +00:00
commit 83b074fa9e
8 changed files with 38 additions and 12 deletions

View file

@ -29,8 +29,10 @@ concurrently. Read both before dispatching parallel work.
**`dev` is a first-class hosted environment, not just an integration branch.**
It runs on vps1 — the same box as Forgejo and the monitoring stack — with its
own Postgres container, reachable only on the WireGuard mesh
(`10.10.0.2:8137`): no public DNS record, no Caddy site, no TLS. It is deployed
own Postgres container, reachable only from vps1 itself (`127.0.0.1:8137` —
`infra/docker-compose.yml` binds the port to loopback, so the mesh does not
reach it either; use an SSH tunnel): no public DNS record, no Caddy site, no
TLS. It is deployed
by CI like beta and prod. The desktop hosts no Thermograph environment at all;
`make dev-up` there is a laptop convenience for running the stack locally, not
a deployment target.

View file

@ -45,7 +45,7 @@ for systemd/CI callers. Entry target is `app:app`.
that disagree with the labels the API returns.
- **Fahrenheit country set**`api/content_payloads.py`'s `F_COUNTRIES` is
canonical; `frontend`'s `server/internal/format::FCountries` and
`static/units.js`'s `F_REGIONS` must stay identical to it. Both are asserted
`frontend/static/units.js`'s `F_REGIONS` must stay identical to it. Both are asserted
by tests in `frontend/server/internal/format/format_test.go` — but note the
backend cross-check **skips in CI** (the frontend image's build context is
`frontend/`, so this file is unreachable from the builder stage, which is the

View file

@ -69,7 +69,7 @@ cities_flavor.json bundled reference data (generated by gen_cities.py /
only builds and publishes its own container image
(`git.thermograph.org/admin_emi/thermograph-backend/app`) and hands infra a tag to
roll out (`SERVICE=backend` + `BACKEND_IMAGE_TAG` into infra's
`deploy/deploy.sh`).
`infra/deploy/deploy.sh`).
- **`thermograph-docs`** holds the cross-repo architecture/runbook docs; this
README only covers what's local to this service.

View file

@ -16,7 +16,7 @@ The `db` service runs the stock **`timescale/timescaledb:latest-pg18`** image
TTL, and the `recent_stamp` token embedded in derived-payload validity.
The schema is created by Alembic (`backend/alembic/versions/0002_climate_hypertables.py`,
run at app boot via `deploy/entrypoint.sh`). The app reads/writes it through
run at app boot via `backend/deploy/entrypoint.sh`). The app reads/writes it through
`backend/data/climate_store.py` (psycopg + polars). See
`deploy/POSTGRES-MIGRATION.md` for the parquet→hypertable cutover.

View file

@ -3,7 +3,7 @@
Runs as `deploy/forgejo/docker-stack.yml` — the only Swarm-scheduled workload
this cluster carries (prod and beta's app stacks are separate `docker stack
deploy`s that happen to run on the manager node, vps2 — see
`deploy/stack/README` context in `DEPLOY.md`). Pinned to the **vps1** node
`DEPLOY.md`). Pinned to the **vps1** node
(`75.119.132.91`) via the `role=forge` label from
`deploy/swarm/label-forge-node.sh`.
@ -153,6 +153,28 @@ echo "10.10.0.2 git.thermograph.org" | sudo tee -a /etc/hosts
numbering — adjust if you assigned it differently.) The git/web UI keeps
working normally for everyone else since only `/v2/*` is restricted.
**Pin the canonical name too, not just the image host.** Forgejo derives the
registry's bearer-token realm from `ROOT_URL`, so a client that already
resolves `git.thermograph.org` over the mesh is still sent to
`https://<ROOT_URL host>/v2/token` to collect a token. When `ROOT_URL` became
`dev.jinemi.com`, that second request took the public route, the `/v2/*`
matcher above answered 403, and docker fell back to anonymous — every push then
failed with `unauthorized: reqPackageAccess`, which reads exactly like a
revoked token or a missing scope. It is neither. Pin both names:
```
echo "10.10.0.2 git.thermograph.org dev.jinemi.com" | sudo tee -a /etc/hosts
```
The realm moves whenever `ROOT_URL` does, so read it rather than assuming:
```sh
curl -sI https://git.thermograph.org/v2/ | grep -i www-authenticate
```
These `/etc/hosts` pins are host state. Nothing in this repo writes them, so a
reprovisioned node has to be pinned again before it can pull.
## Register the Actions runner
Once Forgejo answers at its domain:

View file

@ -14,7 +14,7 @@ submission ($25 one-time) is deferred.
## What's in the repo
- `twa-manifest.json` — Bubblewrap config (reference values; see comment inside).
- `../../frontend/.well-known/assetlinks.json` — Digital Asset Links, served at
- `../../../frontend/static/.well-known/assetlinks.json` — Digital Asset Links, served at
`https://thermograph.org/.well-known/assetlinks.json`. Its fingerprint is a
**placeholder** until you generate the signing key (step 4).
@ -45,7 +45,7 @@ bubblewrap build
bubblewrap fingerprint list # or: keytool -list -v -keystore android-keystore.jks
```
Copy the `SHA256` value into `frontend/.well-known/assetlinks.json`, replacing
Copy the `SHA256` value into `frontend/static/.well-known/assetlinks.json`, replacing
`REPLACE_WITH_TWA_SIGNING_KEY_SHA256_FINGERPRINT`, then **deploy the site** so the
new file is live. Confirm:
@ -80,6 +80,7 @@ install for every user. Store it out of the repo, backed up.
`.aab`; the store review for a well-formed TWA is light. Not part of this pass.
## Why no backend changes
Android delegates the TWA's web notifications to the OS, so `backend/push.py`
(VAPID) and `backend/notify.py` deliver push to the app unchanged. Nothing in
Android delegates the TWA's web notifications to the OS, so
`backend/notifications/push.py` (VAPID) and `backend/notifications/notify.py`
deliver push to the app unchanged. Nothing in
`backend/` is touched by this track.

View file

@ -183,7 +183,8 @@ Terraform brings the stack up — don't let Terraform recreate containers mid-mi
`git.thermograph.org` reaches Forgejo's loopback port on vps1.
`COOKIE_SECURE` is auto-set to `0` when there's no domain (a Secure
cookie is never sent over plain HTTP) and `1` behind Caddy TLS.
- The rendered Caddyfile only reverse-proxies the app. The repo's `deploy/Caddyfile`
- The rendered Caddyfile only reverse-proxies the app. The repo's
`deploy/stack/lb/Caddyfile`
additionally serves the `emigriffith.dev` portfolio and legacy redirects; those are
host-specific and not templated here.
- Provisioner-based by design: the hosts already exist, so this is not a

View file

@ -147,7 +147,7 @@ LOKI_URL=http://10.10.0.2:3100/loki/api/v1/push \
docker compose -f docker-compose.agent.yml -f docker-compose.agent.beta.yml up -d
```
The mesh must already be up (see the main repo's `deploy/swarm/` / `INFRA.md`);
The mesh must already be up (see `infra/deploy/swarm/`);
Swarm is **not** required for the agent itself — it talks plain HTTP over wg0.
<!-- TODO(cutover): desktop no longer runs a Thermograph app stack and ships no