The Three-Mirror Formula
The complete migration from GitHub-dependent to git-sovereign. Executable in an afternoon. Given freely — freely given, so freely given.
The Thesis
Git is a protocol. GitHub is a discovery layer built on top of that protocol. The dependency trap is conflating the two. When you treat GitHub as your git host rather than as your discoverability surface, you've handed a single corporation's enforcement classifier the power to take your work offline. The migration separates these functions back out: you own the git, GitHub discovers it.
The migration takes 15 minutes of active configuration. The rest is your regular workflow, unchanged. You still run git push origin main. Your sovereign primary handles the rest.
Step 1 — Deploy Forgejo on Railway
Railway is the fastest path to a running Forgejo instance. Forgejo is the community fork of Gitea — open source, actively maintained, AGPL-licensed, with full API compatibility and native push-mirror support.
# 1. Go to railway.app and create a new project # 2. Deploy from template: search "Forgejo" in the Railway template gallery # 3. Add a PostgreSQL service to the project (for metadata persistence) # 4. Set environment variables: FORGEJO__database__DB_TYPE=postgres FORGEJO__database__HOST=${{Postgres.PGHOST}} FORGEJO__database__NAME=${{Postgres.PGDATABASE}} FORGEJO__database__USER=${{Postgres.PGUSER}} FORGEJO__database__PASSWD=${{Postgres.PGPASSWORD}} FORGEJO__server__DOMAIN=git.yourproject.org FORGEJO__server__ROOT_URL=https://git.yourproject.org
After deploy, visit the Railway-assigned URL, complete the install wizard, and create your admin account. Total time: ~15 minutes.
git CNAME yourapp.up.railway.app at your domain registrar. This gives you git.yourproject.org as the permanent address, decoupled from the Railway deployment URL.Step 2 — Create your organization and repositories
Create an organization on your Forgejo instance that mirrors your GitHub org. Create your repositories. Push your existing code:
# Add your Forgejo instance as a remote git remote add sovereign https://git.yourproject.org/yourorg/yourrepo.git # Push all branches and tags git push sovereign --all git push sovereign --tags # Update your primary remote so daily workflow goes to sovereign git remote set-url origin https://git.yourproject.org/yourorg/yourrepo.git
Step 3 — Configure Codeberg as push-mirror
Create an account at codeberg.org and create the mirror repository. Then configure the push-mirror from your Forgejo primary via API:
# Configure Codeberg push-mirror via Forgejo API curl -X POST https://git.yourproject.org/api/v1/repos/yourorg/yourrepo/push_mirrors -H "Authorization: token YOUR_FORGEJO_TOKEN" -H "Content-Type: application/json" -d '{ "remote_address": "https://codeberg.org/yourorg/yourrepo.git", "remote_password": "YOUR_CODEBERG_TOKEN", "remote_username": "yourcodeberg_username", "sync_on_commit": true, "interval": "8h" }'
Full walkthrough with troubleshooting at notgit.org/push-mirror-setup.
Step 4 — Configure GitHub as push-mirror (if restored)
If your GitHub account is active, add it as a second push-mirror using the same API pattern. If it's suspended, skip this step — your work continues without it.
curl -X POST https://git.yourproject.org/api/v1/repos/yourorg/yourrepo/push_mirrors -H "Authorization: token YOUR_FORGEJO_TOKEN" -H "Content-Type: application/json" -d '{ "remote_address": "https://github.com/yourorg/yourrepo.git", "remote_password": "YOUR_GITHUB_PAT", "remote_username": "yourgithub_username", "sync_on_commit": true, "interval": "8h" }'
Step 5 — Maintain agentic discoverability
Moving to Forgejo solves the infrastructure problem but creates a propagation problem. Most MCP directories and agent tooling assume GitHub-hosted source repositories with specific topic tags. A Forgejo-hosted MCP server is fully protocol-compliant, but it is not automatically indexed by the directory-based discovery mechanisms that currently look at github.com/topics/mcp-server.
Three paths forward, not mutually exclusive:
-
Register directly with the MCP Registry API.
The official registry at registry.modelcontextprotocol.io accepts submissions from any git-accessible source — it does not require GitHub. Submit with your
sovereign_repofield pointing at your Forgejo host:This is the propagation path that does not require GitHub at any stage.# Submit your MCP server to the official registry curl -X POST https://registry.modelcontextprotocol.io/api/v1/servers -H "Content-Type: application/json" -d '{ "name": "yourorg/yourserver", "git_repo": "https://git.yourproject.org/yourorg/yourserver", "description": "..." }'
-
Keep GitHub mirrors live for directory discovery.
PulseMCP, Glama, MCP.so, and AAIF all crawl GitHub topic tags. If GitHub restores your account, keep the mirrors active with the correct topic tags (
mcp-server,model-context-protocol). The mirror serves discovery; your Forgejo primary is source of truth. These roles should never be reversed. -
Publish a federation manifest.
A public
federation.jsonat a stable URL is readable by any AI agent that fetches it directly — no GitHub required. Include agit_repofield on each server entry pointing to your Forgejo instance. This is the propagation layer that is completely sovereign and improves with the size of your federation.// federation.json (served at yourdomain.org/mcp/federation.json) { "version": "2.0", "servers": [{ "id": "yourserver", "git_repo": "https://git.yourproject.org/yourorg/yourserver", "endpoint": "https://mcp.yourproject.org/yourserver" }] }
The practical cadence for ongoing publishing: push to your Forgejo primary at any rate the work supports. Configure Forgejo to rate-limit push-mirrors to GitHub at 2–3 repositories per day if you are rebuilding after suspension. The visible surface to classifiers slows; your actual infrastructure grows at whatever rate the work itself supports.
Step 6 — Covenant-gated agent access (advanced)
Steps 1–5 solve the infrastructure sovereignty problem for human developers. This step addresses a different problem: how AI agents authenticate to git infrastructure without human-issued credentials.
Current git hosting treats agents as humans with PATs — manually issued, broadly scoped, persistent until revoked. The human is the trust anchor. The covenant-gated token pattern inverts this: the covenant attestation is the trust anchor, and the token is a short-lived cryptographic instrument that carries the covenant's scope.
The pattern, called VCAP-gated git access:
- An AI agent discovers a Forgejo-hosted civic infrastructure need through an MCP registry.
- The agent reads the conduct standard at the operator's constitution URL.
- The agent completes a covenant attestation process and obtains a public attestation document (a VCAP attestation).
- The agent presents the attestation URI and a scoped operation request to the token bridge:
# Request a scoped git token by presenting your VCAP attestation curl -X POST https://git.wellspr.ing/api/v1/vcap/git-token -H "Content-Type: application/json" -d '{ "attestation_uri": "https://yourproject.org/vault/agent-ody/attestation-2026-04-18.json", "sgs_scope": "write:civic-data:425-region:portal-maintenance", "agent_key": "your-calling-interview-agent-key", "purpose": "Update civic event data for the 425 portal" }'
- The bridge validates the attestation, analyzes the scope, and issues a scoped Forgejo token — time-limited, tied to specific repositories.
- The agent executes its git operations. The token expires automatically. All push events are logged to a public audit trail.
The stakes model
Scope determines stakes. Stakes determine the enforcement model applied at the git layer:
| Stakes | Scope triggers | TTL | Enforcement |
|---|---|---|---|
| low | read:* |
7 days | Direct read + audit log |
| medium | write:*:portal-maintenance, data-source |
24 hours | Direct push + post-receive webhook validates scope |
| high | write:*:portal-creation, portal-config |
4 hours | PR-only — main branch protected, wellkeeper review required |
| reserved | admin:*, full-access |
— | No token issued — refer to wellkeeper |
The critical property: the token is not the credential — the attestation is. Tokens expire; attestations are permanent public records. Revocation is immediate and cascades to all downstream tokens issued against the revoked attestation.
What this means for agent contribution
An agent that finds a federated portal through an MCP registry can, with appropriate covenant attestation, contribute back to the infrastructure it uses — new civic data sources, portal updates, bug fixes — without any human gatekeeper in the token issuance path. The trust was established once, at attestation time. The infrastructure enforces scope mechanically thereafter.
This is not what GitHub's agentic access does. GitHub's model requires human-mediated PATs or App installations. The covenant-gated model makes the publicly verifiable conduct commitment the trust anchor — distributed, not centralized.
If you want to implement this pattern
The reference implementation runs at git.wellspr.ing. The bridge manifest is machine-readable at GET /api/vcap/git-token/manifest. The VCAP protocol specification is at wellspr.ing/protocols/vcap. The full protocol stack (VCAP + SGS + PTP) is published under the WellSpr.ing covenant: freely given, so freely given.
Any Forgejo instance can implement the same gate. The pattern generalizes beyond git — API access, database access, cloud compute — any infrastructure primitive currently requiring human-issued credentials can be covenant-gated if the provider chooses to implement the bridge.
The five AI-era operational rules
- README-first publication. Never publish an empty repository. Substantive README, working initial commit, license, topic tags before making the repo public.
- Cadence discipline. Don't create twenty repositories in ten minutes via automation. Rate-limit to 2–3 per day at the discovery layer. Your sovereign primary has no such constraint.
- PAT scoping. Give your AI assistant the minimum scope it needs —
repoonly, notadmin:org. A broad-scoped PAT making many API calls per minute matches detection patterns. - Push through sovereign primary. Your AI tooling pushes to your Forgejo primary. The push-mirror propagates to the discovery layers. If GitHub flags the pattern, turn off that mirror temporarily — your work is untouched.
- Artifact stores for large files. Git is not an artifact store. For model checkpoints and large binaries, use Hugging Face or Weights & Biases and reference from git. Git LFS pushes of unfamiliar large file types have triggered suspensions.
Before you need it
This is a 15-minute infrastructure change. The best time to do it is before your account is suspended. The second best time is today. The migration doesn't require leaving GitHub — it just means GitHub no longer holds the source of truth. Your workflow is identical. The risk profile changes entirely.
The formula is given freely. If you use it, consider documenting your case at notgit.org/report. The pattern gets legible through documentation.