@agentlensai/server 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/__tests__/alerts.test.d.ts +5 -0
  2. package/dist/__tests__/alerts.test.d.ts.map +1 -0
  3. package/dist/__tests__/alerts.test.js +245 -0
  4. package/dist/__tests__/alerts.test.js.map +1 -0
  5. package/dist/__tests__/analytics.test.d.ts +5 -0
  6. package/dist/__tests__/analytics.test.d.ts.map +1 -0
  7. package/dist/__tests__/analytics.test.js +218 -0
  8. package/dist/__tests__/analytics.test.js.map +1 -0
  9. package/dist/__tests__/ingest.test.d.ts +8 -0
  10. package/dist/__tests__/ingest.test.d.ts.map +1 -0
  11. package/dist/__tests__/ingest.test.js +469 -0
  12. package/dist/__tests__/ingest.test.js.map +1 -0
  13. package/dist/__tests__/llm-tracking.test.d.ts +10 -0
  14. package/dist/__tests__/llm-tracking.test.d.ts.map +1 -0
  15. package/dist/__tests__/llm-tracking.test.js +602 -0
  16. package/dist/__tests__/llm-tracking.test.js.map +1 -0
  17. package/dist/__tests__/stream.test.d.ts +5 -0
  18. package/dist/__tests__/stream.test.d.ts.map +1 -0
  19. package/dist/__tests__/stream.test.js +352 -0
  20. package/dist/__tests__/stream.test.js.map +1 -0
  21. package/dist/db/__tests__/sqlite-store-read.test.js +1 -1
  22. package/dist/db/__tests__/sqlite-store-read.test.js.map +1 -1
  23. package/dist/db/__tests__/sqlite-store-write.test.js +1 -1
  24. package/dist/db/__tests__/sqlite-store-write.test.js.map +1 -1
  25. package/dist/db/migrate.d.ts.map +1 -1
  26. package/dist/db/migrate.js +17 -0
  27. package/dist/db/migrate.js.map +1 -1
  28. package/dist/db/schema.sqlite.d.ts +52 -1
  29. package/dist/db/schema.sqlite.d.ts.map +1 -1
  30. package/dist/db/schema.sqlite.js +3 -0
  31. package/dist/db/schema.sqlite.js.map +1 -1
  32. package/dist/db/sqlite-store.d.ts +12 -2
  33. package/dist/db/sqlite-store.d.ts.map +1 -1
  34. package/dist/db/sqlite-store.js +96 -5
  35. package/dist/db/sqlite-store.js.map +1 -1
  36. package/dist/index.d.ts +9 -2
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +35 -2
  39. package/dist/index.js.map +1 -1
  40. package/dist/lib/__tests__/alert-engine.test.d.ts +5 -0
  41. package/dist/lib/__tests__/alert-engine.test.d.ts.map +1 -0
  42. package/dist/lib/__tests__/alert-engine.test.js +211 -0
  43. package/dist/lib/__tests__/alert-engine.test.js.map +1 -0
  44. package/dist/lib/__tests__/retention.test.js +1 -1
  45. package/dist/lib/__tests__/retention.test.js.map +1 -1
  46. package/dist/lib/alert-engine.d.ts +61 -0
  47. package/dist/lib/alert-engine.d.ts.map +1 -0
  48. package/dist/lib/alert-engine.js +280 -0
  49. package/dist/lib/alert-engine.js.map +1 -0
  50. package/dist/lib/event-bus.d.ts +48 -0
  51. package/dist/lib/event-bus.d.ts.map +1 -0
  52. package/dist/lib/event-bus.js +34 -0
  53. package/dist/lib/event-bus.js.map +1 -0
  54. package/dist/lib/retention.d.ts +1 -1
  55. package/dist/lib/retention.d.ts.map +1 -1
  56. package/dist/lib/sse.d.ts +21 -0
  57. package/dist/lib/sse.d.ts.map +1 -0
  58. package/dist/lib/sse.js +114 -0
  59. package/dist/lib/sse.js.map +1 -0
  60. package/dist/routes/agents.d.ts +1 -1
  61. package/dist/routes/agents.d.ts.map +1 -1
  62. package/dist/routes/alerts.d.ts +17 -0
  63. package/dist/routes/alerts.d.ts.map +1 -0
  64. package/dist/routes/alerts.js +133 -0
  65. package/dist/routes/alerts.js.map +1 -0
  66. package/dist/routes/analytics.d.ts +16 -0
  67. package/dist/routes/analytics.d.ts.map +1 -0
  68. package/dist/routes/analytics.js +293 -0
  69. package/dist/routes/analytics.js.map +1 -0
  70. package/dist/routes/config.d.ts +5 -0
  71. package/dist/routes/config.d.ts.map +1 -1
  72. package/dist/routes/config.js +27 -7
  73. package/dist/routes/config.js.map +1 -1
  74. package/dist/routes/events.d.ts +1 -1
  75. package/dist/routes/events.d.ts.map +1 -1
  76. package/dist/routes/events.js +17 -4
  77. package/dist/routes/events.js.map +1 -1
  78. package/dist/routes/ingest.d.ts +30 -0
  79. package/dist/routes/ingest.d.ts.map +1 -0
  80. package/dist/routes/ingest.js +261 -0
  81. package/dist/routes/ingest.js.map +1 -0
  82. package/dist/routes/sessions.d.ts +1 -1
  83. package/dist/routes/sessions.d.ts.map +1 -1
  84. package/dist/routes/sessions.js +1 -1
  85. package/dist/routes/sessions.js.map +1 -1
  86. package/dist/routes/stats.d.ts +1 -1
  87. package/dist/routes/stats.d.ts.map +1 -1
  88. package/dist/routes/stream.d.ts +16 -0
  89. package/dist/routes/stream.d.ts.map +1 -0
  90. package/dist/routes/stream.js +41 -0
  91. package/dist/routes/stream.js.map +1 -0
  92. package/package.json +2 -2
