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.
- package/README.md +333 -159
- package/dist/aims_governance.d.ts +238 -0
- package/dist/aims_governance.d.ts.map +1 -0
- package/dist/aims_governance.js +922 -0
- package/dist/alerts.d.ts +16 -0
- package/dist/alerts.d.ts.map +1 -1
- package/dist/alerts.js +16 -0
- package/dist/api.d.ts +6 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -0
- package/dist/assessment.d.ts +85 -0
- package/dist/assessment.d.ts.map +1 -1
- package/dist/assessment.js +506 -13
- package/dist/attribution.d.ts +44 -3
- package/dist/attribution.d.ts.map +1 -1
- package/dist/attribution.js +197 -10
- package/dist/autodetect.d.ts +68 -0
- package/dist/autodetect.d.ts.map +1 -1
- package/dist/autodetect.js +639 -0
- package/dist/bias.d.ts +130 -0
- package/dist/bias.d.ts.map +1 -0
- package/dist/bias.js +223 -0
- package/dist/cli/diagnostics.d.ts +5 -1
- package/dist/cli/diagnostics.d.ts.map +1 -1
- package/dist/cli/diagnostics.js +23 -6
- package/dist/cli/doctor.d.ts +25 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +381 -0
- package/dist/cli/fix.d.ts +16 -0
- package/dist/cli/fix.d.ts.map +1 -0
- package/dist/cli/fix.js +284 -0
- package/dist/cli/init.d.ts +57 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +205 -0
- package/dist/cli.js +1550 -176
- package/dist/complianceTargets.d.ts +111 -0
- package/dist/complianceTargets.d.ts.map +1 -0
- package/dist/complianceTargets.js +521 -0
- package/dist/config.d.ts +261 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +381 -32
- package/dist/config_migrations.d.ts.map +1 -1
- package/dist/config_migrations.js +38 -1
- package/dist/config_schema.d.ts +2490 -1035
- package/dist/config_schema.d.ts.map +1 -1
- package/dist/config_schema.js +233 -64
- package/dist/context.d.ts +34 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +118 -7
- package/dist/control_backbone.d.ts +122 -0
- package/dist/control_backbone.d.ts.map +1 -0
- package/dist/control_backbone.js +698 -0
- package/dist/data-governance.d.ts +187 -0
- package/dist/data-governance.d.ts.map +1 -0
- package/dist/data-governance.js +424 -0
- package/dist/dataResidency.d.ts +44 -0
- package/dist/dataResidency.d.ts.map +1 -0
- package/dist/dataResidency.js +203 -0
- package/dist/dispatcher.d.ts.map +1 -1
- package/dist/dispatcher.js +17 -5
- package/dist/evidence_store.d.ts +103 -0
- package/dist/evidence_store.d.ts.map +1 -0
- package/dist/evidence_store.js +459 -0
- package/dist/executiveSummary.d.ts +15 -0
- package/dist/executiveSummary.d.ts.map +1 -1
- package/dist/executiveSummary.js +135 -22
- package/dist/identity.d.ts +143 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +231 -0
- package/dist/impact-assessment.d.ts +350 -0
- package/dist/impact-assessment.d.ts.map +1 -0
- package/dist/impact-assessment.js +580 -0
- package/dist/index.d.ts +20 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +247 -5
- package/dist/instrumentation.d.ts +1 -1
- package/dist/instrumentation.d.ts.map +1 -1
- package/dist/instrumentation.js +123 -22
- package/dist/integrations/anthropic.d.ts +3 -0
- package/dist/integrations/anthropic.d.ts.map +1 -1
- package/dist/integrations/anthropic.js +282 -80
- package/dist/integrations/governance.d.ts +33 -0
- package/dist/integrations/governance.d.ts.map +1 -0
- package/dist/integrations/governance.js +208 -0
- package/dist/integrations/langchain.d.ts +4 -0
- package/dist/integrations/langchain.d.ts.map +1 -1
- package/dist/integrations/langchain.js +362 -142
- package/dist/integrations/openai.d.ts +9 -0
- package/dist/integrations/openai.d.ts.map +1 -1
- package/dist/integrations/openai.js +673 -73
- package/dist/iso42001_consolidation.d.ts +16 -0
- package/dist/iso42001_consolidation.d.ts.map +1 -0
- package/dist/iso42001_consolidation.js +413 -0
- package/dist/iso42001_workflows.d.ts +263 -0
- package/dist/iso42001_workflows.d.ts.map +1 -0
- package/dist/iso42001_workflows.js +781 -0
- package/dist/lifecycle.d.ts +299 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +624 -0
- package/dist/lineage.d.ts +2 -2
- package/dist/lineage.d.ts.map +1 -1
- package/dist/lineage.js +9 -16
- package/dist/middleware/express.d.ts.map +1 -1
- package/dist/middleware/express.js +18 -3
- package/dist/middleware/nextjs.js +2 -2
- package/dist/model.d.ts +143 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +371 -0
- package/dist/onboarding.d.ts +42 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +1022 -0
- package/dist/oversight.d.ts +264 -0
- package/dist/oversight.d.ts.map +1 -0
- package/dist/oversight.js +497 -0
- package/dist/presets.js +7 -7
- package/dist/quotas.d.ts +171 -0
- package/dist/quotas.d.ts.map +1 -0
- package/dist/quotas.js +259 -0
- package/dist/register.d.ts +13 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +99 -0
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +7 -0
- package/dist/registryData.json +43 -6
- package/dist/report.d.ts +2 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +189 -2
- package/dist/reporting.d.ts +125 -0
- package/dist/reporting.d.ts.map +1 -1
- package/dist/reporting.js +192 -2
- package/dist/resources.d.ts +285 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +643 -0
- package/dist/risk.d.ts +120 -0
- package/dist/risk.d.ts.map +1 -0
- package/dist/risk.js +220 -0
- package/dist/runtime.d.ts +73 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +415 -18
- package/dist/schemaInference.d.ts +92 -0
- package/dist/schemaInference.d.ts.map +1 -0
- package/dist/schemaInference.js +466 -0
- package/dist/schema_validation.js +2 -2
- package/dist/schemas/config.schema.json +118 -4
- package/dist/security_report.js +4 -4
- package/dist/signing.d.ts +1 -1
- package/dist/signing.d.ts.map +1 -1
- package/dist/signing.js +4 -0
- package/dist/sinks/file.d.ts +19 -1
- package/dist/sinks/file.d.ts.map +1 -1
- package/dist/sinks/file.js +82 -13
- package/dist/sinks/https.d.ts +10 -0
- package/dist/sinks/https.d.ts.map +1 -1
- package/dist/sinks/https.js +76 -16
- package/dist/sinks/stdout.d.ts +1 -0
- package/dist/sinks/stdout.d.ts.map +1 -1
- package/dist/sinks/stdout.js +12 -1
- package/dist/spec.d.ts +159 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +391 -0
- package/dist/stakeholders.d.ts +199 -0
- package/dist/stakeholders.d.ts.map +1 -0
- package/dist/stakeholders.js +398 -0
- package/dist/standards.d.ts.map +1 -1
- package/dist/standards.js +160 -2
- package/dist/standards_ingest.d.ts.map +1 -1
- package/dist/standards_ingest.js +1 -4
- package/dist/telemetry.d.ts +16 -2
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +77 -14
- package/dist/templates/controls/iso42001_control_catalog.json +1443 -0
- package/dist/traced_emitter.d.ts.map +1 -1
- package/dist/traced_emitter.js +19 -9
- package/dist/trust_package.d.ts +19 -1
- package/dist/trust_package.d.ts.map +1 -1
- package/dist/trust_package.js +89 -2
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +9 -2
- package/dist/wal.d.ts.map +1 -1
- package/dist/wal.js +2 -1
- package/package.json +14 -1
- package/scripts/postinstall.js +105 -210
- 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"], "
|
|
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,
|
package/dist/security_report.js
CHANGED
|
@@ -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
package/dist/signing.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
package/dist/sinks/file.d.ts
CHANGED
|
@@ -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
|
|
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
|
}
|
package/dist/sinks/file.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/sinks/file.ts"],"names":[],"mappings":"AAAA
|
|
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"}
|
package/dist/sinks/file.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
99
|
-
const stats = fs.statSync(this.
|
|
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.
|
|
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.
|
|
113
|
-
const basename = path.basename(this.
|
|
114
|
-
const dirname = path.dirname(this.
|
|
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.
|
|
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
|
-
|
|
125
|
-
const
|
|
126
|
-
const
|
|
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() {
|
package/dist/sinks/https.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/sinks/https.js
CHANGED
|
@@ -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
|
-
|
|
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') &&
|
|
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
|
|
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
|
-
|
|
247
|
-
this.
|
|
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
|
-
|
|
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
|
}
|
package/dist/sinks/stdout.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|