monora-ai 2.1.0 → 2.1.3

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 (184) hide show
  1. package/README.md +333 -159
  2. package/dist/aims_governance.d.ts +238 -0
  3. package/dist/aims_governance.d.ts.map +1 -0
  4. package/dist/aims_governance.js +922 -0
  5. package/dist/alerts.d.ts +16 -0
  6. package/dist/alerts.d.ts.map +1 -1
  7. package/dist/alerts.js +16 -0
  8. package/dist/api.d.ts +6 -0
  9. package/dist/api.d.ts.map +1 -1
  10. package/dist/api.js +6 -0
  11. package/dist/assessment.d.ts +85 -0
  12. package/dist/assessment.d.ts.map +1 -1
  13. package/dist/assessment.js +506 -13
  14. package/dist/attribution.d.ts +44 -3
  15. package/dist/attribution.d.ts.map +1 -1
  16. package/dist/attribution.js +197 -10
  17. package/dist/autodetect.d.ts +68 -0
  18. package/dist/autodetect.d.ts.map +1 -1
  19. package/dist/autodetect.js +639 -0
  20. package/dist/bias.d.ts +130 -0
  21. package/dist/bias.d.ts.map +1 -0
  22. package/dist/bias.js +223 -0
  23. package/dist/cli/diagnostics.d.ts +5 -1
  24. package/dist/cli/diagnostics.d.ts.map +1 -1
  25. package/dist/cli/diagnostics.js +23 -6
  26. package/dist/cli/doctor.d.ts +25 -0
  27. package/dist/cli/doctor.d.ts.map +1 -0
  28. package/dist/cli/doctor.js +381 -0
  29. package/dist/cli/fix.d.ts +16 -0
  30. package/dist/cli/fix.d.ts.map +1 -0
  31. package/dist/cli/fix.js +284 -0
  32. package/dist/cli/init.d.ts +57 -0
  33. package/dist/cli/init.d.ts.map +1 -0
  34. package/dist/cli/init.js +205 -0
  35. package/dist/cli.js +1550 -176
  36. package/dist/complianceTargets.d.ts +111 -0
  37. package/dist/complianceTargets.d.ts.map +1 -0
  38. package/dist/complianceTargets.js +521 -0
  39. package/dist/config.d.ts +261 -16
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +381 -32
  42. package/dist/config_migrations.d.ts.map +1 -1
  43. package/dist/config_migrations.js +38 -1
  44. package/dist/config_schema.d.ts +2490 -1035
  45. package/dist/config_schema.d.ts.map +1 -1
  46. package/dist/config_schema.js +233 -64
  47. package/dist/context.d.ts +34 -0
  48. package/dist/context.d.ts.map +1 -1
  49. package/dist/context.js +118 -7
  50. package/dist/control_backbone.d.ts +122 -0
  51. package/dist/control_backbone.d.ts.map +1 -0
  52. package/dist/control_backbone.js +698 -0
  53. package/dist/data-governance.d.ts +187 -0
  54. package/dist/data-governance.d.ts.map +1 -0
  55. package/dist/data-governance.js +424 -0
  56. package/dist/dataResidency.d.ts +44 -0
  57. package/dist/dataResidency.d.ts.map +1 -0
  58. package/dist/dataResidency.js +203 -0
  59. package/dist/dispatcher.d.ts.map +1 -1
  60. package/dist/dispatcher.js +17 -5
  61. package/dist/evidence_store.d.ts +103 -0
  62. package/dist/evidence_store.d.ts.map +1 -0
  63. package/dist/evidence_store.js +459 -0
  64. package/dist/executiveSummary.d.ts +15 -0
  65. package/dist/executiveSummary.d.ts.map +1 -1
  66. package/dist/executiveSummary.js +135 -22
  67. package/dist/identity.d.ts +143 -0
  68. package/dist/identity.d.ts.map +1 -0
  69. package/dist/identity.js +231 -0
  70. package/dist/impact-assessment.d.ts +350 -0
  71. package/dist/impact-assessment.d.ts.map +1 -0
  72. package/dist/impact-assessment.js +580 -0
  73. package/dist/index.d.ts +20 -4
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +247 -5
  76. package/dist/instrumentation.d.ts +1 -1
  77. package/dist/instrumentation.d.ts.map +1 -1
  78. package/dist/instrumentation.js +123 -22
  79. package/dist/integrations/anthropic.d.ts +3 -0
  80. package/dist/integrations/anthropic.d.ts.map +1 -1
  81. package/dist/integrations/anthropic.js +282 -80
  82. package/dist/integrations/governance.d.ts +33 -0
  83. package/dist/integrations/governance.d.ts.map +1 -0
  84. package/dist/integrations/governance.js +208 -0
  85. package/dist/integrations/langchain.d.ts +4 -0
  86. package/dist/integrations/langchain.d.ts.map +1 -1
  87. package/dist/integrations/langchain.js +362 -142
  88. package/dist/integrations/openai.d.ts +9 -0
  89. package/dist/integrations/openai.d.ts.map +1 -1
  90. package/dist/integrations/openai.js +673 -73
  91. package/dist/iso42001_consolidation.d.ts +16 -0
  92. package/dist/iso42001_consolidation.d.ts.map +1 -0
  93. package/dist/iso42001_consolidation.js +413 -0
  94. package/dist/iso42001_workflows.d.ts +263 -0
  95. package/dist/iso42001_workflows.d.ts.map +1 -0
  96. package/dist/iso42001_workflows.js +781 -0
  97. package/dist/lifecycle.d.ts +299 -0
  98. package/dist/lifecycle.d.ts.map +1 -0
  99. package/dist/lifecycle.js +624 -0
  100. package/dist/lineage.d.ts +2 -2
  101. package/dist/lineage.d.ts.map +1 -1
  102. package/dist/lineage.js +9 -16
  103. package/dist/middleware/express.d.ts.map +1 -1
  104. package/dist/middleware/express.js +18 -3
  105. package/dist/middleware/nextjs.js +2 -2
  106. package/dist/model.d.ts +143 -0
  107. package/dist/model.d.ts.map +1 -0
  108. package/dist/model.js +371 -0
  109. package/dist/onboarding.d.ts +42 -0
  110. package/dist/onboarding.d.ts.map +1 -0
  111. package/dist/onboarding.js +1022 -0
  112. package/dist/oversight.d.ts +264 -0
  113. package/dist/oversight.d.ts.map +1 -0
  114. package/dist/oversight.js +497 -0
  115. package/dist/presets.js +7 -7
  116. package/dist/quotas.d.ts +171 -0
  117. package/dist/quotas.d.ts.map +1 -0
  118. package/dist/quotas.js +259 -0
  119. package/dist/register.d.ts +13 -0
  120. package/dist/register.d.ts.map +1 -0
  121. package/dist/register.js +99 -0
  122. package/dist/registry.d.ts +1 -0
  123. package/dist/registry.d.ts.map +1 -1
  124. package/dist/registry.js +7 -0
  125. package/dist/registryData.json +43 -6
  126. package/dist/report.d.ts +2 -1
  127. package/dist/report.d.ts.map +1 -1
  128. package/dist/report.js +189 -2
  129. package/dist/reporting.d.ts +125 -0
  130. package/dist/reporting.d.ts.map +1 -1
  131. package/dist/reporting.js +192 -2
  132. package/dist/resources.d.ts +285 -0
  133. package/dist/resources.d.ts.map +1 -0
  134. package/dist/resources.js +643 -0
  135. package/dist/risk.d.ts +120 -0
  136. package/dist/risk.d.ts.map +1 -0
  137. package/dist/risk.js +220 -0
  138. package/dist/runtime.d.ts +73 -0
  139. package/dist/runtime.d.ts.map +1 -1
  140. package/dist/runtime.js +415 -18
  141. package/dist/schemaInference.d.ts +92 -0
  142. package/dist/schemaInference.d.ts.map +1 -0
  143. package/dist/schemaInference.js +466 -0
  144. package/dist/schema_validation.js +2 -2
  145. package/dist/schemas/config.schema.json +118 -4
  146. package/dist/security_report.js +4 -4
  147. package/dist/signing.d.ts +1 -1
  148. package/dist/signing.d.ts.map +1 -1
  149. package/dist/signing.js +4 -0
  150. package/dist/sinks/file.d.ts +19 -1
  151. package/dist/sinks/file.d.ts.map +1 -1
  152. package/dist/sinks/file.js +82 -13
  153. package/dist/sinks/https.d.ts +10 -0
  154. package/dist/sinks/https.d.ts.map +1 -1
  155. package/dist/sinks/https.js +76 -16
  156. package/dist/sinks/stdout.d.ts +1 -0
  157. package/dist/sinks/stdout.d.ts.map +1 -1
  158. package/dist/sinks/stdout.js +12 -1
  159. package/dist/spec.d.ts +159 -0
  160. package/dist/spec.d.ts.map +1 -0
  161. package/dist/spec.js +391 -0
  162. package/dist/stakeholders.d.ts +199 -0
  163. package/dist/stakeholders.d.ts.map +1 -0
  164. package/dist/stakeholders.js +398 -0
  165. package/dist/standards.d.ts.map +1 -1
  166. package/dist/standards.js +160 -2
  167. package/dist/standards_ingest.d.ts.map +1 -1
  168. package/dist/standards_ingest.js +1 -4
  169. package/dist/telemetry.d.ts +16 -2
  170. package/dist/telemetry.d.ts.map +1 -1
  171. package/dist/telemetry.js +77 -14
  172. package/dist/templates/controls/iso42001_control_catalog.json +1443 -0
  173. package/dist/traced_emitter.d.ts.map +1 -1
  174. package/dist/traced_emitter.js +19 -9
  175. package/dist/trust_package.d.ts +19 -1
  176. package/dist/trust_package.d.ts.map +1 -1
  177. package/dist/trust_package.js +89 -2
  178. package/dist/verify.d.ts.map +1 -1
  179. package/dist/verify.js +9 -2
  180. package/dist/wal.d.ts.map +1 -1
  181. package/dist/wal.js +2 -1
  182. package/package.json +14 -1
  183. package/scripts/postinstall.js +105 -210
  184. package/templates/controls/iso42001_control_catalog.json +1443 -0
