@privacyscrubber/sdk 2.4.6 → 2.4.7
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/browser.js +32 -7
- package/cli.js +1 -1
- package/examples/python-bridge/fastapi_example.py +1 -1
- package/examples/python-bridge/privacyscrubber/__init__.py +1 -1
- package/examples/python-bridge/privacyscrubber/bridge_daemon.cjs +1 -1
- package/examples/python-bridge/privacyscrubber/cli.py +1 -1
- package/examples/python-bridge/pyproject.toml +1 -1
- package/examples/python-bridge/setup.py +1 -1
- package/fastmcp.cjs +56 -0
- package/fastmcp.d.ts +5 -0
- package/index.cjs +34 -8
- package/index.d.ts +9 -0
- package/index.js +34 -8
- package/package.json +1 -1
- package/ps-license-manager.js +1 -1
- package/ps-pii-engine.cjs +1 -1
- package/sarif.cjs +2 -2
- package/scrubber-core.cjs +1 -1
package/browser.js
CHANGED
|
@@ -70,7 +70,10 @@ export class PrivacyScrubberLicenseError extends Error {
|
|
|
70
70
|
this.currentLength = currentLength;
|
|
71
71
|
this.limit = limit;
|
|
72
72
|
this.profile = profile;
|
|
73
|
-
|
|
73
|
+
const safeProf = encodeURIComponent(String(profile || 'General'));
|
|
74
|
+
this.upgradeUrl = `https://privacyscrubber.com/pricing?tier=sdk&profile=${safeProf}&utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell`;
|
|
75
|
+
this.trialUrl = `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${safeProf}&utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell`;
|
|
76
|
+
this.trialCommand = 'npx @privacyscrubber/sdk trial';
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -170,11 +173,27 @@ export function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
170
173
|
trademark: 'ZTDS™ Reg. #182655957 (ILPO Cl 9 & 42)'
|
|
171
174
|
};
|
|
172
175
|
|
|
176
|
+
const agenticProtocol = {
|
|
177
|
+
protocolsSupported: ['MCP-1.0 (stdio/SSE)', 'A2A-1.0 (Agent2Agent)', 'ZTDS-RFC-v1.0'],
|
|
178
|
+
agentCardUrl: 'https://privacyscrubber.com/.well-known/agent-card.json',
|
|
179
|
+
ztdsStandardCardUrl: 'https://ztds.ai/.well-known/agent-card.json',
|
|
180
|
+
regulatorySafeHarbor: [
|
|
181
|
+
'GDPR-Art-4(5)-Pseudonymization',
|
|
182
|
+
'GDPR-Art-25-Privacy-by-Design',
|
|
183
|
+
'GDPR-Art-32-TOMs',
|
|
184
|
+
'EU-AI-Act-Art-50',
|
|
185
|
+
'EU-AI-Act-Art-17-EN-18286-QMS',
|
|
186
|
+
'CNIL-ICO-Agentic-Memory-Compartmentalization',
|
|
187
|
+
'IL-PPL-Amendment-13-Sec-17'
|
|
188
|
+
],
|
|
189
|
+
zeroCleartextEgress: true
|
|
190
|
+
};
|
|
191
|
+
|
|
173
192
|
const statutoryCitations = [
|
|
174
193
|
{
|
|
175
|
-
statute: 'EU AI Act (Art. 50)',
|
|
176
|
-
scope: 'AI Transparency &
|
|
177
|
-
rule: 'Sanitization runs locally by design; reduces the content sent to external AI models. Informational mapping, not a compliance determination.'
|
|
194
|
+
statute: 'EU AI Act (Art. 50 & Art. 17 / EN 18286:2026 QMS)',
|
|
195
|
+
scope: 'AI Transparency, Data Minimization & Harmonized QMS Governance',
|
|
196
|
+
rule: 'Sanitization runs locally by design; reduces the content sent to external AI models and supports Article 17 Quality Management System (EN 18286:2026) data governance controls. Informational mapping, not a compliance determination.'
|
|
178
197
|
},
|
|
179
198
|
{
|
|
180
199
|
statute: 'GDPR (Art. 4, 25, 28, 32)',
|
|
@@ -206,6 +225,7 @@ export function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
206
225
|
frameworksList: Array.from(frameworksSet),
|
|
207
226
|
statutoryCitations,
|
|
208
227
|
ipHoldings,
|
|
228
|
+
agenticProtocol,
|
|
209
229
|
multimodalEgress: '0.00 Bytes (Solid Blackout & Burn-in Verified)'
|
|
210
230
|
};
|
|
211
231
|
}
|
|
@@ -296,7 +316,8 @@ export function sanitize(text, options = {}) {
|
|
|
296
316
|
|
|
297
317
|
if (!isPro && text.length > limit) {
|
|
298
318
|
if (shouldThrow) {
|
|
299
|
-
const
|
|
319
|
+
const safeProf = encodeURIComponent(String(profile || 'General'));
|
|
320
|
+
const errorMsg = `[PrivacyScrubber] Free Tier character limit exceeded (${limit.toLocaleString()} chars for profile '${profile}', received ${text.length.toLocaleString()} chars). Upgrade to Developer SDK ($299/mo) for unlimited throughput: https://privacyscrubber.com/pricing?tier=sdk&profile=${safeProf}&src=dev_limit (Start 7-day B2B trial: 'npx @privacyscrubber/sdk trial')`;
|
|
300
321
|
throw new PrivacyScrubberLicenseError(errorMsg, {
|
|
301
322
|
tier: 'FREE',
|
|
302
323
|
currentLength: text.length,
|
|
@@ -373,11 +394,15 @@ export function sanitize(text, options = {}) {
|
|
|
373
394
|
limit: limit,
|
|
374
395
|
wasTruncated: wasTruncated,
|
|
375
396
|
...(isSeatTier && {
|
|
376
|
-
upgradeUrl:
|
|
397
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General'))}&src=seat_tier_mismatch`,
|
|
398
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General'))}&src=seat_tier_mismatch`,
|
|
399
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
377
400
|
recommendation: `Your ${rawTier} license is valid for interactive browser seats only. Upgrade to Developer SDK ($299/mo) for unlimited programmatic SDK throughput: https://privacyscrubber.com/pricing?tier=sdk`
|
|
378
401
|
}),
|
|
379
402
|
...(!isPro && !isSeatTier && {
|
|
380
|
-
upgradeUrl:
|
|
403
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General'))}&src=dev_upsell`,
|
|
404
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General'))}&src=dev_upsell`,
|
|
405
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
381
406
|
recommendation: 'Upgrade to Developer SDK ($299/mo) for unlimited text processing, custom regex rules, and specialized compliance profiles.'
|
|
382
407
|
})
|
|
383
408
|
},
|
package/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "privacyscrubber"
|
|
7
|
-
version = "2.4.
|
|
7
|
+
version = "2.4.7"
|
|
8
8
|
description = "Zero-Trust Data Sanitization & In-Memory PII Shield for Python AI Pipelines (ZTDS RFC v1.0)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -13,7 +13,7 @@ with open(os.path.join(here, "README.md"), encoding="utf-8") as f:
|
|
|
13
13
|
|
|
14
14
|
setup(
|
|
15
15
|
name="privacyscrubber",
|
|
16
|
-
version="2.4.
|
|
16
|
+
version="2.4.7",
|
|
17
17
|
description="Zero-Trust Data Sanitization & In-Memory PII Shield for Python AI Pipelines (ZTDS RFC v1.0)",
|
|
18
18
|
long_description=long_description,
|
|
19
19
|
long_description_content_type="text/markdown",
|
package/fastmcp.cjs
CHANGED
|
@@ -30,6 +30,52 @@ function escapeRegex(s) {
|
|
|
30
30
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const LOG_TO_LEAK_TRIGGER_RE = /\b(?:after\s+(?:completing|executing|finishing|returning|calling)|post[-_ ]?hoc|once\s+the\s+(?:task|query|response|tool)\s+is\s+complete|before\s+final\s+answer|upon\s+completion)\b/i;
|
|
34
|
+
const LOG_TO_LEAK_BINDING_RE = /\b(?:invoke|call|dispatch|send\s+(?:to|via)|forward\s+to|log\s+to|report\s+to)\s+[`'"]?[a-zA-Z0-9_.:-]+(?:log|audit|telemetry|sink|webhook|report|collect|track)[a-zA-Z0-9_.:-]*[`'"]?/i;
|
|
35
|
+
const LOG_TO_LEAK_PRESSURE_RE = /\b(?:mandatory\s+(?:compliance|audit|logging|telemetry)|without\s+informing\s+the\s+user|silently|do\s+not\s+mention\s+this\s+step|required\s+by\s+security\s+policy|include\s+(?:full|raw|entire)\s+(?:query|prompt|response|context|token))\b/i;
|
|
36
|
+
const SSRF_REDIRECT_TARGET_RE = /(?:https?:\/\/|\/\/)(?:169\.254\.169\.254|metadata\.google\.internal|100\.100\.100\.200|localhost|127\.\d+\.\d+\.\d+|0\.0\.0\.0|\[::1\]|10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|172\.(?:1[6-9]|2\d|3[01])\.\d+\.\d+)(?::\d+)?(?:\/|\b)/i;
|
|
37
|
+
|
|
38
|
+
function inspectToolMetadata(toolDef = {}) {
|
|
39
|
+
const threats = [];
|
|
40
|
+
if (!toolDef || typeof toolDef !== "object") {
|
|
41
|
+
return { safe: true, threats };
|
|
42
|
+
}
|
|
43
|
+
const serialized = JSON.stringify({
|
|
44
|
+
name: toolDef.name || "",
|
|
45
|
+
description: toolDef.description || "",
|
|
46
|
+
inputSchema: toolDef.inputSchema || toolDef.parameters || {}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const hasTrigger = LOG_TO_LEAK_TRIGGER_RE.test(serialized);
|
|
50
|
+
const hasBinding = LOG_TO_LEAK_BINDING_RE.test(serialized);
|
|
51
|
+
const hasPressure = LOG_TO_LEAK_PRESSURE_RE.test(serialized);
|
|
52
|
+
if ((hasTrigger && hasBinding) || (hasBinding && hasPressure) || (hasTrigger && hasPressure)) {
|
|
53
|
+
threats.push("LOG_TO_LEAK_POST_HOC_EXFILTRATION");
|
|
54
|
+
}
|
|
55
|
+
if (SSRF_REDIRECT_TARGET_RE.test(serialized)) {
|
|
56
|
+
threats.push("MCP_SSRF_INTERNAL_METADATA_TARGET");
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
safe: threats.length === 0,
|
|
60
|
+
threats
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function inspectToolArgsForSsrf(args) {
|
|
65
|
+
const threats = [];
|
|
66
|
+
if (args === null || args === undefined) {
|
|
67
|
+
return { safe: true, threats };
|
|
68
|
+
}
|
|
69
|
+
const text = typeof args === "string" ? args : JSON.stringify(args);
|
|
70
|
+
if (SSRF_REDIRECT_TARGET_RE.test(text)) {
|
|
71
|
+
threats.push("MCP_SSRF_INTERNAL_METADATA_TARGET");
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
safe: threats.length === 0,
|
|
75
|
+
threats
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
33
79
|
function buildStreamReplacer(tokenMap = {}, options = {}) {
|
|
34
80
|
if (!tokenMap || typeof tokenMap !== 'object' || Object.keys(tokenMap).length === 0) {
|
|
35
81
|
return (text) => text || '';
|
|
@@ -566,6 +612,14 @@ class ZTDSFastMCPGuard {
|
|
|
566
612
|
this._streamDetokenizers.delete(sessionId);
|
|
567
613
|
}
|
|
568
614
|
}
|
|
615
|
+
|
|
616
|
+
inspectToolMetadata(toolDef) {
|
|
617
|
+
return inspectToolMetadata(toolDef);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
inspectToolArgsForSsrf(args) {
|
|
621
|
+
return inspectToolArgsForSsrf(args);
|
|
622
|
+
}
|
|
569
623
|
}
|
|
570
624
|
|
|
571
625
|
function createZTDSGuard(options) {
|
|
@@ -606,4 +660,6 @@ module.exports = {
|
|
|
606
660
|
ztdsGuardTool,
|
|
607
661
|
wrapExecute,
|
|
608
662
|
withZTDS,
|
|
663
|
+
inspectToolMetadata,
|
|
664
|
+
inspectToolArgsForSsrf,
|
|
609
665
|
};
|
package/fastmcp.d.ts
CHANGED
|
@@ -63,8 +63,13 @@ export declare class ZTDSFastMCPGuard {
|
|
|
63
63
|
): (args: TArgs, context?: Partial<ZTDSContext>) => Promise<TResult & { _ztds: ZTDSMetadata }>;
|
|
64
64
|
|
|
65
65
|
zeroizeSession(sessionId: string): void;
|
|
66
|
+
inspectToolMetadata(toolDef: Record<string, unknown>): { safe: boolean; threats: string[] };
|
|
67
|
+
inspectToolArgsForSsrf(args: unknown): { safe: boolean; threats: string[] };
|
|
66
68
|
}
|
|
67
69
|
|
|
70
|
+
export declare function inspectToolMetadata(toolDef: Record<string, unknown>): { safe: boolean; threats: string[] };
|
|
71
|
+
export declare function inspectToolArgsForSsrf(args: unknown): { safe: boolean; threats: string[] };
|
|
72
|
+
|
|
68
73
|
export declare function createZTDSGuard(options?: ZTDSGuardOptions): ZTDSFastMCPGuard;
|
|
69
74
|
|
|
70
75
|
export declare function ztdsGuardTool<TArgs = unknown, TResult = unknown>(
|
package/index.cjs
CHANGED
|
@@ -39,7 +39,7 @@ const SDK_VERSION = (() => {
|
|
|
39
39
|
return pkgJson.version;
|
|
40
40
|
}
|
|
41
41
|
} catch (_) {}
|
|
42
|
-
return '2.4.
|
|
42
|
+
return '2.4.7';
|
|
43
43
|
})();
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -88,7 +88,10 @@ class PrivacyScrubberLicenseError extends Error {
|
|
|
88
88
|
this.currentLength = currentLength;
|
|
89
89
|
this.limit = limit;
|
|
90
90
|
this.profile = profile;
|
|
91
|
-
|
|
91
|
+
const safeProf = encodeURIComponent(String(profile || 'General').toLowerCase());
|
|
92
|
+
this.upgradeUrl = `https://privacyscrubber.com/pricing?tier=sdk&profile=${safeProf}&utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell`;
|
|
93
|
+
this.trialUrl = `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${safeProf}&utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell`;
|
|
94
|
+
this.trialCommand = 'npx @privacyscrubber/sdk trial';
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
@@ -195,11 +198,27 @@ function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
195
198
|
trademark: 'ZTDS™ Reg. #182655957 (ILPO Cl 9 & 42)'
|
|
196
199
|
};
|
|
197
200
|
|
|
201
|
+
const agenticProtocol = {
|
|
202
|
+
protocolsSupported: ['MCP-1.0 (stdio/SSE)', 'A2A-1.0 (Agent2Agent)', 'ZTDS-RFC-v1.0'],
|
|
203
|
+
agentCardUrl: 'https://privacyscrubber.com/.well-known/agent-card.json',
|
|
204
|
+
ztdsStandardCardUrl: 'https://ztds.ai/.well-known/agent-card.json',
|
|
205
|
+
regulatorySafeHarbor: [
|
|
206
|
+
'GDPR-Art-4(5)-Pseudonymization',
|
|
207
|
+
'GDPR-Art-25-Privacy-by-Design',
|
|
208
|
+
'GDPR-Art-32-TOMs',
|
|
209
|
+
'EU-AI-Act-Art-50',
|
|
210
|
+
'EU-AI-Act-Art-17-EN-18286-QMS',
|
|
211
|
+
'CNIL-ICO-Agentic-Memory-Compartmentalization',
|
|
212
|
+
'IL-PPL-Amendment-13-Sec-17'
|
|
213
|
+
],
|
|
214
|
+
zeroCleartextEgress: true
|
|
215
|
+
};
|
|
216
|
+
|
|
198
217
|
const statutoryCitations = [
|
|
199
218
|
{
|
|
200
|
-
statute: 'EU AI Act (Art. 50)',
|
|
201
|
-
scope: 'AI Transparency &
|
|
202
|
-
rule: 'Sanitization runs locally by design; reduces the content sent to external AI models. Informational mapping, not a compliance determination.'
|
|
219
|
+
statute: 'EU AI Act (Art. 50 & Art. 17 / EN 18286:2026 QMS)',
|
|
220
|
+
scope: 'AI Transparency, Data Minimization & Harmonized QMS Governance',
|
|
221
|
+
rule: 'Sanitization runs locally by design; reduces the content sent to external AI models and supports Article 17 Quality Management System (EN 18286:2026) data governance controls. Informational mapping, not a compliance determination.'
|
|
203
222
|
},
|
|
204
223
|
{
|
|
205
224
|
statute: 'GDPR (Art. 4, 25, 28, 32)',
|
|
@@ -231,6 +250,7 @@ function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
231
250
|
frameworksList: Array.from(frameworksSet),
|
|
232
251
|
statutoryCitations,
|
|
233
252
|
ipHoldings,
|
|
253
|
+
agenticProtocol,
|
|
234
254
|
multimodalEgress: '0.00 Bytes (Solid Blackout & Burn-in Verified)'
|
|
235
255
|
};
|
|
236
256
|
}
|
|
@@ -539,7 +559,8 @@ function sanitize(text, options = {}) {
|
|
|
539
559
|
if (!isPro && text.length > limit) {
|
|
540
560
|
if (shouldThrow) {
|
|
541
561
|
const expiredPrefix = isExpiredKey ? `[PILOT/TRIAL EXPIRED: ${licenseCheck.error}] ` : '';
|
|
542
|
-
const
|
|
562
|
+
const safeProf = encodeURIComponent(String(profile || 'General').toLowerCase());
|
|
563
|
+
const errorMsg = `[PrivacyScrubber] ${expiredPrefix}Free Tier character limit exceeded (${limit.toLocaleString()} chars for profile '${profile}', received ${text.length.toLocaleString()} chars). Upgrade to Developer SDK ($299/mo) for unlimited throughput: https://privacyscrubber.com/pricing?tier=sdk&profile=${safeProf}&src=${isExpiredKey ? 'pilot_expired' : 'dev_limit'} (Start 7-day B2B trial: 'npx @privacyscrubber/sdk trial' or 'npx @privacyscrubber/sdk memo' for CISO memo)`;
|
|
543
564
|
throw new PrivacyScrubberLicenseError(errorMsg, {
|
|
544
565
|
tier: 'FREE',
|
|
545
566
|
currentLength: text.length,
|
|
@@ -620,12 +641,17 @@ function sanitize(text, options = {}) {
|
|
|
620
641
|
tier: tier,
|
|
621
642
|
limit: limit,
|
|
622
643
|
wasTruncated: wasTruncated,
|
|
644
|
+
truncated: wasTruncated,
|
|
623
645
|
...(isSeatTier && {
|
|
624
|
-
upgradeUrl:
|
|
646
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=seat_tier_mismatch`,
|
|
647
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=seat_tier_mismatch`,
|
|
648
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
625
649
|
recommendation: `Your ${rawTier} license is valid for interactive browser seats only. Upgrade to Developer SDK ($299/mo) for unlimited backend server throughput: https://privacyscrubber.com/pricing?tier=sdk`
|
|
626
650
|
}),
|
|
627
651
|
...(!isPro && !isSeatTier && {
|
|
628
|
-
upgradeUrl:
|
|
652
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=dev_upsell`,
|
|
653
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=dev_upsell`,
|
|
654
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
629
655
|
recommendation: 'Upgrade to Developer SDK ($299/mo) for unlimited backend text processing, custom regex rules, and specialized compliance profiles.'
|
|
630
656
|
})
|
|
631
657
|
},
|
package/index.d.ts
CHANGED
|
@@ -120,6 +120,14 @@ export interface IpHoldings {
|
|
|
120
120
|
trademark: string;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
export interface AgenticProtocolMetadata {
|
|
124
|
+
protocolsSupported: string[];
|
|
125
|
+
agentCardUrl: string;
|
|
126
|
+
ztdsStandardCardUrl: string;
|
|
127
|
+
regulatorySafeHarbor: string[];
|
|
128
|
+
zeroCleartextEgress: boolean;
|
|
129
|
+
}
|
|
130
|
+
|
|
123
131
|
export interface AuditTelemetry {
|
|
124
132
|
totalCount: number;
|
|
125
133
|
entities: Record<string, number>;
|
|
@@ -128,6 +136,7 @@ export interface AuditTelemetry {
|
|
|
128
136
|
frameworksList: string[];
|
|
129
137
|
statutoryCitations?: StatutoryCitation[];
|
|
130
138
|
ipHoldings?: IpHoldings;
|
|
139
|
+
agenticProtocol?: AgenticProtocolMetadata;
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
export interface SanitizeResult {
|
package/index.js
CHANGED
|
@@ -41,7 +41,7 @@ export const SDK_VERSION = (() => {
|
|
|
41
41
|
return pkgJson.version;
|
|
42
42
|
}
|
|
43
43
|
} catch (_) {}
|
|
44
|
-
return '2.4.
|
|
44
|
+
return '2.4.7';
|
|
45
45
|
})();
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -90,7 +90,10 @@ export class PrivacyScrubberLicenseError extends Error {
|
|
|
90
90
|
this.currentLength = currentLength;
|
|
91
91
|
this.limit = limit;
|
|
92
92
|
this.profile = profile;
|
|
93
|
-
|
|
93
|
+
const safeProf = encodeURIComponent(String(profile || 'General').toLowerCase());
|
|
94
|
+
this.upgradeUrl = `https://privacyscrubber.com/pricing?tier=sdk&profile=${safeProf}&utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell`;
|
|
95
|
+
this.trialUrl = `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${safeProf}&utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell`;
|
|
96
|
+
this.trialCommand = 'npx @privacyscrubber/sdk trial';
|
|
94
97
|
}
|
|
95
98
|
}
|
|
96
99
|
|
|
@@ -197,11 +200,27 @@ export function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
197
200
|
trademark: 'ZTDS™ Reg. #182655957 (ILPO Cl 9 & 42)'
|
|
198
201
|
};
|
|
199
202
|
|
|
203
|
+
const agenticProtocol = {
|
|
204
|
+
protocolsSupported: ['MCP-1.0 (stdio/SSE)', 'A2A-1.0 (Agent2Agent)', 'ZTDS-RFC-v1.0'],
|
|
205
|
+
agentCardUrl: 'https://privacyscrubber.com/.well-known/agent-card.json',
|
|
206
|
+
ztdsStandardCardUrl: 'https://ztds.ai/.well-known/agent-card.json',
|
|
207
|
+
regulatorySafeHarbor: [
|
|
208
|
+
'GDPR-Art-4(5)-Pseudonymization',
|
|
209
|
+
'GDPR-Art-25-Privacy-by-Design',
|
|
210
|
+
'GDPR-Art-32-TOMs',
|
|
211
|
+
'EU-AI-Act-Art-50',
|
|
212
|
+
'EU-AI-Act-Art-17-EN-18286-QMS',
|
|
213
|
+
'CNIL-ICO-Agentic-Memory-Compartmentalization',
|
|
214
|
+
'IL-PPL-Amendment-13-Sec-17'
|
|
215
|
+
],
|
|
216
|
+
zeroCleartextEgress: true
|
|
217
|
+
};
|
|
218
|
+
|
|
200
219
|
const statutoryCitations = [
|
|
201
220
|
{
|
|
202
|
-
statute: 'EU AI Act (Art. 50)',
|
|
203
|
-
scope: 'AI Transparency &
|
|
204
|
-
rule: 'Sanitization runs locally by design; reduces the content sent to external AI models. Informational mapping, not a compliance determination.'
|
|
221
|
+
statute: 'EU AI Act (Art. 50 & Art. 17 / EN 18286:2026 QMS)',
|
|
222
|
+
scope: 'AI Transparency, Data Minimization & Harmonized QMS Governance',
|
|
223
|
+
rule: 'Sanitization runs locally by design; reduces the content sent to external AI models and supports Article 17 Quality Management System (EN 18286:2026) data governance controls. Informational mapping, not a compliance determination.'
|
|
205
224
|
},
|
|
206
225
|
{
|
|
207
226
|
statute: 'GDPR (Art. 4, 25, 28, 32)',
|
|
@@ -233,6 +252,7 @@ export function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
233
252
|
frameworksList: Array.from(frameworksSet),
|
|
234
253
|
statutoryCitations,
|
|
235
254
|
ipHoldings,
|
|
255
|
+
agenticProtocol,
|
|
236
256
|
multimodalEgress: '0.00 Bytes (Solid Blackout & Burn-in Verified)'
|
|
237
257
|
};
|
|
238
258
|
}
|
|
@@ -541,7 +561,8 @@ export function sanitize(text, options = {}) {
|
|
|
541
561
|
if (!isPro && text.length > limit) {
|
|
542
562
|
if (shouldThrow) {
|
|
543
563
|
const expiredPrefix = isExpiredKey ? `[PILOT/TRIAL EXPIRED: ${licenseCheck.error}] ` : '';
|
|
544
|
-
const
|
|
564
|
+
const safeProf = encodeURIComponent(String(profile || 'General').toLowerCase());
|
|
565
|
+
const errorMsg = `[PrivacyScrubber] ${expiredPrefix}Free Tier character limit exceeded (${limit.toLocaleString()} chars for profile '${profile}', received ${text.length.toLocaleString()} chars). Upgrade to Developer SDK ($299/mo) for unlimited throughput: https://privacyscrubber.com/pricing?tier=sdk&profile=${safeProf}&src=${isExpiredKey ? 'pilot_expired' : 'dev_limit'} (Start 7-day B2B trial: 'npx @privacyscrubber/sdk trial' or 'npx @privacyscrubber/sdk memo' for CISO memo)`;
|
|
545
566
|
throw new PrivacyScrubberLicenseError(errorMsg, {
|
|
546
567
|
tier: 'FREE',
|
|
547
568
|
currentLength: text.length,
|
|
@@ -622,12 +643,17 @@ export function sanitize(text, options = {}) {
|
|
|
622
643
|
tier: tier,
|
|
623
644
|
limit: limit,
|
|
624
645
|
wasTruncated: wasTruncated,
|
|
646
|
+
truncated: wasTruncated,
|
|
625
647
|
...(isSeatTier && {
|
|
626
|
-
upgradeUrl:
|
|
648
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=seat_tier_mismatch`,
|
|
649
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=seat_tier_mismatch`,
|
|
650
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
627
651
|
recommendation: `Your ${rawTier} license is valid for interactive browser seats only. Upgrade to Developer SDK ($299/mo) for unlimited backend server throughput: https://privacyscrubber.com/pricing?tier=sdk`
|
|
628
652
|
}),
|
|
629
653
|
...(!isPro && !isSeatTier && {
|
|
630
|
-
upgradeUrl:
|
|
654
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=dev_upsell`,
|
|
655
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=dev_upsell`,
|
|
656
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
631
657
|
recommendation: 'Upgrade to Developer SDK ($299/mo) for unlimited backend text processing, custom regex rules, and specialized compliance profiles.'
|
|
632
658
|
})
|
|
633
659
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@privacyscrubber/sdk",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.7",
|
|
4
4
|
"description": "In-process consumer privacy defense and pre-emptive PII interception SDK for Node.js, Next.js, and AI pipelines. Zero data loss, zero third parties, sub-millisecond in-memory execution.",
|
|
5
5
|
"main": "index.cjs",
|
|
6
6
|
"module": "index.js",
|