@agentlensai/server 0.9.0 → 0.11.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 (209) hide show
  1. package/dist/cloud/auth/api-key-middleware.d.ts +66 -0
  2. package/dist/cloud/auth/api-key-middleware.d.ts.map +1 -0
  3. package/dist/cloud/auth/api-key-middleware.js +147 -0
  4. package/dist/cloud/auth/api-key-middleware.js.map +1 -0
  5. package/dist/cloud/auth/api-keys.d.ts +90 -0
  6. package/dist/cloud/auth/api-keys.d.ts.map +1 -0
  7. package/dist/cloud/auth/api-keys.js +162 -0
  8. package/dist/cloud/auth/api-keys.js.map +1 -0
  9. package/dist/cloud/auth/audit-log.d.ts +66 -0
  10. package/dist/cloud/auth/audit-log.d.ts.map +1 -0
  11. package/dist/cloud/auth/audit-log.js +92 -0
  12. package/dist/cloud/auth/audit-log.js.map +1 -0
  13. package/dist/cloud/auth/auth-service.d.ts +77 -0
  14. package/dist/cloud/auth/auth-service.d.ts.map +1 -0
  15. package/dist/cloud/auth/auth-service.js +229 -0
  16. package/dist/cloud/auth/auth-service.js.map +1 -0
  17. package/dist/cloud/auth/brute-force.d.ts +36 -0
  18. package/dist/cloud/auth/brute-force.d.ts.map +1 -0
  19. package/dist/cloud/auth/brute-force.js +67 -0
  20. package/dist/cloud/auth/brute-force.js.map +1 -0
  21. package/dist/cloud/auth/index.d.ts +11 -0
  22. package/dist/cloud/auth/index.d.ts.map +1 -0
  23. package/dist/cloud/auth/index.js +11 -0
  24. package/dist/cloud/auth/index.js.map +1 -0
  25. package/dist/cloud/auth/jwt.d.ts +34 -0
  26. package/dist/cloud/auth/jwt.d.ts.map +1 -0
  27. package/dist/cloud/auth/jwt.js +68 -0
  28. package/dist/cloud/auth/jwt.js.map +1 -0
  29. package/dist/cloud/auth/oauth.d.ts +37 -0
  30. package/dist/cloud/auth/oauth.d.ts.map +1 -0
  31. package/dist/cloud/auth/oauth.js +120 -0
  32. package/dist/cloud/auth/oauth.js.map +1 -0
  33. package/dist/cloud/auth/passwords.d.ts +25 -0
  34. package/dist/cloud/auth/passwords.d.ts.map +1 -0
  35. package/dist/cloud/auth/passwords.js +50 -0
  36. package/dist/cloud/auth/passwords.js.map +1 -0
  37. package/dist/cloud/auth/rbac.d.ts +51 -0
  38. package/dist/cloud/auth/rbac.d.ts.map +1 -0
  39. package/dist/cloud/auth/rbac.js +89 -0
  40. package/dist/cloud/auth/rbac.js.map +1 -0
  41. package/dist/cloud/auth/tokens.d.ts +18 -0
  42. package/dist/cloud/auth/tokens.d.ts.map +1 -0
  43. package/dist/cloud/auth/tokens.js +29 -0
  44. package/dist/cloud/auth/tokens.js.map +1 -0
  45. package/dist/cloud/billing/billing-service.d.ts +44 -0
  46. package/dist/cloud/billing/billing-service.d.ts.map +1 -0
  47. package/dist/cloud/billing/billing-service.js +153 -0
  48. package/dist/cloud/billing/billing-service.js.map +1 -0
  49. package/dist/cloud/billing/index.d.ts +11 -0
  50. package/dist/cloud/billing/index.d.ts.map +1 -0
  51. package/dist/cloud/billing/index.js +11 -0
  52. package/dist/cloud/billing/index.js.map +1 -0
  53. package/dist/cloud/billing/invoice-service.d.ts +57 -0
  54. package/dist/cloud/billing/invoice-service.d.ts.map +1 -0
  55. package/dist/cloud/billing/invoice-service.js +123 -0
  56. package/dist/cloud/billing/invoice-service.js.map +1 -0
  57. package/dist/cloud/billing/plan-management.d.ts +46 -0
  58. package/dist/cloud/billing/plan-management.d.ts.map +1 -0
  59. package/dist/cloud/billing/plan-management.js +157 -0
  60. package/dist/cloud/billing/plan-management.js.map +1 -0
  61. package/dist/cloud/billing/quota-enforcement.d.ts +53 -0
  62. package/dist/cloud/billing/quota-enforcement.d.ts.map +1 -0
  63. package/dist/cloud/billing/quota-enforcement.js +143 -0
  64. package/dist/cloud/billing/quota-enforcement.js.map +1 -0
  65. package/dist/cloud/billing/stripe-client.d.ts +142 -0
  66. package/dist/cloud/billing/stripe-client.d.ts.map +1 -0
  67. package/dist/cloud/billing/stripe-client.js +169 -0
  68. package/dist/cloud/billing/stripe-client.js.map +1 -0
  69. package/dist/cloud/billing/trial-service.d.ts +47 -0
  70. package/dist/cloud/billing/trial-service.d.ts.map +1 -0
  71. package/dist/cloud/billing/trial-service.js +104 -0
  72. package/dist/cloud/billing/trial-service.js.map +1 -0
  73. package/dist/cloud/billing/usage-metering.d.ts +83 -0
  74. package/dist/cloud/billing/usage-metering.d.ts.map +1 -0
  75. package/dist/cloud/billing/usage-metering.js +174 -0
  76. package/dist/cloud/billing/usage-metering.js.map +1 -0
  77. package/dist/cloud/ingestion/backpressure.d.ts +107 -0
  78. package/dist/cloud/ingestion/backpressure.d.ts.map +1 -0
  79. package/dist/cloud/ingestion/backpressure.js +134 -0
  80. package/dist/cloud/ingestion/backpressure.js.map +1 -0
  81. package/dist/cloud/ingestion/batch-writer.d.ts +115 -0
  82. package/dist/cloud/ingestion/batch-writer.d.ts.map +1 -0
  83. package/dist/cloud/ingestion/batch-writer.js +319 -0
  84. package/dist/cloud/ingestion/batch-writer.js.map +1 -0
  85. package/dist/cloud/ingestion/dlq-manager.d.ts +116 -0
  86. package/dist/cloud/ingestion/dlq-manager.d.ts.map +1 -0
  87. package/dist/cloud/ingestion/dlq-manager.js +244 -0
  88. package/dist/cloud/ingestion/dlq-manager.js.map +1 -0
  89. package/dist/cloud/ingestion/event-queue.d.ts +105 -0
  90. package/dist/cloud/ingestion/event-queue.d.ts.map +1 -0
  91. package/dist/cloud/ingestion/event-queue.js +185 -0
  92. package/dist/cloud/ingestion/event-queue.js.map +1 -0
  93. package/dist/cloud/ingestion/gateway.d.ts +68 -0
  94. package/dist/cloud/ingestion/gateway.d.ts.map +1 -0
  95. package/dist/cloud/ingestion/gateway.js +198 -0
  96. package/dist/cloud/ingestion/gateway.js.map +1 -0
  97. package/dist/cloud/ingestion/index.d.ts +7 -0
  98. package/dist/cloud/ingestion/index.d.ts.map +1 -0
  99. package/dist/cloud/ingestion/index.js +7 -0
  100. package/dist/cloud/ingestion/index.js.map +1 -0
  101. package/dist/cloud/ingestion/rate-limiter.d.ts +73 -0
  102. package/dist/cloud/ingestion/rate-limiter.d.ts.map +1 -0
  103. package/dist/cloud/ingestion/rate-limiter.js +153 -0
  104. package/dist/cloud/ingestion/rate-limiter.js.map +1 -0
  105. package/dist/cloud/migrate.d.ts +45 -0
  106. package/dist/cloud/migrate.d.ts.map +1 -0
  107. package/dist/cloud/migrate.js +147 -0
  108. package/dist/cloud/migrate.js.map +1 -0
  109. package/dist/cloud/migration/export-import.d.ts +56 -0
  110. package/dist/cloud/migration/export-import.d.ts.map +1 -0
  111. package/dist/cloud/migration/export-import.js +289 -0
  112. package/dist/cloud/migration/export-import.js.map +1 -0
  113. package/dist/cloud/migration/index.d.ts +5 -0
  114. package/dist/cloud/migration/index.d.ts.map +1 -0
  115. package/dist/cloud/migration/index.js +5 -0
  116. package/dist/cloud/migration/index.js.map +1 -0
  117. package/dist/cloud/org-service.d.ts +68 -0
  118. package/dist/cloud/org-service.d.ts.map +1 -0
  119. package/dist/cloud/org-service.js +169 -0
  120. package/dist/cloud/org-service.js.map +1 -0
  121. package/dist/cloud/partition-maintenance.d.ts +29 -0
  122. package/dist/cloud/partition-maintenance.d.ts.map +1 -0
  123. package/dist/cloud/partition-maintenance.js +96 -0
  124. package/dist/cloud/partition-maintenance.js.map +1 -0
  125. package/dist/cloud/retention/index.d.ts +7 -0
  126. package/dist/cloud/retention/index.d.ts.map +1 -0
  127. package/dist/cloud/retention/index.js +7 -0
  128. package/dist/cloud/retention/index.js.map +1 -0
  129. package/dist/cloud/retention/partition-management.d.ts +61 -0
  130. package/dist/cloud/retention/partition-management.d.ts.map +1 -0
  131. package/dist/cloud/retention/partition-management.js +167 -0
  132. package/dist/cloud/retention/partition-management.js.map +1 -0
  133. package/dist/cloud/retention/retention-job.d.ts +70 -0
  134. package/dist/cloud/retention/retention-job.d.ts.map +1 -0
  135. package/dist/cloud/retention/retention-job.js +160 -0
  136. package/dist/cloud/retention/retention-job.js.map +1 -0
  137. package/dist/cloud/retention/retention-policy.d.ts +27 -0
  138. package/dist/cloud/retention/retention-policy.d.ts.map +1 -0
  139. package/dist/cloud/retention/retention-policy.js +36 -0
  140. package/dist/cloud/retention/retention-policy.js.map +1 -0
  141. package/dist/cloud/routes/api-key-routes.d.ts +38 -0
  142. package/dist/cloud/routes/api-key-routes.d.ts.map +1 -0
  143. package/dist/cloud/routes/api-key-routes.js +84 -0
  144. package/dist/cloud/routes/api-key-routes.js.map +1 -0
  145. package/dist/cloud/routes/audit-routes.d.ts +36 -0
  146. package/dist/cloud/routes/audit-routes.d.ts.map +1 -0
  147. package/dist/cloud/routes/audit-routes.js +47 -0
  148. package/dist/cloud/routes/audit-routes.js.map +1 -0
  149. package/dist/cloud/routes/billing-routes.d.ts +51 -0
  150. package/dist/cloud/routes/billing-routes.d.ts.map +1 -0
  151. package/dist/cloud/routes/billing-routes.js +114 -0
  152. package/dist/cloud/routes/billing-routes.js.map +1 -0
  153. package/dist/cloud/routes/onboarding-routes.d.ts +34 -0
  154. package/dist/cloud/routes/onboarding-routes.d.ts.map +1 -0
  155. package/dist/cloud/routes/onboarding-routes.js +58 -0
  156. package/dist/cloud/routes/onboarding-routes.js.map +1 -0
  157. package/dist/cloud/routes/org-routes.d.ts +80 -0
  158. package/dist/cloud/routes/org-routes.d.ts.map +1 -0
  159. package/dist/cloud/routes/org-routes.js +153 -0
  160. package/dist/cloud/routes/org-routes.js.map +1 -0
  161. package/dist/cloud/routes/usage-routes.d.ts +18 -0
  162. package/dist/cloud/routes/usage-routes.d.ts.map +1 -0
  163. package/dist/cloud/routes/usage-routes.js +66 -0
  164. package/dist/cloud/routes/usage-routes.js.map +1 -0
  165. package/dist/cloud/storage/adapter.d.ts +102 -0
  166. package/dist/cloud/storage/adapter.d.ts.map +1 -0
  167. package/dist/cloud/storage/adapter.js +21 -0
  168. package/dist/cloud/storage/adapter.js.map +1 -0
  169. package/dist/cloud/storage/index.d.ts +8 -0
  170. package/dist/cloud/storage/index.d.ts.map +1 -0
  171. package/dist/cloud/storage/index.js +7 -0
  172. package/dist/cloud/storage/index.js.map +1 -0
  173. package/dist/cloud/storage/postgres-adapter.d.ts +34 -0
  174. package/dist/cloud/storage/postgres-adapter.d.ts.map +1 -0
  175. package/dist/cloud/storage/postgres-adapter.js +544 -0
  176. package/dist/cloud/storage/postgres-adapter.js.map +1 -0
  177. package/dist/cloud/storage/sqlite-adapter.d.ts +29 -0
  178. package/dist/cloud/storage/sqlite-adapter.d.ts.map +1 -0
  179. package/dist/cloud/storage/sqlite-adapter.js +176 -0
  180. package/dist/cloud/storage/sqlite-adapter.js.map +1 -0
  181. package/dist/cloud/tenant-pool.d.ts +49 -0
  182. package/dist/cloud/tenant-pool.d.ts.map +1 -0
  183. package/dist/cloud/tenant-pool.js +61 -0
  184. package/dist/cloud/tenant-pool.js.map +1 -0
  185. package/dist/db/capability-store.d.ts +4 -0
  186. package/dist/db/capability-store.d.ts.map +1 -1
  187. package/dist/db/capability-store.js +20 -0
  188. package/dist/db/capability-store.js.map +1 -1
  189. package/dist/index.d.ts.map +1 -1
  190. package/dist/index.js +16 -0
  191. package/dist/index.js.map +1 -1
  192. package/dist/routes/audit.js +3 -3
  193. package/dist/routes/audit.js.map +1 -1
  194. package/dist/routes/capabilities-top.d.ts +15 -0
  195. package/dist/routes/capabilities-top.d.ts.map +1 -0
  196. package/dist/routes/capabilities-top.js +77 -0
  197. package/dist/routes/capabilities-top.js.map +1 -0
  198. package/dist/routes/community.d.ts.map +1 -1
  199. package/dist/routes/community.js +85 -3
  200. package/dist/routes/community.js.map +1 -1
  201. package/dist/routes/delegations-top.d.ts +12 -0
  202. package/dist/routes/delegations-top.d.ts.map +1 -0
  203. package/dist/routes/delegations-top.js +43 -0
  204. package/dist/routes/delegations-top.js.map +1 -0
  205. package/dist/services/community-service.d.ts +6 -0
  206. package/dist/services/community-service.d.ts.map +1 -1
  207. package/dist/services/community-service.js +31 -0
  208. package/dist/services/community-service.js.map +1 -1
  209. package/package.json +1 -1
