@privacyscrubber/sdk 2.4.6 → 2.4.8
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 +210 -18
- package/index.d.ts +9 -0
- package/index.js +210 -18
- 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.8"
|
|
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.8",
|
|
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.8';
|
|
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
|
|
|
@@ -129,7 +132,7 @@ function validateLicenseKey(key) {
|
|
|
129
132
|
* @param {Record<string, string>|string[]} currentTokenMap
|
|
130
133
|
* @returns {object}
|
|
131
134
|
*/
|
|
132
|
-
function buildAuditTelemetry(currentTokenMap = {}) {
|
|
135
|
+
function buildAuditTelemetry(currentTokenMap = {}, extraStats = {}) {
|
|
133
136
|
const entities = {};
|
|
134
137
|
let totalCount = 0;
|
|
135
138
|
|
|
@@ -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)',
|
|
@@ -223,14 +242,34 @@ function buildAuditTelemetry(currentTokenMap = {}) {
|
|
|
223
242
|
}
|
|
224
243
|
];
|
|
225
244
|
|
|
245
|
+
const rawLicenseTier = String(extraStats?.licenseTier || '').trim().toUpperCase();
|
|
246
|
+
const isOrganizationalScope = ['TEAMS', 'SDK', 'OEM', 'ENTERPRISE', 'ENTERPRISE_AIRGAP'].includes(rawLicenseTier);
|
|
247
|
+
const auditScope = isOrganizationalScope ? {
|
|
248
|
+
tier: rawLicenseTier,
|
|
249
|
+
isOrganizational: true,
|
|
250
|
+
badge: 'ORGANIZATIONAL MULTI-SEAT COMPLIANCE SCOPE',
|
|
251
|
+
coverage: 'Covers department, clinic, or firm personnel under unified ZTDS policy governance.',
|
|
252
|
+
upgradeRecommended: false,
|
|
253
|
+
upgradeUrl: null
|
|
254
|
+
} : {
|
|
255
|
+
tier: rawLicenseTier || 'SINGLE_OPERATOR',
|
|
256
|
+
isOrganizational: false,
|
|
257
|
+
badge: 'SINGLE-OPERATOR PERSONAL SCOPE',
|
|
258
|
+
coverage: 'Valid for individual workstation only. Multi-employee clinics, CPA firms, and departments require TEAMS ($99/mo flat, unlimited seats) for organizational audit coverage.',
|
|
259
|
+
upgradeRecommended: true,
|
|
260
|
+
upgradeUrl: 'https://privacyscrubber.com/pricing/?tier=teams&utm_source=audit_receipt&utm_medium=scope_upsell'
|
|
261
|
+
};
|
|
262
|
+
|
|
226
263
|
return {
|
|
227
264
|
totalCount,
|
|
228
265
|
entities,
|
|
229
266
|
types,
|
|
230
267
|
riskLevel,
|
|
231
268
|
frameworksList: Array.from(frameworksSet),
|
|
269
|
+
auditScope,
|
|
232
270
|
statutoryCitations,
|
|
233
271
|
ipHoldings,
|
|
272
|
+
agenticProtocol,
|
|
234
273
|
multimodalEgress: '0.00 Bytes (Solid Blackout & Burn-in Verified)'
|
|
235
274
|
};
|
|
236
275
|
}
|
|
@@ -281,6 +320,19 @@ function _resetCommunityNoticeForTesting() {
|
|
|
281
320
|
communityNoticeLogged = false;
|
|
282
321
|
}
|
|
283
322
|
|
|
323
|
+
const FREE_PROD_SPECIALIZED_CALL_LIMIT = 250;
|
|
324
|
+
let _freeProdSpecializedCalls = 0;
|
|
325
|
+
let _prodProfileFallbackNoticeLogged = false;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Resets the production specialized call quota state for testing purposes.
|
|
329
|
+
* @private
|
|
330
|
+
*/
|
|
331
|
+
function _resetProdQuotaForTesting() {
|
|
332
|
+
_freeProdSpecializedCalls = 0;
|
|
333
|
+
_prodProfileFallbackNoticeLogged = false;
|
|
334
|
+
}
|
|
335
|
+
|
|
284
336
|
let devSecretNoticeLogged = false;
|
|
285
337
|
|
|
286
338
|
function emitDevSecretNoticeIfNeeded(isPro, tokenMap = {}, limit = 15000) {
|
|
@@ -461,6 +513,82 @@ We request approval to acquire a **Developer SDK License** (\$299/month flat or
|
|
|
461
513
|
* auditReceipt: string
|
|
462
514
|
* }}
|
|
463
515
|
*/
|
|
516
|
+
const SDK_VERTICAL_DETECTORS = [
|
|
517
|
+
{ profile: 'medical', label: 'Medical PHI (HIPAA)', regex: /\b(?:Patient\s*(?:Name|ID|DOB|Record)|MRN\b|Medical\s+Record|Attending\s+Physician|Chief\s+Complaint|Diagnosis\s*:|ICD-10|HIPAA|Clinical\s+Intake|Discharge\s+Summary|MedPod|NPI\s*(?:#|No|:)?\s*\d{10}|Medicare\s*(?:ID|Beneficiary|Claim)|Medicaid\s*ID|Prescription|Rx\s*#|Blood\s+Type|Vital\s+Signs|Radiology|Lab\s+Results|EHR\b|EMR\b)\b/gi },
|
|
518
|
+
{ profile: 'accounting', label: 'Tax & Accounting', regex: /\b(?:Form\s*1040|Form\s*W-2|Form\s*1099|Adjusted\s+Gross\s+Income|Employer\s+Identification\s+Number|Schedule\s+C\b|Steuer-ID|USt-IdNr|Tax\s+Return|General\s+Ledger|Withholding\s+Allowance|Total\s+Tax\s+Liability)\b/gi },
|
|
519
|
+
{ profile: 'wealthmgmt', label: 'Wealth Management', regex: /\b(?:Revocable\s+Living\s+Trust|Irrevocable\s+(?:Generation-Skipping\s+)?Trust|Grantor\s*:|Settlor\s*:|Trustee\s*:|Beneficiary\s+Designation|Roth\s+IRA|Asset\s+Allocation|FBO\b|CUSIP\s*:|Grantor\s+Retained\s+Annuity\s+Trust|AUM\s*:)\b/gi },
|
|
520
|
+
{ profile: 'legal', label: 'Legal & Contracts', regex: /\b(?:Non-Disclosure\s+Agreement|Attorney-Client\s+Privilege|Docket\s+No|Hereinafter\s+referred|Indemnification\s+Clause|Governing\s+Law\s+and\s+Jurisdiction|Plaintiff\b|Defendant\b|Subpoena\b|Deposition\b|State\s+Bar\s*#)\b/gi },
|
|
521
|
+
{ profile: 'finance', label: 'Finance & Banking', regex: /\b(?:Wire\s+Transfer\s+Authorization|SWIFT\s*\/?\s*BIC\s*:|IBAN\s*:\s*[A-Z]{2}\d{2}|ABA\s+Routing|ACH\s+Transfer|PCI-DSS|Primary\s+Account\s+Number)\b/gi },
|
|
522
|
+
{ profile: 'hr', label: 'HR & Resumes', regex: /\b(?:Employee\s*ID|Performance\s+Improvement\s+Plan|Payroll\s+Register|Gross\s+Pay\b|Net\s+Pay\b|Candidate\s+Evaluation|Compensation\s+Band|Sozialversicherungsnummer|Personalnummer|EEID\s*:)\b/gi },
|
|
523
|
+
{ profile: 'realestate', label: 'Real Estate', regex: /\b(?:Assessor\s+Parcel\s+Number|APN\s*:|MLS\s*#|Closing\s+Disclosure|Escrow\s+(?:Account|Number|Officer)|Property\s+Deed|Title\s+Insurance|Lease\s+Application)\b/gi },
|
|
524
|
+
{ profile: 'dev', label: 'API & Dev Logs', regex: /\b(?:BEGIN\s+(?:RSA|OPENSSH|EC|PRIVATE)\s+PRIVATE\s+KEY|AWS_SECRET_ACCESS_KEY|DATABASE_URL\s*=|GITHUB_TOKEN\s*=|Bearer\s+eyJ[A-Za-z0-9_-]+)\b/g },
|
|
525
|
+
{ profile: 'sales', label: 'Sales & CRM', regex: /\b(?:CRM\s+(?:Opportunity|Export)|HubSpot\b|Salesforce\b|MEDDPICC\b|Primary\s+Buyer\s*:|MSA\s+Redlines|Deal\s+Stage|Pipeline\s+Forecast|Opportunity\s+ID|Account\s+Executive)\b/gi },
|
|
526
|
+
{ profile: 'engineering', label: 'DevOps & Infra', regex: /\b(?:Incident\s+Postmortem|Kubeconfig|Kubernetes\s+Cluster|Helm\s+Chart|Terraform\s+State|DMAIC\b|Bill\s+of\s+Materials|BOM\s+Spec|CNC\s+Machining|Shop\s+Floor\s+Batch)\b/gi },
|
|
527
|
+
{ profile: 'insurance', label: 'Insurance & Claims', regex: /\b(?:Claim\s+Settlement|Policyholder\s*:|Policy\s*#?POL-|Claim\s+Number|Adjuster\s*:|Loss\s+Location|Loss\s+Run|Subrogation\b|FNOL\b|Deductible\s*:)\b/gi },
|
|
528
|
+
{ profile: 'pharma', label: 'Pharma & Trials', regex: /\b(?:Clinical\s+Trial(?:\s+Protocol)?|NCT\d{8}\b|IRB\s+Protocol|FDA\s+1572|Adverse\s+Event|Pharmacovigilance|Principal\s+Investigator|Cohort\s+[A-Z]\b|Blinded\s+Study|CDISC\b|IND\s*(?:#|Protocol))\b/gi },
|
|
529
|
+
{ profile: 'underwriting', label: 'Loan Underwriting & Income', regex: /\b(?:Loan\s+Underwriting|Mortgage\s+Appraisal|Loan\s+Application\s+#?LOS|FICO\s*:\s*\d{3}|Appraised\s+Value\s*:|80%\s+LTV|Monthly\s+Qualifying\s*:|YTD\s+Earnings|Borrower\s*:)\b/gi },
|
|
530
|
+
{ profile: 'security', label: 'Security & SIEM', regex: /\b(?:SIEM\s+Alert|CVE-\d{4}-\d{4,7}\b|Threat\s*:\s*CRITICAL|Unauthorized\s+S3\s+bucket|SOC\s+Incident|Firewall\s+Rule\s+Violation|Intrusion\s+Detection)\b/gi },
|
|
531
|
+
{ profile: 'support', label: 'Support & Tickets', regex: /\b(?:Support\s+Ticket|Ticket\s*#INC-|Zendesk\b|Intercom\b|Billing\s+Discrepancy|SLA\s+Escalation|CSAT\s+Score|Customer\s+Support\s+Escalation)\b/gi },
|
|
532
|
+
{ profile: 'compliance', label: 'Compliance Audit', regex: /\b(?:Suspicious\s+Activity\s+Report|FinCEN\s+SAR|BSA\s+Officer|31\s+CFR\b|ROPA\s+Register|Data\s+Protection\s+Impact\s+Assessment|SOC\s*2\s+Type\s+II|ISO\s*27001\s+Audit|CMMC\s+Level|ITAR\s+Controlled)\b/gi },
|
|
533
|
+
{ profile: 'ccpa', label: 'CCPA / CPRA Privacy', regex: /\b(?:CCPA\s*\/?\s*CPRA|1798\.105|Right\s+to\s+Delete|Opt-out\s+of\s+Sale|Ticket\s*#?DSAR-)\b/gi },
|
|
534
|
+
{ profile: 'bizops', label: 'Biz Ops & M&A', regex: /\b(?:Vendor\s+Master\s+Agreement|Bill\s+of\s+Lading|Customs\s+Declaration|Purchase\s+Order\s*#?PO-|Supply\s+Chain\s+Manifest)\b/gi },
|
|
535
|
+
{ profile: 'biotech', label: 'Biotech & Genomics', regex: /\b(?:Sequencing\s+Platform|Illumina\s+NovaSeq|Flowcell\s*:|FastQ\s+Sample|ClinVar\b|HGVS\s+Variant|Genomic\s+Sequencing|Bioinformatics\s+Intake|BRCA[12]\s+c\.)\b/gi },
|
|
536
|
+
{ profile: 'automotive', label: 'Automotive & EV', regex: /\b(?:Connected\s+Vehicle\s+Telematics|ECU\s+Serial|Telematics\s+Device|ASIL-D\b|DTC\s+P\d{4}\b|CAN-Bus\s+Log)\b/gi },
|
|
537
|
+
{ profile: 'energy', label: 'Energy & Smart Grid', regex: /\b(?:Critical\s+Infrastructure\s+SCADA|Substation\s+ID|Feeder\s+ID|Smart\s+Meter\s*:|ESI\s+ID\s*:|NERC\s+CIP|BES\s+Cyber\s+Asset)\b/gi },
|
|
538
|
+
{ profile: 'hospitality', label: 'Hospitality & Travel', regex: /\b(?:Airline\s+Passenger\s+Dossier|PNR\s*:\s*[A-Z0-9]{6}|e-Ticket\s*:|Boarding\s+Pass\s*:|Known\s+Traveler\s+KTN|Guest\s+Folio|Marriott\s+Bonvoy|SkyMiles)\b/gi },
|
|
539
|
+
{ profile: 'telecom', label: 'Telecom & Call Center', regex: /\b(?:Telecom\s+Subscriber\s+CDR|MSISDN\s*:|IMSI\s*:\s*\d{14,15}|IMEI\s*:\s*\d{14,16}|Cell\s+Tower\s+ID|SIP\s+Signaling)\b/gi },
|
|
540
|
+
{ profile: 'academic', label: 'Academic & Research', regex: /\b(?:FERPA\s+Student\s+Record|Student\s+ID\s*:\s*#?STU-|Disciplinary\s+Record|IEP\s+Evaluation|IRB\s+Approval)\b/gi },
|
|
541
|
+
{ profile: 'agents', label: 'AI Agents & Prompts', regex: /\b(?:Autonomous\s+Financial\s+Procurement\s+Agent|AgentID\s*:\s*agt_|Encrypted\s+Tool\s+Token|Agent\s+Memory\s*>)\b/gi }
|
|
542
|
+
];
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Automatically detects the most relevant industry compliance profile from text content.
|
|
546
|
+
* Executes in <0.05ms in local RAM with zero network egress.
|
|
547
|
+
*
|
|
548
|
+
* @param {string} text - Input document or prompt text.
|
|
549
|
+
* @returns {{
|
|
550
|
+
* detectedProfile: string,
|
|
551
|
+
* label: string,
|
|
552
|
+
* confidence: 'high'|'medium'|'low',
|
|
553
|
+
* score: number,
|
|
554
|
+
* alternatives: Array<{ profile: string, label: string, score: number }>
|
|
555
|
+
* }}
|
|
556
|
+
*/
|
|
557
|
+
function detectProfile(text) {
|
|
558
|
+
if (!text || typeof text !== 'string') {
|
|
559
|
+
return { detectedProfile: 'general', label: 'General PII', confidence: 'low', score: 0, alternatives: [] };
|
|
560
|
+
}
|
|
561
|
+
const sampleSlice = text.length > 16384 ? text.slice(0, 16384) : text;
|
|
562
|
+
const matches = [];
|
|
563
|
+
for (let i = 0; i < SDK_VERTICAL_DETECTORS.length; i++) {
|
|
564
|
+
const c = SDK_VERTICAL_DETECTORS[i];
|
|
565
|
+
c.regex.lastIndex = 0;
|
|
566
|
+
const found = sampleSlice.match(c.regex);
|
|
567
|
+
if (found && found.length > 0) {
|
|
568
|
+
matches.push({
|
|
569
|
+
profile: c.profile,
|
|
570
|
+
label: c.label,
|
|
571
|
+
score: found.length,
|
|
572
|
+
priority: i
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (matches.length === 0) {
|
|
577
|
+
return { detectedProfile: 'general', label: 'General PII', confidence: 'low', score: 0, alternatives: [] };
|
|
578
|
+
}
|
|
579
|
+
matches.sort((a, b) => (b.score !== a.score) ? (b.score - a.score) : (a.priority - b.priority));
|
|
580
|
+
const primary = matches[0];
|
|
581
|
+
const alternatives = matches.slice(1, 4).map(({ profile, label, score }) => ({ profile, label, score }));
|
|
582
|
+
const confidence = primary.score >= 3 ? 'high' : (primary.score >= 2 ? 'medium' : 'low');
|
|
583
|
+
return {
|
|
584
|
+
detectedProfile: primary.profile,
|
|
585
|
+
label: primary.label,
|
|
586
|
+
confidence,
|
|
587
|
+
score: primary.score,
|
|
588
|
+
alternatives
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
464
592
|
function sanitize(text, options = {}) {
|
|
465
593
|
if (!text || typeof text !== 'string') {
|
|
466
594
|
return {
|
|
@@ -479,7 +607,7 @@ function sanitize(text, options = {}) {
|
|
|
479
607
|
}
|
|
480
608
|
|
|
481
609
|
const {
|
|
482
|
-
profile = 'General',
|
|
610
|
+
profile: rawProfileOption = 'General',
|
|
483
611
|
licenseKey = (typeof process !== 'undefined' && (process.env?.PRIVACYSCRUBBER_KEY || process.env?.PRIVACYSCRUBBER_LICENSE_KEY)) || '',
|
|
484
612
|
customRules = [],
|
|
485
613
|
tokenLabelMap = {},
|
|
@@ -491,6 +619,12 @@ function sanitize(text, options = {}) {
|
|
|
491
619
|
ignoreList = null
|
|
492
620
|
} = options;
|
|
493
621
|
|
|
622
|
+
const isAutoProfile = Boolean(
|
|
623
|
+
(typeof rawProfileOption === 'string' && rawProfileOption.trim().toLowerCase() === 'auto') ||
|
|
624
|
+
options.autoDetectProfile === true
|
|
625
|
+
);
|
|
626
|
+
const autoDetected = isAutoProfile ? detectProfile(text) : null;
|
|
627
|
+
|
|
494
628
|
const licenseCheck = validateLicense(licenseKey);
|
|
495
629
|
const rawTier = licenseCheck.valid ? (licenseCheck.tier || 'PRO') : 'FREE';
|
|
496
630
|
const isExpiredKey = !licenseCheck.valid && typeof licenseCheck.error === 'string' && /expired/i.test(licenseCheck.error);
|
|
@@ -512,6 +646,21 @@ function sanitize(text, options = {}) {
|
|
|
512
646
|
const isSdkTier = licenseCheck.valid && ['SDK', 'OEM', 'ENTERPRISE'].includes(rawTier);
|
|
513
647
|
const isSeatTier = licenseCheck.valid && ['PRO', 'TEAMS'].includes(rawTier);
|
|
514
648
|
|
|
649
|
+
const isPro = isSdkTier;
|
|
650
|
+
const tier = isPro ? rawTier : (isSeatTier ? rawTier : 'FREE');
|
|
651
|
+
|
|
652
|
+
let autoSuggestedOnly = false;
|
|
653
|
+
let profile = rawProfileOption;
|
|
654
|
+
if (isAutoProfile && autoDetected) {
|
|
655
|
+
if (!isPro && text.length > 5000 && text.length <= 15000 && autoDetected.detectedProfile !== 'general') {
|
|
656
|
+
// Non-blocking PLG fallback: keep General for Free 5k-15k texts so auto-mode never breaks free calls
|
|
657
|
+
profile = 'General';
|
|
658
|
+
autoSuggestedOnly = true;
|
|
659
|
+
} else {
|
|
660
|
+
profile = autoDetected.detectedProfile;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
515
664
|
if (isSeatTier) {
|
|
516
665
|
const keyPreview = licenseKey ? `${licenseKey.slice(0, 12)}...` : '';
|
|
517
666
|
const errorMsg = `[PrivacyScrubber] License tier mismatch: ${rawTier} license (${keyPreview}) is licensed strictly for human seats (Web App & Chrome Extension). Backend automation, microservices, and CRM pipelines require a Developer SDK license ($299/mo). Upgrade: https://privacyscrubber.com/pricing?tier=sdk&src=seat_tier_mismatch`;
|
|
@@ -525,9 +674,6 @@ function sanitize(text, options = {}) {
|
|
|
525
674
|
}
|
|
526
675
|
}
|
|
527
676
|
|
|
528
|
-
const isPro = isSdkTier;
|
|
529
|
-
const tier = isPro ? rawTier : (isSeatTier ? rawTier : 'FREE');
|
|
530
|
-
|
|
531
677
|
emitCommunityNoticeIfNeeded(isPro);
|
|
532
678
|
|
|
533
679
|
const isSpecialized = profile && profile.toLowerCase() !== 'general';
|
|
@@ -539,7 +685,8 @@ function sanitize(text, options = {}) {
|
|
|
539
685
|
if (!isPro && text.length > limit) {
|
|
540
686
|
if (shouldThrow) {
|
|
541
687
|
const expiredPrefix = isExpiredKey ? `[PILOT/TRIAL EXPIRED: ${licenseCheck.error}] ` : '';
|
|
542
|
-
const
|
|
688
|
+
const safeProf = encodeURIComponent(String(profile || 'General').toLowerCase());
|
|
689
|
+
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
690
|
throw new PrivacyScrubberLicenseError(errorMsg, {
|
|
544
691
|
tier: 'FREE',
|
|
545
692
|
currentLength: text.length,
|
|
@@ -560,8 +707,33 @@ function sanitize(text, options = {}) {
|
|
|
560
707
|
});
|
|
561
708
|
|
|
562
709
|
// Auto-inject DevOps Secrets rules when in Dev profile or when detectSecrets is requested
|
|
563
|
-
const
|
|
564
|
-
|
|
710
|
+
const isProdEnv = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production';
|
|
711
|
+
const hasCustomEnterpriseConfig = isSpecialized || safeCustomRules.length > 0 || (Array.isArray(ignoreList) && ignoreList.length > 0);
|
|
712
|
+
let profileFallback = false;
|
|
713
|
+
let effectiveProfile = profile;
|
|
714
|
+
let effectiveCustomRules = safeCustomRules;
|
|
715
|
+
let effectiveIgnoreList = ignoreList;
|
|
716
|
+
|
|
717
|
+
if (!isPro && isProdEnv && hasCustomEnterpriseConfig) {
|
|
718
|
+
_freeProdSpecializedCalls++;
|
|
719
|
+
if (_freeProdSpecializedCalls > FREE_PROD_SPECIALIZED_CALL_LIMIT) {
|
|
720
|
+
profileFallback = true;
|
|
721
|
+
effectiveProfile = 'General';
|
|
722
|
+
effectiveCustomRules = [];
|
|
723
|
+
effectiveIgnoreList = null;
|
|
724
|
+
if (!_prodProfileFallbackNoticeLogged && typeof process !== 'undefined' && process.stderr && typeof process.stderr.write === 'function') {
|
|
725
|
+
_prodProfileFallbackNoticeLogged = true;
|
|
726
|
+
process.stderr.write(
|
|
727
|
+
`\n[@privacyscrubber/sdk] Free Production Quota (${FREE_PROD_SPECIALIZED_CALL_LIMIT} specialized calls) reached for profile '${profile}'.\n` +
|
|
728
|
+
`[@privacyscrubber/sdk] Gracefully falling back to 'General' profile (Core PII remains protected, 0 downtime).\n` +
|
|
729
|
+
`[@privacyscrubber/sdk] Unlock unlimited specialized profiles, custom rules & ignoreLists in production ($299/mo): https://privacyscrubber.com/pricing?tier=sdk&src=prod_profile_fallback (7-Day Trial: npx @privacyscrubber/sdk trial)\n\n`
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
const activeRules = [...effectiveCustomRules];
|
|
736
|
+
if (effectiveProfile.toLowerCase() === 'dev' || detectSecrets === true) {
|
|
565
737
|
DEVOPS_SECRETS_DETECTOR.forEach(rule => {
|
|
566
738
|
activeRules.push({
|
|
567
739
|
name: rule.name,
|
|
@@ -582,10 +754,10 @@ function sanitize(text, options = {}) {
|
|
|
582
754
|
textToScrub,
|
|
583
755
|
activeRules,
|
|
584
756
|
tokenLabelMap,
|
|
585
|
-
|
|
757
|
+
effectiveProfile,
|
|
586
758
|
existingSessionMap,
|
|
587
759
|
isPro,
|
|
588
|
-
|
|
760
|
+
effectiveIgnoreList
|
|
589
761
|
);
|
|
590
762
|
|
|
591
763
|
const endTime = (typeof performance !== 'undefined' && typeof performance.now === 'function')
|
|
@@ -593,7 +765,7 @@ function sanitize(text, options = {}) {
|
|
|
593
765
|
: Date.now();
|
|
594
766
|
|
|
595
767
|
const executionMs = Math.round((endTime - startTime) * 100) / 100;
|
|
596
|
-
const telemetry = buildAuditTelemetry(rawResult.tokenMap || {});
|
|
768
|
+
const telemetry = buildAuditTelemetry(rawResult.tokenMap || {}, { licenseTier: tier });
|
|
597
769
|
const auditReceipt = generateReceipt ? formatAuditReceipt(telemetry) : '';
|
|
598
770
|
|
|
599
771
|
emitDevSecretNoticeIfNeeded(isPro, rawResult.tokenMap, limit);
|
|
@@ -620,15 +792,32 @@ function sanitize(text, options = {}) {
|
|
|
620
792
|
tier: tier,
|
|
621
793
|
limit: limit,
|
|
622
794
|
wasTruncated: wasTruncated,
|
|
795
|
+
truncated: wasTruncated,
|
|
796
|
+
profileFallback: profileFallback,
|
|
797
|
+
effectiveProfile: effectiveProfile,
|
|
798
|
+
specializedCallsUsed: _freeProdSpecializedCalls,
|
|
799
|
+
specializedCallsLimit: isPro ? Infinity : FREE_PROD_SPECIALIZED_CALL_LIMIT,
|
|
623
800
|
...(isSeatTier && {
|
|
624
|
-
upgradeUrl:
|
|
801
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=seat_tier_mismatch`,
|
|
802
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=seat_tier_mismatch`,
|
|
803
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
625
804
|
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
805
|
}),
|
|
627
806
|
...(!isPro && !isSeatTier && {
|
|
628
|
-
upgradeUrl:
|
|
807
|
+
upgradeUrl: `https://privacyscrubber.com/pricing?tier=sdk&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=${profileFallback ? 'prod_profile_fallback' : 'dev_upsell'}`,
|
|
808
|
+
trialUrl: `https://privacyscrubber.com/pricing?tier=sdk&trial=true&profile=${encodeURIComponent(String(profile || 'General').toLowerCase())}&src=${profileFallback ? 'prod_profile_fallback' : 'dev_upsell'}`,
|
|
809
|
+
trialCommand: 'npx @privacyscrubber/sdk trial',
|
|
629
810
|
recommendation: 'Upgrade to Developer SDK ($299/mo) for unlimited backend text processing, custom regex rules, and specialized compliance profiles.'
|
|
630
811
|
})
|
|
631
812
|
},
|
|
813
|
+
profileDetection: {
|
|
814
|
+
autoDetected: isAutoProfile,
|
|
815
|
+
detectedProfile: autoDetected ? autoDetected.detectedProfile : String(effectiveProfile || 'General').toLowerCase(),
|
|
816
|
+
label: autoDetected ? autoDetected.label : effectiveProfile,
|
|
817
|
+
confidence: autoDetected ? autoDetected.confidence : 'high',
|
|
818
|
+
suggestedOnly: autoSuggestedOnly,
|
|
819
|
+
alternatives: autoDetected ? autoDetected.alternatives : []
|
|
820
|
+
},
|
|
632
821
|
telemetry: telemetry,
|
|
633
822
|
auditReceipt: auditReceipt
|
|
634
823
|
};
|
|
@@ -3855,6 +4044,7 @@ const {
|
|
|
3855
4044
|
|
|
3856
4045
|
const _defaultExport = {
|
|
3857
4046
|
SDK_VERSION,
|
|
4047
|
+
detectProfile,
|
|
3858
4048
|
sanitize,
|
|
3859
4049
|
sanitizeObject,
|
|
3860
4050
|
scrub,
|
|
@@ -3907,6 +4097,8 @@ const _defaultExport = {
|
|
|
3907
4097
|
scrubText,
|
|
3908
4098
|
unscrubText,
|
|
3909
4099
|
DEVOPS_SECRETS_DETECTOR,
|
|
4100
|
+
FREE_PROD_SPECIALIZED_CALL_LIMIT,
|
|
4101
|
+
_resetProdQuotaForTesting,
|
|
3910
4102
|
stripExifMetadata,
|
|
3911
4103
|
redactImageBoundingBoxes,
|
|
3912
4104
|
generateSvgRedactionOverlay
|
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 {
|