pii-vault 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/LICENSE-MIT +21 -0
- package/README.md +148 -0
- package/dist/analyzer.d.ts +13 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +47 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/anonymizer.d.ts +32 -0
- package/dist/anonymizer.d.ts.map +1 -0
- package/dist/anonymizer.js +68 -0
- package/dist/anonymizer.js.map +1 -0
- package/dist/entity.d.ts +15 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/entity.js +21 -0
- package/dist/entity.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/recognizer.d.ts +41 -0
- package/dist/recognizer.d.ts.map +1 -0
- package/dist/recognizer.js +113 -0
- package/dist/recognizer.js.map +1 -0
- package/dist/vault.d.ts +27 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +85 -0
- package/dist/vault.js.map +1 -0
- package/package.json +28 -0
package/LICENSE-MIT
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jiansen He
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# PII Vault
|
|
2
|
+
|
|
3
|
+
**Presidio-compatible PII detection, anonymization, and reversible tokenization.**
|
|
4
|
+
|
|
5
|
+
Multi-language implementations sharing a common specification. Detect 40+ PII entity types, anonymize with multiple strategies (replace, mask, hash, redact), and reversibly tokenize with a persistent vault.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **29 built-in recognizers** covering 15 countries (US, UK, CN, IN, AU, DE, IT, ES, KR, SG, FI, SE, PL, JP, FR, CA, BR)
|
|
10
|
+
- **Shared spec**: Recognizer patterns defined as JSON, consumed by all language implementations
|
|
11
|
+
- **Vault**: Deterministic, reversible tokenization with collision handling and context disambiguation
|
|
12
|
+
- **Multiple anonymization strategies**: Replace, Mask, Hash, Redact, Vault
|
|
13
|
+
- **Luhn validation** for credit cards, **checksum validation** for Chinese ID cards
|
|
14
|
+
- **Context-aware scoring**: Boost detection confidence when context words appear nearby
|
|
15
|
+
- **Zero runtime dependencies** beyond regex and JSON parsing
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Rust
|
|
20
|
+
|
|
21
|
+
```toml
|
|
22
|
+
[dependencies]
|
|
23
|
+
pii-vault = "0.1"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```rust
|
|
27
|
+
use pii_vault::{Analyzer, Anonymizer, Operator, Vault, load_recognizers_from_dir};
|
|
28
|
+
use std::collections::HashMap;
|
|
29
|
+
use std::path::Path;
|
|
30
|
+
|
|
31
|
+
// Load recognizers from spec/
|
|
32
|
+
let recognizers = load_recognizers_from_dir(Path::new("spec/recognizers"));
|
|
33
|
+
let analyzer = Analyzer::new(recognizers);
|
|
34
|
+
|
|
35
|
+
// Analyze text
|
|
36
|
+
let text = "Email alice@company.com, SSN 123-45-6789";
|
|
37
|
+
let result = analyzer.analyze(text, &[], 0.0);
|
|
38
|
+
|
|
39
|
+
// Anonymize with vault (reversible)
|
|
40
|
+
let mut vault = Vault::new();
|
|
41
|
+
let mut ops = HashMap::new();
|
|
42
|
+
ops.insert("EMAIL_ADDRESS".to_string(), Operator::Vault);
|
|
43
|
+
ops.insert("US_SSN".to_string(), Operator::Vault);
|
|
44
|
+
|
|
45
|
+
let anon = Anonymizer::anonymize(text, &result.entities, &ops, &Operator::default(), Some(&mut vault));
|
|
46
|
+
println!("{}", anon.text);
|
|
47
|
+
// "Email [EMAIL_ADDRESS:a1b2], SSN [US_SSN:c3d4]"
|
|
48
|
+
|
|
49
|
+
// Restore original
|
|
50
|
+
let restored = vault.detokenize(&anon.text);
|
|
51
|
+
assert_eq!(restored, text);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### TypeScript
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install pii-vault
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { Analyzer, Anonymizer, RegexRecognizer, Vault } from 'pii-vault';
|
|
62
|
+
import * as fs from 'fs';
|
|
63
|
+
|
|
64
|
+
// Load recognizers from spec/
|
|
65
|
+
const specDir = './spec/recognizers';
|
|
66
|
+
const recognizers = fs.readdirSync(specDir)
|
|
67
|
+
.filter(f => f.endsWith('.json'))
|
|
68
|
+
.map(f => new RegexRecognizer(JSON.parse(fs.readFileSync(`${specDir}/${f}`, 'utf-8'))));
|
|
69
|
+
|
|
70
|
+
const analyzer = new Analyzer(recognizers);
|
|
71
|
+
|
|
72
|
+
// Analyze
|
|
73
|
+
const text = 'Email alice@company.com, SSN 123-45-6789';
|
|
74
|
+
const result = analyzer.analyze(text);
|
|
75
|
+
|
|
76
|
+
// Anonymize with vault
|
|
77
|
+
const vault = new Vault();
|
|
78
|
+
const ops = { EMAIL_ADDRESS: { type: 'vault' }, US_SSN: { type: 'vault' } };
|
|
79
|
+
const anon = Anonymizer.anonymize(text, result.entities, ops, { type: 'replace' }, vault);
|
|
80
|
+
|
|
81
|
+
// Restore
|
|
82
|
+
const restored = vault.detokenize(anon.text);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Architecture
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
pii-vault/
|
|
89
|
+
├── spec/ # Shared specification (language-agnostic)
|
|
90
|
+
│ ├── entities.json # 45 entity type definitions
|
|
91
|
+
│ ├── recognizers/ # 29 regex recognizer definitions (JSON)
|
|
92
|
+
│ └── test-cases/ # Cross-language test cases
|
|
93
|
+
├── rust/ # Rust implementation → crates.io: pii-vault
|
|
94
|
+
├── typescript/ # TypeScript implementation → npm: pii-vault
|
|
95
|
+
├── go/ # Go implementation (planned)
|
|
96
|
+
├── java/ # Java implementation (planned)
|
|
97
|
+
├── haskell/ # Haskell implementation (planned)
|
|
98
|
+
└── wasm/ # WASM from Rust (planned)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The `spec/recognizers/*.json` files are the **single source of truth**. All language implementations load these patterns at runtime or compile time.
|
|
102
|
+
|
|
103
|
+
## Supported Entity Types
|
|
104
|
+
|
|
105
|
+
### Generic (all languages)
|
|
106
|
+
EMAIL_ADDRESS, PHONE_NUMBER, CREDIT_CARD, CRYPTO, IP_ADDRESS, MAC_ADDRESS, IBAN_CODE, URL, UUID
|
|
107
|
+
|
|
108
|
+
### Country-Specific
|
|
109
|
+
| Country | Entities |
|
|
110
|
+
|---------|----------|
|
|
111
|
+
| US | SSN, ITIN, Passport, Driver License, Bank Routing |
|
|
112
|
+
| UK | NHS, NINO |
|
|
113
|
+
| China | ID Card (18-digit), Phone, Passport, Bank Card |
|
|
114
|
+
| India | Aadhaar, PAN, Passport |
|
|
115
|
+
| Australia | TFN, Medicare, ABN |
|
|
116
|
+
| Germany | Steuer-ID |
|
|
117
|
+
| Italy | Fiscal Code |
|
|
118
|
+
| Spain | NIE, NIF |
|
|
119
|
+
| Korea | RRN |
|
|
120
|
+
| Singapore | NRIC |
|
|
121
|
+
| Finland | Personal ID |
|
|
122
|
+
| Sweden | Personal Number |
|
|
123
|
+
| Poland | PESEL |
|
|
124
|
+
| Japan | My Number, Passport |
|
|
125
|
+
| France | NIR |
|
|
126
|
+
| Canada | SIN |
|
|
127
|
+
| Brazil | CPF |
|
|
128
|
+
|
|
129
|
+
## Anonymization Strategies
|
|
130
|
+
|
|
131
|
+
| Strategy | Description | Reversible |
|
|
132
|
+
|----------|-------------|------------|
|
|
133
|
+
| Replace | Replace with `<ENTITY_TYPE>` or custom string | No |
|
|
134
|
+
| Mask | Partially mask characters (e.g., `****1111`) | No |
|
|
135
|
+
| Hash | FNV hash of original value | No |
|
|
136
|
+
| Redact | Remove entirely | No |
|
|
137
|
+
| **Vault** | Deterministic token `[ENTITY:xxxx]` with persistent mapping | **Yes** |
|
|
138
|
+
|
|
139
|
+
## Contributing
|
|
140
|
+
|
|
141
|
+
Add a new recognizer:
|
|
142
|
+
1. Create `spec/recognizers/your_entity.json` following the existing format
|
|
143
|
+
2. Add test cases to `spec/test-cases/`
|
|
144
|
+
3. Run tests in both Rust and TypeScript to verify
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EntityType, RecognizerResult } from './entity';
|
|
2
|
+
import { Recognizer } from './recognizer';
|
|
3
|
+
export interface AnalyzerResult {
|
|
4
|
+
entities: RecognizerResult[];
|
|
5
|
+
}
|
|
6
|
+
export declare class Analyzer {
|
|
7
|
+
private readonly recognizers;
|
|
8
|
+
constructor(recognizers: Recognizer[]);
|
|
9
|
+
analyze(text: string, entities?: EntityType[], scoreThreshold?: number): AnalyzerResult;
|
|
10
|
+
get recognizerCount(): number;
|
|
11
|
+
private resolveOverlaps;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,UAAU,EAAE;IAEtD,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,UAAU,EAAO,EAAE,cAAc,SAAM,GAAG,cAAc;IAexF,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED,OAAO,CAAC,eAAe;CA6BxB"}
|
package/dist/analyzer.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Analyzer = void 0;
|
|
4
|
+
class Analyzer {
|
|
5
|
+
constructor(recognizers) {
|
|
6
|
+
this.recognizers = recognizers;
|
|
7
|
+
}
|
|
8
|
+
analyze(text, entities = [], scoreThreshold = 0.0) {
|
|
9
|
+
let allResults = [];
|
|
10
|
+
for (const recognizer of this.recognizers) {
|
|
11
|
+
const results = recognizer.analyze(text, entities);
|
|
12
|
+
allResults.push(...results);
|
|
13
|
+
}
|
|
14
|
+
allResults = allResults.filter(r => r.score >= scoreThreshold);
|
|
15
|
+
allResults.sort((a, b) => a.start - b.start || b.score - a.score);
|
|
16
|
+
const deduped = this.resolveOverlaps(allResults);
|
|
17
|
+
return { entities: deduped };
|
|
18
|
+
}
|
|
19
|
+
get recognizerCount() {
|
|
20
|
+
return this.recognizers.length;
|
|
21
|
+
}
|
|
22
|
+
resolveOverlaps(results) {
|
|
23
|
+
const output = [];
|
|
24
|
+
for (const result of results) {
|
|
25
|
+
const dominated = output.some(existing => existing.start <= result.start &&
|
|
26
|
+
existing.end >= result.end &&
|
|
27
|
+
existing.score >= result.score);
|
|
28
|
+
if (dominated)
|
|
29
|
+
continue;
|
|
30
|
+
const toRemove = new Set();
|
|
31
|
+
output.forEach((existing, i) => {
|
|
32
|
+
if (result.start <= existing.start &&
|
|
33
|
+
result.end >= existing.end &&
|
|
34
|
+
result.score >= existing.score) {
|
|
35
|
+
toRemove.add(i);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const filtered = output.filter((_, i) => !toRemove.has(i));
|
|
39
|
+
output.length = 0;
|
|
40
|
+
output.push(...filtered, result);
|
|
41
|
+
}
|
|
42
|
+
output.sort((a, b) => a.start - b.start);
|
|
43
|
+
return output;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.Analyzer = Analyzer;
|
|
47
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":";;;AAOA,MAAa,QAAQ;IACnB,YAA6B,WAAyB;QAAzB,gBAAW,GAAX,WAAW,CAAc;IAAG,CAAC;IAE1D,OAAO,CAAC,IAAY,EAAE,WAAyB,EAAE,EAAE,cAAc,GAAG,GAAG;QACrE,IAAI,UAAU,GAAuB,EAAE,CAAC;QAExC,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACnD,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAC9B,CAAC;QAED,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,cAAc,CAAC,CAAC;QAC/D,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;IACjC,CAAC;IAEO,eAAe,CAAC,OAA2B;QACjD,MAAM,MAAM,GAAuB,EAAE,CAAC;QACtC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAC3B,QAAQ,CAAC,EAAE,CACT,QAAQ,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK;gBAC9B,QAAQ,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG;gBAC1B,QAAQ,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CACjC,CAAC;YACF,IAAI,SAAS;gBAAE,SAAS;YAExB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;YACnC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE;gBAC7B,IACE,MAAM,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;oBAC9B,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG;oBAC1B,MAAM,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,EAC9B,CAAC;oBACD,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAnDD,4BAmDC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { RecognizerResult } from './entity';
|
|
2
|
+
import { Vault } from './vault';
|
|
3
|
+
export type Operator = {
|
|
4
|
+
type: 'replace';
|
|
5
|
+
newValue?: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'mask';
|
|
8
|
+
maskingChar: string;
|
|
9
|
+
charsToMask: number;
|
|
10
|
+
fromEnd: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'hash';
|
|
13
|
+
} | {
|
|
14
|
+
type: 'redact';
|
|
15
|
+
} | {
|
|
16
|
+
type: 'vault';
|
|
17
|
+
};
|
|
18
|
+
export interface AnonymizedItem {
|
|
19
|
+
entityType: string;
|
|
20
|
+
start: number;
|
|
21
|
+
end: number;
|
|
22
|
+
original: string;
|
|
23
|
+
replacement: string;
|
|
24
|
+
}
|
|
25
|
+
export interface AnonymizedResult {
|
|
26
|
+
text: string;
|
|
27
|
+
items: AnonymizedItem[];
|
|
28
|
+
}
|
|
29
|
+
export declare class Anonymizer {
|
|
30
|
+
static anonymize(text: string, entities: RecognizerResult[], operators?: Record<string, Operator>, defaultOperator?: Operator, vault?: Vault): AnonymizedResult;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=anonymizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymizer.d.ts","sourceRoot":"","sources":["../src/anonymizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC5E;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,qBAAa,UAAU;IACrB,MAAM,CAAC,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,gBAAgB,EAAE,EAC5B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAM,EACxC,eAAe,GAAE,QAA8B,EAC/C,KAAK,CAAC,EAAE,KAAK,GACZ,gBAAgB;CA4CpB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Anonymizer = void 0;
|
|
4
|
+
class Anonymizer {
|
|
5
|
+
static anonymize(text, entities, operators = {}, defaultOperator = { type: 'replace' }, vault) {
|
|
6
|
+
const sorted = [...entities].sort((a, b) => b.start - a.start);
|
|
7
|
+
let result = text;
|
|
8
|
+
const items = [];
|
|
9
|
+
for (const entity of sorted) {
|
|
10
|
+
const original = text.slice(entity.start, entity.end);
|
|
11
|
+
const op = operators[entity.entityType.name] || defaultOperator;
|
|
12
|
+
let replacement;
|
|
13
|
+
switch (op.type) {
|
|
14
|
+
case 'replace':
|
|
15
|
+
replacement = op.newValue || `<${entity.entityType.name}>`;
|
|
16
|
+
break;
|
|
17
|
+
case 'mask':
|
|
18
|
+
replacement = maskText(original, op.maskingChar, op.charsToMask, op.fromEnd);
|
|
19
|
+
break;
|
|
20
|
+
case 'hash':
|
|
21
|
+
replacement = hashText(original);
|
|
22
|
+
break;
|
|
23
|
+
case 'redact':
|
|
24
|
+
replacement = '';
|
|
25
|
+
break;
|
|
26
|
+
case 'vault':
|
|
27
|
+
replacement = vault
|
|
28
|
+
? vault.tokenize(entity.entityType.name.toLowerCase(), original)
|
|
29
|
+
: `<${entity.entityType.name}>`;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
items.push({
|
|
33
|
+
entityType: entity.entityType.name,
|
|
34
|
+
start: entity.start,
|
|
35
|
+
end: entity.end,
|
|
36
|
+
original,
|
|
37
|
+
replacement,
|
|
38
|
+
});
|
|
39
|
+
result = result.slice(0, entity.start) + replacement + result.slice(entity.end);
|
|
40
|
+
}
|
|
41
|
+
items.reverse();
|
|
42
|
+
return { text: result, items };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.Anonymizer = Anonymizer;
|
|
46
|
+
function maskText(text, maskChar, charsToMask, fromEnd) {
|
|
47
|
+
const chars = [...text];
|
|
48
|
+
const toMask = Math.min(charsToMask, chars.length);
|
|
49
|
+
if (fromEnd) {
|
|
50
|
+
for (let i = chars.length - 1; i >= chars.length - toMask; i--) {
|
|
51
|
+
chars[i] = maskChar;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
for (let i = 0; i < toMask; i++) {
|
|
56
|
+
chars[i] = maskChar;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return chars.join('');
|
|
60
|
+
}
|
|
61
|
+
function hashText(text) {
|
|
62
|
+
let hash = 2166136261;
|
|
63
|
+
for (let i = 0; i < text.length; i++) {
|
|
64
|
+
hash = Math.imul(hash ^ text.charCodeAt(i), 16777619) >>> 0;
|
|
65
|
+
}
|
|
66
|
+
return hash.toString(16).padStart(8, '0');
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=anonymizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymizer.js","sourceRoot":"","sources":["../src/anonymizer.ts"],"names":[],"mappings":"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"}
|
package/dist/entity.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class EntityType {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
constructor(name: string);
|
|
4
|
+
toString(): string;
|
|
5
|
+
equals(other: EntityType): boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface RecognizerResult {
|
|
8
|
+
entityType: EntityType;
|
|
9
|
+
start: number;
|
|
10
|
+
end: number;
|
|
11
|
+
score: number;
|
|
12
|
+
recognizerName?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function resultText(result: RecognizerResult, input: string): string;
|
|
15
|
+
//# sourceMappingURL=entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU;aACO,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;IAIxC,QAAQ,IAAI,MAAM;IAIlB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;CAGnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1E"}
|
package/dist/entity.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EntityType = void 0;
|
|
4
|
+
exports.resultText = resultText;
|
|
5
|
+
class EntityType {
|
|
6
|
+
constructor(name) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.name = name.toUpperCase();
|
|
9
|
+
}
|
|
10
|
+
toString() {
|
|
11
|
+
return this.name;
|
|
12
|
+
}
|
|
13
|
+
equals(other) {
|
|
14
|
+
return this.name === other.name;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.EntityType = EntityType;
|
|
18
|
+
function resultText(result, input) {
|
|
19
|
+
return input.slice(result.start, result.end);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":";;;AAsBA,gCAEC;AAxBD,MAAa,UAAU;IACrB,YAA4B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QACtC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,KAAiB;QACtB,OAAO,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC;IAClC,CAAC;CACF;AAZD,gCAYC;AAUD,SAAgB,UAAU,CAAC,MAAwB,EAAE,KAAa;IAChE,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { EntityType, RecognizerResult, resultText } from './entity';
|
|
2
|
+
export { Recognizer, RegexRecognizer, RecognizerDef, luhnCheck, cnIdCheck } from './recognizer';
|
|
3
|
+
export { Analyzer, AnalyzerResult } from './analyzer';
|
|
4
|
+
export { Vault, VaultEntry } from './vault';
|
|
5
|
+
export { Anonymizer, Operator, AnonymizedResult, AnonymizedItem } from './anonymizer';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Anonymizer = exports.Vault = exports.Analyzer = exports.cnIdCheck = exports.luhnCheck = exports.RegexRecognizer = exports.resultText = exports.EntityType = void 0;
|
|
4
|
+
var entity_1 = require("./entity");
|
|
5
|
+
Object.defineProperty(exports, "EntityType", { enumerable: true, get: function () { return entity_1.EntityType; } });
|
|
6
|
+
Object.defineProperty(exports, "resultText", { enumerable: true, get: function () { return entity_1.resultText; } });
|
|
7
|
+
var recognizer_1 = require("./recognizer");
|
|
8
|
+
Object.defineProperty(exports, "RegexRecognizer", { enumerable: true, get: function () { return recognizer_1.RegexRecognizer; } });
|
|
9
|
+
Object.defineProperty(exports, "luhnCheck", { enumerable: true, get: function () { return recognizer_1.luhnCheck; } });
|
|
10
|
+
Object.defineProperty(exports, "cnIdCheck", { enumerable: true, get: function () { return recognizer_1.cnIdCheck; } });
|
|
11
|
+
var analyzer_1 = require("./analyzer");
|
|
12
|
+
Object.defineProperty(exports, "Analyzer", { enumerable: true, get: function () { return analyzer_1.Analyzer; } });
|
|
13
|
+
var vault_1 = require("./vault");
|
|
14
|
+
Object.defineProperty(exports, "Vault", { enumerable: true, get: function () { return vault_1.Vault; } });
|
|
15
|
+
var anonymizer_1 = require("./anonymizer");
|
|
16
|
+
Object.defineProperty(exports, "Anonymizer", { enumerable: true, get: function () { return anonymizer_1.Anonymizer; } });
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAoE;AAA3D,oGAAA,UAAU,OAAA;AAAoB,oGAAA,UAAU,OAAA;AACjD,2CAAgG;AAA3E,6GAAA,eAAe,OAAA;AAAiB,uGAAA,SAAS,OAAA;AAAE,uGAAA,SAAS,OAAA;AACzE,uCAAsD;AAA7C,oGAAA,QAAQ,OAAA;AACjB,iCAA4C;AAAnC,8FAAA,KAAK,OAAA;AACd,2CAAsF;AAA7E,wGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EntityType, RecognizerResult } from './entity';
|
|
2
|
+
export interface Recognizer {
|
|
3
|
+
name: string;
|
|
4
|
+
supportedEntities: EntityType[];
|
|
5
|
+
analyze(text: string, entities: EntityType[]): RecognizerResult[];
|
|
6
|
+
}
|
|
7
|
+
export interface PatternDef {
|
|
8
|
+
name: string;
|
|
9
|
+
regex: string;
|
|
10
|
+
score: number;
|
|
11
|
+
}
|
|
12
|
+
export interface RecognizerDef {
|
|
13
|
+
name: string;
|
|
14
|
+
entity_type: string;
|
|
15
|
+
version: string;
|
|
16
|
+
patterns: PatternDef[];
|
|
17
|
+
context_words?: string[];
|
|
18
|
+
context_score_boost?: number;
|
|
19
|
+
deny_list?: string[];
|
|
20
|
+
validators?: string[];
|
|
21
|
+
supported_languages?: string[] | null;
|
|
22
|
+
}
|
|
23
|
+
export declare class RegexRecognizer implements Recognizer {
|
|
24
|
+
private readonly def;
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly supportedEntities: EntityType[];
|
|
27
|
+
private readonly entity;
|
|
28
|
+
private readonly compiled;
|
|
29
|
+
private readonly contextWords;
|
|
30
|
+
private readonly contextBoost;
|
|
31
|
+
private readonly denyList;
|
|
32
|
+
private readonly validators;
|
|
33
|
+
constructor(def: RecognizerDef);
|
|
34
|
+
static fromJson(json: string): RegexRecognizer;
|
|
35
|
+
analyze(text: string, entities: EntityType[]): RecognizerResult[];
|
|
36
|
+
private hasContext;
|
|
37
|
+
private validate;
|
|
38
|
+
}
|
|
39
|
+
export declare function luhnCheck(number: string): boolean;
|
|
40
|
+
export declare function cnIdCheck(id: string): boolean;
|
|
41
|
+
//# sourceMappingURL=recognizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recognizer.d.ts","sourceRoot":"","sources":["../src/recognizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,UAAU,EAAE,CAAC;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,gBAAgB,EAAE,CAAC;CACnE;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CACvC;AAED,qBAAa,eAAgB,YAAW,UAAU;IAUpC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAThC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,iBAAiB,EAAE,UAAU,EAAE,CAAC;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwD;IACjF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAW;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAW;gBAET,GAAG,EAAE,aAAa;IAe/C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAK9C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,gBAAgB,EAAE;IAgCjE,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,QAAQ;CAajB;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAejD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAW7C"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RegexRecognizer = void 0;
|
|
4
|
+
exports.luhnCheck = luhnCheck;
|
|
5
|
+
exports.cnIdCheck = cnIdCheck;
|
|
6
|
+
const entity_1 = require("./entity");
|
|
7
|
+
class RegexRecognizer {
|
|
8
|
+
constructor(def) {
|
|
9
|
+
this.def = def;
|
|
10
|
+
this.name = def.name;
|
|
11
|
+
this.entity = new entity_1.EntityType(def.entity_type);
|
|
12
|
+
this.supportedEntities = [this.entity];
|
|
13
|
+
this.contextWords = (def.context_words || []).map(w => w.toLowerCase());
|
|
14
|
+
this.contextBoost = def.context_score_boost || 0;
|
|
15
|
+
this.denyList = new Set(def.deny_list || []);
|
|
16
|
+
this.validators = def.validators || [];
|
|
17
|
+
this.compiled = def.patterns.map(p => ({
|
|
18
|
+
name: p.name,
|
|
19
|
+
regex: new RegExp(p.regex, 'g'),
|
|
20
|
+
score: p.score,
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
static fromJson(json) {
|
|
24
|
+
const def = JSON.parse(json);
|
|
25
|
+
return new RegexRecognizer(def);
|
|
26
|
+
}
|
|
27
|
+
analyze(text, entities) {
|
|
28
|
+
if (entities.length > 0 && !entities.some(e => e.equals(this.entity))) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
const results = [];
|
|
32
|
+
for (const { name, regex, score } of this.compiled) {
|
|
33
|
+
regex.lastIndex = 0;
|
|
34
|
+
let match;
|
|
35
|
+
while ((match = regex.exec(text)) !== null) {
|
|
36
|
+
const matched = match[0];
|
|
37
|
+
if (this.denyList.has(matched))
|
|
38
|
+
continue;
|
|
39
|
+
if (!this.validate(matched))
|
|
40
|
+
continue;
|
|
41
|
+
let finalScore = score;
|
|
42
|
+
if (this.hasContext(text, match.index, match.index + matched.length)) {
|
|
43
|
+
finalScore = Math.min(finalScore + this.contextBoost, 1.0);
|
|
44
|
+
}
|
|
45
|
+
results.push({
|
|
46
|
+
entityType: this.entity,
|
|
47
|
+
start: match.index,
|
|
48
|
+
end: match.index + matched.length,
|
|
49
|
+
score: finalScore,
|
|
50
|
+
recognizerName: name,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return results;
|
|
55
|
+
}
|
|
56
|
+
hasContext(text, start, end) {
|
|
57
|
+
if (this.contextWords.length === 0)
|
|
58
|
+
return false;
|
|
59
|
+
const windowStart = Math.max(0, start - 100);
|
|
60
|
+
const windowEnd = Math.min(text.length, end + 100);
|
|
61
|
+
const window = text.slice(windowStart, windowEnd).toLowerCase();
|
|
62
|
+
return this.contextWords.some(w => window.includes(w));
|
|
63
|
+
}
|
|
64
|
+
validate(matched) {
|
|
65
|
+
for (const v of this.validators) {
|
|
66
|
+
switch (v) {
|
|
67
|
+
case 'luhn':
|
|
68
|
+
if (!luhnCheck(matched))
|
|
69
|
+
return false;
|
|
70
|
+
break;
|
|
71
|
+
case 'cn_id_checksum':
|
|
72
|
+
if (!cnIdCheck(matched))
|
|
73
|
+
return false;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.RegexRecognizer = RegexRecognizer;
|
|
81
|
+
function luhnCheck(number) {
|
|
82
|
+
const digits = number.replace(/\D/g, '');
|
|
83
|
+
if (digits.length < 2)
|
|
84
|
+
return false;
|
|
85
|
+
let sum = 0;
|
|
86
|
+
let double = false;
|
|
87
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
88
|
+
let val = parseInt(digits[i], 10);
|
|
89
|
+
if (double) {
|
|
90
|
+
val *= 2;
|
|
91
|
+
if (val > 9)
|
|
92
|
+
val -= 9;
|
|
93
|
+
}
|
|
94
|
+
sum += val;
|
|
95
|
+
double = !double;
|
|
96
|
+
}
|
|
97
|
+
return sum % 10 === 0;
|
|
98
|
+
}
|
|
99
|
+
function cnIdCheck(id) {
|
|
100
|
+
if (id.length !== 18)
|
|
101
|
+
return false;
|
|
102
|
+
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
|
103
|
+
const checkChars = '10X98765432';
|
|
104
|
+
let sum = 0;
|
|
105
|
+
for (let i = 0; i < 17; i++) {
|
|
106
|
+
const d = parseInt(id[i], 10);
|
|
107
|
+
if (isNaN(d))
|
|
108
|
+
return false;
|
|
109
|
+
sum += d * weights[i];
|
|
110
|
+
}
|
|
111
|
+
return id[17].toUpperCase() === checkChars[sum % 11];
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=recognizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recognizer.js","sourceRoot":"","sources":["../src/recognizer.ts"],"names":[],"mappings":"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"}
|
package/dist/vault.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface VaultEntry {
|
|
2
|
+
token: string;
|
|
3
|
+
original: string;
|
|
4
|
+
category: string;
|
|
5
|
+
context: string;
|
|
6
|
+
createdAt: string;
|
|
7
|
+
lastUsed: string;
|
|
8
|
+
useCount: number;
|
|
9
|
+
}
|
|
10
|
+
export interface VaultData {
|
|
11
|
+
version: number;
|
|
12
|
+
entries: VaultEntry[];
|
|
13
|
+
}
|
|
14
|
+
export declare class Vault {
|
|
15
|
+
private entries;
|
|
16
|
+
private index;
|
|
17
|
+
static fromJson(json: string): Vault;
|
|
18
|
+
toJson(): string;
|
|
19
|
+
tokenize(category: string, original: string): string;
|
|
20
|
+
tokenizeCtx(category: string, original: string, context: string): string;
|
|
21
|
+
detokenize(text: string): string;
|
|
22
|
+
lookupToken(token: string): VaultEntry | undefined;
|
|
23
|
+
get entryCount(): number;
|
|
24
|
+
private rebuildIndex;
|
|
25
|
+
private static stableToken;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=vault.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,qBAAa,KAAK;IAChB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,KAAK,CAA6B;IAE1C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAQpC,MAAM,IAAI,MAAM;IAKhB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAIpD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAqCxE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAShC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIlD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,MAAM,CAAC,WAAW;CAQ3B"}
|
package/dist/vault.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Vault = void 0;
|
|
4
|
+
class Vault {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.entries = [];
|
|
7
|
+
this.index = new Map();
|
|
8
|
+
}
|
|
9
|
+
static fromJson(json) {
|
|
10
|
+
const data = JSON.parse(json);
|
|
11
|
+
const vault = new Vault();
|
|
12
|
+
vault.entries = data.entries;
|
|
13
|
+
vault.rebuildIndex();
|
|
14
|
+
return vault;
|
|
15
|
+
}
|
|
16
|
+
toJson() {
|
|
17
|
+
const data = { version: 1, entries: this.entries };
|
|
18
|
+
return JSON.stringify(data, null, 2);
|
|
19
|
+
}
|
|
20
|
+
tokenize(category, original) {
|
|
21
|
+
return this.tokenizeCtx(category, original, '');
|
|
22
|
+
}
|
|
23
|
+
tokenizeCtx(category, original, context) {
|
|
24
|
+
const key = `${category}:${original}:${context}`;
|
|
25
|
+
const now = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
26
|
+
const existingIdx = this.index.get(key);
|
|
27
|
+
if (existingIdx !== undefined) {
|
|
28
|
+
const entry = this.entries[existingIdx];
|
|
29
|
+
entry.lastUsed = now;
|
|
30
|
+
entry.useCount += 1;
|
|
31
|
+
return entry.token;
|
|
32
|
+
}
|
|
33
|
+
const hashInput = context ? `${category}:${original}:${context}` : `${category}:${original}`;
|
|
34
|
+
let token = Vault.stableToken(category, hashInput);
|
|
35
|
+
let attempt = 0;
|
|
36
|
+
while (this.entries.some(e => e.token === token && (e.original !== original || e.context !== context))) {
|
|
37
|
+
attempt++;
|
|
38
|
+
token = Vault.stableToken(category, `${category}:${original}:${context}:${attempt}`);
|
|
39
|
+
}
|
|
40
|
+
const entry = {
|
|
41
|
+
token,
|
|
42
|
+
original,
|
|
43
|
+
category,
|
|
44
|
+
context,
|
|
45
|
+
createdAt: now,
|
|
46
|
+
lastUsed: now,
|
|
47
|
+
useCount: 1,
|
|
48
|
+
};
|
|
49
|
+
const idx = this.entries.length;
|
|
50
|
+
this.entries.push(entry);
|
|
51
|
+
this.index.set(key, idx);
|
|
52
|
+
return token;
|
|
53
|
+
}
|
|
54
|
+
detokenize(text) {
|
|
55
|
+
let result = text;
|
|
56
|
+
const sorted = [...this.entries].sort((a, b) => b.token.length - a.token.length);
|
|
57
|
+
for (const entry of sorted) {
|
|
58
|
+
result = result.split(entry.token).join(entry.original);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
lookupToken(token) {
|
|
63
|
+
return this.entries.find(e => e.token === token);
|
|
64
|
+
}
|
|
65
|
+
get entryCount() {
|
|
66
|
+
return this.entries.length;
|
|
67
|
+
}
|
|
68
|
+
rebuildIndex() {
|
|
69
|
+
this.index.clear();
|
|
70
|
+
for (let i = 0; i < this.entries.length; i++) {
|
|
71
|
+
const e = this.entries[i];
|
|
72
|
+
this.index.set(`${e.category}:${e.original}:${e.context}`, i);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
static stableToken(category, input) {
|
|
76
|
+
let hash = 0;
|
|
77
|
+
for (let i = 0; i < input.length; i++) {
|
|
78
|
+
hash = (Math.imul(hash, 31) + input.charCodeAt(i)) >>> 0;
|
|
79
|
+
}
|
|
80
|
+
const short = (hash & 0xffff).toString(16).padStart(4, '0');
|
|
81
|
+
return `[${category.toUpperCase()}:${short}]`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.Vault = Vault;
|
|
85
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pii-vault",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Presidio-compatible PII detection, anonymization, and reversible tokenization",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": ["dist", "README.md", "LICENSE-MIT"],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"prepublishOnly": "npm run build",
|
|
11
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
12
|
+
"lint": "tsc --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["pii", "privacy", "anonymization", "redaction", "presidio", "gdpr"],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/Jiansen/pii-vault.git",
|
|
19
|
+
"directory": "typescript"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/Jiansen/pii-vault",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/jest": "^29",
|
|
24
|
+
"jest": "^29",
|
|
25
|
+
"ts-jest": "^29",
|
|
26
|
+
"typescript": "^5"
|
|
27
|
+
}
|
|
28
|
+
}
|