Document State Hub PATCH procedure, sweep implications, railiance01 host_paths, state-hub image specifics, and rollback. Include batch patch helper; applied tier-2.5 remote_url updates in hub DB.
8.4 KiB
Forgejo Tier 3 — State Hub remote_url and Sweep Playbook
Date: 2026-07-04
Workplans: RAIL-HO-WP-0005-T10, RAIL-HO-WP-0005-T11, CUST-WP-0054-T04, CUST-WP-0054-T05
no_secret_material_recorded: true
Purpose
Operational playbook for promoting a registered State Hub repo from Gitea
(gitea-remote) to Forgejo (forgejo-remote) without breaking the consistency
sweep, DoI checks, or agent attribution.
Applies to:
- Tier 2.5 (done on Forgejo, hub
remote_urlmay still say Gitea) — run §4 after git promotion. - Tier 3 (
state-hub,issue-core, production wave) — full §3–§8 with operator approval.
Does not perform cutover by itself. Gitea remains canonical until tier gates
and explicit approval per RAIL-HO-WP-0005 safety contract.
Preconditions (gates)
| Gate | Tier 2.5 | Tier 3 (state-hub) |
|---|---|---|
| Forgejo repo exists + history mirrored | required | required |
Workstation origin=forgejo-remote, gitea legacy remote |
required | required |
Operator SSH on Forgejo (tegwick or team keys) |
required | required |
CI smoke green on Forgejo (.forgejo/workflows/ci-smoke.yaml) |
required | required |
| Image workflow if applicable | optional | required for state-hub |
| Restore drill passed | recommended | required |
| Scheduled backups automated | optional | required (disaster-control) |
| Operator approval recorded | not required | required |
CUST-WP-0011-T07 freeze/restore for hub primary |
n/a | required before hub production |
Canonical remote conventions
State Hub stores the SSH remote name form used on the operator workstation,
not the HTTPS URL. This matches existing registrations
(gitea-remote:coulomb/<slug>.git).
| Role | Remote name | Example |
|---|---|---|
| Canonical (post-promotion) | origin → forgejo-remote |
forgejo-remote:coulomb/state-hub.git |
| Rollback mirror | gitea → gitea-remote |
gitea-remote:coulomb/state-hub.git |
Hub remote_url field |
same as origin |
forgejo-remote:coulomb/state-hub.git |
HTTPS canonical URL for humans and archive CI:
https://forgejo.coulomb.social/coulomb/<slug>.git
SSH config block (workstation ~/.ssh/config):
Host forgejo-remote
HostName 92.205.62.239
Port 30022
User git
IdentityFile ~/.ssh/id_gitea
StrictHostKeyChecking accept-new
Per-repo promotion procedure
1. Git forge (workstation)
Use railiance-enablement/tools/promote-repo-to-forgejo.sh or manually:
cd ~/REPO_SLUG
# Create empty repo on Forgejo if needed (org coulomb)
git push forgejo-remote:coulomb/REPO_SLUG.git main # first mirror
git remote rename origin gitea
git remote add origin forgejo-remote:coulomb/REPO_SLUG.git
git push -u origin main
# Optional: keep Gitea mirror current
git push gitea main
Add .forgejo/workflows/ci-smoke.yaml from
railiance-enablement/workflows/ci-smoke.yaml. For images, use
container-build-push.yaml or container-build-push-multirepo.yaml (state-hub +
hub-core).
2. Verify git + SSH
git remote -v
# origin forgejo-remote:coulomb/REPO_SLUG.git (fetch/push)
# gitea gitea-remote:coulomb/REPO_SLUG.git (fetch/push)
ssh forgejo-remote # expect: Hi there, tegwick!
git ls-remote origin # reachable
3. Patch State Hub registration
API=http://127.0.0.1:8000
SLUG=REPO_SLUG
NEW_URL="forgejo-remote:coulomb/${SLUG}.git"
curl -s -X PATCH "${API}/repos/${SLUG}" \
-H "Content-Type: application/json" \
-d "{\"remote_url\": \"${NEW_URL}\"}" | python3 -m json.tool
# Confirm
curl -s "${API}/repos/${SLUG}" | python3 -c \
"import json,sys; r=json.load(sys.stdin); print(r['slug'], r['remote_url'])"
Batch helper for tier-2.5 stack (skips slugs not registered in State Hub):
~/the-custodian/tools/patch-forgejo-remote-urls.sh --tier-25
Applied 2026-07-04 for registered tier-2.5 repos + key-cape. glas-harness is
not in State Hub registration — patch when/if registered.
4. Consistency sweep / fix-consistency
The sweep (POST /consistency/sweep/remote-all or statehub fix-consistency)
resolves repos by host_paths[hostname] or local_path, then git pull --ff-only from the checkout's tracking branch (now Forgejo origin).
After remote_url patch:
cd ~/REPO_SLUG
git fetch origin
statehub fix-consistency --repo REPO_SLUG
# or from state-hub checkout:
cd ~/state-hub && make fix-consistency REPO=REPO_SLUG
Attribution: consistency_check.py matches repos by git fingerprint and
remote_url string. Stale gitea-remote in the hub causes mis-attribution when
multiple checkouts exist — patch hub before relying on sweep writebacks.
5. DoI verification
curl -s "http://127.0.0.1:8000/repos/REPO_SLUG/doi" | python3 -m json.tool
# C4 Remote URL set → pass
# C4 reachability → git ls-remote origin succeeds
Railiance01 sweep checkout paths (CUST-WP-0054-T05)
Today sweeps write back from workstation host_paths (bnt-lap001). Wave 2
moves primary checkouts to railiance01 so triage survives workstation loss.
When railiance01 clone tree exists (e.g. /home/tegwick/<slug> or agreed path):
API=http://127.0.0.1:8000
SLUG=REPO_SLUG
HOST=railiance01 # must match socket.gethostname() on that machine
PATH_ON_HOST=/home/tegwick/REPO_SLUG
curl -s -X POST "${API}/repos/${SLUG}/paths" \
-H "Content-Type: application/json" \
-d "{\"host\": \"${HOST}\", \"path\": \"${PATH_ON_HOST}\"}" | python3 -m json.tool
Clone on railiance01 from Forgejo:
git clone forgejo-remote:coulomb/REPO_SLUG.git /home/tegwick/REPO_SLUG
# or HTTPS with deploy key / token
Sweep on railiance01 then uses host_paths[railiance01]; workstation path
remains in map for dev but is no longer the production writeback source.
Tier 3 — state-hub specifics
Before promoting state-hub:
- Multi-repo image workflow — copy
railiance-enablement/workflows/container-build-push-multirepo.yamltostate-hub/.forgejo/workflows/image.yaml; setIMAGE_NAME=coulomb/state-hub,EXTRA_REPOS="coulomb/hub-core@hub_core_src". - Prove image pull on railiance01 (
crictl pullor deployment dry-run). - Hub primary cutover — follow
CUST-WP-0011-T07(freeze → restore → rewire); independent of forge remote but same maintenance window may apply. - ArgoCD / GitOps — repoint repository URLs to Forgejo (Wave 5 in
docs/coulombcore-drain-placement-plan.md). - Record approval —
POST /decisions/or workplan note with operator id.
state-hub promotion order:
mirror git → Forgejo remotes → CI image workflow green → PATCH remote_url →
fix-consistency → (later) railiance01 host_paths → CUST-WP-0011-T07 cutover
Gitea read-only policy (post-cutover per repo)
After Forgejo is canonical for that repo and hub remote_url is patched:
- Do not delete the Gitea repo (safety contract).
- Org/repo setting: disable push for non-admin users, or maintenance flag.
- Workstation: stop pushing to
giteaexcept intentional rollback mirror. - Document rollback:
git push gitea mainfrom last known-good Forgejo SHA.
Org-wide Gitea read-only is an operator action (T11); per-repo is enough for staged ladder.
Rollback
| Step | Action |
|---|---|
| Git canonical | git remote rename origin forgejo; git remote rename gitea origin |
| Hub | PATCH /repos/{slug} → gitea-remote:coulomb/<slug>.git |
| Sweep | statehub fix-consistency on reverted checkout |
| Gitea | Re-enable push if read-only was set |
Verification checklist
GET /repos/{slug}→remote_urlisforgejo-remote:coulomb/<slug>.git- Workstation
git remote -v→originis Forgejo ssh forgejo-remote→ operator user (not onlyforgejo_admin)statehub fix-consistency --repo <slug>→ PASS- Forgejo Actions
ci-smoke→ success (tier 1+) - Gitea copy exists and matches SHA (optional
git push giteamirror) - Tier 3 only: image workflow + pull smoke + operator approval on record
References
docs/forgejo-repo-migration-pilot-glas-harness.md(tiers 1–2.5)railiance-enablement/docs/forgejo-actions-workflow-templates.mdrailiance-enablement/tools/promote-repo-to-forgejo.shstate-hub/docs/consistency-sweep-runbook.mdstate-hub/policies/repo-doi.md(C4 remote URL)docs/coulombcore-drain-placement-plan.md(Wave 1–2)disaster-control/history/2026-07-04-forgejo-backup-strategy-assessment.md