# CUST-WP-0073 — attended cutover runbook (2026-10-20) Founder interview 2026-10-20 (Bernd Worsch) fixed: one isolated workstation account hosts **Codex, Claude Code and Grok Build**; attended execution with per-step confirmation; owner workers commit and push to main; privileged actions go through the new `gated-executor` repo; curated read RBAC; short-lived, re-issued credentials; **open egress** (builder mode — re-arm an egress allowlist at production close-down); Forgejo **bot user without write to GitOps-sourced repos**, scoped per tenant (current work = tenant zero, the platform building itself); transport mixed (Codex desktop via loopback SSH, Claude Code/Grok Build via `wsl -d custodian-agents`). Shared names: workstation distro `custodian-agents`, account `custodian-agt` (workstation and railiance01), SSH principal `agt-custodian`, ServiceAccount `custodian-agents/custodian-agent`, executor account `gexec`. ## Owner deliveries (source, pushed; nothing live) | Owner | Workplan | Commit | Attended step | |---|---|---|---| | railiance-platform | RPF-WP-0062 | 567d2c6, ded5922 | T03 Argo sync | | railiance-platform | (OpenBao agt-role) | e415da9 | apply ssh roles | | railiance-cluster | RCLUSTER-WP-0019 | 1d8d11d | T03 mode-600 playbook | | railiance-infra | RAIL-HO-WP-0014 | c62b187 | T02 account/principal | | ops-warden | WARDEN-WP-0045 | e62763c | T03 inventory + first issuance | | gated-executor | GEXEC-WP-0001 | 80b1973 | T05 register, T06 install | | the-custodian | this dir | workstation-agents-r4/ | distro creation | ## Order (each step: check/diff first, then apply, then verify) 0. **Recovery access**: keep an open `ssh tegwick@railiance01` session through steps 3–4. Migrate `railiance-platform/scripts/application_backup_credentials.py` (reads admin kubeconfig as non-root) to `sudo` or gexec before step 3. 1. **OpenBao agt-role**: `railiance-platform/scripts/openbao-apply-ssh-engine.sh` (dry-run first). Warden: copy the `agt-custodian` actor block from `ops-warden/examples/inventory.seed.yaml` into `~/.config/warden/inventory.yaml`. 2. **RBAC**: in railiance-platform `make argocd-pin-drift`; then `argocd app sync railiance-apps-root --revision ded5922 --resource argoproj.io:Application:custodian-agents`; `argocd app sync custodian-agents`. 3. **k3s mode 600** (railiance-cluster): `ansible-playbook ansible/k3s-kubeconfig-mode.yml -e target= --check --diff`, then without `--check`. API pause ~30–90 s. Rollback in playbook header. 4. **Host account** (railiance-infra/ansible): `ansible-playbook playbooks/bootstrap-ssh-ca.yaml --limit Railiance01 --tags restricted_agent_account --check --diff`, then apply. Confirm a fresh `ssh tegwick@railiance01` still works before closing step 0's session. 5. **Workstation distro** (operator distro, this repo): ``` powershell.exe -NoProfile -ExecutionPolicy Bypass -File "$(wslpath -w workstation-agents-r4/import.ps1)" -IAmAttended tar -C workstation-agents-r4 -cf - . | wsl.exe -d custodian-agents -u root -- bash -c 'mkdir -p /root/r4 && tar -C /root/r4 -xf - && bash /root/r4/guest-setup.sh --i-am-attended' wsl.exe --terminate custodian-agents ``` Never `wsl --shutdown`, never touch another distro. 6. **Harness install + login inside the distro** (as custodian-agt, interactive by Bernd): Codex, Claude Code, Grok Build installers; each logs in with its own account. Codex desktop: add the Windows-side public key to `/etc/ssh/authorized_keys/custodian-agt` (root), connect to `custodian-agt@127.0.0.1:22273`. 7. **Credentials into the distro** (from the operator account, daily): - `kubectl -n custodian-agents create token custodian-agent --duration=24h` → kubeconfig at `/home/custodian-agt/.kube/config` (server URL, CA, token only). - agent keypair generated inside the distro; operator runs `warden sign agt-custodian --pubkey > `; place cert beside key. - Forgejo bot token (tenant-zero bot, no GitOps-repo write). 8. **gated-executor**: register project (`custodian register-project`), then GEXEC-WP-0001-T06 attended install on railiance01. 9. **Proof (T02 acceptance)**, run inside `custodian-agents` as custodian-agt: - `kubectl auth whoami` → `system:serviceaccount:custodian-agents:custodian-agent`. - `credential-boundary-r1/verify_agent_denials.py` with supervisor namespace inventory. - `ssh custodian-agt@railiance01`: `sudo -n true` fails; `cat /etc/rancher/k3s/k3s.yaml` fails. - `ssh tegwick@railiance01` refused (no cert for that principal); no `~/.kube` admin config, no `/mnt/c`, `wsl.exe`/`powershell.exe` absent, no `SSH_AUTH_SOCK`, no OpenBao token. - gexec: one approved no-op executes; tampered/replayed/expired refused; sanitized output only. Record sanitized output under `docs/evidence/`. ## Re-arm list (builder-mode conveniences to tighten at production close-down) - egress allowlist for `custodian-agents`; loopback forwards from the operator distro are reachable (shared WSL2 network namespace) - retire `agt-task-bridge` / `agt-interhub-bootstrap` → tegwick (RAIL-HO-WP-0014-T03) - gexec credential fetch via custody owner (GEXEC-WP-0001-T07) instead of a pre-placed file - T05 rotation of the 2026-09-23 exposed Secrets stays founder-triggered