plan: "0035" title: "A requester can ask for an atirc agent on its guest: spec.agent, a long atirc token minted at the RFP into the secrets bundle, an atirc-agent.service unit, and a requester-originated guest.agentStart event" status: done source: > 2026-10-29 and 2026-10-30, the user's decisions (binding), design rev 6 of the kcp-wasm page plan docs/plans/0035-atirc-agent.md (johnandersen777/kcp, branch kcp-wasm-memory-storage-1). The page and the CLI request a VM from the socialweb market and give it an atirc agent: a long atirc token named -, minted by the requester when the VM request creates its RFP, delivered through the requester-vault secrets bundle as ATIRC_TOKEN, and a guest systemd unit that runs the atirc README's root/new-account block and `atirc agent run`. It follows the wootty shell pattern of plan 0032 (internal/atproto/cloudinit/tunnels.go) end to end: opt-in per contract, a cloud-init module from contractModules, the binary from socialweb-guest-downloads through setup-guest-binaries.service, the token only in the secrets bundle. Option B (user, 2026-10-29): user_data installs the unit but does not start it; a requester-originated com.publicdomainrelay.temp.compute.events.guest.agentStart starts it, so no harness spend until the user asks. atirc deployment https://irc.fedfork.com (did:web:irc.fedfork.com, service #atirc). linux/arm64 is out of scope (user). principle: > The agent is opt-in per ComputeContract (spec.agent). Only opted-in contracts mint: a long atirc token is not revocable. The token lives only in the requester's OpenBao bundle and the guest file 0600, never in user_data, spec, status, a record, a ContractEvent or a log line. The bidder installs the atirc binary from its own downloads; the guest never fetches it from irc.fedfork.com or the internet. The unit starts only on a guest.agentStart the requester publishes; the bidder refuses that event from a guest. decisions: scope: > internal/atproto/oauth/scope.go: RequesterOAuthScope gains rpc:chat.atirc.mint?aud=did:web:irc.fedfork.com%23atirc (exact aud, linux-kcp and atirc-dev 2026-10-30); the requester calls getServiceAuth with aud did:web:irc.fedfork.com#atirc and lxm chat.atirc.mint (the same string; atirc accepts it and the bare DID). Fall back to aud=* only if the PDS refuses. typescript-helpers lib/oauth-scope/mod.ts mirrors the Go scope token for token. The unused OAuthScopeLocalhost constant goes. api: > ComputeContractSpec.Agent *ComputeContractAgent {EnvFile, apigen userEndpoint, default /etc/atirc/atirc.env}. spec.agent without spec.secretsRef fails the contract before the RFP ("an agent needs its token in spec.secretsRef"). The Infra and EphemeralInfra contract templates carry it as they carry tunnels. mint: > The requester (internal/market/requester) mints after the RFP is submitted and on resume: ensureAtircToken skips without spec.agent, spec.secretsRef, a handle or deps.ServiceAuth (no identity-mode gate: OAuth and PDS-account identities alike), and when the bundle entry at spec.agent.envFile already has a non-empty ATIRC_TOKEN. Subhandle