# infra/gitea — platform settings that are NOT GitOps-managed Gitea's own repo settings (branch protection, required status checks, approvals) live in Gitea's database, not in a manifest Flux reconciles. They are therefore **drift-prone and invisible to the gate** — exactly how the state below went unnoticed. ## The gap this closes Verified against the live API on 2026-09-29, against a `DECISIONS-LOG.md` entry (2026-08-31) asserting the opposite: | Claimed | Measured | |---|---| | `main` is a protected branch, gate is a required status check | `branch_protections` → `[]`; `protected:false`, `enable_status_check:false`, `required_approvals:0`, `user_can_push:true` | | Runner `incluster-dind` online | **zero** runners registered at repo, org and site level | So `main` accepted direct pushes, and the gate could not run at all. `CLAUDE.md` is the rule; this directory is how the rule gets enforced by the machine. ## `branch-protection.sh` Blocks direct pushes to `main`. Run it, then run the push probe it prints — **verify, do not trust the API response**, since Gitea may let site admins bypass protection. ./infra/gitea/branch-protection.sh It authenticates with the credential `git` already has stored for this host, and never prints the secret. ## Sequence — order matters 1. **Get an Actions runner registered.** It is GitOps-managed (`apps/wave-1/gitea-actions.yaml`, `apps/wave-1/gitea-actions-runner-secret.sops.yaml`), so it is deployed but not registering — suspect a stale registration token in that SOPS secret. 2. **Watch the gate actually report on a real PR**, and note the context name it produced. 3. **Only then set `enable_status_check: true`** with that exact context. 4. Add the human reviewer as a repo collaborator, then raise `required_approvals` to 1. > **Do not do step 3 before step 1.** A required status check with no runner leaves every > PR permanently pending — including the PR that would fix it. The same applies to > `gate.yml`'s `conformance` job: it is `if: false` and never runs, yet still publishes a > `gate / conformance (pull_request)` context. Never list that one as required.