source=automatic; explicit
operator choices and existing legacy_migration records are preserved, including
existing disabled permissions. Native GitHub API
calls remain a separate audience. MCP OAuth, model, connector, master, and
execution-provider credentials are never included in the sandbox environment.
Each run receives one immutable issuance per provider recording the owning agent, credential
kind, permission revision, and whether a credential was available. The durable
run must belong to the agent. Credential writes/deletions and permission edits
invalidate earlier issuances. A running sandbox cannot silently acquire a newer
permission or credential; a new run is required. Continuations must satisfy the
original sandbox’s credential revision as well. Invalidated inherited sandboxes
are eligible for cleanup even before the child run first acquires a handle.
Permission changes and credential rotation also retire retained project snapshots
from reuse, because shell code may have copied a token into the project tree.
Snapshot capture is serialized with revocation.
Delivery uses a protected file inside the sandbox, not a token in the backend’s
exec URL. Shell tools see authorized GH_TOKEN/GITHUB_TOKEN and/or GITLAB_TOKEN. The same authorization
path applies to Modal and Fly Sprites and preserves the agent’s selected backend
or inherited instance default. Git clone, push, and gh/glab use each granted PAT’s
actual provider permissions. A default repository is not a security scope in
an unrestricted shell.
Revocation prevents new authorized delivery and invalidates active and held
sandboxes. Handles revalidate before operations and monitor running operations;
a background worker checks for pending teardown every five seconds, independently
of the agent loop. In-flight operations are rechecked every second; each authorization read has a
five-second deadline so a database outage cancels the operation rather than
leaving its last permission active indefinitely.
Disabling backend acquisition does not disable teardown with retained backend
credentials. Provider unavailability can delay physical destruction; durable authorization
still fails closed. Exact plaintext tokens are redacted from command output,
file reads, and returned errors. This is not an exfiltration barrier: shell code
that can use a PAT can transform or copy it. Revoke or rotate the PAT at its provider
to invalidate copies already exposed outside Mesh. A future broker can replace
long-lived PATs with short-lived credentials; current delivery does not provide that capability.
Grant issuance is recorded in workspace_credential_issuances; operator permission
changes appear in the existing Activity audit with the connection and agent.
Records contain permission metadata, never plaintext tokens. Per-agent, per-provider delivery
locks serialize credential-file writes with revocation; agent commands do not hold
that lock. Issuance is an authorization record, not proof that a vendor received
credential bytes.
Authorization-store failures fail closed by destroying the sandbox, including
transient database errors. Cancelling a tool request alone cannot stop detached
processes that already hold credentials. This deliberately favors authorization
over availability: after such a failure the agent must start a new run. An absent
coding key allows unauthenticated work; an existing key that cannot be decrypted
surfaces the decryption error instead of a misleading git authentication failure.
GitHub and GitLab permissions default on only for the owning agent. Existing
disabled rows remain disabled. A mixed-provider
sandbox is invalidated when either provider changes, but that does not alter the
other provider’s saved permission. See GitLab coding.
Agent-vault entries in the sandbox
workspace_exec accepts secrets: [name, …], the agent’s own vault entries
(Agent vault), delivered to that command as
MESH_SECRET_<NAME> through the same protected grant file the PATs use and
redacted from output the same way. They are deliberately not in
workspace_credential_permissions or workspace_credential_issuances: those
record an operator’s grant of an acting identity to a run, with the revision
machinery that retires a sandbox when the operator changes their mind. A vault
entry is something a person handed the agent for its own work, requested by the
agent per command; rotating or forgetting one does not tear down a running
sandbox, and the next command naming it gets the new value or a refusal. The
entries are written to the grant file for the one command and withdrawn when
it returns, so a later file read sees only the run’s grants. Exact-plaintext
redaction applies to the credential grants by key and to every per-command
value at any length. Two entries that would meet at one variable after
uppercasing (api_key, API_KEY) are refused rather than letting one win.
The workspace broker (built, off)
internal/workspacebroker (0084_workspace_broker.sql) can carry a provider’s git
traffic through Mesh so its token never enters the sandbox: git’s configuration
rewrites the provider’s URLs to PUBLIC_URL/workspace-broker/..., the sandbox
holds a run-scoped Mesh token, and Mesh adds the agent’s PAT per request.
No provider is brokered. GitHub was, briefly, and it made agents unable to do
their work: the broker speaks only git, so gh, GitHub Packages
(npm.pkg.github.com), and every other tool that reads GH_TOKEN had nothing to
authenticate with. GitHub delivers the agent’s own PAT again. It is the agent’s
own token on purpose — commits, pull requests and comments carry the agent’s
identity — so an app-minted short-lived token is not a substitute.
The broker and its tests remain (coding.Provider.Brokered); it is dormant, not
deleted, so its schema and code stay consistent with the applied migration.