forge is IP-gated: open the edge to the Go proxy so public go install madtea.lol resolves (full-public milestone) #455

Closed
opened 2026-08-26 22:25:48 +00:00 by hexajon · 9 comments
Owner

Verified 2026-08-26: git.cheshirecube.cloud refuses anonymous git clone from outside its IP allowlist, so proxy.golang.org cannot resolve madtea.lol.

This is the "full-public" step ADR 0033 already anticipates (it parks the GitHub fallback #386 and accepts a temporary GOPRIVATE note "while the forge is IP-whitelist-gated"). Not a new architecture fork - it implements the milestone ADR 0033 names.

Evidence

  • proxy.golang.org (Google's servers) fetching the module → HTTP 403 on git ls-remote https://git.cheshirecube.cloud/sixfold-space/madtea.git. It reaches the edge (a 403, not a timeout) but is refused.
  • The same anonymous endpoint (info/refs?service=git-upload-pack) returns 200 from an allowlisted host, for curl / git / Go-http-client user agents alike. So it is source-IP gating, not an auth requirement and not a bot-UA rule.
  • The forge's own Gitea go-get meta is correct (git.cheshirecube.cloud/... git https://git.cheshirecube.cloud/....git). Only the edge access rule blocks the proxy.

Impact

go install madtea.lol@latest via the public Go proxy cannot resolve until the forge edge accepts the proxy.

  • From an allowlisted network: GOPRIVATE=madtea.lol go install madtea.lol@latest works (direct fetch, bypasses the proxy) - once the vanity meta is redeployed (madtea-site#58).
  • Publicly: blocked.

Action (maintainer / infra)

Open the forge edge for anonymous git read to the public / the Go proxy: lift the IP allowlist, or add a Cloudflare rule permitting git + the Go proxy. Scope and timing are an exposure-posture call, so they are yours - this issue only records the verified state and what it blocks.

Blocks / relates

  • Blocks #440 (drop the GOPRIVATE caveat) - stays blocked until this lands.
  • Paired with madtea-site#58 (the stale vanity-meta redeploy - the other half of a working go install madtea.lol).
  • Part of the migration (#420); implements the full-public step of ADR 0033.
Verified 2026-08-26: `git.cheshirecube.cloud` refuses anonymous git clone from outside its IP allowlist, so `proxy.golang.org` cannot resolve `madtea.lol`. This is the "full-public" step ADR 0033 already anticipates (it parks the GitHub fallback #386 and accepts a temporary GOPRIVATE note "while the forge is IP-whitelist-gated"). Not a new architecture fork - it implements the milestone ADR 0033 names. ## Evidence - `proxy.golang.org` (Google's servers) fetching the module → HTTP 403 on `git ls-remote https://git.cheshirecube.cloud/sixfold-space/madtea.git`. It reaches the edge (a 403, not a timeout) but is refused. - The same anonymous endpoint (`info/refs?service=git-upload-pack`) returns 200 from an allowlisted host, for curl / git / Go-http-client user agents alike. So it is source-IP gating, not an auth requirement and not a bot-UA rule. - The forge's own Gitea go-get meta is correct (`git.cheshirecube.cloud/... git https://git.cheshirecube.cloud/....git`). Only the edge access rule blocks the proxy. ## Impact `go install madtea.lol@latest` via the public Go proxy cannot resolve until the forge edge accepts the proxy. - From an allowlisted network: `GOPRIVATE=madtea.lol go install madtea.lol@latest` works (direct fetch, bypasses the proxy) - once the vanity meta is redeployed (madtea-site#58). - Publicly: blocked. ## Action (maintainer / infra) Open the forge edge for anonymous git read to the public / the Go proxy: lift the IP allowlist, or add a Cloudflare rule permitting git + the Go proxy. Scope and timing are an exposure-posture call, so they are yours - this issue only records the verified state and what it blocks. ## Blocks / relates - Blocks #440 (drop the GOPRIVATE caveat) - stays blocked until this lands. - Paired with madtea-site#58 (the stale vanity-meta redeploy - the other half of a working `go install madtea.lol`). - Part of the migration (#420); implements the full-public step of ADR 0033.
Author
Owner

Re-checked 2026-08-26 after an attempted edge change: still gated.

proxy.golang.org gets HTTP 403 on a FRESH, never-cached probe - a live git ls-remote of the public claude-plugins repo from Google's network - so it is a genuine live block, not stale proxy cache. An allowlisted host still gets 200 on the same anonymous endpoint.

Likely layer: the forge is Cloudflare-fronted (server: cloudflare, cf-ray, Cloudflare IPs), and the block differentiates purely by source IP. The probable culprit is a Cloudflare-side rule - Bot Fight Mode, a WAF managed rule, or an IP Access Rule - blocking datacenter IPs (the Go proxy fetches from Google Cloud) while allowing the specific allowlisted IP. A change to only the forge's own IP allowlist would not affect this. The fix is Cloudflare-side: permit the Go proxy / git-upload-pack to the .git paths, or exempt those paths from bot protection.

Re-checked 2026-08-26 after an attempted edge change: still gated. `proxy.golang.org` gets HTTP 403 on a FRESH, never-cached probe - a live `git ls-remote` of the public `claude-plugins` repo from Google's network - so it is a genuine live block, not stale proxy cache. An allowlisted host still gets 200 on the same anonymous endpoint. Likely layer: the forge is Cloudflare-fronted (`server: cloudflare`, `cf-ray`, Cloudflare IPs), and the block differentiates purely by source IP. The probable culprit is a Cloudflare-side rule - Bot Fight Mode, a WAF managed rule, or an IP Access Rule - blocking datacenter IPs (the Go proxy fetches from Google Cloud) while allowing the specific allowlisted IP. A change to only the forge's own IP allowlist would not affect this. The fix is Cloudflare-side: permit the Go proxy / `git-upload-pack` to the `.git` paths, or exempt those paths from bot protection.
Author
Owner

Decided: open the edge with a narrow Cloudflare rule, not a blanket lift.

Confirmed broken live: proxy.golang.org gets a 403 doing git ls-remote against the forge repo, so it reports madtea.lol as not-found and a public go install madtea.lol/... fails. The vanity path resolves fine; what the gating blocks is the proxy's anonymous read of the underlying repo. The block is edge-side (datacenter-IP / bot protection), so widening only the forge's own IP allowlist would not fix it.

Fix: add a targeted rule that permits the Go proxy / git-upload-pack to the anonymous read paths (or exempts those .git fetch paths from bot protection), leaving the rest of the forge gated. Surgical, not a blanket lift.

This is an edge-side action, not a madtea code change. It unblocks #440 (drop the GOPRIVATE caveat once the proxy can fetch) and is the fully-public fetch step of ADR 0033 / #420, paired with madtea-site#58.

Verify after: a fresh proxy.golang.org fetch of madtea.lol returns versions, and go install madtea.lol/cmd/madtea@latest works from a clean environment. Clearing needs-decision.

Decided: open the edge with a narrow Cloudflare rule, not a blanket lift. Confirmed broken live: proxy.golang.org gets a 403 doing `git ls-remote` against the forge repo, so it reports `madtea.lol` as not-found and a public `go install madtea.lol/...` fails. The vanity path resolves fine; what the gating blocks is the proxy's anonymous read of the underlying repo. The block is edge-side (datacenter-IP / bot protection), so widening only the forge's own IP allowlist would not fix it. Fix: add a targeted rule that permits the Go proxy / git-upload-pack to the anonymous read paths (or exempts those `.git` fetch paths from bot protection), leaving the rest of the forge gated. Surgical, not a blanket lift. This is an edge-side action, not a madtea code change. It unblocks #440 (drop the GOPRIVATE caveat once the proxy can fetch) and is the fully-public fetch step of ADR 0033 / #420, paired with madtea-site#58. Verify after: a fresh proxy.golang.org fetch of `madtea.lol` returns versions, and `go install madtea.lol/cmd/madtea@latest` works from a clean environment. Clearing needs-decision.
Author
Owner

Requirement, not a nice-to-have: public go install madtea.lol/... has to work with zero setup. GOPRIVATE is not an acceptable workaround - the public path cannot depend on a user setting an env var. So opening the edge for the Go proxy (the narrow Cloudflare rule above) is required, and #440 drops the GOPRIVATE note the moment it lands.

Re-probed 2026-09-09: proxy.golang.org/madtea.lol still 404s (the proxy's git ls-remote against the forge is 403'd); anonymous git read from an allowlisted host is 200. Still gated.

Requirement, not a nice-to-have: public `go install madtea.lol/...` has to work with zero setup. GOPRIVATE is not an acceptable workaround - the public path cannot depend on a user setting an env var. So opening the edge for the Go proxy (the narrow Cloudflare rule above) is required, and #440 drops the GOPRIVATE note the moment it lands. Re-probed 2026-09-09: `proxy.golang.org/madtea.lol` still 404s (the proxy's `git ls-remote` against the forge is 403'd); anonymous git read from an allowlisted host is 200. Still gated.
Author
Owner

Runbook with the exact dashboard steps: cheshirecube-cloud-infra docs/RUNBOOK-forge-edge-go-proxy.md (merged in cheshirecube-cloud-infra PR #256).

Re-verified 2026-09-09 with a clean-cache go install madtea.lol/cmd/madtea@latest: the vanity meta resolves, the direct download of v0.18.4 starts, and the checksum lookup fails because sum.golang.org gets 403 on its git ls-remote against the forge. Same root cause as before, one step deeper now that the vanity meta is fixed.

The fix in the runbook edits the existing block rule (not ip.src in $remote_wan__site1) to exempt only GET /sixfold-space/madtea.git/info/refs?service=git-upload-pack and POST /sixfold-space/madtea.git/git-upload-pack. Web UI, API, other repos, and git writes stay locked. The runbook also covers the case where Bot Fight Mode still blocks after the edit, because that product accepts no exceptions from custom rules and needs a separate ruling.

Runbook with the exact dashboard steps: cheshirecube-cloud-infra `docs/RUNBOOK-forge-edge-go-proxy.md` (merged in cheshirecube-cloud-infra PR #256). Re-verified 2026-09-09 with a clean-cache `go install madtea.lol/cmd/madtea@latest`: the vanity meta resolves, the direct download of v0.18.4 starts, and the checksum lookup fails because sum.golang.org gets 403 on its `git ls-remote` against the forge. Same root cause as before, one step deeper now that the vanity meta is fixed. The fix in the runbook edits the existing block rule `(not ip.src in $remote_wan__site1)` to exempt only GET `/sixfold-space/madtea.git/info/refs?service=git-upload-pack` and POST `/sixfold-space/madtea.git/git-upload-pack`. Web UI, API, other repos, and git writes stay locked. The runbook also covers the case where Bot Fight Mode still blocks after the edit, because that product accepts no exceptions from custom rules and needs a separate ruling.
Author
Owner

Correction to my earlier comment: the runbook assumed the zone runs the (not ip.src in $remote_wan__site1) block rule that the infra docs record. Checked the zone on 2026-09-09: Security rules holds one rule only, a Crawl Control rule that blocks a list of AI crawler user agents. The recorded block rule is not present. So the 403 that proxy.golang.org gets comes from another product or page (IP Access rules, Zone Lockdown, bot settings, or something else), and that is not yet identified.

The runbook is rewritten to be discovery-first: send a fresh probe from a non-allowlisted host, read the Service and rule in Security Events, record the zone inventory, then apply the fix for that service. It no longer names a rule to edit. docs/RUNBOOK-forge-edge-go-proxy.md in cheshirecube-cloud-infra.

Still gated. Next step is the Security Events read.

Correction to my earlier comment: the runbook assumed the zone runs the `(not ip.src in $remote_wan__site1)` block rule that the infra docs record. Checked the zone on 2026-09-09: Security rules holds one rule only, a Crawl Control rule that blocks a list of AI crawler user agents. The recorded block rule is not present. So the 403 that proxy.golang.org gets comes from another product or page (IP Access rules, Zone Lockdown, bot settings, or something else), and that is not yet identified. The runbook is rewritten to be discovery-first: send a fresh probe from a non-allowlisted host, read the Service and rule in Security Events, record the zone inventory, then apply the fix for that service. It no longer names a rule to edit. `docs/RUNBOOK-forge-edge-go-proxy.md` in cheshirecube-cloud-infra. Still gated. Next step is the Security Events read.
Author
Owner

Root cause found, from the zone's Security Events (2026-09-09).

Every fetch by the Go module proxy (user agent GoModuleMirror/1.0 (+https://proxy.golang.org), Google network) of GET /sixfold-space/madtea.git/info/refs?service=git-upload-pack gets action managed_challenge from service botFight, rule bot_fight_mode. Seven such events on 2026-09-08 and 2026-09-09. Git cannot answer a challenge, so the proxy sees a 403 and reports the module as not found.

There is no IP gate. The block rule (not ip.src in $remote_wan__site1) that the infra docs record is not on the zone; Security rules holds only a Crawl Control user-agent rule. An allowlisted host got 200 only because Bot Fight Mode does not challenge a residential address with a curl user agent. The title of this issue ("forge is IP-gated") is wrong; the gate is Bot Fight Mode.

Bot Fight Mode (free plan) accepts no exceptions from custom rules, IP lists, or paths. The only ways to let the proxy through are to turn it off for the zone, or move the zone to a plan with Super Bot Fight Mode and add a Skip rule for the two git read paths. Both change the zone's bot posture. I have not picked one yet.

Side finding from the same events: AI Labyrinth (linkMaze, link_maze_injected) fires on many Go-http-client/2.0 requests to /api/v1/... on the forge, which is madtea's own API traffic. It injects into HTML only, so JSON responses should be unaffected, but it means the zone classifies madtea's client as a crawler. Worth its own look.

Root cause found, from the zone's Security Events (2026-09-09). Every fetch by the Go module proxy (user agent `GoModuleMirror/1.0 (+https://proxy.golang.org)`, Google network) of `GET /sixfold-space/madtea.git/info/refs?service=git-upload-pack` gets action `managed_challenge` from service `botFight`, rule `bot_fight_mode`. Seven such events on 2026-09-08 and 2026-09-09. Git cannot answer a challenge, so the proxy sees a 403 and reports the module as not found. There is no IP gate. The block rule `(not ip.src in $remote_wan__site1)` that the infra docs record is not on the zone; Security rules holds only a Crawl Control user-agent rule. An allowlisted host got 200 only because Bot Fight Mode does not challenge a residential address with a curl user agent. The title of this issue ("forge is IP-gated") is wrong; the gate is Bot Fight Mode. Bot Fight Mode (free plan) accepts no exceptions from custom rules, IP lists, or paths. The only ways to let the proxy through are to turn it off for the zone, or move the zone to a plan with Super Bot Fight Mode and add a Skip rule for the two git read paths. Both change the zone's bot posture. I have not picked one yet. Side finding from the same events: AI Labyrinth (`linkMaze`, `link_maze_injected`) fires on many `Go-http-client/2.0` requests to `/api/v1/...` on the forge, which is madtea's own API traffic. It injects into HTML only, so JSON responses should be unaffected, but it means the zone classifies madtea's client as a crawler. Worth its own look.
Author
Owner

Decision: turn Bot Fight Mode off on the cheshirecube.cloud zone. Crawl Control, the "Manage AI bots" managed rule, and the WAF managed rules stay on. No plan upgrade.

Verify after the toggle: curl -sS https://proxy.golang.org/madtea.lol/@v/list returns versions, and a clean go install madtea.lol/cmd/madtea@latest with no GOPRIVATE completes. Then #440 drops the GOPRIVATE note.

Decision: turn Bot Fight Mode off on the cheshirecube.cloud zone. Crawl Control, the "Manage AI bots" managed rule, and the WAF managed rules stay on. No plan upgrade. Verify after the toggle: `curl -sS https://proxy.golang.org/madtea.lol/@v/list` returns versions, and a clean `go install madtea.lol/cmd/madtea@latest` with no GOPRIVATE completes. Then #440 drops the GOPRIVATE note.
Author
Owner

Progress 2026-09-09 21:28 UTC. Turning Bot Fight Mode off was not enough on its own: a fresh proxy fetch at 21:18 UTC still got 403. A WAF custom rule with action Skip, matched on user agent GoModuleMirror plus host and the /sixfold-space/madtea.git/ path prefix, skipping managed rules, rate limiting, Browser Integrity Check, Security Level, Zone Lockdown, User Agent Blocking, and Hotlink Protection, fixed the fetch. Proof: curl https://proxy.golang.org/madtea.lol/@v/v0.17.97.info now returns invalid version: unknown revision v0.17.97 with no 403, so Google's git reached the repo and looked up tags.

The version list and v0.18.4.info still return the old 403 text in ~0.1 s, which is the proxy's cache of the earlier failure. Waiting for it to expire, then the clean go install check.

Progress 2026-09-09 21:28 UTC. Turning Bot Fight Mode off was not enough on its own: a fresh proxy fetch at 21:18 UTC still got 403. A WAF custom rule with action Skip, matched on user agent `GoModuleMirror` plus host and the `/sixfold-space/madtea.git/` path prefix, skipping managed rules, rate limiting, Browser Integrity Check, Security Level, Zone Lockdown, User Agent Blocking, and Hotlink Protection, fixed the fetch. Proof: `curl https://proxy.golang.org/madtea.lol/@v/v0.17.97.info` now returns `invalid version: unknown revision v0.17.97` with no 403, so Google's git reached the repo and looked up tags. The version list and `v0.18.4.info` still return the old 403 text in ~0.1 s, which is the proxy's cache of the earlier failure. Waiting for it to expire, then the clean `go install` check.
Author
Owner

Resolved 2026-09-09. The gate was never an IP allowlist; it was Bot Fight Mode plus a second edge product on Google's fetches. Fix applied on the cheshirecube.cloud zone: Bot Fight Mode off, and a WAF custom rule go-proxy-madtea-read (action Skip, user agent contains GoModuleMirror, path prefix /sixfold-space/madtea.git/, skipping managed rules, rate limiting, Browser Integrity Check, Security Level, Zone Lockdown, User Agent Blocking, Hotlink Protection). Runbook: cheshirecube-cloud-infra docs/RUNBOOK-forge-edge-go-proxy.md.

Verification, all with GOPRIVATE unset and empty module and build caches:

  • curl https://proxy.golang.org/madtea.lol/@v/list returns v0.18.1 v0.18.5.
  • curl https://sum.golang.org/lookup/madtea.lol@v0.18.5 returns the h1 hashes.
  • go install madtea.lol/cmd/madtea@v0.18.5 exits 0; madtea --version prints v0.18.5.
  • go install madtea.lol/cmd/madtea@latest exits 0; madtea --version prints v0.18.5.

v0.18.5 was cut to get past the proxy's stored failure for v0.18.4, which it recorded before the edge opened. Tags before v0.18.4 declare the old Codeberg module path and never install under madtea.lol; that is expected.

Resolved 2026-09-09. The gate was never an IP allowlist; it was Bot Fight Mode plus a second edge product on Google's fetches. Fix applied on the cheshirecube.cloud zone: Bot Fight Mode off, and a WAF custom rule `go-proxy-madtea-read` (action Skip, user agent contains `GoModuleMirror`, path prefix `/sixfold-space/madtea.git/`, skipping managed rules, rate limiting, Browser Integrity Check, Security Level, Zone Lockdown, User Agent Blocking, Hotlink Protection). Runbook: cheshirecube-cloud-infra `docs/RUNBOOK-forge-edge-go-proxy.md`. Verification, all with GOPRIVATE unset and empty module and build caches: - `curl https://proxy.golang.org/madtea.lol/@v/list` returns `v0.18.1 v0.18.5`. - `curl https://sum.golang.org/lookup/madtea.lol@v0.18.5` returns the h1 hashes. - `go install madtea.lol/cmd/madtea@v0.18.5` exits 0; `madtea --version` prints v0.18.5. - `go install madtea.lol/cmd/madtea@latest` exits 0; `madtea --version` prints v0.18.5. v0.18.5 was cut to get past the proxy's stored failure for v0.18.4, which it recorded before the edge opened. Tags before v0.18.4 declare the old Codeberg module path and never install under madtea.lol; that is expected.
Sign in to join this conversation.
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.

Reference
sixfold-space/madtea#455
No description provided.