@@ -28,7 +28,11 @@
28
28
  "ai_act": { "$ref": "#/$defs/ai_act" },
29
29
  "telemetry": { "$ref": "#/$defs/telemetry" },
30
30
  "attribution": { "$ref": "#/$defs/attribution" },
31
- "audit": { "$ref": "#/$defs/audit_metadata" }
31
+ "audit": { "$ref": "#/$defs/audit_metadata" },
32
+ "quotas": { "$ref": "#/$defs/quotas" },
33
+ "onboarding": { "$ref": "#/$defs/onboarding" },
34
+ "model_spec": { "$ref": "#/$defs/model_spec" },
35
+ "enrichments": { "$ref": "#/$defs/enrichments" }
32
36
  },
33
37
  "$defs": {
34
38
  "defaults": {
@@ -58,10 +62,13 @@
58
62
  "backoff_base_sec": { "type": "number", "minimum": 0 },
59
63
  "rotation": { "type": ["string", "null"] },
60
64
  "max_size_mb": { "type": ["integer", "null"], "minimum": 1 },
65
+ "symlink": { "type": "boolean" },
61
66
  "format": { "type": ["string", "null"] },
62
67
  "circuit_breaker": { "$ref": "#/$defs/circuit_breaker" },
63
68
  "retry_queue": { "$ref": "#/$defs/retry_queue" },
64
- "idempotency": { "$ref": "#/$defs/idempotency" }
69
+ "idempotency": { "$ref": "#/$defs/idempotency" },
70
+ "data_residency": { "type": ["string", "null"], "enum": ["us", "eu", "any", null] },
71
+ "data_residency_action": { "type": ["string", "null"], "enum": ["block", "warn", null] }
65
72
  }
66
73
  },
