import test from 'node:test'; import assert from 'node:assert/strict'; import { createHash } from 'node:crypto'; import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import { upstream58e2204Operations } from '../src/upstream-58e2204.ts'; const fixturePath = fileURLToPath(new URL('./fixtures/main-routes-58e2204.json', import.meta.url)); const fixture = JSON.parse(await readFile(fixturePath, 'utf8')); const key = (operation: { method: string; path?: string; pathTemplate?: string }) => `${operation.method} ${operation.pathTemplate ?? operation.path}`; const evidenceFixturePath = fileURLToPath( new URL('./fixtures/source-evidence-58e2204.json', import.meta.url), ); const evidenceFixture = JSON.parse(await readFile(evidenceFixturePath, 'utf8')); const snapshotRoot = fileURLToPath(new URL('./fixtures/upstream-58e2204/', import.meta.url)); const snapshotManifest = JSON.parse(await readFile(`${snapshotRoot}/manifest.json`, 'utf8')); const requiredFields = [ 'operationId', 'upstreamDomain', 'method', 'pathTemplate', 'handler', 'capability', 'riskLevel', 'requestSchemaEvidence', 'responseSchemaEvidence', 'requestContentType', 'timeoutMs', 'idempotency', 'confirmationPolicy', 'batchable', 'syncSafe', 'sensitiveFields', 'auditedAtCommit', 'compatibilityAdapter', 'uiOwner', 'sourceEvidence', 'responseFixtureStatus', ] as const; const expectedDomains = new Set([ 'instances-auth', 'device-system', 'sim', 'cellular', 'radio-lock', 'data-connection', 'device-network', 'workmode-esim', 'messages', 'calls', 'notifications', 'automation', 'ota', ]); const expectedOwners = new Set([ 'instances-new', 'settings-instance', 'fleet', 'overview', 'cellular', 'device-network', 'messages', 'calls', 'esim', 'notifications', 'automation', 'ota', ]); const operationKey = (operation: { method: string; pathTemplate: string; handler: string }) => `${operation.method} ${operation.pathTemplate} ${operation.handler}`; test('sensitive fields are independently snapshot-rebuildable model-chain anchors', async () => { const directionClaim = (operation: any, direction: string) => ['request', 'path', 'query'].includes(direction) ? operation.requestEvidence : operation.responseEvidence; for (const operation of upstream58e2204Operations as any[]) for (const field of operation.sensitiveFields) { const evidence = field.evidence; assert.ok(evidence, `${operation.operationId}: ${field.path} missing evidence`); assert.match(evidence.sourceSha256, /^[a-f0-9]{64}$/); assert.ok( evidence.sourceFile && evidence.symbol && (evidence.fieldPath || evidence.modelField || evidence.dynamicKey), ); const source = await readFile(`${snapshotRoot}/${evidence.sourceFile}`, 'utf8'); const slice = source .split('\n') .slice(evidence.startLine - 1, evidence.endLine) .join('\n'); assert.equal( createHash('sha256').update(slice).digest('hex'), evidence.sourceSha256, `${operation.operationId}: ${field.path}`, ); assert.ok(directionClaim(operation, field.direction), `${operation.operationId}: direction`); if (evidence.handlerToken) assert.ok(slice.includes(evidence.handlerToken)); else if (evidence.dynamicKey) assert.match(slice, new RegExp(`["']${evidence.dynamicKey}["']`)); else { assert.match(slice, new RegExp(`(?:struct|enum)\\s+${evidence.symbol}\\b`)); assert.match(slice, new RegExp(`\\b${evidence.modelField}\\s*:`)); assert.equal( evidence.modelField, field.path .replace(/\[\*\]/g, '') .split('.') .at(-1), ); for (const link of evidence.containerPath ?? []) { const linkSource = await readFile(`${snapshotRoot}/${link.sourceFile}`, 'utf8'); const linkSlice = linkSource .split('\n') .slice(link.startLine - 1, link.endLine) .join('\n'); assert.equal(createHash('sha256').update(linkSlice).digest('hex'), link.sourceSha256); assert.match(linkSlice, new RegExp(`struct\\s+${link.symbol}\\b`)); assert.match( linkSlice, new RegExp(`\\b${link.field}\\s*:\\s*(?:Vec<)?${link.targetSymbol}`), ); } } } const get = (method: string, path: string) => (upstream58e2204Operations as any[]).find( (o) => o.method === method && o.pathTemplate === path, ); assert.ok(!get('GET', '/api/sim').sensitiveFields.some((f: any) => f.path.endsWith('.imei'))); assert.deepEqual( get('GET', '/api/device-network/wlan/status').sensitiveFields.map((f: any) => f.path), ['$.response.data.ssid', '$.response.data.ipv4_addresses', '$.response.data.ipv6_addresses'], ); assert.deepEqual( get('GET', '/api/device-network/wlan/profiles').sensitiveFields.map((f: any) => f.path), ['$.response.data.profiles[*].ssid'], ); }); test('Phase 0.2 uses structured, snapshot-rebuildable evidence and directional redaction contracts', () => { for (const operation of upstream58e2204Operations as any[]) { for (const name of ['requestEvidence', 'responseEvidence']) { const claim = operation[name]; assert.ok(claim && typeof claim === 'object', `${operation.operationId}: ${name}`); assert.match( claim.kind, /^(none|path|query|json|multipart|bytes|explicit-return|api-response|dynamic-json|opaque)$/, ); assert.match(claim.sourceSha256, /^[a-f0-9]{64}$/); assert.ok( claim.sourceFile && Number.isInteger(claim.startLine) && Number.isInteger(claim.endLine), ); assert.ok(Array.isArray(claim.symbols)); assert.ok(Array.isArray(claim.modelEvidence)); } for (const field of operation.sensitiveFields) { assert.match(field.direction, /^(request|response|path|query|session)$/); assert.match(field.path, /^\$\.(?:body|response|path|query|session)/); assert.ok(field.reason); assert.match(field.redactionMode, /^(drop|mask)$/); assert.ok(field.sourceAnchor?.symbol || field.sourceAnchor?.token); } } const get = (method: string, path: string) => (upstream58e2204Operations as any[]).find( (o) => o.method === method && o.pathTemplate === path, ); assert.ok( get('GET', '/api/sms/list').responseEvidence.symbols.some( (s: any) => s.symbol === 'SmsListResponse', ), ); assert.ok( get('GET', '/api/device').responseEvidence.symbols.some( (s: any) => s.symbol === 'DeviceInfoResponse', ), ); assert.ok( get('GET', '/api/network').responseEvidence.symbols.some( (s: any) => s.symbol === 'NetworkInfoResponse', ), ); assert.ok( get('POST', '/api/ota/upload').responseEvidence.symbols.some( (s: any) => s.symbol === 'OtaUploadResponse', ), ); }); test('structured claims are rebuilt from the independent snapshot, with exact braces and symbols', async () => { for (const operation of upstream58e2204Operations as any[]) for (const claim of [operation.requestEvidence, operation.responseEvidence]) { const source = await readFile(`${snapshotRoot}/${claim.sourceFile}`, 'utf8'); const slice = source .split('\n') .slice(claim.startLine - 1, claim.endLine) .join('\n'); assert.equal( createHash('sha256').update(slice).digest('hex'), claim.sourceSha256, operation.operationId, ); const fn = operation.handler.split('::').at(-1); const signature = new RegExp(`(?:pub\\s+)?async\\s+fn\\s+${fn}\\b`).exec(source); assert.ok(signature); const open = source.indexOf('{', signature!.index); let depth = 0, close = -1; for (let i = open; i < source.length; i++) { if (source[i] === '{') depth++; else if (source[i] === '}' && --depth === 0) { close = i; break; } } assert.equal( source.slice(0, close + 1).split('\n').length, claim.endLine, `${operation.operationId}: exact end`, ); for (const symbol of claim.symbols) assert.ok( slice.includes(symbol.symbol) || claim.modelEvidence.some((m: any) => m.symbol === symbol.symbol), `${operation.operationId}: ${symbol.symbol}`, ); for (const model of claim.modelEvidence) { const modelSource = await readFile(`${snapshotRoot}/${model.sourceFile}`, 'utf8'); const modelSlice = modelSource .split('\n') .slice(model.startLine - 1, model.endLine) .join('\n'); assert.equal( createHash('sha256').update(modelSlice).digest('hex'), model.sourceSha256, model.symbol, ); assert.match(modelSlice, new RegExp(`(?:struct|enum)\\s+${model.symbol}\\b`)); for (const field of model.fields) assert.match(modelSlice, new RegExp(`\\b${field}\\s*:`)); } if (claim.kind === 'dynamic-json') assert.match(slice, /json!|Json\s*\(|ApiResponse::/); } }); test('Axum route chains are independently parsed from frozen main.rs', async () => { const source = await readFile(`${snapshotRoot}/backend/src/main.rs`, 'utf8'); const parsed: string[] = []; for (let from = 0; ; ) { const start = source.indexOf('.route(', from); if (start < 0) break; let depth = 0, quote = false, end = -1; for (let i = start + 6; i < source.length; i++) { const c = source[i]; if (c === '"' && source[i - 1] !== '\\') quote = !quote; if (!quote && c === '(') depth++; else if (!quote && c === ')' && --depth === 0) { end = i; break; } } const chain = source.slice(start, end + 1); from = end + 1; const path = /\.route\(\s*"([^"]+)"/.exec(chain)?.[1]; if (!path) continue; for (const match of chain.matchAll( /\.(get|post|delete)\(([\w:]+)\)|\b(get|post|delete)\(([\w:]+)\)/g, )) { const method = (match[1] ?? match[3]).toUpperCase(); const handler = match[2] ?? match[4]; if (handler !== 'options_handler') parsed.push(`${method} ${path} ${handler}`); } } const expected = fixture.routes.map((r: any) => `${r.method} ${r.path} ${r.handler}`).sort(); assert.deepEqual(parsed.sort(), expected); assert.deepEqual(parsed.sort(), (upstream58e2204Operations as any[]).map(operationKey).sort()); }); test('Bruno files are independently parsed and agree with structured request claims', async () => { for (const evidence of evidenceFixture.operations) for (const bruno of evidence.brunoEvidence ?? []) { const text = await readFile(`${snapshotRoot}/${bruno.file}`, 'utf8'); const method = /\b(get|post|delete)\s*\{/.exec(text)?.[1].toUpperCase(); const url = /url:\s*(?:\{\{baseUrl\}\}|https?:\/\/[^/\s]+)(\/[^\s]+)/.exec(text)?.[1]; assert.equal(method, bruno.method); assert.equal(url, bruno.path); const bodyMode = /body:(json|multipart|text)/.exec(text)?.[1] ?? 'none'; assert.equal(bodyMode, bruno.bodyMode, bruno.file); const operation: any = (upstream58e2204Operations as any[]).find( (o) => o.method === method && (o.pathTemplate === url || new RegExp(`^${o.pathTemplate.replace(/\{[^}]+\}/g, '[^/]+')}$`).test(url!)), ); assert.ok(operation, bruno.file); if (bodyMode === 'json' && bruno.bodyFields.length) assert.equal(operation.requestEvidence.kind, 'json', bruno.file); if (bodyMode === 'json' && !bruno.bodyFields.length) assert.ok( ['none', 'path', 'query', 'json'].includes(operation.requestEvidence.kind), `${bruno.file}: empty Bruno JSON has no contract fields`, ); for (const field of bruno.bodyFields) assert.match(text, new RegExp(`\\b${field}\\b`)); } }); test('frozen fixture has the audited upstream route totals', () => { assert.equal(fixture.upstreamCommit, '58e220411d6599609f0eeda01eb7016e9212f970'); assert.equal(fixture.routes.length, 117); assert.equal(new Set(fixture.routes.map(key)).size, 117); assert.equal(new Set(fixture.routes.map((route: { path: string }) => route.path)).size, 100); assert.deepEqual( Object.fromEntries( ['GET', 'POST', 'DELETE'].map((method) => [ method, fixture.routes.filter((r: { method: string }) => r.method === method).length, ]), ), { GET: 50, POST: 62, DELETE: 5 }, ); }); test('registry is exactly route-parity complete with independent fixture', () => { assert.equal(upstream58e2204Operations.length, 117); const fixtureTriples = fixture.routes .map((r: any) => `${r.method} ${r.path} ${r.handler}`) .sort(); assert.deepEqual(upstream58e2204Operations.map(operationKey).sort(), fixtureTriples); assert.equal( new Set(upstream58e2204Operations.map((operation) => operation.pathTemplate)).size, 100, ); assert.equal( new Set(upstream58e2204Operations.map((operation) => operation.operationId)).size, 117, ); for (const operation of upstream58e2204Operations) { const route = fixture.routes.find( (r: any) => `${r.method} ${r.path} ${r.handler}` === operationKey(operation), ); assert.ok(route, operationKey(operation)); assert.ok( operation.sourceEvidence.includes(route.source), `${operation.operationId}: exact main.rs evidence`, ); } }); test('frozen static-contract evidence is complete and bound to routes', () => { assert.equal(evidenceFixture.upstreamCommit, fixture.upstreamCommit); assert.equal(evidenceFixture.operations.length, 117); assert.deepEqual( evidenceFixture.operations.map((e: any) => `${e.method} ${e.path} ${e.handler}`).sort(), fixture.routes.map((r: any) => `${r.method} ${r.path} ${r.handler}`).sort(), ); for (const evidence of evidenceFixture.operations) { assert.match( evidence.handlerEvidence, /^backend\/src\/(?:handlers|auth|notification_queue)\.rs:\d+-\d+$/, ); assert.match(evidence.sha256, /^[a-f0-9]{64}$/); assert.ok(evidence.requestSummary && evidence.responseSummary); } }); test('source evidence is independently reproducible from frozen whole-file snapshots', async () => { assert.equal(snapshotManifest.upstreamCommit, fixture.upstreamCommit); assert.equal(snapshotManifest.brunoFileCount, 82); for (const [file, expected] of Object.entries(snapshotManifest.files)) { const bytes = await readFile(`${snapshotRoot}/${file}`); assert.equal(createHash('sha256').update(bytes).digest('hex'), expected, file); } for (const evidence of evidenceFixture.operations) { const range = evidence.handlerRange; assert.ok( range && Number.isInteger(range.startLine) && Number.isInteger(range.endLine), evidence.handler, ); const source = await readFile(`${snapshotRoot}/${range.file}`, 'utf8'); const slice = source .split('\n') .slice(range.startLine - 1, range.endLine) .join('\n'); assert.equal( createHash('sha256').update(slice).digest('hex'), evidence.sha256, evidence.handler, ); assert.match(slice, new RegExp(`async\\s+fn\\s+${evidence.handler.split('::').at(-1)}\\b`)); assert.equal( (slice.match(/{/g) ?? []).length, (slice.match(/}/g) ?? []).length, evidence.handler, ); assert.ok( evidence.extractorTokens.every((token: string) => slice.replace(/\\s+/g, '').includes(token.replace(/\\s+/g, '')), ), evidence.handler, ); assert.ok( evidence.responseKind && evidence.responseTypeEvidence !== 'Rust return impl IntoResponse', evidence.handler, ); } }); test('high-value response, confirmation, sensitive-field and Bruno contracts are fixed', () => { const operations: any[] = upstream58e2204Operations as any; const byPath = (method: string, path: string) => operations.find((o) => o.method === method && o.pathTemplate === path)!; assert.match( byPath('GET', '/api/device').responseSchemaEvidence, /ApiResponse/, ); assert.match( byPath('GET', '/api/network').responseSchemaEvidence, /ApiResponse/, ); assert.match( byPath('POST', '/api/ota/upload').responseSchemaEvidence, /ApiResponse/, ); for (const operation of operations) { if (operation.riskLevel === 'R2') assert.ok( ['explicit', 'strong'].includes(operation.confirmationPolicy), operation.operationId, ); if (operation.riskLevel === 'R3') assert.equal(operation.confirmationPolicy, 'strong', operation.operationId); } const expectedSensitive: Record = { 'POST /api/esim/profiles': ['$.body.matching_id', '$.body.confirmation_code', '$.body.imei'], 'POST /api/sms/send': ['$.body.phone_number', '$.body.content'], 'GET /api/sms/conversation': ['$.query.phone_number'], 'POST /api/call/dial': ['$.body.phone_number'], 'POST /api/auth/setup': ['$.body.password'], 'POST /api/auth/login': ['$.body.password'], 'POST /api/auth/password': ['$.body.new_password'], 'POST /api/device-network/wlan/connect': ['$.body.ssid', '$.body.password'], }; for (const [route, fields] of Object.entries(expectedSensitive)) { const [method, path] = route.split(' '); for (const field of fields) assert.ok( byPath(method, path).sensitiveFields.some((claim: any) => claim.path === field), `${route}: ${field}`, ); } for (const evidence of evidenceFixture.operations) { assert.match(evidence.evidenceLevel, /^route\+handler(?:\+model)?(?:\+bruno)?$/); if (evidence.brunoEvidence) assert.ok(evidence.brunoEvidence.length > 0); } }); test('every operation carries auditable orchestration metadata', () => { for (const operation of upstream58e2204Operations) { for (const field of requiredFields) assert.ok(field in operation, `${operation.operationId}: missing ${field}`); assert.ok( expectedDomains.has(operation.upstreamDomain), `${operation.operationId}: unknown domain`, ); assert.ok(expectedOwners.has(operation.uiOwner), `${operation.operationId}: unknown owner`); assert.match(operation.operationId, /^[a-z][A-Za-z0-9]*$/); assert.ok(['R0', 'R1', 'R2', 'R3'].includes(operation.riskLevel)); assert.ok(Number.isInteger(operation.timeoutMs) && operation.timeoutMs > 0); assert.ok(Array.isArray(operation.sensitiveFields)); assert.ok(Array.isArray(operation.sourceEvidence) && operation.sourceEvidence.length > 0); assert.ok( operation.sourceEvidence.some((evidence) => /^backend\/src\/main\.rs:\d+-\d+$/.test(evidence), ), ); assert.ok( operation.handler && operation.requestSchemaEvidence && operation.responseSchemaEvidence, ); for (const field of [ 'requestSchemaEvidence', 'responseSchemaEvidence', 'requestContentType', 'idempotency', ] as const) { assert.doesNotMatch( operation[field], /TODO_EVIDENCE|not frozen/i, `${operation.operationId}: ${field}`, ); } assert.ok( ['safe', 'idempotent', 'non-idempotent', 'conditional'].includes(operation.idempotency), ); assert.equal(operation.auditedAtCommit, fixture.upstreamCommit); assert.equal(operation.compatibilityAdapter, 'none-pinned-commit'); if (operation.riskLevel === 'R2') assert.equal(operation.syncSafe, false); if (operation.riskLevel === 'R3') { assert.equal(operation.capability, 'job'); assert.equal(operation.syncSafe, false); assert.ok(['explicit', 'strong'].includes(operation.confirmationPolicy)); } if (operation.batchable && operation.riskLevel === 'R2') assert.equal(operation.capability, 'job'); } }); test('dangerous authentication endpoints use dedicated flows, never generic proxy', () => { const dangerous = upstream58e2204Operations.filter((operation) => ['/api/auth/setup', '/api/auth/password'].includes(operation.pathTemplate), ); assert.equal(dangerous.length, 2); for (const operation of dangerous) { assert.equal(operation.riskLevel, 'R3'); assert.equal(operation.executionPolicy, 'dedicatedFlow'); } const loginLogout = upstream58e2204Operations.filter((operation) => ['/api/auth/login', '/api/auth/logout'].includes(operation.pathTemplate), ); assert.equal(loginLogout.length, 2); assert.ok( loginLogout.every((operation) => operation.riskLevel === 'R1' && operation.sessionSensitive), ); const authSettingsPost = upstream58e2204Operations.find( (operation) => key(operation) === 'POST /api/auth/settings', ); assert.ok(authSettingsPost && ['R2', 'R3'].includes(authSettingsPost.riskLevel)); assert.equal(authSettingsPost?.syncSafe, false); }); test('product risk floors and auth replay policy are enforced', () => { const byPath = (method: string, path: string) => upstream58e2204Operations.find((o) => o.method === method && o.pathTemplate === path)!; const r3 = [ ['DELETE', '/api/esim/profiles/{iccid}'], ['DELETE', '/api/call/history/{id}'], ['POST', '/api/call/history/clear'], ['POST', '/api/sms/batch-delete'], ['DELETE', '/api/sms/conversation/{phone_number}'], ['DELETE', '/api/sms/message/{id}'], ['POST', '/api/sms/clear'], ['POST', '/api/notifications/logs/clear'], ['POST', '/api/notifications/queue/clear'], ['DELETE', '/api/notifications/queue/{id}'], ['POST', '/api/automation/logs/clear'], ]; for (const [method, path] of r3) { const operation = byPath(method, path); assert.equal(operation.riskLevel, 'R3', `${method} ${path}`); assert.equal(operation.capability, 'job'); assert.ok(['explicit', 'strong'].includes(operation.confirmationPolicy)); } const r2 = [ ['POST', '/api/sms/send'], ['POST', '/api/notifications/test/{channel}'], ['POST', '/api/notifications/queue/retry-all'], ['POST', '/api/notifications/queue/{id}/retry'], ['POST', '/api/automation/test/{task_id}'], ]; for (const [method, path] of r2) { const operation = byPath(method, path); assert.ok(['R2', 'R3'].includes(operation.riskLevel), `${method} ${path}`); assert.equal(operation.capability, 'job'); assert.equal(operation.syncSafe, false); } for (const path of ['/api/auth/login', '/api/auth/logout']) { const operation = byPath('POST', path); assert.equal(operation.executionPolicy, 'dedicatedFlow'); assert.equal(operation.sessionSensitive, true); assert.equal(operation.automaticReplay, 'forbidden'); } assert.equal(byPath('POST', '/api/auth/settings').executionPolicy, 'dedicatedFlow'); }); test('evidence matrix lists every registry operation', async () => { const documentPath = fileURLToPath( new URL('../../../docs/api/simadmin-upstream-58e2204.md', import.meta.url), ); const document = await readFile(documentPath, 'utf8'); const rows = document.split('\n').filter((line) => /^\| `(?:GET|POST|DELETE)` \|/.test(line)); assert.equal(rows.length, 117); for (const operation of upstream58e2204Operations) { const row = rows.find( (row) => row.includes(`\`${operation.method}\``) && row.includes(`\`${operation.pathTemplate}\``) && row.includes(`\`${operation.operationId}\``), ); assert.ok(row, key(operation)); const evidence = evidenceFixture.operations.find( (e: any) => `${e.method} ${e.path} ${e.handler}` === operationKey(operation), ); assert.ok(evidence, operation.operationId); for (const value of [ operation.upstreamDomain, operation.uiOwner, operation.handler, operation.requestContentType, operation.idempotency, operation.riskLevel, operation.capability, evidence.sha256.slice(0, 16), ]) { assert.ok(row.includes(value), `${operation.operationId}: document drift for ${value}`); } } assert.doesNotMatch(document, /TODO_EVIDENCE|not frozen/i); assert.match(document, /Phase 0\.3[^\n]*真实响应样本/); assert.match(document, /dynamic-json/); assert.match(document, /58e220411d6599609f0eeda01eb7016e9212f970/); for (const operation of upstream58e2204Operations as any[]) for (const field of operation.sensitiveFields) { const exactRow = `| ${operation.method} | \`${operation.pathTemplate}\` | ${field.direction} | \`${field.path}\` | ${field.redactionMode} | ${field.reason} |`; assert.ok( document.includes(exactRow), `${operation.operationId}: sensitive ledger drift ${field.path}`, ); } });