monora-ai 2.0.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 (202) hide show
  1. package/README.md +441 -150
  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 +269 -0
  12. package/dist/assessment.d.ts.map +1 -0
  13. package/dist/assessment.js +1232 -0
  14. package/dist/attestation.js +23 -1
  15. package/dist/attribution.d.ts +349 -0
  16. package/dist/attribution.d.ts.map +1 -0
  17. package/dist/attribution.js +987 -0
  18. package/dist/autodetect.d.ts +69 -1
  19. package/dist/autodetect.d.ts.map +1 -1
  20. package/dist/autodetect.js +644 -1
  21. package/dist/bias.d.ts +130 -0
  22. package/dist/bias.d.ts.map +1 -0
  23. package/dist/bias.js +223 -0
  24. package/dist/circuit_breaker.js +3 -3
  25. package/dist/cli/diagnostics.d.ts +5 -1
  26. package/dist/cli/diagnostics.d.ts.map +1 -1
  27. package/dist/cli/diagnostics.js +31 -8
  28. package/dist/cli/doctor.d.ts +25 -0
  29. package/dist/cli/doctor.d.ts.map +1 -0
  30. package/dist/cli/doctor.js +381 -0
  31. package/dist/cli/fix.d.ts +16 -0
  32. package/dist/cli/fix.d.ts.map +1 -0
  33. package/dist/cli/fix.js +284 -0
  34. package/dist/cli/init.d.ts +57 -0
  35. package/dist/cli/init.d.ts.map +1 -0
  36. package/dist/cli/init.js +205 -0
  37. package/dist/cli.js +1611 -126
  38. package/dist/complianceTargets.d.ts +111 -0
  39. package/dist/complianceTargets.d.ts.map +1 -0
  40. package/dist/complianceTargets.js +521 -0
  41. package/dist/config.d.ts +301 -17
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/config.js +428 -36
  44. package/dist/config_migrations.d.ts +41 -0
  45. package/dist/config_migrations.d.ts.map +1 -1
  46. package/dist/config_migrations.js +205 -0
  47. package/dist/config_schema.d.ts +2900 -731
  48. package/dist/config_schema.d.ts.map +1 -1
  49. package/dist/config_schema.js +257 -55
  50. package/dist/context.d.ts +34 -0
  51. package/dist/context.d.ts.map +1 -1
  52. package/dist/context.js +118 -7
  53. package/dist/control_backbone.d.ts +122 -0
  54. package/dist/control_backbone.d.ts.map +1 -0
  55. package/dist/control_backbone.js +698 -0
  56. package/dist/data-governance.d.ts +187 -0
  57. package/dist/data-governance.d.ts.map +1 -0
  58. package/dist/data-governance.js +424 -0
  59. package/dist/dataResidency.d.ts +44 -0
  60. package/dist/dataResidency.d.ts.map +1 -0
  61. package/dist/dataResidency.js +203 -0
  62. package/dist/dispatcher.d.ts +32 -0
  63. package/dist/dispatcher.d.ts.map +1 -1
  64. package/dist/dispatcher.js +91 -4
  65. package/dist/events.d.ts.map +1 -1
  66. package/dist/events.js +38 -0
  67. package/dist/evidence_store.d.ts +103 -0
  68. package/dist/evidence_store.d.ts.map +1 -0
  69. package/dist/evidence_store.js +459 -0
  70. package/dist/executiveSummary.d.ts +65 -8
  71. package/dist/executiveSummary.d.ts.map +1 -1
  72. package/dist/executiveSummary.js +289 -26
  73. package/dist/identity.d.ts +143 -0
  74. package/dist/identity.d.ts.map +1 -0
  75. package/dist/identity.js +231 -0
  76. package/dist/impact-assessment.d.ts +350 -0
  77. package/dist/impact-assessment.d.ts.map +1 -0
  78. package/dist/impact-assessment.js +580 -0
  79. package/dist/index.d.ts +25 -5
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +300 -4
  82. package/dist/instrumentation.d.ts +1 -1
  83. package/dist/instrumentation.d.ts.map +1 -1
  84. package/dist/instrumentation.js +243 -27
  85. package/dist/integrations/anthropic.d.ts +3 -0
  86. package/dist/integrations/anthropic.d.ts.map +1 -1
  87. package/dist/integrations/anthropic.js +284 -79
  88. package/dist/integrations/governance.d.ts +33 -0
  89. package/dist/integrations/governance.d.ts.map +1 -0
  90. package/dist/integrations/governance.js +208 -0
  91. package/dist/integrations/langchain.d.ts +7 -0
  92. package/dist/integrations/langchain.d.ts.map +1 -1
  93. package/dist/integrations/langchain.js +387 -143
  94. package/dist/integrations/openai.d.ts +9 -0
  95. package/dist/integrations/openai.d.ts.map +1 -1
  96. package/dist/integrations/openai.js +673 -73
  97. package/dist/iso42001_consolidation.d.ts +16 -0
  98. package/dist/iso42001_consolidation.d.ts.map +1 -0
  99. package/dist/iso42001_consolidation.js +413 -0
  100. package/dist/iso42001_workflows.d.ts +263 -0
  101. package/dist/iso42001_workflows.d.ts.map +1 -0
  102. package/dist/iso42001_workflows.js +781 -0
  103. package/dist/lifecycle.d.ts +299 -0
  104. package/dist/lifecycle.d.ts.map +1 -0
  105. package/dist/lifecycle.js +624 -0
  106. package/dist/lineage.d.ts +2 -2
  107. package/dist/lineage.d.ts.map +1 -1
  108. package/dist/lineage.js +12 -17
  109. package/dist/middleware/express.d.ts.map +1 -1
  110. package/dist/middleware/express.js +33 -3
  111. package/dist/middleware/nextjs.d.ts.map +1 -1
  112. package/dist/middleware/nextjs.js +42 -68
  113. package/dist/model.d.ts +143 -0
  114. package/dist/model.d.ts.map +1 -0
  115. package/dist/model.js +371 -0
  116. package/dist/onboarding.d.ts +42 -0
  117. package/dist/onboarding.d.ts.map +1 -0
  118. package/dist/onboarding.js +1022 -0
  119. package/dist/oversight.d.ts +264 -0
  120. package/dist/oversight.d.ts.map +1 -0
  121. package/dist/oversight.js +497 -0
  122. package/dist/pdf_report.d.ts.map +1 -1
  123. package/dist/pdf_report.js +42 -21
  124. package/dist/presets.d.ts +88 -0
  125. package/dist/presets.d.ts.map +1 -0
  126. package/dist/presets.js +520 -0
  127. package/dist/propagation.d.ts.map +1 -1
  128. package/dist/propagation.js +34 -2
  129. package/dist/quotas.d.ts +171 -0
  130. package/dist/quotas.d.ts.map +1 -0
  131. package/dist/quotas.js +259 -0
  132. package/dist/register.d.ts +13 -0
  133. package/dist/register.d.ts.map +1 -0
  134. package/dist/register.js +99 -0
  135. package/dist/registry.d.ts +1 -0
  136. package/dist/registry.d.ts.map +1 -1
  137. package/dist/registry.js +7 -0
  138. package/dist/registryData.json +43 -6
  139. package/dist/report.d.ts +2 -1
  140. package/dist/report.d.ts.map +1 -1
  141. package/dist/report.js +189 -2
  142. package/dist/reporting.d.ts +125 -0
  143. package/dist/reporting.d.ts.map +1 -1
  144. package/dist/reporting.js +196 -5
  145. package/dist/resources.d.ts +285 -0
  146. package/dist/resources.d.ts.map +1 -0
  147. package/dist/resources.js +643 -0
  148. package/dist/risk.d.ts +120 -0
  149. package/dist/risk.d.ts.map +1 -0
  150. package/dist/risk.js +220 -0
  151. package/dist/runtime.d.ts +74 -1
  152. package/dist/runtime.d.ts.map +1 -1
  153. package/dist/runtime.js +598 -22
  154. package/dist/schemaInference.d.ts +92 -0
  155. package/dist/schemaInference.d.ts.map +1 -0
  156. package/dist/schemaInference.js +466 -0
  157. package/dist/schema_validation.js +2 -2
  158. package/dist/schemas/config.schema.json +169 -6
  159. package/dist/schemas/event.schema.json +4 -0
  160. package/dist/security_report.js +4 -4
  161. package/dist/signing.d.ts +1 -1
  162. package/dist/signing.d.ts.map +1 -1
  163. package/dist/signing.js +4 -0
  164. package/dist/sinks/file.d.ts +19 -1
  165. package/dist/sinks/file.d.ts.map +1 -1
  166. package/dist/sinks/file.js +82 -13
  167. package/dist/sinks/https.d.ts +10 -0
  168. package/dist/sinks/https.d.ts.map +1 -1
  169. package/dist/sinks/https.js +76 -16
  170. package/dist/sinks/stdout.d.ts +1 -0
  171. package/dist/sinks/stdout.d.ts.map +1 -1
  172. package/dist/sinks/stdout.js +12 -1
  173. package/dist/spec.d.ts +159 -0
  174. package/dist/spec.d.ts.map +1 -0
  175. package/dist/spec.js +391 -0
  176. package/dist/stakeholders.d.ts +199 -0
  177. package/dist/stakeholders.d.ts.map +1 -0
  178. package/dist/stakeholders.js +398 -0
  179. package/dist/standards.d.ts.map +1 -1
  180. package/dist/standards.js +160 -2
  181. package/dist/standards_ingest.d.ts +2 -2
  182. package/dist/standards_ingest.d.ts.map +1 -1
  183. package/dist/standards_ingest.js +105 -23
  184. package/dist/streaming.d.ts.map +1 -1
  185. package/dist/streaming.js +7 -2
  186. package/dist/telemetry.d.ts +16 -2
  187. package/dist/telemetry.d.ts.map +1 -1
  188. package/dist/telemetry.js +79 -14
  189. package/dist/templates/controls/iso42001_control_catalog.json +1443 -0
  190. package/dist/traced_emitter.d.ts +3 -0
  191. package/dist/traced_emitter.d.ts.map +1 -1
  192. package/dist/traced_emitter.js +142 -25
  193. package/dist/trust_package.d.ts +21 -1
  194. package/dist/trust_package.d.ts.map +1 -1
  195. package/dist/trust_package.js +101 -4
  196. package/dist/verify.d.ts.map +1 -1
  197. package/dist/verify.js +9 -2
  198. package/dist/wal.d.ts.map +1 -1
  199. package/dist/wal.js +2 -1
  200. package/package.json +14 -1
  201. package/scripts/postinstall.js +119 -97
  202. package/templates/controls/iso42001_control_catalog.json +1443 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Data Governance Module for ISO 42001 A.7 compliance.
