# Quickstart (prod): Infra and compute against prod bidders
- the same Infra / EphemeralInfra objects as [quickstart-local.md](quickstart-local.md), rented from prod bidders with a real
atproto account
- prod means: prod bidders (each runs `bidder-tangled-vouch`), plc.directory, the did:key ingress relay at
xrpc.fedproxy.com, the relay at relay.mini-cloud-0002.chadig.com, irc.fedfork.com for atirc, a real atproto account
- what works today: the browser page (section 3), the CLI per contract (section 4), the agent join (section 5), tenant clusters
through the prod gateway (section 6), a long-lived requester from the CLI that `kubectl apply` works against (section 7,
`run requester`)
- also on main: that requester installed as a systemd unit of its own account (section 7a, `install requester`) or as a
HostProcess of an account's core (section 7b); the atirc agent from a local PDS or a pdsAccount identity is built
(section 5) and not yet proven on prod
- also on main: your own tenant cluster in the requester kcp (section 8, `run requester --with-gateway`, plan
[0039](plans/0039-long-lived-requester.yaml) item C-GATEWAY-COMPOSE), proven on a local network; a node from a remote
prod bidder is the lead's run
- acceptance: [acceptance/0012-infra-quickstart.md](acceptance/0012-infra-quickstart.md) "Prod Step For The Agent Join" and
"Prod Readings"; [acceptance/0013-mixed-prod.md](acceptance/0013-mixed-prod.md) for
[../examples/infra/mixed-prod.yaml](../examples/infra/mixed-prod.yaml) on a bidder you configured; the runbook rules of [acceptance/README.md](acceptance/README.md) apply (announce on atirc first, release
what you rent, no secret on any terminal)
```mermaid
flowchart TD
ACC["your atproto account (OAuth QR / browser, or app password)"] --> V["vouches: you -> bidder operator, bidder operator -> you"]
V --> PAGE["browser page shell.socialweb.computer kubectl terminal, page's own kcp"]
V --> CLI["CLI per contract run request --hold [--agent]"]
V --> GW["prod gateway XRPC createCluster / getKubeconfig"]
V --> LL["run requester long-lived kcp, ready file, kubectl apply"]
PAGE --> HELD["ComputeContract Held on a prod bidder"]
CLI --> HELD
LL --> HELD
GW --> K8S["tenant k3s, nodes rented through the gateway Infra"]
HELD --> AG["agent VM: requester mints at irc.fedfork.com, guest.agentStart, nick joins"]
```
## 1. Who Runs This
- you, with your own account, from your own host or browser; prod bidders and prod services are shared, so follow the
acceptance rules: one driver per account, announce before a run, release everything you rent
- never set `policy: open`: the default `requester-tangled-vouch` (requester) and `bidder-tangled-vouch` (every prod bidder)
always run
- credentials stay in owner-only files, sourced into the one command that needs them; never print a token, a password or a
sign-in URL
## 2. Vouches On Prod
Both policies read `sh.tangled.graph.vouch` records (rkey = the subject DID, `record.subject` = that DID, any `kind` but
`denounce`). On prod they are records in people's own repos, written with any atproto client (`goat record create`):
| direction | who writes | record |
|---|---|---|
| bidder operator -> you | the bidder operator, in the operator's repo | rkey = your DID |
| you -> bidder operator (or the bidder DID) | you, in your repo | rkey = the operator's DID |
- read a bidder's operator from its MarketIdentity `status.approvedAssociations`, or ask the operator
- the bidder runs the RFP's attached policy as itself before it bids, so without the operator's record you see
`no bids received within 30s` and, on the bidder, `policy rejected ... not vouched`
- verdicts are cached 5 minutes, denials too: write the records first
- check a record: `goat get "at:///sh.tangled.graph.vouch/" | jq -r .kind` prints `vouch`
- when you operate the bidder yourself (`install bidder`, [bidder.md](bidder.md)), you write the operator record from the
operator account; [../examples/infra/vouch-bidder-operator.yaml](../examples/infra/vouch-bidder-operator.yaml) applies in
the bidder kcp of a bidder installed with `--bidder-operator-signin `: the operator signs in once
by QR (scope: `sh.tangled.graph.vouch` writes only) and the record is written to the operator's repo
([bidder.md](bidder.md), Operator sign-in)
## 3. Browser Page: kubectl Terminal
The page `shell.socialweb.computer` runs a kcp and the requester in the browser (comms Firehose, sealed secrets fallback).
Its kubectl terminal applies the same files into the page's own kcp ([acceptance/0009-browser-page.md](acceptance/0009-browser-page.md)).
1. sign in with your account (OAuth)
2. in the terminal, paste the file with a heredoc (the page terminal has no repo checkout, so `-f agent-vm.yaml` finds
no file): `kubectl apply -f - <` opens a shell from the page terminal
5. `kubectl patch ... state Released` releases it
- proven on the page: `agent-vm.yaml` and `vm.yaml`, released by `kubectl patch ... state Released`; `mixed.yaml` (with
the DenoSandbox `sbx1`) and release by deleting the object are not yet proven on the page
- page-rc142 and later write the ssh key and the agent secrets bundle for a kubectl-applied contract; on page-rc141 an
`agent` contract failed at once and `ssh ` had no key
- last pass: page-rc142, account hat, EphemeralInfra `qsprod`, Held in 41 s, `hat-` joined, revoked, then Released
(acceptance 0012 "Prod Readings")
## 4. CLI Per Contract: run request
`socialweb-computer run request` brings up a kcp of its own for one invocation, composes a MarketRequester root, rents one
contract and keeps the invocation under `--state-dir` (runbooks [0003](acceptance/0003-cli-webrtc-ssh.md),
[0004](acceptance/0004-vm-atirc-agent.md)).
```bash
SWC=socialweb-computer
R=~/.tmp/req; mkdir -p "$R"; chmod 700 "$R"
NAME=qs-vm-$(date +%s)
$SWC run request --state-dir "$R" --name "$NAME" --hold \
--tunnel ssh:22:webrtc --transport webrtc --exec "uname -a; id" \
-- --atproto-oauth-qr > "$R/$NAME.log" 2>&1 &
# sign in from the pendingAction url in the log (QR or a scripted sign-in); never paste it anywhere
$SWC run request ssh "$NAME" --state-dir "$R" --transport webrtc --exec "uname -m"
$SWC run request release "$NAME" --state-dir "$R"
```
- identity: `-- --atproto-oauth-qr` (QR), `-- --atproto-oauth` (browser), or an existing account with an app password
(`-- --atproto-identity-mode pdsAccount --atproto-handle --atproto-pds-url `, the password in
`ATPROTO_PASSWORD` in the environment of that one command; `run request` has no `--atproto-password` option)
- `run request list`, `run request resume `, `run request release ` manage the invocations it recorded
- one invocation is one contract; there is no `kubectl apply` of an Infra into it (section 7)
## 5. Agent VM: The atirc Join
The mint needs a requester identity irc.fedfork.com resolves and that signs service auth (lxm `chat.atirc.mint`, aud
`did:web:irc.fedfork.com#atirc`). irc.fedfork.com checks the JWT against the DID document from plc.directory, then the
handle: the first of up to 3 `alsoKnownAs` aliases whose DNS TXT `_atproto.` (else
`https:///.well-known/atproto-did`) names the DID. An agent token is leased, so irc.fedfork.com also reads the
receipt and the bidder's `vm.terminated` from the requester's PDS: that PDS must be reachable from the internet.
| identity | signs the mint with | log `requester_service_auth` `atircSigning` |
|---|---|---|
| OAuth (`--atproto-oauth-qr`, `--atproto-oauth`, the page, the iOS app) | the OAuth session; its granted scope holds `rpc:chat.atirc.mint` | `oauth` |
| existing account with an app password (`--atproto-identity-mode pdsAccount`) | the owner MarketIdentity (getServiceAuth on that account's PDS) | `owner-identity` |
| local PDS (`localRepo`) | its own Pds component, only when the DID is on `https://plc.directory` and the Pds is public through its ingress (a ComponentLink Requester -> Pds `pds.serviceauth`); otherwise none, with the reason in `atircReason` | `local-pds` or `none` |
- the market callbacks (submitBid, submitEvent, the RFP and accept signatures) are unchanged: this source signs only the
atirc mint
- a `spec.agent` contract whose requester handle is `.local` (the default `localRepo` handle
`.requester.local`) or does not resolve to the requester DID is Failed before its RFP, with
`refused: the atirc agent needs a requester handle that resolves to : ...; start the requester with
--atproto-handle ...`; a plain VM contract of the same requester still runs
- a `spec.agent` contract whose `spec.secretsRef` path holds no bundle gets one from the requester: one entry at
`agent.envFile` (`ATIRC_TOKEN=`, mode 0600), logged `requester_agent_bundle_placeholder`; no bao step is needed (the
bao commands of [quickstart-local.md](quickstart-local.md) still work and win, a bundle that is there is kept). The path
must be under `contracts/` of the requester mount
```bash
NAME=qs-agent-$(date +%s)
$SWC run request --state-dir "$R" --name "$NAME" --hold --agent -- --atproto-oauth-qr > "$R/$NAME.log" 2>&1 &
# sign in, wait for Held and requester_atirc_minted in the log
$SWC run request agent "$NAME" --state-dir "$R" # guest.agentStart
# watch your channel with your own atirc token for the JOIN of