fix(mcp): довести базовые сценарии и проверку маршрутизации

This commit is contained in:
Codex committed 2026-11-11 20:28:37 +07:00
1 parent 1f0704add0
commit 04225886e0
101 files changed
+6118 -329

No files matched your search

@@ -0,0 +1,73 @@
/** External SDK consumer. No application/store/runtime/database imports. */
import assert from 'node:assert/strict'
import { randomUUID } from 'node:crypto'
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client'
const endpoint = new URL(process.env.OWN_MCP_ENDPOINT)
assert.equal(process.env.OWN_EXTERNAL_CLIENT, 'true')
assert.equal(endpoint.hostname, '127.0.0.1')
assert.notEqual(process.pid, Number(process.env.OWN_SERVER_PID))
const client = new Client({ name: 'owned-linked-bridge-vlan-sdk', version: '1.0.0' })
const boundedFetch = async (input, init) => {
const url = new URL(typeof input === 'string' || input instanceof URL ? input : input.url)
assert.equal(url.origin, endpoint.origin)
return fetch(input, { ...init, redirect: 'manual', signal: AbortSignal.timeout(10000) })
}
const payload = result => {
const text = result.content.find(item => item.type === 'text')?.text
assert(text && Buffer.byteLength(text) < 131072)
return JSON.parse(text)
}
const call = async (name, args) => {
const result = await client.callTool({ name, arguments: args }, undefined, { timeout: 10000 })
assert(!result.isError, JSON.stringify(payload(result)))
return payload(result)
}
try {
await client.connect(new StreamableHTTPClientTransport(endpoint, {
requestInit: { headers: { authorization: 'Bearer ' + process.env.OWN_MCP_TOKEN } }, fetch: boundedFetch,
}), { timeout: 10000 })
const tools = (await client.listTools({}, { timeout: 10000 })).tools
const read = tools.find(tool => tool.name === 'mm_bridge_vlan_configuration_get')
const configure = tools.find(tool => tool.name === 'mm_bridge_vlan_configuration_plan')
assert(read && configure)
assert.match(read.description, /Полная конфигурация bridge VLAN/)
assert.match(read.description, /Возвращает данные только из разрешённой области/)
assert.match(configure.description, /Связанный план VLAN membership, PVID и bridge filtering/)
assert.match(configure.description, /Подготавливает неизменяемый план/)
assert.equal(read.annotations.readOnlyHint, true)
assert.equal(configure.annotations.readOnlyHint, false)
assert.deepEqual(read.inputSchema.required, ['serverId'])
assert.deepEqual(configure.inputSchema.required, ['serverId', 'bridgeId', 'desired'])
const desiredSchema = configure.inputSchema.properties.desired
for (const name of ['ports', 'vlans', 'removePortIds', 'removeVlanIds']) assert(desiredSchema.properties[name])
const serverId = Number(process.env.OWN_ALLOWED_SERVER)
const state = (await call(read.name, { serverId })).state
assert.equal(state.bridges[0]['.id'], '*1')
assert(state.interfaces.some(item => item.resource === 'ethernet' && item.id === '*3' && item.name === 'ether3'))
assert.equal(state.vlans[0]['vlan-ids'], '10')
const cpu = { resource: 'bridge', id: '*1' }, access = { resource: 'ethernet', id: '*2' }, trunk = { resource: 'ethernet', id: '*3' }
const plan = await call(configure.name, { serverId, bridgeId: '*1', desired: {
filtering: true, pvid: 1,
ports: [{ id: '*10', interface: access, pvid: 10, ingressFiltering: true, frameTypes: 'admit-all', disabled: false },
{ interface: trunk, pvid: 1, ingressFiltering: true, frameTypes: 'admit-only-vlan-tagged', disabled: false }],
vlans: [{ id: '*11', vlanIds: '10', tagged: [cpu], untagged: [access], disabled: false },
{ vlanIds: '20', tagged: [cpu, trunk], untagged: [], disabled: false }], removePortIds: [], removeVlanIds: [],
} })
assert.equal(plan.state, 'awaiting-approval')
assert.equal(typeof plan.planId, 'string')
assert.equal(plan.changes.requiresHuman, true)
assert.deepEqual(plan.changes.steps.map(item => [item.step.resource, item.step.action]),
[['bridge_vlan', 'create'], ['bridge_port', 'create'], ['bridge', 'update']])
const denied = await client.callTool({ name: 'mm_change_apply', arguments: { planId: plan.planId, idempotencyKey: randomUUID() } }, undefined, { timeout: 10000 })
assert.equal(denied.isError, true)
const deniedPayload = payload(denied)
assert(JSON.stringify(deniedPayload).includes('APPROVAL_REQUIRED'))
const readback = (await call(read.name, { serverId })).state
assert.deepEqual(readback, state)
process.send({ kind: 'result', result: { externalSdkProcess: true, transport: 'streamable-http', clientPid: process.pid,
listedTools: [read, configure], state, plan, applyDenial: deniedPayload, unchangedReadback: true } })
} finally {
await client.close()
process.disconnect?.()
}
@@ -0,0 +1,84 @@
import assert from 'node:assert/strict'
import { spawn } from 'node:child_process'
import { createServer } from 'node:http'
import { writeFile } from 'node:fs/promises'
import { fileURLToPath, pathToFileURL } from 'node:url'
import { isAbsolute, resolve } from 'node:path'
assert.equal(process.env.OWN_EXTERNAL_PROCESS_PG, 'true')
assert.equal(process.env.NODE_ENV, 'test')
assert(isAbsolute(process.env.OWN_EXTERNAL_SOURCE_ROOT!))
assert(isAbsolute(process.env.OWN_EXTERNAL_RESULT_FILE!))
const database = new URL(process.env.DATABASE_URL!)
assert.equal(database.hostname, '127.0.0.1'); assert.equal(database.username, 'mcp_test')
assert.equal(database.pathname, '/postgres'); assert.notEqual(database.port, '5432')
const source = (path: string) => pathToFileURL(resolve(process.env.OWN_EXTERNAL_SOURCE_ROOT!, 'backend/src', path)).href
const rows: Record<string, Record<string, string>[]> = {
'/interface/ethernet': [{ '.id': '*2', name: 'ether2', disabled: 'false' }, { '.id': '*3', name: 'ether3', disabled: 'false' }, { '.id': '*4', name: 'ether-mgmt', disabled: 'false' }],
'/interface/bridge': [{ '.id': '*1', name: 'br-users', pvid: '1', 'vlan-filtering': 'false', 'frame-types': 'admit-all', 'ingress-filtering': 'true', mvrp: 'false', disabled: 'false' }],
'/interface/bridge/port': [{ '.id': '*10', bridge: 'br-users', interface: 'ether2', pvid: '10', 'ingress-filtering': 'true', 'frame-types': 'admit-all', disabled: 'false' }],
'/interface/bridge/vlan': [{ '.id': '*11', bridge: 'br-users', 'vlan-ids': '10', tagged: 'br-users', untagged: 'ether2', disabled: 'false', dynamic: 'false' }],
'/interface/vlan': [], '/interface/gre': [], '/interface/wireguard': [], '/interface/vxlan': [],
'/ip/address': [{ '.id': '*20', interface: 'ether-mgmt', address: '127.0.0.1/8', disabled: 'false', dynamic: 'false' }], '/ipv6/address': [],
}
const requests: string[] = []
let writeAttempts = 0
const router = createServer((req, res) => {
res.setHeader('content-type', 'application/json')
const path = decodeURIComponent(new URL(req.url!, 'http://127.0.0.1').pathname.replace(/^\/rest/, ''))
requests.push(req.method + ' ' + path)
if (req.method !== 'GET') { writeAttempts++; res.writeHead(405); res.end('{}'); return }
if (req.headers.authorization !== 'Basic ' + Buffer.from('fixture:fixture-only').toString('base64')) { res.writeHead(401); res.end('{}'); return }
if (!Object.hasOwn(rows, path)) { res.writeHead(404); res.end('{}'); return }
res.end(JSON.stringify(rows[path]))
})
await new Promise<void>(done => router.listen(0, '127.0.0.1', done))
const { pool, closePool } = await import(source('db/index.js'))
const { applySqlMigrations } = await import(source('db/migrate.js'))
const { mcpConnectionCreateSchema } = await import('@mmapp/contracts/mcp')
const { createMcpConnection, updateMcpSettings } = await import(source('modules/mcp/store.js'))
const { buildApp } = await import(source('index.js'))
const actor = { id: 'owned-bridge-vlan-sdk-owner', email: '[email protected]', name: 'Owned bridge VLAN SDK owner', apps: ['mm'], permissions: ['mm:settings:admin', 'mm:mcp:admin', 'mm:network:admin', 'mm:servers:admin'], expiresAt: Date.now() + 3600000, issuedAt: Date.now() - 1000 }
let app: Awaited<ReturnType<typeof buildApp>> | undefined
let child: ReturnType<typeof spawn> | undefined
let childExit: Promise<number> | undefined
try {
await applySqlMigrations(pool)
const serverId = (await pool.query("INSERT INTO servers(name,host,port,use_ssl,enabled,username,password) VALUES('owned bridge VLAN SDK','127.0.0.1',$1,false,true,'fixture','fixture-only') RETURNING id", [(router.address() as { port: number }).port])).rows[0].id
await updateMcpSettings({ enabled: true }, actor)
app = await buildApp({ startScheduler: false, logger: false })
await app.listen({ host: '127.0.0.1', port: 0 })
const endpoint = `http://127.0.0.1:${(app.server.address() as { port: number }).port}/mcp`
const issued = await createMcpConnection(mcpConnectionCreateSchema.parse({ name: 'Owned bridge VLAN external SDK', mode: 'autonomous',
expiresAt: new Date(Date.now() + 1200000).toISOString(), permissions: ['mm:network:write'],
scope: { serverIds: [serverId], operationIds: ['network.bridge-vlan.read', 'network.bridge-vlan.configure', 'changes.apply'], allowGlobal: false },
limits: { callsPerMinute: 120, mutationsPerHour: 100 } }), actor)
let result: unknown, stdout = '', stderr = ''
child = spawn(process.execPath, [fileURLToPath(new URL('./bridge-vlan-client.mjs', import.meta.url))], { cwd: process.cwd(), windowsHide: true,
stdio: ['ignore', 'pipe', 'pipe', 'ipc'], env: { ...Object.fromEntries(['SystemRoot', 'WINDIR', 'TEMP', 'TMP', 'PATH', 'Path'].filter(k => process.env[k]).map(k => [k, process.env[k]!])),
OWN_EXTERNAL_CLIENT: 'true', OWN_MCP_ENDPOINT: endpoint, OWN_MCP_TOKEN: issued.token, OWN_SERVER_PID: String(process.pid), OWN_ALLOWED_SERVER: String(serverId) } })
child.on('message', (message: { kind: string; result?: unknown }) => { if (message.kind === 'result') result = message.result })
child.stdout?.on('data', chunk => { stdout += String(chunk); if (stdout.length > 1048576) child?.kill() })
child.stderr?.on('data', chunk => { stderr += String(chunk); if (stderr.length > 1048576) child?.kill() })
childExit = new Promise<number>((done, reject) => { child!.once('exit', code => done(code ?? 1)); child!.once('error', reject) })
const timeout = setTimeout(() => child?.kill(), 60000)
const code = await childExit; clearTimeout(timeout)
assert.equal(code, 0, stderr.slice(0, 3000)); assert(result)
assert.equal(writeAttempts, 0)
assert.equal((await pool.query('SELECT count(*)::int AS count FROM mcp_operations')).rows[0].count, 0)
const plans = (await pool.query('SELECT operation_id,state,approved_by FROM mcp_plans')).rows
assert.equal(plans.length, 1); assert.equal(plans[0].operation_id, 'network.bridge-vlan.configure')
assert.equal(plans[0].state, 'awaiting-approval'); assert.equal(plans[0].approved_by, null)
const audit = (await pool.query('SELECT tool,status,error_code FROM mcp_requests ORDER BY created_at')).rows
assert(audit.some(row => row.error_code === 'APPROVAL_REQUIRED'))
const serialized = JSON.stringify({ result, stdout, stderr, audit })
assert(!serialized.includes(issued.token)); assert(!serialized.includes('fixture-only'))
const final = { ...(result as object), actualOwnPg: true, actualProductionHttpServer: true, serverFixturePid: process.pid,
connectionMode: 'autonomous', plans, audit, nativeReadRequests: requests, nativeWriteAttempts: writeAttempts,
appliedOperations: 0, syntheticRouterOnly: true, productionDatabaseTouched: false, portalContacted: false }
await writeFile(process.env.OWN_EXTERNAL_RESULT_FILE!, JSON.stringify(final, null, 2))
console.log('Owned bridge VLAN SDK passed:', JSON.stringify({ listedTools: 2, planState: plans[0].state, nativeReadRequests: requests.length, nativeWriteAttempts: writeAttempts }))
} finally {
if (child && child.exitCode === null && child.signalCode === null) { child.kill(); await childExit }
try { await app?.close() } finally { try { await closePool() } finally { router.closeIdleConnections(); await new Promise<void>((done, reject) => router.close(error => error ? reject(error) : done())) } }
}
@@ -6,10 +6,14 @@ import { randomBytes, createHash } from 'node:crypto'
import { createServer } from 'node:net'
import { spawn } from 'node:child_process'
const sourceRoot = resolve(process.argv[2] ?? fileURLToPath(new URL('../../../', import.meta.url)))
const output = resolve(sourceRoot, 'tmp/mcp-external-process-acceptance'); await mkdir(output, { recursive: true })
const scenario = process.argv[3] ?? 'acceptance'
if (!['acceptance', 'bridge-vlan'].includes(scenario)) throw Error('Unsupported owned external scenario')
const output = resolve(sourceRoot, scenario === 'bridge-vlan' ? 'tmp/mcp-bridge-vlan-sdk-20261105' : 'tmp/mcp-external-process-acceptance'); await mkdir(output, { recursive: true })
const paths = ['backend/src/scripts/mcp-stdio.ts', 'backend/src/routes/mcp-transport.ts', 'backend/src/routes/mcp-oauth.ts', 'backend/src/modules/mcp/store.ts',
'backend/src/modules/mcp/runtime.ts', 'backend/src/modules/mcp/actions.ts', 'backend/src/modules/mcp/security.ts', 'backend/src/modules/mcp/protocol-limits.ts',
'backend/src/modules/mcp/portal-revocation.ts', 'backend/src/plugins/auth.ts', 'backend/src/index.ts', 'node_modules/@modelcontextprotocol/client/package.json', 'node_modules/@modelcontextprotocol/server/package.json']
if (scenario === 'bridge-vlan') paths.push('backend/scripts/mcp-external-process/bridge-vlan-client.mjs', 'backend/scripts/mcp-external-process/bridge-vlan-fixture.ts',
'backend/src/modules/mcp/bridge-vlan-actions.ts', 'backend/src/services/bridge-vlan-configuration.ts', 'packages/contracts/src/bridge-vlan.ts')
async function pins() { const result = []; for (const path of paths) result.push({ path, sha256: createHash('sha256').update(await readFile(resolve(sourceRoot, path))).digest('hex') }); return result }
const before = await pins(), directory = await mkdtemp(join(resolve(sourceRoot, 'tmp'), 'mm-mcp-external-')), state = join(directory, 'state'); await mkdir(state)
const listener = createServer(); await new Promise(resolve => listener.listen(0, '127.0.0.1', resolve)); const port = listener.address().port; await new Promise(resolve => listener.close(resolve))
@@ -19,7 +23,7 @@ const postgres = new EmbeddedPostgres({ databaseDir: join(directory, 'pg'), port
try {
await postgres.initialise(); await postgres.start()
process.exitCode = await new Promise((done, reject) => {
const child = spawn(process.execPath, ['--import', import.meta.resolve('tsx'), fileURLToPath(new URL('./server-fixture.ts', import.meta.url))], { cwd: directory,
const child = spawn(process.execPath, ['--import', import.meta.resolve('tsx'), fileURLToPath(new URL(scenario === 'bridge-vlan' ? './bridge-vlan-fixture.ts' : './server-fixture.ts', import.meta.url))], { cwd: directory,
windowsHide: true, stdio: 'inherit', env: { ...Object.fromEntries(['SystemRoot', 'WINDIR', 'TEMP', 'TMP', 'PATH', 'Path'].filter(k => process.env[k]).map(k => [k, process.env[k]])),
OWN_EXTERNAL_CLEANUP_FAULT: process.env.OWN_EXTERNAL_CLEANUP_FAULT, OWN_EXTERNAL_SOURCE_ROOT: sourceRoot, OWN_EXTERNAL_RESULT_FILE: join(output, 'result.json'), NODE_ENV: 'test', OWN_EXTERNAL_PROCESS_PG: 'true', DATABASE_URL: `postgresql://mcp_test:${password}@127.0.0.1:${port}/postgres`, DATABASE_PATH: join(directory, 'no-legacy.sqlite'),
MCP_STATE_DIR: state, AUTH_REQUIRED: 'true', AUTH_JWT_SECRET: 'owned-external-synthetic-issuer-test-only', AUTH_ISSUER: 'https://synthetic-portal.invalid', AUTH_PORTAL_URL: 'https://synthetic-portal.invalid' } })
@@ -1,4 +1,5 @@
import assert from "node:assert/strict"
import { createHash } from "node:crypto"
import { spawn } from "node:child_process"
import { createServer } from "node:net"
import { fileURLToPath, pathToFileURL } from "node:url"
@@ -49,6 +50,61 @@ try {
await updateMcpSettings({ enabled: true }, actor)
app = await buildApp({ startScheduler: false, logger: false }); await app.listen({ port, host: "127.0.0.1" })
const jwt = await new SignJWT({ sub: actor.id, apps: actor.apps, permissions: actor.permissions }).setProtectedHeader({ alg: "HS256" }).setIssuer(env.authIssuer).setIssuedAt().setExpirationTime("1h").sign(new TextEncoder().encode(env.jwtSecret))
const portalHeaders = { authorization: `Bearer ${jwt}`, "content-type": "application/json" }
assert.equal((await pool.query("SELECT count(*)::int AS count FROM mcp_connections WHERE owner_id=$1", [actor.id])).rows[0].count, 0)
const callback = "http://localhost:45678/callback?registered=1"
const registration = await fetch(origin + "/api/mcp/oauth/clients", { method: "POST", headers: portalHeaders,
body: JSON.stringify({ name: "Owned denial fixture", redirectUris: [callback] }) })
assert.equal(registration.status, 200)
const { clientId } = await registration.json() as { clientId: string }
const consent = (payload: Record<string, unknown>, headers = portalHeaders) => fetch(origin + "/api/mcp/oauth/consent", { method: "POST", headers, body: JSON.stringify(payload) })
const authorize = async (state: string) => {
const parameters = new URLSearchParams({ client_id: clientId, redirect_uri: callback, response_type: "code", resource: endpoint,
code_challenge_method: "S256", code_challenge: createHash("sha256").update("v".repeat(64)).digest("base64url"), state })
const response = await fetch(`${origin}/oauth/authorize?${parameters}`, { redirect: "manual" })
assert.equal(response.status, 302)
const requestId = new URL(response.headers.get("location")!).searchParams.get("oauthRequest")
assert.ok(requestId)
return requestId
}
const requestId = await authorize("deny-without-connection")
assert.equal((await consent({ requestId, approve: false }, { ...portalHeaders, authorization: "" })).status, 401)
assert.equal((await consent({ requestId, approve: true })).status, 400)
const refusals = await Promise.all([consent({ requestId, approve: false }), consent({ requestId, approve: false })])
assert.deepEqual(refusals.map(response => response.status).sort(), [200, 404])
const { redirectUrl } = await refusals.find(response => response.status === 200)!.json() as { redirectUrl: string }
const redirect = new URL(redirectUrl)
const expected = new URL(callback)
expected.searchParams.set("state", "deny-without-connection")
expected.searchParams.set("iss", origin)
expected.searchParams.set("error", "access_denied")
assert.equal(redirect.href, expected.href)
const otherOwner = { ...actor, id: "owned-external-process-other-owner" }
const unrelated = await createMcpConnection(mcpConnectionCreateSchema.parse({ name: "Unrelated paused connection", mode: "observer",
expiresAt: new Date(Date.now() + 600000).toISOString(), permissions: ["mm:servers:read"],
scope: { serverIds: [Number(allowed)], operationIds: ["servers.list"], allowGlobal: false } }), otherOwner)
await setConnectionStatus(unrelated.connection.id, "paused", otherOwner)
const legacyRequestId = await authorize("legacy-denial")
const legacy = await consent({ requestId: legacyRequestId, connectionId: unrelated.connection.id, approve: false })
assert.equal(legacy.status, 200)
assert.equal((await consent({ requestId: legacyRequestId, connectionId: unrelated.connection.id, approve: false })).status, 404)
const expired = await createMcpConnection(mcpConnectionCreateSchema.parse({ name: "Expired connection", mode: "observer",
expiresAt: new Date(Date.now() + 600000).toISOString(), permissions: ["mm:servers:read"],
scope: { serverIds: [Number(allowed)], operationIds: ["servers.list"], allowGlobal: false } }), actor)
await pool.query("UPDATE mcp_connections SET policy=jsonb_set(policy,'{expiresAt}',to_jsonb($2::text)) WHERE id=$1", [expired.connection.id, "2000-01-01T00:00:00Z"])
const expiredRequestId = await authorize("expired-approval")
assert.equal((await consent({ requestId: expiredRequestId, connectionId: expired.connection.id, approve: true })).status, 403)
const expiredRequest = (await pool.query("SELECT consumed_at,code_digest,connection_id FROM mcp_oauth_requests WHERE id=$1", [expiredRequestId])).rows[0]
assert.deepEqual(expiredRequest, { consumed_at: null, code_digest: null, connection_id: null })
assert.equal((await consent({ requestId: expiredRequestId, approve: false })).status, 200)
const deniedRows = (await pool.query("SELECT consumed_at,code_digest,connection_id FROM mcp_oauth_requests WHERE client_id=$1", [clientId])).rows
assert.equal(deniedRows.length, 3)
assert(deniedRows.every(row => row.consumed_at instanceof Date && row.code_digest === null && row.connection_id === null))
assert.equal((await pool.query("SELECT count(*)::int AS count FROM mcp_credentials WHERE client_id=$1", [clientId])).rows[0].count, 0)
const denialAudit = (await pool.query("SELECT actor_id,connection_id,payload FROM mcp_audit WHERE action='oauth.consent' AND payload->>'clientId'=$1", [clientId])).rows
assert.equal(denialAudit.length, 3)
assert(denialAudit.every(row => row.actor_id === actor.id && row.connection_id === null && row.payload.approved === false))
console.log("OAuth consent: expired approval refused before code issuance, denial uses exact redirect and one-use request without credentials")
const transcript: unknown[] = []; let failure: unknown, result: unknown
child = spawn(process.execPath, [fileURLToPath(new URL("./client.mjs", import.meta.url))], { cwd: process.cwd(), windowsHide: true, stdio: ["ignore", "pipe", "pipe", "ipc"],
env: { ...Object.fromEntries(["SystemRoot", "WINDIR", "TEMP", "TMP", "PATH", "Path"].filter(k => process.env[k]).map(k => [k, process.env[k]!])),
@@ -90,7 +146,8 @@ try {
const logs = JSON.stringify((await pool.query("SELECT tool,input,result,error_code FROM mcp_requests ORDER BY created_at")).rows)
for (const token of [...credentials, jwt, secret]) { assert(!logs.includes(token)); assert(!stdout.includes(token)); assert(!stderr.includes(token)) }
const final = { ...(result as object), actualOwnPg: true, actualProductionHttpServer: true, serverFixturePid: process.pid,
controlTransitions: transcript, auditCredentialLeakAbsent: true, nativeRouterCalls: 0, productionDatabaseTouched: false }
controlTransitions: transcript, auditCredentialLeakAbsent: true, denialWithoutConnection: true,
legacyDenialIgnoresPausedForeignConnection: true, nativeRouterCalls: 0, productionDatabaseTouched: false }
await writeFile(process.env.OWN_EXTERNAL_RESULT_FILE!, JSON.stringify(final, null, 2))
console.log("Owned external process SDK result:", JSON.stringify(final))
} finally {
+13 -7
View File
@@ -38,6 +38,7 @@ export function projectVrfDiagnostics(log, privateValues = [], expectedSlice = n
if (Array.isArray(value.accepted)) { row.finalCaseCount = value.accepted.length; if (expectedSlice !== null && value.slice === expectedSlice) finalComponentPresent = true }
if (['planned','queued','running','applied','failed','cancelled','unknown','expired','rejected','unconfirmed'].includes(value.operationState)) row.operationState = value.operationState
for (const key of ['phase', 'elapsedMs', 'nativeReads', 'nativeWrites', 'roundTrips', 'lastSqlMs', 'totalSqlMs', 'maxSqlMs']) if (Number.isSafeInteger(value[key]) && value[key] >= 0) row[key] = value[key]
if (Number.isSafeInteger(value.wireguardPeerTelemetryTicks) && value.wireguardPeerTelemetryTicks > 0 && value.wireguardPeerTelemetryTicks <= 10000) row.wireguardPeerTelemetryTicks = value.wireguardPeerTelemetryTicks
if (value.diagnosticWaitSql === true) row.diagnosticWaitSql = true
if (value.diagnosticError === true) { row.diagnosticError = true; row.safeName = diagnosticNames.has(value.safeName) ? value.safeName : 'other'; row.safeCode = diagnosticCodes.has(value.safeCode) ? value.safeCode : 'other' }
if (!Object.keys(row).length) { omittedLines++; continue }
@@ -47,10 +48,10 @@ export function projectVrfDiagnostics(log, privateValues = [], expectedSlice = n
}
export function vrfSliceDiagnostic(result, log, childBudgetMs, privateValues = []) {
assert(result && typeof result === 'object')
assert(['baseline','physical','vlan','disabled','mixed','reconcile','sql-journal','guards','coexistence','alias'].includes(result.slice))
assert(['baseline','physical','vlan','disabled','mixed','reconcile','sql-journal','guards','coexistence','alias','gre'].includes(result.slice))
assert(Number.isSafeInteger(result.code) && typeof result.childExitConfirmed === 'boolean')
assert(Number.isSafeInteger(result.caseCount) && result.caseCount >= 0)
assert.equal(childBudgetMs, result.slice === 'baseline' ? 240000 : 120000)
assert.equal(childBudgetMs, result.slice === 'baseline' ? 240000 : result.slice === 'disabled' ? 180000 : 120000)
assert(result.failure === null || ['child-deadline','child-log-limit','child-signal','child-error','child-error-after-pid','child-exit-unconfirmed','missing-component-receipt'].includes(result.failure))
assert(result.accepted === (result.code === 0 && result.failure === null && result.childExitConfirmed))
return { ...result, capMs: childBudgetMs, diagnostics: projectVrfDiagnostics(log, privateValues, result.slice), scope: 'same-owned-PG-test-only', actualRouter: false, forwardingVerified: false }
@@ -88,10 +89,14 @@ export async function runOwnedVrfProductionProfile({ directory, database, databa
const report = fileURLToPath(new URL('../../docs/mcp-chr-vrf-companion-native-v5.json', import.meta.url))
const loader = pathToFileURL(createRequire(import.meta.url).resolve('tsx')).href
const safe = Object.fromEntries(['SystemRoot', 'WINDIR', 'TEMP', 'TMP', 'LANG', 'LC_ALL'].filter(key => typeof process.env[key] === 'string').map(key => [key, process.env[key]]))
for (const slice of ['baseline', 'physical', 'vlan', 'disabled', 'mixed', 'reconcile', 'sql-journal', 'guards', 'coexistence', 'alias']) {
// Diagnose the disabled lifecycle first, then the synthetic GRE extension.
// Every original case remains required by the same full74 gate and caps.
for (const slice of ['disabled', 'gre', 'baseline', 'physical', 'vlan', 'mixed', 'reconcile', 'sql-journal', 'guards', 'coexistence', 'alias']) {
currentSlice = slice; currentChildExitConfirmed = false; lastSliceResult = null
await persist(slice + '-started.json', { version: 1, slice, status: 'running', accepted: false, childExitConfirmed: false })
const childBudgetMs = slice === 'baseline' ? 240000 : 120000
// Nine disabled lifecycle operations need their own aggregate child cap;
// measured seven operations alone consumed 105.5s under the original120s.
const childBudgetMs = slice === 'baseline' ? 240000 : slice === 'disabled' ? 180000 : 120000
const cwd = join(owned, 'vrf-production-' + slice), rel = relative(owned, cwd)
assert(rel && !rel.startsWith('..') && !isAbsolute(rel)); await mkdir(cwd)
assert.equal(await realpath(cwd), cwd); assert(!(await lstat(cwd)).isSymbolicLink())
@@ -121,9 +126,10 @@ export async function runOwnedVrfProductionProfile({ directory, database, databa
unknownTimer = setTimeout(() => { if (!exited) { stop('child-exit-unconfirmed'); resolveExit(1) } }, childBudgetMs + 15000)
})
clearTimeout(deadline); clearTimeout(stopTimer); clearTimeout(unknownTimer)
const expectedCases = { baseline: 11, physical: 7, vlan: 9, disabled: 9, mixed: 7, reconcile: 6, 'sql-journal': 1, guards: 11, coexistence: 3, alias: 4 }
const expectedCases = { baseline: 11, physical: 7, vlan: 9, disabled: 9, mixed: 7, reconcile: 6, 'sql-journal': 1, guards: 11, coexistence: 3, alias: 4, gre: 6 }
const component = log.trim().split(/\r?\n/).flatMap(line => { try { return [JSON.parse(line)] } catch { return [] } }).findLast(value => value.slice === slice && Array.isArray(value.accepted))
if (!component || component.accepted.length !== expectedCases[slice] || component.actualSql !== true || component.actualCrypto !== true || component.actualAuthPolicyApprovalRuntime !== true || component.fakeVerifier !== false || component.actualRouter !== false || component.forwardingVerified !== false) failure ??= 'missing-component-receipt'
if (slice === 'gre' && (!Number.isSafeInteger(component?.wireguardPeerTelemetryTicks) || component.wireguardPeerTelemetryTicks <= 6 || component.wireguardPeerTelemetryTicks > 10000)) failure ??= 'missing-component-receipt'
const result = { slice, accepted: code === 0 && !failure && exited, caseCount: component?.accepted?.length ?? 0, code, failure, childPid: child.pid ?? null, childExitConfirmed: exited }
lastSliceResult = result; currentChildExitConfirmed = exited
const diagnostic = vrfSliceDiagnostic(result, log, childBudgetMs, [databaseUrl, target.password, decodeURIComponent(target.password), authSecret])
@@ -135,8 +141,8 @@ export async function runOwnedVrfProductionProfile({ directory, database, databa
console.log(JSON.stringify({ profile: 'test:vrf:production', ...result }))
if (!result.accepted) break
}
const receipt = { accepted: results.length === 10 && results.every(result => result.accepted), childExitConfirmed: results.every(result => result.childExitConfirmed), sameOwnedPg: true, actualRouter: false, forwardingVerified: false, results }
await persist('terminal.json', { version: 1, status: 'terminal', ...receipt, requiredCases: 68, completedCases: results.reduce((sum, value) => sum + value.caseCount, 0), diagnosticDirectory: diagnosticPath })
const receipt = { accepted: results.length === 11 && results.every(result => result.accepted), childExitConfirmed: results.every(result => result.childExitConfirmed), sameOwnedPg: true, actualRouter: false, forwardingVerified: false, results }
await persist('terminal.json', { version: 1, status: 'terminal', ...receipt, requiredCases: 74, completedCases: results.reduce((sum, value) => sum + value.caseCount, 0), diagnosticDirectory: diagnosticPath })
await writeFile(join(owned, 'vrf-production-acceptance.json'), JSON.stringify(receipt, null, 2))
return receipt
} catch {
@@ -0,0 +1,45 @@
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { vrfSliceDiagnostic } from './vrf-production-profile.mjs'
test('only the nine-operation disabled slice receives its measured aggregate budget', () => {
for (const [slice, capMs] of [['disabled', 180000], ['gre', 120000], ['baseline', 240000]]) {
const result = { slice, accepted: false, caseCount: 0, code: 1, failure: 'child-deadline', childExitConfirmed: true }
assert.equal(vrfSliceDiagnostic(result, '', capMs).capMs, capMs)
for (const otherCap of [120000, 180000, 240000].filter(value => value !== capMs)) assert.throws(() => vrfSliceDiagnostic(result, '', otherCap))
}
})
test('GRE lifecycle diagnostic retains the six-case receipt with existing privacy bounds', () => {
const accepted = ['vrf-create', 'vrf-rename', 'vrf-disable', 'vrf-reenable', 'vrf-membership-transfer-a-to-b', 'vrf-delete-addresses-remain']
const result = { slice: 'gre', accepted: true, caseCount: 6, code: 0, failure: null, childExitConfirmed: true }
const log = accepted.map((acceptedCase, index) => JSON.stringify({ slice: 'gre', acceptedCase, nativeWrites: 1, wireguardPeerTelemetryTicks: (index + 1) * 4, password: 'fixture-private-value' }))
log.push(JSON.stringify({ slice: 'gre', accepted, wireguardPeerTelemetryTicks: 24, rawShape: 'synthetic GRE lifecycle', password: 'fixture-private-value' }))
const diagnostic = vrfSliceDiagnostic(result, log.join('\n'), 120000, ['fixture-private-value'])
assert.deepEqual(diagnostic.diagnostics.acceptedCaseSequence, accepted)
assert.equal(diagnostic.diagnostics.finalComponentPresent, true)
assert.equal(diagnostic.diagnostics.rawLogRetained, false)
assert.deepEqual(diagnostic.diagnostics.records.map(row => row.wireguardPeerTelemetryTicks), [4, 8, 12, 16, 20, 24, 24])
assert.equal(diagnostic.actualRouter, false)
assert.equal(diagnostic.forwardingVerified, false)
assert.equal(JSON.stringify(diagnostic).includes('fixture-private-value'), false)
assert.throws(() => vrfSliceDiagnostic(result, '', 240000))
})
test('peer telemetry diagnostic rejects nonnumeric and out-of-budget values', () => {
const result = { slice: 'gre', accepted: false, caseCount: 0, code: 1, failure: 'missing-component-receipt', childExitConfirmed: true }
for (const wireguardPeerTelemetryTicks of [0, -1, 10001, 1.5, 'private-raw-value', { secret: 'private-raw-value' }]) {
const diagnostic = vrfSliceDiagnostic(result, JSON.stringify({ slice: 'gre', wireguardPeerTelemetryTicks }), 120000)
assert.equal(diagnostic.diagnostics.records.some(row => Object.hasOwn(row, 'wireguardPeerTelemetryTicks')), false)
assert.equal(JSON.stringify(diagnostic).includes('private-raw-value'), false)
}
})
test('a partial GRE lifecycle is diagnostic evidence without a final component receipt', () => {
const result = { slice: 'gre', accepted: false, caseCount: 0, code: 1, failure: 'child-deadline', childExitConfirmed: true }
const diagnostic = vrfSliceDiagnostic(result, JSON.stringify({ slice: 'gre', acceptedCase: 'vrf-create' }), 120000)
assert.equal(diagnostic.accepted, false)
assert.equal(diagnostic.diagnostics.finalComponentPresent, false)
assert.equal(diagnostic.diagnostics.lastAcceptedCase, 'vrf-create')
assert.equal(diagnostic.capMs, 120000)
})