Skip to content

docs: why no Centaur tool can run in an Atrium sandbox#557

Merged
gbasin merged 1 commit into
masterfrom
docs/centaur-tool-egress-note
Jul 16, 2026
Merged

docs: why no Centaur tool can run in an Atrium sandbox#557
gbasin merged 1 commit into
masterfrom
docs/centaur-tool-egress-note

Conversation

@gbasin

@gbasin gbasin commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Design note from wiring atrium-preview (#547, #548). No code — a written-up investigation plus a decision to make.

The finding: two correct designs disagree. Upstream's iron-proxy is a credential injector whose default posture is domains: ["*"]; tools resolve deps from PyPI at run time via uvx --from, and that is the intended upstream design. Atrium sets console.enabled: true for per-user BYO credentials, which flips the proxy to managed mode where the allowlist is per-principal and deny-by-default. PyPI was never re-permitted — so every tool starves. That's what TOOL_ALLOWLIST: "none" has been quietly encoding.

The allowlist semantics (the thing worth verifying before touching prod), read from the running console — app/models/proxy.rb, merge_proxy_policy:

allowlist_domains += domains_from_rules(config)
allowlist = allowlist_domains.uniq.sort

Effective allowlist = union(baseline domains, hosts from granted credentials). Additive, not replacing — so adding pypi.org to the baseline cannot remove chatgpt.com. My earlier fear that this could deny api.openai.com and take down every agent turn was unfounded.

There's already a precedent for a credential-less allowlist entry — CODEX_ACCESS_TOKEN_PER_USER_FRAGMENT allowlists chatgpt.com and injects nothing. Confirmed live: the prod baseline is ["chatgpt.com"] and the sync payload carries secrets: [], so chatgpt.com reaches sandboxes via the baseline. A prod sandbox's entire egress surface is chatgpt.com.

Also recorded, so nobody re-derives them:

  • A zero-dep tool does not dodge this — uvx needs hatchling from PyPI (probed in a live prod sandbox).
  • The image pre-bakes httpx/rich into system python; uvx builds an isolated venv and can't see them.
  • The depcache uv tier is 252K, no hatchling/typer — never warmed, because no tool has ever succeeded.
  • Three claims made during this build that were wrong, including the (now-deleted) iron-proxy.md's assertion that top-level [tool.centaur] hosts widens egress. It's only a default for secrets' hosts.

The decision is policy, not mechanism: should an Atrium sandbox be able to reach PyPI at all? If yes, option A is a small, non-destructive, in-architecture change. If no, the honest conclusion is that the uvx-based tool mechanism can't work here and TOOL_ALLOWLIST: "none" should stay — with the 78 upstream tools dead by choice rather than by accident.

The note separates verified (source + live prod) from assumed at the bottom. Nothing here is deployed or changed.

Writes up the investigation from wiring atrium-preview (#547, #548) — the first
tool meant to actually execute in an Atrium sandbox, and so the first to hit
this.

Two correct designs disagree. Upstream's iron-proxy is a credential injector
whose default posture is domains:["*"]; tools resolve deps from PyPI at run time
via `uvx --from`, and that IS the intended design. Atrium sets console.enabled
for per-user BYO credentials, which flips the proxy to managed mode where the
allowlist is per-principal and deny-by-default. PyPI was never re-permitted, so
every tool starves. Hence TOOL_ALLOWLIST: "none".

The load-bearing finding, read from the running console
(app/models/proxy.rb, merge_proxy_policy):

    allowlist_domains += domains_from_rules(config)
    allowlist = allowlist_domains.uniq.sort

The effective allowlist is the UNION of baseline domains and hosts from granted
credentials — additive, not replacing. So adding pypi.org to the baseline cannot
remove chatgpt.com. That was the one thing worth verifying before touching prod,
and the fear was unfounded.

There is already a precedent for a credential-less allowlist entry:
CODEX_ACCESS_TOKEN_PER_USER_FRAGMENT allowlists chatgpt.com and injects nothing.
Confirmed live: the prod baseline is ["chatgpt.com"], the sync payload carries
secrets:[] — so chatgpt.com reaches sandboxes via the baseline, and a prod
sandbox's entire egress surface is chatgpt.com.

Also records that a zero-dep tool does NOT dodge this (uvx needs hatchling from
PyPI — probed in a live sandbox), that the depcache uv tier is 252K and empty,
and three claims made during the build that were wrong, including the retired
iron-proxy.md's assertion that top-level [tool.centaur] hosts widens egress (it
is only a default for secrets' hosts).

The remaining decision is policy, not mechanism: should an Atrium sandbox be
able to reach PyPI at all?
@gbasin
gbasin added this pull request to the merge queue Jul 16, 2026
Merged via the queue into master with commit b035142 Jul 16, 2026
16 checks passed
@gbasin
gbasin deleted the docs/centaur-tool-egress-note branch July 16, 2026 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant