# Self-hosted Subrouter authority S5 — synthetic incremental migration

**Status:** DONE
**Base:** landed/deployed S4 `d55e282811678edf2aa1bc324aca809859155d30`

## Owner-visible evidence first

S5 is complete only when the repository contains one sanitized fixture migration receipt for **Codex** and one for **Claude** proving the full migration/repair/rollback machinery without authenticating or mutating a real account. Each receipt must show that the account stayed dark until every required flow passed, that Repair used the authority-owned login path, that restart preserved authority state, and that rollback required a fresh native-login readiness result before removing the authority binding. No token, raw account slug, route ID, grant ID, OAuth response, Authorization value, or credential path may appear in the receipt.

## Owner constraints

- No live account is authorized for S5 migration, authority binding, reauthentication, or repair.
- `zync2` is unavailable and must not be recreated.
- `zync` remains native and may only be used for the separately authorized native `gpt-5.3-codex-spark` test; S5 does not use it.
- Claude and Codex lifecycle acceptance is synthetic/fake-provider only.
- No native credential file or token is read, copied, imported, reconciled, or restored by migration/rollback machinery.

## Implementation contract

1. **Authority-owned login parity.** Local `authority-account login|repair|status` supports Codex and Claude. Codex continues using the supported device-auth flow. Claude uses the pinned upstream Claude OAuth/login implementation in an isolated temporary authority-owned store, then installs the fresh credential through the authority store's durable `ImportProfileCredential` path. Fixture seams substitute fake logins; no OAuth protocol is reimplemented.
2. **Bounded local admin.** Account lifecycle remains local CLI administration under the dedicated authority service identity. Data-plane route grants cannot invoke login/repair/remove. Output is owner language plus bounded generation/state; no credential or identity body is printed.
3. **Dark-first migration coordinator.** Systray stages an `AuthorityBinding(mode=subrouter-dark)` only after authority login/status and route/grant provisioning succeed. Native launches remain native while dark; gateway health is visible. Promotion to `subrouter` is refused unless the exact provider fixture has passed the complete acceptance checklist.
4. **Required acceptance checklist.** Both providers must prove: CLI launch configuration, resume/session stability, streaming transport, quota/health mapping, Repair through authority, restart/generation durability, exact-route forcing, and no provider credential materialization. Codex additionally proves Responses/realtime/app-server path preservation; Claude proves HTTP/SSE path preservation.
5. **Rollback is reauthentication, not restoration.** Rollback quiesces the binding, disables its route, performs a fresh native login through the injected native lifecycle seam, verifies native readiness without a model request, then atomically removes the authority binding. Only after that switch may the frozen authority account/route/grant be deleted. Failure before native readiness or before the binding switch leaves the binding dark/quiesced; no stored credential is copied back.
6. **Receipts are derived evidence.** `AccountMigrationReceipt/v1` contains provider, authority identity, account/route fingerprints, transition timestamps, flow booleans, generation metadata, rollback outcome, and explicit `provider_credential_copied=false` / `native_fallback_used=false`. It never contains raw account labels, route IDs, grants, keys, credential paths, or OAuth bodies.
7. **Real-account non-mutation proof.** Acceptance includes a metadata-only registry check that any existing `zync` entry still has `authority_binding: null/absent`; no provider credential contents are opened.

## Verification order

1. Focused buildbox tests for Subrouter authority Claude/Codex lifecycle and Systray migration coordinator.
2. Static Go/Python checks and `git diff --check` on a buildbox.
3. Subrouter candidate focused/static/module/full phases for the exact S5 commit plus the Systray migration suite on a registered buildbox.
4. Fixture integration with local fake provider endpoints and exact authority routes, including restart and Repair.
5. Installed credentialless/synthetic proof only. No live login/model call.

S6 is blocked until S5 machinery, fixture receipts, installed proof, landing, and deployment are complete.
## Pre-land verification evidence — 2026-08-22

The current S5 implementation is fixture-only and has not authenticated, repaired, migrated, or authority-bound any real account. Live authority remained at 0 provider credentials / 0 routes / 0 grants / 0 unresolved attempts throughout verification. The protected Codex registry metadata was inspected directly (not provider credential files) and `zync` remained `authority_binding: null`.

