Version history: new image_versions table fed by the webhook (tag, no digest), registry polling and the agents' running inventory (well-formed sha256 digests only; a bare image is recorded as latest).
Registry polling: the master sends one HEAD per distinct followed repo:tag every POLL_INTERVAL (default 6h) via go-containerregistry, with credentials from DOCKER_CONFIG. A new digest becomes the available suggestion; auto services get a job. Registry-controlled text never reaches last_poll_error (status + error codes, or a fixed text per error class).
Version picker and rollback: the Service page lists the 10 most recent versions with a Deploy action (by version id, repo checked server-side). The agent deploys digest-pinned refs as is (protocol 3; v2 agents fail such jobs with a clear message). A rollback of an auto service stays until the registry shows a digest the tag was never deployed at (last_tag_digest).
Overview badges "follows no tag" and "poll failed"; README, CLAUDE.md, spec (Docker Hub HEAD verified) and phase 4 plan updated.
gofmt, go vet ./..., go test ./..., go test -race on agent, master and e2e
Store integration tests against Postgres 16
UI verified in a browser (overview badges, polling row, versions table, Deploy POST with CSRF and version id, 390px)
Migration 0004 applies on the server database
New push of a followed tag shows "update available" (source poll) within one cycle
Auto service gets exactly one poll job; rollback pick holds across cycles; a newer push moves it forward
Private image with bad credentials shows "poll failed" with only registry answered 401 Unauthorized
## Summary
- **Version history:** new `image_versions` table fed by the webhook (tag, no digest), registry polling and the agents' running inventory (well-formed `sha256` digests only; a bare image is recorded as `latest`).
- **Registry polling:** the master sends one HEAD per distinct followed `repo:tag` every `POLL_INTERVAL` (default 6h) via go-containerregistry, with credentials from `DOCKER_CONFIG`. A new digest becomes the available suggestion; auto services get a job. Registry-controlled text never reaches `last_poll_error` (status + error codes, or a fixed text per error class).
- **Version picker and rollback:** the Service page lists the 10 most recent versions with a Deploy action (by version id, repo checked server-side). The agent deploys digest-pinned refs as is (protocol 3; v2 agents fail such jobs with a clear message). A rollback of an auto service stays until the registry shows a digest the tag was never deployed at (`last_tag_digest`).
- Overview badges "follows no tag" and "poll failed"; README, CLAUDE.md, spec (Docker Hub HEAD verified) and phase 4 plan updated.
Closes #9
## Test plan
- [x] `gofmt`, `go vet ./...`, `go test ./...`, `go test -race` on agent, master and e2e
- [x] Store integration tests against Postgres 16
- [x] UI verified in a browser (overview badges, polling row, versions table, Deploy POST with CSRF and version id, 390px)
- [ ] Migration 0004 applies on the server database
- [ ] New push of a followed tag shows "update available" (source poll) within one cycle
- [ ] Auto service gets exactly one poll job; rollback pick holds across cycles; a newer push moves it forward
- [ ] Private image with bad credentials shows "poll failed" with only `registry answered 401 Unauthorized`
Adds services.last_auto_digest so the poller starts one automatic update per
registry digest, and re-reads the service before starting it. Also records a
bare image's running version as tag latest, only records well-formed
digests, and shows a digest-less version unless a digest row of its tag was
first seen at or after it.
Renames last_auto_digest to last_tag_digest. FinishJob sets it to the pinned
digest after any successful job whose to_ref had no digest, so a rollback
holds however the update was started.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
image_versionstable fed by the webhook (tag, no digest), registry polling and the agents' running inventory (well-formedsha256digests only; a bare image is recorded aslatest).repo:tageveryPOLL_INTERVAL(default 6h) via go-containerregistry, with credentials fromDOCKER_CONFIG. A new digest becomes the available suggestion; auto services get a job. Registry-controlled text never reacheslast_poll_error(status + error codes, or a fixed text per error class).last_tag_digest).Closes #9
Test plan
gofmt,go vet ./...,go test ./...,go test -raceon agent, master and e2eregistry answered 401 Unauthorized