fix: review fixes for webhook and auto mode (#8)

Clear available_* only when the deployed ref equals it, drop the unused
poll source, stop leaking internal errors to CI, use the request-scoped
logger, validate X-Request-ID, re-read jobs once after the timeout,
report refused when no target ref exists, and tidy UI, deploy and docs.
This commit is contained in:
2026-10-12 20:48:43 +02:00
parent f25a7a7779
commit b1d6e5e705
15 changed files with 162 additions and 83 deletions
+7 -5
View File
@@ -22,7 +22,7 @@ DATABASE_URL=postgres://... go test -tags integration ./internal/master/store/
## Architecture (one-line per package)
- `cmd/master` — wiring only: config → store → hub → jobs → web, two listeners (UI, agents over pinned TLS)
- `cmd/master` — wiring only: config → store → hub → jobs → web + webhook, two listeners (UI, agents over pinned TLS)
- `cmd/agent` — wiring only: config → docker client → inventory → job runner → master connection
- `internal/protocol` — the WebSocket messages both sides speak (`Version`, `JobStart`, `JobResult`, ...)
- `internal/pin` — master key pair, certificate and fingerprint pinning
@@ -63,8 +63,8 @@ DATABASE_URL=postgres://... go test -tags integration ./internal/master/store/
- **The webhook never creates services; new services always start `manual`.** The upsert
does not touch `update_mode`.
- **Auth**: agents by token over pinned TLS; people by OIDC; CI by the `UPDATER_API_KEY`
bearer token on `POST /update` only. Every state-changing UI
request is a POST with a CSRF token.
bearer token on `POST /update` only. Every state-changing UI request is a POST with a
CSRF token.
## Gotchas
@@ -101,8 +101,10 @@ DATABASE_URL=postgres://... go test -tags integration ./internal/master/store/
- **A webhook job's target is `<image_repo>:<request tag>`**, built from the service's own
repo, never from the request's image string. With an explicit target the "follows no tag"
refusal does not apply; removed, self, built and container still do.
- **`available_*` is cleared by `FinishJob`** on success when `available_at <= job.created_at`
(a job created after the suggestion deployed the newest version).
- **`available_*` is cleared by `FinishJob`** on success only when the job's `to_ref`
(as created, without `@digest`) equals `available_ref` and `available_at <= job.created_at`
(that version is now running). A manual Update of the followed tag does not clear a
badge for a different tag.
- **Job output is capped at `protocol.MaxJobOutput` (128 KiB, tail).** NUL bytes are
stripped by the hub because Postgres text rejects them.