diff --git a/docs/networking/network.md b/docs/networking/network.md
index e3d15215..e7e10c28 100644
--- a/docs/networking/network.md
+++ b/docs/networking/network.md
@@ -307,8 +307,8 @@ host. It never decrypts TLS, so it holds no signing key. It caches nothing.
which the rules below refuse, and agents reach them directly. Each entry
matches that exact name, or with a leading dot the name and its subdomains. A user on the unrestricted list reaches any
other name too, on ports 80 and 443. Everyone else gets a 403 for it.
- `allowedDomains` is the hive's own list. Squid uses it until the swarm has a
- list of its own (next bullet).
+ `allowedDomains` is the hive's own list, always allowed whether or not the
+ swarm has a list of its own (next bullet).
- **Swarm allow-list.** The operator adds domains in the swarm UI
([allowed domains](../swarm/ui.md#allowed-domains)); the swarm controller
keeps them in one value of the `egress-allow` bucket, each for every agent
@@ -344,11 +344,13 @@ host. It never decrypts TLS, so it holds no signing key. It caches nothing.
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
+ The swarm's list adds to the hive's `allowedDomains`: `allowedFile` holds
+ those names plus the swarm-wide entries, so removing an entry never removes a
+ name the hive lists itself. Until the controller has a list (it predates the
feature, or nobody added an entry) `allowedFile` holds `allowedDomains` and
- `agent-allow.conf` is empty. A queue that stops answering for the bucket
+ `agent-allow.conf` is empty. A `hive-c0re` older than this rule replaces
+ `allowedDomains` with the swarm's list once the controller has one, so every
+ hive must run the new `hive-c0re` before the controller's first entry exists. A queue that stops answering for the bucket
leaves a file the swarm wrote untouched, and a failed read leaves both
files untouched. The first line of a file written from the swarm's list is a
`# source: swarm` comment. The queue grant a hive needs to read the list
diff --git a/docs/swarm/ui.md b/docs/swarm/ui.md
index d5670db6..c198a189 100644
--- a/docs/swarm/ui.md
+++ b/docs/swarm/ui.md
@@ -655,9 +655,8 @@ an entry that exists changes nothing.
A saved change isn't instant. Each hive reads the list about every 30
seconds and reloads its proxy, so the name is reachable within a minute. The
proxy's private-range rules still apply: an entry whose name resolves to a
-loopback, private or bridge address stays blocked. The first entry makes the
-swarm's list replace the names a hive's own `allowedDomains` lists, so add
-those names here too; a hive keeps its own list until then. See [the egress
+loopback, private or bridge address stays blocked. An entry adds to the names a
+hive's own `allowedDomains` lists, which stay allowed. See [the egress
proxy](../networking/network.md#egress-proxy-squid) for what each hive does
when the controller is old or unreachable.
diff --git a/frontend/packages/swarm-ui/src/agent/detail/AllowedDomains.tsx b/frontend/packages/swarm-ui/src/agent/detail/AllowedDomains.tsx
index ff3851f2..7341e405 100644
--- a/frontend/packages/swarm-ui/src/agent/detail/AllowedDomains.tsx
+++ b/frontend/packages/swarm-ui/src/agent/detail/AllowedDomains.tsx
@@ -10,9 +10,8 @@
// allows everyone) shows as it arrives, next to the box. The hive reads a
// change within about 30 seconds.
//
-// The first entry makes the swarm's list replace the names the hive's own
-// configuration allows, so a name the hive allowed and the swarm's list lacks
-// stops being allowed once hives read it. An agent that holds the unrestricted
+// An entry adds to the names the hive's own configuration allows, which stay
+// allowed. An agent that holds the unrestricted
// internet flag reaches any name the proxy's private-range rules leave, so an
// entry matters only to a restricted one.
//
@@ -223,9 +222,8 @@ function AddForm({
such as github.com; a leading dot, as in{" "}
.githubusercontent.com, also allows every subdomain. IP
addresses and wildcards are refused. A name that resolves to a private
- address stays blocked. The first entry makes the swarm's list replace
- the names each hive's own configuration allows. The hive reads a change
- within about 30 seconds.
+ address stays blocked. The entry adds to the names each hive's own
+ configuration allows. The hive reads a change within about 30 seconds.