Koda (Garmin Connect IQ) calls POST /auth/login during sync. Only /rest
and /share bypassed the navidrome-gate, so the gate answered 302 with an
empty body and the watch failed with -400
INVALID_HTTP_BODY_IN_NETWORK_RESPONSE ("Native login failed -400").
An IngressRoute sends /auth and /api straight to Navidrome when the
request carries no authentik_proxy_ session cookie; requests with the
cookie (the web UI) keep going through the gate, so SSO is unchanged.
X-Authentik-Username is stripped on this route as on /rest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner-approved on REN-350. Only the Lidarr pod, only 8686; nothing else in
navidrome is admitted. Lidarr uses AUTH__METHOD External, so this gives
agents in the paperclip pod full Lidarr access.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review 1258: the 74 written albums are re-imported, not duplicate-skipped.
Fix the comment and report before/after mb_albumid per album.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two dry runs were checked; the spot check now matches original releases.
Music mount becomes writable for tag writes; move/copy/delete stay off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first dry run (write: no) matched 78 of 560 albums; some matched
reissues (JP/RU) and would have changed year to the reissue year.
Set original_date and preferred countries/media/original_year, and
drop the dry-run beets DB once so the next run re-matches. Still write: no.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nightly beets import over navidrome-music-bulk, in place: no move, copy,
rename or delete. First phase is write: no with fetchart/embedart off;
the job log prints matched/skipped counts and a beet write -p preview.
Renovate rule for the LinuxServer -ls<n> tag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C.1 (CNPG ha-pg) and C.2 (Velero /config) passed; results are on REN-339.
Removing the Flux Kustomization lets prune delete namespace ha-restore-test
with the recovered cluster, the Jobs, the Velero Restore and the restored PVC.
Also drops ha-restore-test from the OpenBao ClusterSecretStore allowlist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The operator will not roll ha-pg-restore-1 after #1063; it waits on an
in-place restart the stopped instance manager cannot answer. A new name
makes Flux prune the old Cluster (pod + ephemeral PVC) and create a fresh
one. The check Job is renamed too (Job templates are immutable).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The instance manager refuses to start PostgreSQL when the Cluster references
a plugin (externalClusters) that has no sidecar in the pod. Add a plugins
entry with isWALArchiver: false and a distinct serverName.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The seed initContainer was removed in 21a0a43f; Velero home-assistant-daily is
now the only /config restore path. home-assistant-backup-password has had no
consumer since then.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Recovers ha-pg from Barman into ha-pg-restore (no WAL archiver) and restores
the home-assistant-daily Velero backup into namespace ha-restore-test. Two
Jobs log the runbook C.1/C.2 checks. The /config probe is deny-all and never
runs Home Assistant. Nothing in namespace home-assistant changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- gitea.renner.uno/**: pinDigests false. Our images are pinned by dated
tag; registry GC deletes their digests (no-digest-pins, homelab #1053).
- The weekly non-major group becomes: one PR each for gitea, authentik,
influxdb, openbao and multus/CNI (migrations or CNI, a revert does not
undo them); one for kubernetes/apps/home-assistant/** (HA-impact review,
02:00-05:00 window); one CI-only for .woodpecker/** and ci/images/**.
Everything else stays in "all non-major dependencies".
- openbao chart: rangeStrategy bump. The default rewrote the bounded range
">=0.28.4 <0.29.0" to "<0.30.0" (homelab #1054) and dropped the lower
bound; bump gives ">=0.29.6 <0.30.0".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The slim Renovate image installs tools (golang for go.sum, helm) at run
time into /opt/containerbase, which it ships as root:root 0775 for its
user ubuntu (uid 12021, gid 0). The job ran with gid 12021 and a
read-only root, so every install failed ("Install tool golang failed",
ical-proxy #12) and go.sum was never updated.
Run with gid 0 and a writable root file system. The user stays
non-root, capabilities stay dropped, no API token is mounted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner decision on REN-107: option B, 30 days on the existing disk.
retention 90d -> 30d, retentionSize 30GB -> 40GiB, PVC unchanged (50Gi).
At ~1 GB/day the 30GiB cap bound first and the real window was a
20.5-27.2 day saw-tooth; 30d peaks near 38 GB, under the 40GiB backstop.
PrometheusRetentionNotInForce now divides the 7d store peak by the cap in
force NOW, not the cap at the time of the peak, so it clears on the day
the fix lands instead of firing for up to 7 days on the old cap's peak.
Adds tests/prometheus-retention_test.yaml (5 scenarios) and 5
`retention-*` mutations, all caught.
Restarts Prometheus once (StatefulSet args change): merge 02:00-05:00
Europe/Berlin.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`retention: 90d` and `retentionSize: 30GB` are both set on kube-prometheus-stack.
Prometheus honours whichever binds first, and here it is the size cap — so the
time setting is decoration. Measured on the live TSDB through the read-only
proxy grant, 2026-09-26:
storage.tsdb.retention.size = 30GiB -> 32,212,254,720 bytes
storage.tsdb.retention.time = 90d -> 7,776,000 s
window actually held -> 2,291,239 s (26.5 days, 29% of 90d)
Size eviction is not pending — it has been running on a ~7-day cycle for at
least as long as the TSDB keeps history. At 2026-09-19 23:00->23:30 the store
went 28.16 GB -> 21.14 GB, `prometheus_tsdb_size_retentions_total` went 0 -> 1,
and the window held collapsed 27.21 -> 20.48 days. Effective retention is a
20.5-27.2 day saw-tooth. Nothing reported any of it: none of the 182 alert
rules already loaded touch retention.
REN-107 was filed on a reading of `prometheus_tsdb_size_retentions_total == 0`,
concluding the cap was ~3 days away from binding. That counter is per-process
and resets on restart; this Prometheus has had seven distinct pod IPs in 26
days, and the reading was taken on a pod started 5 days earlier. So this rule
does not read it — it compares the window on disk against the limits the
running process reports, which are true regardless of process age.
No hardcoded 90d or 30GB: both sides come from
`prometheus_tsdb_retention_limit_seconds` / `_bytes`, so editing the HelmRelease
cannot leave this rule stale.
Two clauses. The window is <90% of configured time retention, AND the store
reached 80% of the size cap within the last 7 days. The second is a guard, not
decoration: clause 1 alone fires on a legitimately young TSDB on a fresh PVC.
`max_over_time(...[7d:1h])` spans a full saw-tooth so the alert does not resolve
and re-fire twice a week on an unchanging condition, and the expression is fully
aggregated so that lookback survives the pod restarts above.
Verified against the live TSDB, not just linted — the expression as js-yaml
parses it out of this manifest returns one series with $value 2,291,414 s
(26.52 days). Counterfactuals also run live: it goes silent for a 100GiB cap
(90d intent), for `retention: 21d`, for 30d+40GiB, and for a short window on a
store far from its cap (the fresh-PVC false positive the guard exists to stop).
Scope is the alert only. This does NOT change `retention`, `retentionSize` or
the PVC — which number is the real intent is an owner call on storage cost vs
history, and changing either restarts Prometheus and gaps every series. That
decision is on REN-107 for Zeus; the config change is a separate PR.
Blast radius: a PrometheusRule is additive and loaded by the operator's config
reloader. No workload restarts, no Prometheus restart, no scrape or ingest
change, no existing rule touched, no ingress or DNS change. Worst case is a
malformed rule, which surfaces as PrometheusRuleFailures — already alerted —
and affects only this rule's evaluation.
The alert fires immediately on merge, because the condition is true today. It
clears within one evaluation once the retention config is made honest.
Revert: revert this one commit. The rule is deleted and nothing else changes.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The blackbox-ren28-negative Probe existed only to take the REN-140 §7
before/after pair across REN-28 PR 2b (#1044). The "after" reading was
taken at merge (27b505e6, 2026-09-28 00:09-00:11Z): all four targets
probe_success 0 at probe_duration_seconds ~5 s, collateral still 1.
Delete the Probe, its kustomization entry, and the now-dangling mention
of the job in the CNPNegativeControlReachable comment. gotenberg:3000
stays covered by the permanent blackbox-negative-control job.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
npm install -g ignored Paperclip's pnpm override and pulled
claude-agent-sdk 0.3.257. Install from a package.json with the override
(0.3.280) into /opt/claude-agent-acp and link the bin into /usr/local/bin.
The build fails if the SDK version is not 0.3.280.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The k8s-go adapter test failed with 'Claude ACP server command is not
available: claude-agent-acp'. Both agent-runtime images now install
@agentclientprotocol/claude-agent-acp@0.73.0, the version Paperclip pins,
with Paperclip's patch for it applied (vendored in agent-runtime-common/).
go and gofmt are also linked into /usr/local/bin, so every tool is found
with the default PATH, not only with the image ENV. The build checks that
with env -i. Kaniko context is now ci/images so both images can COPY the
shared patch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Paperclip Kubernetes sandbox plugin (0.1.0-alpha.1) hardcodes
agents.x-k8s.io/v1alpha1; v1.0.x serves only v1beta1, so the k8s-go
probe gets 404. v0.5.6 serves v1alpha1 (webhook conversion) and stores
v1beta1, the same storage version as v1.0.4.
- GitRepository tag and controller image -> v0.5.6 (digest pinned).
- Deployment: emptyDir for the self-signed webhook cert (read-only root).
- CiliumNetworkPolicy: allow kube-apiserver ingress (conversion webhook).
- Renovate: hold agent-sandbox below 1.0.0 until the plugin moves to v1beta1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>