feat(binjovi): grant the legacy reads ex-mcp needs to be a working project #678

Merged
binjovi-bot merged 1 commit from feat/ex-mcp-bindings into trunk 2026-09-12 15:40:37 +00:00
Owner

Why

The seanfarm half of making sean/ex-mcp a working Binjovi project. Pairs with binjovi PR #1658, which adds the bindings themselves. Without this, none of them work.

Why a grant is needed for objects that do not exist

Binjovi proves the legacy Kubernetes CR is absent before it takes ownership (ServiceLegacyClient.legacy_state/2). Without the name in the Role the scoped read returns 403 — denied, indistinguishable from present — and the gate refuses. With it the read returns 404, which is absent and actionable.

This repo's own guard already says exactly that:

the grant only turns 403 (denied, indistinguishable) into 404 (absent, actionable)

forgejowebhooks           38 -> 39   binjovi-ingest-ex-mcp
forgejobranchprotections  64 -> 66   ex-mcp-main, ex-mcp-trunk
forgejotagprotections     31 -> 32   ex-mcp-tags
forgejocollaborators      77 -> 79   ex-mcp-binjovi-bot, ex-mcp-binjovi-operator-bot

The pinned counts in tests/binjovi-service-handoff.sh and tests/binjovi-active-webhook-handoff.sh move with them, and both now assert the ex-mcp names by hand, as the fleet already does.

Worth noting for whoever hits this next: four other guards call the webhook one as a sub-check, so a single stale 38 failed five guards at once with no output of their own. The trail is bash -x, not the summary.

No forgejorepositories entry, deliberately. ForgejoRepository/ex-mcp is live and owned by forgejo-operator, so that gate refuses by design. A grant there would look like coverage and do nothing.

Also: what the mirror does not cover

gitmirrors/ex-mcp.yaml now records it. branchFilter is an allowlist, so the first sync pruned three branches from codeberg. Two are redundant — feat/optional-cowboy and claude/issue-pr-feedback-hyl8jn point at commits already on mirrored refs. The third is upstream's own cursor/azm-5-track-cowlib-cve-…, which I confirmed is present at github.com/azmaveth/ex_mcp rather than assuming it.

So a ref diff against codeberg is expected to be non-empty here, and widening the filter would be worse: every named branch must exist, so an upstream branch that disappears fails the whole push atomically and stops the backup.

It also records that syncOnCommit fires on a commit, so trunk and main — created before the mirror — needed one manual push_mirrors-sync.

Verification

Full tests/check.sh green.

https://claude.ai/code/session_01XdBRc9CHgFhAxCyHbdVtt6

## Why The seanfarm half of making `sean/ex-mcp` a working Binjovi project. Pairs with **binjovi PR #1658**, which adds the bindings themselves. Without this, none of them work. ## Why a grant is needed for objects that do not exist Binjovi proves the legacy Kubernetes CR is **absent** before it takes ownership (`ServiceLegacyClient.legacy_state/2`). Without the name in the Role the scoped read returns **403** — denied, indistinguishable from present — and the gate refuses. With it the read returns **404**, which is absent and actionable. This repo's own guard already says exactly that: > the grant only turns 403 (denied, indistinguishable) into 404 (absent, actionable) ``` forgejowebhooks 38 -> 39 binjovi-ingest-ex-mcp forgejobranchprotections 64 -> 66 ex-mcp-main, ex-mcp-trunk forgejotagprotections 31 -> 32 ex-mcp-tags forgejocollaborators 77 -> 79 ex-mcp-binjovi-bot, ex-mcp-binjovi-operator-bot ``` The pinned counts in `tests/binjovi-service-handoff.sh` and `tests/binjovi-active-webhook-handoff.sh` move with them, and both now assert the `ex-mcp` names by hand, as the fleet already does. Worth noting for whoever hits this next: **four other guards call the webhook one as a sub-check**, so a single stale `38` failed five guards at once with no output of their own. The trail is `bash -x`, not the summary. **No `forgejorepositories` entry, deliberately.** `ForgejoRepository/ex-mcp` is live and owned by forgejo-operator, so that gate refuses by design. A grant there would look like coverage and do nothing. ## Also: what the mirror does not cover `gitmirrors/ex-mcp.yaml` now records it. `branchFilter` is an allowlist, so the first sync **pruned** three branches from codeberg. Two are redundant — `feat/optional-cowboy` and `claude/issue-pr-feedback-hyl8jn` point at commits already on mirrored refs. The third is upstream's own `cursor/azm-5-track-cowlib-cve-…`, which I confirmed is present at `github.com/azmaveth/ex_mcp` rather than assuming it. So a ref diff against codeberg is **expected** to be non-empty here, and widening the filter would be worse: every named branch must exist, so an upstream branch that disappears fails the whole push atomically and stops the backup. It also records that `syncOnCommit` fires on a *commit*, so `trunk` and `main` — created before the mirror — needed one manual `push_mirrors-sync`. ## Verification Full `tests/check.sh` green. https://claude.ai/code/session_01XdBRc9CHgFhAxCyHbdVtt6
feat(binjovi): grant the legacy reads ex-mcp needs to be a working project
All checks were successful
binjovi/ci Binjovi completed the frozen plan
d2e786d356
sean/ex-mcp became a Binjovi project when v0.1.681 shipped schema 29 and the
catalog record activated, but it is inert without service bindings: a pull
request never wakes Binjovi, binjovi-bot cannot merge or tag, and neither
trunk nor main is protected. The bindings themselves are in sean/binjovi;
this is the half that has to land here or none of them work.

WHY A GRANT IS NEEDED FOR AN OBJECT THAT DOES NOT EXIST. Binjovi proves the
legacy Kubernetes CR is ABSENT before it takes ownership
(ServiceLegacyClient.legacy_state/2). Without the name in the Role the scoped
read returns 403 -- denied, indistinguishable from present -- and the gate
refuses. With it the read returns 404, which is absent and actionable. The
guard in this repo already says exactly that: "the grant only turns 403
(denied, indistinguishable) into 404 (absent, actionable)."

  forgejowebhooks           38 -> 39   binjovi-ingest-ex-mcp
  forgejobranchprotections  64 -> 66   ex-mcp-main, ex-mcp-trunk
  forgejotagprotections     31 -> 32   ex-mcp-tags
  forgejocollaborators      77 -> 79   ex-mcp-binjovi-bot, -binjovi-operator-bot

The pinned counts in tests/binjovi-service-handoff.sh and
tests/binjovi-active-webhook-handoff.sh move with them, and both now assert
the ex-mcp names by hand the way the fleet already does. Four other guards
call the webhook one as a sub-check, which is why a single stale 38 failed
five guards at once.

NO forgejorepositories ENTRY, deliberately. ForgejoRepository/ex-mcp is live
and owned by forgejo-operator, so that gate refuses by design. A grant there
would look like coverage and do nothing.

Also records what ex-mcp.yaml does NOT mirror. branchFilter is an allowlist,
so the first sync pruned three branches from codeberg. Two are redundant; the
third is upstream's own cursor/ branch, present at github.com/azmaveth/ex_mcp
-- checked, not assumed. A ref diff against codeberg is therefore expected to
be non-empty, and widening the filter would be worse: every named branch must
exist, so an upstream branch that disappears fails the push atomically and
stops the backup.

Full tests/check.sh green.

Claude-Session: https://claude.ai/code/session_01XdBRc9CHgFhAxCyHbdVtt6
binjovi-bot deleted branch feat/ex-mcp-bindings 2026-09-12 15:40:37 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
sean/seanfarm!678
No description provided.