thermograph/infra/deploy
Emi Griffith 7b3ea69ef9
All checks were successful
PR build (required check) / changes (pull_request) Successful in 6s
secrets-guard / encrypted (pull_request) Successful in 5s
PR build (required check) / build-backend (pull_request) Has been skipped
shell-lint / shellcheck (pull_request) Successful in 7s
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 2s
secrets: validate CENTRALIS_TEAM at render time, like CENTRALIS_TOKENS
CENTRALIS_TOKENS has a parse-and-prove check in both renderers because it is
JSON, full of double quotes, living in a file bash expands, and because
Centralis fails closed on it. CENTRALIS_TEAM is the same kind of value with
none of the same guard.

It is the allowlist for Google sign-in. Centralis' buildOAuth() requires a
Google client AND at least one team member, so an empty or malformed team does
not fail loudly -- it turns OAuth off and leaves the server bearer-token-only,
which looks exactly like never having configured it.

The sharper failure is a partial one. parseTeam() (centralis src/config.ts)
SKIPS an unparseable entry with a console.error and carries on, so an address
with a typo'd domain drops exactly one person, behind a log line on a container
start nobody watches. Entries parseTeam would skip are therefore refused here,
where a human is reading the output.

Accepts all three shapes parseTeam accepts -- email->role, email->object, and
an array of objects -- and matches its case-insensitive duplicate detection.
Rejects invalid JSON, a non-object/array, an entry without an @, a duplicate
address, and an empty team. Prints member addresses and roles on success, the
same argument the adjacent CENTRALIS_TOKENS line makes for printing subjects:
seeing the list is how an operator notices somebody is missing.

Added to BOTH renderers with identical logic. The parity argument this
migration rests on is that the two backends produce the same file; a validation
present on only one side means one backend can write a file the other would
have refused.

Verified end to end against the live vault with verify-centralis-render.sh:
9 keys, 2 subjects, VERDICT PASS, compose model digests identical.
2026-08-01 15:57:57 +00:00
..
backup infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
db db: raise max_connections to 200, cap work_mem at 64MB, trim async pool overflow (#124) 2026-07-26 19:48:50 +00:00
forgejo ci: add an always-on Actions runner on vps2 2026-08-01 07:54:28 -07:00
migrations Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00
openmeteo infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
secrets secrets: make the two-host age key quorum a checked policy 2026-07-31 05:12:58 +00:00
stack infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
swarm infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
twa Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00
Caddyfile.vps1 dev: leave /healthz outside the basic-auth boundary (#113) 2026-07-26 08:28:18 +00:00
Caddyfile.vps2 infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
deploy-dev.sh infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
deploy.sh deploy.sh: honour TG_POST_DEPLOY on the compose path too (#109) 2026-07-26 07:28:43 +00:00
env-topology.sh openbao: derive the AppRole credential path per environment 2026-07-30 19:49:28 -07:00
migrate-db.py Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00
POSTGRES-MIGRATION.md Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00
provision-agent-access.sh Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00
provision-dev.sh dev: serve at dev.thermograph.org behind basic auth, bound to loopback (#111) 2026-07-26 07:49:43 +00:00
provision-mail-supervision.sh observability: add the estate's first alerting; supervise Postfix 2026-07-24 13:19:19 -07:00
provision-mail.sh infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
provision-secrets.sh infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
render-secrets-openbao.sh secrets: validate CENTRALIS_TEAM at render time, like CENTRALIS_TOKENS 2026-08-01 15:57:57 +00:00
render-secrets.sh secrets: validate CENTRALIS_TEAM at render time, like CENTRALIS_TOKENS 2026-08-01 15:57:57 +00:00
RUNBOOK-vps1-vps2-cutover.md dev: serve at dev.thermograph.org behind basic auth, bound to loopback (#111) 2026-07-26 07:49:43 +00:00
thermograph-dev.service Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00
thermograph.env.example accounts: sign in with Google, on a shared provider-agnostic OAuth engine (#122) 2026-07-27 00:56:43 +00:00
thermograph.service Subtree-merge thermograph-infra (origin/main) into infra/ 2026-07-22 22:01:11 -07:00