@stackone/redaction 1.7.0 → 1.8.0
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/dist/edge/index.d.mts +1 -1
- package/dist/edge/index.mjs +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +1 -1
- package/dist/node/index.d.mts +1 -1
- package/dist/node/index.mjs +1 -1
- package/package.json +1 -1
package/dist/edge/index.d.mts
CHANGED
|
@@ -68,7 +68,7 @@ declare enum CensorType {
|
|
|
68
68
|
FULL = "FULL",
|
|
69
69
|
PARTIAL = "PARTIAL",
|
|
70
70
|
}
|
|
71
|
-
declare const redactUrl: (value: string | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
71
|
+
declare const redactUrl: (value: string | URL | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
72
72
|
declare const redactPath: (value: string | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
73
73
|
declare const redactFields: <T = unknown>(value: T, censorType?: CensorType, recursive?: boolean) => T;
|
|
74
74
|
//#endregion
|
package/dist/edge/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./chunk-Cfxk5zVN.mjs";import{isMissing as t}from"@stackone/utils";const n=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`],r=`req.headers.authorization,req.headers.cookie,req.headers.cookies,req.headers["set-cookie"],req.headers["set-cookies"],req.headers.httpsAgent.options.cert,req.headers.httpsAgent.options.key,req.headers["x-stackone-external-trigger-token"],error.config.headers.authorization,error.config.data,error.config.headers.cookie,error.config.headers.cookies,error.config.headers["set-cookie"],error.config.headers["set-cookies"],error.config.httpsAgent.options.cert,error.config.httpsAgent.options.key,err.config.headers.authorization,err.config.data,err.config.headers.cookie,err.config.headers.cookies,err.config.headers["set-cookie"],err.config.headers["set-cookies"],err.config.httpsAgent.options.cert,err.config.httpsAgent.options.key,res.headers.authorization,res.headers.cookie,res.headers.cookies,res.headers["set-cookie"],res.headers["set-cookies"],res.headers.httpsAgent.options.cert,res.headers.httpsAgent.options.key,context.credentials`.split(`,`),i=`**redacted**`;let a=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>i,partialCensorFn=e=>typeof e==`string`?e.startsWith(i)?e:e.length<=10?i:`${i}${e.slice(-5)}`:i,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>capitalizeKey(e));return[...e,...n]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},o={[a.FULL]:censorFn,[a.PARTIAL]:partialCensorFn},s=getKeysToRedact(n),c=[...getPathsToRedact(r),...Array.from(s)],redactUrl=(e,n=a.FULL,r)=>{if(!t(e))try{let t=new URL(e),r=[...t.searchParams].reduce((e,[t,r])=>(e.set(t,s.has(t)?o[n](r):r),e),new URLSearchParams);return`${t.origin}${t.pathname}${r.toString()?`?`+r:``}${t.hash}`}catch(t){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),e}},redactPath=(e,n=a.FULL,r)=>{if(!t(e))try{let[t,r]=e.split(`?`);return r?`${t}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,s.has(t)?o[n](r):r),e),new URLSearchParams)}`:e}catch(t){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactFields=(e,t=a.FULL,n=!1)=>typeof e!=`object`||!e?e:Array.isArray(e)?n?e.map(e=>typeof e==`object`&&e?redactFields(e,t,n):e):[...e]:e.constructor!==Object&&e.constructor!==void 0?e:Object.entries(e).reduce((e,[r,i])=>(s.has(r)?e[r]=o[t](i):n&&typeof i==`object`&&i?e[r]=redactFields(i,t,n):e[r]=i,e),{});let l;const getRedactors=()=>(t(l)&&(l={[a.FULL]:edgeRedact({paths:c,serialize:!1,censor:o[a.FULL]}),[a.PARTIAL]:edgeRedact({paths:c,serialize:!1,censor:o[a.PARTIAL]})}),l),split=e=>e.replace(/\[(\d+)\]/g,`.$1`).split(`.`).filter(Boolean),fallbackCensor=()=>`***`,edgeRedact=e=>{let t=(e.paths??[]).map(split),n=typeof e.censor==`function`?e.censor:fallbackCensor,r=!!e.serialize,redact=e=>{if(typeof e!=`object`||!e)return r?String(e):e;for(let r of t){let t=e;for(let e=0;e<r.length-1&&t&&typeof t==`object`;e++)t=t[r[e]];let i=r[r.length-1];t&&Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=n(t[i]))}return r?JSON.stringify(e):e};return redact.restore=()=>{},redact},safeClone=e=>{let t=globalThis.structuredClone;return typeof t==`function`?t(e):JSON.parse(JSON.stringify(e))},redactObject=(e,t=a.FULL)=>{if(typeof e!=`object`||!e)return e;let n=safeClone(e);return getRedactors()[t](n)},u=!0;export{a as CensorType,u as I_AM_EDGE,redactFields,redactObject,redactPath,redactUrl,safeClone};
|
|
1
|
+
import{t as e}from"./chunk-Cfxk5zVN.mjs";import{isMissing as t}from"@stackone/utils";const n=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`],r=`req.headers.authorization,req.headers.cookie,req.headers.cookies,req.headers["set-cookie"],req.headers["set-cookies"],req.headers.httpsAgent.options.cert,req.headers.httpsAgent.options.key,req.headers["x-stackone-external-trigger-token"],error.config.headers.authorization,error.config.data,error.config.headers.cookie,error.config.headers.cookies,error.config.headers["set-cookie"],error.config.headers["set-cookies"],error.config.httpsAgent.options.cert,error.config.httpsAgent.options.key,err.config.headers.authorization,err.config.data,err.config.headers.cookie,err.config.headers.cookies,err.config.headers["set-cookie"],err.config.headers["set-cookies"],err.config.httpsAgent.options.cert,err.config.httpsAgent.options.key,res.headers.authorization,res.headers.cookie,res.headers.cookies,res.headers["set-cookie"],res.headers["set-cookies"],res.headers.httpsAgent.options.cert,res.headers.httpsAgent.options.key,context.credentials`.split(`,`),i=`**redacted**`;let a=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>i,partialCensorFn=e=>typeof e==`string`?e.startsWith(i)?e:e.length<=10?i:`${i}${e.slice(-5)}`:i,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>capitalizeKey(e));return[...e,...n]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},o={[a.FULL]:censorFn,[a.PARTIAL]:partialCensorFn},s=getKeysToRedact(n),c=[...getPathsToRedact(r),...Array.from(s)],redactUrl=(e,n=a.FULL,r)=>{if(!t(e))try{let t=new URL(e),r=[...t.searchParams].reduce((e,[t,r])=>(e.set(t,s.has(t)?o[n](r):r),e),new URLSearchParams);return`${t.origin}${t.pathname}${r.toString()?`?`+r:``}${t.hash}`}catch(t){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,n=a.FULL,r)=>{if(!t(e))try{let[t,r]=e.split(`?`);return r?`${t}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,s.has(t)?o[n](r):r),e),new URLSearchParams)}`:e}catch(t){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactFields=(e,t=a.FULL,n=!1)=>typeof e!=`object`||!e?e:Array.isArray(e)?n?e.map(e=>typeof e==`object`&&e?redactFields(e,t,n):e):[...e]:e.constructor!==Object&&e.constructor!==void 0?e:Object.entries(e).reduce((e,[r,i])=>(s.has(r)?e[r]=o[t](i):n&&typeof i==`object`&&i?e[r]=redactFields(i,t,n):e[r]=i,e),{});let l;const getRedactors=()=>(t(l)&&(l={[a.FULL]:edgeRedact({paths:c,serialize:!1,censor:o[a.FULL]}),[a.PARTIAL]:edgeRedact({paths:c,serialize:!1,censor:o[a.PARTIAL]})}),l),split=e=>e.replace(/\[(\d+)\]/g,`.$1`).split(`.`).filter(Boolean),fallbackCensor=()=>`***`,edgeRedact=e=>{let t=(e.paths??[]).map(split),n=typeof e.censor==`function`?e.censor:fallbackCensor,r=!!e.serialize,redact=e=>{if(typeof e!=`object`||!e)return r?String(e):e;for(let r of t){let t=e;for(let e=0;e<r.length-1&&t&&typeof t==`object`;e++)t=t[r[e]];let i=r[r.length-1];t&&Object.prototype.hasOwnProperty.call(t,i)&&(t[i]=n(t[i]))}return r?JSON.stringify(e):e};return redact.restore=()=>{},redact},safeClone=e=>{let t=globalThis.structuredClone;return typeof t==`function`?t(e):JSON.parse(JSON.stringify(e))},redactObject=(e,t=a.FULL)=>{if(typeof e!=`object`||!e)return e;let n=safeClone(e);return getRedactors()[t](n)},u=!0;export{a as CensorType,u as I_AM_EDGE,redactFields,redactObject,redactPath,redactUrl,safeClone};
|
package/dist/node/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require(`./config-tfC_1JL3.cjs`);let t=require(`@stackone/utils`),n=require(`fast-redact`);n=e.p(n);const r=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`],i=`req.headers.authorization,req.headers.cookie,req.headers.cookies,req.headers["set-cookie"],req.headers["set-cookies"],req.headers.httpsAgent.options.cert,req.headers.httpsAgent.options.key,req.headers["x-stackone-external-trigger-token"],error.config.headers.authorization,error.config.data,error.config.headers.cookie,error.config.headers.cookies,error.config.headers["set-cookie"],error.config.headers["set-cookies"],error.config.httpsAgent.options.cert,error.config.httpsAgent.options.key,err.config.headers.authorization,err.config.data,err.config.headers.cookie,err.config.headers.cookies,err.config.headers["set-cookie"],err.config.headers["set-cookies"],err.config.httpsAgent.options.cert,err.config.httpsAgent.options.key,res.headers.authorization,res.headers.cookie,res.headers.cookies,res.headers["set-cookie"],res.headers["set-cookies"],res.headers.httpsAgent.options.cert,res.headers.httpsAgent.options.key,context.credentials`.split(`,`),a=`**redacted**`;let o=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>a,partialCensorFn=e=>typeof e==`string`?e.startsWith(a)?e:e.length<=10?a:`${a}${e.slice(-5)}`:a,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>capitalizeKey(e));return[...e,...n]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},s={[o.FULL]:censorFn,[o.PARTIAL]:partialCensorFn},c=getKeysToRedact(r),l=[...getPathsToRedact(i),...Array.from(c)],redactUrl=(e,n=o.FULL,r)=>{if(!(0,t.isMissing)(e))try{let t=new URL(e),r=[...t.searchParams].reduce((e,[t,r])=>(e.set(t,c.has(t)?s[n](r):r),e),new URLSearchParams);return`${t.origin}${t.pathname}${r.toString()?`?`+r:``}${t.hash}`}catch(t){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),e}},redactPath=(e,n=o.FULL,r)=>{if(!(0,t.isMissing)(e))try{let[t,r]=e.split(`?`);return r?`${t}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,c.has(t)?s[n](r):r),e),new URLSearchParams)}`:e}catch(t){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactFields=(e,t=o.FULL,n=!1)=>typeof e!=`object`||!e?e:Array.isArray(e)?n?e.map(e=>typeof e==`object`&&e?redactFields(e,t,n):e):[...e]:e.constructor!==Object&&e.constructor!==void 0?e:Object.entries(e).reduce((e,[r,i])=>(c.has(r)?e[r]=s[t](i):n&&typeof i==`object`&&i?e[r]=redactFields(i,t,n):e[r]=i,e),{});function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(t,n=`[REDACTED]`,r=e.t){let i=e.a(t,r.skipPatterns),a=[],o=r.candidatePattern.flags.includes(`g`)?r.candidatePattern.flags:`${r.candidatePattern.flags}g`,s=new RegExp(r.candidatePattern.source,o),c;for(;(c=s.exec(t))!==null;){let t=c[0];t.length<r.minLength||e.o(c.index,c.index+t.length,i)||shannonEntropy(t)>=r.threshold&&a.push({start:c.index,end:c.index+t.length,original:t,replacement:n,source:`entropy`})}for(let o of r.piiPatterns??[]){let r=new RegExp(o.source,o.flags.includes(`g`)?o.flags:`${o.flags}g`),s;for(;(s=r.exec(t))!==null;){let t=s.index,r=t+s[0].length;e.o(t,r,i)||a.push({start:t,end:r,original:s[0],replacement:n,source:`entropy`})}}let l=e.s(a);return{scrubbed:e.i(t,l),redactions:l}}var PiiRedaction=class{constructor(t){this.tier2=null,this.tier2LoadPromise=null,this.config=e.r(t),this.enableTier2=t?.enableTier2??!1,this.logger=t?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(t){let n=performance.now();if(!this.enableTier2)return this.scrub(t);let r=!1,i=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let e=await this.tier2.detectSecrets(t);for(let t of e)i.push({start:t.start,end:t.end,original:t.text,replacement:this.config.redactionToken,source:`model`,label:t.label});r=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(t,this.config.redactionToken,this.config.entropy);i.push(...a);let o=e.s(i);return{scrubbed:e.i(t,o),redactions:o,tier:r?`model+entropy`:`entropy`,modelAvailable:r,latencyMs:performance.now()-n}}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await Promise.resolve().then(()=>require(`./tier2-classifier-uX1K94UJ.cjs`));this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed, and the model has been downloaded via \`npm run download-model\`.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let u;const getRedactors=()=>((0,t.isMissing)(u)&&(u={[o.FULL]:(0,n.default)({paths:l,serialize:!1,censor:s[o.FULL]}),[o.PARTIAL]:(0,n.default)({paths:l,serialize:!1,censor:s[o.PARTIAL]})}),u),redactObject=(e,n=o.FULL)=>(0,t.isMissing)(e)||typeof e!=`object`||!e?e:getRedactors()[n]((0,t.deepCopy)(e)),d=!1;exports.CensorType=o,exports.I_AM_EDGE=!1,exports.MODEL_FILES=e.c,exports.PiiRedaction=PiiRedaction,exports.createPiiRedaction=createPiiRedaction,exports.entropyScrub=entropyScrub,exports.getDefaultModelCacheDir=e.u,exports.isModelPresent=e.d,exports.redactFields=redactFields,exports.redactObject=redactObject,exports.redactPath=redactPath,exports.redactUrl=redactUrl,exports.shannonEntropy=shannonEntropy;
|
|
1
|
+
const e=require(`./config-tfC_1JL3.cjs`);let t=require(`@stackone/utils`),n=require(`fast-redact`);n=e.p(n);const r=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`],i=`req.headers.authorization,req.headers.cookie,req.headers.cookies,req.headers["set-cookie"],req.headers["set-cookies"],req.headers.httpsAgent.options.cert,req.headers.httpsAgent.options.key,req.headers["x-stackone-external-trigger-token"],error.config.headers.authorization,error.config.data,error.config.headers.cookie,error.config.headers.cookies,error.config.headers["set-cookie"],error.config.headers["set-cookies"],error.config.httpsAgent.options.cert,error.config.httpsAgent.options.key,err.config.headers.authorization,err.config.data,err.config.headers.cookie,err.config.headers.cookies,err.config.headers["set-cookie"],err.config.headers["set-cookies"],err.config.httpsAgent.options.cert,err.config.httpsAgent.options.key,res.headers.authorization,res.headers.cookie,res.headers.cookies,res.headers["set-cookie"],res.headers["set-cookies"],res.headers.httpsAgent.options.cert,res.headers.httpsAgent.options.key,context.credentials`.split(`,`),a=`**redacted**`;let o=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>a,partialCensorFn=e=>typeof e==`string`?e.startsWith(a)?e:e.length<=10?a:`${a}${e.slice(-5)}`:a,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>capitalizeKey(e));return[...e,...n]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},s={[o.FULL]:censorFn,[o.PARTIAL]:partialCensorFn},c=getKeysToRedact(r),l=[...getPathsToRedact(i),...Array.from(c)],redactUrl=(e,n=o.FULL,r)=>{if(!(0,t.isMissing)(e))try{let t=new URL(e),r=[...t.searchParams].reduce((e,[t,r])=>(e.set(t,c.has(t)?s[n](r):r),e),new URLSearchParams);return`${t.origin}${t.pathname}${r.toString()?`?`+r:``}${t.hash}`}catch(t){return r?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,n=o.FULL,r)=>{if(!(0,t.isMissing)(e))try{let[t,r]=e.split(`?`);return r?`${t}?${[...new URLSearchParams(r)].reduce((e,[t,r])=>(e.set(t,c.has(t)?s[n](r):r),e),new URLSearchParams)}`:e}catch(t){return r?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactFields=(e,t=o.FULL,n=!1)=>typeof e!=`object`||!e?e:Array.isArray(e)?n?e.map(e=>typeof e==`object`&&e?redactFields(e,t,n):e):[...e]:e.constructor!==Object&&e.constructor!==void 0?e:Object.entries(e).reduce((e,[r,i])=>(c.has(r)?e[r]=s[t](i):n&&typeof i==`object`&&i?e[r]=redactFields(i,t,n):e[r]=i,e),{});function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(t,n=`[REDACTED]`,r=e.t){let i=e.a(t,r.skipPatterns),a=[],o=r.candidatePattern.flags.includes(`g`)?r.candidatePattern.flags:`${r.candidatePattern.flags}g`,s=new RegExp(r.candidatePattern.source,o),c;for(;(c=s.exec(t))!==null;){let t=c[0];t.length<r.minLength||e.o(c.index,c.index+t.length,i)||shannonEntropy(t)>=r.threshold&&a.push({start:c.index,end:c.index+t.length,original:t,replacement:n,source:`entropy`})}for(let o of r.piiPatterns??[]){let r=new RegExp(o.source,o.flags.includes(`g`)?o.flags:`${o.flags}g`),s;for(;(s=r.exec(t))!==null;){let t=s.index,r=t+s[0].length;e.o(t,r,i)||a.push({start:t,end:r,original:s[0],replacement:n,source:`entropy`})}}let l=e.s(a);return{scrubbed:e.i(t,l),redactions:l}}var PiiRedaction=class{constructor(t){this.tier2=null,this.tier2LoadPromise=null,this.config=e.r(t),this.enableTier2=t?.enableTier2??!1,this.logger=t?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(t){let n=performance.now();if(!this.enableTier2)return this.scrub(t);let r=!1,i=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let e=await this.tier2.detectSecrets(t);for(let t of e)i.push({start:t.start,end:t.end,original:t.text,replacement:this.config.redactionToken,source:`model`,label:t.label});r=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(t,this.config.redactionToken,this.config.entropy);i.push(...a);let o=e.s(i);return{scrubbed:e.i(t,o),redactions:o,tier:r?`model+entropy`:`entropy`,modelAvailable:r,latencyMs:performance.now()-n}}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await Promise.resolve().then(()=>require(`./tier2-classifier-uX1K94UJ.cjs`));this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed, and the model has been downloaded via \`npm run download-model\`.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let u;const getRedactors=()=>((0,t.isMissing)(u)&&(u={[o.FULL]:(0,n.default)({paths:l,serialize:!1,censor:s[o.FULL]}),[o.PARTIAL]:(0,n.default)({paths:l,serialize:!1,censor:s[o.PARTIAL]})}),u),redactObject=(e,n=o.FULL)=>(0,t.isMissing)(e)||typeof e!=`object`||!e?e:getRedactors()[n]((0,t.deepCopy)(e)),d=!1;exports.CensorType=o,exports.I_AM_EDGE=!1,exports.MODEL_FILES=e.c,exports.PiiRedaction=PiiRedaction,exports.createPiiRedaction=createPiiRedaction,exports.entropyScrub=entropyScrub,exports.getDefaultModelCacheDir=e.u,exports.isModelPresent=e.d,exports.redactFields=redactFields,exports.redactObject=redactObject,exports.redactPath=redactPath,exports.redactUrl=redactUrl,exports.shannonEntropy=shannonEntropy;
|
package/dist/node/index.d.cts
CHANGED
|
@@ -67,7 +67,7 @@ declare enum CensorType {
|
|
|
67
67
|
FULL = "FULL",
|
|
68
68
|
PARTIAL = "PARTIAL",
|
|
69
69
|
}
|
|
70
|
-
declare const redactUrl: (value: string | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
70
|
+
declare const redactUrl: (value: string | URL | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
71
71
|
declare const redactPath: (value: string | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
72
72
|
declare const redactFields: <T = unknown>(value: T, censorType?: CensorType, recursive?: boolean) => T;
|
|
73
73
|
//#endregion
|
package/dist/node/index.d.mts
CHANGED
|
@@ -68,7 +68,7 @@ declare enum CensorType {
|
|
|
68
68
|
FULL = "FULL",
|
|
69
69
|
PARTIAL = "PARTIAL",
|
|
70
70
|
}
|
|
71
|
-
declare const redactUrl: (value: string | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
71
|
+
declare const redactUrl: (value: string | URL | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
72
72
|
declare const redactPath: (value: string | undefined, censorType?: CensorType, logger?: ILogger) => string | undefined;
|
|
73
73
|
declare const redactFields: <T = unknown>(value: T, censorType?: CensorType, recursive?: boolean) => T;
|
|
74
74
|
//#endregion
|
package/dist/node/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./chunk-Cfxk5zVN.mjs";import{a as t,c as n,d as r,i,o as a,r as o,s,t as c,u as l}from"./config-M7RWfWu6.mjs";import{deepCopy as u,isMissing as d}from"@stackone/utils";import f from"fast-redact";const p=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`],m=`req.headers.authorization,req.headers.cookie,req.headers.cookies,req.headers["set-cookie"],req.headers["set-cookies"],req.headers.httpsAgent.options.cert,req.headers.httpsAgent.options.key,req.headers["x-stackone-external-trigger-token"],error.config.headers.authorization,error.config.data,error.config.headers.cookie,error.config.headers.cookies,error.config.headers["set-cookie"],error.config.headers["set-cookies"],error.config.httpsAgent.options.cert,error.config.httpsAgent.options.key,err.config.headers.authorization,err.config.data,err.config.headers.cookie,err.config.headers.cookies,err.config.headers["set-cookie"],err.config.headers["set-cookies"],err.config.httpsAgent.options.cert,err.config.httpsAgent.options.key,res.headers.authorization,res.headers.cookie,res.headers.cookies,res.headers["set-cookie"],res.headers["set-cookies"],res.headers.httpsAgent.options.cert,res.headers.httpsAgent.options.key,context.credentials`.split(`,`),h=`**redacted**`;let g=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>h,partialCensorFn=e=>typeof e==`string`?e.startsWith(h)?e:e.length<=10?h:`${h}${e.slice(-5)}`:h,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>capitalizeKey(e));return[...e,...n]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},_={[g.FULL]:censorFn,[g.PARTIAL]:partialCensorFn},v=getKeysToRedact(p),y=[...getPathsToRedact(m),...Array.from(v)],redactUrl=(e,t=g.FULL,n)=>{if(!d(e))try{let n=new URL(e),r=[...n.searchParams].reduce((e,[n,r])=>(e.set(n,v.has(n)?_[t](r):r),e),new URLSearchParams);return`${n.origin}${n.pathname}${r.toString()?`?`+r:``}${n.hash}`}catch(t){return n?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),e}},redactPath=(e,t=g.FULL,n)=>{if(!d(e))try{let[n,r]=e.split(`?`);return r?`${n}?${[...new URLSearchParams(r)].reduce((e,[n,r])=>(e.set(n,v.has(n)?_[t](r):r),e),new URLSearchParams)}`:e}catch(t){return n?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactFields=(e,t=g.FULL,n=!1)=>typeof e!=`object`||!e?e:Array.isArray(e)?n?e.map(e=>typeof e==`object`&&e?redactFields(e,t,n):e):[...e]:e.constructor!==Object&&e.constructor!==void 0?e:Object.entries(e).reduce((e,[r,i])=>(v.has(r)?e[r]=_[t](i):n&&typeof i==`object`&&i?e[r]=redactFields(i,t,n):e[r]=i,e),{});function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(e,n=`[REDACTED]`,r=c){let o=t(e,r.skipPatterns),l=[],u=r.candidatePattern.flags.includes(`g`)?r.candidatePattern.flags:`${r.candidatePattern.flags}g`,d=new RegExp(r.candidatePattern.source,u),f;for(;(f=d.exec(e))!==null;){let e=f[0];e.length<r.minLength||a(f.index,f.index+e.length,o)||shannonEntropy(e)>=r.threshold&&l.push({start:f.index,end:f.index+e.length,original:e,replacement:n,source:`entropy`})}for(let t of r.piiPatterns??[]){let r=new RegExp(t.source,t.flags.includes(`g`)?t.flags:`${t.flags}g`),i;for(;(i=r.exec(e))!==null;){let e=i.index,t=e+i[0].length;a(e,t,o)||l.push({start:e,end:t,original:i[0],replacement:n,source:`entropy`})}}let p=s(l);return{scrubbed:i(e,p),redactions:p}}var PiiRedaction=class{constructor(e){this.tier2=null,this.tier2LoadPromise=null,this.config=o(e),this.enableTier2=e?.enableTier2??!1,this.logger=e?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(e){let t=performance.now();if(!this.enableTier2)return this.scrub(e);let n=!1,r=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let t=await this.tier2.detectSecrets(e);for(let e of t)r.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});n=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(e,this.config.redactionToken,this.config.entropy);r.push(...a);let o=s(r);return{scrubbed:i(e,o),redactions:o,tier:n?`model+entropy`:`entropy`,modelAvailable:n,latencyMs:performance.now()-t}}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await import(`./tier2-classifier-CehRVVU3.mjs`);this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed, and the model has been downloaded via \`npm run download-model\`.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let b;const getRedactors=()=>(d(b)&&(b={[g.FULL]:f({paths:y,serialize:!1,censor:_[g.FULL]}),[g.PARTIAL]:f({paths:y,serialize:!1,censor:_[g.PARTIAL]})}),b),redactObject=(e,t=g.FULL)=>d(e)||typeof e!=`object`||!e?e:getRedactors()[t](u(e)),x=!1;export{g as CensorType,x as I_AM_EDGE,n as MODEL_FILES,PiiRedaction,createPiiRedaction,entropyScrub,l as getDefaultModelCacheDir,r as isModelPresent,redactFields,redactObject,redactPath,redactUrl,shannonEntropy};
|
|
1
|
+
import{t as e}from"./chunk-Cfxk5zVN.mjs";import{a as t,c as n,d as r,i,o as a,r as o,s,t as c,u as l}from"./config-M7RWfWu6.mjs";import{deepCopy as u,isMissing as d}from"@stackone/utils";import f from"fast-redact";const p=[`client_secret`,`access_token`,`refresh_token`,`api_key`,`password`,`job_board_token`,`private_key`,`certificate`,`service_user_token`,`key_id`,`secret_key`,`provhash`,`admin_key`,`session_key`,`id_token`,`authorization`,`bh_rest_token`,`external_trigger_token`,`tempauth`,`token`],m=`req.headers.authorization,req.headers.cookie,req.headers.cookies,req.headers["set-cookie"],req.headers["set-cookies"],req.headers.httpsAgent.options.cert,req.headers.httpsAgent.options.key,req.headers["x-stackone-external-trigger-token"],error.config.headers.authorization,error.config.data,error.config.headers.cookie,error.config.headers.cookies,error.config.headers["set-cookie"],error.config.headers["set-cookies"],error.config.httpsAgent.options.cert,error.config.httpsAgent.options.key,err.config.headers.authorization,err.config.data,err.config.headers.cookie,err.config.headers.cookies,err.config.headers["set-cookie"],err.config.headers["set-cookies"],err.config.httpsAgent.options.cert,err.config.httpsAgent.options.key,res.headers.authorization,res.headers.cookie,res.headers.cookies,res.headers["set-cookie"],res.headers["set-cookies"],res.headers.httpsAgent.options.cert,res.headers.httpsAgent.options.key,context.credentials`.split(`,`),h=`**redacted**`;let g=function(e){return e.FULL=`FULL`,e.PARTIAL=`PARTIAL`,e}({});const censorFn=e=>h,partialCensorFn=e=>typeof e==`string`?e.startsWith(h)?e:e.length<=10?h:`${h}${e.slice(-5)}`:h,capitalizeWord=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}`,capitalizeLastWordAfterLastDot=e=>{let t=e.split(`.`);if(t.length<2)return capitalizeWord(e);let n=capitalizeWord(t.pop()??``);return[...t,n].join(`.`)},capitalizeWordInsideLastBrackets=e=>{let t=e.lastIndexOf(`[`),n=e.indexOf(`]`,t);if(t===-1||n===-1)return;let r=e.slice(t,n+1).replace(/(["'])([^"']*)(["'])/g,(e,t,n)=>n?t+capitalizeWord(n)+t:t+t);return`${e.slice(0,t)}${r}${e.slice(n+1)}`},capitalizeKey=e=>capitalizeWordInsideLastBrackets(e)||capitalizeLastWordAfterLastDot(e),getPathsToRedact=(e=[],t=!0)=>{if(!t)return[];let n=e.map(e=>capitalizeKey(e));return[...e,...n]},getKeysToRedact=(e=[],t=!0)=>{if(!t)return new Set;let n=new Set;return e.forEach(e=>{n.add(e);let t;t=e.includes(`_`)?e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()):/^[A-Z]/.test(e)?e.charAt(0).toLowerCase()+e.slice(1):e;let r=t.charAt(0).toUpperCase()+t.slice(1),i=t.replace(/([A-Z])/g,`_$1`).toLowerCase();n.add(t),n.add(r),n.add(i)}),n},_={[g.FULL]:censorFn,[g.PARTIAL]:partialCensorFn},v=getKeysToRedact(p),y=[...getPathsToRedact(m),...Array.from(v)],redactUrl=(e,t=g.FULL,n)=>{if(!d(e))try{let n=new URL(e),r=[...n.searchParams].reduce((e,[n,r])=>(e.set(n,v.has(n)?_[t](r):r),e),new URLSearchParams);return`${n.origin}${n.pathname}${r.toString()?`?`+r:``}${n.hash}`}catch(t){return n?.warning({message:`Invalid URL provided, unable to redact`,context:{value:e,error:t},category:`redactUrl`}),typeof e==`string`?e:e?.toString()}},redactPath=(e,t=g.FULL,n)=>{if(!d(e))try{let[n,r]=e.split(`?`);return r?`${n}?${[...new URLSearchParams(r)].reduce((e,[n,r])=>(e.set(n,v.has(n)?_[t](r):r),e),new URLSearchParams)}`:e}catch(t){return n?.warning({message:`Invalid path provided, unable to redact`,context:{value:e,error:t},category:`redactPath`}),e}},redactFields=(e,t=g.FULL,n=!1)=>typeof e!=`object`||!e?e:Array.isArray(e)?n?e.map(e=>typeof e==`object`&&e?redactFields(e,t,n):e):[...e]:e.constructor!==Object&&e.constructor!==void 0?e:Object.entries(e).reduce((e,[r,i])=>(v.has(r)?e[r]=_[t](i):n&&typeof i==`object`&&i?e[r]=redactFields(i,t,n):e[r]=i,e),{});function shannonEntropy(e){if(!e)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=e.length,r=0;for(let e of t.values()){let t=e/n;r-=t*Math.log2(t)}return r}function entropyScrub(e,n=`[REDACTED]`,r=c){let o=t(e,r.skipPatterns),l=[],u=r.candidatePattern.flags.includes(`g`)?r.candidatePattern.flags:`${r.candidatePattern.flags}g`,d=new RegExp(r.candidatePattern.source,u),f;for(;(f=d.exec(e))!==null;){let e=f[0];e.length<r.minLength||a(f.index,f.index+e.length,o)||shannonEntropy(e)>=r.threshold&&l.push({start:f.index,end:f.index+e.length,original:e,replacement:n,source:`entropy`})}for(let t of r.piiPatterns??[]){let r=new RegExp(t.source,t.flags.includes(`g`)?t.flags:`${t.flags}g`),i;for(;(i=r.exec(e))!==null;){let e=i.index,t=e+i[0].length;a(e,t,o)||l.push({start:e,end:t,original:i[0],replacement:n,source:`entropy`})}}let p=s(l);return{scrubbed:i(e,p),redactions:p}}var PiiRedaction=class{constructor(e){this.tier2=null,this.tier2LoadPromise=null,this.config=o(e),this.enableTier2=e?.enableTier2??!1,this.logger=e?.logger}async warmupTier2(){this.enableTier2&&(await this.loadTier2(),this.tier2&&await this.tier2.warmup())}isTier2Ready(){return this.tier2?.isReady()??!1}scrub(e){let t=performance.now(),{scrubbed:n,redactions:r}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return{scrubbed:n,redactions:r,tier:`entropy`,modelAvailable:!1,latencyMs:performance.now()-t}}async scrubAsync(e){let t=performance.now();if(!this.enableTier2)return this.scrub(e);let n=!1,r=[];try{if(await this.loadTier2(),!this.tier2)throw Error(`Tier 2 classifier not loaded`);let t=await this.tier2.detectSecrets(e);for(let e of t)r.push({start:e.start,end:e.end,original:e.text,replacement:this.config.redactionToken,source:`model`,label:e.label});n=!0}catch(e){this.logger?.warning({category:`pii-redaction`,message:`Tier 2 model detection failed, falling back to entropy only`,error:e instanceof Error?e:void 0,code:`TIER2_FALLBACK`})}let{redactions:a}=entropyScrub(e,this.config.redactionToken,this.config.entropy);r.push(...a);let o=s(r);return{scrubbed:i(e,o),redactions:o,tier:n?`model+entropy`:`entropy`,modelAvailable:n,latencyMs:performance.now()-t}}detect(e){let{redactions:t}=entropyScrub(e,this.config.redactionToken,this.config.entropy);return t}getConfig(){return structuredClone(this.config)}async loadTier2(){if(!this.tier2){if(this.tier2LoadPromise)return this.tier2LoadPromise;this.tier2LoadPromise=(async()=>{let{Tier2Classifier:e}=await import(`./tier2-classifier-CehRVVU3.mjs`);this.tier2=new e({onnxModelPath:this.config.model.modelPath})})();try{await this.tier2LoadPromise}catch(e){throw this.tier2LoadPromise=null,Error(`Failed to load Tier 2 classifier: ${e instanceof Error?e.message:String(e)}. Ensure onnxruntime-node and @huggingface/transformers are installed, and the model has been downloaded via \`npm run download-model\`.`)}}}};function createPiiRedaction(e){return new PiiRedaction(e)}let b;const getRedactors=()=>(d(b)&&(b={[g.FULL]:f({paths:y,serialize:!1,censor:_[g.FULL]}),[g.PARTIAL]:f({paths:y,serialize:!1,censor:_[g.PARTIAL]})}),b),redactObject=(e,t=g.FULL)=>d(e)||typeof e!=`object`||!e?e:getRedactors()[t](u(e)),x=!1;export{g as CensorType,x as I_AM_EDGE,n as MODEL_FILES,PiiRedaction,createPiiRedaction,entropyScrub,l as getDefaultModelCacheDir,r as isModelPresent,redactFields,redactObject,redactPath,redactUrl,shannonEntropy};
|