Runners & Provider Credentials
Two credential paths, claim eligibility, and the isolation guarantees.
Every model-using run receives its provider credential from one of two paths. A local runner can serve credentials kept on that machine; the dashboard can serve organization credentials encrypted at rest. Both paths require the active task's bearer token and deliver the credential only to that task.
devboxes credentials setup records local API keys, subscription credentials,
or references to supported local auth files. devboxes credentials sync
explicitly copies selected credentials into the organization store. Dispatch
accepts a run only while the requested provider has a usable organization
credential or an eligible local runner. Claiming checks that capacity again.
If it disappears after dispatch, the run remains visibly Queued.
A machine running devboxes listen controls its Docker daemon and receives credential plaintext
for the tasks it executes. Use a dedicated machine and allow only trusted organization members to
dispatch work to it.
How to test it
| Suite | Proves |
|---|---|
pnpm vp run @firops/api#test — opencode-provider-credentials.integration.test.ts, runner-machines.test.ts | Encrypted organization storage, no secret echo, bans, task-token isolation, OAuth lifecycle and refresh, provider-aware claiming, and the stable machine passphrase |
pnpm vp run @firops/api#test — runs-dispatch-models.integration.test.ts, runner-machines-postgres-race.integration.test.ts | Catalog admission, usable provider capacity, no-write rejection, claim-time capacity loss, and dispatch/claim race safety |
pnpm vp run devboxes#test — runner.test.ts, credential-store.test.ts, local-provider-auth.test.ts | Local credential discovery and references, encrypted device storage, broker authorization, refresh rotation, explicit sync, and credential-safe status output |
pnpm vp run devboxes#test — docker-task-runtime.test.ts, flows.test.ts, provider-auth.test.ts, task-runtime.test.ts | Memory-only container delivery, cleanup on launch failure, vendor device-flow behavior, refresh handling, and the shared URL, provider-id, and credential validators |
pnpm vp run @firops/elysia-opencode#test — opencode-files.test.ts | Credential fetch retries on server failure, fails fast on definitive answers, and rejects unsafe auth-file targets |
Manual smoke: run devboxes login, register the machine with
devboxes connect, choose a local credential with
devboxes credentials setup, then follow the
Quickstart through dispatch and claim. devboxes doctor
shows whether registration and credential references are ready before
devboxes listen starts polling.
Decisions
- Dispatch and claiming check the same provider capacity — dispatch rejects
a model with no currently usable path without creating a run. Claiming
rechecks capacity, so a loss after admission leaves the task
Queuedinstead of consuming launch attempts. - Local and organization credentials share one task contract — containers fetch once through the same authorization boundary, so the execution path does not depend on where the credential is stored.
- Keys land on memory-backed storage, never environment variables — container recovery can preserve durable layers; memory mounts disappear with the task.
- The local broker is bridge-reachable and task-scoped — native Linux containers cannot reach host loopback. A random per-task bearer token, not the bind address, grants access.
- Task authorization binds organization, run, task, machine, attempt, and expiry — stale attempts and reruns cannot reuse an earlier credential grant.
- Subscriptions connect independently and sync explicitly — the runner owns the token family it refreshes. Importing another CLI's rotating tokens would let two clients invalidate each other.
- The device store's passphrase lives server-side — the machine holds only age ciphertext on disk; the dashboard stores the passphrase encrypted at rest and returns it only to the authenticated runner. A running process holds that passphrase in memory. Deleting the machine prevents future fetches after that process exits.
- github.com only, no Enterprise host input — a user-supplied GitHub Enterprise domain would create a caller-controlled outbound URL and an SSRF surface.
- Vendor public clients and device flows, zero OAuth configuration — every flow uses the vendor's verification page, so deployments need no redirect URI or client secret.
- Refresh-on-serve with race-safe persistence — tokens are refreshed when they approach expiry, and concurrent refreshes cannot fork one rotating token family. Definitive vendor rejection marks the credential for reconnect, so it stops making the provider dispatchable or qualifying new claims.
- The unified CLI publishes runner, protocol, and provider-connection source under MIT — the npm package and public release mirror carry those sources. The owner-visible consequence of one CLI is that previously private runner source is now publicly reusable under the MIT license.
Next: Dispatch lifecycle — the queue machinery tying all of the above together.