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

@ -16,6 +16,9 @@
// internet flag reaches any name the proxy's private-range rules leave, so an
// entry matters only to a restricted one.
//
// An entry the controller keeps from the agent's backend environment (`derived`)
// shows as automatic with no remove control; the route refuses to remove it.
//
// Its state belongs to one agent: callers key it by agent name.
import { useEffect, useState } from "preact/hooks";
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
@ -117,19 +120,32 @@ export function AllowedDomains({ agent }: { agent: string }) {
{shown.length > 0 ? (
<ul class="ui-agent-limits-list">
{shown.map((e) => (
<li key={`${e.agent ?? "*"}/${e.domain}`}>
<li key={`${e.agent ?? "*"}/${e.domain}/${e.derived === true}`}>
<Badge
label={e.agent === undefined ? "swarm-wide" : agent}
label={
e.derived === true
? "automatic"
: e.agent === undefined
? "swarm-wide"
: agent
}
value={e.domain}
title={
e.derived === true
? "kept from this agent's backend environment; change that variable to change it"
: undefined
}
/>{" "}
<Badge
variant="quiet"
value="remove"
title={`stop allowing ${e.domain} for ${
e.agent === undefined ? "every agent" : agent
}`}
onClick={() => void remove(e)}
/>
{e.derived === true ? null : (
<Badge
variant="quiet"
value="remove"
title={`stop allowing ${e.domain} for ${
e.agent === undefined ? "every agent" : agent
}`}
onClick={() => void remove(e)}
/>
)}
</li>
))}
</ul>

View file

@ -7,6 +7,11 @@ export interface AllowedDomain {
domain: string;
/** Absent for an entry that holds for every agent in the swarm. */
agent?: string;
/**
* Kept by the controller from the agent's backend environment: shown as
* automatic, and the route refuses to remove it.
*/
derived?: boolean;
}
export const ALLOWED_DOMAINS_URL = "/api/egress/allowed-domains";
@ -28,10 +33,12 @@ export function entriesFor(
export function allowedSummary(shown: AllowedDomain[]): string {
if (shown.length === 0) return "none added";
const swarmWide = shown.filter((e) => e.agent === undefined).length;
const own = shown.length - swarmWide;
const automatic = shown.filter((e) => e.derived === true).length;
const own = shown.length - swarmWide - automatic;
return [
swarmWide > 0 ? `${swarmWide} swarm-wide` : null,
own > 0 ? `${own} for this agent` : null,
automatic > 0 ? `${automatic} automatic` : null,
]
.filter((part) => part !== null)
.join(", ");

View file

@ -52,3 +52,13 @@ test("the body is swarm-wide or for the agent, with the name trimmed", () => {
agent: "atlas",
});
});
test("a derived entry is counted as automatic, not as the operator's own", () => {
const derived = { domain: "llm.example.com", agent: "atlas", derived: true };
assert.equal(
allowedSummary([...entriesFor(all, "atlas"), derived]),
"1 swarm-wide, 2 for this agent, 1 automatic",
);
assert.equal(allowedSummary([derived]), "1 automatic");
assert.deepEqual(entriesFor([derived], "atlas"), [derived]);
});