@nodatachat/mcp 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -126,6 +126,38 @@ The one-sentence version: **encrypt locally, send, revoke later, prove what happ
126
126
 
127
127
  ---
128
128
 
129
+ ## Terms, agents and the status line
130
+
131
+ - **Terms in the terminal.** The data tools wait until the current terms are accepted:
132
+ `nodata_terms` shows them (section 7 covers AI agents: NoData answers for what passes through its
133
+ tools, not for programs an agent writes or files it reaches on its own), and `confirm: true`
134
+ accepts. The acceptance is kept in `~/.nodata/consent.json` and recorded at NoData against your
135
+ organisation, key and agent — and copied to your organisation's proof vault. Operational
136
+ identification only: organisation, agent, version, time, hash. No content.
137
+ - **Every agent has a name and a colour** — `claude-code@your-laptop`, 🟣 — in every tool result, so
138
+ several agents stay apart.
139
+ - **The status line** (installed with the read gate): `● NoData` at the bottom of Claude Code —
140
+ green = guarded, yellow = gate off, red = terms not accepted. No segment = not guarded. A status
141
+ line you already had keeps running beside it, and comes back on `uninstall-gate`.
142
+
143
+ ## The read gate — a scan before the assistant reads
144
+
145
+ The MCP tools keep values out of the model only when the model uses them; Claude Code can also
146
+ open a file with its own Read, Grep or Bash. One command puts NoData's scanner in front of those:
147
+
148
+ ```bash
149
+ npx @nodatachat/mcp install-gate # ask first (default)
150
+ npx @nodatachat/mcp install-gate --block # refuse instead
151
+ npx @nodatachat/mcp uninstall-gate
152
+ ```
153
+
154
+ Before Claude Code reads a data file (csv, xlsx, docx, pdf, .env …), the gate scans it on this
155
+ machine with the same detectors as `nodata_scan_folder`. Findings → you are asked (or the read is
156
+ refused), with the counts and the safer step: `nodata_redact` for a clean copy, `nodata_protect`
157
+ to lock it. Clean copies, sealed files and source code pass without a question. The gate catches
158
+ a Read, a Grep on a file, and a Bash command that names the file; a program that builds the path
159
+ at run time is not caught — `nodata_protect` (ciphertext at rest) is what makes a file unreadable.
160
+
129
161
  ## Available tools
130
162
 
131
163
  **Agent mode** (`--grant-token`):
