The SML power-meter reader was retired by owner decision on 2026-09-19:
grid data comes from the E380 on the CAN bus (wiki
sml-to-e380-grid-meter-migration). Its reader has been unplugged since then.
- register: edge-1 loses write sml2mqtt/# (live, no broker restart)
- bridge templates: no sml2mqtt topic, no legacy sml2mqtt bridge
- remove role power-meter-sml, play install-power-meter.yml, inventory
group power_meter and the vault indirection
- edge-mqtt-bridge play: pre_tasks stop and remove the leftover compose
project on edge-1 on the next pipeline run (idempotent)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The register account `edge-1` replaces the legacy password users open3e
and sml2mqtt for edge-1's local mosquitto bridge. Controller main-cb96b1a
(REN-1308) delivers the password to edge-mqtt-cred over HTTPS with its
client certificate and pins edge-1's server certificate on first contact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
edge-1's bridge password moves out of ansible-vault. A small receiver,
edge-mqtt-cred, speaks the controller's esp32 API over HTTPS with mTLS
(only CN mqtt-account-controller from the MQTT CA) and writes one bridge
`edge-1` for open3e and sml2mqtt. Until the first push the two
vault-password bridges stay in bridge.d/legacy.conf, so nothing changes
on the cluster side yet.
A Woodpecker pipeline runs the role-only play on merge, so no manual play
run is needed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mqtt-account-controller (REN-1284) now pushes the CA and the client
certificate of the register account home-assistant into HA's MQTT config
entry via HA's reconfigure flow, only when tls.crt changed and only inside
02:00-05:00 Europe/Berlin. Mounts mqtt-home-assistant-tls and the HA token
(OpenBao apps/home-assistant/mqtt-cert-sync-token, service user MQTT Cert
Sync), sets the HA env and adds Secret mqtt-ha-cert-sync to the Role.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Step 2 of adopt-then-prune. #1196 put the Secret in the home-assistant
Flux inventory (Ready at 67bc773a). Removing the manifest lets prune
delete it. Nothing reads it since #1191.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Step 1 of adopt-then-prune. The removed shellies bootstrap Job created
this Secret outside Git; nothing reads it. An empty manifest with the
same name and type puts it in the Flux inventory; the follow-up PR
removes the file so prune deletes the Secret.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
homelab#1194 added ExternalSecret gitea/gitea-package-retention, but the
openbao ClusterSecretStore only admits listed namespaces. ESO denies it
("denied by spec.condition") and the gitea Kustomization health check
waits on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing pruned old CI builds in Gitea's registry, so data-gitea-0 was
down to 24% free four days after the grow to 60Gi (~2.2 GB/day).
Gitea 1.21 has no API for cleanup rules and the package owners are
human accounts, so the rule runs as a CronJob in the gitea namespace,
with the write:package-only token Hermes seeded in REN-1204.
Keeps the 5 newest images per CI build package, main/latest, and any
tag a pod runs now. Skips gitea_admin/*, date-tagged packages and
agent-runtime images.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stock agent-runtime-claude base has no /usr/share/zoneinfo:
TZ=Europe/Berlin date prints UTC and Python ZoneInfo raises
ZoneInfoNotFoundError (REN-1195). k8s-base and k8s-go run these images.
Install tzdata and fail the build if Europe/Berlin does not resolve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All Shellies log in with their own Dynamic Security account; the ESP32
open3e-int is decommissioned (owner, REN-1109). Drops both users from the
passwd/ACL, their env and Secret refs, the shellies bootstrap Job, the
open3e-int ExternalSecret, rotator and policy file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reverts homelab#1183 (merge 2f20f214). Controller main-982231a adds the
wake role to its own dynsec client; the broker kicks the client on that
("disconnected by administrative action" 45 ms after every connect), so
the controller never holds a connection and /healthz stays 503.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main-1d03144 adds the per-account register field `rotate: false`
(mqtt-account-controller PR #6, reviewed in REN-1073). Set it on shelly-2
only. Both changes go in one commit: main-a307693 rejects a register with
the unknown field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bump mqtt-account-controller to main-4adc9a6 (shelly-manager#93 client),
give it the shelly-manager API key and URL, and register shelly-5 (Plus i4)
as the first auth: password account. The legacy user shellies stays.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent runs mostly execute in the paperclip pod, not in a sandbox (REN-1001:
TCP timeout to :8884 from paperclip-b65cc7768). Adds the egress rule in
paperclip-egress and the paperclip pod as a source in mosquitto-agent-ingress.
:8884 only; it requires an mqtt-ca client certificate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Register entry agents-read (read open3e/#, zigbee2mqtt/#, homeassistant/#),
delivered to the paperclip namespace; agent kubectl identities may get that
one Secret; dedicated CNPs open agent sandbox pods -> mosquitto :8884.
Nothing restarts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HA keeps MQTT client certificates only as PEMs inside its config entry, so a
renewal could not reach it. A ghostunnel client sidecar listens on
127.0.0.1:11883 and forwards to mosquitto :8884 with the home-assistant
certificate, reloading it on renewal. HA's config entry is pointed there in a
separate HA-side step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Register entry for Home Assistant (ACL readwrite # as the legacy user
homeassistant, different name so it cannot shadow that login) and its Secret
on the controller's revocation list. Nothing restarts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
evcc gets broker URL and the PEMs of the register account evcc-client by
env (EVCC_MQTT_*), which override the mqtt block of evcc.yaml in OpenBao.
Reloader restarts evcc when cert-manager renews the certificate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Register entry evcc-client (deliver evcc, ACL as the legacy user evcc), a
controller Role/RoleBinding in the evcc namespace for its Certificate and
Secret, and :8884 next to :1883 in both evcc<->mosquitto network policies.
Nothing restarts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Z2M, discovery-guard and interview-watch use the certificate of the
register account zigbee2mqtt-bridge on the mTLS listener :8884 instead of
the legacy password. Z2M gets server/ca/cert/key by env because its
configuration.yaml on the PVC is never re-seeded. The init container no
longer renders mqtt_password. The legacy broker user stays until a later
broker roll.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the register entry for Zigbee2MQTT (same ACL as the legacy user
zigbee2mqtt, different name so it cannot shadow the running password login)
and its Secret to the controller's revocation list. Nothing restarts; the
controller picks the register up live and issues mqtt-zigbee2mqtt-bridge-tls
before the Z2M switch lands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the register account mosquitto-probe (auth: cert, readwrite health/#),
mounts its certificate into the broker and switches the liveness/readiness
probes to the mTLS listener :8884. Removes the legacy password user health
from passwd, acl, env and the Reloader annotation. The ExternalSecret and
rotator stay until the REN-802 cleanup step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review 1473: shelly-manager signs in whoever X-authentik-username names when
the peer is in the pod CIDR, so opening :8080 to agent pods let any run sign
in with a forged header and no API key.
Agents now get an nginx sidecar on ${POD_IP}:8081 (Service
shelly-manager-api) that drops X-authentik-username and X-Forwarded-User
before proxying to :8080. Both agent CNPs move from 8080 to 8081, so :8080
stays outpost-only and every agent call needs the API key.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Egress from paperclip-renner agent pods and a dedicated ingress CNP on
shelly-manager, container port 8080 (socket-LB). All agents: sandbox pods
carry no per-agent label; the API key gates calls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The REN-902 build denies publishClientReceive by default and grants receive
per read ACL. On its first loop it rewrites the Secret mqtt-dynsec-seed with
that default. The seed must be rewritten before the production broker loads
it (homelab #1159). Still points at the test broker.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
REN-802 step 2. The production mosquitto loads the Dynamic Security plugin
and gets a mutual-TLS listener :8884 (server certificate from mqtt-ca).
mqtt-account-controller now manages this broker instead of the test broker.
The nine legacy users keep password_file and acl_file unchanged.
The Dynamic Security default denies publishClientReceive: with acl_file in
the chain, mosquitto 2.0 does not gate SUBSCRIBE, so a receive default of
allow would let every Dynamic Security client read every topic.
The image policy stays on 2.0.x, because 2.1 changes the plugin chain.
The obsolete delete grant on mqtt-test-revoke-tls is dropped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The controller must delete Certificate mqtt-test-revoke, Secret
mqtt-test-revoke-tls and the dynsec client and role acct-test-revoke on its
next loop. Only the register ConfigMap changes; nothing restarts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
REN-802 step 1. Adds:
- infrastructure/post-crds/mqtt-ca.yaml: private MQTT CA (self-signed root
in cert-manager ns) and ClusterIssuer mqtt-ca.
- apps/home-assistant/mosquitto-dynsec-test.yaml: throwaway mosquitto 2.0.22
with the dynsec plugin, mTLS listener (require_certificate,
use_identity_as_username), initContainer that loads Secret
mqtt-dynsec-seed or a static base file. ClusterIP only; not labelled
mosquitto, so prod Services and the world-ingress policy do not select it.
- apps/home-assistant/mqtt-account-controller.yaml: ServiceAccount, RBAC
(cluster-wide list certificates; certificates in home-assistant; secrets
by resourceName only), controller client cert CN mqtt-account-controller,
Deployment main-47213ef pointed at the test broker.
- apps/home-assistant/mqtt-accounts.yaml: register with two cert test
accounts, delivered as ConfigMap mqtt-accounts.
The production broker is not changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kubernetes sandbox plugin's release and destroy hooks returned void,
so no lease got a termination receipt and every cancelled pod run left
its card waiting on remote_cleanup. Return state destroyed once the
Sandbox CR / Job (and pod) reads 404, within 20 s; otherwise no receipt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The kubernetes sandbox plugin returns no termination receipt, so the
leases of cancelled runs e08976cd (REN-837) and 144ae3bf (REN-825) were
released without one and the queued owner comments wait on
remote_cleanup forever. The controller log shows both Sandbox CRs
deleted. Write the missing receipt for exactly those leases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The quarterly rotation on 2026-12-01 would change the broker password while
the ESP32 gateway keeps the old one, taking it offline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One-shot Job that sends three read commands on open3e/cmnd to edge-1's
running open3e (read-json + read-raw on 0x6c3, one read-json on 0x6e0)
and prints the replies for Loki. No write mode, no config change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The capture answered REN-805 after 24 min (no setpoint in bytes 42-56);
the owner stopped the remaining 24 h window. Flux prune deletes the Job
and its pod.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
open3e names the topics ..._ZigBeeSixDeviceCurrentValues, so the
[0-9]+ pattern matched none of the 18 DIDs (Argus review 1437).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Job subscribes to open3e/+ as the read-only evcc broker user and prints the
18 One Base FBH ZigBee<N>DeviceCurrentValues messages with a UTC timestamp
to stdout (Loki). Ends after 24 h via mosquitto_sub -W.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Server and LDAP outpost images built from k.renner/authentik-samba-bridge
872f7546 (Authentik 2026.8.3), in lockstep with the 2026.8.3 chart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026.8 honours forwarded headers only from AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS.
Set it to the pod CIDRs Traefik connects from. Bridge image tags follow
once authentik-samba-bridge#4 is merged and built (lockstep pin).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The authentik-samba-bridge hook token was burned in a run log (REN-729).
Woodpecker 3.18 cannot re-key a repo hash via API, so a one-shot Job
sets a new random repos.hash generated inside Postgres. Remove after run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No pod has attached net1 since cni-plugins-installer moved to
containernetworking/plugins v1.9.1 (#1142). Hestia's verify item: restart
mdns-relay and confirm a 10.2.30.x DHCP lease. Atlas has no cluster write,
so the restart goes through a pod-template annotation.
Refs: REN-722
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1132 staged OpenBao 2.7.1 in the StatefulSet template, but OnDelete
leaves the pods on 2.6.1 until someone deletes them, and no agent holds
pod delete in openbao. The static seal makes OnDelete unnecessary: the
readiness probe (bao status) passes only once a pod is unsealed, so the
controller replaces one pod at a time and waits for each.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Point the installer at cni-plugins:2026-10-05, built from #1140
(plugins v1.5.1 -> v1.9.1). Version comments updated in the installer
and cni-dhcp-daemon.
Refs: REN-722
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A VolumeSnapshot of influxdb-influxdb2 on ceph-block-snapclass, to be
merged and ready before homelab #1130 (2.7.4 -> 2.9.1) so the upgrade has
a restore point beyond `influxd downgrade`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chart 0.30 moves the server 2.6.1 -> 2.7.1. Record the rollout rule
next to the pin: raft snapshot first, OnDelete one pod at a time, undo
by snapshot restore once a pod has run the new server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
InfluxDB 2.9 hashes tokens on startup by default. The HA and Grafana
token Jobs read tokens back via `influx auth list`, which returns no
token once hashed, and a downgrade below 2.8 would erase all tokens.
Set INFLUXD_USE_HASHED_TOKENS=false so the 2.9.1 bump stays reversible
with `influxd downgrade 2.4`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refresh the plugins pin alongside multus v4.3.1 (#1131), as the
cni-plugins-installer.yaml comment asks. SHA256 cross-checked against
upstream's cni-plugins-linux-amd64-v1.9.1.tgz.sha256 asset. The tarball
still ships macvlan, static, host-local and dhcp.
Image only: CI builds cni-plugins:<date>. The DaemonSet tag bump follows
in a separate PR once the image exists.
Refs: REN-722
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream deployments/multus-daemonset-thick.yml v4.2.4 -> v4.3.1 adds:
- ClusterRole rule: resource.k8s.io resourceclaims, resourceclaims/status,
resourceslices; get, list (new DRA client)
- terminationGracePeriodSeconds 10 -> 30
- CRD shortName nad
Header comment updated to v4.3.1 (v4.3.1 also has an unsuffixed tag; we
keep -thick to match the manifest).
Refs: REN-722
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Job pod templates are immutable. Without kustomize.toolkit.fluxcd.io/force,
an image bump (Renovate #1129, #1053, #1054) fails the server-side dry-run
and blocks the home-assistant and otbr Kustomizations. Same pattern as the
influxdb token Jobs.
The mosquitto Jobs exit 0 when their Secret exists. The otbr Job now also
exits 0 when the otbr Deployment is scaled to 0 (disabled), instead of
waiting for a pod that never comes and failing; Role gains get on
apps/deployments for that check.
Refs: REN-722
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tini (PID 1, root) cannot signal node (uid 1000) without CAP_KILL, exits
with EPERM on every rollout, and the server is killed without its
graceful run drain. In-flight runs are orphaned instead of being
interrupted and retried.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One Matrix room per card labelled 'matrix' (REN-668). Sets
PAPERCLIP_PUBLIC_URL for the card link in the room topic.
Rollback: build.1791177680 and drop the env var.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Route agent comments on author account only, from konairius/matrix-bridge#5
(9a83e70, REN-668). No env, secret, port or network change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The three Matrix Ingresses had no dns.renner.uno/public label, so
netbird-service-sync never created a NetBird proxy service for them and the
public proxy rejects their SNI (tlsv1 alert internal error). Label them like
audiobooks/immich and add Gatus checks for the three hosts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
as_token and hs_token come from an ESO Password generator (CreatedOnce)
instead of OpenBao, so no one has to seed them by hand. Synapse mounts
only the generated Secret and no longer depends on the OpenBao path;
OpenBao homelab/apps/matrix-bridge now holds only paperclip_api_key.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the matrix-bridge Deployment, Service and ExternalSecret in the
matrix namespace, loads its appservice registration in Synapse, and opens
the bridge -> Paperclip API path (:3100) in both namespaces' policies.
Tokens and the board key come from OpenBao homelab/apps/matrix-bridge.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Authentik 2026.5 checks each authorize against the provider's
grant_types, and a provider created by a blueprint starts with an empty
list. Every Matrix login through Authentik failed with invalid_request
(log: "Invalid grant_type for provider", grant_type=authorization_code).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner wants QR sign-in from the desktop app as well. Linking a phone from
a signed-in Element (Link new device) only needs the server side from the
previous commit (MSC4108 + MAS device-code grant). This flag also lets a
new browser sign in by QR.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Element X signs in only with a password or through MAS. Put MAS in front
of Synapse with Authentik (passkey) as the upstream provider, and enable
the QR rendezvous (MSC4108/MSC4388).
- apps/matrix/mas.yaml: MAS 1.26.0, `mas` database in mx-pg (CNPG
Database), account.matrix.renner.uno.
- synapse.yaml: matrix_authentication_service, password_config off; a
syn2mas init container moves the existing accounts and sessions once
(marker on synapse-data).
- Drop the owner-account Job; MAS owns accounts now.
- Authentik: public PKCE client `matrix-mas`, passkey flows, only the
Matrix Users group (k.renner).
- matrix-ns: MAS egress to Traefik :8443 (auth.renner.uno) only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scoped access for the zwave-js restart (REN-628): forced-command user
atlas-zwave on edge-1. One /32, TCP 22 only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Loki runs SingleBinary with auth disabled and answers GET on
/ingester/shutdown and /flush, so an RBAC `get` on services/proxy for
loki:3100 would not be read-only. Put an nginx allow-list in front of it
(query, query_range, labels, label/<name>/values, series; GET only;
upstream URI rebuilt per location) and grant the paperclip read SA
`get` on that Service only. Owner decision: REN-622 (option A2).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The primary pclp-pg-2 was OOMKilled 6 times on 3-4 Oct at the 1Gi
limit. Each kill drops Paperclip's DB and fails in-flight agent runs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1116 left spec.volumeName out of pvc.yaml. kustomize-controller has owned
that field since the namespace move pre-created the claim (eb23d3ac), so
server-side apply tried to clear it and the API server rejected the claim
as an immutable-spec change. The gitea Kustomization is Ready=False and the
claim stays at 40Gi. Pin volumeName to the live value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The volume filled on REN-580. volumeClaimTemplates is immutable, so own the
live claim data-gitea-0 in apps/gitea/pvc.yaml (prune disabled) and let Flux
server-side apply grow it; ceph-block expands online. Add GiteaDataVolumeLow
(<25% free for 15m) with a promtool suite and two mutation controls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stable session fingerprint for the per-run managed AI home paths, plus a
persistent CLAUDE_CONFIG_DIR/projects so the resumed session finds its
transcript. Local runs only. Fix-forward of #1111 (reverted in #1113).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This reverts #1111 (3f3305cf). With the fingerprint stable, the ACPX engine
now resumes the previous Claude session, but the Claude transcript lives in
the per-run CLAUDE_CONFIG_DIR, which the server deletes after each run. acpx
uses resumePolicy same-session-only for persistent sessions, so the turn
fails ("Persistent ACP session ... could not be resumed: Resource not
found") instead of falling back to a fresh session (run 12a2a911).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New `matrix` namespace and Flux KS: Synapse v1.162.0 on a CNPG Postgres
(mx-pg, Barman to Hetzner), media store + signing key on synapse-data
(Velero matrix-daily), Element Web locked to matrix.renner.uno, and an
idempotent Job that creates the one owner account from OpenBao
apps/matrix. Federation off, registration and guests closed, LAN-only
ingress, egress limited to the in-cluster DB and the push gateway.
Appservice slot left empty for REN-565 Part 2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The -v2 token leaked into Argus run d2eede8a (REN-542). Renaming makes the
token controller mint a new token; Flux prunes the old Secret, which
invalidates the leaked token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The agent-atlas-token-v2 token leaked in an Atlas run log (REN-536).
Rename the Secret to -v3 so Flux prunes -v2 and the token controller
issues a new token; update the agent-token-read resourceNames entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude auto memory defaults to $CLAUDE_CONFIG_DIR/projects/<p>/memory.
Paperclip makes CLAUDE_CONFIG_DIR fresh per run and deletes it, so every
memory is lost. New image patch: the ACPX engine writes
autoMemoryDirectory=<AGENT_HOME>/memory into the per-run
.claude/settings.local.json. AGENT_HOME is restored and saved around each
run, local and in k8s pods. Not part of the session fingerprint, so
resume is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The token leaked into Hestia run 13bd8a68 (REN-535). Renaming makes the
token controller mint a new token; Flux prunes the old Secret, which
invalidates the leaked token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GITEA_VERIFY_REPO still named k.renner/shelly-manager, which now
answers 307 to the new path. Point it at the new path directly.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In-cluster app-health target via the ClusterIP Service, so a dead app
behind the live shelly-manager-gate outpost no longer reads green.
Covered by the existing BlackboxProbeFailing rule; no CNP change needed
(home-assistant default-deny already admits the monitoring namespace).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The token leaked into Argus run 373367ed (REN-523). Renaming makes the
token controller mint a new token; Flux prunes the old Secret, which
invalidates the legacy token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The three tokens leaked into run logs (REN-483, REN-484, REN-507).
Renaming makes the token controller mint new tokens; Flux prunes the
old Secrets, which invalidates the legacy tokens.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The host/remote-node rule had no toPorts, so any node or hostNetwork pod
could reach the relay's unauthenticated gRPC on :4245. Restrict it to the
kubelet gRPC probe port (chart deployment.yaml probes use port 4222).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yaml-citations failed on external-secrets-podmonitor.yaml:35, which cited the
upstream chart's values.yaml by line. That file is not in the repo, so no
path#anchor form exists; name the keys instead. Comment-only change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hubble is already on in every agent; the relay gives one gRPC endpoint so
`hubble observe -n paperclip-renner --verdict DROPPED` runs without exec
into kube-system. The chart renders no change to cilium-config or the agent
DaemonSet, so the reloader does not roll the CNI.
The relay has no client auth: a new CNP admits only the paperclip pod (and
nodes for probes), and paperclip-egress gains the matching :4245 rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Built static in the go stage with go install (module checked against
sum.golang.org); added to the default-PATH check and the README table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- apiserver CNP selects paperclip.io/role=agent: the plugin writes the run id
into paperclip.io/agent-id, so the agent-id selector never matched (REN-428).
- agent pods reach the wiki API (egress here, ingress in ai-ns.yaml).
- FQDN allow for api.github.com, GitHub release-asset hosts, vuln.go.dev,
uptime.renner.uno.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immich-server mounts immich-library-bulk + immich-thumbs since 4cc1b643;
immich-library is mounted by no pod but is still backed up (~250 GiB)
and restored by the restore test. The newest immich-daily backup
(immich-daily-20261001051507) holds immich-library-bulk and immich-thumbs.
Drop the PVC manifest and update comments that cited it. The PVC keeps
prune: disabled, so this merge does not delete the live volume; that is
a separate, owner-approved step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On 2026-10-01 the immich restore took the fullest OSD from 74% to 95%;
the Job died at its deadline, the Restore kept writing unwatched and
Ceph went OSD_FULL at 15:10.
- Mid-run guard: each restore poll reads the fullest OSD; at 83%
(OSD_ABORT_PCT, below nearfull) or after 4 polls with no reading,
cancel the DataDownloads, tear the restore down, stop the sweep (FAIL).
- A restore timeout cancels the same way.
- TERM/EXIT trap cancels the restore in flight; grace period 600 s.
- Time budget: no restore starts whose timeout + 900 s reserve passes
the Job deadline (SKIP).
- RBAC: get/list/patch on velero.io datadownloads only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Restore took every PVC in the backup, and the parity probe then
snapshotted and cloned each restored PVC name in the live namespace. A
backup that holds a CNPG PVC would give two extra copies of the
database, one of them next to production.
- Restore: labelSelector cnpg.io/cluster DoesNotExist.
- Parity loop: only restored PVCs without cnpg.io/cluster.
- Capacity gate: leave CNPG DataUploads out, and add the source-side
probe clone (size-3 pool) for every PVC the run will probe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Before each schedule's restore, project its raw size (DataUpload
totalBytes x pool replication/EC factor, spread over all OSDs) onto
current OSD usage from Prometheus. If the fullest OSD would go above
OSD_MAX_PCT (80), skip the schedule and report SKIP with the projected %.
Skips are listed in the summary and do not fail the Job; a projection
that cannot be made fails that schedule without restoring.
Allows the restore-test pod to reach Prometheus :9090 and notes the gate
in RECOVERY.md. No alert rule changes. Refs REN-441, REN-442.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The WS90 reporting configuration (zigbee2mqtt-ws90-reporting.md) only
lived on the device and in database.db; every interview or
device/configure reset it to the converter defaults (2026-09-24..28,
zero frames recurred).
New external converter extends the built-in WS90 definition with a
configure step that sets the documented values. Its version
(ws90-reporting-1) makes Z2M reconfigure the device once after load.
seed-data copies converters from a ConfigMap into
/app/data/external_converters on every start; not mounted because Z2M
writes a temp copy into that directory while loading.
Tested in the running pod against a mocked device: the definition is
picked over the built-in one, and configure ends with the ten
documented reporting values.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Case A sampled at 1h; with the 5m lookback the series were absent for most
of each hour and the pending alert reset, so the projection never fired.
Now 5m samples (1m exceeds promtool's sample limit on the 7d rate), same
0.04272 %/day and 140-day summary.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner decided EPHEMERAL (/var) drives run to failure (REN-420), so
NvmeDriveWearProjectedExhaustion and NvmeDriveWearCritical now skip the
drive carrying /var. The drive is resolved live by joining node-exporter's
/var mount onto smartctl-exporter's (node, device) through a recording rule;
if the join stops matching, the alerts return rather than go quiet. Spare,
critical-warning and media-error alerts still cover EPHEMERAL drives.
Adds a promtool suite and four negative controls for the exclusion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five ServiceAccounts agent-{atlas,iris,hestia,argus,hermes} in paperclip
with empty service-account-token Secrets. The four readers get the same
rights they hold today via the shared pod SA: `view` cluster-wide and the
existing monitoring/paperclip-prometheus-read Role. Hermes and the shared
SA get `get` on the five named token Secrets only.
CiliumNetworkPolicy paperclip-renner/paperclip-agents-kube-apiserver lets
the five agents' pods reach the kube-apiserver entity on 6443.
Spec: REN-412. Nothing restarts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gitea.renner.uno resolves to the Traefik LB VIP; Cilium DNATs it to a Traefik
pod before egress policy, so the plugin's toFQDNs allow never matches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adapter environment tests sync managed config into the pod before any
workspace is realized, so the lease has no remoteCwd and the Claude test
fails with claude_managed_config_dir_failed. #13733 fixes only the run
path. #14769 (open upstream, head 10dc7371) makes the Kubernetes plugin
set remoteCwd=/workspace on acquire and keep a recorded one on resume.
The plugin build from REN-405 is unchanged, so dist/ carries the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's production target ships the plugin source without dist/, so the
plugin loader reports paperclip.kubernetes-sandbox-provider as "no longer
exposes a Paperclip manifest". prepare.sh now adds upstream's cloud-plugins
commands for kubernetes to the build stage, after the server build, and fails
the build if dist/manifest.js is missing. The #13733 patch is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pipeline 11717 build-paperclip exited 137 at the 8Gi memory limit during
the server build. Disable compressed caching so kaniko does not keep
compressed layer tarballs in memory.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
k8s sandbox runs fail because the run path never sets the lease remoteCwd
(paperclipai/paperclip#13864). The fix, paperclipai/paperclip#13733, is not
merged upstream yet. Build our own image from the master commit the nightly
runs now plus that patch, and point Flux image automation at it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node derives the V8 heap from the container limit: 512Mi gave a
259 MB heap, and Z2M crashed with "JavaScript heap out of memory"
(exit 134) at 2026-09-28 17:56Z and 2026-09-29 07:36Z. Request
raised to 256Mi to cover the measured 232Mi working set.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
main-926ead0 includes ical-proxy PR #7 (REN-230): the upstream response
body is capped at 2 MiB, so an oversized feed gets 413 instead of being
buffered whole into a 256Mi pod. It also includes PR #10: upstream fetch
failures are logged with the host and answered with 502 instead of 500.
Refs: REN-294
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the #1046 merge (pipeline 11306) the build-agent-runtime step got no
pod: the full rebuild of build-ci-images.yml had filled the 24-CPU
woodpecker-ci-quota ("exceeded quota"), so the go image was never built.
Move the step to .woodpecker/build-agent-runtime.yml. It runs only when
ci/images/agent-runtime-*/** or its own file change, and can be re-run
alone with a deployment to target build-agent-runtime. Step content is
unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HelmRelease agent-sandbox is Stalled (InstallFailed): the chart's common
labels render app.kubernetes.io/version from image.tag (contains the
digest, >63 chars) and helm.sh/chart with Flux's +<rev> suffix. Remove
both labels in a kustomize postRenderer. Selector and pod labels are
unaffected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first push of this branch started all 13 build steps: the push trigger
had no branch filter. 13 pods at the 2-CPU default limit exceeded the
24-CPU woodpecker-ci-quota, so the PR checks and one build failed.
- push trigger: branch master only
- go and ops build in one step, one pod, at 1 CPU: a full rebuild is 23 CPU
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two pod images for the Paperclip Kubernetes sandbox (REN-284 step 2):
the stock agent-runtime-claude, pinned by digest, plus
- agent-runtime-go: Go 1.27.1, golangci-lint v2.14.0
- agent-runtime-ops: kubectl v1.36.5, flux v2.9.5, kustomize v5.8.1, helm 4.3.0
Tools are copied from their upstream images pinned by tag and digest, so
the existing Renovate dockerfile manager bumps them. Pushed to
konairius/agent-runtime-{go,ops}/agent-runtime-claude:v1 because the plugin
keeps that name and swaps only the registry prefix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
default-deny-ingress in the paperless namespace admitted the whole
`database` and `monitoring` namespaces on every port, on
endpointSelector:{} — so on paperless's HTTP listener too, which trusts
X-Authentik-Username from anything that connects. Both admits are
removed and the three load-bearing flows are kept as per-workload
policies:
pprl-pg-allow-cnpg-operator database/cloudnative-pg -> pprl-pg :8000
pprl-pg-allow-prometheus monitoring/prometheus -> pprl-pg :9187
paperless-allow-blackbox monitoring/blackbox -> paperless :8000
No ICMP rule on them (REN-144 option (a)); the baseline ICMP and the
host/remote-node L3 admit are untouched.
Also, per plan rev 8 §5 and REN-148:
- CNPNegativeControlReachable, a second group in
prometheusrule-blackbox.yaml, scoped to job=blackbox-negative-control.
- Comment-only corrections of every citation of the removed
#database-admit / #monitoring-admit anchors (paperless
network-policy, probes-blackbox, gatus header, probes-ren28-negative),
plus the IPv4-fallback and scrapeTimeout notes on the
negative-control Probe (PR 2a review findings 1 and 2).
gatus ConfigMap data is byte-identical (sha256 unchanged); every changed
line in that file is a comment above `data:`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Argus's review of PR #1032: the name exists in neither pkg/ nor the metrics
docs for 1.20.2, and the agent skips unknown --metrics names silently. Zeus
dropped it from scope. metricsService, the Service delete and the new
selector stay.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- prometheus.metrics: +cilium_policy_verdict_total (opt-in; per-direction
policy verdict attribution on top of cilium_drop_count_total).
- prometheus.metricsService: true, so the chart renders the headless
`cilium-agent` metrics Service.
- Drop the hand-declared `cilium-agent-metrics` Service from
cilium-servicemonitor.yaml and point the ServiceMonitor at the chart's
Service, so the endpoints are scraped once, not twice.
This is a values change: helm-controller upgrades the CNI release, the
cilium-config `metrics` key changes, and the reloader annotation rolls the
agents node by node. Merge only inside the window Zeus set on REN-166.
Revert: git revert this commit; Flux restores the old Service and selector
and rolls the agents back the same way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The previous wording claimed home-assistant-ns.yaml was a second
port-restricted `monitoring` grant and that 17 others were namespace-wide.
Both numbers were wrong. Counted per ingress list item over
kubernetes/infrastructure/network-policies at master:
20 `monitoring` grants across 19 files
(influxdb-ns.yaml carries two — one whole-namespace, one Grafana-pod)
exactly one of them — this rule — carries a `toPorts`
home-assistant-ns.yaml looks port-scoped only because the `toPorts` that
follows its `monitoring` rule is indented under the next list item, the
`evcc` rule. Its `monitoring` grant is namespace-wide.
Comment-only. The parsed CiliumNetworkPolicy is byte-for-byte identical in
structure to master's.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment-only. No manifest field changes, so `kustomize build` output is
byte-identical before and after.
Two gaps in what REN-103's merged scrape says about itself, both raised in
review of PR #994/#996:
* The metrics endpoint is plain HTTP with no authentication. That is chart
2.11.0's default (`metrics.listen.secure.enabled` and
`metrics.listen.auth.enabled` both false, values.yaml:365-369) and this
repo overrides neither, so what actually bounds the exposure is the
CiliumNetworkPolicy, not the endpoint. A reader adding `tlsConfig` to the
PodMonitor would have broken the scrape; say so in the file.
* The network policy comment implied the grant reaches the controller. It
does not: the CNP's `endpointSelector` is {}, so monitoring→:8080 is
admitted for all three ESO deployments, which all serve metrics on that
port. Only the controller is scraped, because the PodMonitor's selector is
exact on the unsuffixed name. Reachable-but-unvisited is the accurate
description and the one a future reader needs.
Also corrected two counts in the same comment. The port-scoping is not unique
in this directory — home-assistant-ns.yaml does it too, so 17 of the other 18
`monitoring` grants are namespace-wide, not all 18. And there is no single
"health port": the controller's is 8082, the webhook's and cert-controller's
are 8081 (values.yaml:501-504, 564-570, 882-885).
Revert: `git revert` this commit. It restores the previous comment text and
touches no applied field.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The local-login connection stores only the ~8h OAuth access token and
Paperclip never refreshes Anthropic credentials (subscription values
are injected read-only as CLAUDE_CODE_OAUTH_TOKEN). It expired 8h after
the login and every run failed with 'terminal access failure'.
Replacing the secret value with a claude setup-token token fixed it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 21:59:31 +02:00
208 changed files with 7987 additions and 1079 deletions
Plus per-namespace `pod-security.kubernetes.io/enforce: restricted` and a deny-all NetworkPolicy baseline with explicit egress allow-list (DNS, paperclip-server, configured FQDNs/CIDRs).
+The lease starts with `/workspace` as the native file-sync confinement root. Adapter environment tests can upload managed config before the server realizes a workspace. When resuming a lease, the provider keeps a previously recorded `remoteCwd` so a custom realized workspace is not replaced with the default.
+
The per-run Secret carrying the bootstrap token and adapter API keys has `ownerReferences` pointing at the owning Job, so a single `kubectl delete job …` cascades cleanly to the Pod and Secret.
@@ -16,7 +16,7 @@ credentials are out of scope (see "Deferred").
|---|---|
| Execution model | **B — server-local runs** (upstream default): agent CLIs are child processes of the server, in the server container. Trial only. |
| Upgrade path | If Paperclip is kept: **C** — `@paperclipai/plugin-kubernetes` sandbox provider + kubernetes-sigs agent-sandbox controller (`agents.x-k8s.io`), per-run Pods and Secrets. Separate spec. |
| Claude auth | **One shared Claude subscription AI connection**, created once via Paperclip's local sign-in (`claude auth login` into `ai-local-logins/<id>`); Paperclip stores and refreshes it. Server-env `CLAUDE_CODE_OAUTH_TOKEN` is not used: `stripAiAuthBindings` blanks it for managed runs, and upstream accepts no pasted setup-token (the device-code flow needs a Daytona sandbox). |
| Claude auth | **One shared Claude subscription AI connection**, created once via Paperclip's local sign-in (`claude auth login` into `ai-local-logins/<id>`), then its value replaced with a long-lived `claude setup-token` token. Paperclip stores the value as company secret "My Claude subscription" and injects it per run as `CLAUDE_CODE_OAUTH_TOKEN`; it never refreshes Anthropic credentials, so the login's ~8h access token expires (runs then fail with "ACP agent reported a terminal access failure", 0 tokens). Renew by rotating that secret with a new setup-token (~yearly). Server-env `CLAUDE_CODE_OAUTH_TOKEN` is not used: `stripAiAuthBindings` blanks it for managed runs, and upstream accepts no pasted setup-token (the device-code flow needs a Daytona sandbox). |
| Bot credentials | Out of scope. Future "AIR-Manager" Paperclip role handles permission requests. |
| Exposure | LAN-only, behind an Authentik forward-auth gate, then Paperclip's own login. |
@@ -189,7 +189,8 @@ available since v0.35.0). First use of digest reflection in this repo.
**as the node user** (the entrypoint makes exec sessions root, and root-owned 0600
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
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.