2.6 KiB
REPORT — CI runs the static catalog gate on every push (R-168, 2026-08-02)
Overwritten per the standing rule. The prior contents (catalog_gates --fast + the pre-push hook, same day) have their durable record in CHANGELOG.md.
No version bump, no build, no deploy. This adds .gitea/workflows/gates.yml and a CHANGELOG
entry. Nothing compiled changed.
What changed
.gitea/workflows/gates.yml — on every push, a Gitea Actions runner obtains this repo at the
exact pushed SHA (shallow git fetch, no uses: step anywhere) and runs
python3 scripts/catalog_gates.py --fast and nothing else. The exit code is the job's result: no || true, no
pipe that could swallow it.
It REPORTS, it cannot REFUSE, and the workflow header says so in the pre-push hook's voice: this
repo pushes straight to main with no pull request, so there is no merge for a status check to stand
at. The refusing half is .githooks/pre-push (per-clone, --no-verify-able); this half notices when
that was skipped. Making CI blocking needs branch protection plus a PR workflow — an operator
decision, tracked as felhom.eu OPEN-ITEMS.md R-169.
A failed run emails the operator. Probe P5 measured that Gitea itself sends nothing on a
failed run — no mail, no notification row, no log line — so the workflow sends its own via Resend and
prints the provider's accepted id, making "a message left the machine" an observable. Demonstrated on
a real red run in felhom.eu: RESEND-ACCEPTED id=5ff34766-c5f8-4588-8104-08296aeb45ab.
--fast only, and that is the point. check-image-pins.py runs; check-image-resolvable.py
(network) and check-volume-persistence.py (Docker, minutes per app) do not. CI that pulls 53
images on every push gets disabled, and the bypass becomes the habit. No sibling clone is needed
here — unlike the controller and the agent, catalog_gates --fast does not invoke the shared reuse
checker.
Verification
First run: run #1, id=10, conclusion success, sha aa57588f.
Scenario F proven from the run log: image-pin gate OK — 53 templates, 0 unpinned images, the
skip announced (--fast SKIPPED: image-resolvable, volume-persistence …), and zero lines of
resolvability output, volume-persistence output, canary output or image pulls.
The runner is unprivileged host-mode, shared with the other three repos on a single owner-scoped
registration (measured: all four repos' tasks claimed by felhom-gates-runner). Full probe detail,
the security posture and the teardown: felhom.eu/documentation/audits/SPIKE-ci-runner-2026-08-02.md
and felhom.eu/REPORT.md.