package/dist/gate.js ADDED
@@ -0,0 +1,18 @@
1
+ /*! @nodatachat/mcp 1.3.2 | Copyright 2026 Capsule Ltd. | FSL-1.1-ALv2 | see LICENSE.md */
2
+ import{appendFileSync as Ye,copyFileSync as rn,existsSync as Qe,mkdirSync as et,readFileSync as tt,statSync as fe,writeFileSync as sn}from"node:fs";import{homedir as ue}from"node:os";import{basename as nt,extname as pe,isAbsolute as it,join as de,resolve as rt}from"node:path";var P=[{id:"aws-access-key",name:"AWS Access Key",pattern:/(?:^|[^A-Z0-9])AKIA[A-Z2-7]{16}(?:[^A-Z2-7]|$)/,severity:"critical"},{id:"aws-secret-key",name:"AWS Secret Key",pattern:/(?:aws_secret_access_key|aws_secret_key|secret_access_key)\s*[=:]\s*['"]?[A-Za-z0-9/+=]{40}['"]?/,severity:"critical"},{id:"gcp-api-key",name:"GCP API Key",pattern:/AIza[0-9A-Za-z_-]{35}/,severity:"critical"},{id:"gcp-service-account",name:"GCP Service Account",pattern:/"type"\s*:\s*"service_account"/,severity:"critical"},{id:"github-token",name:"GitHub Token",pattern:/gh[pousr]_[0-9a-zA-Z]{36,}/,severity:"critical"},{id:"github-fine-grained",name:"GitHub Fine-Grained Token",pattern:/github_pat_[0-9a-zA-Z_]{22,}/,severity:"critical"},{id:"gitlab-token",name:"GitLab Token",pattern:/glpat-[0-9a-zA-Z_-]{20,}/,severity:"critical"},{id:"stripe-secret",name:"Stripe Secret Key",pattern:/sk_live_[0-9a-zA-Z]{24,}/,severity:"critical"},{id:"stripe-restricted",name:"Stripe Restricted Key",pattern:/rk_live_[0-9a-zA-Z]{24,}/,severity:"critical"},{id:"slack-token",name:"Slack Token",pattern:/xox[baprs]-[0-9a-zA-Z-]{10,}/,severity:"high"},{id:"slack-webhook",name:"Slack Webhook",pattern:/hooks\.slack\.com\/services\/T[0-9A-Z]{8,}\/B[0-9A-Z]{8,}\/[0-9a-zA-Z]{24}/,severity:"high"},{id:"twilio-api-key",name:"Twilio API Key",pattern:/SK[0-9a-fA-F]{32}/,severity:"high"},{id:"sendgrid-api-key",name:"SendGrid API Key",pattern:/SG\.[0-9a-zA-Z_-]{22}\.[0-9a-zA-Z_-]{43}/,severity:"critical"},{id:"postgres-uri",name:"PostgreSQL Connection String",pattern:/postgres(?:ql)?:\/\/[^\s'"]{10,}/,severity:"critical"},{id:"mongodb-uri",name:"MongoDB Connection String",pattern:/mongodb(?:\+srv)?:\/\/[^\s'"]{10,}/,severity:"critical"},{id:"redis-uri",name:"Redis Connection String",pattern:/redis(?:s)?:\/\/[^\s'"]{10,}/,severity:"high"},{id:"openai-key",name:"OpenAI API Key",pattern:/sk-[0-9a-zA-Z]{20,}T3BlbkFJ[0-9a-zA-Z]{20,}/,severity:"critical"},{id:"anthropic-key",name:"Anthropic API Key",pattern:/sk-ant-[0-9a-zA-Z_-]{40,}/,severity:"critical"},{id:"firebase-key",name:"Firebase API Key",pattern:/AIza[0-9A-Za-z_-]{35}/,severity:"high"},{id:"supabase-key",name:"Supabase Service Key",pattern:/eyJ[0-9a-zA-Z_-]{100,}/,severity:"critical"},{id:"private-key",name:"Private Key",pattern:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/,severity:"critical"},{id:"jwt-secret",name:"JWT/Generic Secret",pattern:/(?:jwt_secret|JWT_SECRET|secret_key|SECRET_KEY|api_secret|API_SECRET)\s*[=:]\s*['"][^'"]{8,}['"]/,severity:"high"},{id:"password-in-code",name:"Password in Code",pattern:/(?:password|passwd|pwd)\s*[=:]\s*['"][^'"]{8,}['"]/,severity:"high"},{id:"bearer-token",name:"Bearer Token in Code",pattern:/['"]Bearer\s+[0-9a-zA-Z._-]{20,}['"]/,severity:"high"}];var ye=[{pattern:/^(full_?name|first_?name|last_?name|spouse_?name|beneficiary_?name)$/i,type:"name",label:"Person name"},{pattern:/^(email|e_?mail|email_?address)$/i,type:"email",label:"Email address"},{pattern:/^(phone|mobile|telephone|phone_?number|cell_?phone)$/i,type:"phone",label:"Phone number"},{pattern:/^(id_?number|identity|ssn|social_?security|national_?id|teudat_?zehut)$/i,type:"id",label:"ID number"},{pattern:/^(address|street_?address|home_?address)$/i,type:"address",label:"Address"},{pattern:/^(date_?of_?birth|dob|birth_?date|birthday)$/i,type:"dob",label:"Date of birth"},{pattern:/^(bank_?account|iban|account_?number|bank_?details|routing_?number)$/i,type:"financial",label:"Bank account"},{pattern:/^(credit_?card|card_?number|cvv|cc_?number)$/i,type:"financial",label:"Credit card"},{pattern:/^(salary|income|commission|premium|compensation)$/i,type:"financial",label:"Salary / income"},{pattern:/^(medical_?info|health_?conditions|diagnosis|medication|prescription)$/i,type:"medical",label:"Medical"},{pattern:/^(passport|passport_?number|passport_?id)$/i,type:"id",label:"Passport"},{pattern:/^(driver_?license|drivers_?license|dl_?number)$/i,type:"id",label:"Driver license"},{pattern:/^(tax_?id|tin|vat_?number|ein)$/i,type:"financial",label:"Tax ID"},{pattern:/^(insurance_?number|policy_?number|member_?id)$/i,type:"id",label:"Insurance/Policy"},{pattern:/^(biometric|fingerprint|face_?id|retina)$/i,type:"biometric",label:"Biometric"},{pattern:/^(latitude|longitude|lat|lng|geo_?location|coordinates)$/i,type:"location",label:"Geolocation"}],_e=[{pattern:/^(?:שם|שם_מלא|שם פרטי|שם_פרטי|שם משפחה|שם_משפחה|שם הלקוח|שם בן זוג|שם המבוטח|שם המוטב|שם הילד|שם הקטין)$/i,type:"name",label:"\u05E9\u05DD \u05D0\u05D3\u05DD"},{pattern:/^(?:ת"ז|ת\.ז|ת ז|תז|תעודת זהות|תעודת_זהות|מספר זהות|מס' זהות|teudat_zehut|tz|israeli_id|il_id)$/i,type:"id",label:"\u05EA\u05E2\u05D5\u05D3\u05EA \u05D6\u05D4\u05D5\u05EA"},{pattern:/^(?:דרכון|מספר דרכון|רישיון נהיגה|רישיון_נהיגה|רשיון נהיגה)$/i,type:"id",label:"\u05D3\u05E8\u05DB\u05D5\u05DF/\u05E8\u05D9\u05E9\u05D9\u05D5\u05DF"},{pattern:/^(?:מייל|דוא"ל|דוא_ל|דואר אלקטרוני|אימייל|כתובת מייל)$/i,type:"email",label:"\u05D3\u05D5\u05D0\u05E8 \u05D0\u05DC\u05E7\u05D8\u05E8\u05D5\u05E0\u05D9"},{pattern:/^(?:טלפון|טל'|נייד|פלאפון|סלולרי|מספר טלפון|טלפון נייד)$/i,type:"phone",label:"\u05DE\u05E1\u05E4\u05E8 \u05D8\u05DC\u05E4\u05D5\u05DF"},{pattern:/^(?:כתובת|כתובת מגורים|רחוב|מס בית|עיר|ישוב|יישוב|מיקוד|כתובת מלאה|מען)$/i,type:"address",label:"\u05DB\u05EA\u05D5\u05D1\u05EA"},{pattern:/^(?:תאריך לידה|ת לידה|תאריך הולדת|יום הולדת|גיל)$/i,type:"dob",label:"\u05EA\u05D0\u05E8\u05D9\u05DA \u05DC\u05D9\u05D3\u05D4"},{pattern:/^(?:חשבון בנק|מספר חשבון|מס חשבון|סניף|iban|iban_il)$/i,type:"financial",label:"\u05D7\u05E9\u05D1\u05D5\u05DF \u05D1\u05E0\u05E7"},{pattern:/^(?:כרטיס אשראי|מספר אשראי|cvv|אשראי)$/i,type:"financial",label:"\u05DB\u05E8\u05D8\u05D9\u05E1 \u05D0\u05E9\u05E8\u05D0\u05D9"},{pattern:/^(?:שכר|משכורת|הכנסה|פרמיה|שכר ברוטו|שכר נטו|תגמול|בונוס|פיצוי)$/i,type:"financial",label:"\u05E9\u05DB\u05E8/\u05D4\u05DB\u05E0\u05E1\u05D4"},{pattern:/^(?:אבחון|אבחנה|מחלה|תרופה|מרשם|בדיקה רפואית|מצב רפואי|חיסון|רגישות|אלרגיה|סוג דם)$/i,type:"medical",label:"\u05DE\u05D9\u05D3\u05E2 \u05E8\u05E4\u05D5\u05D0\u05D9"},{pattern:/^(?:מספר פוליסה|מס פוליסה|פוליסה|מספר חבר|מספר ביטוח)$/i,type:"id",label:"\u05E4\u05D5\u05DC\u05D9\u05E1\u05D4/\u05D7\u05D1\u05E8\u05D5\u05EA"},{pattern:/^(?:שם הילד|תעודת זהות של ילד|ילדים|קטין|מספר ילדים|תעודת לידה)$/i,type:"minor_data",label:"\u05DE\u05D9\u05D3\u05E2 \u05E2\u05DC \u05E7\u05D8\u05D9\u05DF"},{pattern:/^(?:דת|לאום|מין|נטייה מינית|השקפה פוליטית|מצב משפחתי|עדה|מוצא)$/i,type:"sensitive_personal",label:"\u05DE\u05D9\u05D3\u05E2 \u05D0\u05D9\u05E9\u05D9 \u05E8\u05D2\u05D9\u05E9"},{pattern:/^(?:מספר רכב|מס רכב|לוחית רישוי|מספר רישוי)$/i,type:"tracking",label:"\u05DE\u05E1\u05E4\u05E8 \u05E8\u05DB\u05D1"}],be=/^(id|uuid|created_?at|updated_?at|deleted_?at|status|type|category|description|title|slug|url|path|key|value|enabled|active|public|version|metadata|config|settings|data|content|note|comment|label|color|icon)$/i;function S(t){if(!t)return null;let e=t.trim();if(be.test(e)||/^name$/i.test(e))return null;let n=e.replace(/[\s-]+/g,"_");for(let i of[..._e,...ye])if(i.pattern.test(e)||i.pattern.test(n))return{type:i.type,label:i.label};return null}function W(t){let e=String(t??"").replace(/\D/g,"");if(e.length===0||e.length>9)return!1;let n=e.padStart(9,"0"),i=0;for(let r=0;r<9;r++){let o=parseInt(n[r]??"0",10)*(r%2+1);o>9&&(o-=9),i+=o}return i%10===0&&parseInt(n,10)>0}function xe(t){let e=String(t??"").replace(/\D/g,"");if(e.length<12||e.length>19)return!1;let n=0,i=!1;for(let r=e.length-1;r>=0;r-=1){let o=parseInt(e[r]??"0",10);i&&(o*=2,o>9&&(o-=9)),n+=o,i=!i}return n%10===0}function ve(t){let e=String(t??"").replace(/\s/g,"").toUpperCase();if(!/^[A-Z]{2}\d{2}[A-Z0-9]{10,30}$/.test(e))return!1;let n=e.slice(4)+e.slice(0,4),i=0;for(let r of n){let o=r>="A"&&r<="Z"?String(r.charCodeAt(0)-55):r;for(let s of o)i=(i*10+Number(s))%97}return i===1}var L="(?<!\\d)(?<!\\d[.,])",R="(?!\\d)(?![.,]\\d)",K=[{subkind:"israeli_id",severity:"high",pattern:new RegExp(`${L}\\d{9}${R}`,"g"),validate:W,hint:"Israeli national ID (check digit verified) in plaintext. Encrypt the column or mask it at rest."},{subkind:"credit_card",severity:"critical",pattern:new RegExp(`${L}[2-6][ -]?(?:\\d[ -]?){11,17}\\d${R}`,"g"),validate:xe,hint:"Payment card number (Luhn verified) in plaintext. This is PCI scope."},{subkind:"iban",severity:"high",pattern:/\b[A-Z]{2}\d{2}(?: ?[A-Z0-9]{4}){2,7}(?: ?[A-Z0-9]{1,4})?\b/g,validate:ve,hint:"Bank account in IBAN form (mod-97 verified) in plaintext."},{subkind:"israeli_phone",severity:"medium",pattern:new RegExp(`${L}(?:\\+972[- ]?|0)(?:[57]\\d|[2-489])[- ]?\\d{3}[- ]?\\d{4}${R}`,"g"),validate:t=>{let e=t.replace(/\D/g,"").replace(/^972/,"0");return/^0[57]\d{8}$/.test(e)?!0:/^0[2-489]\d{7}$/.test(e)&&(/[- ]/.test(t)||t.startsWith("+972"))},hint:"Israeli phone number in plaintext."}];function I(t,e){let n=[],i="",r=!1;for(let o=0;o<t.length;o++){let s=t[o];r?s==='"'&&t[o+1]==='"'?(i+='"',o++):s==='"'?r=!1:i+=s:s==='"'?r=!0:s===e?(n.push(i),i=""):i+=s}return n.push(i),n}import{inflateRawSync as Le}from"node:zlib";import{inflateSync as Se}from"node:zlib";var F=new Set([".pdf"]),X=8*1024*1024;function ke(t){let e=t.toString("latin1"),n=new Map,i=/(\d+)\s+(\d+)\s+obj\b/g,r;for(;(r=i.exec(e))!==null;){let o=Number(r[1]),s=i.lastIndex,a=e.indexOf("endobj",s);if(a<0)continue;let l=e.indexOf("stream",s),d,f=null;if(l>=0&&l<a){d=e.slice(s,l);let u=l+6;e[u]==="\r"&&(u+=1),e[u]===`
3
+ `&&(u+=1);let c=e.indexOf("endstream",u);c>u&&(f=t.subarray(u,c))}else d=e.slice(s,a);n.set(o,{num:o,dict:d,stream:f})}return n}function we(t){let e=t.toString("latin1").replace(/\s/g,"");e.startsWith("<~")&&(e=e.slice(2));let n=e.indexOf("~>");n>=0&&(e=e.slice(0,n));let i=[],r=0,o=0;for(let s of e){if(s==="z"&&o===0){i.push(0,0,0,0);continue}let a=s.charCodeAt(0)-33;if(a<0||a>84)return null;r=r*85+a,o+=1,o===5&&(i.push(r>>>24&255,r>>>16&255,r>>>8&255,r&255),r=0,o=0)}if(o>0){for(let a=o;a<5;a+=1)r=r*85+84;let s=[r>>>24&255,r>>>16&255,r>>>8&255,r&255];for(let a=0;a<o-1;a+=1)i.push(s[a]??0)}return Buffer.from(i)}function Ee(t){let e=t.toString("latin1").replace(/\s/g,"").split(">")[0]??"",n=e.length%2?e+"0":e;return/^[0-9A-Fa-f]*$/.test(n)?Buffer.from(n,"hex"):null}function $e(t){let e=/\/Filter\s*(\[[^\]]*\]|\/\w+)/.exec(t);return!e||!e[1]?[]:[...e[1].matchAll(/\/(\w+)/g)].map(n=>n[1]??"")}function J(t){if(!t.stream)return null;let e=t.stream;for(let n of $e(t.dict)){let i=null;if(n==="FlateDecode")try{i=Se(e)}catch{return null}else if(n==="ASCII85Decode")i=we(e);else if(n==="ASCIIHexDecode")i=Ee(e);else return null;if(i===null)return null;e=i}return e.toString("latin1")}function Ie(t){let e=new Map,n=1,i=/begincodespacerange([\s\S]*?)endcodespacerange/.exec(t);if(i&&i[1]){let l=/<([0-9A-Fa-f]+)>/.exec(i[1]);l&&l[1]&&l[1].length>=4&&(n=2)}let r=l=>{let d="";for(let f=0;f+3<l.length+1;f+=4){let u=parseInt(l.slice(f,f+4),16);Number.isFinite(u)&&u>0&&(d+=String.fromCharCode(u))}return d},o=/beginbfchar([\s\S]*?)endbfchar/g,s;for(;(s=o.exec(t))!==null;){let l=/<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]*)>/g,d;for(;(d=l.exec(s[1]??""))!==null;)e.set(parseInt(d[1]??"0",16),r(d[2]??""))}let a=/beginbfrange([\s\S]*?)endbfrange/g;for(;(s=a.exec(t))!==null;){let l=s[1]??"",d=/<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]*)>/g,f;for(;(f=d.exec(l))!==null;){let u=parseInt(f[1]??"0",16),c=parseInt(f[2]??"0",16),p=parseInt((f[3]??"0").slice(0,4)||"0",16);if(!(c-u>65535))for(let m=u;m<=c;m+=1)e.set(m,String.fromCharCode(p+(m-u)))}}return{map:e,bytes:n}}function Ae(t){let e=new Map,n=new Map,i=[];for(let r of t.values()){let o=/\/Font\s*<<([\s\S]*?)>>/.exec(r.dict);o?.[1]&&i.push(o[1]);let s=/\/Font\s+(\d+)\s+\d+\s+R/.exec(r.dict);if(s){let a=t.get(Number(s[1]));a&&i.push(a.dict)}}for(let r of i){let o=/\/([^\s/<>[\]()]+)\s+(\d+)\s+\d+\s+R/g,s;for(;(s=o.exec(r))!==null;)n.set(s[1]??"",Number(s[2]))}for(let[r,o]of n){let s=t.get(o);if(!s)continue;let a=/\/ToUnicode\s+(\d+)\s+\d+\s+R/.exec(s.dict);if(!a)continue;let l=t.get(Number(a[1]));if(!l)continue;let d=J(l);d&&e.set(r,Ie(d))}return e}function q(t){let e=[];for(let n=0;n<t.length;n+=1){let i=t[n];if(i!=="\\"){e.push(i.charCodeAt(0)&255);continue}let r=t[n+1];if(r===void 0)break;if(r>="0"&&r<="7"){let s="",a=n+1;for(;a<t.length&&s.length<3&&t[a]>="0"&&t[a]<="7";)s+=t[a],a+=1;e.push(parseInt(s,8)&255),n=a-1;continue}let o={n:10,r:13,t:9,b:8,f:12};e.push(o[r]??r.charCodeAt(0)&255),n+=1}return e}function Y(t){if(t.length<2||t[0]!==254||t[1]!==255)return null;let e="";for(let n=2;n+1<t.length;n+=2)e+=String.fromCharCode((t[n]??0)<<8|(t[n+1]??0));return e}function G(t,e){let n=Y(t);if(n!==null)return n;if(!e)return t.map(r=>String.fromCharCode(r)).join("");let i="";if(e.bytes===2)for(let r=0;r+1<t.length;r+=2){let o=(t[r]??0)<<8|(t[r+1]??0);i+=e.map.get(o)??""}else for(let r of t)i+=e.map.get(r)??String.fromCharCode(r);return i}function Ce(t,e){let n="",i,r=/\/([^\s/<>[\]()]+)\s+[\d.]+\s+Tf|\((?:\\.|[^\\)])*\)|<[0-9A-Fa-f\s]*>|TJ|Tj|'|"/g,o,s="";for(;(o=r.exec(t))!==null;){let a=o[0];if(a.endsWith("Tf")){i=e.get(o[1]??"");continue}if(a==="TJ"||a==="Tj"||a==="'"||a==='"'){s&&(n+=s+`
4
+ `,s="");continue}if(a.startsWith("("))s+=G(q(a.slice(1,-1)),i);else if(a.startsWith("<")){let l=a.slice(1,-1).replace(/\s+/g,""),d=[];for(let f=0;f+1<l.length;f+=2)d.push(parseInt(l.slice(f,f+2),16));s+=G(d,i)}}return s&&(n+=s+`
5
+ `),n}function Te(t,e){let n=t.toString("latin1"),i=/\/Info\s+(\d+)\s+\d+\s+R/.exec(n),r=i?e.get(Number(i[1]))?.dict:void 0;if(!r)return"";let o=[],s=/\/(Author|Title|Subject|Keywords|Creator|Producer)\s*(\((?:\\.|[^\\)])*\)|<[0-9A-Fa-f\s]*>)/g,a;for(;(a=s.exec(r))!==null;){let l=a[2]??"";if(l.startsWith("(")){let d=q(l.slice(1,-1));o.push(Y(d)??d.map(f=>String.fromCharCode(f)).join(""))}else{let d=l.slice(1,-1).replace(/\s+/g,""),f="";if(d.toUpperCase().startsWith("FEFF"))for(let u=4;u+3<d.length+1;u+=4)f+=String.fromCharCode(parseInt(d.slice(u,u+4),16));else for(let u=0;u+1<d.length;u+=2)f+=String.fromCharCode(parseInt(d.slice(u,u+2),16));o.push(f)}}return o.join(`
6
+ `)}function Q(t){if(!t.subarray(0,8).toString("latin1").startsWith("%PDF-")||t.toString("latin1",0,Math.min(t.length,4096)).includes("/Encrypt"))return null;let n=ke(t);if(n.size===0)return null;let i=Ae(n),r=[];r.push(Te(t,n));let o=0,s=0,a=!1;for(let l of n.values()){if(!l.stream||/\/Subtype|\/Type\s*\/(XObject|Font|Metadata)|\/FontFile/.test(l.dict))continue;let d=J(l);if(d===null||!/(TJ|Tj)\b/.test(d))continue;let f=Ce(d,i);if(f.trim().length!==0){if(s+=1,o+f.length>X){r.push(f.slice(0,Math.max(0,X-o))),a=!0;break}r.push(f),o+=f.length}}return s===0?null:{text:r.join(`
7
+ `),truncated:a,streams:s}}var ee=new Set([".xlsx",".xlsm",".docx",".pptx"]),D=8*1024*1024,Re=101010256,Pe=33639248,Fe=67324752;function N(t){let e=Math.min(t.length,67584),n=-1;for(let s=t.length-22;s>=t.length-e&&s>=0;s-=1)if(t.readUInt32LE(s)===Re){n=s;break}if(n<0)return null;let i=t.readUInt16LE(n+10),r=t.readUInt32LE(n+16);if(r>=t.length)return null;let o=[];for(let s=0;s<i&&!(r+46>t.length||t.readUInt32LE(r)!==Pe);s+=1){let a=t.readUInt16LE(r+10),l=t.readUInt32LE(r+20),d=t.readUInt32LE(r+24),f=t.readUInt16LE(r+28),u=t.readUInt16LE(r+30),c=t.readUInt16LE(r+32),p=t.readUInt32LE(r+42),m=t.subarray(r+46,r+46+f).toString("utf8");o.push({name:m,method:a,compSize:l,uncompSize:d,localHeaderOffset:p}),r+=46+f+u+c}return o}function U(t,e){let n=e.localHeaderOffset;if(n+30>t.length||t.readUInt32LE(n)!==Fe)return null;let i=t.readUInt16LE(n+26),r=t.readUInt16LE(n+28),o=n+30+i+r,s=o+e.compSize;if(s>t.length)return null;let a=t.subarray(o,s);try{if(e.method===0)return Buffer.from(a);if(e.method===8)return Le(a)}catch{return null}return null}function De(t,e){return U(t,e)?.toString("utf8")??null}var Ne={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&apos;":"'"};function x(t){return t.replace(/&(amp|lt|gt|quot|apos);/g,e=>Ne[e]??e).replace(/&#(\d+);/g,(e,n)=>{let i=Number(n);return i>0&&i<1114112?String.fromCodePoint(i):""}).replace(/&#x([0-9a-fA-F]+);/g,(e,n)=>{let i=parseInt(n,16);return i>0&&i<1114112?String.fromCodePoint(i):""})}function Ue(t){return x(t.replace(/<[^>]*>/g,`
8
+ `)).replace(/\n{2,}/g,`
9
+ `)}function je(t,e,n){let i=new RegExp(`<${e}\\b[^>]*\\b${n}="([^"]*)"`,"g"),r=[],o;for(;(o=i.exec(t))!==null;)o[1]&&r.push(x(o[1]));return r}function Oe(t,e){let n=[];for(let i of e)(i==="docProps/core.xml"||i==="docProps/app.xml")&&n.push(i);if(t===".xlsx"||t===".xlsm")for(let i of e)(i==="xl/sharedStrings.xml"||i==="xl/workbook.xml"||/^xl\/worksheets\/sheet\d+\.xml$/.test(i)||/^xl\/comments\d*\.xml$/.test(i))&&n.push(i);else if(t===".docx")for(let i of e)(i==="word/document.xml"||/^word\/(header|footer|footnotes|endnotes|comments)\d*\.xml$/.test(i))&&n.push(i);else if(t===".pptx")for(let i of e)/^ppt\/(slides|notesSlides)\/(slide|notesSlide)\d+\.xml$/.test(i)&&n.push(i);return n}function ze(t,e){let n=N(t);if(!n||n.length===0)return null;let i=new Map(n.map(d=>[d.name,d])),r=Oe(e,n.map(d=>d.name));if(r.length===0)return null;let o=[],s=[],a=0,l=!1;for(let d of r){if(a>=D){l=!0;break}let f=i.get(d);if(!f)continue;let u=De(t,f);if(u===null)continue;let c=Ue(u);if(d==="xl/workbook.xml"){let p=je(u,"sheet","name");p.length&&(c+=`
10
+ `+p.join(`
11
+ `))}a+c.length>D&&(c=c.slice(0,Math.max(0,D-a)),l=!0),c.trim().length!==0&&(o.push(c),s.push(d),a+=c.length)}return o.length===0?null:{text:o.join(`
12
+ `),truncated:l,parts:s}}function j(t,e){if(ee.has(e))return ze(t,e);if(F.has(e)){let n=Q(t);return n?{text:n.text,truncated:n.truncated,parts:[`pdf:${n.streams}-streams`]}:null}return null}var Be=new Set([...ee,...F]);var At=64*1024*1024,Ct=32*1024;var te={israeli_id:"[ID]",credit_card:"[CARD]",iban:"[IBAN]",israeli_phone:"[PHONE]",email:"[EMAIL]"},Ze=/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,Me=[...K].sort((t,e)=>+(e.subkind==="iban")-+(t.subkind==="iban"));function O(t,e,n=1){t[e]=(t[e]??0)+n}function b(t,e={}){let n=t;for(let i of Me)i.pattern.lastIndex=0,n=n.replace(i.pattern,r=>i.validate(r)?(O(e,i.subkind),te[i.subkind]??`[${i.subkind.toUpperCase()}]`):r);return n=n.replace(Ze,()=>(O(e,"email"),te.email)),{text:n,counts:e,columnsHidden:[]}}function ne(t,e){return t.includes(e)||t.includes('"')||t.includes(`
13
+ `)?`"${t.replace(/"/g,'""')}"`:t}function Ve(t){let e=(t.match(/\t/g)??[]).length,n=(t.match(/;/g)??[]).length,i=(t.match(/,/g)??[]).length;return e>i&&e>=n?" ":n>i?";":","}function z(t,e){let n=t.split(/\r?\n/),i=e??Ve(n[0]??""),r=I(n[0]??"",i),o=r.map(l=>S(l)),s={},a=[r.map(l=>ne(l,i)).join(i)];for(let l of n.slice(1)){if(l===""){a.push(l);continue}let d=I(l,i).map((f,u)=>{let c=o[u];return c&&f.trim()!==""?(O(s,`column:${c.type}`),`[${c.type.toUpperCase()}]`):b(f,s).text});a.push(d.map(f=>ne(f,i)).join(i))}return{text:a.join(`
14
+ `),counts:s,columnsHidden:r.filter((l,d)=>o[d])}}import{deflateRawSync as He}from"node:zlib";var We=/^xl\/(pivotCache|charts|externalLinks)\//,Ke=10;function Xe(t,e,n=1){t[e]=(t[e]??0)+n}function oe(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function ae(t){let e=t.replace(/<rPh\b[\s\S]*?<\/rPh>/g,""),n="";for(let i of e.matchAll(/<t(?:\s[^>]*)?>([\s\S]*?)<\/t>/g))n+=i[1];return x(n)}function Ge(t){return t?[...t.matchAll(/<si\b[^>]*>([\s\S]*?)<\/si>|<si\b[^>]*\/>/g)].map(e=>ae(e[1]??"")):[]}var ie=/<c\b([^>]*?)(?:\/>|>([\s\S]*?)<\/c>)/g;function A(t,e){let n=new RegExp(`\\b${e}="([^"]*)"`).exec(t);return n?n[1]:null}function re(t,e){if(t.type==="s"){let i=/<v>([^<]*)<\/v>/.exec(t.inner);return i?e[Number(i[1])]??null:null}if(t.type==="inlineStr"){let i=/<is>([\s\S]*?)<\/is>/.exec(t.inner);return i?ae(i[1]):null}if(t.type==="b"||t.type==="e")return null;let n=/<v>([^<]*)<\/v>/.exec(t.inner);return n?x(n[1]):null}function se(t,e){return`<c${t.replace(/\s*\bt="[^"]*"/,"")} t="inlineStr"><is><t xml:space="preserve">${oe(e)}</t></is></c>`}var Je=(()=>{let t=new Uint32Array(256);for(let e=0;e<256;e+=1){let n=e;for(let i=0;i<8;i+=1)n=n&1?3988292384^n>>>1:n>>>1;t[e]=n>>>0}return t})();function qe(t){let e=4294967295;for(let n=0;n<t.length;n+=1)e=Je[(e^t[n])&255]^e>>>8;return(e^4294967295)>>>0}function ce(t){let e=[],n=[],i=0;for(let s of t){let a=Buffer.from(s.name,"utf8"),l=s.name.endsWith("/"),d=l?Buffer.alloc(0):He(s.data),f=l?0:8,u=l?0:qe(s.data),c=Buffer.alloc(30);c.writeUInt32LE(67324752,0),c.writeUInt16LE(20,4),c.writeUInt16LE(2048,6),c.writeUInt16LE(f,8),c.writeUInt32LE(u,14),c.writeUInt32LE(d.length,18),c.writeUInt32LE(s.data.length,22),c.writeUInt16LE(a.length,26),e.push(c,a,d);let p=Buffer.alloc(46);p.writeUInt32LE(33639248,0),p.writeUInt16LE(20,4),p.writeUInt16LE(20,6),p.writeUInt16LE(2048,8),p.writeUInt16LE(f,10),p.writeUInt32LE(u,16),p.writeUInt32LE(d.length,20),p.writeUInt32LE(s.data.length,24),p.writeUInt16LE(a.length,28),p.writeUInt32LE(i,42),n.push(p,a),i+=c.length+a.length+d.length}let r=Buffer.concat(n),o=Buffer.alloc(22);return o.writeUInt32LE(101010256,0),o.writeUInt16LE(t.length,8),o.writeUInt16LE(t.length,10),o.writeUInt32LE(r.length,12),o.writeUInt32LE(i,16),Buffer.concat([...e,r,o])}function B(t){let e=N(t);if(!e||e.length===0||e.some(c=>We.test(c.name)))return null;let n=new Map;for(let c of e){if(c.name.endsWith("/")){n.set(c.name,Buffer.alloc(0));continue}let p=U(t,c);if(!p)return null;n.set(c.name,p)}let i=[...n.keys()].filter(c=>/^xl\/worksheets\/sheet\d+\.xml$/.test(c));if(i.length===0)return null;let r=n.get("xl/sharedStrings.xml")?.toString("utf8")??null,o=Ge(r),s=new Set,a={},l=new Set;for(let c of i){let p=n.get(c).toString("utf8"),m=[];for(let h of p.matchAll(ie)){let g=A(h[1],"r"),y=g?/^([A-Z]+)(\d+)$/.exec(g):null;if(!y)return null;m.push({full:h[0],attrs:h[1],inner:h[2]??"",col:y[1],row:Number(y[2]),type:A(h[1],"t")??"n"})}let Z=[...new Set(m.map(h=>h.row))].sort((h,g)=>h-g).slice(0,Ke),k=-1,w=new Map;for(let h of Z){let g=new Map;for(let y of m.filter(_=>_.row===h)){let _=re(y,o),v=_?S(_):null;v&&(g.set(y.col,v.type),l.add(_.trim()))}if(g.size>0){k=h;for(let[y,_]of g)w.set(y,_);break}}let C=p.replace(ie,(h,g,y)=>{let _=A(g,"r"),[,v,ge]=/^([A-Z]+)(\d+)$/.exec(_),E={full:h,attrs:g,inner:y??"",col:v,row:Number(ge),type:A(g,"t")??"n"},$=re(E,o),M=()=>{if(E.type==="s"){let H=/<v>([^<]*)<\/v>/.exec(E.inner);H&&s.add(Number(H[1]))}return h};if($===null||$.trim()==="")return M();let T=w.get(v);if(T&&E.row>k)return Xe(a,`column:${T}`),se(g,`[${T.toUpperCase()}]`);let V=b($,a);return V.text===$?M():se(g,V.text)});n.set(c,Buffer.from(C,"utf8"))}if(r){let c=-1,p=r.replace(/<si\b[^>]*>[\s\S]*?<\/si>|<si\b[^>]*\/>/g,m=>(c+=1,s.has(c)?m:"<si><t></t></si>"));n.set("xl/sharedStrings.xml",Buffer.from(p,"utf8"))}for(let c of[...n.keys()].filter(p=>/^xl\/comments\d*\.xml$/.test(p))){let m=n.get(c).toString("utf8").replace(/(<t(?:\s[^>]*)?>)([\s\S]*?)(<\/t>)/g,(Z,k,w,C)=>{let h=b(x(w),a);return`${k}${oe(h.text)}${C}`});n.set(c,Buffer.from(m,"utf8"))}let d=n.get("docProps/core.xml");if(d){let c=d.toString("utf8").replace(/(<dc:creator>)[\s\S]*?(<\/dc:creator>)/,"$1$2").replace(/(<cp:lastModifiedBy>)[\s\S]*?(<\/cp:lastModifiedBy>)/,"$1$2");n.set("docProps/core.xml",Buffer.from(c,"utf8"))}let f=n.has("xl/calcChain.xml"),u=e.map(c=>c.name).filter(c=>!(f&&c==="xl/calcChain.xml"));if(f)for(let c of["[Content_Types].xml","xl/_rels/workbook.xml.rels"]){let p=n.get(c);p&&n.set(c,Buffer.from(p.toString("utf8").replace(/<(Override|Relationship)\b[^>]*calcChain[^>]*\/>/g,""),"utf8"))}return{bytes:ce(u.map(c=>({name:c,data:n.get(c)}))),counts:a,columnsHidden:[...l]}}function le(t){return/\.ndc$/i.test(t)||/\.clean\.[A-Za-z0-9]+$/.test(t)}var st=new Set([".csv",".tsv",".txt",".md",".json",".log",".xml",".sql",".yaml",".yml",".xlsx",".xlsm",".docx",".pptx",".pdf"]),ot=50*1024*1024,at=8,ct={israeli_id:"Israeli ID",credit_card:"card",iban:"IBAN",israeli_phone:"phone",email:"email",secret:"secret"};function he(t){let e=nt(t).toLowerCase();return st.has(pe(e))||e===".env"||e.startsWith(".env.")}function lt(t){let e=pe(t).toLowerCase(),n=tt(t),i,r;if(e===".csv"||e===".tsv")r=n.toString("utf8"),i=z(r,e===".tsv"?" ":void 0).counts;else if(e===".xlsx"||e===".xlsm"||e===".docx"||e===".pptx"||e===".pdf"){let s=e===".xlsx"||e===".xlsm"?B(n):null;r=j(n,e)?.text??"",i=s?s.counts:b(r).counts}else r=n.toString("utf8"),i=b(r).counts;let o=P.filter(s=>s.pattern.test(r)).length;return o&&(i.secret=(i.secret??0)+o),i}function dt(t){return Object.entries(t).sort((e,n)=>n[1]-e[1]).map(([e,n])=>`${n} ${e.startsWith("column:")?`${e.slice(7)} (column)`:ct[e]??e}`).join(", ")}function ft(t,e,n){let i=o=>it(o)?o:rt(n,o),r=o=>{try{return fe(o).isFile()}catch{return!1}};if(t==="Read"&&typeof e.file_path=="string")return[i(e.file_path)];if(t==="Grep"&&typeof e.path=="string"&&r(i(e.path)))return[i(e.path)];if(t==="Bash"&&typeof e.command=="string"){let o=e.command.match(/"[^"]*"|'[^']*'|[^\s|;&<>()]+/g)??[],s=[];for(let a of o){let l=i(a.replace(/^['"]|['"]$/g,"").replace(/^~(?=\/)/,ue()));if(he(l)&&r(l)&&!s.includes(l)&&s.push(l),s.length>=at)break}return s}return[]}function ut(t,e,n,i){let r=[];for(let s of ft(t,e,n)){if(!he(s)||le(s)||!Qe(s))continue;let a;try{if(fe(s).size>ot)a=`${s}: too large to check here (over 50 MB)`;else{let l=lt(s);if(Object.keys(l).length===0)continue;a=`${s}: ${dt(l)}`}}catch{a=`${s}: could not be checked`}r.push(a)}if(r.length===0)return{decision:"allow"};let o=`NoData scanned this on your machine before the assistant reads it:
15
+ ${r.join(`
16
+ `)}
17
+ Reading it puts these values in front of the AI. Safer: nodata_redact (a clean copy to work on) or nodata_protect (lock it).`+(i?"":" Allow this read anyway?");return{decision:i?"deny":"ask",reason:o}}function pt(t){try{let e=de(ue(),".nodata");et(e,{recursive:!0}),Ye(de(e,"gate.log"),JSON.stringify({at:new Date().toISOString(),...t})+`
18
+ `,{mode:384})}catch{}}async function me(t){let e=t.includes("--block"),n="";for await(let s of process.stdin)n+=s;let i;try{i=JSON.parse(n)}catch{return}let r=i.tool_name??"",o=ut(r,i.tool_input??{},i.cwd??process.cwd(),e);o.decision!=="allow"&&(pt({tool:r,decision:o.decision}),process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:o.decision,permissionDecisionReason:o.reason}})))}me(process.argv.slice(2)).catch(()=>{process.stdout.write(JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"ask",permissionDecisionReason:"NoData could not check this file before it is read. Allow anyway?"}}))});