feat(mirrors): verify push mirrors from the receiving side, on a schedule #967
No reviewers
Labels
No labels
burndown-2026-06
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/infrastructure!967
Loading…
Reference in a new issue
No description provided.
Delete branch "aos/claude/wz68-mirror-watch"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Nothing watched the Tangled mirrors. A push mirror can fail and keep failing with no outward sign, which is the failure coilysiren/inbox#440 named as the whole reason the server-side shape was chosen.
The obvious check is the wrong one
Forgejo exposes
last_errorandlast_updateper mirror, and a monitor built on them reports healthy through the exact failure it exists to catch:last_updatetimestamps the attempt, not the outcome. Observed on 2026-08-27: all three mirrors advanced it while every push was being rejected for an unregistered key.last_errorcan stay empty through total data loss. A knot running an outdated version drops pushes, pull requests, issues, and invites without reporting an error.paulvall.dev/fidexists because of this.So this asks the receiving side instead: compare
refs/heads/mainon both forges. Only the receiver knows whether anything arrived.What landed
scripts/check_mirror_sync.py- anonymousgit ls-remoteon both sides, compares, exits 1 on divergence or unreadability.scripts/mirror-targets.json- the three mirrors..forgejo/workflows/mirror-sync-watch.yml- every six hours, plusworkflow_dispatch, plus on PRs that touch the checker itself.just mirror-sync-checkandjust mirror-sync-check-test.No credentials anywhere. Both forges are public, so the check reads them anonymously, and alerting goes through the existing in-cluster
signoz-telegrammapper which holds the Telegram identity itself. The job carries no secret at all.Proven in both directions
A monitor that has only ever passed is unproven, so the failure path was exercised against live endpoints before landing.
12 unit tests, all green, covering divergence, both unreadable directions, timeout, and malformed target lists.
Two deliberate choices worth reviewing
The target list is static rather than derived. Forgejo's push-mirror API is the owning source, but reading it needs an admin token, and a credential-free check was judged worth more than a derived list. The cost is that a new mirror goes unwatched until listed, which
mirror-targets.jsonstates in its own comment. Reverse this if the drift risk outweighs the credential.It refuses when
ls-remoteanswers with more than one ref.git ls-remote <repo> mainmatches any ref ending inmain, and a stray mirror ref did exactly that on mcp-beaver, doubling the answer and corrupting 25 files downstream (#963). This asks for the full ref name and refuses a multi-ref answer rather than taking the first line.Not included
No automatic repair. #440 kept the read-only-detector split deliberately, and repair stays an operator action.
Closes coilysiren/inbox#441