euredact 0.6.0 → 0.7.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/NOTICE +11 -0
- package/README.md +403 -39
- 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 +63 -10
- package/dist/cjs/rules/cues.js +29 -9
- package/dist/cjs/rules/engine.js +14 -6
- package/dist/cjs/rules/suppressors.js +292 -22
- package/dist/cjs/rules/validators.js +50 -0
- package/dist/cjs/sdk.js +18 -7
- 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 +63 -10
- 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 +291 -21
- package/dist/esm/rules/validators.d.ts +14 -0
- package/dist/esm/rules/validators.js +47 -0
- package/dist/esm/sdk.d.ts +51 -4
- package/dist/esm/sdk.js +18 -9
- package/dist/esm/types.d.ts +58 -2
- package/dist/esm/types.js +4 -1
- package/package.json +12 -4
|
@@ -65,7 +65,21 @@ export declare function validateSpanishDni(candidate: string): boolean;
|
|
|
65
65
|
export declare function validateSpanishNie(candidate: string): boolean;
|
|
66
66
|
export declare function validatePortugueseNif(candidate: string): boolean;
|
|
67
67
|
export declare function validatePolishPesel(candidate: string): boolean;
|
|
68
|
+
/** Polish domestic account number (NRB): the PL IBAN without its "PL", so the IBAN's mod-97 decides it (rules-engine#93). */
|
|
69
|
+
export declare function validatePolishNrb(candidate: string): boolean;
|
|
68
70
|
export declare function validatePolishNip(candidate: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Polish identity card (dowód osobisty): 3 letters + 6 digits, the first digit
|
|
73
|
+
* a check digit. Letters A=10 … Z=35, weights 7,3,1,9,7,3,1,7,3: the weighted
|
|
74
|
+
* sum of all nine is 0 mod 10 exactly when the check digit is right (rules-engine#75).
|
|
75
|
+
*/
|
|
76
|
+
export declare function validatePolishIdCard(candidate: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Polish REGON: 9 digits, or 14 for a local unit, each with a mod-11 check (a
|
|
79
|
+
* remainder of 10 counts as 0). A 14-digit REGON begins with its parent's valid
|
|
80
|
+
* 9-digit REGON (rules-engine#76).
|
|
81
|
+
*/
|
|
82
|
+
export declare function validatePolishRegon(candidate: string): boolean;
|
|
69
83
|
export declare function validateCzechBirthNumber(candidate: string): boolean;
|
|
70
84
|
export declare function validateRomanianCnp(candidate: string): boolean;
|
|
71
85
|
export declare function validateHungarianTaj(candidate: string): boolean;
|
|
@@ -492,6 +492,13 @@ export function validatePolishPesel(candidate) {
|
|
|
492
492
|
total += d[i] * weights[i];
|
|
493
493
|
return d[10] === (10 - (total % 10)) % 10;
|
|
494
494
|
}
|
|
495
|
+
/** Polish domestic account number (NRB): the PL IBAN without its "PL", so the IBAN's mod-97 decides it (rules-engine#93). */
|
|
496
|
+
export function validatePolishNrb(candidate) {
|
|
497
|
+
const c = candidate.replace(/[\s\-]/g, "");
|
|
498
|
+
if (!/^\d{26}$/.test(c))
|
|
499
|
+
return false;
|
|
500
|
+
return validateIban("PL" + c);
|
|
501
|
+
}
|
|
495
502
|
export function validatePolishNip(candidate) {
|
|
496
503
|
const c = candidate.replace(/[\s\-]/g, "");
|
|
497
504
|
if (c.length !== 10 || !/^\d{10}$/.test(c))
|
|
@@ -503,6 +510,43 @@ export function validatePolishNip(candidate) {
|
|
|
503
510
|
total += d[i] * weights[i];
|
|
504
511
|
return total % 11 === d[9];
|
|
505
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Polish identity card (dowód osobisty): 3 letters + 6 digits, the first digit
|
|
515
|
+
* a check digit. Letters A=10 … Z=35, weights 7,3,1,9,7,3,1,7,3: the weighted
|
|
516
|
+
* sum of all nine is 0 mod 10 exactly when the check digit is right (rules-engine#75).
|
|
517
|
+
*/
|
|
518
|
+
export function validatePolishIdCard(candidate) {
|
|
519
|
+
const c = candidate.replace(/\s/g, "").toUpperCase();
|
|
520
|
+
if (!/^[A-Z]{3}\d{6}$/.test(c))
|
|
521
|
+
return false;
|
|
522
|
+
const weights = [7, 3, 1, 9, 7, 3, 1, 7, 3];
|
|
523
|
+
let total = 0;
|
|
524
|
+
for (let i = 0; i < 9; i++) {
|
|
525
|
+
const ch = c[i];
|
|
526
|
+
total += (/[A-Z]/.test(ch) ? ch.charCodeAt(0) - 55 : Number(ch)) * weights[i];
|
|
527
|
+
}
|
|
528
|
+
return total % 10 === 0;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Polish REGON: 9 digits, or 14 for a local unit, each with a mod-11 check (a
|
|
532
|
+
* remainder of 10 counts as 0). A 14-digit REGON begins with its parent's valid
|
|
533
|
+
* 9-digit REGON (rules-engine#76).
|
|
534
|
+
*/
|
|
535
|
+
export function validatePolishRegon(candidate) {
|
|
536
|
+
const c = candidate.replace(/[\s\-]/g, "");
|
|
537
|
+
if (!/^\d+$/.test(c) || (c.length !== 9 && c.length !== 14))
|
|
538
|
+
return false;
|
|
539
|
+
const check = (digits, weights) => {
|
|
540
|
+
let total = 0;
|
|
541
|
+
for (let i = 0; i < weights.length; i++)
|
|
542
|
+
total += Number(digits[i]) * weights[i];
|
|
543
|
+
const rest = total % 11;
|
|
544
|
+
return (rest === 10 ? 0 : rest) === Number(digits[weights.length]);
|
|
545
|
+
};
|
|
546
|
+
if (!check(c.slice(0, 9), [8, 9, 2, 3, 4, 5, 6, 7]))
|
|
547
|
+
return false;
|
|
548
|
+
return c.length === 9 || check(c, [2, 4, 8, 5, 0, 9, 7, 3, 6, 1, 2, 4, 8]);
|
|
549
|
+
}
|
|
506
550
|
// Days per month for the rodné číslo date check. February is 29 because the
|
|
507
551
|
// century is not recoverable from a two-digit year, so a leap year cannot be
|
|
508
552
|
// ruled out -- being permissive by one day is the right direction here.
|
|
@@ -753,6 +797,9 @@ export const VALIDATORS = {
|
|
|
753
797
|
portuguese_nif: validatePortugueseNif,
|
|
754
798
|
polish_pesel: validatePolishPesel,
|
|
755
799
|
polish_nip: validatePolishNip,
|
|
800
|
+
polish_nrb: validatePolishNrb,
|
|
801
|
+
polish_id_card: validatePolishIdCard,
|
|
802
|
+
polish_regon: validatePolishRegon,
|
|
756
803
|
czech_birth_number: validateCzechBirthNumber,
|
|
757
804
|
romanian_cnp: validateRomanianCnp,
|
|
758
805
|
hungarian_taj: validateHungarianTaj,
|
package/dist/esm/sdk.d.ts
CHANGED
|
@@ -22,11 +22,51 @@ type LabelFor = (det: Detection, slice: string) => string;
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function applyReplacements(text: string, detections: Detection[], labelFor: LabelFor): string;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* One label in the text sent to the cloud tier: where it sits in the masked
|
|
26
|
+
* text, and the extent of the original it replaced —
|
|
27
|
+
* `[maskedStart, maskedEnd, start, end]`.
|
|
28
28
|
*/
|
|
29
|
-
export
|
|
29
|
+
export type WireLabel = [number, number, number, number];
|
|
30
|
+
/**
|
|
31
|
+
* Bracket-mask `text` and record where each label landed.
|
|
32
|
+
*
|
|
33
|
+
* Returns what is sent to the cloud tier, plus one `WireLabel` per label.
|
|
34
|
+
* Everything between labels is copied unchanged, so the labels are all it
|
|
35
|
+
* takes to carry an offset from the masked text back to the original.
|
|
36
|
+
*
|
|
37
|
+
* Always `[TYPE]`, whatever label scheme the caller asked for. That is the
|
|
38
|
+
* syntax the model was trained on, where a placeholder means "already handled,
|
|
39
|
+
* do not list it". A token or a numbered label would be read as ordinary text,
|
|
40
|
+
* so the format on the wire is a model contract and not an output option.
|
|
41
|
+
*/
|
|
42
|
+
/** @internal Shared with cloud/batches.ts. */
|
|
43
|
+
export declare function maskForCloud(text: string, detections: Detection[]): [string, WireLabel[]];
|
|
44
|
+
/**
|
|
45
|
+
* Carry the service's spans from the masked text onto the original.
|
|
46
|
+
*
|
|
47
|
+
* The service only ever saw `masked`, so its offsets index that. An offset in
|
|
48
|
+
* copied text shifts by whatever the labels before it added or removed. An
|
|
49
|
+
* offset inside a label has no counterpart in the original, so it snaps
|
|
50
|
+
* outward to the edge of the value the label replaced: an address the model
|
|
51
|
+
* reports around `[POSTAL_CODE]` covers the postal code, never half of it.
|
|
52
|
+
* Over-masking is the safe direction.
|
|
53
|
+
*
|
|
54
|
+
* A span lying wholly inside one label describes the label, not the document.
|
|
55
|
+
* It is dropped; the local detection behind the label stands.
|
|
56
|
+
*
|
|
57
|
+
* Throws `Unplaceable` when a span does not match the text that was sent. Such
|
|
58
|
+
* a span cannot be placed, and masking where it points would cover the wrong
|
|
59
|
+
* characters and leave the right ones in the clear.
|
|
60
|
+
*/
|
|
61
|
+
/** @internal Shared with cloud/batches.ts. */
|
|
62
|
+
export declare function ontoOriginal(spans: Detection[], masked: string, text: string, labels: WireLabel[], Unplaceable: new (message: string) => Error): Detection[];
|
|
63
|
+
/**
|
|
64
|
+
* Characters a token suffix is drawn from. No vowels (and no Y), so a suffix
|
|
65
|
+
* never spells a word; no 0/1/I/O, so it survives being read back by a person;
|
|
66
|
+
* no underscore, so the type prefix stays unambiguous. A, E, U and Y were in it
|
|
67
|
+
* until rules-engine#55, against this comment.
|
|
68
|
+
*/
|
|
69
|
+
export declare const TOKEN_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ23456789";
|
|
30
70
|
export declare const TOKEN_SUFFIX_LENGTH = 4;
|
|
31
71
|
/**
|
|
32
72
|
* Maps each distinct PII value in one call to a reversible token.
|
|
@@ -106,6 +146,13 @@ export interface RedactOptions {
|
|
|
106
146
|
allowlistDomains?: string[] | null;
|
|
107
147
|
detectDates?: boolean;
|
|
108
148
|
cache?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* `mode: "cloud"` only. Sent as the request's `Idempotency-Key`: the same key
|
|
151
|
+
* returns the same job instead of running (and billing) the document again,
|
|
152
|
+
* which is what a caller retrying after its own timeout needs. One is
|
|
153
|
+
* generated per call when omitted.
|
|
154
|
+
*/
|
|
155
|
+
idempotencyKey?: string;
|
|
109
156
|
}
|
|
110
157
|
export declare class EuRedact {
|
|
111
158
|
private engine;
|
package/dist/esm/sdk.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomIndex } from "./platform.js";
|
|
2
2
|
import { ResultCache } from "./cache.js";
|
|
3
3
|
import { normalize, mapOffsetToOriginal } from "./normalizer.js";
|
|
4
4
|
import { RuleEngine } from "./rules/engine.js";
|
|
@@ -60,7 +60,8 @@ export function applyReplacements(text, detections, labelFor) {
|
|
|
60
60
|
* do not list it". A token or a numbered label would be read as ordinary text,
|
|
61
61
|
* so the format on the wire is a model contract and not an output option.
|
|
62
62
|
*/
|
|
63
|
-
|
|
63
|
+
/** @internal Shared with cloud/batches.ts. */
|
|
64
|
+
export function maskForCloud(text, detections) {
|
|
64
65
|
const parts = [];
|
|
65
66
|
const labels = [];
|
|
66
67
|
let pos = 0;
|
|
@@ -110,7 +111,8 @@ function labelBefore(labels, offset, strict) {
|
|
|
110
111
|
* a span cannot be placed, and masking where it points would cover the wrong
|
|
111
112
|
* characters and leave the right ones in the clear.
|
|
112
113
|
*/
|
|
113
|
-
|
|
114
|
+
/** @internal Shared with cloud/batches.ts. */
|
|
115
|
+
export function ontoOriginal(spans, masked, text, labels, Unplaceable) {
|
|
114
116
|
const placed = [];
|
|
115
117
|
for (const span of spans) {
|
|
116
118
|
if (!(0 <= span.start && span.start <= span.end && span.end <= masked.length) ||
|
|
@@ -139,11 +141,12 @@ function ontoOriginal(spans, masked, text, labels, Unplaceable) {
|
|
|
139
141
|
return placed;
|
|
140
142
|
}
|
|
141
143
|
/**
|
|
142
|
-
* Characters a token suffix is drawn from. No vowels, so a suffix
|
|
143
|
-
* a word; no 0/1/I/O, so it survives being read back by a person;
|
|
144
|
-
* underscore, so the type prefix stays unambiguous.
|
|
144
|
+
* Characters a token suffix is drawn from. No vowels (and no Y), so a suffix
|
|
145
|
+
* never spells a word; no 0/1/I/O, so it survives being read back by a person;
|
|
146
|
+
* no underscore, so the type prefix stays unambiguous. A, E, U and Y were in it
|
|
147
|
+
* until rules-engine#55, against this comment.
|
|
145
148
|
*/
|
|
146
|
-
export const TOKEN_ALPHABET = "
|
|
149
|
+
export const TOKEN_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ23456789";
|
|
147
150
|
export const TOKEN_SUFFIX_LENGTH = 4;
|
|
148
151
|
const TOKEN_MAX_DRAWS = 100;
|
|
149
152
|
function escapeRegExp(s) {
|
|
@@ -191,7 +194,7 @@ export class TokenMapper {
|
|
|
191
194
|
}
|
|
192
195
|
let suffix = "";
|
|
193
196
|
for (let i = 0; i < TOKEN_SUFFIX_LENGTH; i++) {
|
|
194
|
-
suffix += TOKEN_ALPHABET[
|
|
197
|
+
suffix += TOKEN_ALPHABET[randomIndex(TOKEN_ALPHABET.length)];
|
|
195
198
|
}
|
|
196
199
|
token = prefix + suffix;
|
|
197
200
|
} while (this.taken.has(token));
|
|
@@ -527,7 +530,9 @@ export class EuRedact {
|
|
|
527
530
|
const [masked, labels] = maskForCloud(text, local.detections);
|
|
528
531
|
// The client converts the service's code-point offsets to UTF-16 units of
|
|
529
532
|
// the text it sent, so everything from here on is in one unit.
|
|
530
|
-
const remote = await client.redact(masked, {
|
|
533
|
+
const remote = await client.redact(masked, {
|
|
534
|
+
country: countries[0], idempotencyKey: options.idempotencyKey,
|
|
535
|
+
});
|
|
531
536
|
// A new array throughout: `local` may be the cached rules result.
|
|
532
537
|
const [detections, exempted] = applyAllowlist(text, [...local.detections, ...ontoOriginal(remote.detections, masked, text, labels, CloudError)], allowed, domains);
|
|
533
538
|
detections.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
@@ -539,6 +544,7 @@ export class EuRedact {
|
|
|
539
544
|
source: "cloud",
|
|
540
545
|
tokens: tokenMapper ? tokenMapper.tokens : {},
|
|
541
546
|
exempted,
|
|
547
|
+
...(remote.cloud ? { cloud: remote.cloud } : {}),
|
|
542
548
|
};
|
|
543
549
|
}
|
|
544
550
|
redact(text, options = {}) {
|
|
@@ -560,6 +566,9 @@ export class EuRedact {
|
|
|
560
566
|
if (requestedMode !== "rules") {
|
|
561
567
|
throw new Error(`unknown mode ${JSON.stringify(requestedMode)}: expected "rules" or "cloud"`);
|
|
562
568
|
}
|
|
569
|
+
if (options.idempotencyKey !== undefined) {
|
|
570
|
+
throw new Error('idempotencyKey applies to mode: "cloud" only: a rules-only redaction makes no request to deduplicate');
|
|
571
|
+
}
|
|
563
572
|
return this.redactRules(text, options, allowed, domains);
|
|
564
573
|
}
|
|
565
574
|
/** The local pipeline: normalise, detect, exempt, mask. */
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -69,7 +69,8 @@ export declare enum EntityType {
|
|
|
69
69
|
BIOMETRIC_REF = "BIOMETRIC_REF",
|
|
70
70
|
FINANCIAL_AMOUNT = "FINANCIAL_AMOUNT",
|
|
71
71
|
QUASI_IDENTIFIER = "QUASI_IDENTIFIER",
|
|
72
|
-
|
|
72
|
+
/** Legacy alias of SECRET: every credential, the model's included, is SECRET (rules-engine#111). */
|
|
73
|
+
CREDENTIAL = "SECRET",
|
|
73
74
|
URL = "URL",
|
|
74
75
|
OTHER = "OTHER"
|
|
75
76
|
}
|
|
@@ -116,7 +117,13 @@ export interface Detection {
|
|
|
116
117
|
text: string;
|
|
117
118
|
source: DetectionSource;
|
|
118
119
|
country: string | null;
|
|
119
|
-
|
|
120
|
+
/**
|
|
121
|
+
* How the type was arrived at: "high", "medium" or "low" for a rules
|
|
122
|
+
* detection. `null` for a span the cloud model found and reported no
|
|
123
|
+
* confidence for: the model emits none today, and "high" would claim the
|
|
124
|
+
* checksum-backed evidence a rules detection has (rules-engine#108).
|
|
125
|
+
*/
|
|
126
|
+
confidence: string | null;
|
|
120
127
|
/**
|
|
121
128
|
* How strongly the document supports {@link Detection.country}, in [0, 1].
|
|
122
129
|
*
|
|
@@ -151,6 +158,52 @@ export interface Exemption {
|
|
|
151
158
|
/** `"value"` for the literal allowlist, `"domain"` for allowlistDomains. */
|
|
152
159
|
ruleKind: "value" | "domain";
|
|
153
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* One reason a cloud request cost what it did. `code` is one of the service's
|
|
163
|
+
* factor codes (`rules_only`, `document_length`, `instructions`,
|
|
164
|
+
* `dense_document`, `special_category_check`, `long_document`, `batch_rate`),
|
|
165
|
+
* kept as a string so a code added later on the service still arrives.
|
|
166
|
+
*/
|
|
167
|
+
export interface UsageFactor {
|
|
168
|
+
code: string;
|
|
169
|
+
/** One sentence explaining the factor, written by the service. */
|
|
170
|
+
detail: string;
|
|
171
|
+
/** `special_category_check` only: the kinds of data that triggered it. */
|
|
172
|
+
types?: string[];
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* What a cloud request cost, and why (rules-engine#89). A total and its
|
|
176
|
+
* reasons, never a cost per step; `credits` is `round(tokens * billingRate)`,
|
|
177
|
+
* the formula the service debits by.
|
|
178
|
+
*/
|
|
179
|
+
export interface Usage {
|
|
180
|
+
tokens: number;
|
|
181
|
+
billingRate: number;
|
|
182
|
+
credits: number;
|
|
183
|
+
factors: UsageFactor[];
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Something the model found that could not be placed in the document: the
|
|
187
|
+
* service could not match it to a position in what it was sent, so nothing was
|
|
188
|
+
* masked for it. Reported so a caller can decide, rather than never being told.
|
|
189
|
+
*/
|
|
190
|
+
export interface Unlocated {
|
|
191
|
+
text: string;
|
|
192
|
+
entityType: EntityType | string;
|
|
193
|
+
}
|
|
194
|
+
/** What the cloud service said about a request, beside its spans (rules-engine#89). */
|
|
195
|
+
export interface CloudInfo {
|
|
196
|
+
/** The service's job id: for support, for `Jobs.retrieve`, and to recognise an
|
|
197
|
+
* idempotent replay. `null` for a batch document. */
|
|
198
|
+
jobId: string | null;
|
|
199
|
+
/** The public name of the model that answered, `null` when only rules ran. */
|
|
200
|
+
modelVersion: string | null;
|
|
201
|
+
/** What the request cost and why. Absent when the service does not report it
|
|
202
|
+
* (older versions, batch documents) or reported it malformed. */
|
|
203
|
+
usage?: Usage;
|
|
204
|
+
/** What the model found but could not place in the text it was sent. */
|
|
205
|
+
unlocated: Unlocated[];
|
|
206
|
+
}
|
|
154
207
|
export interface RedactResult {
|
|
155
208
|
redactedText: string;
|
|
156
209
|
detections: Detection[];
|
|
@@ -188,6 +241,9 @@ export interface RedactResult {
|
|
|
188
241
|
/** Detections the allowlist kept out of the output, with the rule that
|
|
189
242
|
* matched. Empty unless an allowlist was in force. */
|
|
190
243
|
exempted: Exemption[];
|
|
244
|
+
/** What the cloud service reported beside the spans: job id, model, cost and
|
|
245
|
+
* anything it could not place. Absent on a rules-only result. */
|
|
246
|
+
cloud?: CloudInfo;
|
|
191
247
|
}
|
|
192
248
|
export interface PatternDef {
|
|
193
249
|
entityType: EntityType | string;
|
package/dist/esm/types.js
CHANGED
|
@@ -75,7 +75,8 @@ export var EntityType;
|
|
|
75
75
|
EntityType["BIOMETRIC_REF"] = "BIOMETRIC_REF";
|
|
76
76
|
EntityType["FINANCIAL_AMOUNT"] = "FINANCIAL_AMOUNT";
|
|
77
77
|
EntityType["QUASI_IDENTIFIER"] = "QUASI_IDENTIFIER";
|
|
78
|
-
|
|
78
|
+
/** Legacy alias of SECRET: every credential, the model's included, is SECRET (rules-engine#111). */
|
|
79
|
+
EntityType["CREDENTIAL"] = "SECRET";
|
|
79
80
|
EntityType["URL"] = "URL";
|
|
80
81
|
EntityType["OTHER"] = "OTHER";
|
|
81
82
|
})(EntityType || (EntityType = {}));
|
|
@@ -89,6 +90,8 @@ export const LEGACY_TYPE_ALIASES = {
|
|
|
89
90
|
NAME: "PERSON_NAME",
|
|
90
91
|
STREET_ADDRESS: "ADDRESS",
|
|
91
92
|
NATIONALITY_ETHNICITY: "SENSITIVE_ATTRIBUTE",
|
|
93
|
+
// The model labels prose credentials CREDENTIAL; the SDK reports every credential as SECRET (rules-engine#111).
|
|
94
|
+
CREDENTIAL: "SECRET",
|
|
92
95
|
};
|
|
93
96
|
/**
|
|
94
97
|
* Resolve a possibly-legacy type name to its canonical form.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "euredact",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "European PII redaction SDK -- fast, zero-dependency, rule-based detection and redaction of personal data across 31 European countries",
|
|
5
5
|
"homepage": "https://euredact.dev",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -20,10 +20,15 @@
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
+
"browser": {
|
|
24
|
+
"./dist/esm/platform.js": "./dist/esm/platform.browser.js",
|
|
25
|
+
"./dist/cjs/platform.js": "./dist/cjs/platform.browser.js"
|
|
26
|
+
},
|
|
23
27
|
"files": [
|
|
24
28
|
"dist",
|
|
25
29
|
"README.md",
|
|
26
|
-
"LICENSE"
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"NOTICE"
|
|
27
32
|
],
|
|
28
33
|
"engines": {
|
|
29
34
|
"node": ">=16.0.0"
|
|
@@ -54,7 +59,7 @@
|
|
|
54
59
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
55
60
|
"postbuild:cjs": "echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
56
61
|
"build": "rm -rf dist && npm run build:esm && npm run build:cjs",
|
|
57
|
-
"test": "npm run test:spec && npm run test:inference && npm run test:cloud && npm run test:tokenize && npm run test:allowlist && npm run test:eval-scoring && npm run test:conformance",
|
|
62
|
+
"test": "npm run test:spec && npm run test:inference && npm run test:cloud && npm run test:cloud-api && npm run test:tokenize && npm run test:allowlist && npm run test:eval-scoring && npm run test:platform && npm run test:batches && npm run test:conformance",
|
|
58
63
|
"benchmark": "node --import tsx src/__tests__/benchmark.ts",
|
|
59
64
|
"prepublishOnly": "npm run build",
|
|
60
65
|
"test:spec": "node --import tsx src/__tests__/spec.ts",
|
|
@@ -64,9 +69,12 @@
|
|
|
64
69
|
"test:inference": "node --import tsx src/__tests__/inference.ts",
|
|
65
70
|
"dump": "node --import tsx src/__tests__/dump.ts",
|
|
66
71
|
"test:cloud": "node --import tsx src/__tests__/cloud.ts",
|
|
72
|
+
"test:cloud-api": "node --import tsx src/__tests__/cloudApi.ts",
|
|
67
73
|
"test:tokenize": "node --import tsx src/__tests__/tokenize.ts",
|
|
68
74
|
"test:allowlist": "node --import tsx src/__tests__/allowlist.ts",
|
|
69
|
-
"test:eval-scoring": "node --import tsx src/__tests__/evalScoring.ts"
|
|
75
|
+
"test:eval-scoring": "node --import tsx src/__tests__/evalScoring.ts",
|
|
76
|
+
"test:platform": "node --import tsx src/__tests__/platform.ts",
|
|
77
|
+
"test:batches": "node --import tsx src/__tests__/batches.ts"
|
|
70
78
|
},
|
|
71
79
|
"devDependencies": {
|
|
72
80
|
"@types/node": "22.10.2",
|