3
+ *
4
+ * This module provides data governance tracking supporting ISO 42001 controls:
5
+ * - A.7.2: Data for development and enhancement
6
+ * - A.7.4: Quality of data
7
+ * - A.7.6: Data preparation
8
+ *
9
+ * Extends existing lineage and provenance features (A.7.3, A.7.5).
10
+ *
11
+ * Cross-SDK Parity:
12
+ * Both Python and Node.js SDKs provide identical data governance APIs:
13
+ * - createDatasetRecord() / create_dataset_record()
14
+ * - recordQualityMetrics() / record_quality_metrics()
15
+ * - addPreparationStep() / add_preparation_step()
16
+ * - recordBiasAssessment() / record_bias_assessment()
17
+ */
18
+ import { MonoraConfig } from './config';
19
+ export type DatasetCategory = 'training' | 'validation' | 'test' | 'production' | 'synthetic';
20
+ export type QualityStatus = 'passed' | 'failed' | 'not_assessed';
21
+ export type PreparationStepType = 'cleaning' | 'normalization' | 'encoding' | 'augmentation' | 'sampling' | 'transformation' | 'filtering';
22
+ export type AcquisitionMethod = 'api' | 'manual_collection' | 'purchase' | 'synthetic_generation' | 'scraping' | 'donation';
23
+ /**
24
+ * Data quality metrics (A.7.4).
25
+ */
26
+ export interface DataQualityMetrics {
27
+ completeness: number;
28
+ accuracy: number;
29
+ consistency: number;
30
+ timeliness: number;
31
+ uniqueness: number;
32
+ representativeness: number;
33
+ }
34
+ export declare function qualityMetricsToDict(metrics: DataQualityMetrics): Record<string, any>;
35
+ export declare function checkQualityThresholds(metrics: DataQualityMetrics, thresholds: Record<string, number>): string[];
36
+ /**
37
+ * A data preparation step (A.7.6).
38
+ */
39
+ export interface PreparationStep {
40
+ stepId: string;
41
+ stepType: PreparationStepType;
42
+ description: string;
43
+ inputDataset: string;
44
+ outputDataset: string;
45
+ parameters: Record<string, any>;
46
+ executedAt: string;
47
+ executedBy: string;
48
+ }
49
+ export declare function preparationStepToDict(step: PreparationStep): Record<string, any>;
50
+ /**
51
+ * Bias assessment for a dataset.
52
+ */
53
+ export interface DatasetBiasAssessment {
54
+ assessmentId: string;
55
+ dimension: string;
56
+ metric: string;
57
+ value: number;
58
+ threshold: number;
59
+ passed: boolean;
60
+ assessedAt: string;
61
+ }
62
+ export declare function biasAssessmentToDict(assessment: DatasetBiasAssessment): Record<string, any>;
63
+ /**
64
+ * Complete dataset record for ISO 42001 A.7.
65
+ */
66
+ export interface DatasetRecord {
67
+ datasetId: string;
68
+ name: string;
69
+ description: string;
70
+ category: DatasetCategory;
71
+ source: string;
72
+ acquisitionMethod: AcquisitionMethod;
73
+ acquisitionDate: string;
74
+ dataRights: string;
75
+ qualityMetrics?: DataQualityMetrics;
76
+ qualityThresholds: Record<string, number>;
77
+ qualityStatus: QualityStatus;
78
+ lineage: string[];
79
+ transformations: string[];
80
+ preparationSteps: PreparationStep[];
81
+ biasAssessments: DatasetBiasAssessment[];
82
+ recordCount?: number;
83
+ schemaRef?: string;
84
+ createdAt: string;
85
+ updatedAt: string;
86
+ }
87
+ export declare function datasetRecordToDict(dataset: DatasetRecord): Record<string, any>;
88
+ /**
89
+ * Create a new dataset record.
90
+ */
91
+ export interface CreateDatasetRecordOptions {
92
+ name: string;
93
+ description: string;
94
+ category: DatasetCategory;
95
+ source: string;
96
+ acquisitionMethod: AcquisitionMethod;
97
+ acquisitionDate?: string;
98
+ dataRights?: string;
99
+ lineage?: string[];
100
+ recordCount?: number;
101
+ schemaRef?: string;
102
+ config?: MonoraConfig;
103
+ }
104
+ export declare function createDatasetRecord(options: CreateDatasetRecordOptions): DatasetRecord;
105
+ /**
106
+ * Register an existing dataset record.
107
+ */
108
+ export declare function registerDataset(record: DatasetRecord): void;
109
+ /**
110
+ * Get a dataset record by ID.
111
+ */
112
+ export declare function getDatasetRecord(datasetId: string): DatasetRecord | undefined;
113
+ /**
114
+ * Get all registered dataset records.
115
+ */
116
+ export declare function getAllDatasets(): DatasetRecord[];
117
+ /**
118
+ * Clear all dataset records from the registry.
119
+ */
120
+ export declare function clearDatasets(): void;
121
+ /**
122
+ * Record quality metrics for a dataset (A.7.4).
123
+ */
124
+ export interface RecordQualityMetricsOptions {
125
+ datasetId: string;
126
+ completeness?: number;
127
+ accuracy?: number;
128
+ consistency?: number;
129
+ timeliness?: number;
130
+ uniqueness?: number;
131
+ representativeness?: number;
132
+ config?: MonoraConfig;
133
+ }
134
+ export declare function recordQualityMetrics(options: RecordQualityMetricsOptions): DataQualityMetrics;
135
+ /**
136
+ * Add a data preparation step (A.7.6).
137
+ */
138
+ export interface AddPreparationStepOptions {
139
+ datasetId: string;
140
+ stepType: PreparationStepType;
141
+ description: string;
142
+ outputDatasetId?: string;
143
+ parameters?: Record<string, any>;
144
+ executedBy?: string;
145
+ }
146
+ export declare function addPreparationStep(options: AddPreparationStepOptions): PreparationStep;
147
+ /**
148
+ * Record a bias assessment for a dataset.
149
+ */
150
+ export interface RecordBiasAssessmentOptions {
151
+ datasetId: string;
152
+ dimension: string;
153
+ metric: string;
154
+ value: number;
155
+ threshold: number;
156
+ }
157
+ export declare function recordBiasAssessment(options: RecordBiasAssessmentOptions): DatasetBiasAssessment;
158
+ /**
159
+ * Update the lineage of a dataset.
160
+ */
161
+ export declare function updateDatasetLineage(datasetId: string, parentIds: string[]): void;
162
+ /**
163
+ * Get the full lineage graph for a dataset.
164
+ */
165
+ export declare function getDatasetLineage(datasetId: string): Record<string, any>;
166
+ /**
167
+ * Validate that a dataset meets quality requirements for intended use.
168
+ */
169
+ export interface ValidateDatasetOptions {
170
+ datasetId: string;
171
+ intendedUse: DatasetCategory;
172
+ config?: MonoraConfig;
173
+ }
174
+ export declare function validateDatasetForUse(options: ValidateDatasetOptions): Record<string, any>;
175
+ /**
176
+ * Get a summary of a dataset for reporting.
177
+ */
178
+ export declare function getDatasetSummary(datasetId: string): Record<string, any>;
179
+ /**
180
+ * Get aggregate report of all datasets.
181
+ */
182
+ export declare function getDataGovernanceReport(config?: MonoraConfig): Record<string, any>;
183
+ /**
184
+ * Emit the current state of a dataset record as an event.
185
+ */
186
+ export declare function emitDatasetRecord(datasetId: string, config?: MonoraConfig): void;
187
+ //# sourceMappingURL=data-governance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-governance.d.ts","sourceRoot":"","sources":["../src/data-governance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,424 @@
1
+ "use strict";
2
+ /**
3
+ * Data Governance Module for ISO 42001 A.7 compliance.
4
+ *
5
+ * This module provides data governance tracking supporting ISO 42001 controls:
6
+ * - A.7.2: Data for development and enhancement
7
+ * - A.7.4: Quality of data
8
+ * - A.7.6: Data preparation
9
+ *
10
+ * Extends existing lineage and provenance features (A.7.3, A.7.5).
11
+ *
12
+ * Cross-SDK Parity:
13
+ * Both Python and Node.js SDKs provide identical data governance APIs:
14
+ * - createDatasetRecord() / create_dataset_record()
15
+ * - recordQualityMetrics() / record_quality_metrics()
16
+ * - addPreparationStep() / add_preparation_step()
17
+ * - recordBiasAssessment() / record_bias_assessment()
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.qualityMetricsToDict = qualityMetricsToDict;
21
+ exports.checkQualityThresholds = checkQualityThresholds;
22
+ exports.preparationStepToDict = preparationStepToDict;
23
+ exports.biasAssessmentToDict = biasAssessmentToDict;
24
+ exports.datasetRecordToDict = datasetRecordToDict;
25
+ exports.createDatasetRecord = createDatasetRecord;
26
+ exports.registerDataset = registerDataset;
27
+ exports.getDatasetRecord = getDatasetRecord;
28
+ exports.getAllDatasets = getAllDatasets;
29
+ exports.clearDatasets = clearDatasets;
30
+ exports.recordQualityMetrics = recordQualityMetrics;
31
+ exports.addPreparationStep = addPreparationStep;
32
+ exports.recordBiasAssessment = recordBiasAssessment;
33
+ exports.updateDatasetLineage = updateDatasetLineage;
34
+ exports.getDatasetLineage = getDatasetLineage;
35
+ exports.validateDatasetForUse = validateDatasetForUse;
36
+ exports.getDatasetSummary = getDatasetSummary;
37
+ exports.getDataGovernanceReport = getDataGovernanceReport;
38
+ exports.emitDatasetRecord = emitDatasetRecord;
39
+ const crypto_1 = require("crypto");
40
+ const logger_1 = require("./logger");
41
+ /**
42
+ * Generate a deterministic ID from parts.
43
+ */
44
+ function generateId(prefix, ...parts) {
45
+ const combined = parts.join(':');
46
+ const hash = (0, crypto_1.createHash)('sha256').update(combined).digest('hex').slice(0, 12);
47
+ return `${prefix}_${hash}`;
48
+ }
49
+ /**
50
+ * Get current UTC timestamp in ISO format.
51
+ */
52
+ function nowIso() {
53
+ return new Date().toISOString();
54
+ }
55
+ function qualityMetricsToDict(metrics) {
56
+ return {
57
+ completeness: metrics.completeness,
58
+ accuracy: metrics.accuracy,
59
+ consistency: metrics.consistency,
60
+ timeliness: metrics.timeliness,
61
+ uniqueness: metrics.uniqueness,
62
+ representativeness: metrics.representativeness,
63
+ };
64
+ }
65
+ function checkQualityThresholds(metrics, thresholds) {
66
+ const failures = [];
67
+ for (const [metric, threshold] of Object.entries(thresholds)) {
68
+ const value = metrics[metric];
69
+ if (value !== undefined && value < threshold) {
70
+ failures.push(`${metric} (${value.toFixed(3)} < ${threshold})`);
71
+ }
72
+ }
73
+ return failures;
74
+ }
75
+ function preparationStepToDict(step) {
76
+ return {
77
+ step_id: step.stepId,
78
+ step_type: step.stepType,
79
+ description: step.description,
80
+ input_dataset: step.inputDataset,
81
+ output_dataset: step.outputDataset,
82
+ parameters: step.parameters,
83
+ executed_at: step.executedAt,
84
+ executed_by: step.executedBy,
85
+ };
86
+ }
87
+ function biasAssessmentToDict(assessment) {
88
+ return {
89
+ assessment_id: assessment.assessmentId,
90
+ dimension: assessment.dimension,
91
+ metric: assessment.metric,
92
+ value: assessment.value,
93
+ threshold: assessment.threshold,
94
+ passed: assessment.passed,
95
+ assessed_at: assessment.assessedAt,
96
+ };
97
+ }
98
+ function datasetRecordToDict(dataset) {
99
+ const result = {
100
+ dataset_id: dataset.datasetId,
101
+ name: dataset.name,
102
+ description: dataset.description,
103
+ category: dataset.category,
104
+ source: dataset.source,
105
+ acquisition_method: dataset.acquisitionMethod,
106
+ acquisition_date: dataset.acquisitionDate,
107
+ data_rights: dataset.dataRights,
108
+ quality_thresholds: dataset.qualityThresholds,
109
+ quality_status: dataset.qualityStatus,
110
+ lineage: dataset.lineage,
111
+ transformations: dataset.transformations,
112
+ preparation_steps: dataset.preparationSteps.map(preparationStepToDict),
113
+ bias_assessments: dataset.biasAssessments.map(biasAssessmentToDict),
114
+ created_at: dataset.createdAt,
115
+ updated_at: dataset.updatedAt,
116
+ };
117
+ if (dataset.qualityMetrics) {
118
+ result.quality_metrics = qualityMetricsToDict(dataset.qualityMetrics);
119
+ }
120
+ if (dataset.recordCount !== undefined) {
121
+ result.record_count = dataset.recordCount;
122
+ }
123
+ if (dataset.schemaRef) {
124
+ result.schema_ref = dataset.schemaRef;
125
+ }
126
+ return result;
127
+ }
128
+ // Runtime dataset registry
129
+ const datasets = new Map();
130
+ function createDatasetRecord(options) {
131
+ const governanceConfig = options.config?.data_governance;
132
+ const defaultThresholds = governanceConfig?.default_quality_thresholds || {};
133
+ const acquisitionDate = options.acquisitionDate || new Date().toISOString().split('T')[0];
134
+ const datasetId = generateId('ds', options.name, options.source, acquisitionDate);
135
+ const record = {
136
+ datasetId,
137
+ name: options.name,
138
+ description: options.description,
139
+ category: options.category,
140
+ source: options.source,
141
+ acquisitionMethod: options.acquisitionMethod,
142
+ acquisitionDate,
143
+ dataRights: options.dataRights || '',
144
+ qualityThresholds: { ...defaultThresholds },
145
+ qualityStatus: 'not_assessed',
146
+ lineage: options.lineage || [],
147
+ transformations: [],
148
+ preparationSteps: [],
149
+ biasAssessments: [],
150
+ recordCount: options.recordCount,
151
+ schemaRef: options.schemaRef,
152
+ createdAt: nowIso(),
153
+ updatedAt: nowIso(),
154
+ };
155
+ datasets.set(datasetId, record);
156
+ return record;
157
+ }
158
+ /**
159
+ * Register an existing dataset record.
160
+ */
161
+ function registerDataset(record) {
162
+ datasets.set(record.datasetId, record);
163
+ }
164
+ /**
165
+ * Get a dataset record by ID.
166
+ */
167
+ function getDatasetRecord(datasetId) {
168
+ return datasets.get(datasetId);
169
+ }
170
+ /**
171
+ * Get all registered dataset records.
172
+ */
173
+ function getAllDatasets() {
174
+ return Array.from(datasets.values());
175
+ }
176
+ /**
177
+ * Clear all dataset records from the registry.
178
+ */
179
+ function clearDatasets() {
180
+ datasets.clear();
181
+ }
182
+ function recordQualityMetrics(options) {
183
+ const dataset = datasets.get(options.datasetId);
184
+ if (!dataset) {
185
+ throw new Error(`Dataset ${options.datasetId} not found`);
186
+ }
187
+ const metrics = {
188
+ completeness: options.completeness ?? 0,
189
+ accuracy: options.accuracy ?? 0,
190
+ consistency: options.consistency ?? 0,
191
+ timeliness: options.timeliness ?? 0,
192
+ uniqueness: options.uniqueness ?? 0,
193
+ representativeness: options.representativeness ?? 0,
194
+ };
195
+ dataset.qualityMetrics = metrics;
196
+ // Check against thresholds
197
+ const failures = checkQualityThresholds(metrics, dataset.qualityThresholds);
198
+ dataset.qualityStatus = failures.length > 0 ? 'failed' : 'passed';
199
+ dataset.updatedAt = nowIso();
200
+ // Emit quality event
201
+ emitDataGovernanceEvent(dataset, 'data_quality_check', options.config);
202
+ return metrics;
203
+ }
204
+ function addPreparationStep(options) {
205
+ const dataset = datasets.get(options.datasetId);
206
+ if (!dataset) {
207
+ throw new Error(`Dataset ${options.datasetId} not found`);
208
+ }
209
+ const stepId = generateId('prep', options.datasetId, options.stepType, options.description.slice(0, 20));
210
+ const step = {
211
+ stepId,
212
+ stepType: options.stepType,
213
+ description: options.description,
214
+ inputDataset: options.datasetId,
215
+ outputDataset: options.outputDatasetId || options.datasetId,
216
+ parameters: options.parameters || {},
217
+ executedAt: nowIso(),
218
+ executedBy: options.executedBy || '',
219
+ };
220
+ dataset.preparationSteps.push(step);
221
+ dataset.transformations.push(`${options.stepType}: ${options.description}`);
222
+ dataset.updatedAt = nowIso();
223
+ return step;
224
+ }
225
+ function recordBiasAssessment(options) {
226
+ const dataset = datasets.get(options.datasetId);
227
+ if (!dataset) {
228
+ throw new Error(`Dataset ${options.datasetId} not found`);
229
+ }
230
+ const assessmentId = generateId('bias', options.datasetId, options.dimension, options.metric);
231
+ const passed = options.value >= options.threshold;
232
+ const assessment = {
233
+ assessmentId,
234
+ dimension: options.dimension,
235
+ metric: options.metric,
236
+ value: options.value,
237
+ threshold: options.threshold,
238
+ passed,
239
+ assessedAt: nowIso(),
240
+ };
241
+ dataset.biasAssessments.push(assessment);
242
+ dataset.updatedAt = nowIso();
243
+ return assessment;
244
+ }
245
+ /**
246
+ * Update the lineage of a dataset.
247
+ */
248
+ function updateDatasetLineage(datasetId, parentIds) {
249
+ const dataset = datasets.get(datasetId);
250
+ if (!dataset) {
251
+ throw new Error(`Dataset ${datasetId} not found`);
252
+ }
253
+ dataset.lineage = parentIds;
254
+ dataset.updatedAt = nowIso();
255
+ }
256
+ /**
257
+ * Get the full lineage graph for a dataset.
258
+ */
259
+ function getDatasetLineage(datasetId) {
260
+ const dataset = datasets.get(datasetId);
261
+ if (!dataset) {
262
+ return {};
263
+ }
264
+ function getAncestors(dsId, visited) {
265
+ if (visited.has(dsId)) {
266
+ return [];
267
+ }
268
+ visited.add(dsId);
269
+ const ds = datasets.get(dsId);
270
+ if (!ds) {
271
+ return [{ dataset_id: dsId, status: 'not_found' }];
272
+ }
273
+ const ancestors = [];
274
+ for (const parentId of ds.lineage) {
275
+ ancestors.push(...getAncestors(parentId, visited));
276
+ }
277
+ return [
278
+ {
279
+ dataset_id: ds.datasetId,
280
+ name: ds.name,
281
+ category: ds.category,
282
+ parents: ds.lineage,
283
+ transformations: ds.transformations,
284
+ },
285
+ ...ancestors,
286
+ ];
287
+ }
288
+ const visited = new Set();
289
+ const lineageTree = getAncestors(datasetId, visited);
290
+ return {
291
+ dataset_id: datasetId,
292
+ name: dataset.name,
293
+ lineage_depth: visited.size - 1,
294
+ lineage_tree: lineageTree,
295
+ };
296
+ }
297
+ function validateDatasetForUse(options) {
298
+ const dataset = datasets.get(options.datasetId);
299
+ if (!dataset) {
300
+ return {
301
+ valid: false,
302
+ dataset_id: options.datasetId,
303
+ issues: ['Dataset not found'],
304
+ };
305
+ }
306
+ const issues = [];
307
+ const governanceConfig = options.config?.data_governance;
308
+ // Check quality assessment
309
+ if (governanceConfig?.require_quality_assessment !== false) {
310
+ if (dataset.qualityStatus === 'not_assessed') {
311
+ issues.push('Quality assessment not performed');
312
+ }
313
+ else if (dataset.qualityStatus === 'failed') {
314
+ issues.push('Quality metrics below thresholds');
315
+ }
316
+ }
317
+ // Check bias assessment for training/validation
318
+ const requireBiasFor = governanceConfig?.require_bias_assessment_for || ['training', 'validation'];
319
+ if (requireBiasFor.includes(options.intendedUse)) {
320
+ if (dataset.biasAssessments.length === 0) {
321
+ issues.push(`Bias assessment required for ${options.intendedUse} datasets`);
322
+ }
323
+ else {
324
+ const failedBias = dataset.biasAssessments.filter(b => !b.passed);
325
+ if (failedBias.length > 0) {
326
+ issues.push(`Bias thresholds not met: ${failedBias.map(b => b.dimension).join(', ')}`);
327
+ }
328
+ }
329
+ }
330
+ return {
331
+ valid: issues.length === 0,
332
+ dataset_id: options.datasetId,
333
+ name: dataset.name,
334
+ intended_use: options.intendedUse,
335
+ quality_status: dataset.qualityStatus,
336
+ bias_assessments_count: dataset.biasAssessments.length,
337
+ issues,
338
+ };
339
+ }
340
+ /**
341
+ * Get a summary of a dataset for reporting.
342
+ */
343
+ function getDatasetSummary(datasetId) {
344
+ const dataset = datasets.get(datasetId);
345
+ if (!dataset) {
346
+ return {};
347
+ }
348
+ return {
349
+ dataset_id: dataset.datasetId,
350
+ name: dataset.name,
351
+ category: dataset.category,
352
+ source: dataset.source,
353
+ acquisition_method: dataset.acquisitionMethod,
354
+ acquisition_date: dataset.acquisitionDate,
355
+ quality_status: dataset.qualityStatus,
356
+ quality_metrics: dataset.qualityMetrics ? qualityMetricsToDict(dataset.qualityMetrics) : null,
357
+ preparation_steps_count: dataset.preparationSteps.length,
358
+ bias_assessments_count: dataset.biasAssessments.length,
359
+ bias_assessments_passed: dataset.biasAssessments.filter(b => b.passed).length,
360
+ lineage_depth: dataset.lineage.length,
361
+ record_count: dataset.recordCount,
362
+ };
363
+ }
364
+ /**
365
+ * Get aggregate report of all datasets.
366
+ */
367
+ function getDataGovernanceReport(config) {
368
+ if (datasets.size === 0) {
369
+ return {
370
+ total_datasets: 0,
371
+ by_category: {},
372
+ by_quality_status: {},
373
+ datasets: [],
374
+ };
375
+ }
376
+ const byCategory = {};
377
+ const byQuality = {};
378
+ const datasetsSummary = [];
379
+ datasets.forEach(dataset => {
380
+ byCategory[dataset.category] = (byCategory[dataset.category] || 0) + 1;
381
+ byQuality[dataset.qualityStatus] = (byQuality[dataset.qualityStatus] || 0) + 1;
382
+ datasetsSummary.push({
383
+ dataset_id: dataset.datasetId,
384
+ name: dataset.name,
385
+ category: dataset.category,
386
+ quality_status: dataset.qualityStatus,
387
+ });
388
+ });
389
+ return {
390
+ total_datasets: datasets.size,
391
+ by_category: byCategory,
392
+ by_quality_status: byQuality,
393
+ datasets: datasetsSummary,
394
+ };
395
+ }
396
+ /**
397
+ * Emit a data governance event.
398
+ */
399
+ function emitDataGovernanceEvent(dataset, eventType, config) {
400
+ try {
401
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
402
+ const { getState } = require('./runtime');
403
+ const state = getState();
404
+ if (state && typeof state.emitInternal === 'function') {
405
+ state.emitInternal({
406
+ event_type: eventType,
407
+ timestamp: nowIso(),
408
+ body: datasetRecordToDict(dataset),
409
+ });
410
+ }
411
+ }
412
+ catch (err) {
413
+ logger_1.logger.warning('Failed to emit data governance event:', err);
414
+ }
415
+ }
416
+ /**
417
+ * Emit the current state of a dataset record as an event.
418
+ */
419
+ function emitDatasetRecord(datasetId, config) {
420
+ const dataset = getDatasetRecord(datasetId);
421
+ if (dataset) {
422
+ emitDataGovernanceEvent(dataset, 'dataset_record', config);
423
+ }
424
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Data residency validation for sinks.
3
+ *
4
+ * Validates that endpoint URLs match configured data residency requirements
5
+ * based on domain patterns for different geographic regions.
6
+ */
7
+ import { DataResidency } from './config';
8
+ /**
9
+ * Result of a data residency check.
10
+ */
11
+ export interface DataResidencyCheckResult {
12
+ /** Whether the check passed */
13
+ valid: boolean;
14
+ /** Detected region of the endpoint (if determinable) */
15
+ detectedRegion: 'us' | 'eu' | 'unknown';
16
+ /** Required region */
17
+ requiredRegion: DataResidency;
18
+ /** The endpoint URL that was checked */
19
+ endpoint: string;
20
+ /** Human-readable message */
21
+ message: string;
22
+ }
23
+ /**
24
+ * Detect the likely data residency region of an endpoint URL.
25
+ */
26
+ export declare function detectEndpointRegion(endpoint: string): 'us' | 'eu' | 'unknown';
27
+ /**
28
+ * Validate that an endpoint URL matches the required data residency.
29
+ *
30
+ * @param endpoint - The endpoint URL to validate
31
+ * @param requiredResidency - The required data residency ('us', 'eu', 'any', or null)
32
+ * @returns Validation result with details
33
+ */
34
+ export declare function validateDataResidency(endpoint: string, requiredResidency: DataResidency): DataResidencyCheckResult;
35
+ /**
36
+ * Enforce data residency requirements for a sink endpoint.
37
+ *
38
+ * @param endpoint - The endpoint URL to validate
39
+ * @param residency - The required data residency
40
+ * @param action - Action on failure: 'block' throws error, 'warn' logs warning
41
+ * @throws Error if action is 'block' and validation fails
42
+ */
43
+ export declare function enforceDataResidency(endpoint: string, residency: DataResidency, action?: 'block' | 'warn'): DataResidencyCheckResult;
44
+ //# sourceMappingURL=dataResidency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataResidency.d.ts","sourceRoot":"","sources":["../src/dataResidency.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AA0FzC;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,wDAAwD;IACxD,cAAc,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,sBAAsB;IACtB,cAAc,EAAE,aAAa,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAgBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAuB9E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,aAAa,GAC/B,wBAAwB,CA4C1B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,aAAa,EACxB,MAAM,GAAE,OAAO,GAAG,MAAe,GAChC,wBAAwB,CAiB1B"}