# Acceptance 0013: Mixed prod (VM, Deno sandbox, agent VM on a user-configured bidder) Proves [../../examples/infra/mixed-prod.yaml](../../examples/infra/mixed-prod.yaml) end to end against prod services: a long-lived requester (`run requester`, then `install requester`) with a real atproto account, kubectl apply of one EphemeralInfra pinned to a bidder the user configured, use each contract, restart the requester mid-run, delete. The default policy runs on both sides; no file and no command names `open` ([../quickstart-prod.md](../quickstart-prod.md) sections 2, 5 and 7). - Paths: A `run requester` in the foreground (OAuth QR); B `install requester` (systemd user unit of its own account); C the gateway in the requester kcp (`run requester --with-gateway`, a tenant cluster) - Plan: [0039](../plans/0039-long-lived-requester.yaml) items F-MIXED-PROD (this runbook) and ACC39-MIXED-PROD (its live pass) - Last pass: 2026-11-01 on prod: A and C on rc159 (`ec0f4849`), B on the rc160 CLI (`840f0437`; on rc159 B failed its ssh step, Known Pitfalls). Prod readings below ```mermaid sequenceDiagram participant U as user (kubectl, atirc) participant K as requester kcp (run requester) participant R as Requester app participant B as user-configured bidder participant I as irc.fedfork.com U->>K: apply vouch.yaml, mixed-prod.yaml K->>R: ComputeContract vm1, sbx1, agent1 (bidderDids pin) R->>B: RFP (requester-tangled-vouch attached) B->>B: bidder-tangled-vouch + attached policy: operator vouched requester? B->>R: bid R->>R: requester-tangled-vouch: requester vouched bidder? R->>B: accept B->>R: receipt, guest events (onNetwork, hostKeys, vm.sandbox) R->>I: chat.atirc.mint (agent1, leased on receipt + vm.terminated) R->>K: ComputeContracts Held, EphemeralInfra Deployed U->>B: ssh vm1 (iroh, webrtc); read sbx1 stdout U->>K: agent-start ContractEvent -> guest.agentStart U->>I: JOIN of the agent nick, prompt, answer U->>K: Ctrl-C, restart: Held stays Held U->>K: delete EphemeralInfra -> revoke -> vm.delete -> vm.terminated ``` ## Preconditions | Item | Need | | --- | --- | | Bidder | a bidder the user configured: `install bidder` with the default policy (no `--bidder-policy`: `bidder-tangled-vouch`), [../bidder.md](../bidder.md); for sbx1 it must serve deno: `run bidder --compute-kinds vm,deno`, or `install bidder --compute-kinds vm,deno` (written to its `config.json`; on an already installed bidder, run the install again with the flag, which restarts the bidder unit); optional `--bidder-operator-signin ` for the operator vouch of step A4 | | Bidder DID | `MarketBidder app` `status.did` in the bidder kcp (the operator reads it); it replaces `REPLACE-BIDDER-DID` in every contract of `mixed-prod.yaml` | | Requester account | a real atproto account (handle resolves to its DID, PDS public) signed in by OAuth QR; the creds file owner-only (mode 0600), read only by `scripts/oauth-signin.ts` | | Vouches | both directions: requester -> bidder by [../../examples/infra/vouch.yaml](../../examples/infra/vouch.yaml) in the requester kcp (needs the optional scope `repo:sh.tangled.graph.vouch`) or `goat`; bidder operator -> requester by [../../examples/infra/vouch-bidder-operator.yaml](../../examples/infra/vouch-bidder-operator.yaml) in the bidder kcp (operator sign-in) or `goat` from the operator account | | atirc | a token of your own (`atirc token `) to `atirc sub` the owner channel; never print it | | Host | Linux, `kubectl`, `jq`, `ssh`, the release or dev binary of the commit under test as `$SWC`; B: root on the requester host | | Rules | [README.md](README.md) shared rules: announce on atirc first, one driver per account, release what you rent | ## Steps `ST` is an owner-only state dir (`ST=~/.tmp/acc13; mkdir -p "$ST"; chmod 700 "$ST"`). Write each vouch at least 5 minutes before the first apply when a contract was denied before (verdicts are cached, denials too). ### A. run requester (foreground, OAuth QR) 1. Start: `$SWC run requester --name mp --state-dir "$ST" -- --atproto-oauth-qr > "$ST/mp.log" 2>&1 &`. Sign in from the `pendingAction.url` in the log with `scripts/oauth-signin.ts --creds --account --url ""` (read the url right before, never print or paste it). 2. Wait for `$ST/requesters/mp/ready.json` (written atomically once the root is Ready); `eval "$($SWC run requester env mp --state-dir "$ST")"` sets `KUBECONFIG` to the requester workspace; `kubectl get marketrequesters.socialweb.computer app -o jsonpath='{.status.phase} {.status.did}'` is `Ready `; the ready file's `identityMode` is `oauthQr`. 3. Requester -> bidder vouch: `sed -e "s/REPLACE-REQUESTER-REPO/repo-$(jq -r .did "$ST/requesters/mp/ready.json" | tr : -)/" -e "s/REPLACE-BIDDER-DID//g" -e "s/2026-11-01T00:00:00Z/$(date -u +%Y-%m-%dT%H:%M:%SZ)/" examples/infra/vouch.yaml | kubectl apply -f -`; AtprotoRecord `vouch-bidder` Applied with `at:///sh.tangled.graph.vouch/`. When the session lacks the vouch scope, write the same record with `goat record create` from the requester account instead. 4. Bidder operator -> requester vouch: in the bidder kcp, `vouch-bidder-operator.yaml` with `REPLACE-REQUESTER-DID` (the operator sign-in of [../bidder.md](../bidder.md)), or `goat` from the operator account; check with `goat get "at:///sh.tangled.graph.vouch/" | jq -r .kind` -> `vouch`. 5. Apply: `sed -e "s|ssh-ed25519 AAAAREPLACE-WITH-YOUR-PUBLIC-KEY you@laptop|$(cat "$(jq -r .sshPublicKey "$ST/requesters/mp/ready.json")")|" -e "s/REPLACE-BIDDER-DID//" examples/infra/mixed-prod.yaml | kubectl apply -f -`; `kubectl wait ephemeralinfras.socialweb.computer/mixedprod --for=jsonpath='{.status.phase}'=Deployed --timeout=5m`. 6. vm1: `$SWC run requester ssh mp --state-dir "$ST" --contract einfra-mixedprod-vm1 --exec 'cat /root/mixedprod'` prints `mixedprod-vm-ok`; the same with `--transport webrtc --exec 'uname -m'` prints `x86_64`. 7. sbx1: `kubectl get computecontracts.socialweb.computer einfra-mixedprod-sbx1 -o jsonpath='{.status.contract.sandbox}'` has `stdout` `mixedprod-deno-ok sum=10 on linux/x86_64` and `exitCode` 0. 8. agent1: the requester log has `requester_agent_bundle_placeholder` (no bao step) and, after the receipt, `requester_atirc_minted`; then `sed -e 's/quickstart-agent-agent1-start/mixedprod-agent1-start/' -e 's/einfra-quickstart-agent-agent1/einfra-mixedprod-agent1/' examples/infra/agent-start.yaml | kubectl apply -f -`; in your `atirc sub` the agent nick `