@@ -0,0 +1,469 @@
1
+ /**
2
+ * Tests for Stories 10.1, 10.2, 10.3: FormBridge Webhook Integration
3
+ *
4
+ * Also covers AgentGate webhook integration (Story 9.1, 9.2, 9.3) via the
5
+ * shared ingest endpoint for completeness.
6
+ */
7
+ import { describe, it, expect } from 'vitest';
8
+ import { createHmac } from 'node:crypto';
9
+ import { Hono } from 'hono';
10
+ import { createTestDb } from '../db/index.js';
11
+ import { runMigrations } from '../db/migrate.js';
12
+ import { SqliteEventStore } from '../db/sqlite-store.js';
13
+ import { ingestRoutes, verifyWebhookSignature } from '../routes/ingest.js';
14
+ // ─── Helpers ─────────────────────────────────────────────────────────
15
+ const FB_SECRET = 'formbridge-test-secret-abc123';
16
+ const AG_SECRET = 'agentgate-test-secret-xyz789';
17
+ function setup() {
18
+ const db = createTestDb();
19
+ runMigrations(db);
20
+ const store = new SqliteEventStore(db);
21
+ const app = new Hono();
22
+ app.route('/', ingestRoutes(store, {
23
+ formbridgeWebhookSecret: FB_SECRET,
24
+ agentgateWebhookSecret: AG_SECRET,
25
+ }));
26
+ return { app, store, db };
27
+ }
28
+ function sign(body, secret) {
29
+ return createHmac('sha256', secret).update(body).digest('hex');
30
+ }
31
+ function makeRequest(app, body, opts) {
32
+ const rawBody = JSON.stringify(body);
33
+ const headers = { 'Content-Type': 'application/json' };
34
+ if (opts?.signatureHeader !== undefined) {
35
+ headers['X-Webhook-Signature'] = opts.signatureHeader;
36
+ }
37
+ else if (opts?.secret) {
38
+ headers['X-Webhook-Signature'] = sign(rawBody, opts.secret);
39
+ }
40
+ return app.request('/', {
41
+ method: 'POST',
42
+ headers,
43
+ body: rawBody,
44
+ });
45
+ }
46
+ // ─── verifyWebhookSignature unit tests ───────────────────────────────
47
+ describe('verifyWebhookSignature', () => {
48
+ it('returns true for valid signature', () => {
49
+ const payload = '{"test": true}';
50
+ const secret = 'mysecret';
51
+ const sig = createHmac('sha256', secret).update(payload).digest('hex');
52
+ expect(verifyWebhookSignature(payload, sig, secret)).toBe(true);
53
+ });
54
+ it('returns false for invalid signature', () => {
55
+ expect(verifyWebhookSignature('data', 'wrong', 'secret')).toBe(false);
56
+ });
57
+ it('returns false for empty signature', () => {
58
+ expect(verifyWebhookSignature('data', '', 'secret')).toBe(false);
59
+ });
60
+ it('returns false for empty secret', () => {
61
+ expect(verifyWebhookSignature('data', 'sig', '')).toBe(false);
62
+ });
63
+ });
64
+ // ─── FormBridge Webhook Receiver (Story 10.1) ────────────────────────
65
+ describe('FormBridge Webhook Receiver — POST /api/events/ingest (Story 10.1)', () => {
66
+ it('accepts a formbridge webhook with valid HMAC signature', async () => {
67
+ const { app } = setup();
68
+ const res = await makeRequest(app, {
69
+ source: 'formbridge',
70
+ event: 'submission.created',
71
+ data: {
72
+ submissionId: 'sub_001',
73
+ formId: 'form_001',
74
+ formName: 'Contact Form',
75
+ fieldCount: 5,
76
+ },
77
+ context: { agentlens_session_id: 'sess_100' },
78
+ }, { secret: FB_SECRET });
79
+ expect(res.status).toBe(201);
80
+ const body = await res.json();
81
+ expect(body.ok).toBe(true);
82
+ expect(body.eventType).toBe('form_submitted');
83
+ expect(body.sessionId).toBe('sess_100');
84
+ });
85
+ it('rejects formbridge webhook with invalid signature', async () => {
86
+ const { app } = setup();
87
+ const res = await makeRequest(app, {
88
+ source: 'formbridge',
89
+ event: 'submission.created',
90
+ data: { submissionId: 'sub_001', formId: 'form_001', fieldCount: 3 },
91
+ }, { signatureHeader: 'invalid_signature_hex' });
92
+ expect(res.status).toBe(401);
93
+ const body = await res.json();
94
+ expect(body.error).toMatch(/signature/i);
95
+ });
96
+ it('rejects formbridge webhook with missing signature', async () => {
97
+ const { app } = setup();
98
+ const res = await makeRequest(app, {
99
+ source: 'formbridge',
100
+ event: 'submission.created',
101
+ data: { submissionId: 'sub_001', formId: 'form_001', fieldCount: 3 },
102
+ });
103
+ expect(res.status).toBe(401);
104
+ });
105
+ it('returns 400 for invalid source', async () => {
106
+ const { app } = setup();
107
+ const res = await makeRequest(app, { source: 'unknown', event: 'test', data: {} }, { secret: FB_SECRET });
108
+ expect(res.status).toBe(400);
109
+ const body = await res.json();
110
+ expect(body.error).toMatch(/source/i);
111
+ });
112
+ it('returns 400 for missing event field', async () => {
113
+ const { app } = setup();
114
+ const res = await makeRequest(app, { source: 'formbridge', data: {} }, { secret: FB_SECRET });
115
+ expect(res.status).toBe(400);
116
+ });
117
+ it('returns 400 for invalid JSON', async () => {
118
+ const { app } = setup();
119
+ const res = await app.request('/', {
120
+ method: 'POST',
121
+ headers: { 'Content-Type': 'application/json' },
122
+ body: 'not-json',
123
+ });
124
+ expect(res.status).toBe(400);
125
+ });
126
+ });
127
+ // ─── FormBridge Event Mapping (Story 10.2) ───────────────────────────
128
+ describe('FormBridge Event Mapping (Story 10.2)', () => {
129
+ it('maps submission.created to form_submitted', async () => {
130
+ const { app, store } = setup();
131
+ const res = await makeRequest(app, {
132
+ source: 'formbridge',
133
+ event: 'submission.created',
134
+ data: {
135
+ submissionId: 'sub_100',
136
+ formId: 'form_200',
137
+ formName: 'Feedback Form',
138
+ fieldCount: 8,
139
+ },
140
+ context: { agentlens_session_id: 'sess_map1' },
141
+ }, { secret: FB_SECRET });
142
+ expect(res.status).toBe(201);
143
+ const body = await res.json();
144
+ expect(body.eventType).toBe('form_submitted');
145
+ // Verify stored event
146
+ const event = await store.getEvent(body.eventId);
147
+ expect(event).toBeTruthy();
148
+ expect(event.eventType).toBe('form_submitted');
149
+ expect(event.payload).toMatchObject({
150
+ submissionId: 'sub_100',
151
+ formId: 'form_200',
152
+ formName: 'Feedback Form',
153
+ fieldCount: 8,
154
+ });
155
+ });
156
+ it('maps submission.completed to form_completed', async () => {
157
+ const { app, store } = setup();
158
+ const res = await makeRequest(app, {
159
+ source: 'formbridge',
160
+ event: 'submission.completed',
161
+ data: {
162
+ submissionId: 'sub_100',
163
+ formId: 'form_200',
164
+ completedBy: 'user@example.com',
165
+ durationMs: 45000,
166
+ },
167
+ context: { agentlens_session_id: 'sess_map2' },
168
+ }, { secret: FB_SECRET });
169
+ expect(res.status).toBe(201);
170
+ const body = await res.json();
171
+ expect(body.eventType).toBe('form_completed');
172
+ const event = await store.getEvent(body.eventId);
173
+ expect(event.payload).toMatchObject({
174
+ submissionId: 'sub_100',
175
+ formId: 'form_200',
176
+ completedBy: 'user@example.com',
177
+ durationMs: 45000,
178
+ });
179
+ });
180
+ it('maps submission.expired to form_expired', async () => {
181
+ const { app, store } = setup();
182
+ const res = await makeRequest(app, {
183
+ source: 'formbridge',
184
+ event: 'submission.expired',
185
+ data: {
186
+ submissionId: 'sub_100',
187
+ formId: 'form_200',
188
+ expiredAfterMs: 3600000,
189
+ },
190
+ context: { agentlens_session_id: 'sess_map3' },
191
+ }, { secret: FB_SECRET });
192
+ expect(res.status).toBe(201);
193
+ const body = await res.json();
194
+ expect(body.eventType).toBe('form_expired');
195
+ const event = await store.getEvent(body.eventId);
196
+ expect(event.payload).toMatchObject({
197
+ submissionId: 'sub_100',
198
+ formId: 'form_200',
199
+ expiredAfterMs: 3600000,
200
+ });
201
+ });
202
+ it('returns 400 for unknown formbridge event type', async () => {
203
+ const { app } = setup();
204
+ const res = await makeRequest(app, {
205
+ source: 'formbridge',
206
+ event: 'submission.unknown_event',
207
+ data: { submissionId: 'sub_100', formId: 'form_200' },
208
+ context: { agentlens_session_id: 'sess_map4' },
209
+ }, { secret: FB_SECRET });
210
+ expect(res.status).toBe(400);
211
+ const body = await res.json();
212
+ expect(body.error).toMatch(/unknown.*event/i);
213
+ });
214
+ it('stores source metadata on mapped events', async () => {
215
+ const { app, store } = setup();
216
+ const res = await makeRequest(app, {
217
+ source: 'formbridge',
218
+ event: 'submission.created',
219
+ data: {
220
+ submissionId: 'sub_meta',
221
+ formId: 'form_meta',
222
+ fieldCount: 3,
223
+ },
224
+ context: { agentlens_session_id: 'sess_meta' },
225
+ }, { secret: FB_SECRET });
226
+ const body = await res.json();
227
+ const event = await store.getEvent(body.eventId);
228
+ expect(event.metadata).toMatchObject({
229
+ source: 'formbridge',
230
+ webhookEvent: 'submission.created',
231
+ });
232
+ });
233
+ });
234
+ // ─── Session Correlation (Story 10.3) ────────────────────────────────
235
+ describe('FormBridge Session Correlation (Story 10.3)', () => {
236
+ it('links event to session via context.agentlens_session_id', async () => {
237
+ const { app } = setup();
238
+ const res = await makeRequest(app, {
239
+ source: 'formbridge',
240
+ event: 'submission.created',
241
+ data: {
242
+ submissionId: 'sub_corr1',
243
+ formId: 'form_corr1',
244
+ fieldCount: 2,
245
+ },
246
+ context: { agentlens_session_id: 'sess_linked' },
247
+ }, { secret: FB_SECRET });
248
+ expect(res.status).toBe(201);
249
+ const body = await res.json();
250
+ expect(body.sessionId).toBe('sess_linked');
251
+ });
252
+ it('creates unlinked session ID when no context provided', async () => {
253
+ const { app } = setup();
254
+ const res = await makeRequest(app, {
255
+ source: 'formbridge',
256
+ event: 'submission.created',
257
+ data: {
258
+ submissionId: 'sub_corr2',
259
+ formId: 'form_corr2',
260
+ fieldCount: 1,
261
+ },
262
+ }, { secret: FB_SECRET });
263
+ expect(res.status).toBe(201);
264
+ const body = await res.json();
265
+ expect(body.sessionId).toMatch(/^unlinked_/);
266
+ });
267
+ it('creates unlinked session ID when context has no session ID', async () => {
268
+ const { app } = setup();
269
+ const res = await makeRequest(app, {
270
+ source: 'formbridge',
271
+ event: 'submission.completed',
272
+ data: {
273
+ submissionId: 'sub_corr3',
274
+ formId: 'form_corr3',
275
+ completedBy: 'user@test.com',
276
+ durationMs: 5000,
277
+ },
278
+ context: { some_other_key: 'value' },
279
+ }, { secret: FB_SECRET });
280
+ expect(res.status).toBe(201);
281
+ const body = await res.json();
282
+ expect(body.sessionId).toMatch(/^unlinked_/);
283
+ });
284
+ it('uses agent ID from context when available', async () => {
285
+ const { app, store } = setup();
286
+ const res = await makeRequest(app, {
287
+ source: 'formbridge',
288
+ event: 'submission.created',
289
+ data: {
290
+ submissionId: 'sub_agent',
291
+ formId: 'form_agent',
292
+ fieldCount: 4,
293
+ },
294
+ context: {
295
+ agentlens_session_id: 'sess_agent_test',
296
+ agentlens_agent_id: 'my-custom-agent',
297
+ },
298
+ }, { secret: FB_SECRET });
299
+ const body = await res.json();
300
+ const event = await store.getEvent(body.eventId);
301
+ expect(event.agentId).toBe('my-custom-agent');
302
+ });
303
+ it('defaults agent ID to "external" when not in context', async () => {
304
+ const { app, store } = setup();
305
+ const res = await makeRequest(app, {
306
+ source: 'formbridge',
307
+ event: 'submission.created',
308
+ data: {
309
+ submissionId: 'sub_noagent',
310
+ formId: 'form_noagent',
311
+ fieldCount: 1,
312
+ },
313
+ context: { agentlens_session_id: 'sess_noagent' },
314
+ }, { secret: FB_SECRET });
315
+ const body = await res.json();
316
+ const event = await store.getEvent(body.eventId);
317
+ expect(event.agentId).toBe('external');
318
+ });
319
+ it('chains hashes correctly across multiple webhook events in same session', async () => {
320
+ const { app, store } = setup();
321
+ // First event
322
+ const res1 = await makeRequest(app, {
323
+ source: 'formbridge',
324
+ event: 'submission.created',
325
+ data: { submissionId: 'sub_chain', formId: 'form_chain', fieldCount: 3 },
326
+ context: { agentlens_session_id: 'sess_chain' },
327
+ }, { secret: FB_SECRET });
328
+ const body1 = await res1.json();
329
+ // Second event — same session
330
+ const res2 = await makeRequest(app, {
331
+ source: 'formbridge',
332
+ event: 'submission.completed',
333
+ data: { submissionId: 'sub_chain', formId: 'form_chain', completedBy: 'user@x.com', durationMs: 10000 },
334
+ context: { agentlens_session_id: 'sess_chain' },
335
+ }, { secret: FB_SECRET });
336
+ const body2 = await res2.json();
337
+ const event1 = await store.getEvent(body1.eventId);
338
+ const event2 = await store.getEvent(body2.eventId);
339
+ // First event has null prevHash, second chains from first
340
+ expect(event1.prevHash).toBeNull();
341
+ expect(event2.prevHash).toBe(event1.hash);
342
+ });
343
+ });
344
+ // ─── AgentGate Webhook (Story 9.1, 9.2, 9.3 — sanity checks) ────────
345
+ describe('AgentGate Webhook via shared ingest endpoint', () => {
346
+ it('maps request.created to approval_requested', async () => {
347
+ const { app, store } = setup();
348
+ const res = await makeRequest(app, {
349
+ source: 'agentgate',
350
+ event: 'request.created',
351
+ data: {
352
+ requestId: 'req_001',
353
+ action: 'delete_file',
354
+ params: { file: '/tmp/data.txt' },
355
+ urgency: 'high',
356
+ },
357
+ context: { agentlens_session_id: 'sess_ag1' },
358
+ }, { secret: AG_SECRET });
359
+ expect(res.status).toBe(201);
360
+ const body = await res.json();
361
+ expect(body.eventType).toBe('approval_requested');
362
+ const event = await store.getEvent(body.eventId);
363
+ expect(event.payload).toMatchObject({
364
+ requestId: 'req_001',
365
+ action: 'delete_file',
366
+ urgency: 'high',
367
+ });
368
+ });
369
+ it('maps request.approved to approval_granted', async () => {
370
+ const { app } = setup();
371
+ const res = await makeRequest(app, {
372
+ source: 'agentgate',
373
+ event: 'request.approved',
374
+ data: {
375
+ requestId: 'req_002',
376
+ action: 'send_email',
377
+ decidedBy: 'admin',
378
+ reason: 'Looks good',
379
+ },
380
+ context: { agentlens_session_id: 'sess_ag2' },
381
+ }, { secret: AG_SECRET });
382
+ expect(res.status).toBe(201);
383
+ const body = await res.json();
384
+ expect(body.eventType).toBe('approval_granted');
385
+ });
386
+ it('maps request.denied to approval_denied', async () => {
387
+ const { app } = setup();
388
+ const res = await makeRequest(app, {
389
+ source: 'agentgate',
390
+ event: 'request.denied',
391
+ data: {
392
+ requestId: 'req_003',
393
+ action: 'deploy',
394
+ decidedBy: 'ops',
395
+ reason: 'Not now',
396
+ },
397
+ context: { agentlens_session_id: 'sess_ag3' },
398
+ }, { secret: AG_SECRET });
399
+ expect(res.status).toBe(201);
400
+ const body = await res.json();
401
+ expect(body.eventType).toBe('approval_denied');
402
+ });
403
+ it('maps request.expired to approval_expired', async () => {
404
+ const { app } = setup();
405
+ const res = await makeRequest(app, {
406
+ source: 'agentgate',
407
+ event: 'request.expired',
408
+ data: {
409
+ requestId: 'req_004',
410
+ action: 'restart',
411
+ },
412
+ context: { agentlens_session_id: 'sess_ag4' },
413
+ }, { secret: AG_SECRET });
414
+ expect(res.status).toBe(201);
415
+ const body = await res.json();
416
+ expect(body.eventType).toBe('approval_expired');
417
+ });
418
+ });
419
+ // ─── Generic Webhook ─────────────────────────────────────────────────
420
+ describe('Generic Webhook via ingest endpoint', () => {
421
+ it('accepts generic webhooks without HMAC verification', async () => {
422
+ const { app } = setup();
423
+ // No X-Webhook-Signature header
424
+ const res = await makeRequest(app, {
425
+ source: 'generic',
426
+ event: 'deployment',
427
+ data: {
428
+ eventType: 'custom',
429
+ type: 'deployment',
430
+ data: { service: 'api', version: '1.2.3' },
431
+ },
432
+ context: { agentlens_session_id: 'sess_gen1' },
433
+ });
434
+ expect(res.status).toBe(201);
435
+ const body = await res.json();
436
+ expect(body.eventType).toBe('custom');
437
+ });
438
+ });
439
+ // ─── Webhook secret not configured ──────────────────────────────────
440
+ describe('Missing webhook secret configuration', () => {
441
+ it('returns 500 when formbridge secret is not configured', async () => {
442
+ const db = createTestDb();
443
+ runMigrations(db);
444
+ const store = new SqliteEventStore(db);
445
+ const app = new Hono();
446
+ app.route('/', ingestRoutes(store, {
447
+ // No formbridgeWebhookSecret
448
+ agentgateWebhookSecret: AG_SECRET,
449
+ }));
450
+ const body = {
451
+ source: 'formbridge',
452
+ event: 'submission.created',
453
+ data: { submissionId: 's', formId: 'f', fieldCount: 1 },
454
+ };
455
+ const rawBody = JSON.stringify(body);
456
+ const res = await app.request('/', {
457
+ method: 'POST',
458
+ headers: {
459
+ 'Content-Type': 'application/json',
460
+ 'X-Webhook-Signature': sign(rawBody, 'any'),
461
+ },
462
+ body: rawBody,
463
+ });
464
+ expect(res.status).toBe(500);
465
+ const respBody = await res.json();
466
+ expect(respBody.error).toMatch(/secret.*not configured/i);
467
+ });
468
+ });
469
+ //# sourceMappingURL=ingest.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest.test.js","sourceRoot":"","sources":["../../src/__tests__/ingest.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tests for Epic 2: LLM Call Tracking — Server Ingest & Storage
3
+ *
4
+ * Stories covered:
5
+ * - 2.1: Session materialization for LLM events
6
+ * - 2.2: LLM-specific analytics queries
7
+ * - 2.3: Server-side tests (this file)
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=llm-tracking.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-tracking.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/llm-tracking.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}