# Self-hosted Subrouter authority S6 — retire distributed refresh capability

**Status:** SUPERSEDED
**Base:** S5 final evidence `47c1ae06f0ed271d027211324c73cbbffed77904`
**Authority policy:** no live account migration or repair is authorized in this slice. `zync` remains native/unbound and may only be used for the previously authorized direct `gpt-5.3-codex-spark` model test. `zync2` is unavailable and must not be recreated.

> **Superseded 2026-08-22:** The owner moved Factory and agentic execution to AWP and narrowed Overdeck to workstation management. The K3s/Factory acceptance in this plan is no longer authoritative. Continue with [Workstation AI account Gateway convergence](2026-08-22-workstation-ai-account-gateway.md). Historical evidence below is preserved.

## Goal

Retire provider-refresh-token distribution for **authority-managed** entries without removing intentional native support for accounts that have not migrated.

Authority-managed execution must be structurally unable to:

- copy/mount a Codex `auth.json` or Claude provider credential into a buildbox/seat/K3s job;
- use the legacy `cdx-codex-auth` Kubernetes Secret;
- create or reconcile Claudex copies of provider access/refresh tokens;
- fall back to native/podman/provider credentials when the authority path is unavailable;
- invoke provider repair except through the local Subrouter authority lifecycle.

Native/unmigrated entries keep existing behavior until explicitly migrated by a future owner-authorized transaction.

## S6 implementation

### K3s authority mode

- CommandRouter passes an explicit non-secret authority descriptor (`provider`, `authority_name`, `route_id`) separately from provider `Credential`.
- Authority-managed remote dispatch requires K3s; if K3s is disabled/unavailable, it fails closed instead of entering the native podman path.
- K3s authority mode never queries or mounts `cdx-codex-auth` and never creates the `prepare-credential` init container.
- A short-lived `audience=buildbox-run` grant is minted by the established `seat-grant` helper.
- The attempt-owned Kubernetes Secret contains exactly `route.id` and `proxy.key`; it is owner-referenced to the suspended Job.
- The Job materializes only gateway Codex `config.toml` and `SUBROUTER_PROXY_KEY` in ephemeral home state.
- NetworkPolicy adds only the exact tailnet authority IP/port in addition to the existing Git proxy/result-mailbox paths.
- Grant ownership transfers to the returned Session only after the Job is unsuspended; every pre-agent failure revokes it in `finally`; normal Session release also revokes it.
- Native K3s behavior is unchanged and continues to require `cdx-codex-auth`.

### Claudex authority mode

- Migrated Codex selection reads authority binding metadata without opening native `CODEX_HOME/auth.json`.
- Fully migrated `subrouter` entries use the verified authority data-plane route; dark/native entries retain the old path.
- `claude-code-proxy` receives `CCP_CODEX_BASE_URL` pointing at the exact Subrouter `/v1/responses` route.
- Its temporary private config contains only the gateway grant, an empty refresh field required by the proxy schema, and verified grant expiry. It contains no provider refresh token/account identifier and is deleted after the proxy exits.
- Migrated Claudex never calls `reconcile_credentials` and does not expose `SYSTRAY_CODEX_ACCOUNT_HOME`.
- Non-ready/quiesced authority state fails closed.

### Tailnet edge / K3s runtime

S3 intentionally approved only `debian1` and used `debian2` as the negative peer. S6 authority-managed K3s workers are pinned to `debian2`/`debian3`, so installed acceptance expands the approved machine set to `debian1,debian2,debian3`. Route-scoped run grants remain the second authentication layer. This is not an open edge: peers outside that exact set remain machine-denied.

The tracked non-secret K3s registry gains:

```json
"authority_origin": "http://100.126.128.50:31416"
```

The buildbox-registry parser treats it as an optional, validated HTTP Tailnet IPv4 origin and rejects credentials, non-tailnet addresses, paths, queries, fragments, or missing ports. Canonical deploy syncs this tracked registry to `~/.claude/buildbox-hosts.json`; no provider credential is added to registry configuration.

## Acceptance

Fixture/buildbox gates must prove:

