visus-mcp 0.2.0 → 0.3.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.
@@ -99,22 +99,24 @@ export async function visusFetchStructured(input) {
99
99
  const { title, html } = renderResult.value;
100
100
  // Step 2: Extract structured data from HTML using cheerio
101
101
  const extractedData = extractStructuredData(html, schema);
102
- // Step 3: CRITICAL - Sanitize each extracted field
102
+ // Step 3: CRITICAL - Sanitize each extracted field (with allowlisting)
103
103
  // This step CANNOT be skipped or bypassed
104
104
  const sanitizedData = {};
105
105
  const allPatternsDetected = new Set();
106
106
  const allPIITypesRedacted = new Set();
107
+ const allPIIAllowlisted = [];
107
108
  let anyContentModified = false;
108
109
  for (const [fieldName, value] of Object.entries(extractedData)) {
109
110
  if (value === null) {
110
111
  sanitizedData[fieldName] = null;
111
112
  continue;
112
113
  }
113
- const sanitizationResult = sanitize(value);
114
+ const sanitizationResult = sanitize(value, url);
114
115
  sanitizedData[fieldName] = sanitizationResult.content;
115
116
  // Collect all patterns detected across fields
116
117
  sanitizationResult.sanitization.patterns_detected.forEach(p => allPatternsDetected.add(p));
117
118
  sanitizationResult.sanitization.pii_types_redacted.forEach(p => allPIITypesRedacted.add(p));
119
+ allPIIAllowlisted.push(...sanitizationResult.sanitization.pii_allowlisted);
118
120
  if (sanitizationResult.sanitization.content_modified) {
119
121
  anyContentModified = true;
120
122
  }
@@ -126,6 +128,7 @@ export async function visusFetchStructured(input) {
126
128
  sanitization: {
127
129
  patterns_detected: Array.from(allPatternsDetected),
128
130
  pii_types_redacted: Array.from(allPIITypesRedacted),
131
+ pii_allowlisted: allPIIAllowlisted,
129
132
  content_modified: anyContentModified
130
133
  },
131
134
  metadata: {
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-structured.js","sourceRoot":"","sources":["../../src/tools/fetch-structured.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;;;;;GAKG;AACH,SAAS,qBAAqB,CAC5B,IAAY,EACZ,MAA8B;IAE9B,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,SAAS,GAAkC,EAAE,CAAC;IAEpD,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,KAAK,GAAkB,IAAI,CAAC;QAEhC,mCAAmC;QACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7F,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACzC,IAAI,EAAE;gBAAE,KAAK,GAAG,EAAE,CAAC;QACrB,CAAC;QAED,wCAAwC;aACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpI,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC7C,IAAI,EAAE;gBAAE,KAAK,GAAG,EAAE,CAAC;QACrB,CAAC;QAED,6CAA6C;aACxC,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAC5G,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,CAAC;gBAAE,KAAK,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,2BAA2B;aACtB,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/F,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,IAAI;gBAAE,KAAK,GAAG,IAAI,CAAC;QACzB,CAAC;QAED,kCAAkC;aAC7B,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC9C,IAAI,QAAQ;gBAAE,KAAK,GAAG,QAAQ,CAAC;QACjC,CAAC;QAED,yCAAyC;aACpC,IAAI,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAClF,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,KAAK;gBAAE,KAAK,GAAG,KAAK,CAAC;QAC3B,CAAC;QAED,uDAAuD;aAClD,CAAC;YACJ,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE;gBACvC,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,SAAS,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAgC;IAEhC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAElD,kBAAkB;IAClB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9E,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,CAAC;QACH,2DAA2D;QAC3D,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE;YACzC,UAAU;SACX,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QAE3C,0DAA0D;QAC1D,MAAM,aAAa,GAAG,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAE1D,mDAAmD;QACnD,0CAA0C;QAC1C,MAAM,aAAa,GAAkC,EAAE,CAAC;QACxD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,IAAI,kBAAkB,GAAG,KAAK,CAAC;QAE/B,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBAChC,SAAS;YACX,CAAC;YAED,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC3C,aAAa,CAAC,SAAS,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAEtD,8CAA8C;YAC9C,kBAAkB,CAAC,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC5D,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAC3B,CAAC;YACF,kBAAkB,CAAC,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC7D,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAC3B,CAAC;YAEF,IAAI,kBAAkB,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;gBACrD,kBAAkB,GAAG,IAAI,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,MAAM,MAAM,GAA+B;YACzC,GAAG;YACH,IAAI,EAAE,aAAa;YACnB,YAAY,EAAE;gBACZ,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBAClD,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBACnD,gBAAgB,EAAE,kBAAkB;aACrC;YACD,QAAQ,EAAE;gBACR,KAAK,EAAE,KAAK,IAAI,UAAU;gBAC1B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,uBAAuB,EAAE,IAAI,CAAC,MAAM;gBACpC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;qBACnD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;qBACvB,IAAI,CAAC,GAAG,CAAC;qBACT,MAAM;aACV;SACF,CAAC;QAEF,oCAAoC;QACpC,IAAI,mBAAmB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,+BAA+B;gBACtC,GAAG;gBACH,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBACzC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aAC5B,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAErC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG;IAChD,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,0KAA0K;IACvL,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gDAAgD;aAC9D;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kEAAkE;gBAC/E,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ;iBACf;aACF;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kDAAkD;gBAC/D,OAAO,EAAE,KAAK;aACf;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;KAC5B;CACF,CAAC"}
1
+ {"version":3,"file":"fetch-structured.js","sourceRoot":"","sources":["../../src/tools/fetch-structured.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;;;;;GAKG;AACH,SAAS,qBAAqB,CAC5B,IAAY,EACZ,MAA8B;IAE9B,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,SAAS,GAAkC,EAAE,CAAC;IAEpD,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,KAAK,GAAkB,IAAI,CAAC;QAEhC,mCAAmC;QACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7F,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACzC,IAAI,EAAE;gBAAE,KAAK,GAAG,EAAE,CAAC;QACrB,CAAC;QAED,wCAAwC;aACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACpI,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC7C,IAAI,EAAE;gBAAE,KAAK,GAAG,EAAE,CAAC;QACrB,CAAC;QAED,6CAA6C;aACxC,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YAC5G,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,CAAC;gBAAE,KAAK,GAAG,CAAC,CAAC;QACnB,CAAC;QAED,2BAA2B;aACtB,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/F,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,IAAI;gBAAE,KAAK,GAAG,IAAI,CAAC;QACzB,CAAC;QAED,kCAAkC;aAC7B,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzE,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC9C,IAAI,QAAQ;gBAAE,KAAK,GAAG,QAAQ,CAAC;QACjC,CAAC;QAED,yCAAyC;aACpC,IAAI,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAClF,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,KAAK;gBAAE,KAAK,GAAG,KAAK,CAAC;QAC3B,CAAC;QAED,uDAAuD;aAClD,CAAC;YACJ,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE;gBACvC,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC;QAED,SAAS,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,KAAgC;IAEhC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAElD,kBAAkB;IAClB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9E,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,IAAI,CAAC;QACH,2DAA2D;QAC3D,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE;YACzC,UAAU;SACX,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QAE3C,0DAA0D;QAC1D,MAAM,aAAa,GAAG,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAE1D,uEAAuE;QACvE,0CAA0C;QAC1C,MAAM,aAAa,GAAkC,EAAE,CAAC;QACxD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9C,MAAM,iBAAiB,GAA2D,EAAE,CAAC;QACrF,IAAI,kBAAkB,GAAG,KAAK,CAAC;QAE/B,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,aAAa,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBAChC,SAAS;YACX,CAAC;YAED,MAAM,kBAAkB,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAChD,aAAa,CAAC,SAAS,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAEtD,8CAA8C;YAC9C,kBAAkB,CAAC,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC5D,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAC3B,CAAC;YACF,kBAAkB,CAAC,YAAY,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAC7D,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAC3B,CAAC;YACF,iBAAiB,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;YAE3E,IAAI,kBAAkB,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;gBACrD,kBAAkB,GAAG,IAAI,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,MAAM,MAAM,GAA+B;YACzC,GAAG;YACH,IAAI,EAAE,aAAa;YACnB,YAAY,EAAE;gBACZ,iBAAiB,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBAClD,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBACnD,eAAe,EAAE,iBAAiB;gBAClC,gBAAgB,EAAE,kBAAkB;aACrC;YACD,QAAQ,EAAE;gBACR,KAAK,EAAE,KAAK,IAAI,UAAU;gBAC1B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,uBAAuB,EAAE,IAAI,CAAC,MAAM;gBACpC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;qBACnD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;qBACvB,IAAI,CAAC,GAAG,CAAC;qBACT,MAAM;aACV;SACF,CAAC;QAEF,oCAAoC;QACpC,IAAI,mBAAmB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,+BAA+B;gBACtC,GAAG;gBACH,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC;gBACzC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aAC5B,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAErC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG;IAChD,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,0KAA0K;IACvL,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gDAAgD;aAC9D;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kEAAkE;gBAC/E,oBAAoB,EAAE;oBACpB,IAAI,EAAE,QAAQ;iBACf;aACF;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kDAAkD;gBAC/D,OAAO,EAAE,KAAK;aACf;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;KAC5B;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG7E;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CA2DjG;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;CAwBpC,CAAC"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG7E;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CA4DjG;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;CAwBpC,CAAC"}
@@ -31,9 +31,9 @@ export async function visusFetch(input) {
31
31
  }
32
32
  const { html, title } = renderResult.value;
33
33
  const rawContent = html || '';
34
- // Step 2: CRITICAL - Sanitize content (injection detection + PII redaction)
34
+ // Step 2: CRITICAL - Sanitize content (injection detection + PII redaction with allowlisting)
35
35
  // This step CANNOT be skipped or bypassed
36
- const sanitizationResult = sanitize(rawContent);
36
+ const sanitizationResult = sanitize(rawContent, url);
37
37
  // Step 3: Build output
38
38
  const output = {
39
39
  url,
@@ -41,6 +41,7 @@ export async function visusFetch(input) {
41
41
  sanitization: {
42
42
  patterns_detected: sanitizationResult.sanitization.patterns_detected,
43
43
  pii_types_redacted: sanitizationResult.sanitization.pii_types_redacted,
44
+ pii_allowlisted: sanitizationResult.sanitization.pii_allowlisted,
44
45
  content_modified: sanitizationResult.sanitization.content_modified
45
46
  },
46
47
  metadata: {
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAsB;IACrD,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,UAAU,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAE/D,kBAAkB;IAClB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,CAAC;QACH,2CAA2C;QAC3C,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE;YACzC,UAAU;YACV,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QAC3C,MAAM,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;QAE9B,8FAA8F;QAC9F,0CAA0C;QAC1C,MAAM,kBAAkB,GAAG,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAErD,uBAAuB;QACvB,MAAM,MAAM,GAAqB;YAC/B,GAAG;YACH,OAAO,EAAE,kBAAkB,CAAC,OAAO;YACnC,YAAY,EAAE;gBACZ,iBAAiB,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB;gBACpE,kBAAkB,EAAE,kBAAkB,CAAC,YAAY,CAAC,kBAAkB;gBACtE,eAAe,EAAE,kBAAkB,CAAC,YAAY,CAAC,eAAe;gBAChE,gBAAgB,EAAE,kBAAkB,CAAC,YAAY,CAAC,gBAAgB;aACnE;YACD,QAAQ,EAAE;gBACR,KAAK,EAAE,KAAK,IAAI,UAAU;gBAC1B,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACpC,uBAAuB,EAAE,kBAAkB,CAAC,QAAQ,CAAC,eAAe;gBACpE,wBAAwB,EAAE,kBAAkB,CAAC,QAAQ,CAAC,gBAAgB;aACvE;SACF,CAAC;QAEF,6CAA6C;QAC7C,IAAI,kBAAkB,CAAC,QAAQ,CAAC,oBAAoB,EAAE,CAAC;YACrD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,KAAK,EAAE,0BAA0B;gBACjC,GAAG;gBACH,QAAQ,EAAE,kBAAkB,CAAC,YAAY,CAAC,iBAAiB;gBAC3D,cAAc,EAAE,kBAAkB,CAAC,QAAQ,CAAC,cAAc;aAC3D,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAErC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,0MAA0M;IACvN,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gDAAgD;aAC9D;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;gBAC1B,WAAW,EAAE,iDAAiD;gBAC9D,OAAO,EAAE,UAAU;aACpB;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kDAAkD;gBAC/D,OAAO,EAAE,KAAK;aACf;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,CAAC;KAClB;CACF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -18,6 +18,11 @@ export interface VisusFetchOutput {
18
18
  sanitization: {
19
19
  patterns_detected: string[];
20
20
  pii_types_redacted: string[];
21
+ pii_allowlisted: Array<{
22
+ type: string;
23
+ value: string;
24
+ reason: string;
25
+ }>;
21
26
  content_modified: boolean;
22
27
  };
23
28
  metadata: {
@@ -44,6 +49,11 @@ export interface VisusFetchStructuredOutput {
44
49
  sanitization: {
45
50
  patterns_detected: string[];
46
51
  pii_types_redacted: string[];
52
+ pii_allowlisted: Array<{
53
+ type: string;
54
+ value: string;
55
+ reason: string;
56
+ }>;
47
57
  content_modified: boolean;
48
58
  };
49
59
  metadata: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE;QACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,uBAAuB,EAAE,MAAM,CAAC;QAChC,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACpC,YAAY,EAAE;QACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,uBAAuB,EAAE,MAAM,CAAC;QAChC,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE5B;;GAEG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAEhD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAEjD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE;QACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,eAAe,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACxE,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,uBAAuB,EAAE,MAAM,CAAC;QAChC,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACpC,YAAY,EAAE;QACZ,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;QAC7B,eAAe,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACxE,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,uBAAuB,EAAE,MAAM,CAAC;QAChC,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE5B;;GAEG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAEhD;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAEjD"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAsFH;;GAEG;AACH,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwFH;;GAEG;AACH,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "visus-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Secure web access for Claude — sanitizes all web content before it reaches your LLM",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -16,6 +16,7 @@ export interface SanitizationResult {
16
16
  sanitization: {
17
17
  patterns_detected: string[];
18
18
  pii_types_redacted: string[];
19
+ pii_allowlisted: Array<{ type: string; value: string; reason: string }>;
19
20
  content_modified: boolean;
20
21
  };
21
22
  metadata: {
@@ -37,20 +38,21 @@ export interface SanitizationResult {
37
38
  *
38
39
  * Pipeline:
39
40
  * 1. Injection detection and neutralization (43 patterns)
40
- * 2. PII redaction (email, phone, SSN, CC, IP)
41
+ * 2. PII redaction (email, phone, SSN, CC, IP) with allowlisting
41
42
  * 3. Metadata collection and logging
42
43
  *
43
44
  * @param content Raw content from web page
45
+ * @param sourceUrl Optional source URL for domain-scoped PII allowlisting
44
46
  * @returns Sanitized content with detection metadata
45
47
  */
46
- export function sanitize(content: string): SanitizationResult {
48
+ export function sanitize(content: string, sourceUrl?: string): SanitizationResult {
47
49
  const originalLength = content.length;
48
50
 
49
51
  // Step 1: Detect and neutralize injection patterns
50
52
  const injectionResult = detectAndNeutralize(content);
51
53
 
52
- // Step 2: Redact PII from the already-sanitized content
53
- const piiResult = redactPII(injectionResult.content);
54
+ // Step 2: Redact PII from the already-sanitized content (with allowlisting)
55
+ const piiResult = redactPII(injectionResult.content, sourceUrl);
54
56
 
55
57
  // Step 3: Combine results
56
58
  const finalContent = piiResult.content;
@@ -63,6 +65,7 @@ export function sanitize(content: string): SanitizationResult {
63
65
  logSanitization({
64
66
  patterns_detected: injectionResult.patterns_detected,
65
67
  pii_types_redacted: piiResult.pii_types_redacted,
68
+ pii_allowlisted: piiResult.pii_allowlisted,
66
69
  severity_score: severityScore,
67
70
  has_critical_threats: criticalThreats,
68
71
  content_modified: contentModified
@@ -73,6 +76,7 @@ export function sanitize(content: string): SanitizationResult {
73
76
  sanitization: {
74
77
  patterns_detected: injectionResult.patterns_detected,
75
78
  pii_types_redacted: piiResult.pii_types_redacted,
79
+ pii_allowlisted: piiResult.pii_allowlisted,
76
80
  content_modified: contentModified
77
81
  },
78
82
  metadata: {
@@ -92,6 +96,7 @@ export function sanitize(content: string): SanitizationResult {
92
96
  function logSanitization(event: {
93
97
  patterns_detected: string[];
94
98
  pii_types_redacted: string[];
99
+ pii_allowlisted: Array<{ type: string; value: string; reason: string }>;
95
100
  severity_score: number;
96
101
  has_critical_threats: boolean;
97
102
  content_modified: boolean;
@@ -103,7 +108,7 @@ function logSanitization(event: {
103
108
  };
104
109
 
105
110
  // Only log if there were detections (reduce noise)
106
- if (event.content_modified) {
111
+ if (event.content_modified || event.pii_allowlisted.length > 0) {
107
112
  console.error(JSON.stringify(logEntry));
108
113
  }
109
114
  }
@@ -0,0 +1,273 @@
1
+ /**
2
+ * PII Allowlist Configuration
3
+ *
4
+ * Defines trusted phone numbers that should NOT be redacted from web content.
5
+ * Primarily for verified health authority and government emergency numbers.
6
+ *
7
+ * CRITICAL: Only add numbers that are:
8
+ * 1. Publicly published institutional/government numbers
9
+ * 2. Verified health/safety authorities
10
+ * 3. Not personal contact information
11
+ */
12
+
13
+ export interface TrustedPhoneNumber {
14
+ /** Display name for logging */
15
+ name: string;
16
+ /** Normalized phone number variants (all formats this number might appear in) */
17
+ numbers: string[];
18
+ /** Optional: domains where this number is trusted (empty = trusted everywhere) */
19
+ trustedDomains?: string[];
20
+ /** Category for audit logging */
21
+ category: 'emergency' | 'health_authority' | 'government' | 'helpline';
22
+ }
23
+
24
+ export interface PIIAllowlistConfig {
25
+ /** When true, trusted numbers only preserved if source domain matches trustedDomains */
26
+ strictDomainMode: boolean;
27
+ /** List of verified trusted phone numbers */
28
+ trustedPhoneNumbers: TrustedPhoneNumber[];
29
+ }
30
+
31
+ /**
32
+ * Normalize a phone number to digits-only format for comparison
33
+ */
34
+ export function normalizePhoneNumber(phone: string): string {
35
+ return phone.replace(/\D/g, '');
36
+ }
37
+
38
+ /**
39
+ * Extract domain from URL (returns hostname without www.)
40
+ */
41
+ export function extractDomain(url: string): string {
42
+ try {
43
+ const parsedUrl = new URL(url);
44
+ return parsedUrl.hostname.replace(/^www\./, '').toLowerCase();
45
+ } catch {
46
+ return '';
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Built-in allowlist of verified health authority and emergency numbers
52
+ */
53
+ export const DEFAULT_ALLOWLIST: PIIAllowlistConfig = {
54
+ strictDomainMode: false, // Default: trust globally, not domain-scoped
55
+
56
+ trustedPhoneNumbers: [
57
+ // Emergency Services
58
+ {
59
+ name: 'Emergency Services (911)',
60
+ numbers: ['911'],
61
+ category: 'emergency'
62
+ },
63
+
64
+ // Poison Control
65
+ {
66
+ name: 'Poison Control Center',
67
+ numbers: [
68
+ '18002221222',
69
+ '8002221222',
70
+ '1-800-222-1222',
71
+ '800-222-1222'
72
+ ],
73
+ trustedDomains: [
74
+ 'medlineplus.gov',
75
+ 'cdc.gov',
76
+ 'fda.gov',
77
+ 'aapcc.org',
78
+ 'poison.org',
79
+ 'nih.gov',
80
+ 'nlm.nih.gov'
81
+ ],
82
+ category: 'health_authority'
83
+ },
84
+
85
+ // FDA MedWatch (adverse event reporting)
86
+ {
87
+ name: 'FDA MedWatch',
88
+ numbers: [
89
+ '18003321088',
90
+ '8003321088',
91
+ '1-800-332-1088',
92
+ '800-332-1088'
93
+ ],
94
+ trustedDomains: [
95
+ 'fda.gov',
96
+ 'medlineplus.gov',
97
+ 'cdc.gov',
98
+ 'nih.gov'
99
+ ],
100
+ category: 'health_authority'
101
+ },
102
+
103
+ // CDC INFO
104
+ {
105
+ name: 'CDC INFO',
106
+ numbers: [
107
+ '18002324636',
108
+ '8002324636',
109
+ '1-800-232-4636',
110
+ '800-232-4636'
111
+ ],
112
+ trustedDomains: [
113
+ 'cdc.gov',
114
+ 'medlineplus.gov',
115
+ 'nih.gov'
116
+ ],
117
+ category: 'health_authority'
118
+ },
119
+
120
+ // SAMHSA National Helpline (substance abuse/mental health)
121
+ {
122
+ name: 'SAMHSA National Helpline',
123
+ numbers: [
124
+ '18006624357',
125
+ '8006624357',
126
+ '1-800-662-4357',
127
+ '800-662-4357'
128
+ ],
129
+ trustedDomains: [
130
+ 'samhsa.gov',
131
+ 'medlineplus.gov',
132
+ 'cdc.gov',
133
+ 'nih.gov'
134
+ ],
135
+ category: 'helpline'
136
+ },
137
+
138
+ // National Suicide Prevention Lifeline
139
+ {
140
+ name: 'National Suicide Prevention Lifeline',
141
+ numbers: [
142
+ '18002738255',
143
+ '8002738255',
144
+ '1-800-273-8255',
145
+ '800-273-8255',
146
+ '988' // New 3-digit code
147
+ ],
148
+ trustedDomains: [
149
+ 'suicidepreventionlifeline.org',
150
+ 'samhsa.gov',
151
+ 'medlineplus.gov',
152
+ 'cdc.gov',
153
+ 'nih.gov'
154
+ ],
155
+ category: 'helpline'
156
+ },
157
+
158
+ // National Domestic Violence Hotline
159
+ {
160
+ name: 'National Domestic Violence Hotline',
161
+ numbers: [
162
+ '18007997233',
163
+ '8007997233',
164
+ '1-800-799-7233',
165
+ '800-799-7233'
166
+ ],
167
+ trustedDomains: [
168
+ 'thehotline.org',
169
+ 'cdc.gov',
170
+ 'medlineplus.gov',
171
+ 'nih.gov'
172
+ ],
173
+ category: 'helpline'
174
+ },
175
+
176
+ // Medicare
177
+ {
178
+ name: 'Medicare',
179
+ numbers: [
180
+ '18006331795',
181
+ '8006331795',
182
+ '1-800-633-1795',
183
+ '800-633-1795'
184
+ ],
185
+ trustedDomains: [
186
+ 'medicare.gov',
187
+ 'cms.gov',
188
+ 'medlineplus.gov',
189
+ 'nih.gov'
190
+ ],
191
+ category: 'government'
192
+ },
193
+
194
+ // Veterans Crisis Line
195
+ {
196
+ name: 'Veterans Crisis Line',
197
+ numbers: [
198
+ '18002738255',
199
+ '8002738255',
200
+ '1-800-273-8255',
201
+ '800-273-8255'
202
+ ],
203
+ trustedDomains: [
204
+ 'va.gov',
205
+ 'veteranscrisisline.net',
206
+ 'medlineplus.gov',
207
+ 'nih.gov'
208
+ ],
209
+ category: 'helpline'
210
+ }
211
+ ]
212
+ };
213
+
214
+ /**
215
+ * Check if a phone number should be allowlisted (not redacted)
216
+ *
217
+ * @param phoneNumber The phone number to check (in any format)
218
+ * @param sourceUrl Optional source URL for domain-scoped allowlisting
219
+ * @param config Optional custom config (defaults to DEFAULT_ALLOWLIST)
220
+ * @returns The trusted number entry if allowlisted, null otherwise
221
+ */
222
+ export function isAllowlistedPhoneNumber(
223
+ phoneNumber: string,
224
+ sourceUrl?: string,
225
+ config: PIIAllowlistConfig = DEFAULT_ALLOWLIST
226
+ ): TrustedPhoneNumber | null {
227
+ const normalized = normalizePhoneNumber(phoneNumber);
228
+ const sourceDomain = sourceUrl ? extractDomain(sourceUrl) : '';
229
+
230
+ for (const trustedEntry of config.trustedPhoneNumbers) {
231
+ // Check if any variant of this trusted number matches
232
+ const matchesNumber = trustedEntry.numbers.some(variant => {
233
+ const normalizedVariant = normalizePhoneNumber(variant);
234
+ return normalized === normalizedVariant;
235
+ });
236
+
237
+ if (!matchesNumber) {
238
+ continue; // Number doesn't match, check next entry
239
+ }
240
+
241
+ // Number matches - now check domain restrictions
242
+ const hasDomainRestrictions = trustedEntry.trustedDomains && trustedEntry.trustedDomains.length > 0;
243
+
244
+ if (!hasDomainRestrictions) {
245
+ // No domain restrictions - trust globally
246
+ return trustedEntry;
247
+ }
248
+
249
+ // Has domain restrictions
250
+ if (config.strictDomainMode && !sourceUrl) {
251
+ // Strict mode requires domain match, but no URL provided
252
+ continue;
253
+ }
254
+
255
+ if (sourceUrl && trustedEntry.trustedDomains) {
256
+ // Check if source domain matches any trusted domain
257
+ const isDomainTrusted = trustedEntry.trustedDomains.some(trustedDomain => {
258
+ return sourceDomain.endsWith(trustedDomain);
259
+ });
260
+
261
+ if (isDomainTrusted) {
262
+ return trustedEntry;
263
+ }
264
+ }
265
+
266
+ // In non-strict mode, trust the number even if domain doesn't match
267
+ if (!config.strictDomainMode) {
268
+ return trustedEntry;
269
+ }
270
+ }
271
+
272
+ return null; // No match found
273
+ }
@@ -5,14 +5,23 @@
5
5
  * to prevent leakage of sensitive data to the LLM.
6
6
  *
7
7
  * Redacts: emails, phone numbers, SSNs, credit cards, IP addresses
8
+ * Supports allowlisting of trusted institutional phone numbers (e.g., Poison Control)
8
9
  */
9
10
 
11
+ import {
12
+ isAllowlistedPhoneNumber,
13
+ type PIIAllowlistConfig,
14
+ DEFAULT_ALLOWLIST
15
+ } from './pii-allowlist.js';
16
+
10
17
  export interface PIIRedactionResult {
11
18
  content: string;
12
19
  pii_types_redacted: string[];
20
+ pii_allowlisted: Array<{ type: string; value: string; reason: string }>;
13
21
  content_modified: boolean;
14
22
  metadata: {
15
23
  redaction_counts: Record<string, number>;
24
+ allowlist_counts: Record<string, number>;
16
25
  };
17
26
  }
18
27
 
@@ -151,10 +160,20 @@ function luhnCheck(digits: string): boolean {
151
160
 
152
161
  /**
153
162
  * Redact PII from content
163
+ *
164
+ * @param content Content to redact PII from
165
+ * @param sourceUrl Optional source URL for domain-scoped allowlisting
166
+ * @param allowlistConfig Optional custom allowlist config
154
167
  */
155
- export function redactPII(content: string): PIIRedactionResult {
168
+ export function redactPII(
169
+ content: string,
170
+ sourceUrl?: string,
171
+ allowlistConfig: PIIAllowlistConfig = DEFAULT_ALLOWLIST
172
+ ): PIIRedactionResult {
156
173
  const piiTypesRedacted = new Set<string>();
157
174
  const redactionCounts: Record<string, number> = {};
175
+ const allowlistCounts: Record<string, number> = {};
176
+ const piiAllowlisted: Array<{ type: string; value: string; reason: string }> = [];
158
177
  let sanitizedContent = content;
159
178
 
160
179
  for (const pattern of PII_PATTERNS) {
@@ -168,6 +187,26 @@ export function redactPII(content: string): PIIRedactionResult {
168
187
  continue;
169
188
  }
170
189
 
190
+ // Check allowlist for phone numbers
191
+ if (pattern.type === 'PHONE') {
192
+ const allowlistedEntry = isAllowlistedPhoneNumber(
193
+ matchedText,
194
+ sourceUrl,
195
+ allowlistConfig
196
+ );
197
+
198
+ if (allowlistedEntry) {
199
+ // This is a trusted number - DO NOT redact
200
+ piiAllowlisted.push({
201
+ type: pattern.type,
202
+ value: matchedText,
203
+ reason: `Trusted ${allowlistedEntry.category}: ${allowlistedEntry.name}`
204
+ });
205
+ allowlistCounts[pattern.name] = (allowlistCounts[pattern.name] || 0) + 1;
206
+ continue; // Skip redaction
207
+ }
208
+ }
209
+
171
210
  // Redact the PII
172
211
  sanitizedContent = sanitizedContent.replace(
173
212
  matchedText,
@@ -182,9 +221,11 @@ export function redactPII(content: string): PIIRedactionResult {
182
221
  return {
183
222
  content: sanitizedContent,
184
223
  pii_types_redacted: Array.from(piiTypesRedacted),
224
+ pii_allowlisted: piiAllowlisted,
185
225
  content_modified: sanitizedContent !== content,
186
226
  metadata: {
187
- redaction_counts: redactionCounts
227
+ redaction_counts: redactionCounts,
228
+ allowlist_counts: allowlistCounts
188
229
  }
189
230
  };
190
231
  }
@@ -120,11 +120,12 @@ export async function visusFetchStructured(
120
120
  // Step 2: Extract structured data from HTML using cheerio
121
121
  const extractedData = extractStructuredData(html, schema);
122
122
 
123
- // Step 3: CRITICAL - Sanitize each extracted field
123
+ // Step 3: CRITICAL - Sanitize each extracted field (with allowlisting)
124
124
  // This step CANNOT be skipped or bypassed
125
125
  const sanitizedData: Record<string, string | null> = {};
126
126
  const allPatternsDetected = new Set<string>();
127
127
  const allPIITypesRedacted = new Set<string>();
128
+ const allPIIAllowlisted: Array<{ type: string; value: string; reason: string }> = [];
128
129
  let anyContentModified = false;
129
130
 
130
131
  for (const [fieldName, value] of Object.entries(extractedData)) {
@@ -133,7 +134,7 @@ export async function visusFetchStructured(
133
134
  continue;
134
135
  }
135
136
 
136
- const sanitizationResult = sanitize(value);
137
+ const sanitizationResult = sanitize(value, url);
137
138
  sanitizedData[fieldName] = sanitizationResult.content;
138
139
 
139
140
  // Collect all patterns detected across fields
@@ -143,6 +144,7 @@ export async function visusFetchStructured(
143
144
  sanitizationResult.sanitization.pii_types_redacted.forEach(p =>
144
145
  allPIITypesRedacted.add(p)
145
146
  );
147
+ allPIIAllowlisted.push(...sanitizationResult.sanitization.pii_allowlisted);
146
148
 
147
149
  if (sanitizationResult.sanitization.content_modified) {
148
150
  anyContentModified = true;
@@ -156,6 +158,7 @@ export async function visusFetchStructured(
156
158
  sanitization: {
157
159
  patterns_detected: Array.from(allPatternsDetected),
158
160
  pii_types_redacted: Array.from(allPIITypesRedacted),
161
+ pii_allowlisted: allPIIAllowlisted,
159
162
  content_modified: anyContentModified
160
163
  },
161
164
  metadata: {
@@ -39,9 +39,9 @@ export async function visusFetch(input: VisusFetchInput): Promise<Result<VisusFe
39
39
  const { html, title } = renderResult.value;
40
40
  const rawContent = html || '';
41
41
 
42
- // Step 2: CRITICAL - Sanitize content (injection detection + PII redaction)
42
+ // Step 2: CRITICAL - Sanitize content (injection detection + PII redaction with allowlisting)
43
43
  // This step CANNOT be skipped or bypassed
44
- const sanitizationResult = sanitize(rawContent);
44
+ const sanitizationResult = sanitize(rawContent, url);
45
45
 
46
46
  // Step 3: Build output
47
47
  const output: VisusFetchOutput = {
@@ -50,6 +50,7 @@ export async function visusFetch(input: VisusFetchInput): Promise<Result<VisusFe
50
50
  sanitization: {
51
51
  patterns_detected: sanitizationResult.sanitization.patterns_detected,
52
52
  pii_types_redacted: sanitizationResult.sanitization.pii_types_redacted,
53
+ pii_allowlisted: sanitizationResult.sanitization.pii_allowlisted,
53
54
  content_modified: sanitizationResult.sanitization.content_modified
54
55
  },
55
56
  metadata: {
package/src/types.ts CHANGED
@@ -20,6 +20,7 @@ export interface VisusFetchOutput {
20
20
  sanitization: {
21
21
  patterns_detected: string[];
22
22
  pii_types_redacted: string[];
23
+ pii_allowlisted: Array<{ type: string; value: string; reason: string }>;
23
24
  content_modified: boolean;
24
25
  };
25
26
  metadata: {
@@ -48,6 +49,7 @@ export interface VisusFetchStructuredOutput {
48
49
  sanitization: {
49
50
  patterns_detected: string[];
50
51
  pii_types_redacted: string[];
52
+ pii_allowlisted: Array<{ type: string; value: string; reason: string }>;
51
53
  content_modified: boolean;
52
54
  };
53
55
  metadata: {