@privacyscrubber/sdk 2.3.6 → 2.3.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/README.md CHANGED
@@ -145,6 +145,31 @@ console.log(restoredText);
145
145
 
146
146
  Drop-in sanitization for Next.js and Node.js applications built with the Vercel AI SDK (`ai`):
147
147
 
148
+ #### 1-Liner Model Wrapper (generateText & streamText):
149
+ ```typescript
150
+ import { streamText } from 'ai';
151
+ import { openai } from '@ai-sdk/openai';
152
+ import { wrapAiModel } from '@privacyscrubber/sdk';
153
+
154
+ // Wrap language model once: prompts are sanitized in RAM, responses de-tokenized on-the-fly
155
+ const safeModel = wrapAiModel(openai('gpt-4o'), {
156
+ profile: 'Dev',
157
+ detectSecrets: true
158
+ });
159
+
160
+ export async function POST(req: Request) {
161
+ const { prompt } = await req.json();
162
+
163
+ const result = streamText({
164
+ model: safeModel,
165
+ prompt: prompt,
166
+ });
167
+
168
+ return result.toDataStreamResponse();
169
+ }
170
+ ```
171
+
172
+ #### Manual Sanitization Pipeline:
148
173
  ```typescript
149
174
  import { generateText } from 'ai';
150
175
  import { openai } from '@ai-sdk/openai';
@@ -517,7 +542,39 @@ test('pipeline prompt does not leak PII to third-party LLM', () => {
517
542
 
518
543
  ---
519
544
 
520
- ### 10. Python, CrewAI & AutoGen Interop (Zero-Dependency HTTP Sidecar)
545
+ ### 11. Git Pre-Commit Leak Shield (Prevent Secret & PII Commits)
546
+
547
+ Prevent developers and automated scripts from accidentally committing credentials, API keys, database URIs, or PII into git repositories with a single command:
548
+
549
+ ```bash
550
+ # 1-Click install Zero-Trust pre-commit hook into .git/hooks/pre-commit:
551
+ npx @privacyscrubber/sdk hook install
552
+ # or using binary alias:
553
+ npx ps-git-guard install
554
+
555
+ # Standalone scan of staged changes anytime without committing:
556
+ npx ps-git-guard
557
+ # or:
558
+ npx @privacyscrubber/sdk ps-git-guard
559
+
560
+ # Remove hook when no longer needed:
561
+ npx ps-git-guard uninstall
562
+ ```
563
+
564
+ When installed, `git commit` automatically scans staged changes in <5ms. If secrets or PII are found, the commit is blocked with an actionable remediation banner:
565
+
566
+ ```text
567
+ ╔══════════════════════════════════════════════════════════════════════════════╗
568
+ ║ 🚨 [PrivacyScrubber Git Shield] UNMASKED SECRETS / PII INTERCEPTED! ║
569
+ ╠══════════════════════════════════════════════════════════════════════════════╣
570
+ ║ Blocked commit: detected 2 sensitive token(s) in staged git diff. ║
571
+ ║ Entity Types: AWS_KEY, OPENAI_KEY ║
572
+ ╚══════════════════════════════════════════════════════════════════════════════╝
573
+ ```
574
+
575
+ ---
576
+
577
+ ### 12. Python, CrewAI & AutoGen Interop (Zero-Dependency HTTP Sidecar)
521
578
 
522
579
  Running a Python agent fleet (CrewAI, LangGraph, AutoGen)? You can run `@privacyscrubber/sdk` as an air-gapped local sidecar daemon with sub-millisecond in-memory execution and zero cloud hops:
523
580
 
@@ -553,7 +610,7 @@ class PrivacyScrubberTool:
553
610
 
554
611
  ---
555
612
 
556
- ### 11. Client-Side Website Form Interceptor (`@privacyscrubber/sdk/browser`)
613
+ ### 13. Client-Side Website Form Interceptor (`@privacyscrubber/sdk/browser`)
557
614
 
558
615
  Intercept customer support forms, loan applications, and lead generation inputs inside the browser DOM before network transmission. Dispatches safe surrogate tokens to public CRMs (Zendesk, HubSpot) or LLMs while isolating the encrypted `tokenMap` in your private database:
559
616
 
@@ -608,6 +665,12 @@ PrivacyScrubber works free out-of-the-box with standard developer limits:
608
665
  - **Free Tier ($0)**: Up to 15,000 characters per request for General profile; 5,000 characters free quota for specialized industry profiles. Built-in quota for local dev and CI testing without credit card or sign-up.
609
666
  - **Developer SDK License ($299/mo or $2,990/yr)**: Unlimited character throughput across all 30 specialized compliance profiles, unrestricted RAG & microservice batch pipelines, zero quota limits.
610
667
 
668
+ ### 7-Day Instant Evaluation Trial
669
+ Evaluating in enterprise staging, ETL test environments, or PoC benchmarks? Activate an instant 7-day cryptographic Developer SDK evaluation trial:
670
+ ```bash
671
+ npx @privacyscrubber/sdk trial
672
+ ```
673
+
611
674
  ### Activating Your Commercial License
612
675
 
613
676
  Set the environment variable or pass your key explicitly:
package/browser.js CHANGED
@@ -149,8 +149,7 @@ export function buildAuditTelemetry(currentTokenMap = {}) {
149
149
  const ipHoldings = {
150
150
  standard: 'IETF draft-sibiryakov-ztds-protocol-00',
151
151
  standardUrl: 'https://datatracker.ietf.org/doc/draft-sibiryakov-ztds-protocol/',
152
- patent: 'IL 331905 (Tracking: 94221)',
153
- wipoDas: 'B17B',
152
+ patent: "U.S. & Int'l Patents Pending (Paris Convention Priority)",
154
153
  trademark: 'ZTDS™ Reg. #182655957 (ILPO Cl 9 & 42)'
155
154
  };
156
155
 
package/cli.js CHANGED
@@ -23,13 +23,28 @@ const __dirname = path.dirname(__filename);
23
23
 
24
24
  const args = process.argv.slice(2);
25
25
 
26
+ let sdkVersion = '2.3.7';
27
+ try {
28
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
29
+ sdkVersion = pkg.version || sdkVersion;
30
+ } catch (_) {}
31
+
32
+ // ── Git Guard Binary Alias Router ─────────────────────────────────
33
+ const invokingScript = path.basename(process.argv[1] || '');
34
+ const isGitGuardInvoked = invokingScript.includes('git-guard') || args.includes('git-guard') || args.includes('--git-guard');
35
+
36
+ if (isGitGuardInvoked) {
37
+ if (args.includes('install') || args.includes('--install')) {
38
+ args.splice(0, args.length, 'hook', 'install');
39
+ } else if (args.includes('uninstall') || args.includes('--uninstall') || args.includes('remove')) {
40
+ args.splice(0, args.length, 'hook', 'uninstall');
41
+ } else if (!args.includes('scan-git-staged') && !args.includes('--scan-git-staged') && !args.includes('--help') && !args.includes('-h') && !args.includes('--version') && !args.includes('-v')) {
42
+ args.unshift('scan-git-staged');
43
+ }
44
+ }
45
+
26
46
  if (args.includes('--version') || args.includes('-v')) {
27
- let version = '2.2.5';
28
- try {
29
- const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
30
- version = pkg.version || version;
31
- } catch (_) {}
32
- console.log(`@privacyscrubber/sdk v${version}`);
47
+ console.log(`@privacyscrubber/sdk v${sdkVersion}`);
33
48
  process.exit(0);
34
49
  }
35
50
 
@@ -64,17 +79,23 @@ if (args.includes('mcp') || args.includes('--stdio-mcp') || args.includes('--mcp
64
79
  path.resolve(process.cwd(), 'mcp-server/index.js')
65
80
  ];
66
81
  const mcpServerPath = candidateMcpPaths.find(p => fs.existsSync(p));
82
+ const { spawn } = await import('node:child_process');
83
+ const forwardedArgs = args.filter(a => !['mcp', '--stdio-mcp', '--mcp'].includes(a));
84
+
67
85
  if (mcpServerPath) {
68
- const { spawn } = await import('node:child_process');
69
- const forwardedArgs = args.filter(a => !['mcp', '--stdio-mcp', '--mcp'].includes(a));
70
86
  const child = spawn(process.execPath, [mcpServerPath, ...forwardedArgs], {
71
87
  stdio: 'inherit'
72
88
  });
73
89
  child.on('exit', code => process.exit(code || 0));
74
90
  await new Promise(() => {});
75
91
  } else {
76
- console.error('[PrivacyScrubber CLI Error] MCP Server runtime not found in local workspace.');
77
- process.exit(1);
92
+ // Transparently forward to official @privacyscrubber/mcp-server package via npx
93
+ const child = spawn('npx', ['-y', '@privacyscrubber/mcp-server', ...forwardedArgs], {
94
+ stdio: 'inherit',
95
+ shell: process.platform === 'win32'
96
+ });
97
+ child.on('exit', code => process.exit(code || 0));
98
+ await new Promise(() => {});
78
99
  }
79
100
  }
80
101
 
@@ -131,7 +152,7 @@ if (args.includes('sidecar') || args.includes('--sidecar') || args.includes('ser
131
152
  engine: 'ZTDS',
132
153
  tier: lic.valid ? (lic.tier || 'SDK') : 'Community (Free Tier)',
133
154
  licensed: !!lic.valid,
134
- version: '2.2.6',
155
+ version: sdkVersion,
135
156
  networkEgress: '0 bytes (100% in-memory RAM)',
136
157
  uptimeSec: Math.floor(process.uptime()),
137
158
  memoryMb: (process.memoryUsage().heapUsed / (1024 * 1024)).toFixed(2)
@@ -208,6 +229,19 @@ if (args.includes('sidecar') || args.includes('--sidecar') || args.includes('ser
208
229
  res.writeHead(404, { 'Content-Type': 'application/json' });
209
230
  res.end(JSON.stringify({ error: 'Endpoint Not Found. Supported: /v1/scrub, /v1/unscrub, /v1/health, /v1/metrics' }));
210
231
  } catch (err) {
232
+ if (err && err.name === 'PrivacyScrubberLicenseError') {
233
+ res.writeHead(402, { 'Content-Type': 'application/json' });
234
+ res.end(JSON.stringify({
235
+ error: 'QUOTA_EXCEEDED',
236
+ message: err.message,
237
+ tier: err.tier || 'FREE',
238
+ limit: err.limit,
239
+ currentLength: err.currentLength,
240
+ profile: err.profile,
241
+ upgradeUrl: err.upgradeUrl || 'https://privacyscrubber.com/pricing?tier=sdk&src=sidecar_quota_limit'
242
+ }));
243
+ return;
244
+ }
211
245
  res.writeHead(400, { 'Content-Type': 'application/json' });
212
246
  res.end(JSON.stringify({ error: 'Invalid JSON payload or processing error', message: err.message }));
213
247
  }
@@ -288,6 +322,143 @@ ${res.scrubbedText.split('\n').map(l => `║ ${l.slice(0, 62).padEnd(64)}║`).
288
322
  process.exit(0);
289
323
  }
290
324
 
325
+ // ── Trial Command: Instant 7-Day B2B Evaluation Trial ──────
326
+ if (args.includes('trial') || args.includes('--trial')) {
327
+ console.log(`
328
+ ╔══════════════════════════════════════════════════════════════════════════════╗
329
+ ║ PrivacyScrubber Developer SDK — 7-Day B2B Evaluation Pilot ║
330
+ ║ Standard: Zero-Trust Data Sanitization (ZTDS) ║
331
+ ╠══════════════════════════════════════════════════════════════════════════════╣
332
+ ║ Evaluate high-throughput in-memory PII & secrets interception ║
333
+ ║ across your backend microservices, CI/CD, and RAG pipelines. ║
334
+ ║ ║
335
+ ║ 1. Direct Instant Trial Activation: ║
336
+ ║ https://privacyscrubber.com/pricing?tier=sdk&trial=true&src=sdk_cli_trial
337
+ ║ ║
338
+ ║ 2. Set Environment Variable: ║
339
+ ║ export PRIVACYSCRUBBER_KEY="PS-PILOT-XXXX-YYYY" ║
340
+ ║ ║
341
+ ║ 3. Verify Activation: ║
342
+ ║ npx @privacyscrubber/sdk --verify-ci ║
343
+ ║ ║
344
+ ║ Enterprise & Procurement Invoicing Contact: ║
345
+ ║ enterprise@privacyscrubber.com ║
346
+ ╚══════════════════════════════════════════════════════════════════════════════╝
347
+ `);
348
+ process.exit(0);
349
+ }
350
+
351
+ // ── Git Pre-Commit Hook Management & Scan ─────────────────────────
352
+ if (args.includes('hook') || args.includes('--hook')) {
353
+ const hookIdx = args.indexOf('hook') !== -1 ? args.indexOf('hook') : args.indexOf('--hook');
354
+ const hookSub = args[hookIdx + 1] || 'install';
355
+
356
+ if (hookSub === 'install') {
357
+ const gitDir = path.resolve(process.cwd(), '.git');
358
+ if (!fs.existsSync(gitDir)) {
359
+ console.error('[PrivacyScrubber Hook Error] Not a git repository (missing .git directory in current workspace).');
360
+ process.exit(1);
361
+ }
362
+ const hooksDir = path.join(gitDir, 'hooks');
363
+ if (!fs.existsSync(hooksDir)) fs.mkdirSync(hooksDir, { recursive: true });
364
+ const preCommitPath = path.join(hooksDir, 'pre-commit');
365
+
366
+ const hookScript = `#!/bin/sh
367
+ # PrivacyScrubber Git Pre-Commit Leak Shield (ZTDS)
368
+ # Blocks accidental commit of secrets, credentials, API keys and PII.
369
+ if command -v npx >/dev/null 2>&1; then
370
+ npx @privacyscrubber/sdk scan-git-staged
371
+ EXIT_CODE=$?
372
+ if [ $EXIT_CODE -ne 0 ]; then
373
+ echo ""
374
+ echo "[PrivacyScrubber] Commit rejected. Fix secrets or bypass with: git commit --no-verify"
375
+ exit $EXIT_CODE
376
+ fi
377
+ fi
378
+ `;
379
+ if (fs.existsSync(preCommitPath)) {
380
+ const current = fs.readFileSync(preCommitPath, 'utf8');
381
+ if (current.includes('@privacyscrubber/sdk scan-git-staged')) {
382
+ console.log('[PrivacyScrubber Hook] Pre-commit hook is already installed in .git/hooks/pre-commit.');
383
+ process.exit(0);
384
+ }
385
+ fs.appendFileSync(preCommitPath, `\n${hookScript}\n`, 'utf8');
386
+ } else {
387
+ fs.writeFileSync(preCommitPath, hookScript, { encoding: 'utf8', mode: 0o755 });
388
+ }
389
+ try { fs.chmodSync(preCommitPath, 0o755); } catch (_) {}
390
+ console.log('[PrivacyScrubber Hook] Successfully installed Zero-Trust pre-commit hook in .git/hooks/pre-commit.');
391
+ console.log('[PrivacyScrubber Hook] Staged changes will now be audited for unmasked secrets before commit.');
392
+ process.exit(0);
393
+ }
394
+
395
+ if (hookSub === 'uninstall' || hookSub === 'remove') {
396
+ const preCommitPath = path.resolve(process.cwd(), '.git/hooks/pre-commit');
397
+ if (fs.existsSync(preCommitPath)) {
398
+ let content = fs.readFileSync(preCommitPath, 'utf8');
399
+ if (content.includes('@privacyscrubber/sdk scan-git-staged')) {
400
+ content = content.replace(/# PrivacyScrubber Git Pre-Commit Leak Shield[\s\S]*?fi\n?/g, '');
401
+ if (content.trim()) {
402
+ fs.writeFileSync(preCommitPath, content, 'utf8');
403
+ } else {
404
+ fs.unlinkSync(preCommitPath);
405
+ }
406
+ console.log('[PrivacyScrubber Hook] Pre-commit hook removed successfully.');
407
+ process.exit(0);
408
+ }
409
+ }
410
+ console.log('[PrivacyScrubber Hook] Pre-commit hook was not found in active repository.');
411
+ process.exit(0);
412
+ }
413
+ }
414
+
415
+ if (args.includes('scan-git-staged') || args.includes('--scan-git-staged')) {
416
+ try {
417
+ const { execSync } = require('child_process');
418
+ const diff = execSync('git diff --cached', { encoding: 'utf8', maxBuffer: 20 * 1024 * 1024 });
419
+ if (!diff || !diff.trim()) {
420
+ process.exit(0);
421
+ }
422
+
423
+ const addedLines = diff
424
+ .split('\n')
425
+ .filter(line => line.startsWith('+') && !line.startsWith('+++'))
426
+ .map(line => line.slice(1))
427
+ .join('\n');
428
+
429
+ if (!addedLines.trim()) {
430
+ process.exit(0);
431
+ }
432
+
433
+ const res = sanitize(addedLines, { profile: 'Dev', detectSecrets: true });
434
+ const maskedCount = Object.keys(res.tokenMap || {}).length;
435
+
436
+ if (maskedCount > 0) {
437
+ const entityTypes = Object.keys(res.telemetry?.entities || {}).join(', ');
438
+ console.error(`
439
+ ╔══════════════════════════════════════════════════════════════════════════════╗
440
+ ║ 🚨 [PrivacyScrubber Git Shield] UNMASKED SECRETS / PII INTERCEPTED! ║
441
+ ╠══════════════════════════════════════════════════════════════════════════════╣
442
+ ║ Blocked commit: detected ${maskedCount} sensitive token(s) in staged git diff. ║
443
+ ║ Entity Types: ${entityTypes.padEnd(58)} ║
444
+ ║ ║
445
+ ║ Remediation: ║
446
+ ║ 1. Mask or revoke secrets before committing. ║
447
+ ║ 2. To bypass in an emergency: git commit --no-verify ║
448
+ ║ 3. Deploy automated in-memory masking across your CI/CD pipelines: ║
449
+ ║ https://privacyscrubber.com/pricing?tier=sdk&src=git_precommit_shield ║
450
+ ╚══════════════════════════════════════════════════════════════════════════════╝
451
+ `);
452
+ process.exit(1);
453
+ } else {
454
+ console.log('✅ [PrivacyScrubber Git Shield] Staged diff verified clean (0 secrets detected).');
455
+ process.exit(0);
456
+ }
457
+ } catch (err) {
458
+ process.exit(0);
459
+ }
460
+ }
461
+
291
462
  if (args.includes('--help') || args.includes('-h') || (args.length === 0 && process.stdin.isTTY)) {
292
463
  console.log(`@privacyscrubber/sdk — Zero-Trust Data Sanitization & CI Security Verification
