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}`); } });