import test from 'node:test'; import assert from 'node:assert/strict'; import { OperationRegistry, RuntimeRegistryError, listOperations, operationRegistry, requireExecutableOperation, requireOperation, } from '../src/index.ts'; import { upstream58e2204Operations } from '../src/upstream-58e2204.ts'; import { operationAcceptanceOverrides58e2204 } from '../src/acceptance-58e2204.ts'; import { operationMetadata58e2204 } from '../src/catalog-metadata-58e2204.ts'; test('generated API catalog is an exact safe projection of the runtime registry', async () => { const { default: generated } = await import( '../../../apps/api/src/application/operations/operation-catalog-58e2204.json', { with: { type: 'json' } } ); const expected = listOperations().map( ({ operationId, title, riskLevel, capability, batchable, parameterSchemaId }) => ({ operationId, title, riskLevel, capability, batchable, parameterSchemaId, }), ); assert.deepEqual(generated, expected); }); test('runtime registry projects exactly 117 descriptors in stable operationId order', () => { const listed = listOperations(); assert.equal(listed.length, 117); assert.equal(new Set(listed.map((row) => row.operationId)).size, 117); assert.deepEqual( listed.map((row) => row.operationId), listed.map((row) => row.operationId).toSorted(), ); assert.ok(Object.isFrozen(listed)); assert.ok(listed.every((row) => Object.isFrozen(row))); const device = requireOperation('getDevice'); assert.equal(device.module, device.upstreamDomain); assert.equal(device.uiStrategy, operationAcceptanceOverrides58e2204.getDevice.uiStrategy); assert.equal(device.method, 'GET'); assert.ok(Object.isFrozen(device.sourceEvidence)); assert.strictEqual(requireOperation('getDevice'), device); assert.strictEqual(operationRegistry.requireOperation('getDevice'), device); }); test('runtime construction rejects duplicate rows and missing acceptance overrides', () => { const rows = upstream58e2204Operations as readonly (typeof upstream58e2204Operations)[number][]; assert.throws( () => new OperationRegistry( [...rows, rows[0]], operationAcceptanceOverrides58e2204, operationMetadata58e2204, ), /duplicate operationId: getDevice/, ); const missing = { ...operationAcceptanceOverrides58e2204 }; delete (missing as Record).getDevice; assert.throws( () => new OperationRegistry(rows, missing, operationMetadata58e2204), /missing acceptance override: getDevice/, ); }); test('requireOperation validates only operationId and fails closed with a stable typed error', () => { for (const id of [ '', ' ', 'GET /api/device', '/api/device', '__proto__', 'constructor', 'get-device', undefined, null, ]) { assert.throws( () => requireOperation(id as string), (error: unknown) => error instanceof RuntimeRegistryError && error.code === 'UNKNOWN_OPERATION', String(id), ); } assert.throws( () => requireOperation('getDefinitelyUnknown'), (error: unknown) => error instanceof RuntimeRegistryError && error.code === 'UNKNOWN_OPERATION', ); }); test('dedicated auth flows are catalogued but cannot cross executable boundary', () => { for (const id of [ 'postAuthSetup', 'postAuthPassword', 'postAuthSettings', 'postAuthLogin', 'postAuthLogout', ]) { assert.equal(requireOperation(id).executionPolicy, 'dedicatedFlow'); assert.throws( () => requireExecutableOperation(id), (error: unknown) => error instanceof RuntimeRegistryError && error.code === 'DEDICATED_FLOW_REQUIRED', id, ); } const malformed = new OperationRegistry( upstream58e2204Operations.map((row) => row.operationId === 'getDevice' ? { ...row, executionPolicy: 'futurePolicy' } : row, ), operationAcceptanceOverrides58e2204, operationMetadata58e2204, ); assert.throws( () => malformed.requireExecutableOperation('getDevice'), (error: unknown) => error instanceof RuntimeRegistryError && error.code === 'DEDICATED_FLOW_REQUIRED', ); assert.strictEqual(requireExecutableOperation('getDevice'), requireOperation('getDevice')); }); test('descriptors are deeply immutable and mutation cannot affect later lookups or frozen source', () => { const source = upstream58e2204Operations.find((row) => row.operationId === 'getDevice')!; const originalSourceEvidence = structuredClone(source.sourceEvidence); const descriptor = requireOperation('getDevice'); assert.ok(Object.isFrozen(descriptor)); assert.ok(Object.isFrozen(descriptor.sourceEvidence)); assert.ok(Object.isFrozen(descriptor.sensitiveFields)); assert.throws(() => ((descriptor as { method: string }).method = 'DELETE'), TypeError); assert.throws(() => (descriptor.sourceEvidence as string[]).push('mutation'), TypeError); assert.equal(requireOperation('getDevice').method, 'GET'); assert.deepEqual(source.sourceEvidence, originalSourceEvidence); });