Files
the-custodian/docs/forgejo-tier3-remote-url-sweep-playbook.md
codex 5c63c2f354 Add Forgejo tier-3 remote_url and sweep playbook
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.
2026-07-04 13:21:40 +02:00

238 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_url` may 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`):
```ssh
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:
```bash
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
```bash
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
```bash
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):
```bash
~/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:
```bash
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
```bash
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):
```bash
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**:
```bash
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`:
1. **Multi-repo image workflow** — copy
`railiance-enablement/workflows/container-build-push-multirepo.yaml` to
`state-hub/.forgejo/workflows/image.yaml`; set `IMAGE_NAME=coulomb/state-hub`,
`EXTRA_REPOS="coulomb/hub-core@hub_core_src"`.
2. **Prove image pull** on railiance01 (`crictl pull` or deployment dry-run).
3. **Hub primary cutover** — follow `CUST-WP-0011-T07` (freeze → restore →
rewire); independent of forge remote but same maintenance window may apply.
4. **ArgoCD / GitOps** — repoint repository URLs to Forgejo (Wave 5 in
`docs/coulombcore-drain-placement-plan.md`).
5. **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:
1. Do **not** delete the Gitea repo (safety contract).
2. Org/repo setting: disable push for non-admin users, or maintenance flag.
3. Workstation: stop pushing to `gitea` except intentional rollback mirror.
4. Document rollback: `git push gitea main` from 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_url` is `forgejo-remote:coulomb/<slug>.git`
- [ ] Workstation `git remote -v``origin` is Forgejo
- [ ] `ssh forgejo-remote` → operator user (not only `forgejo_admin`)
- [ ] `statehub fix-consistency --repo <slug>` → PASS
- [ ] Forgejo Actions `ci-smoke` → success (tier 1+)
- [ ] Gitea copy exists and matches SHA (optional `git push gitea` mirror)
- [ ] Tier 3 only: image workflow + pull smoke + operator approval on record
## References
- `docs/forgejo-repo-migration-pilot-glas-harness.md` (tiers 12.5)
- `railiance-enablement/docs/forgejo-actions-workflow-templates.md`
- `railiance-enablement/tools/promote-repo-to-forgejo.sh`
- `state-hub/docs/consistency-sweep-runbook.md`
- `state-hub/policies/repo-doi.md` (C4 remote URL)
- `docs/coulombcore-drain-placement-plan.md` (Wave 12)
- `disaster-control/history/2026-07-04-forgejo-backup-strategy-assessment.md`