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
package/dist/executiveSummary.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.FRAMEWORK_WEIGHTS = void 0;
|
|
|
42
42
|
exports.getFrameworkWeights = getFrameworkWeights;
|
|
43
43
|
exports.calculateComplianceScore = calculateComplianceScore;
|
|
44
44
|
exports.generateExecutiveSummary = generateExecutiveSummary;
|
|
45
|
+
exports.generateEvidenceMapping = generateEvidenceMapping;
|
|
45
46
|
exports.writeExecutiveSummary = writeExecutiveSummary;
|
|
46
47
|
const fs = __importStar(require("fs"));
|
|
47
48
|
/**
|
|
@@ -189,22 +190,29 @@ function calculateComplianceScore(report, chainStatus, config, framework) {
|
|
|
189
190
|
const weights = getFrameworkWeights(framework);
|
|
190
191
|
let score = 100;
|
|
191
192
|
const breakdown = {};
|
|
193
|
+
const applyAdjustment = (key, intended) => {
|
|
194
|
+
if (intended === 0) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const headroom = 100 - score;
|
|
198
|
+
const floor = 0 - score;
|
|
199
|
+
const applied = intended > 0 ? Math.min(intended, headroom) : Math.max(intended, floor);
|
|
200
|
+
breakdown[key] = applied;
|
|
201
|
+
score += applied;
|
|
202
|
+
};
|
|
192
203
|
// Policy violations
|
|
193
204
|
const violations = report.violations || [];
|
|
194
205
|
const violationCount = violations.length;
|
|
195
206
|
const violationPenalty = Math.min(violationCount * weights.policyViolation, weights.maxPolicyPenalty);
|
|
196
207
|
if (violationPenalty > 0) {
|
|
197
|
-
|
|
198
|
-
score -= violationPenalty;
|
|
208
|
+
applyAdjustment('policy_violations', -violationPenalty);
|
|
199
209
|
}
|
|
200
210
|
// Chain integrity
|
|
201
211
|
if (chainStatus === 'failed') {
|
|
202
|
-
|
|
203
|
-
score -= weights.chainIntegrityFailed;
|
|
212
|
+
applyAdjustment('chain_integrity_failed', -weights.chainIntegrityFailed);
|
|
204
213
|
}
|
|
205
214
|
else if (chainStatus === 'disabled') {
|
|
206
|
-
|
|
207
|
-
score -= weights.chainIntegrityDisabled;
|
|
215
|
+
applyAdjustment('chain_integrity_disabled', -weights.chainIntegrityDisabled);
|
|
208
216
|
}
|
|
209
217
|
else {
|
|
210
218
|
breakdown['chain_integrity_verified'] = 0;
|
|
@@ -212,46 +220,38 @@ function calculateComplianceScore(report, chainStatus, config, framework) {
|
|
|
212
220
|
// Signing
|
|
213
221
|
const signing = config.signing || {};
|
|
214
222
|
if (signing.enabled) {
|
|
215
|
-
|
|
216
|
-
score += weights.signingEnabled;
|
|
223
|
+
applyAdjustment('signing_enabled', weights.signingEnabled);
|
|
217
224
|
}
|
|
218
225
|
else {
|
|
219
|
-
|
|
220
|
-
score -= weights.signingDisabled;
|
|
226
|
+
applyAdjustment('signing_disabled', -weights.signingDisabled);
|
|
221
227
|
}
|
|
222
228
|
// WAL (crash resilience)
|
|
223
229
|
const wal = config.wal || {};
|
|
224
230
|
if (wal.enabled) {
|
|
225
|
-
|
|
226
|
-
score += weights.walEnabled;
|
|
231
|
+
applyAdjustment('wal_enabled', weights.walEnabled);
|
|
227
232
|
}
|
|
228
233
|
else {
|
|
229
|
-
|
|
230
|
-
score -= weights.walDisabled;
|
|
234
|
+
applyAdjustment('wal_disabled', -weights.walDisabled);
|
|
231
235
|
}
|
|
232
236
|
// Unknown models used
|
|
233
237
|
const compliance = report.model_compliance || {};
|
|
234
238
|
const unknownModels = compliance.unknown_models_used || [];
|
|
235
239
|
const unknownPenalty = Math.min(unknownModels.length * weights.unknownModel, weights.maxUnknownPenalty);
|
|
236
240
|
if (unknownPenalty > 0) {
|
|
237
|
-
|
|
238
|
-
score -= unknownPenalty;
|
|
241
|
+
applyAdjustment('unknown_models', -unknownPenalty);
|
|
239
242
|
}
|
|
240
243
|
// Data handling (framework-specific bonus/penalty)
|
|
241
244
|
const dataHandling = config.data_handling || {};
|
|
242
245
|
if (dataHandling.enabled && weights.dataHandlingEnabled > 0) {
|
|
243
|
-
|
|
244
|
-
score += weights.dataHandlingEnabled;
|
|
246
|
+
applyAdjustment('data_handling_enabled', weights.dataHandlingEnabled);
|
|
245
247
|
}
|
|
246
248
|
else if (!dataHandling.enabled && weights.dataHandlingDisabled > 0) {
|
|
247
|
-
|
|
248
|
-
score -= weights.dataHandlingDisabled;
|
|
249
|
+
applyAdjustment('data_handling_disabled', -weights.dataHandlingDisabled);
|
|
249
250
|
}
|
|
250
251
|
// AI Act compliance (framework-specific bonus)
|
|
251
252
|
const aiAct = config.ai_act || {};
|
|
252
253
|
if (aiAct.enabled && weights.aiActEnabled > 0) {
|
|
253
|
-
|
|
254
|
-
score += weights.aiActEnabled;
|
|
254
|
+
applyAdjustment('ai_act_enabled', weights.aiActEnabled);
|
|
255
255
|
}
|
|
256
256
|
// Clamp score to 0-100
|
|
257
257
|
score = Math.max(0, Math.min(100, score));
|
|
@@ -492,6 +492,9 @@ function generateExecutiveSummary(report, events, chainStatus, config, traceId)
|
|
|
492
492
|
}
|
|
493
493
|
}
|
|
494
494
|
lines.push('');
|
|
495
|
+
// Evidence Mapping Section
|
|
496
|
+
const evidenceLines = generateEvidenceSection(events);
|
|
497
|
+
lines.push(...evidenceLines);
|
|
495
498
|
// Footer
|
|
496
499
|
lines.push('---');
|
|
497
500
|
lines.push('');
|
|
@@ -499,6 +502,116 @@ function generateExecutiveSummary(report, events, chainStatus, config, traceId)
|
|
|
499
502
|
lines.push('');
|
|
500
503
|
return lines.join('\n');
|
|
501
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* Evidence mapping for compliance frameworks.
|
|
507
|
+
*/
|
|
508
|
+
const CONTROL_EVENT_MAPPING = {
|
|
509
|
+
soc2: [
|
|
510
|
+
{ controlId: 'CC6.1', controlName: 'Logical Access Controls', eventTypes: ['llm_call', 'tool_call'] },
|
|
511
|
+
{ controlId: 'CC7.2', controlName: 'System Monitoring', eventTypes: ['llm_call', 'tool_call', 'agent_step'] },
|
|
512
|
+
{ controlId: 'CC8.1', controlName: 'Change Management', eventTypes: ['policy_violation'] },
|
|
513
|
+
],
|
|
514
|
+
gdpr: [
|
|
515
|
+
{ controlId: 'Art.5', controlName: 'Data Processing Principles', eventTypes: ['llm_call'] },
|
|
516
|
+
{ controlId: 'Art.25', controlName: 'Data Protection by Design', eventTypes: ['llm_call', 'tool_call'] },
|
|
517
|
+
{ controlId: 'Art.30', controlName: 'Records of Processing', eventTypes: ['llm_call', 'tool_call', 'agent_step'] },
|
|
518
|
+
],
|
|
519
|
+
hipaa: [
|
|
520
|
+
{ controlId: '164.312(b)', controlName: 'Audit Controls', eventTypes: ['llm_call', 'tool_call', 'agent_step'] },
|
|
521
|
+
{ controlId: '164.312(c)', controlName: 'Integrity Controls', eventTypes: ['llm_call'] },
|
|
522
|
+
{ controlId: '164.312(d)', controlName: 'Authentication', eventTypes: ['llm_call', 'tool_call'] },
|
|
523
|
+
],
|
|
524
|
+
ai_act: [
|
|
525
|
+
{ controlId: 'Art.13', controlName: 'Transparency & Disclosure', eventTypes: ['llm_call'] },
|
|
526
|
+
{ controlId: 'Art.14', controlName: 'Human Oversight', eventTypes: ['agent_step', 'tool_call'] },
|
|
527
|
+
{ controlId: 'Art.17', controlName: 'Quality Management', eventTypes: ['llm_call', 'policy_violation'] },
|
|
528
|
+
],
|
|
529
|
+
iso27001: [
|
|
530
|
+
{ controlId: 'A.12.4', controlName: 'Logging and Monitoring', eventTypes: ['llm_call', 'tool_call', 'agent_step'] },
|
|
531
|
+
{ controlId: 'A.12.6', controlName: 'Technical Vulnerability Management', eventTypes: ['policy_violation'] },
|
|
532
|
+
{ controlId: 'A.14.2', controlName: 'Security in Development', eventTypes: ['llm_call', 'tool_call'] },
|
|
533
|
+
],
|
|
534
|
+
iso42001: [
|
|
535
|
+
{ controlId: '6.1.2', controlName: 'AI Risk Assessment', eventTypes: ['llm_call', 'policy_violation'] },
|
|
536
|
+
{ controlId: '8.4', controlName: 'AI System Development', eventTypes: ['llm_call', 'tool_call', 'agent_step'] },
|
|
537
|
+
{ controlId: '9.1', controlName: 'Monitoring & Measurement', eventTypes: ['llm_call', 'tool_call'] },
|
|
538
|
+
],
|
|
539
|
+
};
|
|
540
|
+
/**
|
|
541
|
+
* Generate evidence mapping for compliance controls.
|
|
542
|
+
*/
|
|
543
|
+
function generateEvidenceMapping(events, framework) {
|
|
544
|
+
const evidence = [];
|
|
545
|
+
// Count events by type
|
|
546
|
+
const eventsByType = {};
|
|
547
|
+
for (const event of events) {
|
|
548
|
+
const eventType = event.event_type || 'unknown';
|
|
549
|
+
if (!eventsByType[eventType]) {
|
|
550
|
+
eventsByType[eventType] = [];
|
|
551
|
+
}
|
|
552
|
+
eventsByType[eventType].push(event);
|
|
553
|
+
}
|
|
554
|
+
// Get frameworks to process
|
|
555
|
+
const frameworksToProcess = framework
|
|
556
|
+
? [framework.toLowerCase().replace(/[- ]/g, '_')]
|
|
557
|
+
: Object.keys(CONTROL_EVENT_MAPPING);
|
|
558
|
+
for (const fw of frameworksToProcess) {
|
|
559
|
+
const controls = CONTROL_EVENT_MAPPING[fw];
|
|
560
|
+
if (!controls)
|
|
561
|
+
continue;
|
|
562
|
+
for (const control of controls) {
|
|
563
|
+
let totalCount = 0;
|
|
564
|
+
const sampleIds = [];
|
|
565
|
+
for (const eventType of control.eventTypes) {
|
|
566
|
+
const matchingEvents = eventsByType[eventType] || [];
|
|
567
|
+
totalCount += matchingEvents.length;
|
|
568
|
+
// Collect sample event IDs (up to 3 per control)
|
|
569
|
+
for (const evt of matchingEvents.slice(0, 3 - sampleIds.length)) {
|
|
570
|
+
if (evt.event_id && sampleIds.length < 3) {
|
|
571
|
+
sampleIds.push(evt.event_id);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if (totalCount > 0) {
|
|
576
|
+
evidence.push({
|
|
577
|
+
controlId: control.controlId,
|
|
578
|
+
controlName: control.controlName,
|
|
579
|
+
framework: fw.toUpperCase().replace(/_/g, ' '),
|
|
580
|
+
eventTypes: control.eventTypes,
|
|
581
|
+
eventCount: totalCount,
|
|
582
|
+
sampleEventIds: sampleIds,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return evidence;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Generate evidence section for executive summary.
|
|
591
|
+
*/
|
|
592
|
+
function generateEvidenceSection(events, framework) {
|
|
593
|
+
const lines = [];
|
|
594
|
+
const evidence = generateEvidenceMapping(events, framework);
|
|
595
|
+
if (evidence.length === 0) {
|
|
596
|
+
return lines;
|
|
597
|
+
}
|
|
598
|
+
lines.push('---');
|
|
599
|
+
lines.push('');
|
|
600
|
+
lines.push('## Compliance Evidence Mapping');
|
|
601
|
+
lines.push('');
|
|
602
|
+
lines.push('Events linked to specific compliance controls:');
|
|
603
|
+
lines.push('');
|
|
604
|
+
lines.push('| Framework | Control ID | Control Name | Events | Sample IDs |');
|
|
605
|
+
lines.push('|-----------|------------|--------------|--------|------------|');
|
|
606
|
+
for (const item of evidence) {
|
|
607
|
+
const sampleIds = item.sampleEventIds.length > 0
|
|
608
|
+
? item.sampleEventIds.map(id => `\`${id.slice(0, 12)}...\``).join(', ')
|
|
609
|
+
: '-';
|
|
610
|
+
lines.push(`| ${item.framework} | ${item.controlId} | ${item.controlName} | ${item.eventCount} | ${sampleIds} |`);
|
|
611
|
+
}
|
|
612
|
+
lines.push('');
|
|
613
|
+
return lines;
|
|
614
|
+
}
|
|
502
615
|
/**
|
|
503
616
|
* Write executive summary to a file.
|
|
504
617
|
*/
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User/identity tracking for SOC 2 CC6 access control compliance.
|
|
3
|
+
*
|
|
4
|
+
* This module provides identity context management for tracking who invoked
|
|
5
|
+
* each AI call, supporting SOC 2 access control audit trails.
|
|
6
|
+
*
|
|
7
|
+
* Cross-SDK Parity:
|
|
8
|
+
* Both Python and Node.js SDKs provide identical identity tracking APIs:
|
|
9
|
+
* - setIdentity() / set_identity()
|
|
10
|
+
* - getIdentity() / get_identity()
|
|
11
|
+
* - clearIdentity() / clear_identity()
|
|
12
|
+
* - withIdentity() / identity_context()
|
|
13
|
+
*/
|
|
14
|
+
import { MonoraConfig } from './config';
|
|
15
|
+
/**
|
|
16
|
+
* Represents a user/system identity for audit tracking.
|
|
17
|
+
*/
|
|
18
|
+
export interface Identity {
|
|
19
|
+
/** Unique identifier for the user (required if identity.require_user_id is True). */
|
|
20
|
+
userId: string;
|
|
21
|
+
/** Optional session identifier for grouping related calls. */
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
/** Authentication method used (oauth2, api_key, jwt, etc.). */
|
|
24
|
+
authMethod?: string;
|
|
25
|
+
/** List of roles assigned to the user. */
|
|
26
|
+
roles?: string[];
|
|
27
|
+
/** Organization identifier for multi-tenant systems. */
|
|
28
|
+
orgId?: string;
|
|
29
|
+
/** Additional custom identity metadata. */
|
|
30
|
+
metadata?: Record<string, any>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Options for converting identity to dict.
|
|
34
|
+
*/
|
|
35
|
+
export interface IdentityToDictOptions {
|
|
36
|
+
/** Include roles array in output. */
|
|
37
|
+
includeRoles?: boolean;
|
|
38
|
+
/** Include org_id in output. */
|
|
39
|
+
includeOrg?: boolean;
|
|
40
|
+
/** Hash user_id for privacy (SHA-256). */
|
|
41
|
+
redactUserId?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Convert identity to dictionary for event inclusion.
|
|
45
|
+
*
|
|
46
|
+
* @param identity - The identity object.
|
|
47
|
+
* @param options - Conversion options.
|
|
48
|
+
* @returns Dictionary representation of identity.
|
|
49
|
+
*/
|
|
50
|
+
export declare function identityToDict(identity: Identity, options?: IdentityToDictOptions): Record<string, any>;
|
|
51
|
+
/**
|
|
52
|
+
* Set the current identity context.
|
|
53
|
+
*
|
|
54
|
+
* All subsequent events will include this identity information until
|
|
55
|
+
* clearIdentity() is called or the context exits.
|
|
56
|
+
*
|
|
57
|
+
* Note: This sets identity in the current async context. For scoped identity,
|
|
58
|
+
* use withIdentity() instead.
|
|
59
|
+
*
|
|
60
|
+
* @param identity - The identity to set.
|
|
61
|
+
* @returns The identity object.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* setIdentity({ userId: 'usr_123', sessionId: 'sess_456', roles: ['admin'] });
|
|
66
|
+
* // All subsequent AI calls will include identity
|
|
67
|
+
* await llmCall(...);
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function setIdentity(identity: Identity): Identity;
|
|
71
|
+
/**
|
|
72
|
+
* Get the current identity from context.
|
|
73
|
+
*
|
|
74
|
+
* @returns The current Identity object, or undefined if not set.
|
|
75
|
+
*/
|
|
76
|
+
export declare function getIdentity(): Identity | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Clear the current identity context.
|
|
79
|
+
*/
|
|
80
|
+
export declare function clearIdentity(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Run a function within a specific identity context.
|
|
83
|
+
*
|
|
84
|
+
* The identity is automatically cleared when the function completes.
|
|
85
|
+
*
|
|
86
|
+
* @param identity - The identity to use.
|
|
87
|
+
* @param fn - The function to execute.
|
|
88
|
+
* @returns The result of the function.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* await withIdentity({ userId: 'usr_789', roles: ['analyst'] }, async () => {
|
|
93
|
+
* await llmCall(...); // Includes identity
|
|
94
|
+
* });
|
|
95
|
+
* // Identity cleared after function completes
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare function withIdentity<T>(identity: Identity, fn: () => T): T;
|
|
99
|
+
/**
|
|
100
|
+
* Async version of withIdentity for async functions.
|
|
101
|
+
*
|
|
102
|
+
* @param identity - The identity to use.
|
|
103
|
+
* @param fn - The async function to execute.
|
|
104
|
+
* @returns Promise resolving to the result of the function.
|
|
105
|
+
*/
|
|
106
|
+
export declare function withIdentityAsync<T>(identity: Identity, fn: () => Promise<T>): Promise<T>;
|
|
107
|
+
/**
|
|
108
|
+
* Bind a function to the current identity context.
|
|
109
|
+
*
|
|
110
|
+
* The returned function, when called, will execute with the captured
|
|
111
|
+
* identity context regardless of where it's called from.
|
|
112
|
+
*
|
|
113
|
+
* @param fn - The function to bind to the current identity.
|
|
114
|
+
* @returns A wrapped function that will execute with the captured identity.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* setIdentity({ userId: 'usr_123' });
|
|
119
|
+
* const boundCallback = bindIdentity(myCallback);
|
|
120
|
+
* // Call from anywhere - identity is preserved
|
|
121
|
+
* boundCallback();
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export declare function bindIdentity<T extends (...args: any[]) => any>(fn: T): T;
|
|
125
|
+
/**
|
|
126
|
+
* Get identity dict for event inclusion based on config.
|
|
127
|
+
*
|
|
128
|
+
* This is called internally when building events to include identity
|
|
129
|
+
* information according to the configuration settings.
|
|
130
|
+
*
|
|
131
|
+
* @param config - The Monora configuration.
|
|
132
|
+
* @returns Identity dict for event inclusion, or undefined if identity not set
|
|
133
|
+
* or identity tracking is disabled.
|
|
134
|
+
*/
|
|
135
|
+
export declare function getIdentityForEvent(config: MonoraConfig): Record<string, any> | undefined;
|
|
136
|
+
/**
|
|
137
|
+
* Validate that identity is set if required by config.
|
|
138
|
+
*
|
|
139
|
+
* @param config - The Monora configuration.
|
|
140
|
+
* @throws Error if require_user_id is true but no identity is set.
|
|
141
|
+
*/
|
|
142
|
+
export declare function validateIdentityRequirement(config: MonoraConfig): void;
|
|
143
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qCAAqC;IACrC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gCAAgC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAgCrB;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAIxD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,QAAQ,GAAG,SAAS,CAElD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAElE;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,QAAQ,EAAE,QAAQ,EAClB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAQxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,GACnB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAgBjC;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAetE"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* User/identity tracking for SOC 2 CC6 access control compliance.
|
|
4
|
+
*
|
|
5
|
+
* This module provides identity context management for tracking who invoked
|
|
6
|
+
* each AI call, supporting SOC 2 access control audit trails.
|
|
7
|
+
*
|
|
8
|
+
* Cross-SDK Parity:
|
|
9
|
+
* Both Python and Node.js SDKs provide identical identity tracking APIs:
|
|
10
|
+
* - setIdentity() / set_identity()
|
|
11
|
+
* - getIdentity() / get_identity()
|
|
12
|
+
* - clearIdentity() / clear_identity()
|
|
13
|
+
* - withIdentity() / identity_context()
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.identityToDict = identityToDict;
|
|
50
|
+
exports.setIdentity = setIdentity;
|
|
51
|
+
exports.getIdentity = getIdentity;
|
|
52
|
+
exports.clearIdentity = clearIdentity;
|
|
53
|
+
exports.withIdentity = withIdentity;
|
|
54
|
+
exports.withIdentityAsync = withIdentityAsync;
|
|
55
|
+
exports.bindIdentity = bindIdentity;
|
|
56
|
+
exports.getIdentityForEvent = getIdentityForEvent;
|
|
57
|
+
exports.validateIdentityRequirement = validateIdentityRequirement;
|
|
58
|
+
const async_hooks_1 = require("async_hooks");
|
|
59
|
+
const crypto = __importStar(require("crypto"));
|
|
60
|
+
/**
|
|
61
|
+
* Convert identity to dictionary for event inclusion.
|
|
62
|
+
*
|
|
63
|
+
* @param identity - The identity object.
|
|
64
|
+
* @param options - Conversion options.
|
|
65
|
+
* @returns Dictionary representation of identity.
|
|
66
|
+
*/
|
|
67
|
+
function identityToDict(identity, options = {}) {
|
|
68
|
+
const { includeRoles = true, includeOrg = true, redactUserId = false } = options;
|
|
69
|
+
let userIdValue = identity.userId;
|
|
70
|
+
if (redactUserId && userIdValue) {
|
|
71
|
+
const hash = crypto.createHash('sha256').update(userIdValue).digest('hex');
|
|
72
|
+
userIdValue = `sha256:${hash.slice(0, 16)}`;
|
|
73
|
+
}
|
|
74
|
+
const result = { user_id: userIdValue };
|
|
75
|
+
if (identity.sessionId) {
|
|
76
|
+
result.session_id = identity.sessionId;
|
|
77
|
+
}
|
|
78
|
+
if (identity.authMethod) {
|
|
79
|
+
result.auth_method = identity.authMethod;
|
|
80
|
+
}
|
|
81
|
+
if (includeRoles && identity.roles && identity.roles.length > 0) {
|
|
82
|
+
result.roles = identity.roles;
|
|
83
|
+
}
|
|
84
|
+
if (includeOrg && identity.orgId) {
|
|
85
|
+
result.org_id = identity.orgId;
|
|
86
|
+
}
|
|
87
|
+
if (identity.metadata && Object.keys(identity.metadata).length > 0) {
|
|
88
|
+
result.metadata = identity.metadata;
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
// AsyncLocalStorage for identity context propagation
|
|
93
|
+
const identityStorage = new async_hooks_1.AsyncLocalStorage();
|
|
94
|
+
/**
|
|
95
|
+
* Set the current identity context.
|
|
96
|
+
*
|
|
97
|
+
* All subsequent events will include this identity information until
|
|
98
|
+
* clearIdentity() is called or the context exits.
|
|
99
|
+
*
|
|
100
|
+
* Note: This sets identity in the current async context. For scoped identity,
|
|
101
|
+
* use withIdentity() instead.
|
|
102
|
+
*
|
|
103
|
+
* @param identity - The identity to set.
|
|
104
|
+
* @returns The identity object.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* setIdentity({ userId: 'usr_123', sessionId: 'sess_456', roles: ['admin'] });
|
|
109
|
+
* // All subsequent AI calls will include identity
|
|
110
|
+
* await llmCall(...);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
function setIdentity(identity) {
|
|
114
|
+
// Note: AsyncLocalStorage.enterWith() sets the store for the current execution context
|
|
115
|
+
identityStorage.enterWith(identity);
|
|
116
|
+
return identity;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get the current identity from context.
|
|
120
|
+
*
|
|
121
|
+
* @returns The current Identity object, or undefined if not set.
|
|
122
|
+
*/
|
|
123
|
+
function getIdentity() {
|
|
124
|
+
return identityStorage.getStore();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Clear the current identity context.
|
|
128
|
+
*/
|
|
129
|
+
function clearIdentity() {
|
|
130
|
+
identityStorage.enterWith(undefined);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Run a function within a specific identity context.
|
|
134
|
+
*
|
|
135
|
+
* The identity is automatically cleared when the function completes.
|
|
136
|
+
*
|
|
137
|
+
* @param identity - The identity to use.
|
|
138
|
+
* @param fn - The function to execute.
|
|
139
|
+
* @returns The result of the function.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* await withIdentity({ userId: 'usr_789', roles: ['analyst'] }, async () => {
|
|
144
|
+
* await llmCall(...); // Includes identity
|
|
145
|
+
* });
|
|
146
|
+
* // Identity cleared after function completes
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
function withIdentity(identity, fn) {
|
|
150
|
+
return identityStorage.run(identity, fn);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Async version of withIdentity for async functions.
|
|
154
|
+
*
|
|
155
|
+
* @param identity - The identity to use.
|
|
156
|
+
* @param fn - The async function to execute.
|
|
157
|
+
* @returns Promise resolving to the result of the function.
|
|
158
|
+
*/
|
|
159
|
+
async function withIdentityAsync(identity, fn) {
|
|
160
|
+
return identityStorage.run(identity, fn);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Bind a function to the current identity context.
|
|
164
|
+
*
|
|
165
|
+
* The returned function, when called, will execute with the captured
|
|
166
|
+
* identity context regardless of where it's called from.
|
|
167
|
+
*
|
|
168
|
+
* @param fn - The function to bind to the current identity.
|
|
169
|
+
* @returns A wrapped function that will execute with the captured identity.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* setIdentity({ userId: 'usr_123' });
|
|
174
|
+
* const boundCallback = bindIdentity(myCallback);
|
|
175
|
+
* // Call from anywhere - identity is preserved
|
|
176
|
+
* boundCallback();
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
function bindIdentity(fn) {
|
|
180
|
+
const captured = identityStorage.getStore();
|
|
181
|
+
if (!captured) {
|
|
182
|
+
return fn;
|
|
183
|
+
}
|
|
184
|
+
return ((...args) => {
|
|
185
|
+
return identityStorage.run(captured, () => fn(...args));
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get identity dict for event inclusion based on config.
|
|
190
|
+
*
|
|
191
|
+
* This is called internally when building events to include identity
|
|
192
|
+
* information according to the configuration settings.
|
|
193
|
+
*
|
|
194
|
+
* @param config - The Monora configuration.
|
|
195
|
+
* @returns Identity dict for event inclusion, or undefined if identity not set
|
|
196
|
+
* or identity tracking is disabled.
|
|
197
|
+
*/
|
|
198
|
+
function getIdentityForEvent(config) {
|
|
199
|
+
const identityConfig = config.identity;
|
|
200
|
+
if (!identityConfig?.enabled) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const identity = getIdentity();
|
|
204
|
+
if (!identity) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return identityToDict(identity, {
|
|
208
|
+
includeRoles: identityConfig.capture_roles ?? false,
|
|
209
|
+
includeOrg: identityConfig.capture_org ?? false,
|
|
210
|
+
redactUserId: identityConfig.redact_user_id ?? false,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Validate that identity is set if required by config.
|
|
215
|
+
*
|
|
216
|
+
* @param config - The Monora configuration.
|
|
217
|
+
* @throws Error if require_user_id is true but no identity is set.
|
|
218
|
+
*/
|
|
219
|
+
function validateIdentityRequirement(config) {
|
|
220
|
+
const identityConfig = config.identity;
|
|
221
|
+
if (!identityConfig?.enabled) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (identityConfig.require_user_id) {
|
|
225
|
+
const identity = getIdentity();
|
|
226
|
+
if (!identity) {
|
|
227
|
+
throw new Error('Identity is required but not set. ' +
|
|
228
|
+
'Use setIdentity() or withIdentity() before making AI calls.');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|