@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.
- package/README.md +382 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +6 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/pii-map-crypto.d.ts +100 -0
- package/dist/crypto/pii-map-crypto.d.ts.map +1 -0
- package/dist/crypto/pii-map-crypto.js +163 -0
- package/dist/crypto/pii-map-crypto.js.map +1 -0
- package/dist/index.d.ts +173 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +294 -0
- package/dist/index.js.map +1 -0
- package/dist/ner/bio-decoder.d.ts +64 -0
- package/dist/ner/bio-decoder.d.ts.map +1 -0
- package/dist/ner/bio-decoder.js +216 -0
- package/dist/ner/bio-decoder.js.map +1 -0
- package/dist/ner/index.d.ts +10 -0
- package/dist/ner/index.d.ts.map +1 -0
- package/dist/ner/index.js +10 -0
- package/dist/ner/index.js.map +1 -0
- package/dist/ner/model-manager.d.ts +102 -0
- package/dist/ner/model-manager.d.ts.map +1 -0
- package/dist/ner/model-manager.js +253 -0
- package/dist/ner/model-manager.js.map +1 -0
- package/dist/ner/ner-model.d.ts +114 -0
- package/dist/ner/ner-model.d.ts.map +1 -0
- package/dist/ner/ner-model.js +240 -0
- package/dist/ner/ner-model.js.map +1 -0
- package/dist/ner/onnx-runtime.d.ts +45 -0
- package/dist/ner/onnx-runtime.d.ts.map +1 -0
- package/dist/ner/onnx-runtime.js +99 -0
- package/dist/ner/onnx-runtime.js.map +1 -0
- package/dist/ner/tokenizer.d.ts +140 -0
- package/dist/ner/tokenizer.d.ts.map +1 -0
- package/dist/ner/tokenizer.js +341 -0
- package/dist/ner/tokenizer.js.map +1 -0
- package/dist/pipeline/index.d.ts +9 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +9 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/prenormalize.d.ts +48 -0
- package/dist/pipeline/prenormalize.d.ts.map +1 -0
- package/dist/pipeline/prenormalize.js +94 -0
- package/dist/pipeline/prenormalize.js.map +1 -0
- package/dist/pipeline/resolver.d.ts +56 -0
- package/dist/pipeline/resolver.d.ts.map +1 -0
- package/dist/pipeline/resolver.js +238 -0
- package/dist/pipeline/resolver.js.map +1 -0
- package/dist/pipeline/tagger.d.ts +74 -0
- package/dist/pipeline/tagger.d.ts.map +1 -0
- package/dist/pipeline/tagger.js +169 -0
- package/dist/pipeline/tagger.js.map +1 -0
- package/dist/pipeline/validator.d.ts +65 -0
- package/dist/pipeline/validator.d.ts.map +1 -0
- package/dist/pipeline/validator.js +264 -0
- package/dist/pipeline/validator.js.map +1 -0
- package/dist/recognizers/base.d.ts +78 -0
- package/dist/recognizers/base.d.ts.map +1 -0
- package/dist/recognizers/base.js +100 -0
- package/dist/recognizers/base.js.map +1 -0
- package/dist/recognizers/bic-swift.d.ts +10 -0
- package/dist/recognizers/bic-swift.d.ts.map +1 -0
- package/dist/recognizers/bic-swift.js +107 -0
- package/dist/recognizers/bic-swift.js.map +1 -0
- package/dist/recognizers/credit-card.d.ts +32 -0
- package/dist/recognizers/credit-card.d.ts.map +1 -0
- package/dist/recognizers/credit-card.js +160 -0
- package/dist/recognizers/credit-card.js.map +1 -0
- package/dist/recognizers/custom-id.d.ts +28 -0
- package/dist/recognizers/custom-id.d.ts.map +1 -0
- package/dist/recognizers/custom-id.js +116 -0
- package/dist/recognizers/custom-id.js.map +1 -0
- package/dist/recognizers/email.d.ts +10 -0
- package/dist/recognizers/email.d.ts.map +1 -0
- package/dist/recognizers/email.js +75 -0
- package/dist/recognizers/email.js.map +1 -0
- package/dist/recognizers/iban.d.ts +14 -0
- package/dist/recognizers/iban.d.ts.map +1 -0
- package/dist/recognizers/iban.js +67 -0
- package/dist/recognizers/iban.js.map +1 -0
- package/dist/recognizers/index.d.ts +20 -0
- package/dist/recognizers/index.d.ts.map +1 -0
- package/dist/recognizers/index.js +42 -0
- package/dist/recognizers/index.js.map +1 -0
- package/dist/recognizers/ip-address.d.ts +14 -0
- package/dist/recognizers/ip-address.d.ts.map +1 -0
- package/dist/recognizers/ip-address.js +183 -0
- package/dist/recognizers/ip-address.js.map +1 -0
- package/dist/recognizers/phone.d.ts +10 -0
- package/dist/recognizers/phone.d.ts.map +1 -0
- package/dist/recognizers/phone.js +145 -0
- package/dist/recognizers/phone.js.map +1 -0
- package/dist/recognizers/registry.d.ts +59 -0
- package/dist/recognizers/registry.d.ts.map +1 -0
- package/dist/recognizers/registry.js +113 -0
- package/dist/recognizers/registry.js.map +1 -0
- package/dist/recognizers/url.d.ts +14 -0
- package/dist/recognizers/url.d.ts.map +1 -0
- package/dist/recognizers/url.js +121 -0
- package/dist/recognizers/url.js.map +1 -0
- package/dist/types/index.d.ts +134 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +69 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/pii-types.d.ts +50 -0
- package/dist/types/pii-types.d.ts.map +1 -0
- package/dist/types/pii-types.js +114 -0
- package/dist/types/pii-types.js.map +1 -0
- package/dist/utils/iban-checksum.d.ts +23 -0
- package/dist/utils/iban-checksum.d.ts.map +1 -0
- package/dist/utils/iban-checksum.js +106 -0
- package/dist/utils/iban-checksum.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/luhn.d.ts +17 -0
- package/dist/utils/luhn.d.ts.map +1 -0
- package/dist/utils/luhn.js +55 -0
- package/dist/utils/luhn.js.map +1 -0
- package/dist/utils/offsets.d.ts +86 -0
- package/dist/utils/offsets.d.ts.map +1 -0
- package/dist/utils/offsets.js +124 -0
- package/dist/utils/offsets.js.map +1 -0
- 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 @@
|
|
|
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"}
|