euredact 0.6.0 → 0.7.1
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/NOTICE +11 -0
- package/README.md +455 -44
- package/dist/cjs/cache.js +2 -8
- package/dist/cjs/cloud/account.js +180 -0
- package/dist/cjs/cloud/batches.js +469 -0
- package/dist/cjs/cloud/client.js +124 -14
- package/dist/cjs/cloud/config.js +28 -2
- package/dist/cjs/cloud/errors.js +39 -2
- package/dist/cjs/cloud/index.js +16 -1
- package/dist/cjs/index.js +9 -1
- package/dist/cjs/platform.browser.js +98 -0
- package/dist/cjs/platform.js +140 -0
- package/dist/cjs/rules/bicGleif.js +57 -0
- package/dist/cjs/rules/bicRegistry.js +37 -11
- package/dist/cjs/rules/countries/index.js +83 -13
- package/dist/cjs/rules/cues.js +29 -9
- package/dist/cjs/rules/engine.js +14 -6
- package/dist/cjs/rules/suppressors.js +479 -26
- package/dist/cjs/rules/validators.js +50 -0
- package/dist/cjs/sdk.js +108 -14
- package/dist/cjs/types.js +4 -1
- package/dist/esm/cache.js +2 -8
- package/dist/esm/cloud/account.d.ts +155 -0
- package/dist/esm/cloud/account.js +175 -0
- package/dist/esm/cloud/batches.d.ts +166 -0
- package/dist/esm/cloud/batches.js +464 -0
- package/dist/esm/cloud/client.d.ts +83 -1
- package/dist/esm/cloud/client.js +119 -22
- package/dist/esm/cloud/config.d.ts +6 -0
- package/dist/esm/cloud/config.js +27 -2
- package/dist/esm/cloud/errors.d.ts +26 -1
- package/dist/esm/cloud/errors.js +35 -1
- package/dist/esm/cloud/index.d.ts +4 -2
- package/dist/esm/cloud/index.js +4 -2
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/platform.browser.d.ts +27 -0
- package/dist/esm/platform.browser.js +92 -0
- package/dist/esm/platform.d.ts +20 -0
- package/dist/esm/platform.js +101 -0
- package/dist/esm/rules/bicGleif.d.ts +4 -0
- package/dist/esm/rules/bicGleif.js +53 -0
- package/dist/esm/rules/bicRegistry.d.ts +25 -11
- package/dist/esm/rules/bicRegistry.js +36 -11
- package/dist/esm/rules/countries/index.js +83 -13
- package/dist/esm/rules/cues.d.ts +1 -1
- package/dist/esm/rules/cues.js +29 -9
- package/dist/esm/rules/engine.js +14 -6
- package/dist/esm/rules/suppressors.d.ts +1 -0
- package/dist/esm/rules/suppressors.js +478 -25
- package/dist/esm/rules/validators.d.ts +14 -0
- package/dist/esm/rules/validators.js +47 -0
- package/dist/esm/sdk.d.ts +77 -4
- package/dist/esm/sdk.js +108 -17
- package/dist/esm/types.d.ts +64 -6
- package/dist/esm/types.js +4 -1
- package/package.json +13 -4
package/dist/esm/rules/cues.js
CHANGED
|
@@ -90,7 +90,7 @@ export const CUES = [
|
|
|
90
90
|
/(?<![A-Za-z0-9_])(?:phone|tel|telephone|téléphone|telefoon|telefon|telefono|teléfono|tlf|mobil|mobile|gsm|handy|sími|puh|móvil|cell|tālrunis|τηλέφωνο|τηλ)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
91
91
|
// National identity number.
|
|
92
92
|
[EntityType.NATIONAL_ID,
|
|
93
|
-
/(?<![A-Za-z0-9_])(?:bsn|burgerservicenummer(?:\s*\(bsn\))?|personnummer|rijksregisternummer|nationaal\s*nummer|numéro\s*national|national\s*(?:id|number)|identiteitsnummer|henkilötunnus|kennitala|cpr(?:-?nummer)?|nif|nie|
|
|
93
|
+
/(?<![A-Za-z0-9_])(?:bsn(?!r)|burgerservicenummer(?:\s*\(bsn\))?|personnummer|rijksregisternummer|nationaal\s*nummer|numéro\s*national|national\s*(?:id|number)|identiteitsnummer|henkilötunnus|kennitala|cpr(?:-?nummer)?|nif|nie|dnie?(?![A-Za-z]|[^\x00-\x7F])|rr|nn|nir|insz|niss|nis|matricule|id\s*card(?:\s*(?:no|nr|number))?|ausweisnummer|personalausweis|osobní\s*číslo|ЕГН|EGN|dow[óo]d(?:u|em)?\s*osobist(?:y|ego|ym)|nr\s*dowodu|ahv(?:-?(?:nr|nummer))?|avs)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
94
94
|
// Cyprus: "ID number" in both official languages, plus the Greek abbreviation
|
|
95
95
|
// ΑΔΤ (Αστυνομική Ταυτότητα). Neither has a phone reading.
|
|
96
96
|
[EntityType.NATIONAL_ID,
|
|
@@ -111,16 +111,16 @@ export const CUES = [
|
|
|
111
111
|
/(?<![A-Za-z0-9_])(?:αφμ|α\.φ\.μ\.|steuerliche\s*identifikations-?nummer|steuer-?identifikations-?nummer|steuer-?id-?nr\.?|steuer-?id|steuernummer|st\.?-?nr|stnr|tin|finanzamt\s+ist|tax\s*(?:id|no|number)|daňové\s*číslo|numer\s*podatkowy)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
112
112
|
// Health insurance: the insured person.
|
|
113
113
|
[EntityType.HEALTH_INSURANCE,
|
|
114
|
-
/(?<![A-Za-z0-9_])(?:versichertennummer|krankenversicherung|kvnr|kv-?nr|mutualité|ziekenfonds|aansluitingsnummer|medical\s*card(?:\s*(?:no|number))?)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
114
|
+
/(?<![A-Za-z0-9_])(?:versichertennummer|krankenversicherung|kvnr|kv-?nr|mutualité|ziekenfonds|aansluitingsnummer|medical\s*card(?:\s*(?:no|number))?|nhs(?:\s*(?:no|number))?)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
115
115
|
// Healthcare provider: the clinician or practice, not the patient — the Dutch
|
|
116
116
|
// AGB-code, the German LANR, the UK GMC number.
|
|
117
117
|
[EntityType.HEALTHCARE_PROVIDER,
|
|
118
|
-
/(?<![A-Za-z0-9_])(?:agb-?code|lanr|bsnr|gmc(?:\s*(?:no|number|reg))?|big
|
|
118
|
+
/(?<![A-Za-z0-9_])(?:agb-?code|lanr|bsnr|gmc(?:\s*(?:no|number|reg))?|big(?:-?registratie)?-?(?:nummer|nr)|zorgverlener(?:snummer)?|lebenslange\s*arztnummer|betriebsst[äa]ttennummer|rpps|adeli|pwz)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
119
119
|
// Company / trade register. "Companies House" and "Company Registration
|
|
120
120
|
// Number" are written out: the tail allows a run-on *or* one qualifier word,
|
|
121
121
|
// never a second word, so a three-word label needs to be spelled.
|
|
122
122
|
[EntityType.CHAMBER_OF_COMMERCE,
|
|
123
|
-
/(?<![A-Za-z0-9_])(?:siren|siret|kbo|bce|kvk|ondernemingsnummer|ondernemingen\s+onder\s+nummer|kruispuntbank|numéro\s*d'entreprise|enterprise\s*number|handelsregister|companies\s*house(?:\s*(?:registration|reg|no|number))?|company\s*registration(?:\s*(?:number|no))?|company\s*(?:no|number|reg)|organisationsnummer|orgnr|i[čc]o|identifikační\s*číslo|ЕИК|eik|bulstat|cvr(?:-?nummer)?|virksomhedsnummer)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
123
|
+
/(?<![A-Za-z0-9_])(?:siren|siret|kbo|bce|kvk|ondernemingsnummer|ondernemingen\s+onder\s+nummer|kruispuntbank|numéro\s*d'entreprise|enterprise\s*number|handelsregister|companies\s*house(?:\s*(?:registration|reg|no|number))?|company\s*registration(?:\s*(?:number|no))?|company\s*(?:no|number|reg)|organisationsnummer|orgnr|i[čc]o|identifikační\s*číslo|ЕИК|eik|bulstat|cvr(?:-?nummer)?|virksomhedsnummer|regon|krs)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
124
124
|
// VAT.
|
|
125
125
|
[EntityType.VAT,
|
|
126
126
|
/(?<![A-Za-z0-9_])(?:vat|btw|tva|ust|iva|moms|alv|mwst|dič|vsk)(?:(?:[A-Za-z0-9_.\-]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
@@ -130,6 +130,15 @@ export const CUES = [
|
|
|
130
130
|
[EntityType.BANK_ACCOUNT,
|
|
131
131
|
/(?<![A-Za-z0-9_])(?:sort\s*code|account\s*(?:no|number)|rekeningnummer|kontonummer|numéro\s*de\s*compte|sort-?code)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
132
132
|
// Passport.
|
|
133
|
+
// Residence permit. No permit patterns exist, so a permit number was filed
|
|
134
|
+
// under whichever ID, passport or phone pattern fitted it (rules-engine#53).
|
|
135
|
+
// The tail admits the Belgian card category ("nr. B 565992336"), unmasked.
|
|
136
|
+
[EntityType.RESIDENCE_PERMIT,
|
|
137
|
+
/(?<![A-Za-z0-9_])(?:aufenthalts(?:titel|erlaubnis|karte|gestattung)|niederlassungs(?:erlaubnis|bewilligung)|verblijfs(?:vergunning|kaart|document|titel)|titre\s*de\s*s[ée]jour|carte\s*de\s*s[ée]jour|permis\s*de\s*s[ée]jour|carte\s*de\s*r[ée]sident|residence\s*(?:permit|card|document)|biometric\s*residence\s*permit|permesso\s*di\s*soggiorno|carta\s*di\s*soggiorno|kart(?:a|y|ę|ą)\s*pobytu(?:\s*cukr)?|naklejk(?:a|i|ę|ą)\s*wizow(?:a|ej|ą)|uppehållstillstånd|opholdstilladelse|oppholdstillatelse|oleskelulupa)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*(?:[A-Z]\s+)?$/i],
|
|
138
|
+
// Driving licence: Polish labels; the document number has the passport
|
|
139
|
+
// shape, so without this cue it lost the span to the passport rule (rules-engine#77).
|
|
140
|
+
[EntityType.DRIVERS_LICENSE,
|
|
141
|
+
/(?<![A-Za-z0-9_])(?:(?:nr\s*dokumentu\s*)?(?:prawo|prawa|prawem)\s*jazdy|numer\s*blankietu\s*prawa\s*jazdy)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
133
142
|
[EntityType.PASSPORT,
|
|
134
143
|
/(?<![A-Za-z0-9_])(?:passport(?:\s*(?:no|number))?|paspoort(?:nummer)?|reisepass(?:nummer)?|passeport|passnummer)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
135
144
|
// BIC / SWIFT.
|
|
@@ -146,7 +155,7 @@ export const CUES = [
|
|
|
146
155
|
// only thing that identifies one, which is why the engine emits this type
|
|
147
156
|
// from here and nowhere else.
|
|
148
157
|
[EntityType.INTERNAL_ID,
|
|
149
|
-
/(?<![A-Za-z0-9_])(?:medarbejdernummer|ansattnummer|anställningsnummer|personalnummer|personeelsnummer|matricule\s*salarié|employee\s*(?:no|number|id)|badge(?:\s*(?:no|number))?|betriebsstätten(?:nr|nummer)|grundstücks(?:nr|nummer)|dossier-?(?:nr|nummer)|aktenzeichen|osobní\s*(?:číslo\s*)?zaměstnance)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
158
|
+
/(?<![A-Za-z0-9_])(?:medarbejdernummer|ansattnummer|anställningsnummer|personalnummer|personeelsnummer|matricule\s*salarié|employee\s*(?:no|number|id)|badge(?:\s*(?:no|number))?|betriebsstätten(?:nr|nummer)|grundstücks(?:nr|nummer)|dossier-?(?:nr|nummer)|aktenzeichen|schade(?:claim|nummer|dossier)|schadens?-?(?:nummer|nr)|num[ée]ro\s*de\s*sinistre|numero\s*(?:di\s*)?sinistro|n[úu]mero\s*de\s*siniestro|skade(?:nummer|sag)|claim\s*(?:no|number|id)|collar|osobní\s*(?:číslo\s*)?zaměstnance)(?:(?:[A-Za-z0-9_]|[^\x00-\x7F])*|\s+[^\s:.\-\d,;()\/]{2,20})\s*\)?\s*[:.\-]*\s*$/i],
|
|
150
159
|
// Credential. Typed SECRET because that is the type this SDK has; the
|
|
151
160
|
// training pipeline's report asks for CREDENTIAL, which does not exist here.
|
|
152
161
|
[EntityType.SECRET,
|
|
@@ -192,6 +201,13 @@ const RETYPABLE = new Set([
|
|
|
192
201
|
* "Betriebsstättennr. 260326822" both landed, each reported as Czech.
|
|
193
202
|
*/
|
|
194
203
|
const RETYPABLE_UNCORROBORATED = new Set([EntityType.NATIONAL_ID]);
|
|
204
|
+
/**
|
|
205
|
+
* Retypable to RESIDENCE_PERMIT by a permit label touching the span, whatever
|
|
206
|
+
* the country support: a German eAT number fits the identity-card pattern and a
|
|
207
|
+
* Dutch permit number the passport pattern (rules-engine#53). Not a Spanish
|
|
208
|
+
* NIE, which the canon keeps NATIONAL_ID.
|
|
209
|
+
*/
|
|
210
|
+
const RETYPABLE_BY_PERMIT_LABEL = new Set([EntityType.NATIONAL_ID, EntityType.PASSPORT]);
|
|
195
211
|
/**
|
|
196
212
|
* Types a label can assert on its own.
|
|
197
213
|
*
|
|
@@ -205,7 +221,7 @@ export const CUE_TARGETS = new Set([
|
|
|
205
221
|
EntityType.HEALTH_INSURANCE, EntityType.HEALTHCARE_PROVIDER,
|
|
206
222
|
EntityType.CHAMBER_OF_COMMERCE, EntityType.VAT, EntityType.POSTAL_CODE,
|
|
207
223
|
EntityType.PASSPORT, EntityType.INTERNAL_ID, EntityType.BANK_ACCOUNT,
|
|
208
|
-
EntityType.SECRET,
|
|
224
|
+
EntityType.SECRET, EntityType.RESIDENCE_PERMIT,
|
|
209
225
|
]);
|
|
210
226
|
/**
|
|
211
227
|
* Which of those a label may also *rescue* — re-admit after its checksum
|
|
@@ -242,13 +258,17 @@ export const RESCUE_TARGETS = new Set([
|
|
|
242
258
|
* `countryScore` is the document's support for the country the winning pattern
|
|
243
259
|
* came from; see RETYPABLE_UNCORROBORATED.
|
|
244
260
|
*/
|
|
245
|
-
export function retypedBy(text, start, entityType, countryScore) {
|
|
261
|
+
export function retypedBy(text, start, entityType, countryScore, country = null) {
|
|
246
262
|
const type = String(entityType);
|
|
247
|
-
|
|
248
|
-
|
|
263
|
+
const general = RETYPABLE.has(type)
|
|
264
|
+
|| (RETYPABLE_UNCORROBORATED.has(type) && countryScore === 0);
|
|
265
|
+
const byPermit = RETYPABLE_BY_PERMIT_LABEL.has(type) && country !== "ES";
|
|
266
|
+
if (!general && !byPermit)
|
|
249
267
|
return null;
|
|
250
268
|
const cued = cuedType(text, start);
|
|
251
269
|
if (cued === null || cued === entityType || !CUE_TARGETS.has(String(cued)))
|
|
252
270
|
return null;
|
|
271
|
+
if (!general && cued !== EntityType.RESIDENCE_PERMIT)
|
|
272
|
+
return null;
|
|
253
273
|
return cued;
|
|
254
274
|
}
|
package/dist/esm/rules/engine.js
CHANGED
|
@@ -242,12 +242,20 @@ export class RuleEngine {
|
|
|
242
242
|
if (this.matcher.validate(m)) {
|
|
243
243
|
validated.push({ match: m, hasValidValidator: m.patternDef.validator !== null });
|
|
244
244
|
}
|
|
245
|
-
else if (m.patternDef.validator !== null
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (
|
|
249
|
-
|
|
245
|
+
else if (m.patternDef.validator !== null) {
|
|
246
|
+
const cued = RESCUE_TARGETS.has(String(m.patternDef.entityType))
|
|
247
|
+
&& cuedType(text, m.start) === m.patternDef.entityType;
|
|
248
|
+
if (!m.patternDef.requiresContext) {
|
|
249
|
+
failedSpans.push({ start: m.start, end: m.end, code: m.countryCode,
|
|
250
|
+
etype: String(m.patternDef.entityType) });
|
|
251
|
+
if (cued)
|
|
252
|
+
rescued.push(m);
|
|
253
|
+
}
|
|
254
|
+
else if (cued) {
|
|
255
|
+
// A label-gated pattern is rescued too, but only by a cue touching the
|
|
256
|
+
// value; it casts no demotion zone (rules-engine#75).
|
|
250
257
|
rescued.push(m);
|
|
258
|
+
}
|
|
251
259
|
}
|
|
252
260
|
}
|
|
253
261
|
// Evidence pass: work out which countries this document belongs to, from
|
|
@@ -457,7 +465,7 @@ export class RuleEngine {
|
|
|
457
465
|
// the value is filed as a Cypriot identity number. Dropping it also clears
|
|
458
466
|
// outOfScope, which would otherwise claim the detection belongs to a
|
|
459
467
|
// country the caller did not declare while naming no country at all.
|
|
460
|
-
const retyped = retypedBy(text, match.start, entityType, countryScores.get(match.countryCode) ?? 0);
|
|
468
|
+
const retyped = retypedBy(text, match.start, entityType, countryScores.get(match.countryCode) ?? 0, match.countryCode);
|
|
461
469
|
if (retyped !== null) {
|
|
462
470
|
entityType = retyped;
|
|
463
471
|
country = null;
|