import { test } from 'node:test'; import assert from 'node:assert/strict'; import { BadRequestException, ServiceUnavailableException } from '@nestjs/common'; import { IngestService, expectedSignature, stableJson } from '../src/ingest/ingest.service.js'; test('ingest canonical JSON is stable across object key order', () => { assert.equal(stableJson({ z: 1, a: { y: 2, b: 3 } }), '{"a":{"b":3,"y":2},"z":1}'); }); test('ingest is disabled unless an HMAC secret is configured', () => { const previous = process.env.CASAN_CP_INGEST_TOKEN; delete process.env.CASAN_CP_INGEST_TOKEN; try { assert.throws(() => new IngestService().ingest({}, '0', 'none'), ServiceUnavailableException); } finally { if (previous === undefined) delete process.env.CASAN_CP_INGEST_TOKEN; else process.env.CASAN_CP_INGEST_TOKEN = previous; } }); test('signed ingest rejects raw prompt/content fields before persistence', () => { const previous = process.env.CASAN_CP_INGEST_TOKEN; process.env.CASAN_CP_INGEST_TOKEN = 'test-only-secret'; const timestamp = String(Math.floor(Date.now() / 1000)); const body = { schema_version: 1, sent_at: new Date().toISOString(), project_id: 'safe-project', trace_id: 'safe-trace', receipt: {}, metric: { trace_id: 'safe-trace', prompt: 'must-not-cross-boundary' }, trace: { trace_id: 'safe-trace' }, events: [], }; try { const signature = expectedSignature('test-only-secret', timestamp, body); assert.throws( () => new IngestService().ingest(body, timestamp, signature), BadRequestException, ); } finally { if (previous === undefined) delete process.env.CASAN_CP_INGEST_TOKEN; else process.env.CASAN_CP_INGEST_TOKEN = previous; } });