1. native K3s still contains the existing native credential Secret/init contract;
2. authority K3s contains no `cdx-codex-auth`, `/credential/auth.json`, provider access/refresh token field, or native fallback;
3. authority K3s creates only route+run-grant Secret material and revokes it on success/failure teardown;
4. authority K3s NetworkPolicy permits only the exact tailnet authority endpoint;
5. migrated Claudex resolves with native auth absent, starts with an ephemeral gateway-only CCP profile, never reconciles provider credentials, and deletes that profile;
6. dark/quiesced/non-ready gateway state cannot use the migrated path;
7. Systray Repair remains delegated to local Subrouter authority administration (S5 lifecycle adapter contract);
8. metadata-only registry inspection shows real `zync` remains `authority_binding: null`;
9. repository/runtime scan finds native credential machinery only behind native/unmigrated branches, not reachable from authority-managed branches;
10. installed credentialless K3s probe reaches the exact synthetic route through the tailnet edge, then revokes/removes grant/route state and returns authority to 0 credentials / 0 routes / 0 grants / 0 unresolved attempts.

No live provider call is required or authorized for S6.

## Installed proof sequencing

1. Seal focused/static/module/full candidate gates.
2. Land/deploy S6 code.
3. Verify canonical deploy synced the tracked non-secret `authority_origin` into `~/.claude/buildbox-hosts.json`.
4. Expand edge approved hosts to `debian1,debian2,debian3` using the deployed `install-tailnet-edge`.
5. Create one temporary credentialless Codex fixture route (no provider account/credential).
6. Run a K3s authority probe only; do not invoke a provider.
7. Verify no provider credential Secret/material is delivered and run grant is revoked on release.
8. Remove fixture route/state and verify authority returns to all-zero.
9. Re-run metadata-only `zync` binding check and repository/runtime retirement scan.
10. Record final evidence, seal/land/deploy the evidence commit.

## Rollback

S6 code rollback does not mutate account bindings. Any future migrated account rollback must use the S5 quiesce → fresh native reauthentication → readiness → binding switch → authority cleanup transaction. Native credential support remains present for intentionally native entries, but authority-managed entries cannot select it as fallback.
## Pre-land verification evidence — 2026-08-22

Current S6 implementation remains fixture-only. No real provider account has been authenticated, migrated, repaired, copied, or authority-bound; live authority remained 0 provider credentials / 0 routes / 0 grants / 0 unresolved attempts with Gateway ready throughout implementation verification.

Authenticated candidate verifier on registered buildbox `debian1` is green on the current tree:

- candidate digest `1e965f976a76708a6878ab37ac93d5dbf6d5df553af409f743fef5fe8b458037`;
- Subrouter patch digest remains `596196781fbd18ef47eeac1335c07c787db41321bdfb1f84fc9510f283010219`;
- focused PASS, including native seat contracts, authority seat contracts, remote-runner contracts, `buildbox-registry.test.mjs`, **256 Systray S5/S6 authority tests**, and Codex+Claude migration fixture verification;
- static PASS;
- module PASS (**54 passed**);
- full upstream Subrouter suite PASS.

Broader Systray verification from a complete module/packaging snapshot under a protected buildbox parent produced **1190 passed, 1 skipped, 1 deselected, 2 failed**. The deselected test is the previously reproduced CPU-spin stall-supervisor baseline. Both failures (`test_store_rejects_malformed_or_unsafe_state` and `test_cinnamon_autostart_desktop_entry_is_templated_and_installed`) reproduce identically from exact clean `origin/main` under the same buildbox environment, so they are inherited baselines rather than S6 regressions.

Focused direct verification of the latest tracked registry/schema and S6 authority surfaces also passed: `buildbox-registry.test.mjs` PASS and **240 Python tests passed**. The tests prove migrated K3s has no native auth Secret/init path or native fallback, run grants are revoked on normal/pre-agent/ambiguous-start teardown, migrated Claudex can operate with native `auth.json` absent, and no provider credential reconciliation occurs.
## Installed acceptance finding — edge config reload

The first deployed credentialless K3s probe reached the authority probe command but exited with the bounded probe status `rc=71`. Its detached controller cleaned the Job, input ref, and run grant correctly, returning authority to one intentional fixture route / zero grants. A no-auth machine-level diagnostic then proved the transport mismatch without using any credential material: `debian1` received upstream HTTP 404 while `debian2` and `debian3` received the edge's bare HTTP 403, despite the protected edge config already listing all three hosts.

Root cause: `install-tailnet-edge` rewrote `/etc/overdeck/subrouter-edge.json` but used `systemctl enable --now`; an already-running edge resolves its approved Tailnet IPs only at process startup, so its in-memory S3 allowlist remained `debian1`-only. S6 now requires `systemctl enable` followed by an explicit `systemctl restart` after every config/install update. A buildbox regression test verifies this contract. The live K3s acceptance must be retried only after this fix is sealed, landed, and deployed.

