@elanlanguages/bridge-anonymization 0.1.0

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 (126) hide show
  1. package/README.md +382 -0
  2. package/dist/crypto/index.d.ts +6 -0
  3. package/dist/crypto/index.d.ts.map +1 -0
  4. package/dist/crypto/index.js +6 -0
  5. package/dist/crypto/index.js.map +1 -0
  6. package/dist/crypto/pii-map-crypto.d.ts +100 -0
  7. package/dist/crypto/pii-map-crypto.d.ts.map +1 -0
  8. package/dist/crypto/pii-map-crypto.js +163 -0
  9. package/dist/crypto/pii-map-crypto.js.map +1 -0
  10. package/dist/index.d.ts +173 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +294 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/ner/bio-decoder.d.ts +64 -0
  15. package/dist/ner/bio-decoder.d.ts.map +1 -0
  16. package/dist/ner/bio-decoder.js +216 -0
  17. package/dist/ner/bio-decoder.js.map +1 -0
  18. package/dist/ner/index.d.ts +10 -0
  19. package/dist/ner/index.d.ts.map +1 -0
  20. package/dist/ner/index.js +10 -0
  21. package/dist/ner/index.js.map +1 -0
  22. package/dist/ner/model-manager.d.ts +102 -0
  23. package/dist/ner/model-manager.d.ts.map +1 -0
  24. package/dist/ner/model-manager.js +253 -0
  25. package/dist/ner/model-manager.js.map +1 -0
  26. package/dist/ner/ner-model.d.ts +114 -0
  27. package/dist/ner/ner-model.d.ts.map +1 -0
  28. package/dist/ner/ner-model.js +240 -0
  29. package/dist/ner/ner-model.js.map +1 -0
  30. package/dist/ner/onnx-runtime.d.ts +45 -0
  31. package/dist/ner/onnx-runtime.d.ts.map +1 -0
  32. package/dist/ner/onnx-runtime.js +99 -0
  33. package/dist/ner/onnx-runtime.js.map +1 -0
  34. package/dist/ner/tokenizer.d.ts +140 -0
  35. package/dist/ner/tokenizer.d.ts.map +1 -0
  36. package/dist/ner/tokenizer.js +341 -0
  37. package/dist/ner/tokenizer.js.map +1 -0
  38. package/dist/pipeline/index.d.ts +9 -0
  39. package/dist/pipeline/index.d.ts.map +1 -0
  40. package/dist/pipeline/index.js +9 -0
  41. package/dist/pipeline/index.js.map +1 -0
  42. package/dist/pipeline/prenormalize.d.ts +48 -0
  43. package/dist/pipeline/prenormalize.d.ts.map +1 -0
  44. package/dist/pipeline/prenormalize.js +94 -0
  45. package/dist/pipeline/prenormalize.js.map +1 -0
  46. package/dist/pipeline/resolver.d.ts +56 -0
  47. package/dist/pipeline/resolver.d.ts.map +1 -0
  48. package/dist/pipeline/resolver.js +238 -0
  49. package/dist/pipeline/resolver.js.map +1 -0
  50. package/dist/pipeline/tagger.d.ts +74 -0
  51. package/dist/pipeline/tagger.d.ts.map +1 -0
  52. package/dist/pipeline/tagger.js +169 -0
  53. package/dist/pipeline/tagger.js.map +1 -0
  54. package/dist/pipeline/validator.d.ts +65 -0
  55. package/dist/pipeline/validator.d.ts.map +1 -0
  56. package/dist/pipeline/validator.js +264 -0
  57. package/dist/pipeline/validator.js.map +1 -0
  58. package/dist/recognizers/base.d.ts +78 -0
  59. package/dist/recognizers/base.d.ts.map +1 -0
  60. package/dist/recognizers/base.js +100 -0
  61. package/dist/recognizers/base.js.map +1 -0
  62. package/dist/recognizers/bic-swift.d.ts +10 -0
  63. package/dist/recognizers/bic-swift.d.ts.map +1 -0
  64. package/dist/recognizers/bic-swift.js +107 -0
  65. package/dist/recognizers/bic-swift.js.map +1 -0
  66. package/dist/recognizers/credit-card.d.ts +32 -0
  67. package/dist/recognizers/credit-card.d.ts.map +1 -0
  68. package/dist/recognizers/credit-card.js +160 -0
  69. package/dist/recognizers/credit-card.js.map +1 -0
  70. package/dist/recognizers/custom-id.d.ts +28 -0
  71. package/dist/recognizers/custom-id.d.ts.map +1 -0
  72. package/dist/recognizers/custom-id.js +116 -0
  73. package/dist/recognizers/custom-id.js.map +1 -0
  74. package/dist/recognizers/email.d.ts +10 -0
  75. package/dist/recognizers/email.d.ts.map +1 -0
  76. package/dist/recognizers/email.js +75 -0
  77. package/dist/recognizers/email.js.map +1 -0
  78. package/dist/recognizers/iban.d.ts +14 -0
  79. package/dist/recognizers/iban.d.ts.map +1 -0
  80. package/dist/recognizers/iban.js +67 -0
  81. package/dist/recognizers/iban.js.map +1 -0
  82. package/dist/recognizers/index.d.ts +20 -0
  83. package/dist/recognizers/index.d.ts.map +1 -0
  84. package/dist/recognizers/index.js +42 -0
  85. package/dist/recognizers/index.js.map +1 -0
  86. package/dist/recognizers/ip-address.d.ts +14 -0
  87. package/dist/recognizers/ip-address.d.ts.map +1 -0
  88. package/dist/recognizers/ip-address.js +183 -0
  89. package/dist/recognizers/ip-address.js.map +1 -0
  90. package/dist/recognizers/phone.d.ts +10 -0
  91. package/dist/recognizers/phone.d.ts.map +1 -0
  92. package/dist/recognizers/phone.js +145 -0
  93. package/dist/recognizers/phone.js.map +1 -0
  94. package/dist/recognizers/registry.d.ts +59 -0
  95. package/dist/recognizers/registry.d.ts.map +1 -0
  96. package/dist/recognizers/registry.js +113 -0
  97. package/dist/recognizers/registry.js.map +1 -0
  98. package/dist/recognizers/url.d.ts +14 -0
  99. package/dist/recognizers/url.d.ts.map +1 -0
  100. package/dist/recognizers/url.js +121 -0
  101. package/dist/recognizers/url.js.map +1 -0
  102. package/dist/types/index.d.ts +134 -0
  103. package/dist/types/index.d.ts.map +1 -0
  104. package/dist/types/index.js +69 -0
  105. package/dist/types/index.js.map +1 -0
  106. package/dist/types/pii-types.d.ts +50 -0
  107. package/dist/types/pii-types.d.ts.map +1 -0
  108. package/dist/types/pii-types.js +114 -0
  109. package/dist/types/pii-types.js.map +1 -0
  110. package/dist/utils/iban-checksum.d.ts +23 -0
  111. package/dist/utils/iban-checksum.d.ts.map +1 -0
  112. package/dist/utils/iban-checksum.js +106 -0
  113. package/dist/utils/iban-checksum.js.map +1 -0
  114. package/dist/utils/index.d.ts +8 -0
  115. package/dist/utils/index.d.ts.map +1 -0
  116. package/dist/utils/index.js +8 -0
  117. package/dist/utils/index.js.map +1 -0
  118. package/dist/utils/luhn.d.ts +17 -0
  119. package/dist/utils/luhn.d.ts.map +1 -0
  120. package/dist/utils/luhn.js +55 -0
  121. package/dist/utils/luhn.js.map +1 -0
  122. package/dist/utils/offsets.d.ts +86 -0
  123. package/dist/utils/offsets.d.ts.map +1 -0
  124. package/dist/utils/offsets.js +124 -0
  125. package/dist/utils/offsets.js.map +1 -0
  126. package/package.json +62 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Output Validator