Authenticated candidate verification on registered buildboxes is green on the current implementation bytes:

- focused: PASS, including existing S4 contracts, remote-runner contracts, **95 Systray authority/migration tests**, and the standalone Codex+Claude migration fixture verifier;
- static: PASS;
- module: PASS after correcting deterministic compensation for a synthetic workstation-grant creation failure;
- full upstream Subrouter suite: PASS.

The standalone fixture verifier generated:

- `docs/receipts/2026-08-22-subrouter-authority-s5-codex.json`;
- `docs/receipts/2026-08-22-subrouter-authority-s5-claude.json`.

Both receipts end in native state after a full synthetic dark → repair → restart → promote → quiesce → fresh-native-ready → authority-cleanup transaction. They contain only fingerprints/status/timestamps and explicitly record `provider_credential_copied=false`, `native_fallback_used=false`, and `cleanup_complete=true`.

A broader Systray run from a complete S5 module snapshot produced **1157 passed, 1 skipped, 1 deselected, 17 failed**. Every one of those 17 failures reproduced unchanged from a clean `origin/main` archive in the same buildbox environment: one account-lock mode-order expectation, fifteen authority-client tests whose protected-parent checks reject pytest's group/world-writable `/tmp` ancestry, and one pre-existing packaging created-file tuple expectation. Separately, `test_stall_supervisor.py::test_output_ceiling_catches_a_run_that_only_burns_cpu` hung on both S5 and exact clean `origin/main`; the run-owned CPU-spin child was terminated after the clean baseline reproduction. These are inherited baselines, not S5 regressions, and no S5 gate is weakened to hide them.

## Deploy-sourced installed-proof sequencing

S5 Systray installation is performed by `packaging/deploy-local.sh` from the canonical deploy clone, and `SubrouterMigrationAdmin` intentionally resolves `migration-provision` from that same deploy clone. Therefore the installed synthetic proof cannot truthfully run from an unlanded worktree. The accepted sequence is: exact post-commit candidate verification → install the exact Subrouter candidate → land the verified S5 implementation → synchronous canonical deploy → rerun the standalone fixture verifier from deployed bytes → recheck `zync` metadata and live all-zero authority state → record/land/deploy the final S5 evidence commit. S6 remains blocked until that sequence is complete.
## Installed acceptance evidence — 2026-08-22

S5 implementation commit `828162286907e453cd091be0430feff587bf87f8` was landed on `main` and synchronously deployed. The canonical deploy completed with `status=deployed`, `sha=82816228`, and `phase=deploy-finish exit=0`. Installed `cdx.py`, `cld.py`, and `systray_codex_switcher.py` resolve directly into `/home/user/.local/share/overdeck/deploy/modules/systray/` at that deploy revision. `migration-provision` is present in the deploy clone as a regular immutable `0555` executable.

The standalone migration fixture verifier was then executed **from the deployed clone**, not the worktree. It returned `{"status":"pass","providers":["codex","claude"]}`. The deployed outputs were byte-for-byte identical to the committed receipts:

- Claude receipt SHA-256 `543dbbbd6cdfe0fd422619f73217c923edefbc7a3e21f96723ed55a31f003847`;
- Codex receipt SHA-256 `68ee8414a28b0e8e9be4c9b46619c02d7be2ec89f912f0b1a1e60304b7dffc16`.

After deployed fixture acceptance, the protected runtime registry was inspected metadata-only. The real `zync` entry remained exactly `authority_binding: null`; no provider credential file was opened. Live authority remained:

```text
Provider credentials: 0
Authority routes: 0
Proxy grants: 0
Unresolved attempts: 0
Gateway: ready
```

The installed Subrouter reports patch digest `596196781fbd18ef47eeac1335c07c787db41321bdfb1f84fc9510f283010219`. `overdeck-subrouter.service` and `overdeck-subrouter-edge.service` are active/running/success, with listeners restricted to `127.0.0.1:31415` and `100.126.128.50:31416`.

No real Codex or Claude account was authenticated, migrated, repaired, copied, or authority-bound. S5 is complete and S6 may begin only after this final evidence commit is sealed, landed, and deployed.

