source-controller v1.9.5 uses go-git v5.19.1, whose documented RedirectPolicy
default is "initial", mirroring git's http.followRedirects: follow the
redirect on the discovery request and use the redirected URL as the base for
follow-up requests. The break-glass stays as a fallback only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Snapshot collaborators, konairius teams and branch-protection whitelists
before the transfer and compare after (Gitea drops collaborators who are
members of the new org).
- Break-glass suspends the flux-system Kustomization so it cannot re-apply the
old URL.
- Task 1 notes the off-cycle mint of both review-bot PATs and checks the
k.renner org holds only the two org secrets.
- Prompts move out of the branch PR into a post-rename PR to main, which
rebuilds the review-bot image (build-ci-images would not fire otherwise).
- Expected side effects of the transfer PR listed; greps widened to the whole
repo; wiki-maintenance cron deleted (no pipeline uses it); GitHub mirror gets
its default branch switched before master is deleted.
- Verified facts recorded: transfer collaborator rule, repair copies the
default branch, repo/cron ids, org secret inventory, repoRenameBranch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two cut-overs with their own windows, prep PRs and rollbacks, built on the
2026-10-18 inventory (repo references, live Flux/Woodpecker/rotator state,
workstation consumers) and the pattern proven on the five repos moved the same
day.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes the Paperclip deployment (namespace paperclip, CNPG cluster
pclp-pg, ingresses, image automation, server image build) and the
infrastructure that existed only for its agents:
- agent sandbox: paperclip-renner namespace and CNPs, the
kubernetes-sigs/agent-sandbox controller with its namespace, CNP and
Renovate rules
- agent-runtime-{go,ops} images and the build-agent-runtime pipeline
- matrix bridge (Element <-> Paperclip agents) and synapse's appservice
registration mount
- monitoring loki-read-gateway (only called by the paperclip Role)
- MQTT account agents-read and the controller's RBAC in ns paperclip
- the OpenBao secret-exists-check policy file
- agent admits in the wiki, lidarr, shelly-manager, mosquitto and
hubble-relay CNPs; the paperclip-api Gitea webhook host; the wiki API
key; the ClusterSecretStore namespace entry; the pclp-pg RECOVERY row
- the Paperclip design spec and plan
Authentik group "Paperclip Users" is switched to state: absent so the
blueprint deletes it. package-retention's EXCLUDE_PACKAGES becomes
optional, since its only value was the agent-runtime prefix.
The shelly-manager api-proxy sidecar stays: mqtt-account-controller
calls shelly-manager-api too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gitea-mcp advertises its -H URL as the authorization server in the OAuth protected-resource metadata, so clients doing discovery were sent to http://gitea.gitea.svc.cluster.local:3000. Switch -H to https://gitea.renner.uno; egress now goes to Traefik (as woodpecker-server and wiki already do) and the gitea:3000 grant on both sides is removed. Tool results' clone_url/html_url become public URLs too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Implementation plan for docs/superpowers/specs/2026-10-10-backup-verify-cloud-vm-design.md:
PR A image, PR B jq filters + scripts + manifests (CronJob suspended)
with offline fixture/stub tests, live runs, PR C cut-over.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Design for replacing the monthly Velero restore-test: an in-cluster
CronJob creates a throwaway VM in fsn1, which runs kopia snapshot verify
(100% of files, read-only) against every latest DataUpload snapshot and
checks sizes against DataUpload totalBytes. No restored data is written
to the Ceph OSDs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The proxy-grant paragraph named `prometheus-read-rbac.yaml` and
`helmrelease-prometheus.yaml` by bare filename. Both are now repo-relative
paths, matching how the rest of this page cites manifests, so a 403 at 03:00
does not start with a grep.
Docs-only. No manifest changed. `docs/` is outside every Flux Kustomization
`spec.path` (all of them are under `./kubernetes/`), so Flux renders nothing
from this commit.
Follow-up to Argus's non-blocking note 2 on REN-113/REN-47.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Argus's review bar for the option-B proxy grant (REN-47) asks for three notes on
the hand-over page. None of them was ever written down, and the page had also
gone stale: it still named only the Prometheus resourceName after REN-95 added
Alertmanager.
Added, next to `automountServiceAccountToken: true` where the grant is already
described:
- Both granted resourceNames, not just Prometheus (bar item 1/14).
- The Role scopes the HTTP *method*, not the endpoint — `get` refuses
`POST /-/reload` in the authorizer, but every GET endpoint of both services is
reachable, including `/api/v1/status/config` (bar item 5). Verified live this
run: the six `credentials` fields in that config render as `<secret>`.
- Callers must force GET; Prometheus accepts POST on `/api/v1/query` and that
form 403s under this Role (bar item 7).
- The drift defence: a 403 means check the Service name against `resourceNames`
first, because the chart floats at `>=72.0.0` and a rename breaks this path
silently (bar item 15).
BLAST RADIUS: none. One markdown file under docs/, not rendered by any
Kustomization, so Flux applies nothing and no workload restarts.
REVERT: revert this commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Owner picked option B on REN-37: reach Prometheus through the apiserver
service proxy under an RBAC Role holding one verb, instead of an L4 Cilium
allow on :9090.
The port cannot be the boundary. The chart leaves `reloadStrategy` unset, so
the operator defaults it to HTTP and appends `--web.enable-lifecycle`, which
puts `POST /-/quit` and `POST /-/reload` on :9090 with no auth in front of
them. An L4 allow cannot distinguish those from `GET /api/v1/query`. The
apiserver can: it maps HTTP method to RBAC verb, so a Role with only `get`
refuses both in the authorizer before the request reaches Prometheus.
ServiceAccount paperclip/paperclip-prometheus-read
Role monitoring/paperclip-prometheus-read
get on services/proxy, resourceNames:
["kube-prometheus-stack-prometheus:9090"]
RoleBinding monitoring/paperclip-prometheus-read -> the SA above
paperclip.yaml serviceAccountName + automountServiceAccountToken: true
Shape copied from monitoring/ci-diagnostics-rbac.yaml, which has run this
same proxy path for the alert-monitor since 2026-07-16. No network-policy
edit: paperclip-egress already allows kube-apiserver on 6443.
BLAST RADIUS: applying this restarts the paperclip pod, and every agent with
it. Nothing in production monitoring restarts — Prometheus, Alertmanager,
Loki and the ingress controllers are untouched.
REVERT: revert this commit. One commit, four files, no state left behind;
Flux prunes the SA, Role and RoleBinding and rolls the pod back to no
mounted token.
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>
The cluster-internal name keeps working when runs move to sandbox pods
(option C), where loopback would not reach the server. The name is
added to PAPERCLIP_ALLOWED_HOSTNAMES because the private-hostname guard
otherwise returns 403 for it. Same-namespace traffic is already allowed
by the baseline CNP in both directions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream derives the agents' PAPERCLIP_API_URL from the public URL, so
agent API calls went out through Traefik to the paperclip-gate outpost.
With intercept_header_auth the outpost treats the agent's Authorization
header as an Authentik credential and returns 401; agents could not
create tasks, post cards or update status.
Agents run in the server pod (option B), so PAPERCLIP_API_URL is set to
http://localhost:3100 (upstream keeps an explicit value and passes it to
every run). Loopback passes the private-hostname guard and agent JWTs
still authenticate each call; the gate stays fully enforced for browser
traffic instead of carving out /api/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first admin is claimed, so PAPERCLIP_AUTH_DISABLE_SIGN_UP flips to
true.
Spec: Claude auth is a Paperclip-managed subscription connection created
once via the local sign-in. The server-env CLAUDE_CODE_OAUTH_TOKEN was
never used (stripAiAuthBindings blanks it for managed runs; upstream
accepts no pasted setup-token), so it is dropped from the spec. The
login must run as the node user: exec sessions start as root and
root-owned 0600 credentials are unreadable to the server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>