3
+ * Validates anonymized output and performs leak scan
4
+ */
5
+ import { PIIType } from '../types/index.js';
6
+ import { spansOverlap } from '../utils/offsets.js';
7
+ import { extractTags, isValidTag } from './tagger.js';
8
+ /**
9
+ * Validation error codes
10
+ */
11
+ export var ValidationErrorCode;
12
+ (function (ValidationErrorCode) {
13
+ ValidationErrorCode["OVERLAPPING_ENTITIES"] = "OVERLAPPING_ENTITIES";
14
+ ValidationErrorCode["DUPLICATE_IDS"] = "DUPLICATE_IDS";
15
+ ValidationErrorCode["MALFORMED_TAG"] = "MALFORMED_TAG";
16
+ ValidationErrorCode["ID_MISMATCH"] = "ID_MISMATCH";
17
+ ValidationErrorCode["MISSING_IN_MAP"] = "MISSING_IN_MAP";
18
+ ValidationErrorCode["POTENTIAL_PII_LEAK"] = "POTENTIAL_PII_LEAK";
19
+ })(ValidationErrorCode || (ValidationErrorCode = {}));
20
+ /**
21
+ * Leak scan patterns for common structured PII
22
+ * These are simplified patterns for quick scanning
23
+ */
24
+ const LEAK_SCAN_PATTERNS = [
25
+ {
26
+ type: PIIType.EMAIL,
27
+ pattern: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
28
+ name: 'Email',
29
+ },
30
+ {
31
+ type: PIIType.PHONE,
32
+ pattern: /(?:\+|00)[1-9][0-9]{7,14}|0[1-9][0-9]{6,11}/g,
33
+ name: 'Phone',
34
+ },
35
+ {
36
+ type: PIIType.IBAN,
37
+ pattern: /[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}/gi,
38
+ name: 'IBAN',
39
+ },
40
+ {
41
+ type: PIIType.CREDIT_CARD,
42
+ pattern: /[0-9]{4}[\s-]?[0-9]{4}[\s-]?[0-9]{4}[\s-]?[0-9]{4}/g,
43
+ name: 'Credit Card',
44
+ },
45
+ {
46
+ type: PIIType.IP_ADDRESS,
47
+ pattern: /(?:\d{1,3}\.){3}\d{1,3}/g,
48
+ name: 'IP Address',
49
+ },
50
+ ];
51
+ /**
52
+ * Validates anonymization output
53
+ */
54
+ export function validateOutput(anonymizedText, entities, piiMapKeys, policy) {
55
+ const errors = [];
56
+ // Validate no overlapping entities
57
+ const overlapErrors = checkOverlappingEntities(entities);
58
+ errors.push(...overlapErrors);
59
+ // Validate unique IDs (per type or globally)
60
+ const idErrors = checkUniqueIds(entities);
61
+ errors.push(...idErrors);
62
+ // Validate tags in text are well-formed
63
+ const tagErrors = checkTags(anonymizedText);
64
+ errors.push(...tagErrors);
65
+ // Validate tag count matches entity count
66
+ const countErrors = checkTagEntityMatch(anonymizedText, entities);
67
+ errors.push(...countErrors);
68
+ // Validate all entities have entries in PII map
69
+ const mapErrors = checkPIIMapCompleteness(entities, piiMapKeys);
70
+ errors.push(...mapErrors);
71
+ // Perform leak scan if enabled
72
+ let leakScanPassed;
73
+ let potentialLeaks;
74
+ if (policy.enableLeakScan) {
75
+ const leakResult = performLeakScan(anonymizedText, policy);
76
+ potentialLeaks = leakResult.matches;
77
+ leakScanPassed = potentialLeaks.length === 0;
78
+ if (!leakScanPassed) {
79
+ errors.push({
80
+ code: ValidationErrorCode.POTENTIAL_PII_LEAK,
81
+ message: `Leak scan found ${potentialLeaks.length} potential PII leak(s)`,
82
+ details: { leaks: potentialLeaks },
83
+ });
84
+ }
85
+ }
86
+ return {
87
+ valid: errors.length === 0,
88
+ errors,
89
+ leakScanPassed,
90
+ potentialLeaks,
91
+ };
92
+ }
93
+ /**
94
+ * Checks for overlapping entities
95
+ */
96
+ function checkOverlappingEntities(entities) {
97
+ const errors = [];
98
+ for (let i = 0; i < entities.length; i++) {
99
+ for (let j = i + 1; j < entities.length; j++) {
100
+ const a = entities[i];
101
+ const b = entities[j];
102
+ if (spansOverlap(a, b)) {
103
+ errors.push({
104
+ code: ValidationErrorCode.OVERLAPPING_ENTITIES,
105
+ message: `Entities ${a.id} (${a.type}) and ${b.id} (${b.type}) overlap`,
106
+ details: {
107
+ entity1: { id: a.id, type: a.type, start: a.start, end: a.end },
108
+ entity2: { id: b.id, type: b.type, start: b.start, end: b.end },
109
+ },
110
+ });
111
+ }
112
+ }
113
+ }
114
+ return errors;
115
+ }
116
+ /**
117
+ * Checks for duplicate IDs
118
+ */
119
+ function checkUniqueIds(entities) {
120
+ const errors = [];
121
+ const seenIds = new Map();
122
+ for (const entity of entities) {
123
+ const existing = seenIds.get(entity.id);
124
+ if (existing !== undefined) {
125
+ // Duplicate ID - only an error if they have different original text
126
+ // (reuse of IDs for same text is allowed with policy.reuseIdsForRepeatedPII)
127
+ if (existing.original !== entity.original) {
128
+ errors.push({
129
+ code: ValidationErrorCode.DUPLICATE_IDS,
130
+ message: `Duplicate ID ${entity.id} used for different text values`,
131
+ details: {
132
+ id: entity.id,
133
+ first: { type: existing.type, text: existing.original },
134
+ second: { type: entity.type, text: entity.original },
135
+ },
136
+ });
137
+ }
138
+ }
139
+ else {
140
+ seenIds.set(entity.id, entity);
141
+ }
142
+ }
143
+ return errors;
144
+ }
145
+ /**
146
+ * Checks that all tags in text are well-formed
147
+ */
148
+ function checkTags(anonymizedText) {
149
+ const errors = [];
150
+ // Find anything that looks like a PII tag
151
+ const tagLikePattern = /<PII[^>]*>/g;
152
+ let match;
153
+ while ((match = tagLikePattern.exec(anonymizedText)) !== null) {
154
+ // Check if it ends with /> for self-closing
155
+ const fullTag = match[0].endsWith('/>') ? match[0] : match[0] + '/>';
156
+ if (!isValidTag(fullTag) && !match[0].endsWith('/>')) {
157
+ errors.push({
158
+ code: ValidationErrorCode.MALFORMED_TAG,
159
+ message: `Malformed PII tag at position ${match.index}`,
160
+ details: { tag: match[0], position: match.index },
161
+ });
162
+ }
163
+ }
164
+ return errors;
165
+ }
166
+ /**
167
+ * Checks that tag count matches entity count
168
+ */
169
+ function checkTagEntityMatch(anonymizedText, entities) {
170
+ const errors = [];
171
+ const tags = extractTags(anonymizedText);
172
+ // Get unique entity IDs
173
+ const entityIds = new Set(entities.map((e) => e.id));
174
+ const tagIds = new Set(tags.map((t) => t.id));
175
+ // Check for mismatches
176
+ for (const id of entityIds) {
177
+ if (!tagIds.has(id)) {
178
+ errors.push({
179
+ code: ValidationErrorCode.ID_MISMATCH,
180
+ message: `Entity ID ${id} not found in anonymized text`,
181
+ details: { missingId: id },
182
+ });
183
+ }
184
+ }
185
+ return errors;
186
+ }
187
+ /**
188
+ * Checks that all entities have entries in PII map
189
+ */
190
+ function checkPIIMapCompleteness(entities, piiMapKeys) {
191
+ const errors = [];
192
+ const keySet = new Set(piiMapKeys);
193
+ for (const entity of entities) {
194
+ const expectedKey = `${entity.type}_${entity.id}`;
195
+ if (!keySet.has(expectedKey)) {
196
+ errors.push({
197
+ code: ValidationErrorCode.MISSING_IN_MAP,
198
+ message: `Entity ${entity.id} (${entity.type}) missing from PII map`,
199
+ details: { entityId: entity.id, entityType: entity.type, expectedKey },
200
+ });
201
+ }
202
+ }
203
+ return errors;
204
+ }
205
+ /**
206
+ * Performs leak scan on anonymized text
207
+ */
208
+ function performLeakScan(anonymizedText, policy) {
209
+ const matches = [];
210
+ // Skip scanning inside PII tags
211
+ const textWithoutTags = anonymizedText.replace(/<PII[^>]*\/>/g, ' '.repeat(20));
212
+ for (const { type, pattern, name } of LEAK_SCAN_PATTERNS) {
213
+ // Skip if type not enabled in policy
214
+ if (!policy.enabledTypes.has(type)) {
215
+ continue;
216
+ }
217
+ const globalPattern = new RegExp(pattern.source, 'g');
218
+ let match;
219
+ while ((match = globalPattern.exec(textWithoutTags)) !== null) {
220
+ // Double-check this isn't inside a tag
221
+ const position = match.index;
222
+ const isInTag = isPositionInsideTag(anonymizedText, position);
223
+ if (!isInTag) {
224
+ matches.push({
225
+ type,
226
+ text: match[0],
227
+ position,
228
+ pattern: name,
229
+ });
230
+ }
231
+ }
232
+ }
233
+ return { matches };
234
+ }
235
+ /**
236
+ * Checks if a position is inside a PII tag
237
+ */
238
+ function isPositionInsideTag(text, position) {
239
+ // Find the nearest < before position
240
+ const before = text.lastIndexOf('<', position);
241
+ if (before === -1)
242
+ return false;
243
+ // Find the nearest > after the <
244
+ const after = text.indexOf('>', before);
245
+ if (after === -1)
246
+ return false;
247
+ // Position is inside tag if it's between < and >
248
+ return position > before && position < after;
249
+ }
250
+ /**
251
+ * Validates that no overlaps exist (fast check)
252
+ */
253
+ export function hasNoOverlaps(entities) {
254
+ if (entities.length <= 1)
255
+ return true;
256
+ const sorted = [...entities].sort((a, b) => a.start - b.start);
257
+ for (let i = 0; i < sorted.length - 1; i++) {
258
+ if (sorted[i].end > sorted[i + 1].start) {
259
+ return false;
260
+ }
261
+ }
262
+ return true;
263
+ }
264
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/pipeline/validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Base Recognizer Interface
3
+ * Defines the contract for all PII recognizers (regex-based)
4
+ */
5
+ import { PIIType, SpanMatch } from '../types/index.js';
6
+ /**
7
+ * Base interface for all PII recognizers
8
+ */
9
+ export interface Recognizer {
10
+ /** The PII type this recognizer detects */
11
+ readonly type: PIIType;
12
+ /** Human-readable name for logging/debugging */
13
+ readonly name: string;
14
+ /** Default confidence score for matches (0.0 to 1.0) */
15
+ readonly defaultConfidence: number;
16
+ /**
17
+ * Finds all matches of this PII type in the given text
18
+ * @param text - The text to search
19
+ * @returns Array of span matches
20
+ */
21
+ find(text: string): SpanMatch[];
22
+ /**
23
+ * Optional validation of a match (e.g., checksum validation)
24
+ * @param match - The matched text
25
+ * @returns true if the match is valid
26
+ */
27
+ validate?(match: string): boolean;
28
+ /**
29
+ * Optional normalization of a match for storage
30
+ * @param match - The matched text
31
+ * @returns Normalized version of the match
32
+ */
33
+ normalize?(match: string): string;
34
+ }
35
+ /**
36
+ * Base class for regex-based recognizers
37
+ */
38
+ export declare abstract class RegexRecognizer implements Recognizer {
39
+ abstract readonly type: PIIType;
40
+ abstract readonly name: string;
41
+ readonly defaultConfidence: number;
42
+ /** Compiled regex pattern(s) for matching */
43
+ protected abstract readonly patterns: RegExp[];
44
+ /**
45
+ * Finds all matches using the configured patterns
46
+ */
47
+ find(text: string): SpanMatch[];
48
+ /**
49
+ * Removes duplicate matches (same span matched by multiple patterns)
50
+ */
51
+ protected deduplicateMatches(matches: SpanMatch[]): SpanMatch[];
52
+ /**
53
+ * Default validation (always passes)
54
+ * Override in subclasses for checksum validation etc.
55
+ */
56
+ validate?(match: string): boolean;
57
+ /**
58
+ * Default normalization (returns as-is)
59
+ * Override in subclasses for specific normalization
60
+ */
61
+ normalize?(match: string): string;
62
+ }
63
+ /**
64
+ * Configuration for a regex recognizer created from patterns
65
+ */
66
+ export interface RegexRecognizerConfig {
67
+ type: PIIType;
68
+ name: string;
69
+ patterns: RegExp[];
70
+ defaultConfidence?: number;
71
+ validate?: (match: string) => boolean;
72
+ normalize?: (match: string) => string;
73
+ }
74
+ /**
75
+ * Creates a simple regex recognizer from configuration
76
+ */
77
+ export declare function createRegexRecognizer(config: RegexRecognizerConfig): Recognizer;
78
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/recognizers/base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,SAAS,EAAmB,MAAM,mBAAmB,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAEvB,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,wDAAwD;IACxD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAEnC;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAEhC;;;;OAIG;IACH,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAElC;;;;OAIG;IACH,SAAS,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACnC;AAED;;GAEG;AACH,8BAAsB,eAAgB,YAAW,UAAU;IACzD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAQ;IAE1C,6CAA6C;IAC7C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAE/C;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAiC/B;;OAEG;IACH,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE;IAe/D;;;OAGG;IACH,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAEjC;;;OAGG;IACH,SAAS,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,UAAU,CA8C/E"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Base Recognizer Interface
3
+ * Defines the contract for all PII recognizers (regex-based)
4
+ */
5
+ import { DetectionSource } from '../types/index.js';
6
+ /**
7
+ * Base class for regex-based recognizers
8
+ */
9
+ export class RegexRecognizer {
10
+ defaultConfidence = 0.95;
11
+ /**
12
+ * Finds all matches using the configured patterns
13
+ */
14
+ find(text) {
15
+ const matches = [];
16
+ for (const pattern of this.patterns) {
17
+ // Ensure pattern has global flag for matchAll
18
+ const globalPattern = pattern.global
19
+ ? pattern
20
+ : new RegExp(pattern.source, pattern.flags + 'g');
21
+ for (const match of text.matchAll(globalPattern)) {
22
+ if (match.index === undefined)
23
+ continue;
24
+ const matchText = match[0];
25
+ // Skip if validation fails
26
+ if (this.validate !== undefined && !this.validate(matchText)) {
27
+ continue;
28
+ }
29
+ matches.push({
30
+ type: this.type,
31
+ start: match.index,
32
+ end: match.index + matchText.length,
33
+ confidence: this.defaultConfidence,
34
+ source: DetectionSource.REGEX,
35
+ text: matchText,
36
+ });
37
+ }
38
+ }
39
+ return this.deduplicateMatches(matches);
40
+ }
41
+ /**
42
+ * Removes duplicate matches (same span matched by multiple patterns)
43
+ */
44
+ deduplicateMatches(matches) {
45
+ const seen = new Set();
46
+ const unique = [];
47
+ for (const match of matches) {
48
+ const key = `${match.start}:${match.end}`;
49
+ if (!seen.has(key)) {
50
+ seen.add(key);
51
+ unique.push(match);
52
+ }
53
+ }
54
+ return unique;
55
+ }
56
+ }
57
+ /**
58
+ * Creates a simple regex recognizer from configuration
59
+ */
60
+ export function createRegexRecognizer(config) {
61
+ return {
62
+ type: config.type,
63
+ name: config.name,
64
+ defaultConfidence: config.defaultConfidence ?? 0.95,
65
+ find(text) {
66
+ const matches = [];
67
+ const seen = new Set();
68
+ for (const pattern of config.patterns) {
69
+ const globalPattern = pattern.global
70
+ ? pattern
71
+ : new RegExp(pattern.source, pattern.flags + 'g');
72
+ for (const match of text.matchAll(globalPattern)) {
73
+ if (match.index === undefined)
74
+ continue;
75
+ const matchText = match[0];
76
+ const key = `${match.index}:${match.index + matchText.length}`;
77
+ if (seen.has(key))
78
+ continue;
79
+ // Skip if validation fails
80
+ if (config.validate !== undefined && !config.validate(matchText)) {
81
+ continue;
82
+ }
83
+ seen.add(key);
84
+ matches.push({
85
+ type: config.type,
86
+ start: match.index,
87
+ end: match.index + matchText.length,
88
+ confidence: config.defaultConfidence ?? 0.95,
89
+ source: DetectionSource.REGEX,
90
+ text: matchText,
91
+ });
92
+ }
93
+ }
94
+ return matches;
95
+ },
96
+ validate: config.validate,
97
+ normalize: config.normalize,
98
+ };
99
+ }
100
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/recognizers/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * BIC/SWIFT Code Recognizer
3
+ * Bank Identifier Code (ISO 9362)
4
+ */
5
+ import type { Recognizer } from './base.js';
6
+ /**
7
+ * BIC/SWIFT code recognizer
8
+ */
9
+ export declare const bicSwiftRecognizer: Recognizer;
10
+ //# sourceMappingURL=bic-swift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bic-swift.d.ts","sourceRoot":"","sources":["../../src/recognizers/bic-swift.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AA2C5C;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAsEhC,CAAC"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * BIC/SWIFT Code Recognizer
3
+ * Bank Identifier Code (ISO 9362)
4
+ */
5
+ import { PIIType, DetectionSource } from '../types/index.js';
6
+ /**
7
+ * BIC/SWIFT code pattern
8
+ * Format: AAAA BB CC DDD (8 or 11 characters)
9
+ * - AAAA: Bank code (4 letters)
10
+ * - BB: Country code (2 letters, ISO 3166-1)
11
+ * - CC: Location code (2 alphanumeric)
12
+ * - DDD: Branch code (3 alphanumeric, optional)
13
+ */
14
+ const BIC_PATTERN = /\b[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}(?:[A-Z0-9]{3})?\b/g;
15
+ /**
16
+ * Valid ISO 3166-1 alpha-2 country codes (common subset)
17
+ */
18
+ const VALID_COUNTRY_CODES = new Set([
19
+ 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AR', 'AS', 'AT', 'AU', 'AW', 'AZ',
20
+ 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT', 'BW', 'BY', 'BZ',
21
+ 'CA', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CY', 'CZ',
22
+ 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ',
23
+ 'EC', 'EE', 'EG', 'ER', 'ES', 'ET',
24
+ 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR',
25
+ 'GA', 'GB', 'GD', 'GE', 'GF', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GT', 'GU', 'GW', 'GY',
26
+ 'HK', 'HN', 'HR', 'HT', 'HU',
27
+ 'ID', 'IE', 'IL', 'IN', 'IQ', 'IR', 'IS', 'IT',
28
+ 'JM', 'JO', 'JP',
29
+ 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ',
30
+ 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY',
31
+ 'MA', 'MC', 'MD', 'ME', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ',
32
+ 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ',
33
+ 'OM',
34
+ 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY',
35
+ 'QA',
36
+ 'RE', 'RO', 'RS', 'RU', 'RW',
37
+ 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SY', 'SZ',
38
+ 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ',
39
+ 'UA', 'UG', 'US', 'UY', 'UZ',
40
+ 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU',
41
+ 'WF', 'WS',
42
+ 'YE', 'YT',
43
+ 'ZA', 'ZM', 'ZW',
44
+ ]);
45
+ /**
46
+ * BIC/SWIFT code recognizer
47
+ */
48
+ export const bicSwiftRecognizer = {
49
+ type: PIIType.BIC_SWIFT,
50
+ name: 'BIC/SWIFT Code',
51
+ defaultConfidence: 0.95,
52
+ find(text) {
53
+ const matches = [];
54
+ const pattern = new RegExp(BIC_PATTERN.source, 'g');
55
+ for (const match of text.matchAll(pattern)) {
56
+ if (match.index === undefined)
57
+ continue;
58
+ const bic = match[0];
59
+ // Validate the BIC code
60
+ if (!this.validate(bic))
61
+ continue;
62
+ matches.push({
63
+ type: PIIType.BIC_SWIFT,
64
+ start: match.index,
65
+ end: match.index + bic.length,
66
+ confidence: this.defaultConfidence,
67
+ source: DetectionSource.REGEX,
68
+ text: bic,
69
+ });
70
+ }
71
+ return matches;
72
+ },
73
+ validate(bic) {
74
+ const normalized = bic.toUpperCase();
75
+ // Check length (8 or 11 characters)
76
+ if (normalized.length !== 8 && normalized.length !== 11) {
77
+ return false;
78
+ }
79
+ // Extract and validate country code (characters 5-6)
80
+ const countryCode = normalized.slice(4, 6);
81
+ if (!VALID_COUNTRY_CODES.has(countryCode)) {
82
+ return false;
83
+ }
84
+ // Bank code should be letters only
85
+ const bankCode = normalized.slice(0, 4);
86
+ if (!/^[A-Z]{4}$/.test(bankCode)) {
87
+ return false;
88
+ }
89
+ // Location code should be alphanumeric
90
+ const locationCode = normalized.slice(6, 8);
91
+ if (!/^[A-Z0-9]{2}$/.test(locationCode)) {
92
+ return false;
93
+ }
94
+ // Branch code (if present) should be alphanumeric
95
+ if (normalized.length === 11) {
96
+ const branchCode = normalized.slice(8, 11);
97
+ if (!/^[A-Z0-9]{3}$/.test(branchCode)) {
98
+ return false;
99
+ }
100
+ }
101
+ return true;
102
+ },
103
+ normalize(bic) {
104
+ return bic.toUpperCase().trim();
105
+ },
106
+ };
107
+ //# sourceMappingURL=bic-swift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bic-swift.js","sourceRoot":"","sources":["../../src/recognizers/bic-swift.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Credit Card Number Recognizer
3
+ * Detects major card types with Luhn checksum validation
4
+ */
5
+ import type { Recognizer } from './base.js';
6
+ /**
7
+ * Credit card patterns for major card types
8
+ * All patterns allow optional separators (spaces, dashes)
9
+ */
10
+ declare const CARD_PATTERNS: {
11
+ visa: RegExp;
12
+ mastercard: RegExp;
13
+ amex: RegExp;
14
+ discover: RegExp;
15
+ diners: RegExp;
16
+ jcb: RegExp;
17
+ generic: RegExp;
18
+ };
19
+ /**
20
+ * Card type names for identification
21
+ */
22
+ type CardType = keyof typeof CARD_PATTERNS;
23
+ /**
24
+ * Credit card recognizer with Luhn validation
25
+ */
26
+ export declare const creditCardRecognizer: Recognizer;
27
+ /**
28
+ * Identifies the card type from a card number
29
+ */
30
+ export declare function identifyCardType(cardNumber: string): CardType | 'unknown';
31
+ export {};
32
+ //# sourceMappingURL=credit-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credit-card.d.ts","sourceRoot":"","sources":["../../src/recognizers/credit-card.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C;;;GAGG;AACH,QAAA,MAAM,aAAa;;;;;;;;CAuBlB,CAAC;AAEF;;GAEG;AACH,KAAK,QAAQ,GAAG,MAAM,OAAO,aAAa,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAuElC,CAAC;AA6DF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAWzE"}