refactor(mitm): extract provisionDnsEntries to dns/provision.ts (manager.ts under file-size cap) (#6127)

This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-05 00:39:15 -03:00
parent 987b9aa42a
commit cda5917160
3 changed files with 95 additions and 82 deletions

92
src/mitm/dns/provision.ts Normal file
View File

@@ -0,0 +1,92 @@
/**
* AgentBridge DNS provisioning — best-effort, extracted from manager.ts so each step
* is guarded and unit-testable without spawning the MITM server (#6127 / #6198).
*/
import { addDNSEntry, addDNSEntries } from "./dnsConfig.ts";
import { ALL_TARGETS } from "../targets/index.ts";
import { getAllAgentBridgeStates } from "@/lib/db/agentBridgeState.ts";
import { listCustomHosts } from "@/lib/db/inspectorCustomHosts.ts";
import { createLogger } from "@/shared/utils/logger.ts";
const defaultLog = createLogger("mitm-dns-provision");
/** Minimal logger shape used by {@link provisionDnsEntries} (injectable for tests). */
interface DnsProvisionLogger {
error: (payload: unknown, msg: string) => void;
info: (payload: unknown, msg?: string) => void;
}
/** Injectable dependencies for {@link provisionDnsEntries} (all default to the real ones). */
export interface DnsProvisionDeps {
addDefaultDns?: (sudoPassword: string) => Promise<void>;
addHostsDns?: (hosts: string[], sudoPassword: string) => Promise<void>;
getAgentStates?: () => ReturnType<typeof getAllAgentBridgeStates>;
listEnabledCustomHosts?: () => ReturnType<typeof listCustomHosts>;
logger?: DnsProvisionLogger;
}
/**
* Provision every AgentBridge DNS entry (Antigravity defaults + agents with
* `dns_enabled=true` + enabled custom hosts). **Every step is best-effort**: a failure
* is logged with the full `err` — which carries the privileged command's stderr
* (`systemCommands.ts` folds stderr into the Error message) — and never aborts the
* bridge start.
*
* Previously the default step (`addDNSEntry`) was called unguarded while the two
* sibling steps and cert install were wrapped, so in containers/headless (Docker
* `USER node`, no `sudo`, read-only /etc/hosts) it threw out of `startMitmInternal`
* and killed the whole start (#6127); its stderr also never reached app.log — only a
* bare exit code hit the toast (#6198). Extracting + guarding all three steps here
* restores the symmetry and makes the behavior unit-testable without spawning the
* MITM server.
*/
export async function provisionDnsEntries(
sudoPassword: string,
deps: DnsProvisionDeps = {}
): Promise<void> {
const addDefaultDns = deps.addDefaultDns ?? addDNSEntry;
const addHostsDns = deps.addHostsDns ?? addDNSEntries;
const getAgentStates = deps.getAgentStates ?? getAllAgentBridgeStates;
const listEnabledCustomHosts =
deps.listEnabledCustomHosts ?? (() => listCustomHosts({ enabledOnly: true }));
const logger = deps.logger ?? defaultLog;
// Antigravity default hosts.
try {
await addDefaultDns(sudoPassword);
} catch (err) {
logger.error({ err }, "Failed to add default DNS entries (continuing)");
}
// Collect hosts from agents that have dns_enabled=true in the DB.
try {
const agentStates = getAgentStates();
const agentHostsToAdd: string[] = [];
for (const state of agentStates) {
if (!state.dns_enabled) continue;
const target = ALL_TARGETS.find((t) => t.id === state.agent_id);
if (target) {
agentHostsToAdd.push(...target.hosts);
}
}
if (agentHostsToAdd.length > 0) {
logger.info({ count: agentHostsToAdd.length }, "Adding DNS for agent host(s)...");
await addHostsDns(agentHostsToAdd, sudoPassword);
}
} catch (err) {
logger.error({ err }, "Failed to add agent DNS entries (continuing)");
}
// Collect enabled custom hosts.
try {
const customHosts = listEnabledCustomHosts();
const customHostNames = customHosts.map((h) => h.host);
if (customHostNames.length > 0) {
logger.info({ count: customHostNames.length }, "Adding DNS for custom host(s)...");
await addHostsDns(customHostNames, sudoPassword);
}
} catch (err) {
logger.error({ err }, "Failed to add custom host DNS entries (continuing)");
}
}

View File

@@ -2,7 +2,8 @@ import { spawn, type ChildProcess } from "child_process";
import path from "path";
import fs from "fs";
import { resolveMitmDataDir } from "./dataDir.ts";
import { addDNSEntry, addDNSEntries, removeDNSEntry, removeDNSEntries } from "./dns/dnsConfig.ts";
import { removeDNSEntry, removeDNSEntries } from "./dns/dnsConfig.ts";
import { provisionDnsEntries } from "./dns/provision.ts";
import { generateCert } from "./cert/generate.ts";
import { installCertResult, uninstallCert } from "./cert/install.ts";
import { ALL_TARGETS } from "./targets/index.ts";
@@ -501,86 +502,6 @@ export async function startMitm(
}
}
/** Minimal logger shape used by {@link provisionDnsEntries} (injectable for tests). */
interface DnsProvisionLogger {
error: (payload: unknown, msg: string) => void;
info: (payload: unknown, msg?: string) => void;
}
/** Injectable dependencies for {@link provisionDnsEntries} (all default to the real ones). */
export interface DnsProvisionDeps {
addDefaultDns?: (sudoPassword: string) => Promise<void>;
addHostsDns?: (hosts: string[], sudoPassword: string) => Promise<void>;
getAgentStates?: () => ReturnType<typeof getAllAgentBridgeStates>;
listEnabledCustomHosts?: () => ReturnType<typeof listCustomHosts>;
logger?: DnsProvisionLogger;
}
/**
* Provision every AgentBridge DNS entry (Antigravity defaults + agents with
* `dns_enabled=true` + enabled custom hosts). **Every step is best-effort**: a failure
* is logged with the full `err` — which carries the privileged command's stderr
* (`systemCommands.ts` folds stderr into the Error message) — and never aborts the
* bridge start.
*
* Previously the default step (`addDNSEntry`) was called unguarded while the two
* sibling steps and cert install were wrapped, so in containers/headless (Docker
* `USER node`, no `sudo`, read-only /etc/hosts) it threw out of `startMitmInternal`
* and killed the whole start (#6127); its stderr also never reached app.log — only a
* bare exit code hit the toast (#6198). Extracting + guarding all three steps here
* restores the symmetry and makes the behavior unit-testable without spawning the
* MITM server.
*/
export async function provisionDnsEntries(
sudoPassword: string,
deps: DnsProvisionDeps = {}
): Promise<void> {
const addDefaultDns = deps.addDefaultDns ?? addDNSEntry;
const addHostsDns = deps.addHostsDns ?? addDNSEntries;
const getAgentStates = deps.getAgentStates ?? getAllAgentBridgeStates;
const listEnabledCustomHosts =
deps.listEnabledCustomHosts ?? (() => listCustomHosts({ enabledOnly: true }));
const logger = deps.logger ?? log;
// Antigravity default hosts.
try {
await addDefaultDns(sudoPassword);
} catch (err) {
logger.error({ err }, "Failed to add default DNS entries (continuing)");
}
// Collect hosts from agents that have dns_enabled=true in the DB.
try {
const agentStates = getAgentStates();
const agentHostsToAdd: string[] = [];
for (const state of agentStates) {
if (!state.dns_enabled) continue;
const target = ALL_TARGETS.find((t) => t.id === state.agent_id);
if (target) {
agentHostsToAdd.push(...target.hosts);
}
}
if (agentHostsToAdd.length > 0) {
logger.info({ count: agentHostsToAdd.length }, "Adding DNS for agent host(s)...");
await addHostsDns(agentHostsToAdd, sudoPassword);
}
} catch (err) {
logger.error({ err }, "Failed to add agent DNS entries (continuing)");
}
// Collect enabled custom hosts.
try {
const customHosts = listEnabledCustomHosts();
const customHostNames = customHosts.map((h) => h.host);
if (customHostNames.length > 0) {
logger.info({ count: customHostNames.length }, "Adding DNS for custom host(s)...");
await addHostsDns(customHostNames, sudoPassword);
}
} catch (err) {
logger.error({ err }, "Failed to add custom host DNS entries (continuing)");
}
}
/**
* Internal body of startMitm(), extracted so the single-flight lock in
* startMitm() cleanly wraps it in try/finally without re-indenting the

View File

@@ -19,7 +19,7 @@
*/
import { test } from "node:test";
import assert from "node:assert/strict";
import { provisionDnsEntries } from "../../src/mitm/manager.ts";
import { provisionDnsEntries } from "../../src/mitm/dns/provision.ts";
function makeSpyLogger() {
const errorCalls: Array<{ payload: unknown; msg: string }> = [];