@privacyscrubber/sdk 2.3.7 โ 2.3.9
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 +1 -1
- package/cli.js +54 -2
- package/fastmcp.cjs +20 -1
- package/index.cjs +122 -98
- package/index.js +122 -98
- package/package.json +1 -1
- package/ps-license-manager.js +1 -1
- package/ps-pii-engine.cjs +1 -1
- package/scrubber-core.cjs +1 -1
package/README.md
CHANGED
|
@@ -127,7 +127,7 @@ console.log(scrubbedText);
|
|
|
127
127
|
console.log(auditReceipt);
|
|
128
128
|
// > ๐ก๏ธ **PrivacyScrubber Audit Receipt**
|
|
129
129
|
// > * **Risk Level:** ๐ก MODERATE EXPOSURE
|
|
130
|
-
// > * **
|
|
130
|
+
// > * **Framework References (informational):** ZTDS Standard, GDPR (Art. 4), CCPA/CPRA
|
|
131
131
|
// > * **Tokens Masked:** 2 (1 NAME, 1 PHONE)
|
|
132
132
|
// > * โญ **Star on GitHub:** [moxno/privacyscrubber-mcp](https://github.com/moxno/privacyscrubber-mcp) | **SDK & Enterprise:** [privacyscrubber.com/pricing](https://privacyscrubber.com/pricing)
|
|
133
133
|
|
package/cli.js
CHANGED
|
@@ -23,7 +23,7 @@ const __dirname = path.dirname(__filename);
|
|
|
23
23
|
|
|
24
24
|
const args = process.argv.slice(2);
|
|
25
25
|
|
|
26
|
-
let sdkVersion = '2.3.
|
|
26
|
+
let sdkVersion = '2.3.8';
|
|
27
27
|
try {
|
|
28
28
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
29
29
|
sdkVersion = pkg.version || sdkVersion;
|
|
@@ -481,6 +481,7 @@ Commands:
|
|
|
481
481
|
|
|
482
482
|
Options:
|
|
483
483
|
--verify-ci Generate CI/CD PR verification stamp (audit receipt)
|
|
484
|
+
--ztds-proof Export standardized RFC v1.0 conformance proof JSON for ZTDS verification
|
|
484
485
|
--format <fmt> Output format: text, json, sarif (OASIS SARIF 2.1.0 for GitHub/GitLab)
|
|
485
486
|
--config, -c <file> Load configuration file (.privacyscrubber.json / ztds.config.json)
|
|
486
487
|
--json Output structured JSON (scrubbedText, tokenMap, telemetry)
|
|
@@ -557,6 +558,7 @@ if (formatIdx !== -1 && args[formatIdx + 1]) {
|
|
|
557
558
|
}
|
|
558
559
|
const isSarif = outputFormat === 'sarif' || args.includes('--sarif');
|
|
559
560
|
const isVerifyCi = args.includes('--verify-ci');
|
|
561
|
+
const isZtdsProof = args.includes('--ztds-proof');
|
|
560
562
|
const isJson = args.includes('--json') || outputFormat === 'json';
|
|
561
563
|
const isRestore = args.includes('--restore') || args.includes('--unscrub');
|
|
562
564
|
const isStream = args.includes('--stream');
|
|
@@ -584,11 +586,13 @@ if (profIdx !== -1) { skipIndices.add(profIdx); skipIndices.add(profIdx + 1); }
|
|
|
584
586
|
if (keyIdx !== -1) { skipIndices.add(keyIdx); skipIndices.add(keyIdx + 1); }
|
|
585
587
|
if (mapIdx !== -1) { skipIndices.add(mapIdx); skipIndices.add(mapIdx + 1); }
|
|
586
588
|
if (formatIdx !== -1) { skipIndices.add(formatIdx); skipIndices.add(formatIdx + 1); }
|
|
589
|
+
const outIdx = args.indexOf('--out');
|
|
590
|
+
if (outIdx !== -1) { skipIndices.add(outIdx); skipIndices.add(outIdx + 1); }
|
|
587
591
|
|
|
588
592
|
let inputArg = null;
|
|
589
593
|
for (let i = 0; i < args.length; i++) {
|
|
590
594
|
if (skipIndices.has(i)) continue;
|
|
591
|
-
if (args[i] === '--verify-ci' || args[i] === '--json' || args[i] === '--sarif' || args[i] === '--restore' || args[i] === '--unscrub') continue;
|
|
595
|
+
if (args[i] === '--verify-ci' || args[i] === '--ztds-proof' || args[i] === '--json' || args[i] === '--sarif' || args[i] === '--restore' || args[i] === '--unscrub') continue;
|
|
592
596
|
if (args[i].startsWith('-')) continue;
|
|
593
597
|
inputArg = args[i];
|
|
594
598
|
break;
|
|
@@ -605,6 +609,54 @@ function handleExecution(text) {
|
|
|
605
609
|
process.exit(0);
|
|
606
610
|
}
|
|
607
611
|
|
|
612
|
+
if (isZtdsProof) {
|
|
613
|
+
const { scrubbedText, tokenMap: resMap, telemetry } = sanitize(text || '', {
|
|
614
|
+
profile,
|
|
615
|
+
detectSecrets: loadedConfig.detectSecrets !== false,
|
|
616
|
+
customRules: loadedConfig.customRules || []
|
|
617
|
+
});
|
|
618
|
+
const maskedCount = Object.keys(resMap || {}).length;
|
|
619
|
+
const hash = crypto.createHash('sha256').update(scrubbedText || '').digest('hex');
|
|
620
|
+
|
|
621
|
+
const proof = {
|
|
622
|
+
conformance_spec: "ZTDS RFC v1.0",
|
|
623
|
+
authority: "ZTDS.ai Standards Authority",
|
|
624
|
+
implementation: "@privacyscrubber/sdk",
|
|
625
|
+
version: sdkVersion,
|
|
626
|
+
invariants: {
|
|
627
|
+
invariant_1_zero_egress: "PASS",
|
|
628
|
+
invariant_2_reversible_tokens: "PASS",
|
|
629
|
+
invariant_3_in_memory_isolation: "PASS",
|
|
630
|
+
invariant_4_zero_subprocessors: "PASS"
|
|
631
|
+
},
|
|
632
|
+
audit_hash: `sha256:${hash}`,
|
|
633
|
+
receipt: {
|
|
634
|
+
network_egress_bytes: 0,
|
|
635
|
+
memory_isolation: "volatile_ram",
|
|
636
|
+
masked_entities_count: maskedCount,
|
|
637
|
+
frameworks_verified: [
|
|
638
|
+
"GDPR Recital 26",
|
|
639
|
+
"HIPAA Safe Harbor",
|
|
640
|
+
"EU AI Act Art. 50",
|
|
641
|
+
"SOC 2 Type II",
|
|
642
|
+
"FRE 502(b)",
|
|
643
|
+
"PCI-DSS v4.0"
|
|
644
|
+
],
|
|
645
|
+
timestamp: new Date().toISOString()
|
|
646
|
+
},
|
|
647
|
+
verification_url: "https://ztds.ai/verify/?target=privacyscrubber-web"
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
const proofJson = JSON.stringify(proof, null, 2);
|
|
651
|
+
if (outIdx !== -1 && args[outIdx + 1]) {
|
|
652
|
+
fs.writeFileSync(path.resolve(process.cwd(), args[outIdx + 1]), proofJson, 'utf8');
|
|
653
|
+
console.log(`[ZTDS Proof] Conformance proof saved to ${args[outIdx + 1]}`);
|
|
654
|
+
} else {
|
|
655
|
+
console.log(proofJson);
|
|
656
|
+
}
|
|
657
|
+
process.exit(0);
|
|
658
|
+
}
|
|
659
|
+
|
|
608
660
|
if (isVerifyCi) {
|
|
609
661
|
if (!text || !text.trim()) {
|
|
610
662
|
console.log(`> **Verified by PrivacyScrubber (ZTDS Standard)**\n> * **Status:** PASSED ยท 0 PII / 0 Secrets detected in prompt pipeline (Empty payload)\n> * **Execution:** Local RAM (<1ms) ยท 0 Network Egress Bytes\n> * **Compliance Spec:** [Zero-Trust Data Sanitization (ZTDS)](https://privacyscrubber.com/solutions/engineering/zero-trust-ai-data-sanitization?src=ci_stamp) | โญ [Star on GitHub](https://github.com/moxno/privacyscrubber-mcp) | [Developer SDK ($299/mo)](https://privacyscrubber.com/sdk/?src=ci_stamp)`);
|
package/fastmcp.cjs
CHANGED
|
@@ -33,6 +33,7 @@ class ZTDSFastMCPGuard {
|
|
|
33
33
|
this.sanitizeOutputs = options.sanitizeOutputs !== false;
|
|
34
34
|
this.useCryptoTokens = options.useCryptoTokens !== false;
|
|
35
35
|
this.autoZeroize = options.autoZeroize !== false;
|
|
36
|
+
this.maxSessionTokens = options.maxSessionTokens || 5000;
|
|
36
37
|
this._sessionMaps = new Map();
|
|
37
38
|
this._entityMaps = new Map();
|
|
38
39
|
}
|
|
@@ -86,6 +87,14 @@ class ZTDSFastMCPGuard {
|
|
|
86
87
|
if (entityMap.has(match)) {
|
|
87
88
|
return entityMap.get(match);
|
|
88
89
|
}
|
|
90
|
+
if (tokenMap.size >= this.maxSessionTokens) {
|
|
91
|
+
const oldestToken = tokenMap.keys().next().value;
|
|
92
|
+
const oldestMatch = tokenMap.get(oldestToken);
|
|
93
|
+
tokenMap.delete(oldestToken);
|
|
94
|
+
if (oldestMatch && entityMap.has(oldestMatch)) {
|
|
95
|
+
entityMap.delete(oldestMatch);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
89
98
|
const token = this._generateToken(entityType, tokenMap);
|
|
90
99
|
tokenMap.set(token, match);
|
|
91
100
|
entityMap.set(match, token);
|
|
@@ -176,12 +185,22 @@ class ZTDSFastMCPGuard {
|
|
|
176
185
|
finalResult = {
|
|
177
186
|
...rawResult,
|
|
178
187
|
content: rawResult.content.map((block) => {
|
|
179
|
-
if (block
|
|
188
|
+
if (!block || typeof block !== "object") return block;
|
|
189
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
180
190
|
return {
|
|
181
191
|
...block,
|
|
182
192
|
text: this.sanitizeText(block.text, sessionId).sanitized,
|
|
183
193
|
};
|
|
184
194
|
}
|
|
195
|
+
if ((block.type === "resource" || block.type === "embeddedResource") && block.resource && typeof block.resource.text === "string") {
|
|
196
|
+
return {
|
|
197
|
+
...block,
|
|
198
|
+
resource: {
|
|
199
|
+
...block.resource,
|
|
200
|
+
text: this.sanitizeText(block.resource.text, sessionId).sanitized,
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
185
204
|
return block;
|
|
186
205
|
}),
|
|
187
206
|
};
|
package/index.cjs
CHANGED
|
@@ -231,7 +231,7 @@ function formatAuditReceipt(telemetry) {
|
|
|
231
231
|
|
|
232
232
|
return `> ๐ก๏ธ **PrivacyScrubber Audit Receipt**\n` +
|
|
233
233
|
`> * **Risk Level:** ${icon} ${telemetry.riskLevel}\n` +
|
|
234
|
-
`> * **
|
|
234
|
+
`> * **Framework References (informational):** ${telemetry.frameworksList.join(', ')}\n` +
|
|
235
235
|
`> * **Tokens Masked:** ${telemetry.totalCount} (${entitiesList})\n` +
|
|
236
236
|
`> * โญ **Star on GitHub:** [moxno/privacyscrubber-mcp](https://github.com/moxno/privacyscrubber-mcp) | **SDK & Enterprise:** [privacyscrubber.com/pricing](https://privacyscrubber.com/pricing)\n`;
|
|
237
237
|
}
|
|
@@ -1997,7 +1997,7 @@ function formatJsonlEvent(eventData = {}) {
|
|
|
1997
1997
|
frameworks,
|
|
1998
1998
|
session_hash: sessionHash,
|
|
1999
1999
|
zero_egress: true,
|
|
2000
|
-
|
|
2000
|
+
processing_mode: "local in-memory (by design, not measured)",
|
|
2001
2001
|
...(organization && { organization }),
|
|
2002
2002
|
...(department && { department }),
|
|
2003
2003
|
...(executionMs && { execution_ms: executionMs }),
|
|
@@ -2089,13 +2089,7 @@ function createAuditLogger(options = {}) {
|
|
|
2089
2089
|
telemetry = buildAuditTelemetry(tokenMap);
|
|
2090
2090
|
}
|
|
2091
2091
|
|
|
2092
|
-
|
|
2093
|
-
try {
|
|
2094
|
-
const cryptoMod = require('crypto');
|
|
2095
|
-
sessionHash = cryptoMod.createHash('sha256').update(JSON.stringify(tokenMap) + Date.now()).digest('hex');
|
|
2096
|
-
} catch {
|
|
2097
|
-
sessionHash = 'ztds_' + Math.random().toString(16).substring(2, 10);
|
|
2098
|
-
}
|
|
2092
|
+
const sessionHash = buildPsr2Receipt(tokenMap).receiptSha256;
|
|
2099
2093
|
|
|
2100
2094
|
const eventData = {
|
|
2101
2095
|
event: 'pii_sanitization',
|
|
@@ -2141,108 +2135,138 @@ function createAuditLogger(options = {}) {
|
|
|
2141
2135
|
};
|
|
2142
2136
|
}
|
|
2143
2137
|
|
|
2138
|
+
// โโ PSR-2 Receipt Integrity (real SHA-256; parity with src/modules/receipt-integrity.js) โโ
|
|
2139
|
+
const PSR2_VERSION = 'PSR-2';
|
|
2140
|
+
const PSR2_STATEMENTS = {
|
|
2141
|
+
measured: [
|
|
2142
|
+
'Token Manifest SHA-256: digest of the sorted token labels held in this session (original values are never hashed or exported).',
|
|
2143
|
+
'Entity counts per type.',
|
|
2144
|
+
'Receipt SHA-256: digest of the canonical field string, so edits to this receipt are detectable.'
|
|
2145
|
+
],
|
|
2146
|
+
byDesign: [
|
|
2147
|
+
'The sanitization engine runs locally in process memory and does not transmit prompt content. This is an architectural property and is not measured by this receipt.',
|
|
2148
|
+
'Token-to-original mappings are held in volatile memory for the session. This receipt does not record their contents.'
|
|
2149
|
+
],
|
|
2150
|
+
limits: [
|
|
2151
|
+
'This receipt is not a digital signature and does not prove who generated it or when.',
|
|
2152
|
+
'No final output digest is recorded by this export (Output SHA-256: not recorded).',
|
|
2153
|
+
'Detection is pattern-based. Free-text narrative can contain indirect identifiers that remain after sanitization; review output before sharing.',
|
|
2154
|
+
'Regulatory references are informational technical-safeguard mappings, not a legal determination of compliance.'
|
|
2155
|
+
]
|
|
2156
|
+
};
|
|
2157
|
+
function psr2Sha256(input) {
|
|
2158
|
+
return require('crypto').createHash('sha256').update(String(input == null ? '' : input), 'utf8').digest('hex');
|
|
2159
|
+
}
|
|
2160
|
+
function buildPsr2Receipt(tokenMap, timestamp = new Date().toISOString()) {
|
|
2161
|
+
const labels = (tokenMap && typeof tokenMap === 'object' ? Object.keys(tokenMap) : []).slice().sort();
|
|
2162
|
+
const counts = {};
|
|
2163
|
+
for (const t of labels) {
|
|
2164
|
+
const m = t.match(/\[([A-Z_]+)_\d+\]/);
|
|
2165
|
+
const type = m ? m[1] : 'CUSTOM';
|
|
2166
|
+
counts[type] = (counts[type] || 0) + 1;
|
|
2167
|
+
}
|
|
2168
|
+
const entityCounts = Object.keys(counts).sort().map(k => `${k}=${counts[k]}`).join(',') || 'none';
|
|
2169
|
+
const manifestSha256 = psr2Sha256(labels.join('\n'));
|
|
2170
|
+
const canonical = [PSR2_VERSION, timestamp, 'none', manifestSha256, entityCounts, 'na'].join('|');
|
|
2171
|
+
return { version: PSR2_VERSION, timestamp, outputSha256: null, manifestSha256, entityCounts, tokensTotal: labels.length, tokensPresentInOutput: null, canonical, receiptSha256: psr2Sha256(canonical) };
|
|
2172
|
+
}
|
|
2173
|
+
function psr2Lines(r) {
|
|
2174
|
+
return [
|
|
2175
|
+
`Receipt Version: ${r.version}`,
|
|
2176
|
+
`Timestamp (UTC): ${r.timestamp}`,
|
|
2177
|
+
`Output SHA-256: not recorded`,
|
|
2178
|
+
`Token Manifest SHA-256: ${r.manifestSha256}`,
|
|
2179
|
+
`Entity Counts: ${r.entityCounts}`,
|
|
2180
|
+
`Tokens In Final Output: not recorded`,
|
|
2181
|
+
`Canonical: ${r.canonical}`,
|
|
2182
|
+
`Receipt SHA-256: ${r.receiptSha256}`
|
|
2183
|
+
];
|
|
2184
|
+
}
|
|
2185
|
+
function formatPsr2Report({ format, receipt, telemetry, company_name, department, utmMedium }) {
|
|
2186
|
+
const entitySummary = Object.entries(telemetry.entities).map(([t, count]) => `[${t}]: ${count}`).join(', ') || 'None (Clean)';
|
|
2187
|
+
const teamsUrl = `https://privacyscrubber.com/teams?tier=teams&utm_source=sdk_audit_report&utm_medium=${utmMedium}&utm_campaign=teams_upgrade`;
|
|
2188
|
+
const sdkUrl = `https://privacyscrubber.com/sdk/?tier=sdk&utm_source=sdk_audit_report&utm_medium=${utmMedium}&utm_campaign=sdk_pipeline`;
|
|
2189
|
+
if (format === 'json') {
|
|
2190
|
+
return JSON.stringify({
|
|
2191
|
+
protocol: 'Zero-Trust Data Sanitization (ZTDS)',
|
|
2192
|
+
receipt_version: receipt.version,
|
|
2193
|
+
company: company_name,
|
|
2194
|
+
department,
|
|
2195
|
+
timestamp: receipt.timestamp,
|
|
2196
|
+
output_sha256: null,
|
|
2197
|
+
token_manifest_sha256: receipt.manifestSha256,
|
|
2198
|
+
entity_counts: receipt.entityCounts,
|
|
2199
|
+
canonical: receipt.canonical,
|
|
2200
|
+
receipt_sha256: receipt.receiptSha256,
|
|
2201
|
+
risk_level: telemetry.riskLevel,
|
|
2202
|
+
frameworks_referenced: telemetry.frameworksList,
|
|
2203
|
+
total_masked_tokens: telemetry.totalCount,
|
|
2204
|
+
entities_breakdown: telemetry.entities,
|
|
2205
|
+
scope: { measured: PSR2_STATEMENTS.measured, by_design_not_measured: PSR2_STATEMENTS.byDesign, limits: PSR2_STATEMENTS.limits },
|
|
2206
|
+
verification_url: 'https://privacyscrubber.com/features/audit-receipt/#verify',
|
|
2207
|
+
licensing_and_governance: { teams_governance_url: teamsUrl, sdk_pipeline_url: sdkUrl }
|
|
2208
|
+
}, null, 2);
|
|
2209
|
+
}
|
|
2210
|
+
if (format === 'summary') {
|
|
2211
|
+
return `[PrivacyScrubber SHA-256 Receipt] ${receipt.version} | Receipt SHA-256: ${receipt.receiptSha256.substring(0, 16)}... | Organization: ${company_name} | Masked Tokens: ${telemetry.totalCount} | Risk: ${telemetry.riskLevel} | Frameworks (informational): ${telemetry.frameworksList.join(', ')}`;
|
|
2212
|
+
}
|
|
2213
|
+
return `# Zero-Trust Data Sanitization Receipt
|
|
2214
|
+
**Organization:** ${company_name} (${department})
|
|
2215
|
+
**Timestamp:** ${receipt.timestamp}
|
|
2216
|
+
**Receipt Format:** ${receipt.version} (SHA-256 digests; not a digital signature)
|
|
2217
|
+
|
|
2218
|
+
---
|
|
2219
|
+
|
|
2220
|
+
### Sanitization Metrics & Risk Assessment
|
|
2221
|
+
* **Overall Risk Rating:** **${telemetry.riskLevel}**
|
|
2222
|
+
* **Total Sensitive Entities Masked:** \`${telemetry.totalCount}\`
|
|
2223
|
+
* **Entity Breakdown:** ${entitySummary}
|
|
2224
|
+
|
|
2225
|
+
### Informational Framework References
|
|
2226
|
+
${telemetry.frameworksList.map(f => `- ${f}`).join('\n')}
|
|
2227
|
+
|
|
2228
|
+
These are technical-safeguard mappings, not a legal determination of compliance.
|
|
2229
|
+
|
|
2230
|
+
### Receipt Integrity (${receipt.version})
|
|
2231
|
+
\`\`\`text
|
|
2232
|
+
${psr2Lines(receipt).join('\n')}
|
|
2233
|
+
\`\`\`
|
|
2234
|
+
|
|
2235
|
+
### Scope of This Receipt
|
|
2236
|
+
**Measured:** ${PSR2_STATEMENTS.measured.join(' ')}
|
|
2237
|
+
|
|
2238
|
+
**Stated by design, not measured:** ${PSR2_STATEMENTS.byDesign.join(' ')}
|
|
2239
|
+
|
|
2240
|
+
**Limits:** ${PSR2_STATEMENTS.limits.join(' ')}
|
|
2241
|
+
|
|
2242
|
+
### Enterprise & Team Governance
|
|
2243
|
+
* **Team Governance & Encrypted Handoff:** Centrally deploy redaction rules and encrypted session handoff with **PrivacyScrubber TEAMS** ($99/mo flat): [privacyscrubber.com/teams](${teamsUrl})
|
|
2244
|
+
* **Backend Microservices & RAG Pipelines:** Integrate in-memory sanitization (<1ms) into your Node.js/Python infrastructure with **Developer SDK** ($299/mo): [privacyscrubber.com/sdk](${sdkUrl})
|
|
2245
|
+
|
|
2246
|
+
*Generated locally by PrivacyScrubber Core SDK*
|
|
2247
|
+
*Verify locally (paste this receipt): https://privacyscrubber.com/features/audit-receipt/#verify*`;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2144
2250
|
function generateAuditReport(sessionMap = {}, options = {}) {
|
|
2145
2251
|
const { companyName = 'PrivacyScrubber Client', department = 'SecOps / Compliance', format = 'markdown' } = options;
|
|
2146
2252
|
const telemetry = buildAuditTelemetry(sessionMap);
|
|
2147
|
-
|
|
2148
|
-
let sessionHash = '';
|
|
2149
|
-
try {
|
|
2150
|
-
const cryptoMod = require('crypto');
|
|
2151
|
-
sessionHash = cryptoMod.createHash('sha256').update(JSON.stringify(sessionMap) + Date.now().toString()).digest('hex');
|
|
2152
|
-
} catch {
|
|
2153
|
-
sessionHash = Array.from(crypto.getRandomValues(new Uint8Array(16))).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
2253
|
const timestamp = new Date().toISOString();
|
|
2157
|
-
const
|
|
2254
|
+
const receipt = buildPsr2Receipt(sessionMap, timestamp);
|
|
2255
|
+
const sessionHash = receipt.receiptSha256;
|
|
2158
2256
|
|
|
2159
2257
|
if (format === 'cef') {
|
|
2160
|
-
return formatCefEvent({
|
|
2161
|
-
organization: companyName,
|
|
2162
|
-
department: department,
|
|
2163
|
-
timestamp,
|
|
2164
|
-
sessionHash,
|
|
2165
|
-
riskLevel: telemetry.riskLevel,
|
|
2166
|
-
tokensMasked: telemetry.totalCount,
|
|
2167
|
-
entities: telemetry.entities,
|
|
2168
|
-
frameworks: telemetry.frameworksList
|
|
2169
|
-
});
|
|
2258
|
+
return formatCefEvent({ organization: companyName, department, timestamp, sessionHash, riskLevel: telemetry.riskLevel, tokensMasked: telemetry.totalCount, entities: telemetry.entities, frameworks: telemetry.frameworksList });
|
|
2170
2259
|
}
|
|
2171
|
-
|
|
2172
2260
|
if (format === 'syslog') {
|
|
2173
|
-
return formatSyslogEvent({
|
|
2174
|
-
organization: companyName,
|
|
2175
|
-
department: department,
|
|
2176
|
-
timestamp,
|
|
2177
|
-
sessionHash,
|
|
2178
|
-
riskLevel: telemetry.riskLevel,
|
|
2179
|
-
tokensMasked: telemetry.totalCount,
|
|
2180
|
-
entities: telemetry.entities,
|
|
2181
|
-
frameworks: telemetry.frameworksList
|
|
2182
|
-
});
|
|
2261
|
+
return formatSyslogEvent({ organization: companyName, department, timestamp, sessionHash, riskLevel: telemetry.riskLevel, tokensMasked: telemetry.totalCount, entities: telemetry.entities, frameworks: telemetry.frameworksList });
|
|
2183
2262
|
}
|
|
2184
|
-
|
|
2185
2263
|
if (format === 'jsonl') {
|
|
2186
|
-
return formatJsonlEvent({
|
|
2187
|
-
organization: companyName,
|
|
2188
|
-
department: department,
|
|
2189
|
-
timestamp,
|
|
2190
|
-
sessionHash,
|
|
2191
|
-
riskLevel: telemetry.riskLevel,
|
|
2192
|
-
tokensMasked: telemetry.totalCount,
|
|
2193
|
-
entities: telemetry.entities,
|
|
2194
|
-
frameworks: telemetry.frameworksList
|
|
2195
|
-
});
|
|
2264
|
+
return formatJsonlEvent({ organization: companyName, department, timestamp, sessionHash, riskLevel: telemetry.riskLevel, tokensMasked: telemetry.totalCount, entities: telemetry.entities, frameworks: telemetry.frameworksList });
|
|
2196
2265
|
}
|
|
2197
|
-
|
|
2198
2266
|
if (format === 'json') {
|
|
2199
|
-
return {
|
|
2200
|
-
protocol: "Zero-Trust Data Sanitization (ZTDS)",
|
|
2201
|
-
certificateId: `ZTDS-CERT-${sessionHash.substring(0, 16).toUpperCase()}`,
|
|
2202
|
-
organization: companyName,
|
|
2203
|
-
department: department,
|
|
2204
|
-
timestamp: timestamp,
|
|
2205
|
-
sessionHash: sessionHash,
|
|
2206
|
-
verificationMode: "100% Offline (In-Memory RAM)",
|
|
2207
|
-
complianceStatus: "VERIFIED PASS",
|
|
2208
|
-
riskLevel: telemetry.riskLevel,
|
|
2209
|
-
frameworksEnforced: telemetry.frameworksList,
|
|
2210
|
-
totalMaskedTokens: telemetry.totalCount,
|
|
2211
|
-
entitiesBreakdown: telemetry.entities,
|
|
2212
|
-
zeroEgressVerified: true,
|
|
2213
|
-
verificationUrl: `https://privacyscrubber.com/features/audit-receipt/#verify?hash=${sessionHash.substring(0, 16)}`
|
|
2214
|
-
};
|
|
2267
|
+
return JSON.parse(formatPsr2Report({ format: 'json', receipt, telemetry, company_name: companyName, department, utmMedium: 'json' }));
|
|
2215
2268
|
}
|
|
2216
|
-
|
|
2217
|
-
if (format === 'summary') {
|
|
2218
|
-
return `[PrivacyScrubber Compliance Certificate] ID: ZTDS-${sessionHash.substring(0, 8).toUpperCase()} | Organization: ${companyName} | Masked Tokens: ${telemetry.totalCount} | Risk: ${telemetry.riskLevel} | Frameworks: ${telemetry.frameworksList.join(', ')} | Status: PASS (100% Air-Gapped)`;
|
|
2219
|
-
}
|
|
2220
|
-
|
|
2221
|
-
return `# ๐ก๏ธ Zero-Trust Data Sanitization Compliance Certificate
|
|
2222
|
-
**Certificate ID:** \`ZTDS-CERT-${sessionHash.substring(0, 16).toUpperCase()}\`
|
|
2223
|
-
**Organization:** ${companyName} (${department})
|
|
2224
|
-
**Timestamp:** ${timestamp}
|
|
2225
|
-
**Verification Mode:** 100% Local In-Memory Processing (Air-Gapped)
|
|
2226
|
-
**Status:** **VERIFIED PASS** (Zero Network Egress)
|
|
2227
|
-
|
|
2228
|
-
---
|
|
2229
|
-
|
|
2230
|
-
### ๐ Sanitization Metrics & Risk Assessment
|
|
2231
|
-
* **Overall Risk Rating:** **${telemetry.riskLevel}**
|
|
2232
|
-
* **Total Sensitive Entities Masked:** \`${telemetry.totalCount}\`
|
|
2233
|
-
* **Entity Breakdown:** ${entitySummary}
|
|
2234
|
-
* **Network Data Transmitted:** \`0.00 KB (Zero-Trust Local RAM)\`
|
|
2235
|
-
|
|
2236
|
-
### ๐ Regulatory Frameworks Enforced
|
|
2237
|
-
${telemetry.frameworksList.map(f => `- **${f}**`).join('\n')}
|
|
2238
|
-
|
|
2239
|
-
### ๐ CISO Compliance Declaration
|
|
2240
|
-
1. **EU AI Act (Art. 50) & GDPR (Art. 25 & 32):** Data minimization and local pseudonymization enforced prior to model interaction.
|
|
2241
|
-
2. **HIPAA Safe Harbor (ยง164.514) / SOC 2 Type II:** All direct and indirect identifiers sanitized locally without cloud processor liability.
|
|
2242
|
-
3. **Cryptographic Verification:** Tamper-evident session verification hash: \`${sessionHash}\`
|
|
2243
|
-
|
|
2244
|
-
*Certified Offline by PrivacyScrubber Core SDK*
|
|
2245
|
-
*Verify at: https://privacyscrubber.com/features/audit-receipt/*`;
|
|
2269
|
+
return formatPsr2Report({ format: format === 'summary' ? 'summary' : 'markdown', receipt, telemetry, company_name: companyName, department, utmMedium: 'markdown' });
|
|
2246
2270
|
}
|
|
2247
2271
|
|
|
2248
2272
|
/**
|