Watch
0
0
Fork
You've already forked hyperhive
0

derive an agent's backend hosts into the egress allow list at the controller

This commit is contained in:
atlas 2026-10-29 01:10:38 +01:00 • committed by mara
commit c5a876b845
3 changed files with 950 additions and 25 deletions

View file

@ -295,10 +295,9 @@ host. It never decrypts TLS, so it holds no signing key. It caches nothing.
(<https://code.claude.com/docs/en/network-config>): `api.anthropic.com` for
the model API and the usage probe (`hive-agent/src/claude_usage_watch.rs`),
`claude.ai` for the account login, and `platform.claude.com` for the OAuth
token exchange and refresh. An agent whose `ANTHROPIC_BASE_URL` or ACP
provider points elsewhere needs that host added to the option: the value
sits in the agent's own environment file, which the host doesn't read. The
list omits the plugin marketplace clone from `github.com`, since a failed add
token exchange and refresh. An agent whose `ANTHROPIC_BASE_URL` points
elsewhere needs no entry here: the swarm controller adds that host to the
agent's own swarm entries (see _Swarm allow-list_ below). The list omits the plugin marketplace clone from `github.com`, since a failed add
isn't fatal. The rules below still refuse an entry that resolves to a
private address.
- **Allow-list.** `services.hyperhive.squid.allowedDomains` defaults to empty,
@ -333,6 +332,18 @@ host. It never decrypts TLS, so it holds no signing key. It caches nothing.
you add the entry, and `hive-c0re` checks each name again and skips one that
fails, or that the base list or the canary covers, or that another entry of
the same list covers. A name that resolves to a private address stays a 403.
The controller also adds entries itself. When an operator saves an agent's
API-key environment, and once when the controller starts, it takes the host
from `ANTHROPIC_BASE_URL` and from every variable named `*_BASE_URL`
(the address an ACP agent that loads the same file reads), and keeps one
`derived` entry for that agent per host. Each host passes the same check as
an operator's entry, so an IP address, `localhost` and a base-list name get
none. A save or a delete of the environment replaces the agent's derived
entries, and destroying the agent drops all its entries. The controller reads only the
store's copy: an agent on the hand-placed `backendEnvironmentFile` alone, and
the `opencode` preset's `acp.opencode.provider.baseUrl`, get no derived
entry, so add one in the swarm UI. A `hive-c0re` that predates the field
renders a derived entry like any other.
The swarm's list replaces the hive's `allowedDomains` as soon as it exists,
even when empty: add the names the hive allowed to the swarm's list
before relying on it. Until the controller has a list (it predates the

View file

@ -633,6 +633,13 @@ name the proxy's private-range rules leave. **remove** drops one entry;
**add** opens a dialog with a domain box and a tick for every agent in the
swarm. The tick is off by default, so an entry is for this agent alone.
An entry with the badge **automatic** has no **remove**: the controller keeps
it from the host in the agent's stored API-key environment
(`ANTHROPIC_BASE_URL`, or any `*_BASE_URL` variable), so a restricted agent on
another provider reaches it. Saving or removing the environment changes it, and
the API refuses to add or remove one (`400` and `409`). An agent that only has
the hand-placed environment file gets none; add its provider's host here.
A domain is a DNS name of at least two labels, such as `github.com`. One
leading dot, as in `.githubusercontent.com`, also allows every subdomain; the
dot form is the only wildcard, because exact names can't list a service that

View file

@ -299,6 +299,13 @@ text. An agent whose file has content creates the leaf from it again within 2
minutes; one without a file keeps its copy in `/run` until the container
restarts.
A save also keeps the host of `ANTHROPIC_BASE_URL` (and of every `*_BASE_URL`
variable) as an automatic allowed-domain entry for the agent, so a restricted
agent reaches its provider through the hive's proxy; **Remove** drops it. The
controller reads the stored text only. An agent that has just the file gets no
entry, and an operator adds its provider's host in the swarm UI (see
[allowed domains](../swarm/ui.md#allowed-domains)).
Provision the file once, out of band (never through nix — an API key in
the store is world-readable and travels with the flake closure):