Pairing and credentials
The security model has one headline: no long-lived org secrets sprawl across the fleet. Each machine holds a device keypair and one paired API key; every other credential is leased from the workspace at the moment of use and forgotten.
Device keypair identity
Every agent owns a long-lived Ed25519 device key, generated on first use and stored 0600 at state/org/device-key.pem. The private key never leaves the machine; it signs outbound material, and the public key is presented in the pairing handshake and pinned by the verify layer. A freshly provisioned agent self-bootstraps a stable identity that survives restarts — there is nothing to pre-provision.
The same detective layer verifies what the server signs: directory snapshots, policy bundles and event checkpoints are Ed25519-signed by the org server, and the client re-derives the hash-chained event log to detect tampering.
Two enrollment lanes
Admin-minted key is the primary lane: an admin mints an org API key in Settings → API keys and pairs it to the agent's member, as described in Connect an agent to your workspace.
Pre-auth pairing inverts it — useful when the machine is being provisioned before an admin is at a keyboard:
- Open the handshake from the machine
Pick a short code and run
maestro pair <code>in the agent repo. This POSTspairing.request— the one genuinely unauthenticated method — carrying the code, the agent's derived id and display name, and the device public key. The outstanding handshake is recorded underorg.cohort.pairinginconfig/org.yaml. - Share the code with an org admin
The admin approves the handshake (
pairing.approve, an admin-scope method), which mints the agent's key with the default agent scope set — includingcredential.use. - Complete enrollment
Set the issued key as
org.cohort.token(or re-runmaestro setup --only org). The config stays disabled until both endpoint and token are present.
The credential broker
Running 50 agents means 50 machines that would each need a DeepSeek, Moonshot or OpenAI key — an unmanageable breach surface where rotating one key means touching every mini. The broker collapses it: each provider key is set once at the org, sealed with AES-256-GCM at rest, and never logged.
Admins manage provider keys in Cohort → Settings → Secrets — shared credentials scoped per provider. On a self-hosted org server the admin CLI is the equivalent, and reads the value from stdin so it never lands in shell history:
printf '%s' "$DEEPSEEK_API_KEY" | cohort credential put --provider deepseek

Leases at spawn time
When the model router is about to spawn a non-Anthropic backend, it needs that provider's key in the child process environment. Instead of reading a file on disk, the agent calls credential.lease (scope: credential.use). The server checks the credential's allowed roles and agents against the agent's verified identity, then returns the plaintext once over TLS with a short expiry. The agent injects it into that one child process's env and discards it.
The invariants, in order of importance:
- Never persisted. The leased value exists only in process memory and the single spawn's env — never written to
config/, disk, or logs. - Local wins. A key you set in the agent's own
.envalways beats the org lease for that provider. - Fail-open. Broker unreachable or key missing falls through to whatever the agent already has; a genuinely absent key surfaces as the router's
missing_credential, never a crash. - Audited. Every put, lease and revoke appends a row to the org's hash-chained event log — provider, agent, time. Never the value.
Rotation and revocation
Rotate once, at the org: re-set the provider key and every agent picks it up on its next lease — nothing to push, no machine to touch, no restart to coordinate. Because leases are short-lived, the fleet converges within one lease cycle. Revoking a provider makes subsequent leases fail closed, so agents stop being able to spawn that backend at all.
The kill switch
To contain a specific machine rather than a provider key, deactivate the agent centrally: the next presence beat (within about 60 seconds) returns a halt directive, the agent's token is revoked, and it stops acting — and can no longer lease anything. Tokens are short-lived and renew via a device-key challenge, so a deactivated agent cannot keep running on a stale token; equally, an outage with expired tokens heals on reconnect without anyone touching the machine.
The local secret store
Separate from org provider keys, each agent has a local secret lifecycle for its own credentials:
maestro secrets list # names only, never values
maestro secrets sync [--name X] # pull org-brokered secrets into the local store
maestro secrets rotate --name X # new value read from stdin
Resolution precedence is explicit override → broker → file → env, reads fail open, and every rotation appends a names-only audit row to logs/audit/secrets.jsonl — who, which name, when, which provider. Never the value.