Files
MikrotikManager/backend/src/modules/mcp/routing-network-native-session.test.ts
T

374 lines
32 KiB
TypeScript

import assert from "node:assert/strict"
import { readFile } from "node:fs/promises"
import { runInNewContext } from "node:vm"
import { EventEmitter } from "node:events"
import { randomUUID } from "node:crypto"
import { isIP } from "node:net"
import { test } from "node:test"
import { z } from "zod"
import ts from "typescript"
import { canonicalVrfMembers } from "../../services/vrf-members.js"
import { readOspfEffectiveDisabled } from "../../services/ospf-effective-disabled.js"
import { readMeasurementAddress } from "./routing-measurement-address.js"
/** Actual source, inert module providers: no configured DB, sockets, signing
* keys, native grants or checkpoint writers are initialized by these tests. */
async function loadSource(file: string, providers: Record<string, unknown>, globals: Record<string, unknown> = {}) {
const source = await readFile(new URL(file, import.meta.url), "utf8")
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 } }).outputText
const exports: Record<string, unknown> = {}
runInNewContext(compiled, { exports, require(name: string) { assert(name in providers, "Unexpected production dependency: " + name); return providers[name] },
Buffer, URL, AbortSignal, AbortController, setTimeout, clearTimeout, structuredClone, ...globals })
return exports
}
class SessionError extends Error { constructor(readonly code: string, message: string) { super(message) } }
type Factory = (options: Record<string, unknown>) => Promise<{ readSnapshot(stage: string): Promise<Record<string, unknown>>;
readConfigurationBoundForwardSnapshot(context: object): Promise<Record<string, unknown>>; close(): void; readBudget(): Record<string, unknown> }>
async function fixture() {
let clock = Date.now(), revoked = false, sourceChanged = false, endpointChanged = false, payloadRows = 1, wrongVrf = false, failedProbe = false
let afterNative: (() => void) | undefined, pendingNative: (() => Promise<void>) | undefined
let nativeCalls = 0, authorityCalls = 0, callbacks = 0, transports = 0, sourceChecks = 0
const requests: { serverId: number; path: string; body?: unknown }[] = []
class ClockDate extends Date { static now() { return clock } }
const principal = { connectionId: randomUUID(), credentialId: randomUUID(), credentialExpiresAt: new ClockDate(clock + 600000).toISOString() }
const connection = { id: principal.connectionId, owner_id: "owner", generation: "generation", owner_permissions: ["mm:network:read"], owner_valid_until: new ClockDate(clock + 600000),
policy: { scope: { serverIds: [1] }, expiresAt: new ClockDate(clock + 600000).toISOString(), permissions: ["mm:network:read"] } }
const fingerprint = (value: unknown): string => JSON.stringify(value)
const profile = { serverId: 1, family: "ipv4", probeVrf: "probe", candidates: [{ id: "a", jumpHostId: 1, exitNodeId: 1, wanInterface: "wan",
controlProbe: { targetInterface: "target", expectedHops: [{ serverId: 1, interface: "hop" }, { serverId: 1, interface: "target" }] } }] }
const input = { profile, principal, ownerId: "owner", policyProof: fingerprint(connection.policy), connectionGeneration: connection.generation, generation: "access", contextSources: [{ serverId: 1, proof: "source" }] }
const row = { id: randomUUID(), state: "running", connection_id: principal.connectionId, created_at: new ClockDate(clock - 1000), plan_id: randomUUID(), operation_id: "routing.community.switch", operation_version: 7,
approved_by: "owner", step_state: "intent", intended_state: { kind: "service", service: "routing.community.scoped", input }, expires_at: new ClockDate(clock + 600000), evidence: { sealed: JSON.stringify({ steps: [{ kind: "service", service: "routing.community.scoped", input }], target: { scope: "servers", serverIds: [1] } }) } }
const endpoints = [{ id: 1, enabled: true, host: "owned", password: "private", routingEndpointEpoch: "fixed" }]
const configurationToken = Object.freeze({})
const exports = await loadSource("./routing-network-native-session.ts", {
"node:net": { isIP }, zod: { z }, "@mmapp/contracts/mcp-routing": { routeAiProfileSchema: { parse: (value: unknown) => value } },
"../../db/index.js": { pool: { query: async () => { sourceChecks++; return { rows: [{ ...row, plan_id: sourceChanged ? "changed" : row.plan_id }] } } } },
"../../lib/permissions.js": { hasPermission: (permissions: string[], permission: string) => permissions.includes(permission) },
"../../services/vrf-members.js": { canonicalVrfMembers }, "../../services/ospf-effective-disabled.js": { readOspfEffectiveDisabled }, "./routing-measurement-address.js": { readMeasurementAddress },
"./security.js": { fingerprint, redact: (value: unknown) => value, McpError: SessionError, accessGeneration: async () => "access", decryptSecret: async (value: string) => value },
"./store.js": { effectiveMcpConnection: async () => { authorityCalls++; if (revoked) throw new SessionError("RESET_REQUIRED", "revoked"); return connection } },
"./routing-community-context.js": { readRouteCommunityContextWithSharedNativeSession: async () => { throw Error("No shared context invoked by legacy reader fixture") } },
"./routing-network-configuration-bridge.js": { readRoutingNetworkForwardRoundConfigurationContext: async (token: object, acquisition: object) => {
assert.equal(token, configurationToken, "Only the fixed bridge capability is accepted by this inert provider")
const read = exports.readRoutingNetworkSharedResource as (token: object, serverId: number, path: string) => Promise<unknown>
await read(acquisition, 1, "/system/resource")
return { operationId: row.id, phase: "forward", checkpointProof: "inert-boundary-only", configuration: { nativeId: "*1" }, securityProof: false }
} },
"./registry.js": { findMcpOperation: () => ({ version: 7 }) },
"./routing-community-scoped-request.js": { assertScopedCommunityRequest: async () => "genuine-provider-seal" },
"./routing-profile-authority.js": { assertPersistentScopedProfileAuthority: async () => { if (revoked) throw new SessionError("RESET_REQUIRED", "profile revoked") }, routingProfileAuthorityBindingSchema: { parse: () => { throw Error("No persistent binding fixture") } } },
"./routing-observation-source.js": { readRoutingEndpoints: async () => endpoints, createRoutingSourceContext: async () => ({ expected: input.contextSources, assertCurrent: async () => { if (endpointChanged) throw new SessionError("STATE_CONFLICT", "source changed") } }) },
"./routing-network-native-destination.js": { resolveRoutingNetworkDestinationPins: async (_endpoints: unknown, options: { authorize(): Promise<void> }) => { await options.authorize(); return [{ serverId: 1, host: "owned", address: "127.0.0.1", family: 4 }] } },
"./routing-community-context-native.js": { routeContextClients: (_endpoints: unknown, _signal: AbortSignal, limits: { deadline: number; maxCalls: number; maxBytes: number }) => {
transports++; let calls = 0, bytes = 0
const read = async (path: string, body?: unknown) => {
calls++; nativeCalls++; requests.push({ serverId: 1, path, body }); await pendingNative?.()
const payload = path === "/tool/ping" ? [{ sent: "3", received: failedProbe ? "0" : "3", "packet-loss": failedProbe ? "100%" : "0%" }]
: path.endsWith("/get") ? { ret: "false" } : path === "/interface" ? ["wan", "hop", "target"].map((name,index) => ({ ".id": "*i"+index, name }))
: path === "/ip/address" ? ["wan", "hop", "target"].map((name,index) => ({ ".id": "*a"+index, interface: name, address: ["192.0.2.1/32","198.51.100.1/32","198.51.100.2/32"][index] }))
: path === "/ip/vrf" ? [{ ".id": "*v1", name: wrongVrf ? "other" : "probe", interfaces: "wan" }, { ".id": "*v2", name: "main", interfaces: "all" }]
: path === "/system/resource" ? [{ version: "7.20.1" }] : Array.from({ length: payloadRows }, () => ({ ".id": "*1" }))
bytes += Buffer.byteLength(JSON.stringify(payload)); afterNative?.(); afterNative = undefined; return payload
}
return Object.assign(new Map([[1, { get: read, post: read }]]), { readBudget: () => ({ ...limits, calls, bytes }) })
} },
}, { Date: ClockDate })
const options = { sourceOperationId: row.id, context: { principal, connection }, authorize: async () => { callbacks++ }, deadline: clock + 119000, manifest: { servers: [1], probes: [] } }
return { create: exports.createRoutingNetworkNativeSession as Factory, configurationToken, options, requests, stats: () => ({ nativeCalls, authorityCalls, callbacks, transports, sourceChecks }),
advance: (ms: number) => { clock += ms }, revoke: () => { revoked = true }, changeSource: () => { sourceChanged = true }, changeEndpoint: () => { endpointChanged = true },
rows: (value: number) => { payloadRows = value }, wrongVrf: () => { wrongVrf = true }, failProbe: () => { failedProbe = true }, afterNative: (hook: () => void) => { afterNative = hook }, pendingNative: (hook: () => Promise<void>) => { pendingNative = hook } }
}
test("configuration-bound forward reads serialize around the native snapshot and charge both reads before publishing budget", async () => {
const f = await fixture(), session = await f.create(f.options)
await session.readSnapshot("before")
let release!: () => void, entered = false
const barrier = new Promise<void>(done => { release = done })
f.pendingNative(async () => { entered = true; await barrier })
const round = session.readConfigurationBoundForwardSnapshot(f.configurationToken)
const concurrent = session.readSnapshot("after-forward")
try {
for (let i = 0; i < 50 && !entered; i++) await new Promise<void>(done => setTimeout(done, 1))
assert.equal(entered, true); assert.equal(f.stats().nativeCalls, 7, "Concurrent snapshot must stay behind the current acquisition")
} finally { f.pendingNative(async () => {}); release() }
const captured = await round
assert.equal((captured.budget as { calls: number }).calls, 14)
assert(captured.configurationReadbacks); assert.equal(captured.securityProof, false)
assert.equal(captured.forwardingVerified, false); assert.equal(captured.logCoverage, "unknown")
assert.equal((await concurrent).round, 2); assert.equal(session.readBudget().calls, 20)
assert.equal(f.stats().transports, 1)
session.close()
})
for (const fault of ["caller-object", "endpoint", "revoke", "rows"] as const)
test("bound forward round closes the shared owner on " + fault, async () => {
const f = await fixture(), session = await f.create(f.options)
await session.readSnapshot("before")
if (fault === "endpoint") f.afterNative(f.changeEndpoint)
if (fault === "revoke") f.afterNative(f.revoke)
if (fault === "rows") f.rows(1000)
if (fault === "rows") await session.readConfigurationBoundForwardSnapshot(f.configurationToken)
await assert.rejects(session.readConfigurationBoundForwardSnapshot(fault === "caller-object" ? {} : f.configurationToken))
assert.equal(session.readBudget().closed, true)
const stopped = f.stats().nativeCalls
await assert.rejects(session.readSnapshot("after-forward")); assert.equal(f.stats().nativeCalls, stopped)
})
test("one captured session retains deadline, manifest and cumulative counters across stable repeated phase rounds", async () => {
const f = await fixture(), session = await f.create(f.options)
f.options.authorize = async () => { throw Error("outer callback replaced") }; f.options.manifest.servers[0] = 999; f.options.deadline += 600000
const first = await session.readSnapshot("before"), second = await session.readSnapshot("after-forward")
await session.readSnapshot("after-forward")
const third = await session.readSnapshot("after-inverse"); await session.readSnapshot("after-inverse")
assert.equal(first.securityProof, false); assert.equal(first.logCoverage, "unknown")
assert.equal((first.budget as { calls: number }).calls, 6); assert.equal((second.budget as { calls: number }).calls, 12); assert.equal((third.budget as { calls: number }).calls, 24)
assert.equal(session.readBudget().rows, 30); assert.equal(f.stats().transports, 1); assert(f.stats().authorityCalls > 30); assert(f.stats().callbacks > 60)
assert.equal(typeof first.startedAt, "string"); assert.equal(typeof first.observedAt, "string")
assert(f.requests.every(request => request.serverId === 1)); assert(Object.isFrozen(first)); assert(Object.isFrozen(first.servers))
await assert.rejects(f.create({ ...f.options, deadline: Date.now() + 1000, manifest: { servers: [1], probes: [] }, authorize: async () => {} }), /уже создавалась/)
})
test("additive noop authorize cannot mask actual revoked authority, endpoint drift or source plan drift", async () => {
for (const change of ["revoke", "changeSource", "changeEndpoint"] as const) {
const f = await fixture(), session = await f.create(f.options)
f[change](); await assert.rejects(session.readSnapshot("before")); assert.equal(f.stats().nativeCalls, 0)
await assert.rejects(session.readSnapshot("before")); assert.equal(f.stats().nativeCalls, 0)
}
})
test("authority loss during a native await discards the entire response and permanently closes the session", async () => {
const f = await fixture(), session = await f.create(f.options)
f.afterNative(f.revoke); await assert.rejects(session.readSnapshot("before")); assert.equal(f.stats().nativeCalls, 1)
await assert.rejects(session.readSnapshot("after-forward")); assert.equal(f.stats().nativeCalls, 1)
})
test("row overflow, stage replay, explicit close and elapsed original deadline cannot reopen a session", async () => {
for (const failure of ["rows", "stage", "close", "deadline"] as const) {
const f = await fixture(), session = await f.create(f.options)
if (failure === "rows") f.rows(1001)
if (failure === "close") session.close()
if (failure === "deadline") f.advance(120000)
await assert.rejects(session.readSnapshot(failure === "stage" ? "after-forward" : "before"))
assert.equal(f.stats().nativeCalls, failure === "rows" ? 2 : 0)
await assert.rejects(session.readSnapshot("before"))
}
})
test("queued stages share cancellation and cannot dispatch after an in-flight close", async () => {
const f = await fixture(), session = await f.create(f.options)
let release!: () => void, began!: () => void
const pending = new Promise<void>(resolve => { release = resolve }), started = new Promise<void>(resolve => { began = resolve })
f.pendingNative(async () => { began(); await pending })
const first = assert.rejects(session.readSnapshot("before")), second = assert.rejects(session.readSnapshot("after-forward"))
await started; session.close(); release(); await Promise.all([first, second]); assert.equal(f.stats().nativeCalls, 1)
})
test("cumulative rows span snapshots rather than restarting for the inverse", async () => {
const f = await fixture(), session = await f.create(f.options)
f.rows(500)
await session.readSnapshot("before"); await session.readSnapshot("after-forward"); await session.readSnapshot("after-forward")
await assert.rejects(session.readSnapshot("after-inverse"), (error: { code?: string }) => error.code === "LIMIT_EXCEEDED")
assert.equal(session.readBudget().rows, 10004); assert.equal(f.stats().transports, 1)
})
test("phase rounds reject a fourth sample, early inverse and backward reads without resetting their budget", async () => {
for (const scenario of ["forward-fourth", "inverse-early", "inverse-fourth", "backward"] as const) {
const f = await fixture(), session = await f.create(f.options)
await session.readSnapshot("before"); await session.readSnapshot("after-forward")
if (scenario !== "inverse-early") await session.readSnapshot("after-forward")
if (scenario === "forward-fourth") await session.readSnapshot("after-forward")
if (["inverse-fourth", "backward"].includes(scenario)) await session.readSnapshot("after-inverse")
if (scenario === "inverse-fourth") { await session.readSnapshot("after-inverse"); await session.readSnapshot("after-inverse") }
const before = f.stats().nativeCalls
await assert.rejects(session.readSnapshot(scenario === "inverse-early" || scenario === "inverse-fourth" ? "after-inverse" : "after-forward"))
assert.equal(f.stats().nativeCalls, before); assert.equal(f.stats().transports, 1)
}
})
test("an already aborted original signal performs no source SQL or native dispatch", async () => {
const f = await fixture(), controller = new AbortController(); controller.abort()
await assert.rejects(f.create({ ...f.options, context: { ...f.options.context, signal: controller.signal } }))
assert.equal(f.stats().sourceChecks, 0); assert.equal(f.stats().nativeCalls, 0)
})
test("invalid or reduced manifests fail before source SQL/native acquisition", async () => {
const f = await fixture()
for (const manifest of [{ servers: [1,1] }, { servers: [1], url: "https://arbitrary" }, { servers: [1], probes: [{ key: "x", serverId: 2 }] }]) await assert.rejects(f.create({ ...f.options, manifest }))
assert.equal(f.stats().sourceChecks, 0); assert.equal(f.stats().transports, 0)
await assert.rejects(f.create({ ...f.options, manifest: { servers: [2] } }))
assert.equal(f.stats().nativeCalls, 0)
})
test("probe commands use only original candidate owned addresses, disabled lookups and ordered VRF membership", async () => {
const f = await fixture()
const probe = { key: "a", serverId: 1, destination: "198.51.100.2", source: "192.0.2.1", interface: "wan", probeVrf: "probe" }
const session = await f.create({ ...f.options, manifest: { servers: [1], probes: [probe] } })
const snapshot = await session.readSnapshot("before"), probes = snapshot.probes as { request: typeof probe; expectedHopAddresses: unknown[] }[]
assert.equal(probes.length, 1); assert.equal(probes[0].expectedHopAddresses.length, 2)
const commands = f.requests.filter(request => ["/tool/ping", "/tool/traceroute"].includes(request.path))
assert.equal(commands.length, 2)
assert(commands.every(request => request.serverId === 1 && (request.body as { address: string })?.address === probe.destination && (request.body as { "src-address": string })["src-address"] === probe.source))
assert(f.requests.some(request => request.path === "/interface/get")); assert(f.requests.some(request => request.path === "/ip/address/get")); assert(f.requests.some(request => request.path === "/ip/vrf/get"))
assert((snapshot.budget as { calls: number }).calls > 8)
})
test("arbitrary candidate identities, foreign addresses and earlier conflicting VRF rows cannot dispatch probes", async () => {
const valid = { key: "a", serverId: 1, destination: "198.51.100.2", source: "192.0.2.1", interface: "wan", probeVrf: "probe" }
for (const change of ["key", "source", "destination", "interface", "vrf-order"] as const) {
const f = await fixture(), probe = { ...valid }
if (change === "key") probe.key = "foreign"
if (change === "source") probe.source = "203.0.113.1"
if (change === "destination") probe.destination = "203.0.113.2"
if (change === "interface") probe.interface = "foreign"
if (change === "vrf-order") f.wrongVrf()
if (["key", "interface"].includes(change)) await assert.rejects(f.create({ ...f.options, manifest: { servers: [1], probes: [probe] } }))
else { const session = await f.create({ ...f.options, manifest: { servers: [1], probes: [probe] } }); await assert.rejects(session.readSnapshot("before")) }
assert.equal(f.requests.filter(request => request.path.startsWith("/tool/")).length, 0)
}
})
test("explicit terminal zero of three sends only ping and preserves absent trace for independent parser validation", async () => {
const f = await fixture(); f.failProbe()
const session = await f.create({ ...f.options, manifest: { servers: [1], probes: [{ key: "a", serverId: 1, destination: "198.51.100.2", source: "192.0.2.1", interface: "wan", probeVrf: "probe" }] } })
const snapshot = await session.readSnapshot("before"), probes = snapshot.probes as Record<string, unknown>[]
assert.equal(f.requests.filter(request => request.path === "/tool/ping").length, 1)
assert.equal(f.requests.filter(request => request.path === "/tool/traceroute").length, 0)
assert(!Object.hasOwn(probes[0], "tracePayload")); assert.equal(snapshot.securityProof, false)
})
test("actual native transport keeps wire whitespace bytes across calls, captures limits and exposes no reset", async () => {
let requests = 0
const transport = { request: (_options: unknown, receive: (response: EventEmitter) => void) => {
requests++; const request = new EventEmitter() as EventEmitter & { end(): void; destroy(error?: Error): void }
request.destroy = error => { if (error) queueMicrotask(() => request.emit("error", error)); request.emit("close") }
request.end = () => queueMicrotask(() => {
const response = Object.assign(new EventEmitter(), { statusCode: 200, headers: {}, destroy() {} })
receive(response); response.emit("data", Buffer.from(" ".repeat(600000) + "[]")); response.emit("end"); request.emit("close")
}); return request
} }
const exports = await loadSource("./routing-community-context-native.ts", { "node:http": { default: transport }, "node:https": { default: transport }, "node:net": { isIP }, "./routing-network-native-destination.js": { captureRoutingNetworkDestinationPins: () => { throw Error("Unexpected pins") } }, "./security.js": { McpError: SessionError } })
const create = exports.routeContextClients as (endpoints: unknown[], signal: undefined, limits: { deadline: number; maxCalls: number; maxBytes: number }) => Map<number, { get(path: string): Promise<unknown> }> & { readBudget(): { bytes: number; maxCalls: number; deadline: number } }
const limits = { deadline: Date.now() + 119000, maxCalls: 2, maxBytes: 1000000 }
const clients = create([{ id: 1, host: "inert", username: "u", password: "p" }], undefined, limits), deadline = limits.deadline
limits.deadline += 500000; limits.maxCalls = 256; limits.maxBytes = 8000000
const first = await clients.get(1)!.get("/routing/route"); assert(Array.isArray(first) && first.length === 0)
await assert.rejects(clients.get(1)!.get("/routing/route"), (error: { code?: string }) => error.code === "LIMIT_EXCEEDED")
assert.equal(clients.readBudget().bytes, 1200004); assert.equal(clients.readBudget().deadline, deadline); assert.equal(clients.readBudget().maxCalls, 2)
await assert.rejects(clients.get(1)!.get("/routing/route")); assert.equal(requests, 2)
assert(!("reset" in clients)); assert(Object.isFrozen(clients.readBudget()))
})
type Pin = { serverId: number; host: string; address: string; family: number }
async function destinationFixture(lookup: (host: string) => Promise<{ address: string; family: number }[]>, globals: Record<string, unknown> = {}) {
// Loading the actual shared policy proves its dependency graph is pure:
// any attempt to import configured DB/actions/services fails this provider.
const policy = await loadSource("./server-connection-destination-policy.ts", { "node:net": { isIP }, zod: { z } })
const exports = await loadSource("./routing-network-native-destination.ts", {
"node:dns/promises": { lookup }, "node:net": { isIP }, "./server-connection-destination-policy.js": policy, "./security.js": { McpError: SessionError },
}, globals)
return {
resolve: exports.resolveRoutingNetworkDestinationPins as (endpoints: { id: number; host: string }[], options: { deadline: number; signal: AbortSignal; authorize(): Promise<void> }) => Promise<Pin[]>,
capture: exports.captureRoutingNetworkDestinationPins as (endpoints: { id: number; host: string }[], pins: Pin[]) => Map<number, Pin>,
}
}
test("DNS resolves once per captured authenticated source, rejects mixed unsafe answers and never falls back", async () => {
const names: string[] = [], endpoints = [{ id: 1, host: "router.example" }]
const f = await destinationFixture(async host => { names.push(host); return [{ address: "192.168.88.1", family: 4 }, { address: "10.0.0.1", family: 4 }] })
let checks = 0
const pins = await f.resolve(endpoints, { deadline: Date.now() + 10000, signal: new AbortController().signal, authorize: async () => { if (++checks === 1) endpoints[0].host = "changed.example" } })
assert.equal(names.join(","), "router.example"); assert.equal(pins[0].host, "router.example"); assert.equal(pins[0].address, "10.0.0.1"); assert(Object.isFrozen(pins[0])); assert(checks >= 3)
for (const address of ["169.254.169.254", "224.0.0.1", "168.63.129.16", "100.100.100.200", "fe80::1", "ff02::1", "::ffff:a9fe:a9fe", "fd00:ec2::254"]) {
const denied = await destinationFixture(async () => [{ address: "127.0.0.1", family: 4 }, { address, family: isIP(address) }])
await assert.rejects(denied.resolve([{ id: 1, host: "router.example" }], { deadline: Date.now() + 10000, signal: new AbortController().signal, authorize: async () => {} }), (error: { code?: string }) => error.code === "DESTINATION_DENIED")
}
})
test("timed out uncancellable DNS lookups retain capacity until their real settlement", async () => {
const pending: ((rows: { address: string; family: number }[]) => void)[] = []
const f = await destinationFixture(() => new Promise(resolve => pending.push(resolve)), {
setTimeout: (work: () => void) => { queueMicrotask(work); return 1 }, clearTimeout: () => {},
})
const options = { deadline: Date.now() + 10000, signal: new AbortController().signal, authorize: async () => {} }
for (let index = 0; index < 16; index++) await assert.rejects(f.resolve([{ id: index + 1, host: "router.example" }], options))
assert.equal(pending.length, 16)
await assert.rejects(f.resolve([{ id: 17, host: "router.example" }], options), (error: { code?: string }) => error.code === "LIMIT_EXCEEDED")
assert.equal(pending.length, 16)
pending[0]([{ address: "127.0.0.1", family: 4 }]); await Promise.resolve(); await Promise.resolve()
await assert.rejects(f.resolve([{ id: 18, host: "router.example" }], options)); assert.equal(pending.length, 17)
for (const resolve of pending.slice(1)) resolve([{ address: "127.0.0.1", family: 4 }])
})
test("pin capture refuses reduced/foreign/unsafe sets and caller lookup injection", async () => {
const f = await destinationFixture(async () => { throw Error("DNS must not run") }), endpoint = { id: 1, host: "router.example" }
const pin = { serverId: 1, host: "router.example", address: "127.0.0.1", family: 4 }
for (const pins of [[], [pin,pin], [{ ...pin, serverId: 2 }], [{ ...pin, host: "foreign.example" }], [{ ...pin, address: "169.254.169.254" }], [{ ...pin, address: "router.example" }], [{ ...pin, lookup: () => {} }]]) assert.throws(() => f.capture([endpoint], pins))
const captured = f.capture([endpoint], [pin]); pin.address = "203.0.113.1"
assert.equal(captured.get(1)!.address, "127.0.0.1"); assert(Object.isFrozen(captured.get(1)))
assert.throws(() => f.capture([{ id: 1, host: "127.0.0.1" }], [{ ...pin, host: "127.0.0.1", address: "10.0.0.1" }]))
})
test("pinned transport connects only the chosen literal and preserves original HTTP Host, TLS SNI and verification", async () => {
const destination = await destinationFixture(async () => { throw Error("No transport DNS lookup") }), requests: Record<string, unknown>[] = []
const transport = { request: (options: Record<string, unknown>, receive: (response: EventEmitter) => void) => {
requests.push(options)
const request = Object.assign(new EventEmitter(), { end() { queueMicrotask(() => { const response = Object.assign(new EventEmitter(), { statusCode: 200, headers: {}, destroy() {} }); receive(response); response.emit("data", Buffer.from("[]")); response.emit("end"); request.emit("close") }) }, destroy() {} })
return request
} }
const exports = await loadSource("./routing-community-context-native.ts", {
"node:http": { default: transport }, "node:https": { default: transport }, "node:net": { isIP },
"./routing-network-native-destination.js": { captureRoutingNetworkDestinationPins: destination.capture }, "./security.js": { McpError: SessionError },
})
const create = exports.routeContextClients as (endpoints: Record<string, unknown>[], signal: undefined, limits: Record<string, unknown>) => Map<number, { get(path: string): Promise<unknown> }>
const endpoint = { id: 1, host: "router.example", port: 8443, useSsl: true, verifySsl: true, username: "u", password: "p" }
const pin = { serverId: 1, host: "router.example", address: "127.0.0.1", family: 4 }
const clients = create([endpoint], undefined, { deadline: Date.now() + 10000, maxCalls: 2, maxBytes: 10000, pins: [pin] })
endpoint.host = "changed.example"; endpoint.verifySsl = false; pin.address = "203.0.113.1"
await clients.get(1)!.get("/routing/route"); await clients.get(1)!.get("/routing/bgp/session")
assert.equal(requests.length, 2)
for (const request of requests) {
assert.equal(request.hostname, "127.0.0.1"); assert.equal(request.servername, "router.example"); assert.equal(request.rejectUnauthorized, true)
assert.equal((request.headers as { Host: string }).Host, "router.example:8443"); assert(!("lookup" in request))
}
const ip = create([{ ...endpoint, host: "::1", port: 8443, verifySsl: true }], undefined, { deadline: Date.now() + 10000, maxCalls: 1, maxBytes: 10000, pins: [{ serverId: 1, host: "::1", address: "::1", family: 6 }] })
await ip.get(1)!.get("/routing/route")
assert.equal((requests[2].headers as { Host: string }).Host, "[::1]:8443"); assert.equal(requests[2].servername, undefined); assert.equal(requests[2].rejectUnauthorized, true)
})
test("DNS cancellation retains uncancellable lookup capacity and a late answer cannot bypass revoked authority", async () => {
const pending: ((rows: { address: string; family: number }[]) => void)[] = []
const f = await destinationFixture(() => new Promise(resolve => pending.push(resolve)))
for (let index = 0; index < 16; index++) {
const controller = new AbortController()
const rejected = assert.rejects(f.resolve([{ id: index + 1, host: "router.example" }], { deadline: Date.now() + 10000, signal: controller.signal, authorize: async () => {} }))
for (let tick = 0; pending.length <= index && tick < 30; tick++) await Promise.resolve()
assert.equal(pending.length, index + 1); controller.abort(); await rejected
}
await assert.rejects(f.resolve([{ id: 17, host: "router.example" }], { deadline: Date.now() + 10000, signal: new AbortController().signal, authorize: async () => {} }), (error: { code?: string }) => error.code === "LIMIT_EXCEEDED")
for (const resolve of pending) resolve([{ address: "127.0.0.1", family: 4 }])
let checks = 0, lookups = 0
const revoked = await destinationFixture(async () => { lookups++; return [{ address: "127.0.0.1", family: 4 }] })
await assert.rejects(revoked.resolve([{ id: 1, host: "router.example" }], { deadline: Date.now() + 10000, signal: new AbortController().signal,
authorize: async () => { if (++checks > 1) throw new SessionError("RESET_REQUIRED", "revoked during DNS") } }), (error: { code?: string }) => error.code === "RESET_REQUIRED")
assert.equal(lookups, 1)
})
test("complete authority fences bound repeated runtime authorization while preserving every native boundary", async () => {
const f = await fixture(), session = await f.create(f.options)
const before = f.stats()
await session.readSnapshot("before")
const after = f.stats(), native = after.nativeCalls - before.nativeCalls, callbacks = after.callbacks - before.callbacks
assert.equal(native, 6)
// Two full fences and the direct dispatch guard stay fresh for every call.
// SQL/file leaves inside those fences must not recursively multiply them.
assert(callbacks >= native * 4)
assert(callbacks <= 50, "Six native reads must fit a bounded number of complete runtime revalidations")
f.afterNative(f.revoke)
await assert.rejects(session.readSnapshot("after-forward"))
assert.equal(f.stats().nativeCalls, after.nativeCalls + 1)
await assert.rejects(session.readSnapshot("after-forward"))
assert.equal(f.stats().nativeCalls, after.nativeCalls + 1)
})