From d910edd4adbe9e619773989ba5f03d59aa0f340f Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 10 Jul 2026 17:53:51 +0200 Subject: [PATCH] docs: v0.112.0 CHANGELOG + README (registry access modes) + REUSE (runner vars seam, WWW-Authenticate parser) Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6 --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ REUSE.md | 3 ++- controller/README.md | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66a5ced..c7bdb94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ ## Changelog +### v0.112.0 — self-update without credentials: anonymous registry mode (2026-07-10) + +Root cause (live on Peti's box): the updater piggybacked on the Git Sync credentials and REFUSED when +they were absent — but the registry serves the public package anonymously (Docker v2 token dance, +verified empirically). A fresh customer without a private catalog silently lost version discovery + +self-update for no reason. Credentials become what they were meant to be: optional, private-catalog only. + +- **`queryRegistry` (internal/selfupdate):** both creds empty → anonymous mode — plain GET; on 401 + parse `WWW-Authenticate` (realm + service FROM THE HEADER — never hardcoded, quoted/bare/any-order/ + comma-in-quotes handled); GET the realm with `service` + `repository::pull` scope and NO + credentials; retry tags/list with the Bearer. Creds present → the BasicAuth path unchanged. + Half-configured pair → loud "hiányos registry hitelesítő adatok". A genuinely-denying registry → + "registry denied anonymous access — a private registry requires Git Sync credentials" (never the old + "credentials missing"). The registry base URL now derives from the image ref (was hardcoded host). +- **`pullImage`:** no creds → the `docker login` step is skipped entirely (docker's native anonymous + flow covers public packages); creds → login/pull/logout unchanged (token still stdin-only). +- **Settings page truthfulness:** "Verzió és frissítés" gains a mode line — "Registry: nyilvános + (hitelesítés nélkül)" vs "Registry: hitelesített"; credential-less is no longer an error state; the + Hiba row appears only on a real failure. `DryRun.PullCapable` counts anonymous as capable. +- Tests (`registry_anon_test.go`, httptest fake registry + fake CLI runner): full anonymous dance with + ZERO creds (token request auth-free, correct scope, highest semver); creds path byte-shape unchanged + (BasicAuth, no dance); both denial paths (token 401 / tags-with-Bearer 401) → the new clear error; + WWW-Authenticate parser table; pull with no creds → no login invocation recorded, pull still invoked; + creds → login/pull/logout order + stdin token; partial creds refuse everywhere. **Red-proof:** old + creds-required guard restored → all three anonymous tests FAIL with + "registry hitelesítő adatok hiányoznak" visible. Restored green. +- Pairs with hub v0.43.1 (Git Sync form hint: "Opcionális — csak privát alkalmazás-katalógushoz…"). + ### v0.111.0 — remote app-log diagnostics: error context + on-demand log tails (2026-07-10) Extends the app-telemetry pipeline with what the live Peti support session lacked: readable error diff --git a/REUSE.md b/REUSE.md index 77cd46f..9599683 100644 --- a/REUSE.md +++ b/REUSE.md @@ -26,7 +26,8 @@ | `rsyncCopy` | controller/internal/stacks/migrate.go | `(ctx, src, dst, onBytes)` | Additive copy (migration/moves) | `-a --checksum`, NEVER `--delete`; progress2 byte callback; ctx timeout | | `rsyncVerify` | controller/internal/stacks/migrate.go | `(ctx, src, dst) error` | Post-copy verification | Dry-run `-ani`; fails on any pending content transfer; attr-only lines ignored | | `walkMerge` | controller/internal/stacks/migrate.go | `(lg, srcNS, dstNS, skip, assertOnly, onBytes)` | Collision-safe userdata merge | Renames to lowest-free sibling on content mismatch; additive | -| `runCommand` / `runCommandStdin` | controller/internal/selfupdate/updater.go | `(name, args...) (string, error)` | docker CLI in updater | stdin variant for `docker login --password-stdin` (no secret in argv) | +| `runCommand` / `runCommandStdin` | controller/internal/selfupdate/updater.go | `(name, args...) (string, error)` | docker CLI in updater | stdin variant for `docker login --password-stdin` (no secret in argv); package VARS since v0.112.0 — override in tests (fakeRunner in registry_anon_test.go) | +| `parseWWWAuthenticate` + `fetchAnonymousToken` | controller/internal/selfupdate/updater.go | Bearer-challenge parse + anonymous Docker v2 token | Any credential-free registry API access | realm comes FROM THE HEADER (never hardcode a token URL); denial = errAnonymousDenied, never "credentials missing" | | `Syncer.runGit` / `runGitInDir` | controller/internal/sync/sync.go | `(args...) error` | git CLI ops | Credentials masked in logs via `maskRepoURL` | ### HTTP/JSON envelopes + flash messages diff --git a/controller/README.md b/controller/README.md index 1b877df..9085da0 100644 --- a/controller/README.md +++ b/controller/README.md @@ -1403,10 +1403,25 @@ The "Verzió és frissítés" card on the Settings page (`/settings`) shows: - Current version and latest available version - "Frissítés elérhető" (update available) badge - Last check time and any errors +- Registry mode line (v0.112.0): "Registry: nyilvános (hitelesítés nélkül)" vs "Registry: hitelesített" — credential-less is a supported mode, not an error state - Auto-update status with configured time - Last update result (success/failed/pending) - **Buttons:** "Frissítés keresése" (check) + "Frissítés telepítése" (apply) +##### Registry access modes (v0.112.0) + +Git Sync credentials (`git.username`/`git.token`) are **optional — for private catalogs only**; version +discovery and self-update work without them: +- **Anonymous (both empty):** `queryRegistry` performs the Docker Registry v2 anonymous token dance — + plain GET → 401 with `WWW-Authenticate` → token fetched from the ADVERTISED realm (parsed from the + header, never hardcoded — registry-agnostic) with no credentials → Bearer retry. `pullImage` skips + `docker login` entirely (docker's native anonymous flow covers public packages). +- **Authenticated (both set):** the previous BasicAuth + login/pull/logout path, unchanged. +- **Half-configured (only one set):** loud incomplete-credentials error — never a silent anonymous + downgrade. +- A registry that genuinely denies anonymous access surfaces + "registry denied anonymous access — a private registry requires Git Sync credentials". + After triggering an update, the page polls `/api/health` every 3s and reloads when the new container responds. A global info-level alert ("Új controller verzió elérhető") appears on all pages when an update is available, linking to the Settings page.