@@ -0,0 +1,244 @@
1
+ /**
2
+ * DLQ Management & Monitoring (S-3.6)
3
+ *
4
+ * Manages the dead-letter queue stream:
5
+ * - Inspect DLQ entries (list with metadata)
6
+ * - Replay events back to the main ingestion stream
7
+ * - Expire old entries (> 7 days)
8
+ * - Report DLQ depth in health checks
9
+ */
10
+ import { DLQ_STREAM_NAME, STREAM_NAME } from './event-queue.js';
11
+ /** DLQ expiry — 7 days in milliseconds */
12
+ const DLQ_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000;
13
+ export class DlqManager {
14
+ redis;
15
+ constructor(redis) {
16
+ this.redis = redis;
17
+ }
18
+ /**
19
+ * Get DLQ depth (number of entries).
20
+ */
21
+ async getDepth() {
22
+ try {
23
+ return await this.redis.xlen(DLQ_STREAM_NAME);
24
+ }
25
+ catch {
26
+ return 0;
27
+ }
28
+ }
29
+ /**
30
+ * List DLQ entries, optionally with pagination.
31
+ * @param limit Max entries to return (default 50)
32
+ * @param startId Stream ID to start from (default '-' = beginning)
33
+ */
34
+ async listEntries(limit = 50, startId = '-') {
35
+ const raw = await this.redis.xrange(DLQ_STREAM_NAME, startId, '+', 'COUNT', limit);
36
+ return raw.map(([streamId, fields]) => this.parseEntry(streamId, fields));
37
+ }
38
+ /**
39
+ * Get a single DLQ entry by stream ID.
40
+ */
41
+ async getEntry(streamId) {
42
+ const raw = await this.redis.xrange(DLQ_STREAM_NAME, streamId, streamId, 'COUNT', 1);
43
+ if (raw.length === 0)
44
+ return null;
45
+ return this.parseEntry(raw[0][0], raw[0][1]);
46
+ }
47
+ /**
48
+ * Replay a single DLQ entry back to the main ingestion stream.
49
+ * Removes the entry from DLQ after successful re-queue.
50
+ */
51
+ async replayEntry(streamId) {
52
+ const entry = await this.getEntry(streamId);
53
+ if (!entry) {
54
+ return { success: false, error: 'Entry not found in DLQ' };
55
+ }
56
+ // Re-publish to main stream (strip DLQ metadata)
57
+ const cleanEvent = { ...entry.event };
58
+ // Remove internal DLQ fields from data if present
59
+ const cleanData = { ...cleanEvent.data };
60
+ delete cleanData._dlq_reason;
61
+ delete cleanData._dlq_stream_id;
62
+ delete cleanData._dlq_timestamp;
63
+ cleanEvent.data = cleanData;
64
+ const payload = JSON.stringify(cleanEvent);
65
+ const newId = await this.redis.xadd(STREAM_NAME, '*', 'payload', payload);
66
+ // Remove from DLQ
67
+ await this.redis.xdel(DLQ_STREAM_NAME, streamId);
68
+ return { success: true, newStreamId: newId };
69
+ }
70
+ /**
71
+ * Replay multiple DLQ entries. Returns count of successfully replayed.
72
+ */
73
+ async replayBatch(streamIds) {
74
+ let replayed = 0;
75
+ let failed = 0;
76
+ const errors = [];
77
+ for (const id of streamIds) {
78
+ const result = await this.replayEntry(id);
79
+ if (result.success) {
80
+ replayed++;
81
+ }
82
+ else {
83
+ failed++;
84
+ errors.push(`${id}: ${result.error}`);
85
+ }
86
+ }
87
+ return { replayed, failed, errors };
88
+ }
89
+ /**
90
+ * Expire DLQ entries older than 7 days.
91
+ * Returns count of expired entries.
92
+ */
93
+ async expireOldEntries() {
94
+ const cutoffTime = Date.now() - DLQ_EXPIRY_MS;
95
+ // Redis stream IDs are timestamp-based: "timestamp-seq"
96
+ const cutoffId = `${cutoffTime}-0`;
97
+ // Get all entries older than cutoff
98
+ const old = await this.redis.xrange(DLQ_STREAM_NAME, '-', cutoffId, 'COUNT', 1000);
99
+ if (old.length === 0)
100
+ return 0;
101
+ const ids = old.map(([id]) => id);
102
+ const deleted = await this.redis.xdel(DLQ_STREAM_NAME, ...ids);
103
+ return deleted;
104
+ }
105
+ /**
106
+ * Get DLQ health info for inclusion in health check response.
107
+ */
108
+ async healthInfo() {
109
+ const depth = await this.getDepth();
110
+ const WARNING_THRESHOLD = 1000;
111
+ return {
112
+ dlqDepth: depth,
113
+ dlqHealthy: depth < WARNING_THRESHOLD,
114
+ dlqWarning: depth >= WARNING_THRESHOLD
115
+ ? `DLQ depth (${depth}) exceeds warning threshold (${WARNING_THRESHOLD})`
116
+ : undefined,
117
+ };
118
+ }
119
+ // ── Private ──
120
+ parseEntry(streamId, fields) {
121
+ const payloadIdx = fields.indexOf('payload');
122
+ let parsed = {};
123
+ if (payloadIdx !== -1 && payloadIdx + 1 < fields.length) {
124
+ try {
125
+ parsed = JSON.parse(fields[payloadIdx + 1]);
126
+ }
127
+ catch {
128
+ // unparseable
129
+ }
130
+ }
131
+ const dlqReason = parsed._dlq_reason ?? 'unknown';
132
+ const originalStreamId = parsed._dlq_stream_id ?? '';
133
+ const dlqTimestamp = parsed._dlq_timestamp ?? '';
134
+ // Strip DLQ metadata from the event
135
+ const eventData = { ...parsed };
136
+ delete eventData._dlq_reason;
137
+ delete eventData._dlq_stream_id;
138
+ delete eventData._dlq_timestamp;
139
+ return {
140
+ streamId,
141
+ event: eventData,
142
+ dlqReason,
143
+ originalStreamId,
144
+ dlqTimestamp,
145
+ };
146
+ }
147
+ }
148
+ export class InMemoryDlqManager {
149
+ entries = [];
150
+ replayedToMain = [];
151
+ counter = 0;
152
+ /** Add an entry to the in-memory DLQ */
153
+ addEntry(event, reason, originalStreamId) {
154
+ const streamId = `${Date.now()}-${this.counter++}`;
155
+ this.entries.push({
156
+ streamId,
157
+ payload: {
158
+ ...event,
159
+ _dlq_reason: reason,
160
+ _dlq_stream_id: originalStreamId,
161
+ _dlq_timestamp: new Date().toISOString(),
162
+ },
163
+ addedAt: Date.now(),
164
+ });
165
+ return streamId;
166
+ }
167
+ async getDepth() {
168
+ return this.entries.length;
169
+ }
170
+ async listEntries(limit = 50) {
171
+ return this.entries.slice(0, limit).map((e) => this.toEntry(e));
172
+ }
173
+ async getEntry(streamId) {
174
+ const found = this.entries.find((e) => e.streamId === streamId);
175
+ return found ? this.toEntry(found) : null;
176
+ }
177
+ async replayEntry(streamId) {
178
+ const idx = this.entries.findIndex((e) => e.streamId === streamId);
179
+ if (idx === -1)
180
+ return { success: false, error: 'Entry not found in DLQ' };
181
+ const entry = this.entries[idx];
182
+ const clean = { ...entry.payload };
183
+ delete clean._dlq_reason;
184
+ delete clean._dlq_stream_id;
185
+ delete clean._dlq_timestamp;
186
+ this.replayedToMain.push(clean);
187
+ this.entries.splice(idx, 1);
188
+ return { success: true, newStreamId: `${Date.now()}-replayed-${this.counter++}` };
189
+ }
190
+ async replayBatch(streamIds) {
191
+ let replayed = 0;
192
+ let failed = 0;
193
+ const errors = [];
194
+ for (const id of streamIds) {
195
+ const r = await this.replayEntry(id);
196
+ if (r.success)
197
+ replayed++;
198
+ else {
199
+ failed++;
200
+ errors.push(`${id}: ${r.error}`);
201
+ }
202
+ }
203
+ return { replayed, failed, errors };
204
+ }
205
+ async expireOldEntries(expiryMs = DLQ_EXPIRY_MS) {
206
+ const cutoff = Date.now() - expiryMs;
207
+ const before = this.entries.length;
208
+ this.entries = this.entries.filter((e) => e.addedAt > cutoff);
209
+ return before - this.entries.length;
210
+ }
211
+ async healthInfo() {
212
+ const depth = this.entries.length;
213
+ return {
214
+ dlqDepth: depth,
215
+ dlqHealthy: depth < 1000,
216
+ dlqWarning: depth >= 1000 ? `DLQ depth (${depth}) exceeds warning threshold` : undefined,
217
+ };
218
+ }
219
+ /** Test helper: get replayed events */
220
+ getReplayed() {
221
+ return [...this.replayedToMain];
222
+ }
223
+ /** Test helper: clear all */
224
+ clear() {
225
+ this.entries = [];
226
+ this.replayedToMain = [];
227
+ this.counter = 0;
228
+ }
229
+ toEntry(e) {
230
+ const p = e.payload;
231
+ const clean = { ...p };
232
+ delete clean._dlq_reason;
233
+ delete clean._dlq_stream_id;
234
+ delete clean._dlq_timestamp;
235
+ return {
236
+ streamId: e.streamId,
237
+ event: clean,
238
+ dlqReason: p._dlq_reason ?? 'unknown',
239
+ originalStreamId: p._dlq_stream_id ?? '',
240
+ dlqTimestamp: p._dlq_timestamp ?? '',
241
+ };
242
+ }
243
+ }
244
+ //# sourceMappingURL=dlq-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dlq-manager.js","sourceRoot":"","sources":["../../../src/cloud/ingestion/dlq-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Event Queue Abstraction (S-3.1)
3
+ *
4
+ * Interface for event ingestion queue with two implementations:
5
+ * - InMemoryEventQueue: for testing and when REDIS_URL is not set
6
+ * - RedisEventQueue: production implementation using Redis Streams
7
+ *
8
+ * Streams: `event_ingestion` (main), `event_ingestion_dlq` (dead letter)
9
+ * Consumer group: `ingestion_workers`
10
+ */
11
+ export interface QueuedEvent {
12
+ /** Unique event ID */
13
+ id: string;
14
+ /** Event type (e.g. 'llm_call', 'tool_use') */
15
+ type: string;
16
+ /** Event timestamp */
17
+ timestamp: string;
18
+ /** Event payload */
19
+ data: Record<string, unknown>;
20
+ /** Session ID */
21
+ session_id: string;
22
+ /** Enrichment fields */
23
+ org_id: string;
24
+ api_key_id: string;
25
+ received_at: string;
26
+ request_id: string;
27
+ }
28
+ export interface QueueHealth {
29
+ healthy: boolean;
30
+ streamLength: number;
31
+ dlqLength: number;
32
+ consumerGroupExists: boolean;
33
+ error?: string;
34
+ }
35
+ export interface EventQueue {
36
+ /** Initialize the queue (create streams, consumer groups) */
37
+ initialize(): Promise<void>;
38
+ /** Publish a single event to the ingestion stream. Returns stream message ID. */
39
+ publish(event: QueuedEvent): Promise<string>;
40
+ /** Publish multiple events. Returns stream message IDs. */
41
+ publishBatch(events: QueuedEvent[]): Promise<string[]>;
42
+ /** Get stream lengths and health status */
43
+ healthCheck(): Promise<QueueHealth>;
44
+ /** Get main stream length */
45
+ getStreamLength(): Promise<number>;
46
+ /** Get DLQ stream length */
47
+ getDlqLength(): Promise<number>;
48
+ /** Shutdown / cleanup */
49
+ close(): Promise<void>;
50
+ }
51
+ export declare const STREAM_NAME = "event_ingestion";
52
+ export declare const DLQ_STREAM_NAME = "event_ingestion_dlq";
53
+ export declare const CONSUMER_GROUP = "ingestion_workers";
54
+ export declare const BACKPRESSURE_THRESHOLD = 100000;
55
+ export declare class InMemoryEventQueue implements EventQueue {
56
+ private stream;
57
+ private dlq;
58
+ private initialized;
59
+ private counter;
60
+ initialize(): Promise<void>;
61
+ publish(event: QueuedEvent): Promise<string>;
62
+ publishBatch(events: QueuedEvent[]): Promise<string[]>;
63
+ healthCheck(): Promise<QueueHealth>;
64
+ getStreamLength(): Promise<number>;
65
+ getDlqLength(): Promise<number>;
66
+ close(): Promise<void>;
67
+ /** Get all published events */
68
+ getEvents(): QueuedEvent[];
69
+ /** Clear all events */
70
+ clear(): void;
71
+ get isInitialized(): boolean;
72
+ }
73
+ /**
74
+ * Redis Streams implementation. Activated when REDIS_URL is set.
75
+ * Uses ioredis client passed in constructor.
76
+ */
77
+ export declare class RedisEventQueue implements EventQueue {
78
+ private client;
79
+ constructor(client: RedisClient);
80
+ initialize(): Promise<void>;
81
+ publish(event: QueuedEvent): Promise<string>;
82
+ publishBatch(events: QueuedEvent[]): Promise<string[]>;
83
+ healthCheck(): Promise<QueueHealth>;
84
+ getStreamLength(): Promise<number>;
85
+ getDlqLength(): Promise<number>;
86
+ close(): Promise<void>;
87
+ }
88
+ export interface RedisClient {
89
+ xgroup(...args: unknown[]): Promise<unknown>;
90
+ xadd(...args: unknown[]): Promise<string>;
91
+ xlen(key: string): Promise<number>;
92
+ xinfo(...args: unknown[]): Promise<unknown>;
93
+ pipeline(): RedisPipeline;
94
+ }
95
+ export interface RedisPipeline {
96
+ xadd(...args: unknown[]): RedisPipeline;
97
+ exec(): Promise<Array<[Error | null, unknown]> | null>;
98
+ }
99
+ /**
100
+ * Create the appropriate EventQueue based on environment.
101
+ * If a Redis client is provided, uses Redis Streams.
102
+ * Otherwise, falls back to in-memory.
103
+ */
104
+ export declare function createEventQueue(redisClient?: RedisClient): EventQueue;
105
+ //# sourceMappingURL=event-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-queue.d.ts","sourceRoot":"","sources":["../../../src/cloud/ingestion/event-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Event Queue Abstraction (S-3.1)
3
+ *
4
+ * Interface for event ingestion queue with two implementations:
5
+ * - InMemoryEventQueue: for testing and when REDIS_URL is not set
6
+ * - RedisEventQueue: production implementation using Redis Streams
7
+ *
8
+ * Streams: `event_ingestion` (main), `event_ingestion_dlq` (dead letter)
9
+ * Consumer group: `ingestion_workers`
10
+ */
11
+ // ═══════════════════════════════════════════
12
+ // Stream names & constants
13
+ // ═══════════════════════════════════════════
14
+ export const STREAM_NAME = 'event_ingestion';
15
+ export const DLQ_STREAM_NAME = 'event_ingestion_dlq';
16
+ export const CONSUMER_GROUP = 'ingestion_workers';
17
+ export const BACKPRESSURE_THRESHOLD = 100_000;
18
+ // ═══════════════════════════════════════════
19
+ // In-Memory Implementation (testing / no Redis)
20
+ // ═══════════════════════════════════════════
21
+ export class InMemoryEventQueue {
22
+ stream = [];
23
+ dlq = [];
24
+ initialized = false;
25
+ counter = 0;
26
+ async initialize() {
27
+ this.initialized = true;
28
+ }
29
+ async publish(event) {
30
+ if (!this.initialized)
31
+ throw new Error('Queue not initialized');
32
+ const id = `${Date.now()}-${this.counter++}`;
33
+ this.stream.push({ id, event });
34
+ return id;
35
+ }
36
+ async publishBatch(events) {
37
+ const ids = [];
38
+ for (const event of events) {
39
+ ids.push(await this.publish(event));
40
+ }
41
+ return ids;
42
+ }
43
+ async healthCheck() {
44
+ return {
45
+ healthy: this.initialized,
46
+ streamLength: this.stream.length,
47
+ dlqLength: this.dlq.length,
48
+ consumerGroupExists: this.initialized,
49
+ };
50
+ }
51
+ async getStreamLength() {
52
+ return this.stream.length;
53
+ }
54
+ async getDlqLength() {
55
+ return this.dlq.length;
56
+ }
57
+ async close() {
58
+ this.initialized = false;
59
+ }
60
+ // ── Test helpers ──
61
+ /** Get all published events */
62
+ getEvents() {
63
+ return this.stream.map((m) => m.event);
64
+ }
65
+ /** Clear all events */
66
+ clear() {
67
+ this.stream = [];
68
+ this.dlq = [];
69
+ this.counter = 0;
70
+ }
71
+ get isInitialized() {
72
+ return this.initialized;
73
+ }
74
+ }
75
+ // ═══════════════════════════════════════════
76
+ // Redis Implementation
77
+ // ═══════════════════════════════════════════
78
+ /**
79
+ * Redis Streams implementation. Activated when REDIS_URL is set.
80
+ * Uses ioredis client passed in constructor.
81
+ */
82
+ export class RedisEventQueue {
83
+ client;
84
+ constructor(client) {
85
+ this.client = client;
86
+ }
87
+ async initialize() {
88
+ // Create consumer group (creates stream implicitly with MKSTREAM)
89
+ try {
90
+ await this.client.xgroup('CREATE', STREAM_NAME, CONSUMER_GROUP, '0', 'MKSTREAM');
91
+ }
92
+ catch (err) {
93
+ // BUSYGROUP = group already exists, safe to ignore
94
+ if (!(err instanceof Error) || !err.message.includes('BUSYGROUP')) {
95
+ throw err;
96
+ }
97
+ }
98
+ // Ensure DLQ stream exists
99
+ try {
100
+ await this.client.xgroup('CREATE', DLQ_STREAM_NAME, CONSUMER_GROUP, '0', 'MKSTREAM');
101
+ }
102
+ catch (err) {
103
+ if (!(err instanceof Error) || !err.message.includes('BUSYGROUP')) {
104
+ throw err;
105
+ }
106
+ }
107
+ }
108
+ async publish(event) {
109
+ const id = await this.client.xadd(STREAM_NAME, '*', 'payload', JSON.stringify(event));
110
+ return id;
111
+ }
112
+ async publishBatch(events) {
113
+ const pipeline = this.client.pipeline();
114
+ for (const event of events) {
115
+ pipeline.xadd(STREAM_NAME, '*', 'payload', JSON.stringify(event));
116
+ }
117
+ const results = await pipeline.exec();
118
+ return (results ?? []).map((r) => String(r[1]));
119
+ }
120
+ async healthCheck() {
121
+ try {
122
+ const [streamLen, dlqLen] = await Promise.all([
123
+ this.getStreamLength(),
124
+ this.getDlqLength(),
125
+ ]);
126
+ let consumerGroupExists = false;
127
+ try {
128
+ const groups = await this.client.xinfo('GROUPS', STREAM_NAME);
129
+ consumerGroupExists = Array.isArray(groups) && groups.length > 0;
130
+ }
131
+ catch {
132
+ // Stream may not exist yet
133
+ }
134
+ return {
135
+ healthy: true,
136
+ streamLength: streamLen,
137
+ dlqLength: dlqLen,
138
+ consumerGroupExists,
139
+ };
140
+ }
141
+ catch (err) {
142
+ return {
143
+ healthy: false,
144
+ streamLength: 0,
145
+ dlqLength: 0,
146
+ consumerGroupExists: false,
147
+ error: err instanceof Error ? err.message : String(err),
148
+ };
149
+ }
150
+ }
151
+ async getStreamLength() {
152
+ try {
153
+ return await this.client.xlen(STREAM_NAME);
154
+ }
155
+ catch {
156
+ return 0;
157
+ }
158
+ }
159
+ async getDlqLength() {
160
+ try {
161
+ return await this.client.xlen(DLQ_STREAM_NAME);
162
+ }
163
+ catch {
164
+ return 0;
165
+ }
166
+ }
167
+ async close() {
168
+ // Don't close the client — caller owns it
169
+ }
170
+ }
171
+ // ═══════════════════════════════════════════
172
+ // Factory
173
+ // ═══════════════════════════════════════════
174
+ /**
175
+ * Create the appropriate EventQueue based on environment.
176
+ * If a Redis client is provided, uses Redis Streams.
177
+ * Otherwise, falls back to in-memory.
178
+ */
179
+ export function createEventQueue(redisClient) {
180
+ if (redisClient) {
181
+ return new RedisEventQueue(redisClient);
182
+ }
183
+ return new InMemoryEventQueue();
184
+ }
185
+ //# sourceMappingURL=event-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-queue.js","sourceRoot":"","sources":["../../../src/cloud/ingestion/event-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * API Gateway Service (S-3.2)
3
+ *
4
+ * Ingestion endpoints:
5
+ * POST /v1/events — single event
6
+ * POST /v1/events/batch — up to 100 events
7
+ *
8
+ * Flow: Auth → Validate → Enrich → Publish to queue → 202 Accepted
9
+ */
10
+ import type { EventQueue } from './event-queue.js';
11
+ import type { ApiKeyAuthContext } from '../auth/api-key-middleware.js';
12
+ /** Raw event from SDK */
13
+ export interface IncomingEvent {
14
+ id?: string;
15
+ type: string;
16
+ timestamp?: string;
17
+ session_id: string;
18
+ data?: Record<string, unknown>;
19
+ }
20
+ export interface SingleEventRequest {
21
+ event: IncomingEvent;
22
+ }
23
+ export interface BatchEventRequest {
24
+ events: IncomingEvent[];
25
+ }
26
+ export interface BatchEventResponse {
27
+ accepted: number;
28
+ rejected: number;
29
+ errors: Array<{
30
+ index: number;
31
+ error: string;
32
+ }>;
33
+ request_id: string;
34
+ }
35
+ export interface SingleEventResponse {
36
+ accepted: boolean;
37
+ request_id: string;
38
+ }
39
+ export interface ValidationError {
40
+ index: number;
41
+ error: string;
42
+ }
43
+ export declare function validateEvent(event: unknown, index: number): ValidationError | null;
44
+ export declare class IngestionGateway {
45
+ private queue;
46
+ constructor(queue: EventQueue);
47
+ /**
48
+ * POST /v1/events — ingest a single event
49
+ */
50
+ ingestSingle(event: unknown, auth: ApiKeyAuthContext): Promise<{
51
+ status: number;
52
+ body: SingleEventResponse | {
53
+ error: string;
54
+ };
55
+ requestId: string;
56
+ }>;
57
+ /**
58
+ * POST /v1/events/batch — ingest up to 100 events
59
+ */
60
+ ingestBatch(events: unknown, auth: ApiKeyAuthContext): Promise<{
61
+ status: number;
62
+ body: BatchEventResponse | {
63
+ error: string;
64
+ };
65
+ requestId: string;
66
+ }>;
67
+ }
68
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../src/cloud/ingestion/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,kBAAkB,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAMvE,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAyBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAmCnF;AA4BD,qBAAa,gBAAgB;IACf,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,UAAU;IAErC;;OAEG;IACG,YAAY,CAChB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,mBAAmB,GAAG;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IA2ChG;;OAEG;IACG,WAAW,CACf,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,kBAAkB,GAAG;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CA6EhG"}