@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 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
- this.upgradeUrl = 'https://privacyscrubber.com/pricing?utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell';
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 & Data Minimization',
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 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&src=dev_limit`;
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: 'https://privacyscrubber.com/pricing?tier=sdk&src=seat_tier_mismatch',
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: 'https://privacyscrubber.com/pricing?tier=sdk&src=dev_upsell',
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
@@ -32,7 +32,7 @@ for (const a of rawArgs) {
32
32
  }
33
33
  }
34
34
 
35
- let sdkVersion = '2.4.6';
35
+ let sdkVersion = '2.4.7';
36
36
  try {
37
37
  const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
38
38
  sdkVersion = pkg.version || sdkVersion;
@@ -59,7 +59,7 @@ if FASTAPI_AVAILABLE:
59
59
  app = FastAPI(
60
60
  title="PrivacyScrubber ZTDS Sidecar Proxy",
61
61
  description="Zero-Trust Data Sanitization & In-Memory PII Shield for LLM Pipelines",
62
- version="2.4.6"
62
+ version="2.4.7"
63
63
  )
64
64
 
65
65
  @app.on_event("startup")
@@ -24,7 +24,7 @@ from privacyscrubber.exceptions import (
24
24
  PrivacyScrubberLicenseError,
25
25
  )
26
26
 
27
- __version__ = "2.4.6"
27
+ __version__ = "2.4.7"
28
28
  __author__ = "Ilya Sibiryakov (BrandMeWeb)"
29
29
  __license__ = "Proprietary"
30
30
 
@@ -115,7 +115,7 @@ rl.on('line', (line) => {
115
115
  sendResponse(id, {
116
116
  pong: true,
117
117
  engine: 'PrivacyScrubber ZTDS',
118
- version: sdk.SDK_VERSION || '2.4.6',
118
+ version: sdk.SDK_VERSION || '2.4.7',
119
119
  uptime: process.uptime()
120
120
  });
121
121
  break;
@@ -50,7 +50,7 @@ def main() -> None:
50
50
  args = parser.parse_args()
51
51
 
52
52
  if args.version:
53
- print("PrivacyScrubber ZTDS Python SDK v2.4.6")
53
+ print("PrivacyScrubber ZTDS Python SDK v2.4.7")
54
54
  sys.exit(0)
55
55
 
56
56
  if not args.command:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "privacyscrubber"
7
- version = "2.4.6"
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.6",
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.6';
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
- this.upgradeUrl = 'https://privacyscrubber.com/pricing?utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell';
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 & Data Minimization',
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 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&src=${isExpiredKey ? 'pilot_expired' : 'dev_limit'} (Run 'npx @privacyscrubber/sdk memo' for CISO approval memo)`;
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: 'https://privacyscrubber.com/pricing?tier=sdk&src=seat_tier_mismatch',
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: 'https://privacyscrubber.com/pricing?tier=sdk&src=dev_upsell',
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.6';
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
- this.upgradeUrl = 'https://privacyscrubber.com/pricing?utm_source=npm_sdk&utm_medium=sdk_error&utm_campaign=dev_upsell';
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 & Data Minimization',
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 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&src=${isExpiredKey ? 'pilot_expired' : 'dev_limit'} (Run 'npx @privacyscrubber/sdk memo' for CISO approval memo)`;
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: 'https://privacyscrubber.com/pricing?tier=sdk&src=seat_tier_mismatch',
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: 'https://privacyscrubber.com/pricing?tier=sdk&src=dev_upsell',
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.6",
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",