67
74
  "circuit_breaker": {
@@ -257,7 +264,7 @@
257
264
  "queue_size": { "type": "integer", "minimum": 1, "default": 1000 },
258
265
  "batch_size": { "type": "integer", "minimum": 1, "default": 50 },
259
266
  "flush_interval_sec": { "type": "number", "minimum": 0, "default": 1.0 },
260
- "queue_full_timeout_sec": { "type": ["number", "null"], "minimum": 0 },
267
+ "queue_full_timeout_sec": { "type": ["number", "null"], "exclusiveMinimum": 0 },
261
268
  "adaptive_batching": { "type": "boolean", "default": true },
262
269
  "min_batch_size": { "type": "integer", "minimum": 1, "default": 10 },
263
270
  "max_batch_size": { "type": "integer", "minimum": 1, "default": 500 }
@@ -305,7 +312,7 @@
305
312
  "enabled": { "type": "boolean", "default": true },
306
313
  "backend": {
307
314
  "type": "string",
308
- "enum": ["minimal", "prometheus", "statsd"],
315
+ "enum": ["none", "minimal", "memory", "prometheus", "statsd"],
309
316
  "default": "minimal"
310
317
  },
311
318
  "prometheus": { "$ref": "#/$defs/prometheus" },
@@ -359,6 +366,113 @@
359
366
  "notes": { "type": ["string", "null"] }
360
367
  }
361
368
  },
369
+ "quotas": {
370
+ "type": "object",
371
+ "additionalProperties": true,
372
+ "properties": {
373
+ "enabled": { "type": "boolean", "default": false },
374
+ "max_tokens_per_trace": { "type": "integer", "minimum": 0, "default": 100000 },
375
+ "max_llm_calls_per_trace": { "type": "integer", "minimum": 0, "default": 50 },
376
+ "max_trace_duration_sec": { "type": "integer", "minimum": 0, "default": 3600 },
377
+ "max_cost_per_trace": { "type": "number", "minimum": 0, "default": 10.0 },
378
+ "action": { "type": "string", "enum": ["warn", "block"], "default": "warn" }
379
+ }
380
+ },
381
+ "onboarding_artifacts": {
382
+ "type": "object",
383
+ "additionalProperties": true,
384
+ "properties": {
385
+ "production_logs_path": { "type": "string", "default": "./monora_events.jsonl" },
386
+ "schema_contract_path": { "type": "string", "default": "./onboarding/schema_contract.json" },
387
+ "dataset_sample_path": { "type": ["string", "null"] },
388
+ "baseline_reports_dir": { "type": "string", "default": "./monora_reports/onboarding" }
389
+ }
390
+ },
391
+ "onboarding_validation": {
392
+ "type": "object",
393
+ "additionalProperties": true,
394
+ "properties": {
395
+ "min_log_records": { "type": "integer", "minimum": 1, "default": 100 },
396
+ "required_field_presence_threshold": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.95 },
397
+ "type_conformance_threshold": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.9 }
398
+ }
399
+ },
400
+ "onboarding_completion": {
401
+ "type": "object",
402
+ "additionalProperties": true,
403
+ "properties": {
404
+ "completed_at": { "type": ["string", "null"] },
405
+ "completed_by": { "type": ["string", "null"] },
406
+ "last_validated_at": { "type": ["string", "null"] }
407
+ }
408
+ },
409
+ "onboarding": {
410
+ "type": "object",
411
+ "additionalProperties": true,
412
+ "properties": {
413
+ "enabled": { "type": "boolean", "default": false },
414
+ "required_in_production": { "type": "boolean", "default": true },
415
+ "status": { "type": "string", "enum": ["draft", "validated", "completed"], "default": "draft" },
416
+ "standards": {
417
+ "type": "array",
418
+ "items": { "type": "string" },
419
+ "default": ["SOC2", "GDPR", "ISO27001"]
420
+ },
421
+ "artifacts": { "$ref": "#/$defs/onboarding_artifacts" },
422
+ "validation": { "$ref": "#/$defs/onboarding_validation" },
423
+ "completion": { "$ref": "#/$defs/onboarding_completion" }
424
+ }
425
+ },
426
+ "model_spec_roles": {
427
+ "type": "object",
428
+ "additionalProperties": true,
429
+ "properties": {
430
+ "inputs": { "type": "array", "items": { "type": "string" }, "default": [] },
431
+ "outputs": { "type": "array", "items": { "type": "string" }, "default": [] },
432
+ "metadata": { "type": "array", "items": { "type": "string" }, "default": [] },
433
+ "identifiers": {
434
+ "type": "array",
435
+ "items": { "type": "string" },
436
+ "default": ["event_id", "trace_id", "span_id"]
437
+ }
438
+ }
439
+ },
440
+ "model_spec": {
441
+ "type": "object",
442
+ "additionalProperties": true,
443
+ "properties": {
444
+ "name": { "type": "string", "default": "monora_default" },
445
+ "version": { "type": "string", "default": "v1" },
446
+ "event_ts_field": { "type": "string", "default": "timestamp" },
447
+ "schema_ref": { "type": "string", "default": "./onboarding/schema_contract.json" },
448
+ "roles": { "$ref": "#/$defs/model_spec_roles" }
449
+ }
450
+ },
451
+ "enrichment_toggles": {
452
+ "type": "object",
453
+ "additionalProperties": true,
454
+ "properties": {
455
+ "identity_tracking": { "type": "boolean", "default": true },
456
+ "risk_tracking": { "type": "boolean", "default": true },
457
+ "bias_tracking": { "type": "boolean", "default": false },
458
+ "oversight_tracking": { "type": "boolean", "default": true },
459
+ "data_governance_tracking": { "type": "boolean", "default": true },
460
+ "lifecycle_tracking": { "type": "boolean", "default": true }
461
+ }
462
+ },
463
+ "enrichments": {
464
+ "type": "object",
465
+ "additionalProperties": true,
466
+ "properties": {
467
+ "profile": { "type": "string", "default": "recommended" },
468
+ "bundles": {
469
+ "type": "array",
470
+ "items": { "type": "string" },
471
+ "default": ["core_observability", "soc2_access", "gdpr_privacy", "iso27001_security"]
472
+ },
473
+ "toggles": { "$ref": "#/$defs/enrichment_toggles" }
474
+ }
475
+ },
362
476
  "prometheus": {
363
477
  "type": "object",
364
478
  "additionalProperties": true,
@@ -148,7 +148,7 @@ function buildCompleteness(events) {
148
148
  };
149
149
  }
