Skip to content

Access you must grant

Every tier of Fermi is a trust decision. This page enumerates exactly what each component holds, where it sits, and what its blast radius is if compromised. No prose reassurances — read the table, decide per row.

The grants, by tier

GrantHeld byStored whereNeeded forBlast radius if leaked
Cloudflare accountyouwrangler auth on your machineTier 1 deployyour CF account
FERMI_BEARER_TOKENWorker + daemon + broker executorWorker secret; Mac .envall /admin/* endpointsfull control plane: launch fleet, read session state, drain queues
FERMI_SECRETS_KEYWorkerWorker secretencrypting your stored secretsoffline decryption of the secrets table (needs D1 access too)
FERMI_OWNER_SECRET (+ TOTP)WorkerWorker secretOAuth consent gateattacker can authorize new MCP clients
ANTHROPIC_API_KEYWorkerWorker secretchannel inference onlyAPI spend
MACOS_MCP_TOKENWorker + MacOSMCPWorker secret; Mac configTier 3 mac_* toolsremote shell on your Mac (approval-gated at the tool layer)
AWS keys (EC2 scope)WorkerFermi secrets store, host-allowlisted to *.amazonaws.comTier 4 launch/terminateEC2 spend + instances in one region
CLAUDE_CODE_OAUTH_TOKENWorker → each boxFermi secrets store; injected into box env at provisionbox inference on your subscriptionyour Claude subscription usage
GITHUB_TOKENWorker → boxes needing repo workFermi secrets storeagent pushes/PRsyour repos, to the token's scope
Web session cookiesMac broker executor onlyD1 encrypted at rest; decrypted only on the Macsession-brokered browsingthe captured site session — and only until you web_session_invalidate

Design rules that bound each grant

  1. Per-box tokens, not the admin token, on fleet boxes. A neutrino authenticates as <box_id>.<secret>; the secret is hashed at rest and scoped to the /box/* gateway. A stolen box token can claim that box's task and post artifacts — it cannot call /admin/fleet/launch or read another box's results (wait is box-scoped; tested in test/session-broker.test.ts).
  2. Secrets are allowlisted, then injected. A stored secret carries allowed_hosts and allowed_capabilities. The sandbox and browser lanes see {{secret:NAME}} placeholders; the gateway expands them only toward allowlisted hosts. secret_resolve (plaintext to the model) must be explicitly enabled per secret and is rate-limited and audited.
  3. Cookies never ride to boxes. Fleet agents get a broker handle, never storageState. Every browser op round-trips the Worker, which re-checks session validity — web_session_invalidate cuts off in-flight agents at their next op. Leak witness tests assert the canary cookie never crosses. See The session broker.
  4. The boot path is pinned. Boxes fetch box-runner.mjs at a pinned commit SHA and verify its sha256 before executing; mismatch fails closed and the box reports rather than runs. Launch refuses when no pin is set.
  5. High-risk tools are approval-gated (mint-token-then-redeem, single use, 300s TTL), everything is audited to D1, and plan mode blocks mutation wholesale.

Threat-model honesty

What the rules above do NOT guarantee

  • The budget cap is soft: accrual is checked between polls, not enforced by AWS. A runaway box costs money until the TTL reaper or you kill it.
  • The approval gate keys on token presence, not argument re-verification (args are hashed for audit, not re-compared).
  • MacOSMCP behind a tunnel is a remote-control surface for anyone holding both your Worker auth and a connected host. Host discipline is part of the perimeter.
  • Channel allowlists gate who can enqueue work; they do not sandbox what a queued task may ask for. Prompt-injection through channel content remains your risk to manage.

The minimum-grant configurations

  • Paranoid useful: Tier 1 + Tier 2 without MacOSMCP. Nothing can push into your Mac; the Mac only pulls.
  • Reference deployment: all tiers, with: fleet region pinned, t3.small, max_concurrent 5, budget $50/mo, runner pinned, sessions named per-launch, broker executor on one Mac only.

MIT licensed. Built for people who want to own their agent.