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
@@ -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
- breakdown['policy_violations'] = -violationPenalty;
198
- score -= violationPenalty;
208
+ applyAdjustment('policy_violations', -violationPenalty);
199
209
  }
200
210
  // Chain integrity
201
211
  if (chainStatus === 'failed') {
202
- breakdown['chain_integrity_failed'] = -weights.chainIntegrityFailed;
203
- score -= weights.chainIntegrityFailed;
212
+ applyAdjustment('chain_integrity_failed', -weights.chainIntegrityFailed);
204
213
  }
205
214
  else if (chainStatus === 'disabled') {
206
- breakdown['chain_integrity_disabled'] = -weights.chainIntegrityDisabled;
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
- breakdown['signing_enabled'] = weights.signingEnabled;
216
- score += weights.signingEnabled;
223
+ applyAdjustment('signing_enabled', weights.signingEnabled);
217
224
  }
218
225
  else {
219
- breakdown['signing_disabled'] = -weights.signingDisabled;
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
- breakdown['wal_enabled'] = weights.walEnabled;
226
- score += weights.walEnabled;
231
+ applyAdjustment('wal_enabled', weights.walEnabled);
227
232
  }
228
233
  else {
229
- breakdown['wal_disabled'] = -weights.walDisabled;
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
- breakdown['unknown_models'] = -unknownPenalty;
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
- breakdown['data_handling_enabled'] = weights.dataHandlingEnabled;
244
- score += weights.dataHandlingEnabled;
246
+ applyAdjustment('data_handling_enabled', weights.dataHandlingEnabled);
245
247
  }
246
248
  else if (!dataHandling.enabled && weights.dataHandlingDisabled > 0) {
247
- breakdown['data_handling_disabled'] = -weights.dataHandlingDisabled;
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
- breakdown['ai_act_enabled'] = weights.aiActEnabled;
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"}
@@ -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
+ }