150
150
  function buildComplianceSummary(events, config) {
151
- const report = (0, report_1.buildReport)(events, config.policies);
151
+ const report = (0, report_1.buildReport)(events, config.policies, config.registry);
152
152
  const violations = report.violations || [];
153
153
  const compliance = report.model_compliance || {};
154
154
  const timestamps = events.map((event) => event.timestamp).filter(Boolean);
@@ -200,7 +200,7 @@ function buildClassificationCompliance(events) {
200
200
  return result;
201
201
  }
202
202
  function assessRisks(events, config) {
203
- const report = (0, report_1.buildReport)(events, config.policies);
203
+ const report = (0, report_1.buildReport)(events, config.policies, config.registry);
204
204
  const violations = report.violations || [];
205
205
  const unknownModels = report.model_compliance?.unknown_models_used || [];
206
206
  const tampered = (0, verify_1.detectTampering)(events);
@@ -294,9 +294,9 @@ function buildOperationalMetrics(events, config) {
294
294
  };
295
295
  }
296
296
  function buildEvidence(events, config) {
297
- const report = (0, report_1.buildReport)(events, config.policies);
297
+ const report = (0, report_1.buildReport)(events, config.policies, config.registry);
298
298
  const compliance = report.model_compliance || {};
299
- const evidence = report.evidence || {};
299
+ const evidence = { ...(report.evidence || {}) };
300
300
  evidence.unknown_models_used = compliance.unknown_models_used || [];
301
301
  evidence.forbidden_models_blocked = compliance.forbidden_models_blocked || [];
302
302
  evidence.tampered_events = (0, verify_1.detectTampering)(events);
package/dist/signing.d.ts CHANGED
@@ -9,7 +9,7 @@ export interface SigningConfig {
9
9
  algorithm?: 'ed25519' | 'hmac-sha256';
10
10
  key_id?: string | null;
11
11
  key_file?: string | null;
12
- key_env?: string;
12
+ key_env?: string | null;
13
13
  }
14
14
  export interface EventSignature {
15
15
  algorithm: string;
@@ -1 +1 @@
1
- {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuCH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,iBAAiB,CAAiC;gBAE9C,MAAM,GAAE,aAAkB;IActC,OAAO,CAAC,OAAO;IAmEf;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,cAAc,GAAG,SAAS;IAgB5D,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,QAAQ;CAkBjB;AAED;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAA4E;IAExF;;;;;;OAMG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IA2CjE;;;;OAIG;IACH,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAA6B,EACrC,KAAK,CAAC,EAAE,MAAM,GACb,OAAO;IAkBV;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAuC3C,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,UAAU;CAUnB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,GAAG,WAAW,CAEd;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,GAAE,MAA6B,GACpC,OAAO,CAsBT"}
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../src/signing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuCH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,iBAAiB,CAAiC;gBAE9C,MAAM,GAAE,aAAkB;IActC,OAAO,CAAC,OAAO;IAyEf;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,cAAc,GAAG,SAAS;IAgB5D,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,QAAQ;CAkBjB;AAED;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAA4E;IAExF;;;;;;OAMG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IA2CjE;;;;OAIG;IACH,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAA6B,EACrC,KAAK,CAAC,EAAE,MAAM,GACb,OAAO;IAkBV;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO;IAuC3C,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,UAAU;CAUnB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,GAAG,WAAW,CAEd;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,GAAE,MAA6B,GACpC,OAAO,CAsBT"}
package/dist/signing.js CHANGED
@@ -129,6 +129,10 @@ class EventSigner {
129
129
  throw new Error(`Ed25519 signing enabled but no key provided. ` +
130
130
  `Set ${this.config.key_env} or provide key_file.`);
131
131
  }
132
+ if (this.config.algorithm === 'hmac-sha256') {
133
+ throw new Error(`HMAC-SHA256 signing enabled but no key provided. ` +
134
+ `Set ${this.config.key_env} or provide key_file.`);
135
+ }
132
136
  return;
133
137
  }
134
138
  this.signingKey = keyData;
@@ -1,13 +1,23 @@
1
1
  /**
2
2
  * File sink with JSON-lines output and optional rotation.
3
+ *
4
+ * Supports:
5
+ * - `rotation: 'daily'` - Rotate files daily with date suffix
6
+ * - `rotation: 'size'` - Rotate when file exceeds `maxSizeMb`
7
+ * - `symlink: true` - Maintain symlinks that point to the current file:
8
+ * - original path (e.g., `monora_events.jsonl`)
9
+ * - latest path (e.g., `monora_events.latest.jsonl`)
10
+ * (useful for npm scripts and log viewers that need a stable path)
3
11
  */
4
12
  import { Sink } from './base';
5
13
  export declare class FileSink implements Sink {
6
- private path;
14
+ private originalPath;
15
+ private currentPath;
7
16
  private batchSize;
8
17
  private flushIntervalSec;
9
18
  private rotation;
10
19
  private maxSizeMb?;
20
+ private symlink;
11
21
  private buffer;
12
22
  private timer?;
13
23
  private currentDate;
@@ -16,6 +26,7 @@ export declare class FileSink implements Sink {
16
26
  flushIntervalSec?: number;
17
27
  rotation?: 'none' | 'daily' | 'size';
18
28
  maxSizeMb?: number;
29
+ symlink?: boolean;
19
30
  });
20
31
  emit(events: Array<Record<string, any>>): void;
21
32
  flush(): void;
@@ -23,6 +34,13 @@ export declare class FileSink implements Sink {
23
34
  private flushInternal;
24
35
  private ensurePath;
25
36
  private rotateFile;
37
+ /**
38
+ * Update symlinks to point to the current rotated file.
39
+ * This allows npm scripts and log viewers to always access the latest file
40
+ * via stable paths (e.g., `monora_events.jsonl` or `monora_events.latest.jsonl`).
41
+ */
42
+ private updateSymlink;
43
+ private latestPath;
26
44
  private dailyPath;
27
45
  private today;
28
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/sinks/file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,IAAI,EAAa,MAAM,QAAQ,CAAC;AAEzC,qBAAa,QAAS,YAAW,IAAI;IACnC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,KAAK,CAAC,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAAS;gBAG1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;QACrC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IAiBH,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI;IAO9C,KAAK,IAAI,IAAI;IAIb,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,UAAU;IAuBlB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,KAAK;CAId"}
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/sinks/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,IAAI,EAAa,MAAM,QAAQ,CAAC;AAEzC,qBAAa,QAAS,YAAW,IAAI;IACnC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,KAAK,CAAC,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAAS;gBAG1B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;QACrC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB;IA2BH,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI;IAO9C,KAAK,IAAI,IAAI;IAIb,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,UAAU;IA4BlB,OAAO,CAAC,UAAU;IAclB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAyCrB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,KAAK;CAId"}
@@ -1,6 +1,14 @@
1
1
  "use strict";
2
2
  /**
3
3
  * File sink with JSON-lines output and optional rotation.
4
+ *
5
+ * Supports:
6
+ * - `rotation: 'daily'` - Rotate files daily with date suffix
7
+ * - `rotation: 'size'` - Rotate when file exceeds `maxSizeMb`
8
+ * - `symlink: true` - Maintain symlinks that point to the current file:
9
+ * - original path (e.g., `monora_events.jsonl`)
10
+ * - latest path (e.g., `monora_events.latest.jsonl`)
11
+ * (useful for npm scripts and log viewers that need a stable path)
4
12
  */
5
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
14
  if (k2 === undefined) k2 = k;
@@ -42,13 +50,23 @@ const path = __importStar(require("path"));
42
50
  const base_1 = require("./base");
43
51
  class FileSink {
44
52
  constructor(filePath, options) {
45
- this.path = filePath;
53
+ this.originalPath = filePath;
54
+ this.currentPath = filePath;
46
55
  this.batchSize = options?.batchSize || 100;
47
56
  this.flushIntervalSec = options?.flushIntervalSec || 5.0;
48
57
  this.rotation = options?.rotation || 'none';
49
58
  this.maxSizeMb = options?.maxSizeMb;
59
+ this.symlink = options?.symlink ?? false;
50
60
  this.buffer = [];
51
61
  this.currentDate = this.today();
62
+ // Initialize the current path for daily rotation
63
+ if (this.rotation === 'daily') {
64
+ this.currentPath = this.dailyPath(this.currentDate);
65
+ this.updateSymlink();
66
+ }
67
+ else if (this.rotation !== 'none') {
68
+ this.updateSymlink();
69
+ }
52
70
  if (this.flushIntervalSec > 0) {
53
71
  this.timer = setInterval(() => {
54
72
  this.flush();
@@ -78,7 +96,7 @@ class FileSink {
78
96
  try {
79
97
  this.ensurePath();
80
98
  const lines = this.buffer.map((event) => JSON.stringify(event)).join('\n') + '\n';
81
- fs.appendFileSync(this.path, lines, 'utf-8');
99
+ fs.appendFileSync(this.currentPath, lines, 'utf-8');
82
100
  this.buffer = [];
83
101
  }
84
102
  catch (error) {
@@ -90,40 +108,91 @@ class FileSink {
90
108
  const today = this.today();
91
109
  if (today !== this.currentDate) {
92
110
  this.currentDate = today;
111
+ this.currentPath = this.dailyPath(today);
112
+ this.updateSymlink();
93
113
  }
94
- this.path = this.dailyPath(today);
95
114
  }
96
115
  else if (this.rotation === 'size' && this.maxSizeMb) {
97
116
  const maxBytes = this.maxSizeMb * 1024 * 1024;
98
- if (fs.existsSync(this.path)) {
99
- const stats = fs.statSync(this.path);
117
+ if (fs.existsSync(this.currentPath)) {
118
+ const stats = fs.statSync(this.currentPath);
100
119
  if (stats.size >= maxBytes) {
101
120
  this.rotateFile();
102
121
  }
103
122
  }
104
123
  }
105
- const dir = path.dirname(this.path);
124
+ const dir = path.dirname(this.currentPath);
106
125
  if (!fs.existsSync(dir)) {
107
126
  fs.mkdirSync(dir, { recursive: true });
108
127
  }
128
+ if (this.symlink && this.rotation !== 'none') {
129
+ this.updateSymlink();
130
+ }
109
131
  }
110
132
  rotateFile() {
111
133
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T').join('_');
112
- const ext = path.extname(this.path);
113
- const basename = path.basename(this.path, ext);
114
- const dirname = path.dirname(this.path);
134
+ const ext = path.extname(this.currentPath);
135
+ const basename = path.basename(this.currentPath, ext);
136
+ const dirname = path.dirname(this.currentPath);
115
137
  const rotated = path.join(dirname, `${basename}.${timestamp}${ext}`);
116
138
  try {
117
- fs.renameSync(this.path, rotated);
139
+ fs.renameSync(this.currentPath, rotated);
118
140
  }
119
141
  catch (error) {
120
142
  throw new base_1.SinkError(`Failed to rotate file: ${error}`);
121
143
  }
122
144
  }
145
+ /**
146
+ * Update symlinks to point to the current rotated file.
147
+ * This allows npm scripts and log viewers to always access the latest file
148
+ * via stable paths (e.g., `monora_events.jsonl` or `monora_events.latest.jsonl`).
149
+ */
150
+ updateSymlink() {
151
+ if (!this.symlink || this.rotation === 'none') {
152
+ return;
153
+ }
154
+ const targets = [
155
+ { linkPath: this.originalPath, skipIfSame: true },
156
+ { linkPath: this.latestPath(), skipIfSame: false },
157
+ ];
158
+ for (const target of targets) {
159
+ if (target.skipIfSame && this.currentPath === target.linkPath) {
160
+ continue;
161
+ }
162
+ try {
163
+ if (fs.existsSync(target.linkPath)) {
164
+ const stats = fs.lstatSync(target.linkPath);
165
+ if (stats.isSymbolicLink()) {
166
+ fs.unlinkSync(target.linkPath);
167
+ }
168
+ else {
169
+ // Avoid removing user data.
170
+ continue;
171
+ }
172
+ }
173
+ const relativePath = path.relative(path.dirname(target.linkPath), this.currentPath);
174
+ fs.symlinkSync(relativePath, target.linkPath);
175
+ }
176
+ catch (error) {
177
+ // Symlink creation is best-effort; log but don't throw
178
+ // Windows may require admin privileges for symlinks
179
+ if (process.env.DEBUG) {
180
+ console.warn(`Failed to create symlink: ${error}`);
181
+ }
182
+ }
183
+ }
184
+ }
185
+ latestPath() {
186
+ const ext = path.extname(this.originalPath);
187
+ const basename = path.basename(this.originalPath, ext);
188
+ const dirname = path.dirname(this.originalPath);
189
+ return path.join(dirname, `${basename}.latest${ext}`);
190
+ }
123
191
  dailyPath(date) {
124
- const ext = path.extname(this.path);
125
- const basename = path.basename(this.path, ext);
126
- const dirname = path.dirname(this.path);
192
+ // Use originalPath for calculating daily path (not currentPath)
193
+ const ext = path.extname(this.originalPath);
194
+ const basename = path.basename(this.originalPath, ext);
195
+ const dirname = path.dirname(this.originalPath);
127
196
  return path.join(dirname, `${basename}.${date}${ext}`);
128
197
  }
129
198
  today() {
@@ -7,6 +7,13 @@
7
7
  */
8
8
  import { Sink } from './base';
9
9
  import { CircuitBreakerConfig } from '../circuit_breaker';
10
+ import { DataResidency } from '../config';
11
+ export interface DataResidencyOptions {
12
+ /** Required data residency region (us, eu, any, or null for no enforcement) */
13
+ residency?: DataResidency;
14
+ /** Action on failure: 'block' throws error, 'warn' logs warning (default: 'warn') */
15
+ action?: 'block' | 'warn';
16
+ }
10
17
  export interface HttpSinkOptions {
11
18
  batchSize?: number;
12
19
  timeoutSec?: number;
@@ -15,6 +22,7 @@ export interface HttpSinkOptions {
15
22
  circuitBreaker?: CircuitBreakerConfig;
16
23
  retryQueue?: RetryQueueOptions;
17
24
  idempotency?: IdempotencyOptions;
25
+ dataResidency?: DataResidencyOptions;
18
26
  }
19
27
  export interface RetryQueueOptions {
20
28
  enabled?: boolean;
@@ -24,6 +32,7 @@ export interface RetryQueueOptions {
24
32
  }
25
33
  export interface IdempotencyOptions {
26
34
  enabled?: boolean;
35
+ header?: string;
27
36
  headerName?: string;
28
37
  }
29
38
  export declare class HttpSink implements Sink {
@@ -41,6 +50,7 @@ export declare class HttpSink implements Sink {
41
50
  private readonly idempotencyEnabled;
42
51
  private readonly idempotencyHeader;
43
52
  private flushing;
53
+ private readonly dataResidencyResult;
44
54
  constructor(endpoint: string, headers: Record<string, string>, options?: HttpSinkOptions);
45
55
  emit(events: Array<Record<string, any>>): void | Promise<void>;
46
56
  flush(): void | Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"https.d.ts","sourceRoot":"","sources":["../../src/sinks/https.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,IAAI,EAAa,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAkB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAa1E,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiMD,qBAAa,QAAS,YAAW,IAAI;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAiB;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAU;gBAGxB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE,eAAe;IAuD3B,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9D,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7B,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAQf,kBAAkB;YA0BlB,eAAe;IAO7B,OAAO,CAAC,YAAY;YAQN,WAAW;IA0CnB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC"}
1
+ {"version":3,"file":"https.d.ts","sourceRoot":"","sources":["../../src/sinks/https.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,IAAI,EAAa,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAkB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAQ1E,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAO1C,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,qFAAqF;IACrF,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAgQD,qBAAa,QAAS,YAAW,IAAI;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAiB;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkC;gBAGpE,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE,eAAe;IAgE3B,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9D,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7B,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAQf,kBAAkB;YA4BlB,eAAe;IAO7B,OAAO,CAAC,YAAY;YAQN,WAAW;IA0CnB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC"}
@@ -52,6 +52,7 @@ const circuit_breaker_1 = require("../circuit_breaker");
52
52
  const verify_1 = require("../verify");
53
53
  const telemetry_1 = require("../telemetry");
54
54
  const logger_1 = require("../logger");
55
+ const dataResidency_1 = require("../dataResidency");
55
56
  function sleep(ms) {
56
57
  return new Promise((resolve) => setTimeout(resolve, ms));
57
58
  }
@@ -73,6 +74,7 @@ class HttpRetryQueue {
73
74
  const filepath = path.join(this.queueDir, filename);
74
75
  const payload = {
75
76
  created_at: new Date().toISOString(),
77
+ attempts: 0,
76
78
  events,
77
79
  };
78
80
  fs.writeFileSync(filepath, JSON.stringify(payload));
@@ -103,8 +105,9 @@ class HttpRetryQueue {
103
105
  try {
104
106
  await sendFunc(events);
105
107
  }
106
- catch {
107
- return;
108
+ catch (error) {
109
+ this.handleSendFailure(filepath, payload, error);
110
+ continue;
108
111
  }
109
112
  this.removeFile(filepath);
110
113
  }
@@ -119,7 +122,9 @@ class HttpRetryQueue {
119
122
  try {
120
123
  entries = fs
121
124
  .readdirSync(this.queueDir)
122
- .filter((entry) => entry.endsWith('.json') && entry !== HttpRetryQueue.STATS_FILENAME);
125
+ .filter((entry) => entry.endsWith('.json') &&
126
+ entry !== HttpRetryQueue.STATS_FILENAME &&
127
+ !entry.endsWith(HttpRetryQueue.DEAD_LETTER_SUFFIX));
123
128
  }
124
129
  catch {
125
130
  return [];
@@ -135,12 +140,58 @@ class HttpRetryQueue {
135
140
  // Best-effort cleanup
136
141
  }
137
142
  }
143
+ handleSendFailure(filepath, payload, error) {
144
+ const attempts = this.getAttempts(payload);
145
+ const nextAttempts = attempts + 1;
146
+ payload.attempts = nextAttempts;
147
+ payload.updated_at = new Date().toISOString();
148
+ logger_1.logger.warning('HTTP retry queue send failed: %s', error);
149
+ if (nextAttempts >= HttpRetryQueue.MAX_ATTEMPTS) {
150
+ logger_1.logger.warning('HTTP retry queue max attempts reached (%d); moving batch to dead letter.', nextAttempts);
151
+ this.moveToDeadLetter(filepath, payload);
152
+ return;
153
+ }
154
+ this.requeueFile(filepath, payload);
155
+ }
156
+ getAttempts(payload) {
157
+ const attempts = Number(payload.attempts);
158
+ return Number.isFinite(attempts) && attempts >= 0 ? attempts : 0;
159
+ }
160
+ requeueFile(filepath, payload) {
161
+ const tmpPath = `${filepath}.tmp`;
162
+ try {
163
+ fs.writeFileSync(tmpPath, JSON.stringify(payload));
164
+ fs.renameSync(tmpPath, filepath);
165
+ }
166
+ catch (error) {
167
+ logger_1.logger.warning('Failed to requeue HTTP retry batch: %s', error);
168
+ try {
169
+ if (fs.existsSync(tmpPath)) {
170
+ fs.unlinkSync(tmpPath);
171
+ }
172
+ }
173
+ catch {
174
+ return;
175
+ }
176
+ }
177
+ }
178
+ moveToDeadLetter(filepath, payload) {
179
+ const baseName = this.nextFilename().replace(/\.json$/, '');
180
+ const deadPath = path.join(this.queueDir, `${baseName}${HttpRetryQueue.DEAD_LETTER_SUFFIX}`);
181
+ try {
182
+ fs.writeFileSync(deadPath, JSON.stringify(payload));
183
+ this.removeFile(filepath);
184
+ }
185
+ catch (error) {
186
+ logger_1.logger.warning('Failed to move HTTP retry batch to dead letter: %s', error);
187
+ }
188
+ }
138
189
  pruneIfNeeded() {
139
190
  if (this.maxItems <= 0) {
140
191
  return;
141
192
  }
142
193
  const files = this.listFiles();
143
- if (files.length < this.maxItems) {
194
+ if (files.length <= this.maxItems - 1) {
144
195
  return;
145
196
  }
146
197
  const excess = files.length - this.maxItems + 1;
@@ -233,8 +284,18 @@ class HttpRetryQueue {
233
284
  }
234
285
  }
235
286
  HttpRetryQueue.STATS_FILENAME = '.monora_retry_queue_stats.json';
287
+ HttpRetryQueue.DEAD_LETTER_SUFFIX = '.dead.json';
288
+ HttpRetryQueue.MAX_ATTEMPTS = 5;
236
289
  class HttpSink {
237
290
  constructor(endpoint, headers, options) {
291
+ // Enforce data residency before accepting the endpoint
292
+ const residencyConfig = options?.dataResidency || {};
293
+ if (residencyConfig.residency) {
294
+ this.dataResidencyResult = (0, dataResidency_1.enforceDataResidency)(endpoint, residencyConfig.residency, residencyConfig.action || 'warn');
295
+ }
296
+ else {
297
+ this.dataResidencyResult = null;
298
+ }
238
299
  this.endpoint = endpoint;
239
300
  this.headers = headers;
240
301
  this.batchSize = options?.batchSize || 50;
@@ -243,8 +304,13 @@ class HttpSink {
243
304
  this.backoffBaseSec = options?.backoffBaseSec || 0.5;
244
305
  this.buffer = [];
245
306
  this.retryIntervalMs = 5000;
246
- this.idempotencyEnabled = true;
247
- this.idempotencyHeader = 'Idempotency-Key';
307
+ const idempotencyConfig = options?.idempotency;
308
+ this.idempotencyEnabled = idempotencyConfig?.enabled ?? true;
309
+ const headerValue = idempotencyConfig?.header ?? idempotencyConfig?.headerName;
310
+ this.idempotencyHeader =
311
+ headerValue && headerValue.trim().length > 0
312
+ ? headerValue.trim()
313
+ : 'Idempotency-Key';
248
314
  this.flushing = false;
249
315
  // Initialize circuit breaker
250
316
  const cbConfig = options?.circuitBreaker || {};
@@ -273,14 +339,6 @@ class HttpSink {
273
339
  this.retryTimer.unref();
274
340
  }
275
341
  }
276
- const idempotencyConfig = options?.idempotency || {};
277
- if (idempotencyConfig.enabled === false) {
278
- this.idempotencyEnabled = false;
279
- }
280
- const headerName = idempotencyConfig.headerName;
281
- if (headerName && headerName.trim().length > 0) {
282
- this.idempotencyHeader = headerName.trim();
283
- }
284
342
  }
285
343
  emit(events) {
286
344
  this.buffer.push(...events);
@@ -306,8 +364,10 @@ class HttpSink {
306
364
  try {
307
365
  await this.drainRetryQueue();
308
366
  while (this.buffer.length > 0) {
309
- const batch = this.buffer;
310
- this.buffer = [];
367
+ const batch = this.buffer.splice(0);
368
+ if (batch.length === 0) {
369
+ break;
370
+ }
311
371
  try {
312
372
  await this.sendPayload(batch);
313
373
  }
@@ -4,6 +4,7 @@
4
4
  import { Sink } from './base';
5
5
  export declare class StdoutSink implements Sink {
6
6
  private format;
7
+ private quiet;
7
8
  constructor(format?: 'json' | 'pretty');
8
9
  emit(events: Array<Record<string, any>>): void;
9
10
  flush(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"stdout.d.ts","sourceRoot":"","sources":["../../src/sinks/stdout.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,qBAAa,UAAW,YAAW,IAAI;IACrC,OAAO,CAAC,MAAM,CAAoB;gBAEtB,MAAM,GAAE,MAAM,GAAG,QAAiB;IAI9C,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI;IAkB9C,KAAK,IAAI,IAAI;IAIb,KAAK,IAAI,IAAI;CAGd"}
1
+ {"version":3,"file":"stdout.d.ts","sourceRoot":"","sources":["../../src/sinks/stdout.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,qBAAa,UAAW,YAAW,IAAI;IACrC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,KAAK,CAAU;gBAEX,MAAM,GAAE,MAAM,GAAG,QAAmB;IAKhD,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI;IAqB9C,KAAK,IAAI,IAAI;IAIb,KAAK,IAAI,IAAI;CAGd"}