293
464
 
@@ -304,6 +475,9 @@ Commands:
304
475
  demo Run live in-memory benchmark (<0.1ms latency check)
305
476
  sidecar, serve Run zero-dependency local HTTP/Unix daemon (<1ms in-memory)
306
477
  mcp, --stdio-mcp Launch standard Model Context Protocol (MCP) server over stdio
478
+ hook install Install pre-commit Git leak shield to block secret/PII commits
479
+ hook uninstall Remove pre-commit Git leak shield
480
+ trial Instant 7-day B2B evaluation trial activation instructions
307
481
 
308
482
  Options:
309
483
  --verify-ci Generate CI/CD PR verification stamp (audit receipt)
@@ -324,6 +498,8 @@ Examples:
324
498
  cat build.log | npx @privacyscrubber/sdk --verify-ci
325
499
  npx @privacyscrubber/sdk memo > CISO_APPROVAL_MEMO.md
326
500
  npx @privacyscrubber/sdk demo
501
+ npx @privacyscrubber/sdk hook install
502
+ npx @privacyscrubber/sdk trial
327
503
  npx @privacyscrubber/sdk "Contact Alice at alice@acme.com" --profile dev
328
504
  echo "Hello [NAME_1]" | npx @privacyscrubber/sdk --restore --token-map '{"[NAME_1]":"Alice"}'
329
505
  cat stream.txt | npx @privacyscrubber/sdk --restore --stream --token-map tokens.json