@nodatachat/mcp 1.1.0 → 1.3.1

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.
Files changed (3) hide show
  1. package/README.md +25 -1
  2. package/dist/index.js +109 -56
  3. package/package.json +9 -1
package/README.md CHANGED
@@ -101,6 +101,29 @@ Credential precedence: `--api-key` / `--grant-token` › `NODATA_API_KEY` / `NOD
101
101
 
102
102
  On **Windows**, native (non‑WSL) `npx` needs the `cmd /c` wrapper: `claude mcp add nodata -- cmd /c npx @nodatachat/mcp …`. After changing the credential, **restart** — the running server keeps its old arguments.
103
103
 
104
+ ## The local workspace — scan, lock, work, release
105
+
106
+ Any mode except agent mode, **no account needed**, entirely on your machine. Anything that changes files or policy **asks first**: the call without `confirm: true` shows exactly what would happen and changes nothing.
107
+
108
+ | Say | Tool | What happens |
109
+ |-----|------|--------------|
110
+ | "scan this folder" | `nodata_scan_folder` | The **whole** result — counts by type, folder and file — plus a full content‑free HTML report in `~/.nodata/reports` (every finding, never a value). |
111
+ | "lock what it found" | `nodata_protect` | Seals the files with findings to this device's key as `<file>.ndc` — the same v3 seal and format as `nodata protect`, so `nodata open` opens it too. Local receipt with hashes. |
112
+ | "clean copy of this file" | `nodata_redact` | A copy with every detected value replaced by `[CARD]`, `[ID]`, `[IBAN]`, `[PHONE]`, `[EMAIL]` (a personal‑data CSV column hidden whole) — the rest can be analysed. Same detectors as the scan. |
113
+ | "open this .ndc" | `nodata_open` | Opens it back next to itself, hash‑checked. |
114
+ | "who can read what?" | `nodata_policy` | The policy board (admin): every agent and its exact reach. Change it with `nodata_grant` (preview → approve, a copy of the approval kept in `~/.nodata/approvals`) or `nodata_revoke` (immediate). |
115
+
116
+ ## Govern sharing — send, prove, revoke (admin)
117
+
118
+ The one-sentence version: **encrypt locally, send, revoke later, prove what happened.** NoData never holds a key that opens your file.
119
+
120
+ | Say | Tool | What happens |
121
+ |-----|------|--------------|
122
+ | "send this file to …" | `nodata_send` | Encrypts on this machine (post‑quantum hybrid) and returns a `/lock/open/<id>#<key>` link. The key rides in the `#fragment`, which never reaches a server; NoData stores ciphertext only. Expiry (≤ 7 days) and max opens. Filed under your org with a signed receipt + `proof_url`. Preview first. |
123
+ | "was it opened?" | `nodata_link_status` | Opens so far, expiry, burned — one link or every link sent from this machine. |
124
+ | "revoke it" | `nodata_burn` | Zeroes the stored ciphertext: nobody can open it again, including a forwarded copy. Signed receipt. Preview first. |
125
+ | "archive these" | `nodata_wrap` | Seals files to the public half of your **org master key (the 12 words)** into your zero‑knowledge capsule. NoData can never open them; your 12 words always can — even if this computer is lost. Signed receipt + `proof_url` per document. Preview first. |
126
+
104
127
  ---
105
128
 
106
129
  ## Available tools
@@ -120,7 +143,8 @@ On **Windows**, native (non‑WSL) `npx` needs the `cmd /c` wrapper: `claude mcp
120
143
  |------|--------------|
121
144
  | `nodata_register_table` | Register one of your tables' **policy** (which columns are sensitive, which are metadata). Encrypts nothing — the response says what your table still needs. |
122
145
  | `nodata_connect_source` | Connect your own Supabase project as the data source. Reads the URL, anon key and JWT secret from your **local** `.env.local` / `.env` and sends them straight to NoData — the model never sees them. |
123
- | `nodata_grant` | Issue **one** agent a claim‑scoped grant — over one table, or several with `tables: [...]`; returns a `grant_token` (shown once). |
146
+ | `nodata_grant` | Issue **one** agent a claim‑scoped grant — over one table, or several with `tables: [...]`. Previews the policy change first; with `confirm: true` it grants, returns a `grant_token` (shown once) and a `proof_url`, and keeps a copy of the approval. |
147
+ | `nodata_policy` | The policy board — every agent and exactly what it can reach. |
124
148
  | `nodata_revoke` | Revoke a grant by handle or jti — access stops at once. |
125
149
  | `nodata_encrypt` / `nodata_decrypt` | Field‑level AES‑256‑GCM; NoData stores nothing of the plaintext. |
126
150
  | `nodata_deliver` | Create a burn‑after‑read secure link with OTP. |
package/dist/index.js CHANGED
@@ -1,24 +1,77 @@
1
1
  #!/usr/bin/env node
2
- /*! @nodatachat/mcp 1.1.0 | Copyright 2026 Capsule Ltd. | FSL-1.1-ALv2 | see LICENSE.md */
3
- import{McpServer as _t}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as vt}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as c}from"zod";import{readdirSync as be,readFileSync as Se,statSync as Q}from"node:fs";import{join as pt}from"node:path";var oe=[{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"}],se=/node_modules\/|\.next\/|\.test\.|\.spec\.|__tests__\/|\.env\.example$|\.nodata-proof\.json$|\.git\//,Ue=[{name:"lodash",below:"4.17.21",severity:"critical",cve:"CVE-2021-23337",desc:"Command injection via template"},{name:"minimist",below:"1.2.6",severity:"critical",cve:"CVE-2021-44906",desc:"Prototype pollution"},{name:"json5",below:"2.2.2",severity:"high",cve:"CVE-2022-46175",desc:"Prototype pollution"},{name:"express",below:"4.19.2",severity:"high",cve:"CVE-2024-29041",desc:"Open redirect"},{name:"path-to-regexp",below:"6.3.0",severity:"high",cve:"CVE-2024-45296",desc:"ReDoS"},{name:"sanitize-html",below:"2.12.1",severity:"high",cve:"CVE-2024-21501",desc:"XSS bypass"},{name:"dompurify",below:"3.0.9",severity:"high",cve:"CVE-2024-45801",desc:"mXSS"},{name:"jsonwebtoken",below:"9.0.0",severity:"critical",cve:"CVE-2022-23529",desc:"Key confusion attack"},{name:"jose",below:"4.15.5",severity:"high",cve:"CVE-2024-28176",desc:"DoS via JWE"},{name:"axios",below:"1.6.0",severity:"high",cve:"CVE-2023-45857",desc:"CSRF cookie leak"},{name:"node-fetch",below:"2.6.7",severity:"high",cve:"CVE-2022-0235",desc:"Header leak on redirect"},{name:"serialize-javascript",below:"6.0.2",severity:"critical",cve:"CVE-2024-11831",desc:"XSS via serialization"},{name:"xml2js",below:"0.6.0",severity:"high",cve:"CVE-2023-0842",desc:"Prototype pollution"},{name:"next",below:"14.1.1",severity:"high",cve:"CVE-2024-34350",desc:"SSRF via headers"},{name:"sharp",below:"0.32.6",severity:"high",cve:"CVE-2023-4863",desc:"libwebp heap overflow"},{name:"multer",below:"1.4.5",severity:"high",cve:"CVE-2022-24434",desc:"Prototype pollution"},{name:"tough-cookie",below:"4.1.3",severity:"medium",cve:"CVE-2023-26136",desc:"Prototype pollution"},{name:"semver",below:"7.5.4",severity:"medium",cve:"CVE-2022-25883",desc:"ReDoS"},{name:"ip",below:"2.0.1",severity:"critical",cve:"CVE-2024-29415",desc:"SSRF bypass via octal IP"},{name:"tar",below:"6.2.1",severity:"high",cve:"CVE-2024-28863",desc:"DoS via path traversal"}];function Be(e,t){let n=o=>o.replace(/^[^0-9]*/,"").split(".").map(r=>parseInt(r,10)||0),a=n(e),i=n(t);for(let o=0;o<3;o++){if((a[o]||0)<(i[o]||0))return!0;if((a[o]||0)>(i[o]||0))return!1}return!1}function ce(e){let t=[],n;try{n=JSON.parse(e)}catch{return t}let a={...n.dependencies??{},...n.devDependencies??{}};for(let[i,o]of Object.entries(a)){let r=(o||"").replace(/^[\^~>=<\s]+/,""),s=Ue.find(l=>l.name===i&&Be(r,l.below));s&&t.push({name:i,version:r,vuln:s})}return t}var je=[{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"}],Fe=[{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"}],Me=/^(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 G(e){if(!e)return null;let t=e.trim();if(Me.test(t)||/^name$/i.test(t))return null;for(let n of[...Fe,...je])if(n.pattern.test(t))return{type:n.type,label:n.label};return null}var Z={id:"critical",financial:"critical",medical:"critical",biometric:"critical",minor_data:"critical",sensitive_personal:"critical",email:"high",phone:"high",name:"high",address:"high",dob:"high",tracking:"medium",location:"medium"};function F(e){let t=String(e??"").replace(/\D/g,"");if(t.length===0||t.length>9)return!1;let n=t.padStart(9,"0"),a=0;for(let i=0;i<9;i++){let o=parseInt(n[i]??"0",10)*(i%2+1);o>9&&(o-=9),a+=o}return a%10===0&&parseInt(n,10)>0}var U=/(?:\+972[\s-]?|0)(?:5[0-9]|[2-4]|[89])(?:[\s-]?\d){7}/g;var B=/\bIL\d{2}\s?(?:\d{4}\s?){4}\d{3}\b/g;function Ke(e){let t=String(e??"").replace(/\D/g,"");if(t.length<12||t.length>19)return!1;let n=0,a=!1;for(let i=t.length-1;i>=0;i-=1){let o=parseInt(t[i]??"0",10);a&&(o*=2,o>9&&(o-=9)),n+=o,a=!a}return n%10===0}function He(e){let t=String(e??"").replace(/\s/g,"").toUpperCase();if(!/^[A-Z]{2}\d{2}[A-Z0-9]{10,30}$/.test(t))return!1;let n=t.slice(4)+t.slice(0,4),a=0;for(let i of n){let o=i>="A"&&i<="Z"?String(i.charCodeAt(0)-55):i;for(let r of o)a=(a*10+Number(r))%97}return a===1}var W="(?<![\\d.,])",Y="(?![\\d.,])",ze=[{subkind:"israeli_id",severity:"high",pattern:new RegExp(`${W}\\d{9}${Y}`,"g"),validate:F,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(`${W}(?:\\d[ -]?){12,18}\\d${Y}`,"g"),validate:Ke,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]{10,30}\b/g,validate:He,hint:"Bank account in IBAN form (mod-97 verified) in plaintext."},{subkind:"israeli_phone",severity:"medium",pattern:new RegExp(`${W}(?:\\+972[- ]?|0)(?:5\\d|[2-489])[- ]?\\d{3}[- ]?\\d{4}${Y}`,"g"),validate:e=>{let t=e.replace(/\D/g,"").replace(/^972/,"0");return t.length===10&&t.startsWith("0")},hint:"Israeli phone number in plaintext."}];function le(e){let t=[];for(let n of ze){n.pattern.lastIndex=0;let a=new Set,i,o=0;for(;(i=n.pattern.exec(e))!==null&&(o+=1,!(o>2e5));){let r=i[0];if(n.validate(r)&&a.add(r.replace(/[\s-]/g,"")),a.size>=1e5)break}a.size>0&&t.push({subkind:n.subkind,severity:n.severity,hint:n.hint,count:a.size})}return t}function X(e,t){let n=[],a="",i=!1;for(let o=0;o<e.length;o++){let r=e[o];i?r==='"'&&e[o+1]==='"'?(a+='"',o++):r==='"'?i=!1:a+=r:r==='"'?i=!0:r===t?(n.push(a),a=""):a+=r}return n.push(a),n}import{inflateRawSync as et}from"node:zlib";import{inflateSync as Ve}from"node:zlib";var J=new Set([".pdf"]),de=8*1024*1024;function We(e){let t=e.toString("latin1"),n=new Map,a=/(\d+)\s+(\d+)\s+obj\b/g,i;for(;(i=a.exec(t))!==null;){let o=Number(i[1]),r=a.lastIndex,s=t.indexOf("endobj",r);if(s<0)continue;let l=t.indexOf("stream",r),d,p=null;if(l>=0&&l<s){d=t.slice(r,l);let f=l+6;t[f]==="\r"&&(f+=1),t[f]===`
4
- `&&(f+=1);let E=t.indexOf("endstream",f);E>f&&(p=e.subarray(f,E))}else d=t.slice(r,s);n.set(o,{num:o,dict:d,stream:p})}return n}function Ye(e){let t=e.toString("latin1").replace(/\s/g,"");t.startsWith("<~")&&(t=t.slice(2));let n=t.indexOf("~>");n>=0&&(t=t.slice(0,n));let a=[],i=0,o=0;for(let r of t){if(r==="z"&&o===0){a.push(0,0,0,0);continue}let s=r.charCodeAt(0)-33;if(s<0||s>84)return null;i=i*85+s,o+=1,o===5&&(a.push(i>>>24&255,i>>>16&255,i>>>8&255,i&255),i=0,o=0)}if(o>0){for(let s=o;s<5;s+=1)i=i*85+84;let r=[i>>>24&255,i>>>16&255,i>>>8&255,i&255];for(let s=0;s<o-1;s+=1)a.push(r[s]??0)}return Buffer.from(a)}function Ge(e){let t=e.toString("latin1").replace(/\s/g,"").split(">")[0]??"",n=t.length%2?t+"0":t;return/^[0-9A-Fa-f]*$/.test(n)?Buffer.from(n,"hex"):null}function Ze(e){let t=/\/Filter\s*(\[[^\]]*\]|\/\w+)/.exec(e);return!t||!t[1]?[]:[...t[1].matchAll(/\/(\w+)/g)].map(n=>n[1]??"")}function ue(e){if(!e.stream)return null;let t=e.stream;for(let n of Ze(e.dict)){let a=null;if(n==="FlateDecode")try{a=Ve(t)}catch{return null}else if(n==="ASCII85Decode")a=Ye(t);else if(n==="ASCIIHexDecode")a=Ge(t);else return null;if(a===null)return null;t=a}return t.toString("latin1")}function Xe(e){let t=new Map,n=1,a=/begincodespacerange([\s\S]*?)endcodespacerange/.exec(e);if(a&&a[1]){let l=/<([0-9A-Fa-f]+)>/.exec(a[1]);l&&l[1]&&l[1].length>=4&&(n=2)}let i=l=>{let d="";for(let p=0;p+3<l.length+1;p+=4){let f=parseInt(l.slice(p,p+4),16);Number.isFinite(f)&&f>0&&(d+=String.fromCharCode(f))}return d},o=/beginbfchar([\s\S]*?)endbfchar/g,r;for(;(r=o.exec(e))!==null;){let l=/<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]*)>/g,d;for(;(d=l.exec(r[1]??""))!==null;)t.set(parseInt(d[1]??"0",16),i(d[2]??""))}let s=/beginbfrange([\s\S]*?)endbfrange/g;for(;(r=s.exec(e))!==null;){let l=r[1]??"",d=/<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]*)>/g,p;for(;(p=d.exec(l))!==null;){let f=parseInt(p[1]??"0",16),E=parseInt(p[2]??"0",16),P=parseInt((p[3]??"0").slice(0,4)||"0",16);if(!(E-f>65535))for(let R=f;R<=E;R+=1)t.set(R,String.fromCharCode(P+(R-f)))}}return{map:t,bytes:n}}function Je(e){let t=new Map,n=new Map,a=[];for(let i of e.values()){let o=/\/Font\s*<<([\s\S]*?)>>/.exec(i.dict);o?.[1]&&a.push(o[1]);let r=/\/Font\s+(\d+)\s+\d+\s+R/.exec(i.dict);if(r){let s=e.get(Number(r[1]));s&&a.push(s.dict)}}for(let i of a){let o=/\/([^\s/<>[\]()]+)\s+(\d+)\s+\d+\s+R/g,r;for(;(r=o.exec(i))!==null;)n.set(r[1]??"",Number(r[2]))}for(let[i,o]of n){let r=e.get(o);if(!r)continue;let s=/\/ToUnicode\s+(\d+)\s+\d+\s+R/.exec(r.dict);if(!s)continue;let l=e.get(Number(s[1]));if(!l)continue;let d=ue(l);d&&t.set(i,Xe(d))}return t}function fe(e){let t=[];for(let n=0;n<e.length;n+=1){let a=e[n];if(a!=="\\"){t.push(a.charCodeAt(0)&255);continue}let i=e[n+1];if(i===void 0)break;if(i>="0"&&i<="7"){let r="",s=n+1;for(;s<e.length&&r.length<3&&e[s]>="0"&&e[s]<="7";)r+=e[s],s+=1;t.push(parseInt(r,8)&255),n=s-1;continue}let o={n:10,r:13,t:9,b:8,f:12};t.push(o[i]??i.charCodeAt(0)&255),n+=1}return t}function he(e){if(e.length<2||e[0]!==254||e[1]!==255)return null;let t="";for(let n=2;n+1<e.length;n+=2)t+=String.fromCharCode((e[n]??0)<<8|(e[n+1]??0));return t}function pe(e,t){let n=he(e);if(n!==null)return n;if(!t)return e.map(i=>String.fromCharCode(i)).join("");let a="";if(t.bytes===2)for(let i=0;i+1<e.length;i+=2){let o=(e[i]??0)<<8|(e[i+1]??0);a+=t.map.get(o)??""}else for(let i of e)a+=t.map.get(i)??String.fromCharCode(i);return a}function qe(e,t){let n="",a,i=/\/([^\s/<>[\]()]+)\s+[\d.]+\s+Tf|\((?:\\.|[^\\)])*\)|<[0-9A-Fa-f\s]*>|TJ|Tj|'|"/g,o,r="";for(;(o=i.exec(e))!==null;){let s=o[0];if(s.endsWith("Tf")){a=t.get(o[1]??"");continue}if(s==="TJ"||s==="Tj"||s==="'"||s==='"'){r&&(n+=r+`
5
- `,r="");continue}if(s.startsWith("("))r+=pe(fe(s.slice(1,-1)),a);else if(s.startsWith("<")){let l=s.slice(1,-1).replace(/\s+/g,""),d=[];for(let p=0;p+1<l.length;p+=2)d.push(parseInt(l.slice(p,p+2),16));r+=pe(d,a)}}return r&&(n+=r+`
6
- `),n}function Qe(e,t){let n=e.toString("latin1"),a=/\/Info\s+(\d+)\s+\d+\s+R/.exec(n),i=a?t.get(Number(a[1]))?.dict:void 0;if(!i)return"";let o=[],r=/\/(Author|Title|Subject|Keywords|Creator|Producer)\s*(\((?:\\.|[^\\)])*\)|<[0-9A-Fa-f\s]*>)/g,s;for(;(s=r.exec(i))!==null;){let l=s[2]??"";if(l.startsWith("(")){let d=fe(l.slice(1,-1));o.push(he(d)??d.map(p=>String.fromCharCode(p)).join(""))}else{let d=l.slice(1,-1).replace(/\s+/g,""),p="";if(d.toUpperCase().startsWith("FEFF"))for(let f=4;f+3<d.length+1;f+=4)p+=String.fromCharCode(parseInt(d.slice(f,f+4),16));else for(let f=0;f+1<d.length;f+=2)p+=String.fromCharCode(parseInt(d.slice(f,f+2),16));o.push(p)}}return o.join(`
7
- `)}function ge(e){if(!e.subarray(0,8).toString("latin1").startsWith("%PDF-")||e.toString("latin1",0,Math.min(e.length,4096)).includes("/Encrypt"))return null;let n=We(e);if(n.size===0)return null;let a=Je(n),i=[];i.push(Qe(e,n));let o=0,r=0,s=!1;for(let l of n.values()){if(!l.stream||/\/Subtype|\/Type\s*\/(XObject|Font|Metadata)|\/FontFile/.test(l.dict))continue;let d=ue(l);if(d===null||!/(TJ|Tj)\b/.test(d))continue;let p=qe(d,a);if(p.trim().length!==0){if(r+=1,o+p.length>de){i.push(p.slice(0,Math.max(0,de-o))),s=!0;break}i.push(p),o+=p.length}}return r===0?null:{text:i.join(`
8
- `),truncated:s,streams:r}}var me=new Set([".xlsx",".xlsm",".docx",".pptx"]),q=8*1024*1024,tt=101010256,nt=33639248,rt=67324752;function it(e){let t=Math.min(e.length,67584),n=-1;for(let r=e.length-22;r>=e.length-t&&r>=0;r-=1)if(e.readUInt32LE(r)===tt){n=r;break}if(n<0)return null;let a=e.readUInt16LE(n+10),i=e.readUInt32LE(n+16);if(i>=e.length)return null;let o=[];for(let r=0;r<a&&!(i+46>e.length||e.readUInt32LE(i)!==nt);r+=1){let s=e.readUInt16LE(i+10),l=e.readUInt32LE(i+20),d=e.readUInt32LE(i+24),p=e.readUInt16LE(i+28),f=e.readUInt16LE(i+30),E=e.readUInt16LE(i+32),P=e.readUInt32LE(i+42),R=e.subarray(i+46,i+46+p).toString("utf8");o.push({name:R,method:s,compSize:l,uncompSize:d,localHeaderOffset:P}),i+=46+p+f+E}return o}function at(e,t){let n=t.localHeaderOffset;if(n+30>e.length||e.readUInt32LE(n)!==rt)return null;let a=e.readUInt16LE(n+26),i=e.readUInt16LE(n+28),o=n+30+a+i,r=o+t.compSize;if(r>e.length)return null;let s=e.subarray(o,r);try{if(t.method===0)return s.toString("utf8");if(t.method===8)return et(s).toString("utf8")}catch{return null}return null}var ot={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&apos;":"'"};function ye(e){return e.replace(/&(amp|lt|gt|quot|apos);/g,t=>ot[t]??t).replace(/&#(\d+);/g,(t,n)=>{let a=Number(n);return a>0&&a<1114112?String.fromCodePoint(a):""}).replace(/&#x([0-9a-fA-F]+);/g,(t,n)=>{let a=parseInt(n,16);return a>0&&a<1114112?String.fromCodePoint(a):""})}function st(e){return ye(e.replace(/<[^>]*>/g,`
2
+ /*! @nodatachat/mcp 1.3.1 | Copyright 2026 Capsule Ltd. | FSL-1.1-ALv2 | see LICENSE.md */
3
+ import{createRequire as __ndReq}from"node:module";const require=__ndReq(import.meta.url);
4
+ var ai=Object.create;var Dr=Object.defineProperty;var ii=Object.getOwnPropertyDescriptor;var si=Object.getOwnPropertyNames;var ci=Object.getPrototypeOf,li=Object.prototype.hasOwnProperty;var T=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var N=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var di=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of si(t))!li.call(e,o)&&o!==n&&Dr(e,o,{get:()=>t[o],enumerable:!(r=ii(t,o))||r.enumerable});return e};var Or=(e,t,n)=>(n=e!=null?ai(ci(e)):{},di(t||!e||!e.__esModule?Dr(n,"default",{value:e,enumerable:!0}):n,e));var In=N(Z=>{"use strict";Object.defineProperty(Z,"__esModule",{value:!0});Z.MAX_SEALED_BYTES=void 0;Z.kidForPublicKey=no;Z.deriveKeyPairFromSeed=as;Z.generateSeed=is;Z.buildEnvInfo=ss;Z.sealDek=cs;Z.openSealedDek=ls;Z.decodeSealHeader=ro;var Qr=T("crypto"),Zr=T("@hpke/core"),es=T("@hpke/dhkem-x25519"),ts=T("@hpke/chacha20poly1305"),ns=T("@noble/curves/ed25519.js"),rs=T("@noble/hashes/hkdf.js"),os=T("@noble/hashes/sha2.js"),Nt=new Zr.CipherSuite({kem:new es.DhkemX25519HkdfSha256,kdf:new Zr.HkdfSha256,aead:new ts.Chacha20Poly1305}),eo=1,to=1;Z.MAX_SEALED_BYTES=4096;function no(e){return(0,Qr.createHash)("sha256").update(e).digest("hex").slice(0,16)}function as(e){if(e.length<16)throw new Error("seed too short (need at least 16 bytes)");let t=new TextEncoder().encode("protect.env.x25519.v1"),n=Buffer.from((0,rs.hkdf)(os.sha256,e,new Uint8Array(0),t,32)),r=Buffer.from(ns.x25519.scalarMultBase(n));return{secretKey:n,publicKey:r,kid:no(r)}}function is(){return(0,Qr.randomBytes)(32)}function ss(e){return Buffer.from(`protect.env.v3|${e}`,"utf8")}async function cs(e,t,n){if(e.length!==32)throw new Error("sealDek: DEK must be 32 bytes");if(t.length!==32)throw new Error("sealDek: public key must be 32 bytes");let r=await Nt.kem.deserializePublicKey(De(t)),o=await Nt.createSenderContext({recipientPublicKey:r,info:De(n)}),a=Buffer.from(await o.seal(De(e),new ArrayBuffer(0))),i=Buffer.from(o.enc),s=Buffer.alloc(6+i.length+a.length);return s[0]=eo,s[1]=to,s.writeUInt16BE(i.length,2),s.writeUInt16BE(a.length,4),i.copy(s,6),a.copy(s,6+i.length),s}async function ls(e,t,n){let r=ro(e),o=e.subarray(6,6+r.encLen),a=e.subarray(6+r.encLen),i=await Nt.kem.deserializePrivateKey(De(t)),s=await Nt.createRecipientContext({recipientKey:i,enc:De(o),info:De(n)});return Buffer.from(await s.open(De(a)))}function ro(e){if(e.length<6)throw new Error("sealed bytes too short");if(e.length>Z.MAX_SEALED_BYTES)throw new Error("sealed bytes too long");let t=e[0],n=e[1];if(t!==eo)throw new Error(`unsupported seal version 0x${t.toString(16)}`);if(n!==to)throw new Error(`unsupported HPKE suite 0x${n.toString(16)}`);let r=e.readUInt16BE(2),o=e.readUInt16BE(4);if(e.length!==6+r+o)throw new Error("sealed length mismatch");if(r!==32)throw new Error("unexpected KEM enc length (X25519 is 32 bytes)");if(o<16)throw new Error("ciphertext shorter than the AEAD tag");return{ver:t,suite:n,encLen:r,ctLen:o}}function De(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}});var ao=N(pe=>{"use strict";Object.defineProperty(pe,"__esModule",{value:!0});pe.V3_PREFIX=void 0;pe.sealValue=ds;pe.formatToken=us;pe.parseToken=oo;pe.openValue=ps;var Ct=T("crypto"),Rt=In();pe.V3_PREFIX="aes256gcm:v3:";async function ds(e,t){let n=(0,Ct.randomBytes)(32),r=(0,Ct.randomBytes)(12),o=(0,Ct.createCipheriv)("aes-256-gcm",n,r),a=Buffer.concat([o.update(e,"utf8"),o.final()]),i=Buffer.concat([a,o.getAuthTag()]),s=await(0,Rt.sealDek)(n,t.publicKey,(0,Rt.buildEnvInfo)(t.kid));return n.fill(0),{sealedDekB64:s.toString("base64"),iv:r,cipher:i}}function us(e,t){return`${pe.V3_PREFIX}${e.iv.toString("base64")}:${e.cipher.toString("base64")}:${t}`}function oo(e){let t=e.split(":");if(t.length!==5||t[0]!=="aes256gcm"||t[1]!=="v3")throw new Error("not a v3 token");let[,,n,r,o]=t;if(!o)throw new Error("v3 token has no seal id");let a=Buffer.from(n,"base64"),i=Buffer.from(r,"base64");if(a.length!==12)throw new Error("v3 token has a malformed iv");if(i.length<17)throw new Error("v3 token ciphertext is too short");return{iv:a,cipher:i,sealId:o}}async function ps(e,t,n){let{iv:r,cipher:o}=oo(e),a=await(0,Rt.openSealedDek)(Buffer.from(t,"base64"),n.secretKey,(0,Rt.buildEnvInfo)(n.kid)),i=o.subarray(o.length-16),s=o.subarray(0,o.length-16),c=(0,Ct.createDecipheriv)("aes-256-gcm",a,r);c.setAuthTag(i);try{return Buffer.concat([c.update(s),c.final()]).toString("utf8")}finally{a.fill(0)}}});var lo=N(V=>{"use strict";var fs=V&&V.__createBinding||(Object.create?(function(e,t,n,r){r===void 0&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);(!o||("get"in o?!t.__esModule:o.writable||o.configurable))&&(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}):(function(e,t,n,r){r===void 0&&(r=n),e[r]=t[n]})),hs=V&&V.__setModuleDefault||(Object.create?(function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}):function(e,t){e.default=t}),Cn=V&&V.__importStar||(function(){var e=function(t){return e=Object.getOwnPropertyNames||function(n){var r=[];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(r[r.length]=o);return r},e(t)};return function(t){if(t&&t.__esModule)return t;var n={};if(t!=null)for(var r=e(t),o=0;o<r.length;o++)r[o]!=="default"&&fs(n,t,r[o]);return hs(n,t),n}})();Object.defineProperty(V,"__esModule",{value:!0});V.deviceKeyPath=ms;V.hasDeviceKey=gs;V.loadDeviceKey=_s;V.createDeviceKey=bs;V.importDeviceKey=Ss;V.exportSeedHex=ws;V.deviceKeyIsExposed=vs;var z=Cn(T("fs")),ys=Cn(T("os")),io=Cn(T("path")),ct=In(),Nn=io.join(ys.homedir(),".nodata"),M=io.join(Nn,"device-key.json");function ms(){return M}function so(){let e=process.env.NODATA_DEVICE_SEED;if(!e)return null;let t=e.trim();if(!/^[0-9a-fA-F]{64}$/.test(t))throw new Error("NODATA_DEVICE_SEED must be 64 hex characters (32 bytes)");return Buffer.from(t,"hex")}function gs(){return so()!==null||z.existsSync(M)}function _s(){let e=so();if(e)return(0,ct.deriveKeyPairFromSeed)(e);if(!z.existsSync(M))return null;let t;try{t=JSON.parse(z.readFileSync(M,"utf-8"))}catch{throw new Error(`Device key file is unreadable: ${M}`)}if(!t.seed_hex||!/^[0-9a-f]{64}$/i.test(t.seed_hex))throw new Error(`Device key file is malformed (bad seed): ${M}`);let n=(0,ct.deriveKeyPairFromSeed)(Buffer.from(t.seed_hex,"hex"));if(t.kid&&t.kid!==n.kid)throw new Error(`Device key file is inconsistent: stored kid ${t.kid} does not match the seed (${n.kid}).`);return n}function bs(e={}){if(z.existsSync(M)&&!e.force)throw new Error(`A device key already exists at ${M}. Replacing it makes every existing v3 seal unopenable. Back up the seed first (nodata key export), then pass --force.`);let t=(0,ct.generateSeed)(),n=(0,ct.deriveKeyPairFromSeed)(t);return co(t,n),n}function Ss(e,t={}){let n=e.trim().replace(/\s+/g,"");if(!/^[0-9a-fA-F]{64}$/.test(n))throw new Error("Seed must be 64 hex characters (32 bytes).");if(z.existsSync(M)&&!t.force)throw new Error(`A device key already exists at ${M}. Pass --force to replace it.`);let r=Buffer.from(n,"hex"),o=(0,ct.deriveKeyPairFromSeed)(r);return co(r,o),o}function ws(){if(!z.existsSync(M))throw new Error("No device key file to export.");return JSON.parse(z.readFileSync(M,"utf-8")).seed_hex}function co(e,t){z.existsSync(Nn)||z.mkdirSync(Nn,{recursive:!0});let n={version:1,kid:t.kid,pubkey_hex:t.publicKey.toString("hex"),seed_hex:e.toString("hex"),created_at:new Date().toISOString()};z.writeFileSync(M,JSON.stringify(n,null,2)+`
5
+ `,{mode:384});try{z.chmodSync(M,384)}catch{}}function vs(){if(process.platform==="win32"||!z.existsSync(M))return!1;try{return(z.statSync(M).mode&63)!==0}catch{return!1}}});var fo=N(Y=>{"use strict";var Es=Y&&Y.__createBinding||(Object.create?(function(e,t,n,r){r===void 0&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);(!o||("get"in o?!t.__esModule:o.writable||o.configurable))&&(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}):(function(e,t,n,r){r===void 0&&(r=n),e[r]=t[n]})),ks=Y&&Y.__setModuleDefault||(Object.create?(function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}):function(e,t){e.default=t}),uo=Y&&Y.__importStar||(function(){var e=function(t){return e=Object.getOwnPropertyNames||function(n){var r=[];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(r[r.length]=o);return r},e(t)};return function(t){if(t&&t.__esModule)return t;var n={};if(t!=null)for(var r=e(t),o=0;o<r.length;o++)r[o]!=="default"&&Es(n,t,r[o]);return ks(n,t),n}})();Object.defineProperty(Y,"__esModule",{value:!0});Y.ensureDeviceKey=xs;Y.sealFile=As;Y.readManifest=po;Y.openFile=Ts;Y.writeLocalReceipt=Ps;var Rn=T("crypto"),me=T("fs"),lt=T("path"),$n=uo(ao()),Bn=uo(lo());function xs(){let e=Bn.loadDeviceKey();return e?{key:e,created:!1}:{key:Bn.createDeviceKey(),created:!0}}async function As(e,t,n){let r=(0,me.readFileSync)(e),o=(0,Rn.createHash)("sha256").update(r).digest("hex"),a=n??"local-"+(0,Rn.randomUUID)(),i=await $n.sealValue(r.toString("base64"),t),s={v:3,alg:"aes256gcm:v3",kid:t.kid,orig:(0,lt.basename)(e),enc:"base64",token:$n.formatToken(i,a),sealed_dek:i.sealedDekB64,sha256:o,sealed_at:new Date().toISOString()},c=e+".ndc";return(0,me.writeFileSync)(c,JSON.stringify(s,null,2)+`
6
+ `,{mode:384}),{path:e,ndc:c,sha256:o,sealId:a}}function po(e){try{let t=JSON.parse((0,me.readFileSync)(e,"utf8"));return t.alg==="aes256gcm:v3"&&t.token&&t.sealed_dek?t:null}catch{return null}}async function Ts(e,t){if(!(0,me.existsSync)(e))return{ok:!1,error:"not_found"};let n=po(e);if(!n)return{ok:!1,error:"not_a_seal"};let r=t===void 0?Bn.loadDeviceKey():t;if(!r)return{ok:!1,error:"no_device_key"};let o;try{o=await $n.openValue(n.token,n.sealed_dek,r)}catch{return{ok:!1,error:"wrong_key"}}let a=Buffer.from(o,"base64"),i=e.endsWith(".ndc")?e.slice(0,-4):e+".opened";(0,me.existsSync)(i)&&(i=i+".opened"),(0,me.writeFileSync)(i,a);let s=(0,Rn.createHash)("sha256").update(a).digest("hex")===n.sha256;return{ok:!0,outPath:i,sha256:n.sha256,intact:s}}function Ps(e,t){let n=(0,lt.join)(e,".nodata","receipts");(0,me.mkdirSync)(n,{recursive:!0});let r={action:t.action,at:new Date().toISOString(),governed:"local",device_kid:t.kid,removed_plaintext:t.removed_plaintext,files:t.files.map(a=>({path:(0,lt.relative)(e,a.path),sha256:a.sha256,seal_id:a.sealId,sealed:(0,lt.basename)(a.ndc)})),...t.extra??{}},o=(0,lt.join)(n,`${t.action}-${Date.now()}.json`);return(0,me.writeFileSync)(o,JSON.stringify(r,null,2)+`
7
+ `),o}});var Oe=N(Hn=>{"use strict";Object.defineProperty(Hn,"__esModule",{value:!0});var pt=class{static async generateKeyPair(){let t=await crypto.subtle.generateKey({name:"RSA-OAEP",modulusLength:4096,publicExponent:new Uint8Array([1,0,1]),hash:"SHA-256"},!0,["encrypt","decrypt"]),n=await crypto.subtle.exportKey("jwk",t.publicKey),r=await crypto.subtle.exportKey("jwk",t.privateKey);return{publicKeyJwk:n,privateKeyJwk:r}}static async encryptMessage(t,n){let r=await crypto.subtle.importKey("jwk",n,{name:"RSA-OAEP",hash:"SHA-256"},!1,["encrypt"]),o=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),a=crypto.getRandomValues(new Uint8Array(12)),i=new TextEncoder().encode(t),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:a,tagLength:128},o,i),c=await crypto.subtle.exportKey("raw",o),d=await crypto.subtle.encrypt({name:"RSA-OAEP"},r,c);return{encrypted_blob:this.arrayBufferToBase64(s),encrypted_aes_key:this.arrayBufferToBase64(d),iv:this.arrayBufferToBase64(a)}}static async decryptMessage(t,n){let r=await crypto.subtle.importKey("jwk",n,{name:"RSA-OAEP",hash:"SHA-256"},!1,["decrypt"]),o=this.base64ToArrayBuffer(t.encrypted_aes_key),a=await crypto.subtle.decrypt({name:"RSA-OAEP"},r,o),i=await crypto.subtle.importKey("raw",a,{name:"AES-GCM",length:256},!1,["decrypt"]),s=this.base64ToArrayBuffer(t.iv),c=this.base64ToArrayBuffer(t.encrypted_blob),d=await crypto.subtle.decrypt({name:"AES-GCM",iv:s,tagLength:128},i,c);return new TextDecoder().decode(d)}static async encryptFile(t,n){let r=await t.arrayBuffer(),o=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),a=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:a,tagLength:128},o,r),s=JSON.stringify({name:t.name,type:t.type,size:t.size,lastModified:t.lastModified}),c=crypto.getRandomValues(new Uint8Array(12)),d=await crypto.subtle.encrypt({name:"AES-GCM",iv:c,tagLength:128},o,new TextEncoder().encode(s)),u=await crypto.subtle.importKey("jwk",n,{name:"RSA-OAEP",hash:"SHA-256"},!1,["encrypt"]),p=await crypto.subtle.exportKey("raw",o),f=await crypto.subtle.encrypt({name:"RSA-OAEP"},u,p);return{encrypted_file:this.arrayBufferToBase64(i),encrypted_file_key:this.arrayBufferToBase64(f),iv:this.arrayBufferToBase64(a),encrypted_metadata:this.arrayBufferToBase64(d),metadata_iv:this.arrayBufferToBase64(c),encrypted_size:i.byteLength}}static async importKeyFromFragment(t){let n=t.replace(/-/g,"+").replace(/_/g,"/"),r=this.base64ToArrayBuffer(n.padEnd(Math.ceil(n.length/4)*4,"="));if(r.byteLength!==32)throw new Error("channel key must be 32 bytes");return crypto.subtle.importKey("raw",r,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}static async deriveKeyFromOTP(t,n,r="SHA-512"){let o=await crypto.subtle.importKey("raw",new TextEncoder().encode(t),"PBKDF2",!1,["deriveBits","deriveKey"]);return await crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode(n),iterations:31e4,hash:r},o,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"])}static async encryptWithDerivedKey(t,n){let r=crypto.getRandomValues(new Uint8Array(12)),o=new TextEncoder().encode(t),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r,tagLength:128},n,o);return{encrypted:this.arrayBufferToBase64(a),iv:this.arrayBufferToBase64(r)}}static async decryptWithDerivedKey(t,n,r){let o=this.base64ToArrayBuffer(t),a=this.base64ToArrayBuffer(n),i=await crypto.subtle.decrypt({name:"AES-GCM",iv:a,tagLength:128},r,o);return new TextDecoder().decode(i)}static async sha256Hex(t){let n=t instanceof Uint8Array?t.buffer.slice(t.byteOffset,t.byteOffset+t.byteLength):t,r=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(r)).map(o=>o.toString(16).padStart(2,"0")).join("")}static async encryptFileWithDerivedKey(t,n){let r=await t.arrayBuffer(),o=await this.sha256Hex(r),a=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:a,tagLength:128},n,r),s=JSON.stringify({name:t.name,type:t.type,size:t.size,lastModified:t.lastModified}),c=crypto.getRandomValues(new Uint8Array(12)),d=await crypto.subtle.encrypt({name:"AES-GCM",iv:c,tagLength:128},n,new TextEncoder().encode(s));return{encrypted_file:this.arrayBufferToBase64(i),iv:this.arrayBufferToBase64(a),encrypted_metadata:this.arrayBufferToBase64(d),metadata_iv:this.arrayBufferToBase64(c),encrypted_size:i.byteLength,plaintext_sha256:o,ciphertext_sha256:await this.sha256Hex(i)}}static async decryptFileBytesWithDerivedKey(t,n,r){let o=this.base64ToArrayBuffer(n);return crypto.subtle.decrypt({name:"AES-GCM",iv:o,tagLength:128},r,t)}static async decryptFileWithDerivedKey(t,n,r){let o=this.base64ToArrayBuffer(t),a=this.base64ToArrayBuffer(n);return crypto.subtle.decrypt({name:"AES-GCM",iv:a,tagLength:128},r,o)}static async deriveSeedKey(t,n="SHA-512"){let r=t.trim().toLowerCase(),o=await crypto.subtle.importKey("raw",new TextEncoder().encode(r),"PBKDF2",!1,["deriveBits","deriveKey"]);return await crypto.subtle.deriveKey({name:"PBKDF2",salt:new TextEncoder().encode(this.SEED_SALT),iterations:this.PBKDF2_ITERATIONS,hash:n},o,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}static async exportKeyWithSeed(t,n){let r=await crypto.subtle.exportKey("jwk",t),o=new TextEncoder().encode(JSON.stringify(r)),a=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:a,tagLength:128},n,o),s=new Uint8Array(a.byteLength+i.byteLength);return s.set(a,0),s.set(new Uint8Array(i),a.byteLength),s.buffer}static async importKeyWithSeed(t,n){let r=new Uint8Array(t),o=r.slice(0,12),a=r.slice(12),i=await crypto.subtle.decrypt({name:"AES-GCM",iv:o,tagLength:128},n,a),s=new TextDecoder().decode(i),c=JSON.parse(s),d=await crypto.subtle.importKey("jwk",c,{name:"RSA-OAEP",hash:"SHA-256"},!0,["decrypt"]);return new Uint8Array(i).fill(0),d}static async hashPhone(t){let n=new TextEncoder().encode(t.replace(/\D/g,"")),r=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(r)).map(o=>o.toString(16).padStart(2,"0")).join("")}static arrayBufferToBase64(t){let n=new Uint8Array(t),r=32768,o=[];for(let a=0;a<n.length;a+=r)o.push(String.fromCharCode(...n.subarray(a,a+r)));return btoa(o.join(""))}static async encryptFileToBytesWithDerivedKey(t,n){let r=await t.arrayBuffer(),o=await this.sha256Hex(r),a=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:a,tagLength:128},n,r),s=JSON.stringify({name:t.name,type:t.type,size:t.size,lastModified:t.lastModified}),c=crypto.getRandomValues(new Uint8Array(12)),d=await crypto.subtle.encrypt({name:"AES-GCM",iv:c,tagLength:128},n,new TextEncoder().encode(s));return{ciphertext:i,iv:this.arrayBufferToBase64(a),encrypted_metadata:this.arrayBufferToBase64(d),metadata_iv:this.arrayBufferToBase64(c),encrypted_size:i.byteLength,plaintext_sha256:o,ciphertext_sha256:await this.sha256Hex(i)}}static base64ToArrayBuffer(t){let n=atob(t),r=new Uint8Array(n.length);for(let o=0;o<n.length;o++)r[o]=n.charCodeAt(o);return r.buffer}static wipeFromMemory(t){new Uint8Array(t).fill(0)}};pt.PBKDF2_ITERATIONS=31e4;pt.SEED_SALT="NoDataChat-Seed-v1";Hn.default=pt});var _o=N(jt=>{"use strict";Object.defineProperty(jt,"__esModule",{value:!0});jt.solveProofOfWork=js;jt.verifyProofOfWork=Ms;function Ks(e){let t=new Uint8Array(e),n="";for(let r=0;r<t.length;r++)n+=t[r].toString(16).padStart(2,"0");return n}async function go(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest("SHA-256",t);return Ks(n)}async function js(e,t=4){if(t<1||t>16)throw new Error("Difficulty must be between 1 and 16");let n="0".repeat(t),r=0;for(;;){let o=e+r.toString(),a=await go(o);if(a.startsWith(n))return{nonce:r,hash:a};if(r++,r>2e9)throw new Error("Proof of work exceeded maximum attempts")}}async function Ms(e,t,n=4){if(n<1||n>16)return!1;let r="0".repeat(n),o=e+t.toString();return(await go(o)).startsWith(r)}});var Gn=N(Fe=>{"use strict";var Ls=Fe&&Fe.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Fe,"__esModule",{value:!0});Fe.NoDataEmail=void 0;var ie=Ls(Oe()),Vn=class{static async seal(t,n,r,o,a,i={}){let{encrypt_subject:s=!0,ttl_hours:c=72,attachments:d=[]}=i,u=await ie.default.encryptMessage(o,a),p=r,f=!1;if(s){let b=await ie.default.encryptMessage(r,a);p=JSON.stringify(b),f=!0}let y=[];for(let b of d){let k=await ie.default.encryptFile(b,a);y.push({encrypted_file:k})}return{from_alias:t,to:n,subject:p,subject_encrypted:f,body:u,attachments:y,sealed_at:new Date().toISOString(),ttl_hours:c,envelope_id:crypto.randomUUID(),crypto_version:"0.2.0"}}static async open(t,n){let r=await ie.default.decryptMessage(t.body,n),o=t.subject;if(t.subject_encrypted){let i=JSON.parse(t.subject);o=await ie.default.decryptMessage(i,n)}let a=[];for(let i of t.attachments){let{encrypted_file:s}=i,c=ie.default.base64ToArrayBuffer(s.metadata_iv),d=ie.default.base64ToArrayBuffer(s.encrypted_metadata),u=ie.default.base64ToArrayBuffer(s.encrypted_file_key),p=await crypto.subtle.importKey("jwk",n,{name:"RSA-OAEP",hash:"SHA-256"},!1,["decrypt"]),f=await crypto.subtle.decrypt({name:"RSA-OAEP"},p,u),y=await crypto.subtle.importKey("raw",f,{name:"AES-GCM",length:256},!1,["decrypt"]),b=await crypto.subtle.decrypt({name:"AES-GCM",iv:c,tagLength:128},y,d),k=JSON.parse(new TextDecoder().decode(b)),S=ie.default.base64ToArrayBuffer(s.iv),_=ie.default.base64ToArrayBuffer(s.encrypted_file),v=await crypto.subtle.decrypt({name:"AES-GCM",iv:S,tagLength:128},y,_);a.push({filename:k.name,mime_type:k.type,data:v,size:k.size})}return{subject:o,body:r,attachments:a,sealed_at:t.sealed_at,ttl_hours:t.ttl_hours,envelope_id:t.envelope_id}}static isExpired(t){let r=new Date(t.sealed_at).getTime()+t.ttl_hours*60*60*1e3;return Date.now()>r}static toMimeBody(t,n){let r=JSON.stringify(t),o=btoa(unescape(encodeURIComponent(r)));return['Content-Type: multipart/mixed; boundary="nodata-boundary"',"","--nodata-boundary","Content-Type: text/html; charset=utf-8","",'<div style="font-family:system-ui;padding:24px;text-align:center">',"<h2>This email is encrypted with Capsule</h2>","<p>The sender used end-to-end encryption. To read this message:</p>",`<a href="${n}?env=${t.envelope_id}" `,'style="display:inline-block;padding:12px 24px;background:#000;color:#fff;','border-radius:8px;text-decoration:none;font-weight:600">',"Open Encrypted Email</a>",'<p style="color:#888;font-size:12px;margin-top:16px">',"Powered by Capsule &mdash; Nothing is ever stored. Ever.</p>","</div>","--nodata-boundary",'Content-Type: application/x-nodata-envelope; name="envelope.nodata"',"Content-Transfer-Encoding: base64",'Content-Disposition: attachment; filename="envelope.nodata"',"",o,"--nodata-boundary--"].join(`\r
8
+ `)}};Fe.NoDataEmail=Vn});var Jn=N(Ue=>{"use strict";var Fs=Ue&&Ue.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ue,"__esModule",{value:!0});Ue.NoDataWebhook=void 0;var qn=Fs(Oe()),Wn=class{static async encrypt(t,n,r,o){let{event_type:a,source:i,ttl_seconds:s=3600}=o,c=JSON.stringify(t),d=await qn.default.encryptMessage(c,n),u=new Date().toISOString(),p=crypto.randomUUID(),f=`${p}.${u}.${d.encrypted_blob}`,y=await this.hmacSign(f,r);return{encrypted_event:d,event_type:a,source:i,signature:y,timestamp:u,delivery_id:p,ttl_seconds:s,crypto_version:"0.2.0"}}static async verify(t,n){let r=`${t.delivery_id}.${t.timestamp}.${t.encrypted_event.encrypted_blob}`,o=await this.hmacSign(r,n),a=new TextEncoder().encode(t.signature),i=new TextEncoder().encode(o),s=a.length^i.length,c=Math.min(a.length,i.length);for(let y=0;y<c;y++)s|=a[y]^i[y];let d=s===0,p=new Date(t.timestamp).getTime()+t.ttl_seconds*1e3,f=Date.now()>p;return{valid:d,expired:f,event_type:t.event_type,source:t.source,delivery_id:t.delivery_id}}static async decrypt(t,n){let r=await qn.default.decryptMessage(t.encrypted_event,n);return JSON.parse(r)}static async verifyAndDecrypt(t,n,r){let o=await this.verify(t,r);if(!o.valid)throw new Error(`[NoDataWebhook] Invalid signature for delivery ${o.delivery_id}`);if(o.expired)throw new Error(`[NoDataWebhook] Payload expired for delivery ${o.delivery_id}`);return{data:await this.decrypt(t,n),delivery_id:o.delivery_id,event_type:o.event_type}}static async hmacSign(t,n){let r=await crypto.subtle.importKey("raw",new TextEncoder().encode(n),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),o=await crypto.subtle.sign("HMAC",r,new TextEncoder().encode(t));return qn.default.arrayBufferToBase64(o)}};Ue.NoDataWebhook=Wn});var Yn=N(He=>{"use strict";var Us=He&&He.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(He,"__esModule",{value:!0});He.NoDataSystems=void 0;var Mt=Us(Oe()),zn=class{static async encryptRecord(t,n,r,o,a,i){let s=[],c={};for(let[d,u]of Object.entries(r))if(o.sensitive.includes(d)){let p=typeof u=="string"?u:JSON.stringify(u),f=await Mt.default.encryptMessage(p,a),y=await this.hashValue(p);s.push({value:f,search_hash:y,field_name:d,encrypted_at:new Date().toISOString()})}else c[d]=u;return{record_id:t,record_type:n,encrypted_fields:s,clear_fields:c,encrypted_by:i,created_at:new Date().toISOString(),crypto_version:"0.2.0"}}static async decryptRecord(t,n){let r={...t.clear_fields};for(let o of t.encrypted_fields){let a=await Mt.default.decryptMessage(o.value,n);try{r[o.field_name]=JSON.parse(a)}catch{r[o.field_name]=a}}return{record_id:t.record_id,record_type:t.record_type,fields:r,created_at:t.created_at}}static async searchByHash(t,n,r){let o=await this.hashValue(r);return t.filter(a=>a.encrypted_fields.some(i=>i.field_name===n&&i.search_hash===o))}static async encryptField(t,n,r){let o=typeof n=="string"?n:JSON.stringify(n),a=await Mt.default.encryptMessage(o,r),i=await this.hashValue(o);return{value:a,search_hash:i,field_name:t,encrypted_at:new Date().toISOString()}}static async decryptField(t,n){let r=await Mt.default.decryptMessage(t.value,n);try{return JSON.parse(r)}catch{return r}}static createSchema(t,n){return{sensitive:n,clear:t.filter(r=>!n.includes(r))}}static async hashValue(t){let n=`nodatachat:field:${t}`,r=new TextEncoder().encode(n),o=await crypto.subtle.digest("SHA-256",r);return Array.from(new Uint8Array(o)).map(a=>a.toString(16).padStart(2,"0")).join("")}};He.NoDataSystems=zn});var Zn=N(Ve=>{"use strict";var Hs=Ve&&Ve.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ve,"__esModule",{value:!0});Ve.NoDataForms=void 0;var se=Hs(Oe()),Xn=class{static async encryptSubmission(t,n,r,o,a={}){let{ttl_hours:i=0,view_once:s=!1,attachments:c=[]}=a,d={},u={};for(let S of n)S.sensitive!==!1?d[S.name]=S.value:u[S.name]=S.value;let p=JSON.stringify(n.map(S=>({name:S.name,value:S.value}))),f=await this.sha256(p),y=await se.default.encryptMessage(JSON.stringify(d),r),b=[];for(let S of c){let _=await se.default.encryptFile(S,r);b.push(_)}let k=n.map(S=>S.name);return{submission_id:crypto.randomUUID(),form_id:t,encrypted_fields:y,clear_fields:u,attachments:b,integrity_hash:f,field_order:k,submitter_id:o,submitted_at:new Date().toISOString(),ttl_hours:i,view_once:s,crypto_version:"0.2.0"}}static async decryptSubmission(t,n){let r=await se.default.decryptMessage(t.encrypted_fields,n),o=JSON.parse(r),a={...t.clear_fields,...o},s=(t.field_order||Object.keys(a).sort()).map(p=>({name:p,value:a[p]})),d=await this.sha256(JSON.stringify(s))===t.integrity_hash,u=[];for(let p of t.attachments){let f=await crypto.subtle.importKey("jwk",n,{name:"RSA-OAEP",hash:"SHA-256"},!1,["decrypt"]),y=await crypto.subtle.decrypt({name:"RSA-OAEP"},f,se.default.base64ToArrayBuffer(p.encrypted_file_key)),b=await crypto.subtle.importKey("raw",y,{name:"AES-GCM",length:256},!1,["decrypt"]),k=await crypto.subtle.decrypt({name:"AES-GCM",iv:se.default.base64ToArrayBuffer(p.metadata_iv),tagLength:128},b,se.default.base64ToArrayBuffer(p.encrypted_metadata)),S=JSON.parse(new TextDecoder().decode(k)),_=await crypto.subtle.decrypt({name:"AES-GCM",iv:se.default.base64ToArrayBuffer(p.iv),tagLength:128},b,se.default.base64ToArrayBuffer(p.encrypted_file));u.push({filename:S.name,mime_type:S.type,data:_,size:S.size})}return{submission_id:t.submission_id,form_id:t.form_id,fields:a,attachments:u,integrity_valid:d,submitted_at:t.submitted_at}}static isExpired(t){if(t.ttl_hours===0)return!1;let r=new Date(t.submitted_at).getTime()+t.ttl_hours*60*60*1e3;return Date.now()>r}static async encryptGrade(t,n,r,o,a=0){let i=await se.default.encryptMessage(JSON.stringify(t),n),s=await this.sha256(`nodatachat:student:${t.student_id}`);return{encrypted_grade:i,student_hash:s,course_id:r,term:o,delivery_id:crypto.randomUUID(),delivered_at:new Date().toISOString(),ttl_hours:a,crypto_version:"0.2.0"}}static async decryptGrade(t,n){let r=await se.default.decryptMessage(t.encrypted_grade,n);return JSON.parse(r)}static async sha256(t){let n=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(r)).map(o=>o.toString(16).padStart(2,"0")).join("")}};Ve.NoDataForms=Xn});var bo=N(Ge=>{"use strict";var Vs=Ge&&Ge.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(Ge,"__esModule",{value:!0});Ge.NoDataSDK=void 0;var Lt=Vs(Oe()),_e=Gn(),be=Jn(),Q=Yn(),ce=Zn(),Qn=class{static async init(t={}){let n;return t.keyPair?n=t.keyPair:(n=await Lt.default.generateKeyPair(),t.onKeysGenerated&&await t.onKeysGenerated(n)),{publicKey:n.publicKeyJwk,email:{seal:_e.NoDataEmail.seal.bind(_e.NoDataEmail),open:_e.NoDataEmail.open.bind(_e.NoDataEmail),isExpired:_e.NoDataEmail.isExpired.bind(_e.NoDataEmail),toMimeBody:_e.NoDataEmail.toMimeBody.bind(_e.NoDataEmail)},webhook:{encrypt:be.NoDataWebhook.encrypt.bind(be.NoDataWebhook),verify:be.NoDataWebhook.verify.bind(be.NoDataWebhook),decrypt:be.NoDataWebhook.decrypt.bind(be.NoDataWebhook),verifyAndDecrypt:be.NoDataWebhook.verifyAndDecrypt.bind(be.NoDataWebhook)},systems:{encryptRecord:Q.NoDataSystems.encryptRecord.bind(Q.NoDataSystems),decryptRecord:Q.NoDataSystems.decryptRecord.bind(Q.NoDataSystems),searchByHash:Q.NoDataSystems.searchByHash.bind(Q.NoDataSystems),encryptField:Q.NoDataSystems.encryptField.bind(Q.NoDataSystems),decryptField:Q.NoDataSystems.decryptField.bind(Q.NoDataSystems),createSchema:Q.NoDataSystems.createSchema.bind(Q.NoDataSystems)},forms:{encryptSubmission:ce.NoDataForms.encryptSubmission.bind(ce.NoDataForms),decryptSubmission:ce.NoDataForms.decryptSubmission.bind(ce.NoDataForms),isExpired:ce.NoDataForms.isExpired.bind(ce.NoDataForms),encryptGrade:ce.NoDataForms.encryptGrade.bind(ce.NoDataForms),decryptGrade:ce.NoDataForms.decryptGrade.bind(ce.NoDataForms)},crypto:Lt.default}}static async quickEncrypt(t,n){let r=typeof t=="string"?t:JSON.stringify(t),o=await Lt.default.encryptMessage(r,n);return JSON.stringify(o)}static async quickDecrypt(t,n){let r=JSON.parse(t),o=await Lt.default.decryptMessage(r,n);try{return JSON.parse(o)}catch{return o}}};Ge.NoDataSDK=Qn});var So=N(ee=>{"use strict";Object.defineProperty(ee,"__esModule",{value:!0});ee.NoDataSDK=ee.NoDataForms=ee.NoDataSystems=ee.NoDataWebhook=ee.NoDataEmail=void 0;var Gs=Gn();Object.defineProperty(ee,"NoDataEmail",{enumerable:!0,get:function(){return Gs.NoDataEmail}});var qs=Jn();Object.defineProperty(ee,"NoDataWebhook",{enumerable:!0,get:function(){return qs.NoDataWebhook}});var Ws=Yn();Object.defineProperty(ee,"NoDataSystems",{enumerable:!0,get:function(){return Ws.NoDataSystems}});var Js=Zn();Object.defineProperty(ee,"NoDataForms",{enumerable:!0,get:function(){return Js.NoDataForms}});var zs=bo();Object.defineProperty(ee,"NoDataSDK",{enumerable:!0,get:function(){return zs.NoDataSDK}})});var We=N(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0});D.PQ_SIZES=D.NDC_WIRE_V03=D.NDC_WIRE_V1=D.NDC_V03_RATCHET_DOMAIN=D.NDC_V03_CONTENT_KEY_DOMAIN=D.NDC_V03_KEM_DOMAIN=D.PQ_SUITE=void 0;D.generateHybridKemKeypair=Ys;D.deriveHybridKemKeypairFromSeed=Xs;D.hybridKemEncapsulate=Zs;D.hybridKemDecapsulate=Qs;D.deriveContentKey=ec;D.ratchetAdvance=tc;D.generateHybridSigKeypair=nc;D.hybridSign=rc;D.hybridVerify=oc;D.generateMlDsa65Keypair=ac;D.mlDsa65SignDetached=ic;D.mlDsa65VerifyDetached=sc;var Se=T("@noble/curves/ed25519.js"),ft=T("@noble/hashes/sha2.js"),ht=T("@noble/hashes/hkdf.js"),Ft=T("@noble/post-quantum/ml-kem.js"),qe=T("@noble/post-quantum/ml-dsa.js");D.PQ_SUITE={KEM:"X25519+ML-KEM-768",SIG:"Ed25519+ML-DSA-65",AEAD:"AES-256-GCM",KDF:"HKDF-SHA-256"};D.NDC_V03_KEM_DOMAIN="NDC-v0.3-hybrid-kem";D.NDC_V03_CONTENT_KEY_DOMAIN="NDC-v0.3-content-key";D.NDC_V03_RATCHET_DOMAIN="NDC-ratchet";D.NDC_WIRE_V1=1;D.NDC_WIRE_V03=2;function wo(...e){let t=0;for(let o of e)t+=o.length;let n=new Uint8Array(t),r=0;for(let o of e)n.set(o,r),r+=o.length;return n}function yt(e){return new TextEncoder().encode(e)}function vo(e,t,n,r){let o=wo(e,t),a=wo(yt(D.NDC_V03_KEM_DOMAIN),n,r);return(0,ht.hkdf)(ft.sha256,o,new Uint8Array(0),a,32)}function Ys(){let{secretKey:e,publicKey:t}=Se.x25519.keygen(),{publicKey:n,secretKey:r}=Ft.ml_kem768.keygen();return{publicKey:{x25519:t,mlKem:n},secretKey:{x25519:e,mlKem:r}}}function Xs(e){if(e.length<32)throw new Error("seed too short (need >=32 bytes)");let t=(0,ht.hkdf)(ft.sha256,e,new Uint8Array(0),yt("ndc-hybrid-kem-x25519-v1"),32),n=(0,ht.hkdf)(ft.sha256,e,new Uint8Array(0),yt("ndc-hybrid-kem-mlkem768-v1"),64),r=Se.x25519.getPublicKey(t),{publicKey:o,secretKey:a}=Ft.ml_kem768.keygen(n);return{publicKey:{x25519:r,mlKem:o},secretKey:{x25519:t,mlKem:a}}}function Zs(e){let{secretKey:t,publicKey:n}=Se.x25519.keygen(),r=Se.x25519.getSharedSecret(t,e.x25519),{cipherText:o,sharedSecret:a}=Ft.ml_kem768.encapsulate(e.mlKem),i=vo(a,r,n,e.x25519);return{ciphertext:{ctClassical:n,ctPq:o},sharedSecret:i,ephemeralX25519Pk:n}}function Qs(e,t,n){let r=Se.x25519.getSharedSecret(e.x25519,n.ctClassical),o=Ft.ml_kem768.decapsulate(n.ctPq,e.mlKem);return vo(o,r,n.ctClassical,t)}function ec(e){return(0,ht.hkdf)(ft.sha256,e,new Uint8Array(0),yt(D.NDC_V03_CONTENT_KEY_DOMAIN),32)}function tc(e,t){return(0,ht.hkdf)(ft.sha256,e,t,yt(D.NDC_V03_RATCHET_DOMAIN),32)}function nc(){let{secretKey:e,publicKey:t}=Se.ed25519.keygen(),{publicKey:n,secretKey:r}=qe.ml_dsa65.keygen();return{publicKey:{ed25519:t,mlDsa:n},secretKey:{ed25519:e,mlDsa:r}}}function rc(e,t){return{ed25519:Se.ed25519.sign(t,e.ed25519),mlDsa:qe.ml_dsa65.sign(t,e.mlDsa)}}function oc(e,t,n){return Se.ed25519.verify(n.ed25519,t,e.ed25519)?qe.ml_dsa65.verify(n.mlDsa,t,e.mlDsa):!1}function ac(){let{publicKey:e,secretKey:t}=qe.ml_dsa65.keygen();return{publicKey:e,secretKey:t}}function ic(e,t){return qe.ml_dsa65.sign(t,e)}function sc(e,t,n){return qe.ml_dsa65.verify(n,t,e)}D.PQ_SIZES={X25519_PK:32,X25519_SK:32,ML_KEM_768_PK:1184,ML_KEM_768_SK:2400,ML_KEM_768_CT:1088,ED25519_PK:32,ED25519_SK:32,ED25519_SIG:64,ML_DSA_65_PK:1952,ML_DSA_65_SK:4032,ML_DSA_65_SIG:3309,HYBRID_SHARED_SECRET:32}});var Ht=N(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.deriveContentKey=O.ContainerV3Error=O.CONTAINER_HEADER_MAX_BYTES=O.CONTAINER_FIXED_PREFIX_BYTES=O.CONTAINER_MAGIC=void 0;O.canonicalJson=Ut;O.headerSigningBytes=er;O.signContainerHeader=Ao;O.verifyContainerHeader=To;O.encodeContainerV3=Po;O.decodeContainerV3=Do;O.sealHybrid=fc;O.openHybrid=hc;var cc=T("@noble/hashes/hkdf.js"),lc=T("@noble/hashes/sha2.js"),j=We();Object.defineProperty(O,"deriveContentKey",{enumerable:!0,get:function(){return j.deriveContentKey}});O.CONTAINER_MAGIC=new Uint8Array([78,68,76,66]);O.CONTAINER_FIXED_PREFIX_BYTES=8;O.CONTAINER_HEADER_MAX_BYTES=16777215;var dc="NDC-v0.3-wrap-key",L=class extends Error{constructor(t,n){super(n),this.name="ContainerV3Error",this.code=t}};O.ContainerV3Error=L;var fe=e=>{if(typeof Buffer<"u")return Buffer.from(e).toString("base64");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)},Ie=e=>{if(typeof Buffer<"u")return new Uint8Array(Buffer.from(e,"base64"));let t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n},xo=e=>{let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t};function Ut(e){if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return"["+e.map(Ut).join(",")+"]";let t=e;return"{"+Object.keys(t).sort().map(r=>JSON.stringify(r)+":"+Ut(t[r])).join(",")+"}"}function er(e){let t={...e};return delete t.sig,new TextEncoder().encode(Ut(t))}function Ao(e,t,n){let r=(0,j.hybridSign)(n.secretKey,er(e));return{...e,sig:{signer_kid:t,ed25519:fe(r.ed25519),ml_dsa_65:fe(r.mlDsa)}}}function To(e,t){let n={ed25519:Ie(e.sig.ed25519),mlDsa:Ie(e.sig.ml_dsa_65)};return(0,j.hybridVerify)(t,er(e),n)}var uc=["lockbox_id","format_version","profile","suite","server","kem","wrapped_content_key","iv","tag","bearer","dpop_required","ciphertext_sha256","issued_at","cache_ttl_seconds","original_filename","original_content_type","sig"];function pc(e){if(!e||typeof e!="object")throw new L("header_schema_mismatch","header is not an object");let t=e;for(let r of uc)if(t[r]===void 0)throw new L("header_schema_mismatch",`header missing required field: ${String(r)}`);if(t.format_version!==3)throw new L("unsupported_version",`format_version ${t.format_version} unknown`);if(t.profile!=="pq-hybrid")throw new L("suite_unknown",`profile must be 'pq-hybrid', got '${String(t.profile)}'`);let n=t.suite;if(n.kem!==j.PQ_SUITE.KEM||n.sig!==j.PQ_SUITE.SIG||n.aead!==j.PQ_SUITE.AEAD||n.kdf!==j.PQ_SUITE.KDF)throw new L("suite_unknown",`suite mismatch: viewer supports ${JSON.stringify(j.PQ_SUITE)}, header has ${JSON.stringify(n)}`)}function Po(e,t){let n=new TextEncoder().encode(JSON.stringify(e));if(n.length>O.CONTAINER_HEADER_MAX_BYTES)throw new L("header_schema_mismatch",`header too large (${n.length} bytes; max 16 MB)`);let r=new Uint8Array(O.CONTAINER_FIXED_PREFIX_BYTES+n.length+t.length);return r.set(O.CONTAINER_MAGIC,0),r[4]=j.NDC_WIRE_V03,r[5]=n.length>>16&255,r[6]=n.length>>8&255,r[7]=n.length&255,r.set(n,O.CONTAINER_FIXED_PREFIX_BYTES),r.set(t,O.CONTAINER_FIXED_PREFIX_BYTES+n.length),r}function Do(e){if(e.length<O.CONTAINER_FIXED_PREFIX_BYTES)throw new L("header_truncated",`container truncated: ${e.length} bytes (need \u2265 ${O.CONTAINER_FIXED_PREFIX_BYTES})`);for(let o=0;o<4;o++)if(e[o]!==O.CONTAINER_MAGIC[o])throw new L("bad_magic",`bad magic: expected NDLB, got ${xo(e.slice(0,4))}`);if(e[4]!==j.NDC_WIRE_V03)throw new L("unsupported_version",`expected wire version 0x${j.NDC_WIRE_V03.toString(16)}, got 0x${e[4].toString(16)}`);let t=e[5]<<16|e[6]<<8|e[7],n=O.CONTAINER_FIXED_PREFIX_BYTES+t;if(e.length<n)throw new L("header_truncated",`header truncated: declared ${t}, only ${e.length-O.CONTAINER_FIXED_PREFIX_BYTES} bytes left`);let r;try{r=JSON.parse(new TextDecoder("utf-8").decode(e.slice(O.CONTAINER_FIXED_PREFIX_BYTES,n)))}catch(o){throw new L("header_invalid_json",`header JSON parse failed: ${o.message}`)}return pc(r),{header:r,ciphertextWithTag:e.slice(n)}}var Ne=e=>e;async function Eo(e,t,n){let r=await crypto.subtle.importKey("raw",Ne(e),{name:"AES-GCM"},!1,["encrypt"]),o=await crypto.subtle.encrypt({name:"AES-GCM",iv:Ne(t)},r,Ne(n));return new Uint8Array(o)}async function ko(e,t,n){let r=await crypto.subtle.importKey("raw",Ne(e),{name:"AES-GCM"},!1,["decrypt"]),o=await crypto.subtle.decrypt({name:"AES-GCM",iv:Ne(t)},r,Ne(n));return new Uint8Array(o)}function Oo(e){return(0,cc.hkdf)(lc.sha256,e,new Uint8Array(0),new TextEncoder().encode(dc),32)}async function Io(e){let t=await crypto.subtle.digest("SHA-256",Ne(e));return xo(new Uint8Array(t))}async function fc(e){let t=crypto.getRandomValues(new Uint8Array(32)),n=crypto.getRandomValues(new Uint8Array(12)),r=await Eo(t,n,e.plaintext),o=r.slice(r.length-16),a=r.slice(0,r.length-16),i=(0,j.hybridKemEncapsulate)(e.recipientPublicKey),s=Oo(i.sharedSecret),c=crypto.getRandomValues(new Uint8Array(12)),d=await Eo(s,c,t),u=await Io(a),p={lockbox_id:e.meta.lockbox_id,format_version:3,profile:"pq-hybrid",suite:{kem:j.PQ_SUITE.KEM,sig:j.PQ_SUITE.SIG,aead:j.PQ_SUITE.AEAD,kdf:j.PQ_SUITE.KDF},server:e.meta.server,kem:{recipient_kid:e.recipientKid,ct_classical:fe(i.ciphertext.ctClassical),ct_pq:fe(i.ciphertext.ctPq),ephemeral_x25519_pk:fe(i.ephemeralX25519Pk)},wrapped_content_key:{wrapped:fe(d),wrap_iv:fe(c)},iv:fe(n),tag:fe(o),bearer:e.meta.bearer,dpop_required:e.meta.dpop_required,ratchet_state:e.meta.ratchet_state,tee_attestation_url:e.meta.tee_attestation_url,original_filename:e.meta.original_filename,original_content_type:e.meta.original_content_type,ciphertext_sha256:u,issued_at:new Date().toISOString(),cache_ttl_seconds:e.meta.cache_ttl_seconds},f=Ao(p,e.signerKid,e.signerKeypair),y=Po(f,r);return t.fill(0),{container:y,header:f,serverState:{lockbox_id:e.meta.lockbox_id,kem_ct_classical_b64:f.kem.ct_classical,kem_ct_pq_b64:f.kem.ct_pq,wrapped_content_key_b64:f.wrapped_content_key.wrapped,wrap_iv_b64:f.wrapped_content_key.wrap_iv}}}async function hc(e){let{header:t,ciphertextWithTag:n}=Do(e.container);if(!To(t,e.signerPublicKey))throw new L("signature_invalid","hybrid signature verification failed");let r=n.slice(0,n.length-16),o=await Io(r);if(o!==t.ciphertext_sha256)throw new L("integrity_mismatch",`ciphertext sha256 mismatch: expected ${t.ciphertext_sha256.slice(0,16)}\u2026, got ${o.slice(0,16)}\u2026`);let a={ctClassical:Ie(t.kem.ct_classical),ctPq:Ie(t.kem.ct_pq)},i=(0,j.hybridKemDecapsulate)(e.recipientSecretKey,e.recipientPublicX25519,a),s=Oo(i),c=Ie(t.wrapped_content_key.wrapped),d=Ie(t.wrapped_content_key.wrap_iv),u=await ko(s,d,c),p=Ie(t.iv),f=await ko(u,p,n);return u.fill(0),{plaintext:f,header:t}}});var nr=N(ze=>{"use strict";Object.defineProperty(ze,"__esModule",{value:!0});ze.publicJwkFromBytes=Co;ze.jwkThumbprint=Ro;ze.createDpop=mc;ze.verifyDpop=_c;var No=T("@noble/curves/ed25519.js"),yc=T("@noble/hashes/sha2.js"),Je=e=>{if(typeof Buffer<"u")return Buffer.from(e).toString("base64").replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t).replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_")},Vt=e=>{let t=e.replace(/-/g,"+").replace(/_/g,"/"),n=t.length%4?4-t.length%4:0,r=t+"=".repeat(n);if(typeof Buffer<"u")return new Uint8Array(Buffer.from(r,"base64"));let o=atob(r),a=new Uint8Array(o.length);for(let i=0;i<o.length;i++)a[i]=o.charCodeAt(i);return a},mt=e=>new TextEncoder().encode(e);function Co(e){if(e.length!==32)throw new Error(`expected 32-byte Ed25519 public key, got ${e.length}`);return{kty:"OKP",crv:"Ed25519",x:Je(e)}}function Ro(e){let t=`{"crv":"${e.crv}","kty":"${e.kty}","x":"${e.x}"}`,n=(0,yc.sha256)(mt(t));return Je(n)}function mc(e){let n={typ:"dpop+jwt",alg:"EdDSA",jwk:Co(e.publicKey)},r={htm:e.htm.toUpperCase(),htu:tr(e.htu),jti:e.jti??gc(),iat:e.iat??Math.floor(Date.now()/1e3)};e.nonce&&(r.nonce=e.nonce);let o=Je(mt(JSON.stringify(n))),a=Je(mt(JSON.stringify(r))),i=`${o}.${a}`,s=No.ed25519.sign(mt(i),e.secretKey);return`${i}.${Je(s)}`}function gc(){return Je(crypto.getRandomValues(new Uint8Array(16)))}function tr(e){try{let t=new URL(e);return`${t.protocol}//${t.host}${t.pathname}`}catch{return e}}async function _c(e,t){let n=e.split(".");if(n.length!==3)return F("malformed","expected three JWT parts");let[r,o,a]=n,i;try{i=JSON.parse(new TextDecoder().decode(Vt(r)))}catch{return F("bad_header","header is not valid base64url JSON")}if(i.typ!=="dpop+jwt")return F("bad_typ",`typ must be 'dpop+jwt', got '${String(i.typ)}'`);if(i.alg!=="EdDSA")return F("bad_alg",`alg must be 'EdDSA', got '${String(i.alg)}'`);if(!i.jwk||i.jwk.kty!=="OKP"||i.jwk.crv!=="Ed25519")return F("bad_header","jwk must be an Ed25519 OKP key");let s=Ro(i.jwk);if(s!==t.expectedJkt)return F("jkt_mismatch",`jkt does not match registered key: expected ${t.expectedJkt.slice(0,12)}\u2026, got ${s.slice(0,12)}\u2026`);let c;try{c=JSON.parse(new TextDecoder().decode(Vt(o)))}catch{return F("bad_payload","payload is not valid base64url JSON")}if(c.htm!==t.expectedHtm.toUpperCase())return F("htm_mismatch",`htm '${c.htm}' \u2260 expected '${t.expectedHtm.toUpperCase()}'`);if(c.htu!==tr(t.expectedHtu))return F("htu_mismatch",`htu '${c.htu}' \u2260 expected '${tr(t.expectedHtu)}'`);if(t.expectedNonce!==void 0&&c.nonce!==t.expectedNonce)return F("nonce_mismatch","DPoP nonce does not match server-issued nonce");let d=Math.floor(Date.now()/1e3),u=t.maxAgeSeconds??30;if(typeof c.iat!="number")return F("bad_payload","iat missing or not a number");if(c.iat>d+5)return F("iat_in_future",`iat ${c.iat} > now+skew`);if(d-c.iat>u)return F("iat_too_old",`iat ${c.iat} older than ${u}s`);let p;try{p=Vt(i.jwk.x)}catch{return F("bad_header","jwk.x is not base64url")}let f=Vt(a),y=mt(`${r}.${o}`);return No.ed25519.verify(f,y,p)?await t.isJtiFresh(c.jti)?{ok:!0,jti:c.jti,iat:c.iat}:F("replay",`jti ${c.jti} was already seen`):F("signature_invalid","Ed25519 signature does not verify")}function F(e,t){return{ok:!1,code:e,reason:t}}});var Fo=N(w=>{"use strict";Object.defineProperty(w,"__esModule",{value:!0});w.ABSORB_STATUS=w.DELTA_KIND=w.RCPT_TOTAL_LEN=w.RCPT_SIGNED_LEN=w.PVE_TOTAL_LEN=w.PVE_SIGNED_LEN=w.RCPT_VERSION=w.PVE_VERSION=w.RCPT_MAGIC=w.PVE_MAGIC=void 0;w.deltaIdFromUuid=vc;w.uuidFromDeltaId=Ec;w.originJktForPublicKey=_t;w.encodePveSignedBytes=Ko;w.signPve=kc;w.parsePve=jo;w.pveHash=xc;w.verifyPve=Ac;w.encodeReceiptSignedBytes=Mo;w.signReceipt=Tc;w.parseReceipt=Lo;w.verifyReceipt=Pc;var Gt=T("@noble/curves/ed25519.js"),bc=T("@noble/hashes/sha2.js"),$o=nr();w.PVE_MAGIC=new Uint8Array([80,86,69,49]);w.RCPT_MAGIC=new Uint8Array([82,67,86,49]);w.PVE_VERSION=1;w.RCPT_VERSION=1;w.PVE_SIGNED_LEN=160;w.PVE_TOTAL_LEN=w.PVE_SIGNED_LEN+64;w.RCPT_SIGNED_LEN=78;w.RCPT_TOTAL_LEN=w.RCPT_SIGNED_LEN+64;var Bo=new Uint8Array(32);w.DELTA_KIND={relay:1,ndc:2,v4section:3,chatmsg:4};w.ABSORB_STATUS={decrypted_ok:1,verified_only:2,denied:3};function Sc(e){if(typeof Buffer<"u")return Buffer.from(e).toString("base64").replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t).replace(/=+$/,"").replace(/\+/g,"-").replace(/\//g,"_")}function wc(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),n=t.length%4?4-t.length%4:0,r=t+"=".repeat(n);if(typeof Buffer<"u")return new Uint8Array(Buffer.from(r,"base64"));let o=atob(r),a=new Uint8Array(o.length);for(let i=0;i<o.length;i++)a[i]=o.charCodeAt(i);return a}function ar(e,t){if(e.length!==t.length)return!1;let n=0;for(let r=0;r<e.length;r++)n|=e[r]^t[r];return n===0}function gt(e){for(let t=0;t<e.length;t++)if(e[t]!==0)return!1;return!0}function rr(e){if(e==null)return Bo;if(e instanceof Uint8Array){if(e.length!==32)throw new Error(`jkt bytes must be 32, got ${e.length}`);return e}let t=wc(e);if(t.length!==32)throw new Error(`jkt must decode to 32 bytes, got ${t.length}`);return t}function or(e){return gt(e)?null:Sc(e)}function vc(e){let t=e.replace(/-/g,"");if(t.length!==32)throw new Error(`expected a 16-byte UUID, got '${e}'`);let n=new Uint8Array(16);for(let r=0;r<16;r++)n[r]=parseInt(t.slice(r*2,r*2+2),16);return n}function Ec(e){if(e.length!==16)throw new Error(`expected 16 bytes, got ${e.length}`);let t=Array.from(e,n=>n.toString(16).padStart(2,"0")).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}function _t(e){return(0,$o.jwkThumbprint)((0,$o.publicJwkFromBytes)(e))}function Ko(e){if(e.deltaId.length!==16)throw new Error("delta_id must be 16 bytes");if(e.ciphertextSha256.length!==32)throw new Error("ciphertext_sha256 must be 32 bytes");if(e.classification<0||e.classification>65535)throw new Error("classification must fit in uint16");let t=new Uint8Array(w.PVE_SIGNED_LEN),n=new DataView(t.buffer),r=0;return t.set(w.PVE_MAGIC,r),r+=4,t[r]=w.PVE_VERSION,r+=1,t[r]=e.deltaKind,r+=1,t.set(e.deltaId,r),r+=16,t.set(e.ciphertextSha256,r),r+=32,t.set(rr(e.originJkt),r),r+=32,t.set(rr(e.destJkt??null),r),r+=32,t.set(e.prevDeltaHash??Bo,r),r+=32,n.setUint16(r,e.classification,!1),r+=2,n.setBigUint64(r,BigInt(e.issuedAt),!1),r+=8,t}function kc(e,t){let n=_t(e.originPublicKey),r=Ko({deltaKind:e.deltaKind,deltaId:e.deltaId,ciphertextSha256:e.ciphertextSha256,originJkt:n,destJkt:e.destJkt??null,prevDeltaHash:e.prevDeltaHash??null,classification:e.classification,issuedAt:e.issuedAt??Date.now()}),o=Gt.ed25519.sign(r,t),a=new Uint8Array(w.PVE_TOTAL_LEN);return a.set(r,0),a.set(o,w.PVE_SIGNED_LEN),a}function jo(e){if(e.length!==w.PVE_TOTAL_LEN)throw new Error(`PVE must be ${w.PVE_TOTAL_LEN} bytes, got ${e.length}`);if(!ar(e.subarray(0,4),w.PVE_MAGIC))throw new Error("bad PVE magic");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=4,r=e[n];n+=1;let o=e[n];n+=1;let a=e.slice(n,n+16);n+=16;let i=e.slice(n,n+32);n+=32;let s=e.slice(n,n+32);n+=32;let c=e.slice(n,n+32);n+=32;let d=e.slice(n,n+32);n+=32;let u=t.getUint16(n,!1);n+=2;let p=Number(t.getBigUint64(n,!1));n+=8;let f=e.slice(0,w.PVE_SIGNED_LEN),y=e.slice(w.PVE_SIGNED_LEN,w.PVE_TOTAL_LEN),b=or(s);if(b===null)throw new Error("origin_jkt must not be zero");return{fields:{version:r,deltaKind:o,deltaId:a,ciphertextSha256:i,originJkt:b,destJkt:or(c),prevDeltaHash:gt(d)?null:d,classification:u,issuedAt:p},signedBytes:f,originSig:y,broadcast:gt(c),genesis:gt(d)}}function xc(e){return(0,bc.sha256)(e)}function Ac(e,t){let n;try{n=jo(e)}catch(o){let a=o instanceof Error?o.message:String(o);return a.includes("magic")?{ok:!1,code:"bad_magic",reason:a}:{ok:!1,code:"malformed",reason:a}}if(n.fields.version!==w.PVE_VERSION)return{ok:!1,code:"bad_version",reason:`unsupported PVE version ${n.fields.version}`};let r;try{r=_t(t)}catch(o){return{ok:!1,code:"malformed",reason:o instanceof Error?o.message:String(o)}}return r!==n.fields.originJkt?{ok:!1,code:"jkt_mismatch",reason:`presented key thumbprint ${r.slice(0,12)}\u2026 \u2260 committed origin_jkt ${n.fields.originJkt.slice(0,12)}\u2026`}:Gt.ed25519.verify(n.originSig,n.signedBytes,t)?{ok:!0,parsed:n}:{ok:!1,code:"signature_invalid",reason:"Ed25519 origin signature does not verify"}}function Mo(e){if(e.pveHash.length!==32)throw new Error("pve_hash must be 32 bytes");let t=rr(e.destJkt);if(gt(t))throw new Error("receipt dest_jkt must not be zero");let n=new Uint8Array(w.RCPT_SIGNED_LEN),r=new DataView(n.buffer),o=0;return n.set(w.RCPT_MAGIC,o),o+=4,n[o]=w.RCPT_VERSION,o+=1,n.set(e.pveHash,o),o+=32,n.set(t,o),o+=32,n[o]=e.absorbStatus,o+=1,r.setBigUint64(o,BigInt(e.absorbedAt),!1),o+=8,n}function Tc(e,t){let n=_t(e.destPublicKey),r=Mo({pveHash:e.pveHash,destJkt:n,absorbStatus:e.absorbStatus,absorbedAt:e.absorbedAt??Date.now()}),o=Gt.ed25519.sign(r,t),a=new Uint8Array(w.RCPT_TOTAL_LEN);return a.set(r,0),a.set(o,w.RCPT_SIGNED_LEN),a}function Lo(e){if(e.length!==w.RCPT_TOTAL_LEN)throw new Error(`receipt must be ${w.RCPT_TOTAL_LEN} bytes, got ${e.length}`);if(!ar(e.subarray(0,4),w.RCPT_MAGIC))throw new Error("bad receipt magic");let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=4,r=e[n];n+=1;let o=e.slice(n,n+32);n+=32;let a=e.slice(n,n+32);n+=32;let i=e[n];n+=1;let s=Number(t.getBigUint64(n,!1));n+=8;let c=or(a);if(c===null)throw new Error("receipt dest_jkt must not be zero");return{fields:{version:r,pveHash:o,destJkt:c,absorbStatus:i,absorbedAt:s},signedBytes:e.slice(0,w.RCPT_SIGNED_LEN),destSig:e.slice(w.RCPT_SIGNED_LEN,w.RCPT_TOTAL_LEN)}}function Pc(e,t,n){let r;try{r=Lo(e)}catch(a){let i=a instanceof Error?a.message:String(a);return i.includes("magic")?{ok:!1,code:"bad_magic",reason:i}:{ok:!1,code:"malformed",reason:i}}if(r.fields.version!==w.RCPT_VERSION)return{ok:!1,code:"bad_version",reason:`unsupported receipt version ${r.fields.version}`};let o;try{o=_t(t)}catch(a){return{ok:!1,code:"malformed",reason:a instanceof Error?a.message:String(a)}}return o!==r.fields.destJkt?{ok:!1,code:"jkt_mismatch",reason:`presented key thumbprint ${o.slice(0,12)}\u2026 \u2260 committed dest_jkt ${r.fields.destJkt.slice(0,12)}\u2026`}:n!==void 0&&!ar(n,r.fields.pveHash)?{ok:!1,code:"pve_hash_mismatch",reason:"receipt does not acknowledge the expected PVE"}:Gt.ed25519.verify(r.destSig,r.signedBytes,t)?{ok:!0,parsed:r}:{ok:!1,code:"signature_invalid",reason:"Ed25519 destination signature does not verify"}}});var Ho=N(bt=>{"use strict";Object.defineProperty(bt,"__esModule",{value:!0});bt.stepRatchet=Dc;bt.replayRatchet=Oc;bt.destroyKey=Ic;var Uo=We();function Dc(e,t){if(t.length!==32)throw new Error(`ratchet token must be 32 bytes, got ${t.length}`);return{nextContentKey:(0,Uo.ratchetAdvance)(e.contentKey,t),openCount:e.openCount+1}}function Oc(e,t){let n=[e],r=e;for(let o of t)r=(0,Uo.ratchetAdvance)(r,o),n.push(r);return n}function Ic(e){e.fill(0)}});var cr=N(Ye=>{"use strict";Object.defineProperty(Ye,"__esModule",{value:!0});Ye.__coseInternals=void 0;Ye.verifyCoseSign1Es384=Rc;Ye.decodeAttestationPayload=$c;var Nc=T("@noble/curves/nist.js"),Cc=T("@noble/hashes/sha2.js"),ir=class{constructor(t){this.b=t,this.p=0}u8(){if(this.p>=this.b.length)throw new Error("cbor: truncated");return this.b[this.p++]}uN(t){let n=0;for(let r=0;r<t;r++)n=n*256+this.u8();return n}len(t){if(t<24)return t;if(t===24)return this.u8();if(t===25)return this.uN(2);if(t===26)return this.uN(4);if(t===27){let n=this.uN(4),r=this.uN(4);return n*4294967296+r}throw new Error(`cbor: unsupported additional info ${t}`)}read(){let t=this.u8(),n=t>>5,r=t&31;switch(n){case 0:return this.len(r);case 1:return-1-this.len(r);case 2:{let o=this.len(r),a=this.b.subarray(this.p,this.p+o);if(a.length!==o)throw new Error("cbor: bstr truncated");return this.p+=o,a.slice()}case 3:{let o=this.len(r),a=this.b.subarray(this.p,this.p+o);if(a.length!==o)throw new Error("cbor: tstr truncated");return this.p+=o,new TextDecoder("utf-8").decode(a)}case 4:{let o=this.len(r),a=[];for(let i=0;i<o;i++)a.push(this.read());return a}case 5:{let o=this.len(r),a=new Map;for(let i=0;i<o;i++){let s=this.read(),c=this.read();a.set(s,c)}return a}case 6:return this.len(r),this.read();case 7:if(r===20)return!1;if(r===21)return!0;if(r===22||r===23)return null;throw new Error(`cbor: unsupported simple/float ${r}`);default:throw new Error(`cbor: unknown major ${n}`)}}};function sr(e){return new ir(e).read()}function Wt(e,t){let n=e<<5;return t<24?Uint8Array.of(n|t):t<=255?Uint8Array.of(n|24,t):t<=65535?Uint8Array.of(n|25,t>>8&255,t&255):Uint8Array.of(n|26,t>>>24&255,t>>16&255,t>>8&255,t&255)}function Jt(...e){let t=e.reduce((o,a)=>o+a.length,0),n=new Uint8Array(t),r=0;for(let o of e)n.set(o,r),r+=o.length;return n}function qt(e){return Jt(Wt(2,e.length),e)}function Vo(e){let t=new TextEncoder().encode(e);return Jt(Wt(3,t.length),t)}function Go(e,t){return Jt(Wt(4,4),Vo("Signature1"),qt(e),qt(new Uint8Array(0)),qt(t))}function Rc(e,t){let n;try{n=sr(e)}catch(d){return{ok:!1,code:"malformed",reason:`cbor decode failed: ${d.message}`}}if(!Array.isArray(n)||n.length!==4)return{ok:!1,code:"bad_structure",reason:"COSE_Sign1 must be a 4-element array"};let[r,,o,a]=n;if(!(r instanceof Uint8Array))return{ok:!1,code:"bad_structure",reason:"protected header must be a byte string"};if(!(o instanceof Uint8Array)||o.length===0)return{ok:!1,code:"no_payload",reason:"detached/empty payload is not supported"};if(!(a instanceof Uint8Array))return{ok:!1,code:"bad_structure",reason:"signature must be a byte string"};if(a.length!==96)return{ok:!1,code:"bad_signature_len",reason:`expected 96-byte ES384 sig, got ${a.length}`};let i=Go(r,o),s=(0,Cc.sha384)(i),c=!1;try{c=Nc.p384.verify(a,s,t,{prehash:!1})}catch(d){return{ok:!1,code:"signature_invalid",reason:`verify threw: ${d.message}`}}return c?{ok:!0,payload:o}:{ok:!1,code:"signature_invalid",reason:"ECDSA P-384 verification failed"}}function $c(e){try{let t=sr(e);return t instanceof Map?t:null}catch{return null}}Ye.__coseInternals={sig1Structure:Go,encBstr:qt,encText:Vo,encHead:Wt,concat:Jt,decodeCbor:sr}});var qo=N(St=>{"use strict";Object.defineProperty(St,"__esModule",{value:!0});St.parseAttestation=Kc;St.verifyAttestation=jc;St.fetchAttestation=Mc;var Bc=cr();function Kc(e){try{let t=new TextDecoder("utf-8").decode(e),n=JSON.parse(t);return n.vendor?n.module_id?!n.pcrs||typeof n.pcrs!="object"?{error:"missing pcrs"}:typeof n.timestamp!="number"?{error:"missing timestamp"}:typeof n.user_data_sha256!="string"?{error:"missing user_data_sha256"}:{vendor:n.vendor,module_id:n.module_id,pcrs:n.pcrs,timestamp:n.timestamp,user_data_sha256:n.user_data_sha256,raw:e}:{error:"missing module_id"}:{error:"missing vendor"}}catch(t){return{error:`parse failed: ${t.message}`}}}function jc(e,t){if(e.vendor!==t.vendor)return{ok:!1,code:"vendor_mismatch",reason:`vendor '${e.vendor}' \u2260 expected '${t.vendor}'`};if(e.module_id!==t.module_id)return{ok:!1,code:"module_id_mismatch",reason:`module_id mismatch (got '${e.module_id.slice(0,16)}\u2026')`};for(let[a,i]of Object.entries(t.pcrs))if(e.pcrs[a]!==i)return{ok:!1,code:"pcr_mismatch",reason:`PCR ${a}: got '${(e.pcrs[a]??"").slice(0,16)}\u2026', expected '${i.slice(0,16)}\u2026'`};if(e.user_data_sha256!==t.expected_user_data_sha256)return{ok:!1,code:"user_data_mismatch",reason:"attested user_data does not match presented key"};let n=Math.floor(Date.now()/1e3),r=t.maxAgeSeconds??600;if(e.timestamp>n+30)return{ok:!1,code:"in_future",reason:`attestation timestamp ${e.timestamp} > now+30s`};if(n-e.timestamp>r)return{ok:!1,code:"expired",reason:`attestation ${n-e.timestamp}s old (max ${r}s)`};let o=!1;if(t.cose){if(!t.trustedLeafPubKey)return{ok:!1,code:"signature_invalid",reason:"cose supplied without trustedLeafPubKey \u2014 cannot verify, refusing"};let a=(0,Bc.verifyCoseSign1Es384)(t.cose,t.trustedLeafPubKey);if(!a.ok)return{ok:!1,code:"signature_invalid",reason:`cose: ${a.code}: ${a.reason}`};o=!0}return{ok:!0,vendor:e.vendor,module_id:e.module_id,signature_verified:o}}async function Mc(e){let n=await(e.fetchImpl??fetch)(e.attestationUrl,{method:"GET"});if(!n.ok)throw new Error(`attestation fetch failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}});var zo=N(Xe=>{"use strict";Object.defineProperty(Xe,"__esModule",{value:!0});Xe.splitSecret=Hc;Xe.combineShares=Vc;Xe.serializeShare=Wc;Xe.deserializeShare=Jc;var Ce=null,Re=null;function Wo(){if(Ce&&Re)return;Ce=new Uint8Array(512),Re=new Uint8Array(256);let e=1;for(let t=0;t<255;t++){Ce[t]=e,Re[e]=t;let n=e<<1;n&256&&(n^=283),n^=e,e=n&255}for(let t=255;t<512;t++)Ce[t]=Ce[t-255]}function zt(e,t){return e===0||t===0?0:(Wo(),Ce[Re[e]+Re[t]])}function Lc(e,t){if(e===0)return 0;if(t===0)throw new Error("division by zero in GF(2^8)");Wo();let n=Re[e]-Re[t];return Ce[n<0?n+255:n]}function Jo(e,t){return e^t}function Fc(e,t){let n=0;for(let r=e.length-1;r>=0;r--)n=Jo(zt(n,t),e[r]);return n}var Uc=e=>crypto.getRandomValues(new Uint8Array(e));function Hc(e,t){if(t.k<2)throw new Error("threshold k must be \u2265 2");if(t.n<t.k)throw new Error(`total shares n (${t.n}) must be \u2265 threshold k (${t.k})`);if(t.n>255)throw new Error("total shares n must be \u2264 255 (limit of GF(2^8))");if(e.length===0)throw new Error("secret must be non-empty");let n=t.randomBytes??Uc,r=[];for(let o=1;o<=t.n;o++)r.push({x:o,y:new Uint8Array(e.length)});for(let o=0;o<e.length;o++){let a=new Uint8Array(t.k);a[0]=e[o];let i=n(t.k-1);for(let s=1;s<t.k;s++)a[s]=i[s-1];for(let s=0;s<t.n;s++)r[s].y[o]=Fc(a,r[s].x)}return r}function Vc(e){if(e.length<2)throw new Error("need at least 2 shares to reconstruct");let t=e[0].y.length;for(let o of e){if(o.y.length!==t)throw new Error("shares have inconsistent length");if(o.x===0)throw new Error("share x must not be 0")}let n=new Set;for(let o of e){if(n.has(o.x))throw new Error(`duplicate share x=${o.x}`);n.add(o.x)}let r=new Uint8Array(t);for(let o=0;o<t;o++){let a=0;for(let i=0;i<e.length;i++){let s=1,c=1;for(let u=0;u<e.length;u++)i!==u&&(s=zt(s,e[u].x),c=zt(c,e[i].x^e[u].x));let d=Lc(s,c);a=Jo(a,zt(e[i].y[o],d))}r[o]=a}return r}var Gc=e=>{if(typeof Buffer<"u")return Buffer.from(e).toString("base64");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)},qc=e=>{if(typeof Buffer<"u")return new Uint8Array(Buffer.from(e,"base64"));let t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n};function Wc(e){return{x:e.x,y_b64:Gc(e.y)}}function Jc(e){return{x:e.x,y:qc(e.y_b64)}}});var Qo=N(we=>{"use strict";Object.defineProperty(we,"__esModule",{value:!0});we.SegmentError=void 0;we.sealSegments=Qc;we.openSegments=el;we.manifestDigest=tl;we.buildCapability=nl;var lr=T("@noble/hashes/sha2.js"),zc="pq-hybrid-segments",Yc="AES-256-GCM",Ze=e=>e,Yo=e=>{if(typeof Buffer<"u")return Buffer.from(e).toString("base64");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)},Xo=e=>{if(typeof Buffer<"u")return new Uint8Array(Buffer.from(e,"base64"));let t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n},Zo=e=>{let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t};async function Xc(e,t,n){let r=await crypto.subtle.importKey("raw",Ze(e),{name:"AES-GCM"},!1,["encrypt"]),o=await crypto.subtle.encrypt({name:"AES-GCM",iv:Ze(t)},r,Ze(n));return new Uint8Array(o)}async function Zc(e,t,n){let r=await crypto.subtle.importKey("raw",Ze(e),{name:"AES-GCM"},!1,["decrypt"]),o=await crypto.subtle.decrypt({name:"AES-GCM",iv:Ze(t)},r,Ze(n));return new Uint8Array(o)}var $e=class extends Error{constructor(t,n){super(n),this.name="SegmentError",this.code=t}};we.SegmentError=$e;async function Qc(e){let t=new Set;for(let o of e){if(t.has(o.segment_id))throw new $e("duplicate_segment_id",`segment_id '${o.segment_id}' appears twice`);t.add(o.segment_id)}let n=[],r=[];for(let o of e){let a=crypto.getRandomValues(new Uint8Array(32)),i=crypto.getRandomValues(new Uint8Array(12)),s=await Xc(a,i,o.plaintext),c=s.slice(0,s.length-16),d=Zo((0,lr.sha256)(c));n.push({segment_id:o.segment_id,key:a}),r.push({segment_id:o.segment_id,label:o.label,content_type:o.content_type,iv_b64:Yo(i),ciphertext_b64:Yo(s),ciphertext_sha256:d})}return{manifest:{profile:zc,aead:Yc,segments:r},keys:n}}async function el(e,t){let n=new Map;for(let o of t.keys)n.set(o.segment_id,o.key);let r=[];for(let o of e.segments){if(!t.allowed_segment_ids.includes(o.segment_id))continue;let a=n.get(o.segment_id);if(!a)throw new $e("key_missing",`capability lists ${o.segment_id} as allowed but holds no key for it`);let i=Xo(o.ciphertext_b64),s=i.slice(0,i.length-16);if(Zo((0,lr.sha256)(s))!==o.ciphertext_sha256)throw new $e("integrity_mismatch",`segment ${o.segment_id}: ciphertext sha256 mismatch`);let d=Xo(o.iv_b64),u=await Zc(a,d,i);r.push({segment_id:o.segment_id,label:o.label,content_type:o.content_type,plaintext:u})}return r}function tl(e){let t=e.segments.map(r=>({id:r.segment_id,h:r.ciphertext_sha256})),n=JSON.stringify({profile:e.profile,aead:e.aead,segments:t});return(0,lr.sha256)(new TextEncoder().encode(n))}function nl(e,t,n){let r=new Set(t),o=n.filter(a=>r.has(a.segment_id));if(o.length!==t.length){let a=t.filter(i=>!o.find(s=>s.segment_id===i));throw new $e("segment_not_found",`cannot build capability \u2014 no key for: ${a.join(", ")}`)}return{recipient_kid:e,allowed_segment_ids:t,keys:o}}});var na=N(wt=>{"use strict";Object.defineProperty(wt,"__esModule",{value:!0});wt.computeWatermark=ta;wt.findLeakSource=al;wt.watermarkSvgOverlay=il;var rl=T("@noble/hashes/hmac.js"),ol=T("@noble/hashes/sha2.js");function ta(e){let t=[e.recipientId,e.lockboxId,String(e.openCount),String(e.iat)].join("|"),n=(0,rl.hmac)(ol.sha256,e.tenantSecret,new TextEncoder().encode(t)),r=ea(n.slice(0,16)),o=ea(n.slice(0,4)),a=new Date(e.iat*1e3).toISOString().slice(0,10),i=`${e.recipientId} \xB7 ${a} \xB7 ${o}`;return{short_hex:o,full_hex:r,display_label:i}}function al(e,t,n){let r=e.toLowerCase();for(let o of n){let a=ta({tenantSecret:t,...o});if(r===a.full_hex)return{matched:!0,candidate:o,matched_on:"full_hex"};if(r===a.short_hex)return{matched:!0,candidate:o,matched_on:"short_hex"}}return{matched:!1,reason:"no_candidate_matched"}}function il(e,t){let n=t?.width??800,r=t?.height??1e3,o=t?.opacity??.1,i=(s=>s.replace(/[<>&"]/g,c=>({"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;"})[c]))(e.display_label);return`<svg xmlns="http://www.w3.org/2000/svg" width="${n}" height="${r}" pointer-events="none">
9
+ <g fill="#000" opacity="${o}" font-family="Helvetica, Arial, sans-serif" font-size="20" text-anchor="middle">
10
+ <text x="${n/2}" y="${r*.2}" transform="rotate(-30 ${n/2} ${r*.2})">${i}</text>
11
+ <text x="${n/2}" y="${r*.5}" transform="rotate(-30 ${n/2} ${r*.5})">${i}</text>
12
+ <text x="${n/2}" y="${r*.8}" transform="rotate(-30 ${n/2} ${r*.8})">${i}</text>
13
+ </g>
14
+ <text x="${n-12}" y="${r-8}" font-family="monospace" font-size="10" fill="#000" opacity="${o*2}" text-anchor="end">${e.short_hex}</text>
15
+ </svg>`}function ea(e){let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t}});var la=N(q=>{"use strict";Object.defineProperty(q,"__esModule",{value:!0});q.DRAND_LOE_MAINNET=q.TimeGateError=void 0;q.timeGateEncrypt=sl;q.timeGateDecrypt=cl;q.roundForTime=ll;q.timeForRound=dl;q.drandTimeLockEncrypt=pl;q.drandTimeLockDecrypt=sa;q.makeFakeDrandChain=fl;q.fetchDrandRound=ca;q.drandTimeLockOpen=yl;var le=T("@noble/curves/bls12-381.js"),Zt=T("@noble/hashes/sha2.js"),ve=e=>e,oa="NDC-v0.3-server-time-gate";async function sl(e){let t=crypto.getRandomValues(new Uint8Array(12)),n=new TextEncoder().encode(`${oa}|${e.notBeforeUnixSec}`),r=await crypto.subtle.importKey("raw",ve(e.serverWrapKey),{name:"AES-GCM"},!1,["encrypt"]),o=await crypto.subtle.encrypt({name:"AES-GCM",iv:ve(t),additionalData:ve(n)},r,ve(e.plaintext));return{variant:"server-attested",notBeforeUnixSec:e.notBeforeUnixSec,iv_b64:Yt(t),ciphertext_b64:Yt(new Uint8Array(o))}}var vt=class extends Error{constructor(t,n){super(n),this.name="TimeGateError",this.code=t}};q.TimeGateError=vt;async function cl(e){if(e.currentUnixSec<e.ciphertext.notBeforeUnixSec)throw new vt("not_yet",`time-gate not yet open: now ${e.currentUnixSec} < notBefore ${e.ciphertext.notBeforeUnixSec}`);let t=new TextEncoder().encode(`${oa}|${e.ciphertext.notBeforeUnixSec}`),n=await crypto.subtle.importKey("raw",ve(e.serverWrapKey),{name:"AES-GCM"},!1,["decrypt"]);try{let r=await crypto.subtle.decrypt({name:"AES-GCM",iv:ve(Xt(e.ciphertext.iv_b64)),additionalData:ve(t)},n,ve(Xt(e.ciphertext.ciphertext_b64)));return new Uint8Array(r)}catch{throw new vt("tamper_detected","AES-GCM authentication tag failed \u2014 ciphertext or AAD tampered")}}q.DRAND_LOE_MAINNET={publicKeyHex:"868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31",chainHashHex:"8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce",genesisUnixSec:1595431050,periodSec:30,hashDst:"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"};function ll(e,t){return e<=t.genesisUnixSec?1:Math.ceil((e-t.genesisUnixSec)/t.periodSec)}function dl(e,t){return t.genesisUnixSec+e*t.periodSec}function aa(e){let t=new Uint8Array(8),n=e;for(let r=7;r>=0;r--)t[r]=n&255,n=Math.floor(n/256);return(0,Zt.sha256)(t)}function ia(e){let t=new Uint8Array(576),n=0;for(let r of[e.c0,e.c1])for(let o of[r.c0,r.c1,r.c2])for(let a of[o.c0,o.c1])ul(a,t,n,48),n+=48;return t}function ul(e,t,n,r){let o=e,a=BigInt(255),i=BigInt(8);for(let s=r-1;s>=0;s--)t[n+s]=Number(o&a),o>>=i}function pl(e,t,n,r){if(e.length!==32)throw new Error(`drand-IBE expects a 32-byte content key, got ${e.length}`);let o=le.bls12_381.G1.Point,a=le.bls12_381.fields.Fr,i=o.fromBytes(n),s;do s=ml(crypto.getRandomValues(new Uint8Array(32)))%a.ORDER;while(s===BigInt(0));let c=o.BASE.multiply(s),d=le.bls12_381.longSignatures.hash(aa(t),r.hashDst),u=i.multiply(s),p=le.bls12_381.pairing(u,d,!0),f=(0,Zt.sha256)(ia(p)),y=new Uint8Array(32);for(let b=0;b<32;b++)y[b]=e[b]^f[b];return{variant:"drand-ibe",chainHashHex:r.chainHashHex,round:t,u_b64:Yt(c.toBytes()),v_b64:Yt(y)}}function sa(e){if(e.ciphertext.variant!=="drand-ibe")throw new Error("not a drand-IBE ciphertext");if(e.ciphertext.chainHashHex!==e.chain.chainHashHex)throw new Error("chain hash mismatch \u2014 ciphertext sealed to a different drand chain");let n=le.bls12_381.G1.Point.fromBytes(Xt(e.ciphertext.u_b64)),r=le.bls12_381.longSignatures.Signature.fromBytes(e.roundSignature),o=le.bls12_381.pairing(n,r,!0),a=(0,Zt.sha256)(ia(o)),i=Xt(e.ciphertext.v_b64);if(i.length!==32)throw new Error("drand-IBE V must be 32 bytes");let s=new Uint8Array(32);for(let c=0;c<32;c++)s[c]=i[c]^a[c];return s}function fl(e){let t;if(e&&e.length===48)t=e;else{t=new Uint8Array(48);let a=e??crypto.getRandomValues(new Uint8Array(48));t.set(a.slice(0,48),0)}let{secretKey:n,publicKey:r}=le.bls12_381.longSignatures.keygen(t),o={publicKeyHex:ra(r.toBytes()),chainHashHex:ra((0,Zt.sha256)(r.toBytes())),genesisUnixSec:17e8,periodSec:30,hashDst:"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"};return{config:o,publicKey:r.toBytes(),signRound(a){let i=le.bls12_381.longSignatures.hash(aa(a),o.hashDst);return le.bls12_381.longSignatures.sign(i,n).toBytes()}}}function ra(e){let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t}function hl(e){if(e.length%2!==0)throw new Error("hex must have even length");let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}async function ca(e,t,n={}){let r=n.fetchImpl??fetch,o=n.timeoutMs??8e3,a=`${t.replace(/\/$/,"")}/public/${e}`,i,s;typeof AbortController<"u"&&(i=new AbortController,s=setTimeout(()=>i.abort(),o));let c;try{c=await r(a,{signal:i?.signal})}finally{s&&clearTimeout(s)}if(!c.ok)throw new Error(`drand fetch failed: ${a} \u2192 HTTP ${c.status}`);let d=await c.json();if(typeof d.round!="number"||typeof d.signature!="string"||typeof d.randomness!="string")throw new Error(`drand response malformed at ${a}`);let u=hl(d.signature);if(u.length!==96)throw new Error(`drand signature wrong length: expected 96 bytes (compressed G2), got ${u.length}`);return{round:d.round,randomness_hex:d.randomness,signature_bytes:u,previous_signature_hex:d.previous_signature}}async function yl(e,t,n,r={}){let o=await ca(e.round,t,r);return sa({ciphertext:e,roundSignature:o.signature_bytes,chain:n})}function Yt(e){if(typeof Buffer<"u")return Buffer.from(e).toString("base64");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function Xt(e){if(typeof Buffer<"u")return new Uint8Array(Buffer.from(e,"base64"));let t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n}function ml(e){let t=BigInt(0),n=BigInt(8);for(let r=0;r<e.length;r++)t=t<<n|BigInt(e[r]);return t}});var ha=N(te=>{"use strict";Object.defineProperty(te,"__esModule",{value:!0});te.GENESIS_PREV_HASH=void 0;te.receiptHash=ur;te.issueReceipt=pr;te.verifyReceipt=fa;te.auditChain=bl;te.issueGenesisReceipt=Sl;te.appendReceipt=wl;var gl=T("@noble/hashes/sha2.js"),dr=Ht(),pa=We();te.GENESIS_PREV_HASH="0".repeat(64);var da=e=>{if(typeof Buffer<"u")return Buffer.from(e).toString("base64");let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)},ua=e=>{if(typeof Buffer<"u")return new Uint8Array(Buffer.from(e,"base64"));let t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n},_l=e=>{let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t};function ur(e){return _l((0,gl.sha256)(new TextEncoder().encode((0,dr.canonicalJson)(e))))}function pr(e){let t={event_type:e.event_type,sequence:e.sequence,iat:e.iat??new Date().toISOString(),lockbox_id:e.lockbox_id,prev_hash:e.prev_hash,payload:e.payload},n=new TextEncoder().encode((0,dr.canonicalJson)(t)),r=(0,pa.hybridSign)(e.signing_key.secretKey,n);return{body:t,sig:{signer_kid:e.signer_kid,ed25519_b64:da(r.ed25519),ml_dsa_65_b64:da(r.mlDsa)}}}function fa(e,t){let n=new TextEncoder().encode((0,dr.canonicalJson)(e.body)),r={ed25519:ua(e.sig.ed25519_b64),mlDsa:ua(e.sig.ml_dsa_65_b64)};return(0,pa.hybridVerify)(t,n,r)}function bl(e,t,n=1){if(e.length===0)return{ok:!0,receipts_checked:0};let r=n,o=n===1?te.GENESIS_PREV_HASH:null;for(let a of e){if(a.body.sequence!==r)return{ok:!1,code:a.body.sequence<r?"duplicate_sequence":"out_of_order",at_sequence:a.body.sequence,reason:`expected sequence ${r}, got ${a.body.sequence}`};if(o!==null&&a.body.prev_hash!==o)return{ok:!1,code:r===1?"missing_genesis":"broken_prev_hash",at_sequence:a.body.sequence,reason:`prev_hash mismatch: expected ${o.slice(0,16)}\u2026, got ${a.body.prev_hash.slice(0,16)}\u2026`};if(!fa(a,t))return{ok:!1,code:"bad_signature",at_sequence:a.body.sequence,reason:"hybrid signature does not verify"};o=ur(a.body),r+=1}return{ok:!0,receipts_checked:e.length}}function Sl(e){return pr({event_type:e.initial_event,lockbox_id:e.lockbox_id,prev_hash:te.GENESIS_PREV_HASH,sequence:1,payload:e.initial_payload,signer_kid:e.signer_kid,signing_key:e.signing_key,iat:e.iat})}function wl(e,t){return pr({...t,prev_hash:ur(e.body),sequence:e.body.sequence+1})}});var ma=N(Qt=>{"use strict";Object.defineProperty(Qt,"__esModule",{value:!0});Qt.recommend=Tl;Qt.summarise=Pl;var vl={healthcare:{mode:"mode-4h",ttlSeconds:3600,forensicWatermark:!0,teeAttestation:!0,rationale:"HIPAA \xB7 BAA \xB7 per-recipient attribution required"},insurance:{mode:"mode-4",ttlSeconds:28800,forensicWatermark:!0,teeAttestation:!1,rationale:"Adjusters need offline access during field visits"},bank:{mode:"mode-4h",ttlSeconds:3600,forensicWatermark:!0,teeAttestation:!1,rationale:"SOX \xB7 per-open audit \xB7 forward secrecy on signed mandates"},legal:{mode:"mode-4p",ttlSeconds:86400,forensicWatermark:!0,teeAttestation:!1,rationale:"Client privilege \xB7 approval-quorum patterns common"},government:{mode:"mode-4h",ttlSeconds:3600,forensicWatermark:!0,teeAttestation:!0,rationale:"Classified \xB7 per-open attestation \xB7 k-of-N release"},media:{mode:"mode-4p",ttlSeconds:604800,forensicWatermark:!0,teeAttestation:!1,rationale:"Source protection \xB7 leak attribution \xB7 light verification UX"},hr:{mode:"mode-4",ttlSeconds:86400,forensicWatermark:!0,teeAttestation:!1,rationale:"Performance reviews \xB7 separation packages \xB7 low compliance"},smb:{mode:"mode-4",ttlSeconds:604800,forensicWatermark:!1,teeAttestation:!1,rationale:"Cost-sensitive \xB7 low compliance overhead"}},El={"medical-phi":{minMode:"mode-4h",maxTtlSeconds:3600,watermarkRequired:!0,selectiveDisclosure:!0,thresholdSuggested:!1,teeRequired:!0},"financial-statements":{minMode:"mode-4",maxTtlSeconds:28800,watermarkRequired:!0,selectiveDisclosure:!0,thresholdSuggested:!0,teeRequired:!1},"identity-documents":{minMode:"mode-4h",maxTtlSeconds:3600,watermarkRequired:!0,selectiveDisclosure:!0,thresholdSuggested:!1,teeRequired:!0},"legal-contracts":{minMode:"mode-4p",maxTtlSeconds:86400,watermarkRequired:!0,selectiveDisclosure:!0,thresholdSuggested:!0,teeRequired:!1},"board-materials":{minMode:"mode-4p",maxTtlSeconds:86400,watermarkRequired:!0,selectiveDisclosure:!0,thresholdSuggested:!0,teeRequired:!1},"source-code":{minMode:"mode-4h",maxTtlSeconds:3600,watermarkRequired:!0,selectiveDisclosure:!0,thresholdSuggested:!1,teeRequired:!0},marketing:{minMode:"mode-4",maxTtlSeconds:604800,watermarkRequired:!1,selectiveDisclosure:!1,thresholdSuggested:!1,teeRequired:!1},"internal-memo":{minMode:"mode-4",maxTtlSeconds:86400,watermarkRequired:!1,selectiveDisclosure:!1,thresholdSuggested:!1,teeRequired:!1},"live-ops-data":{minMode:"mode-4",maxTtlSeconds:86400,watermarkRequired:!1,selectiveDisclosure:!1,thresholdSuggested:!1,teeRequired:!1}},kl={email:{deliveryMode:"attachment",adapters:["gmail","outlook","smtp"],notes:[]},chat:{deliveryMode:"link",adapters:["whatsapp","telegram","slack","teams"],notes:["Send the ndc:// link only; file bytes never traverse the chat provider"]},"cloud-share":{deliveryMode:"link",adapters:["drive","sharepoint","dropbox","box"],notes:[]},sftp:{deliveryMode:"attachment",adapters:["sftp","ftps"],notes:["Legacy partners often require this"]},sms:{deliveryMode:"link",adapters:["sms-short-link"],notes:["Link only; SMS cannot carry binary"]},voice:{deliveryMode:"link",adapters:["voice-readback"],notes:["Voice carries the unlock factor, not the content"]},"web-portal":{deliveryMode:"link",adapters:["web-portal-pickup","embed-iframe"],notes:[]},"qr-physical":{deliveryMode:"in-person",adapters:["qr-code","usb-handoff","airdrop"],notes:["Recipient must scan / plug in physically"]},webhook:{deliveryMode:"attachment",adapters:["webhook-push"],notes:["B2B server-to-server only"]}},xl=[{channel:"chat",fileClass:"medical-phi",note:"PHI over chat \u2192 link only; never attach the bytes"},{channel:"chat",fileClass:"identity-documents",note:"ID documents over chat \u2192 link only"},{channel:"chat",fileClass:"legal-contracts",note:"Legal contracts over chat are discouraged; use email/portal"},{channel:"chat",fileClass:"board-materials",note:"Board materials over chat are discouraged; use email/portal"},{channel:"chat",fileClass:"source-code",note:"Source code over chat is discouraged; use cloud-share/portal"},{channel:"cloud-share",fileClass:"identity-documents",note:"ID documents on cloud share discouraged; prefer email or portal"},{channel:"sms",fileClass:"medical-phi",note:"PHI over SMS is not compliant; reroute to web-portal"},{channel:"voice",fileClass:"medical-phi",note:"Voice only carries the unlock; the bytes must travel another channel"}],ya={"mode-4":1,"mode-4p":2,"mode-4h":3,"mode-6":4};function Al(e,t){return ya[e]>=ya[t]?e:t}function Tl(e){let t=vl[e.orgType],n=El[e.fileClass],r=kl[e.channel],o=Al(t.mode,n.minMode);e.recipientLacksPasskey&&o==="mode-4h"&&(o="mode-4p");let a=Math.min(t.ttlSeconds,n.maxTtlSeconds),i={forensicWatermark:t.forensicWatermark||n.watermarkRequired,selectiveDisclosureSegments:n.selectiveDisclosure||!!e.perRecipientPolicy,thresholdKofN:e.multipleApproversRequired??null,teeAttestation:t.teeAttestation||n.teeRequired,perOpenRatchet:o==="mode-4h"||o==="mode-4p"||o==="mode-6",dpopRequired:o!=="mode-4",timelockDrand:!!e.timeLockUnixSec&&!!e.timeLockDecentralized,timelockServerGate:!!e.timeLockUnixSec&&!e.timeLockDecentralized},s={...r,adapterCandidates:[...r.adapters]},c=[...s.notes],d=xl.find(u=>u.channel===e.channel&&u.fileClass===e.fileClass);return d&&(c.unshift(`\u26A0 ${d.note}`),s.deliveryMode==="attachment"&&(s.deliveryMode="link")),e.fileClass==="live-ops-data"&&e.channel==="email"&&c.push("Live ops data over email is non-standard; consider webhook-push or web-portal."),{sensitivityMode:o,cacheTtlSeconds:a,features:i,delivery:{deliveryMode:s.deliveryMode,adapterCandidates:s.adapterCandidates},notes:c}}function Pl(e){let t=[e.sensitivityMode,`TTL ${e.cacheTtlSeconds}s`];return e.features.forensicWatermark&&t.push("watermark"),e.features.selectiveDisclosureSegments&&t.push("segments"),e.features.thresholdKofN&&t.push(`threshold ${e.features.thresholdKofN.k}-of-${e.features.thresholdKofN.n}`),e.features.teeAttestation&&t.push("TEE"),e.features.perOpenRatchet&&t.push("ratchet"),e.features.dpopRequired&&t.push("DPoP"),e.features.timelockDrand?t.push("drand-tlock"):e.features.timelockServerGate&&t.push("server-timegate"),t.push(`via ${e.delivery.deliveryMode} (${e.delivery.adapterCandidates.join("/")})`),t.join(" \xB7 ")}});var _a=N(Qe=>{"use strict";Object.defineProperty(Qe,"__esModule",{value:!0});Qe.recommendationToMandate=Cl;Qe.v3SealReceiptPayload=Rl;Qe.v3OpenReceiptPayload=$l;Qe.showcaseChips=Bl;function Dl(e){switch(e){case"mode-4":return"name_email";case"mode-4p":return"name_email";case"mode-4h":return"hardware_attest";case"mode-6":return"name_email_phone"}}function Ol(e){return e.features.dpopRequired?"device_mfa":e.sensitivityMode==="mode-4h"?"first_device":e.sensitivityMode==="mode-4"?"any":"first_device"}function Il(e){return e.delivery.deliveryMode==="attachment"?"file":e.delivery.deliveryMode==="link"?"link":"view_only"}function ga(e){let t=e.delivery.adapterCandidates;return t.some(n=>n==="outlook"||n==="sharepoint"||n==="teams")?"m365":t.some(n=>n==="webhook-push"||n==="web-portal-pickup"||n==="embed-iframe")?"in_app":"capsule"}function Nl(e){let t=ga(e);return t==="m365"?"m365_only":t==="in_app"?"in_app":"any"}function Cl(e){let{recommendation:t,source:n}=e,r=t.sensitivityMode==="mode-6",o=n.timeLockUnixSec?new Date(n.timeLockUnixSec*1e3).toISOString():null;return{time:{ttl_seconds:t.cacheTtlSeconds,burn_after_first_read:r,unlock_at:o,max_opens:r?1:null},identity:{capture:Dl(t.sensitivityMode),claim_required:t.sensitivityMode!=="mode-4",allow_magic_link:t.sensitivityMode==="mode-4",allowed_emails:null},device:{binding:Ol(t),listed_fingerprints:null},channel:{delivery:Il(t),route:ga(t),channel_constraint:Nl(t)},burn:{crypto_shred_on_burn:!0,mdm_wipe_webhook:!1,undo_window_s:0,dual_control:!!t.features.thresholdKofN},encrypt:{mode:"hpke",vault_mirror:t.features.teeAttestation,scoped_key_release:!0},proof:{signing:"ed25519",anchor:t.features.teeAttestation?"rekor":"none",c2pa_in_file:!1,ndc_seal:!0},watermark:{visible:t.features.forensicWatermark,forensic:t.features.forensicWatermark,content:t.features.forensicWatermark?"recipient_id":null,custom_text:null,forensics_lookup:t.features.forensicWatermark},ndc_v3_extensions:{profile:"pq-hybrid",suite:{kem:"X25519+ML-KEM-768",sig:"Ed25519+ML-DSA-65",aead:"AES-256-GCM",kdf:"HKDF-SHA-256"},dpop_required:t.features.dpopRequired,ratchet_enabled:t.features.perOpenRatchet,tee_attestation_required:t.features.teeAttestation,threshold_k_of_n:t.features.thresholdKofN,segments_enabled:t.features.selectiveDisclosureSegments,timelock_drand:t.features.timelockDrand,timelock_server_gate:t.features.timelockServerGate,timelock_unix_sec:n.timeLockUnixSec??null}}}function Rl(e){return{event_kind:"ndc_v3_sealed",lockbox_id:e.lockbox_id,ciphertext_sha256:e.ciphertext_sha256,recipient_kid:e.recipient_kid,signer_kid:e.signer_kid,mandate:e.mandate,bytes_sealed:e.bytes_sealed,issued_at:e.issued_at??new Date().toISOString()}}function $l(e){return{event_kind:"ndc_v3_opened",lockbox_id:e.lockbox_id,ratchet_sequence:e.ratchet_sequence,dpop_jkt:e.dpop_jkt,ip_hash:e.ip_hash,opened_at:e.opened_at??new Date().toISOString()}}function Bl(e){let t=[],n=e.ndc_v3_extensions;return t.push("PQ-hybrid"),n.dpop_required&&t.push("DPoP"),n.ratchet_enabled&&t.push("per-open ratchet"),e.watermark.forensic&&t.push("forensic watermark"),n.segments_enabled&&t.push("selective disclosure"),n.threshold_k_of_n&&t.push(`${n.threshold_k_of_n.k}-of-${n.threshold_k_of_n.n} quorum`),n.tee_attestation_required&&t.push("TEE attest"),n.timelock_drand?t.push("drand time-lock"):n.timelock_server_gate&&t.push("server time-gate"),e.time.burn_after_first_read&&t.push("burn-after-read"),t}});var Ea=N(de=>{"use strict";Object.defineProperty(de,"__esModule",{value:!0});de.encodeFragment=va;de.decodeFragment=Kl;de.extractProofToken=jl;de.encodeProofToken=Ml;de.decodeShareCredential=Ll;de.sealBytesForPublicShare=Hl;de.openPublicShare=Vl;de.wrapFragmentForShortLink=Gl;var ba=We(),Sa=Ht();function Ee(e){let t="";for(let n=0;n<e.length;n++)t+=String.fromCharCode(e[n]);return btoa(t)}function Et(e){let t=atob(e),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n}function wa(e){return Ee(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function va(e){return encodeURIComponent(JSON.stringify(e))}function Kl(e){let t=JSON.parse(decodeURIComponent(e));if(t.v!==3)throw new Error(`fragment version unsupported: ${t.v}`);return t}function jl(e){return{v:3,kind:"proof",n:e.n,t:e.t,spe:e.spe,spm:e.spm}}function Ml(e){return encodeURIComponent(JSON.stringify(e))}function Ll(e){let t=e.trim(),n=t.indexOf("#"),r=n>=0?t.slice(n+1):t,o;try{o=JSON.parse(decodeURIComponent(r))}catch(a){throw new Error(`credential parse failed: ${a.message??"invalid_json"}`)}if(o.v!==3)throw new Error(`credential version unsupported: ${String(o.v)}`);return o.kind==="proof"?{kind:"proof",value:o}:{kind:"fragment",value:o}}function Fl(){let e=new Uint8Array(16);crypto.getRandomValues(e);let t="";for(let n=0;n<e.length;n++)t+=e[n].toString(16).padStart(2,"0");return t}function Ul(){let e=new Uint8Array(32);return crypto.getRandomValues(e),wa(e)}async function Hl(e){let t=e.bytes,n={name:e.filename,type:e.contentType},r=(0,ba.generateHybridKemKeypair)(),o=(0,ba.generateHybridSigKeypair)(),a=Fl(),i=Ul(),s=await(0,Sa.sealHybrid)({plaintext:t,recipientPublicKey:r.publicKey,recipientKid:`ephemeral-${a}`,signerKeypair:o,signerKid:`lock-${a}`,meta:{lockbox_id:a,server:e.server,bearer:i,original_filename:n.name,original_content_type:n.type||"application/octet-stream",cache_ttl_seconds:e.ttlSeconds,dpop_required:!1,tee_attestation_url:null,ratchet_state:null}}),c=va({v:3,n:n.name,t:n.type||"application/octet-stream",rsx:Ee(r.secretKey.x25519),rsm:Ee(r.secretKey.mlKem),rpx:Ee(r.publicKey.x25519),spe:Ee(o.publicKey.ed25519),spm:Ee(o.publicKey.mlDsa)});return{container:s.container,fragment:c,lockboxId:a}}async function Vl(e){let t={x25519:Et(e.fragment.rsx),mlKem:Et(e.fragment.rsm)},n=Et(e.fragment.rpx),r={ed25519:Et(e.fragment.spe),mlDsa:Et(e.fragment.spm)},{plaintext:o,header:a}=await(0,Sa.openHybrid)({container:e.container,recipientSecretKey:t,recipientPublicX25519:n,signerPublicKey:r});return{plaintext:o,filename:a.original_filename||e.fragment.n,contentType:a.original_content_type||e.fragment.t,signerKid:a.sig.signer_kid,issuedAt:a.issued_at,ciphertextSha256:a.ciphertext_sha256}}async function Gl(e){let t=crypto.getRandomValues(new Uint8Array(32)),n=crypto.getRandomValues(new Uint8Array(12)),r=new TextEncoder().encode(e),o=new ArrayBuffer(32);new Uint8Array(o).set(t);let a=new ArrayBuffer(12);new Uint8Array(a).set(n);let i=new ArrayBuffer(r.byteLength);new Uint8Array(i).set(r);let s=await crypto.subtle.importKey("raw",o,{name:"AES-GCM"},!1,["encrypt"]),c=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:a},s,i));return{wrapKeyB64Url:wa(t),wrappedFragmentB64:Ee(c),wrapIvB64:Ee(n)}}});var Ta=N(l=>{"use strict";var ql=l&&l.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(l,"__esModule",{value:!0});l.PVE_SIGNED_LEN=l.RCPT_VERSION=l.PVE_VERSION=l.RCPT_MAGIC=l.PVE_MAGIC=l.verifyDpop=l.publicJwkFromBytes=l.jwkThumbprint=l.createDpop=l.verifyContainerHeader=l.signContainerHeader=l.sealHybrid=l.openHybrid=l.headerSigningBytes=l.encodeContainerV3=l.decodeContainerV3=l.ContainerV3Error=l.CONTAINER_HEADER_MAX_BYTES=l.CONTAINER_FIXED_PREFIX_BYTES=l.CONTAINER_MAGIC=l.canonicalJson=l.NDC_V03_RATCHET_DOMAIN=l.NDC_V03_CONTENT_KEY_DOMAIN=l.NDC_V03_KEM_DOMAIN=l.NDC_WIRE_V03=l.NDC_WIRE_V1=l.PQ_SIZES=l.PQ_SUITE=l.ratchetAdvance=l.deriveContentKey=l.mlDsa65VerifyDetached=l.mlDsa65SignDetached=l.generateMlDsa65Keypair=l.hybridVerify=l.hybridSign=l.hybridKemDecapsulate=l.hybridKemEncapsulate=l.generateHybridSigKeypair=l.deriveHybridKemKeypairFromSeed=l.generateHybridKemKeypair=l.ALGORITHMS=l.CRYPTO_VERSION=l.NoDataSDK=l.NoDataForms=l.NoDataSystems=l.NoDataWebhook=l.NoDataEmail=l.verifyProofOfWork=l.solveProofOfWork=l.NoDataCrypto=void 0;l.auditChain=l.appendReceipt=l.timeGateEncrypt=l.timeGateDecrypt=l.timeForRound=l.TimeGateError=l.roundForTime=l.makeFakeDrandChain=l.fetchDrandRound=l.drandTimeLockOpen=l.drandTimeLockEncrypt=l.drandTimeLockDecrypt=l.DRAND_LOE_MAINNET=l.watermarkSvgOverlay=l.findLeakSource=l.computeWatermark=l.SegmentError=l.sealSegments=l.openSegments=l.manifestDigest=l.buildCapability=l.splitSecret=l.serializeShare=l.deserializeShare=l.combineShares=l.decodeAttestationPayload=l.verifyCoseSign1Es384=l.verifyAttestation=l.parseAttestation=l.fetchAttestation=l.stepRatchet=l.replayRatchet=l.destroyKey=l.verifyReceiptDelta=l.parseReceiptDelta=l.signReceiptDelta=l.encodeReceiptDeltaSignedBytes=l.verifyPve=l.pveHash=l.parsePve=l.signPve=l.encodePveSignedBytes=l.originJktForPublicKey=l.uuidFromDeltaId=l.deltaIdFromUuid=l.ABSORB_STATUS=l.DELTA_KIND=l.RCPT_TOTAL_LEN=l.RCPT_SIGNED_LEN=l.PVE_TOTAL_LEN=void 0;l.wrapFragmentForShortLink=l.openPublicShare=l.sealBytesForPublicShare=l.decodeShareCredential=l.encodeProofToken=l.extractProofToken=l.decodeFragment=l.encodeFragment=l.v3SealReceiptPayload=l.v3OpenReceiptPayload=l.showcaseChips=l.recommendationToMandate=l.summarise=l.recommend=l.verifyReceipt=l.receiptHash=l.issueReceipt=l.issueGenesisReceipt=l.GENESIS_PREV_HASH=void 0;var Wl=Oe();Object.defineProperty(l,"NoDataCrypto",{enumerable:!0,get:function(){return ql(Wl).default}});var ka=_o();Object.defineProperty(l,"solveProofOfWork",{enumerable:!0,get:function(){return ka.solveProofOfWork}});Object.defineProperty(l,"verifyProofOfWork",{enumerable:!0,get:function(){return ka.verifyProofOfWork}});var kt=So();Object.defineProperty(l,"NoDataEmail",{enumerable:!0,get:function(){return kt.NoDataEmail}});Object.defineProperty(l,"NoDataWebhook",{enumerable:!0,get:function(){return kt.NoDataWebhook}});Object.defineProperty(l,"NoDataSystems",{enumerable:!0,get:function(){return kt.NoDataSystems}});Object.defineProperty(l,"NoDataForms",{enumerable:!0,get:function(){return kt.NoDataForms}});Object.defineProperty(l,"NoDataSDK",{enumerable:!0,get:function(){return kt.NoDataSDK}});l.CRYPTO_VERSION="0.2.0";l.ALGORITHMS={ENCRYPTION:"AES-256-GCM",KEY_EXCHANGE:"RSA-OAEP-4096",KEY_DERIVATION:"PBKDF2-SHA256-310K",SIGNING:"Ed25519",HASHING:"SHA-256",PROOF_OF_WORK:"SHA-256-NONCE"};var K=We();Object.defineProperty(l,"generateHybridKemKeypair",{enumerable:!0,get:function(){return K.generateHybridKemKeypair}});Object.defineProperty(l,"deriveHybridKemKeypairFromSeed",{enumerable:!0,get:function(){return K.deriveHybridKemKeypairFromSeed}});Object.defineProperty(l,"generateHybridSigKeypair",{enumerable:!0,get:function(){return K.generateHybridSigKeypair}});Object.defineProperty(l,"hybridKemEncapsulate",{enumerable:!0,get:function(){return K.hybridKemEncapsulate}});Object.defineProperty(l,"hybridKemDecapsulate",{enumerable:!0,get:function(){return K.hybridKemDecapsulate}});Object.defineProperty(l,"hybridSign",{enumerable:!0,get:function(){return K.hybridSign}});Object.defineProperty(l,"hybridVerify",{enumerable:!0,get:function(){return K.hybridVerify}});Object.defineProperty(l,"generateMlDsa65Keypair",{enumerable:!0,get:function(){return K.generateMlDsa65Keypair}});Object.defineProperty(l,"mlDsa65SignDetached",{enumerable:!0,get:function(){return K.mlDsa65SignDetached}});Object.defineProperty(l,"mlDsa65VerifyDetached",{enumerable:!0,get:function(){return K.mlDsa65VerifyDetached}});Object.defineProperty(l,"deriveContentKey",{enumerable:!0,get:function(){return K.deriveContentKey}});Object.defineProperty(l,"ratchetAdvance",{enumerable:!0,get:function(){return K.ratchetAdvance}});Object.defineProperty(l,"PQ_SUITE",{enumerable:!0,get:function(){return K.PQ_SUITE}});Object.defineProperty(l,"PQ_SIZES",{enumerable:!0,get:function(){return K.PQ_SIZES}});Object.defineProperty(l,"NDC_WIRE_V1",{enumerable:!0,get:function(){return K.NDC_WIRE_V1}});Object.defineProperty(l,"NDC_WIRE_V03",{enumerable:!0,get:function(){return K.NDC_WIRE_V03}});Object.defineProperty(l,"NDC_V03_KEM_DOMAIN",{enumerable:!0,get:function(){return K.NDC_V03_KEM_DOMAIN}});Object.defineProperty(l,"NDC_V03_CONTENT_KEY_DOMAIN",{enumerable:!0,get:function(){return K.NDC_V03_CONTENT_KEY_DOMAIN}});Object.defineProperty(l,"NDC_V03_RATCHET_DOMAIN",{enumerable:!0,get:function(){return K.NDC_V03_RATCHET_DOMAIN}});var ne=Ht();Object.defineProperty(l,"canonicalJson",{enumerable:!0,get:function(){return ne.canonicalJson}});Object.defineProperty(l,"CONTAINER_MAGIC",{enumerable:!0,get:function(){return ne.CONTAINER_MAGIC}});Object.defineProperty(l,"CONTAINER_FIXED_PREFIX_BYTES",{enumerable:!0,get:function(){return ne.CONTAINER_FIXED_PREFIX_BYTES}});Object.defineProperty(l,"CONTAINER_HEADER_MAX_BYTES",{enumerable:!0,get:function(){return ne.CONTAINER_HEADER_MAX_BYTES}});Object.defineProperty(l,"ContainerV3Error",{enumerable:!0,get:function(){return ne.ContainerV3Error}});Object.defineProperty(l,"decodeContainerV3",{enumerable:!0,get:function(){return ne.decodeContainerV3}});Object.defineProperty(l,"encodeContainerV3",{enumerable:!0,get:function(){return ne.encodeContainerV3}});Object.defineProperty(l,"headerSigningBytes",{enumerable:!0,get:function(){return ne.headerSigningBytes}});Object.defineProperty(l,"openHybrid",{enumerable:!0,get:function(){return ne.openHybrid}});Object.defineProperty(l,"sealHybrid",{enumerable:!0,get:function(){return ne.sealHybrid}});Object.defineProperty(l,"signContainerHeader",{enumerable:!0,get:function(){return ne.signContainerHeader}});Object.defineProperty(l,"verifyContainerHeader",{enumerable:!0,get:function(){return ne.verifyContainerHeader}});var en=nr();Object.defineProperty(l,"createDpop",{enumerable:!0,get:function(){return en.createDpop}});Object.defineProperty(l,"jwkThumbprint",{enumerable:!0,get:function(){return en.jwkThumbprint}});Object.defineProperty(l,"publicJwkFromBytes",{enumerable:!0,get:function(){return en.publicJwkFromBytes}});Object.defineProperty(l,"verifyDpop",{enumerable:!0,get:function(){return en.verifyDpop}});var $=Fo();Object.defineProperty(l,"PVE_MAGIC",{enumerable:!0,get:function(){return $.PVE_MAGIC}});Object.defineProperty(l,"RCPT_MAGIC",{enumerable:!0,get:function(){return $.RCPT_MAGIC}});Object.defineProperty(l,"PVE_VERSION",{enumerable:!0,get:function(){return $.PVE_VERSION}});Object.defineProperty(l,"RCPT_VERSION",{enumerable:!0,get:function(){return $.RCPT_VERSION}});Object.defineProperty(l,"PVE_SIGNED_LEN",{enumerable:!0,get:function(){return $.PVE_SIGNED_LEN}});Object.defineProperty(l,"PVE_TOTAL_LEN",{enumerable:!0,get:function(){return $.PVE_TOTAL_LEN}});Object.defineProperty(l,"RCPT_SIGNED_LEN",{enumerable:!0,get:function(){return $.RCPT_SIGNED_LEN}});Object.defineProperty(l,"RCPT_TOTAL_LEN",{enumerable:!0,get:function(){return $.RCPT_TOTAL_LEN}});Object.defineProperty(l,"DELTA_KIND",{enumerable:!0,get:function(){return $.DELTA_KIND}});Object.defineProperty(l,"ABSORB_STATUS",{enumerable:!0,get:function(){return $.ABSORB_STATUS}});Object.defineProperty(l,"deltaIdFromUuid",{enumerable:!0,get:function(){return $.deltaIdFromUuid}});Object.defineProperty(l,"uuidFromDeltaId",{enumerable:!0,get:function(){return $.uuidFromDeltaId}});Object.defineProperty(l,"originJktForPublicKey",{enumerable:!0,get:function(){return $.originJktForPublicKey}});Object.defineProperty(l,"encodePveSignedBytes",{enumerable:!0,get:function(){return $.encodePveSignedBytes}});Object.defineProperty(l,"signPve",{enumerable:!0,get:function(){return $.signPve}});Object.defineProperty(l,"parsePve",{enumerable:!0,get:function(){return $.parsePve}});Object.defineProperty(l,"pveHash",{enumerable:!0,get:function(){return $.pveHash}});Object.defineProperty(l,"verifyPve",{enumerable:!0,get:function(){return $.verifyPve}});Object.defineProperty(l,"encodeReceiptDeltaSignedBytes",{enumerable:!0,get:function(){return $.encodeReceiptSignedBytes}});Object.defineProperty(l,"signReceiptDelta",{enumerable:!0,get:function(){return $.signReceipt}});Object.defineProperty(l,"parseReceiptDelta",{enumerable:!0,get:function(){return $.parseReceipt}});Object.defineProperty(l,"verifyReceiptDelta",{enumerable:!0,get:function(){return $.verifyReceipt}});var fr=Ho();Object.defineProperty(l,"destroyKey",{enumerable:!0,get:function(){return fr.destroyKey}});Object.defineProperty(l,"replayRatchet",{enumerable:!0,get:function(){return fr.replayRatchet}});Object.defineProperty(l,"stepRatchet",{enumerable:!0,get:function(){return fr.stepRatchet}});var hr=qo();Object.defineProperty(l,"fetchAttestation",{enumerable:!0,get:function(){return hr.fetchAttestation}});Object.defineProperty(l,"parseAttestation",{enumerable:!0,get:function(){return hr.parseAttestation}});Object.defineProperty(l,"verifyAttestation",{enumerable:!0,get:function(){return hr.verifyAttestation}});var xa=cr();Object.defineProperty(l,"verifyCoseSign1Es384",{enumerable:!0,get:function(){return xa.verifyCoseSign1Es384}});Object.defineProperty(l,"decodeAttestationPayload",{enumerable:!0,get:function(){return xa.decodeAttestationPayload}});var tn=zo();Object.defineProperty(l,"combineShares",{enumerable:!0,get:function(){return tn.combineShares}});Object.defineProperty(l,"deserializeShare",{enumerable:!0,get:function(){return tn.deserializeShare}});Object.defineProperty(l,"serializeShare",{enumerable:!0,get:function(){return tn.serializeShare}});Object.defineProperty(l,"splitSecret",{enumerable:!0,get:function(){return tn.splitSecret}});var xt=Qo();Object.defineProperty(l,"buildCapability",{enumerable:!0,get:function(){return xt.buildCapability}});Object.defineProperty(l,"manifestDigest",{enumerable:!0,get:function(){return xt.manifestDigest}});Object.defineProperty(l,"openSegments",{enumerable:!0,get:function(){return xt.openSegments}});Object.defineProperty(l,"sealSegments",{enumerable:!0,get:function(){return xt.sealSegments}});Object.defineProperty(l,"SegmentError",{enumerable:!0,get:function(){return xt.SegmentError}});var yr=na();Object.defineProperty(l,"computeWatermark",{enumerable:!0,get:function(){return yr.computeWatermark}});Object.defineProperty(l,"findLeakSource",{enumerable:!0,get:function(){return yr.findLeakSource}});Object.defineProperty(l,"watermarkSvgOverlay",{enumerable:!0,get:function(){return yr.watermarkSvgOverlay}});var oe=la();Object.defineProperty(l,"DRAND_LOE_MAINNET",{enumerable:!0,get:function(){return oe.DRAND_LOE_MAINNET}});Object.defineProperty(l,"drandTimeLockDecrypt",{enumerable:!0,get:function(){return oe.drandTimeLockDecrypt}});Object.defineProperty(l,"drandTimeLockEncrypt",{enumerable:!0,get:function(){return oe.drandTimeLockEncrypt}});Object.defineProperty(l,"drandTimeLockOpen",{enumerable:!0,get:function(){return oe.drandTimeLockOpen}});Object.defineProperty(l,"fetchDrandRound",{enumerable:!0,get:function(){return oe.fetchDrandRound}});Object.defineProperty(l,"makeFakeDrandChain",{enumerable:!0,get:function(){return oe.makeFakeDrandChain}});Object.defineProperty(l,"roundForTime",{enumerable:!0,get:function(){return oe.roundForTime}});Object.defineProperty(l,"TimeGateError",{enumerable:!0,get:function(){return oe.TimeGateError}});Object.defineProperty(l,"timeForRound",{enumerable:!0,get:function(){return oe.timeForRound}});Object.defineProperty(l,"timeGateDecrypt",{enumerable:!0,get:function(){return oe.timeGateDecrypt}});Object.defineProperty(l,"timeGateEncrypt",{enumerable:!0,get:function(){return oe.timeGateEncrypt}});var Be=ha();Object.defineProperty(l,"appendReceipt",{enumerable:!0,get:function(){return Be.appendReceipt}});Object.defineProperty(l,"auditChain",{enumerable:!0,get:function(){return Be.auditChain}});Object.defineProperty(l,"GENESIS_PREV_HASH",{enumerable:!0,get:function(){return Be.GENESIS_PREV_HASH}});Object.defineProperty(l,"issueGenesisReceipt",{enumerable:!0,get:function(){return Be.issueGenesisReceipt}});Object.defineProperty(l,"issueReceipt",{enumerable:!0,get:function(){return Be.issueReceipt}});Object.defineProperty(l,"receiptHash",{enumerable:!0,get:function(){return Be.receiptHash}});Object.defineProperty(l,"verifyReceipt",{enumerable:!0,get:function(){return Be.verifyReceipt}});var Aa=ma();Object.defineProperty(l,"recommend",{enumerable:!0,get:function(){return Aa.recommend}});Object.defineProperty(l,"summarise",{enumerable:!0,get:function(){return Aa.summarise}});var nn=_a();Object.defineProperty(l,"recommendationToMandate",{enumerable:!0,get:function(){return nn.recommendationToMandate}});Object.defineProperty(l,"showcaseChips",{enumerable:!0,get:function(){return nn.showcaseChips}});Object.defineProperty(l,"v3OpenReceiptPayload",{enumerable:!0,get:function(){return nn.v3OpenReceiptPayload}});Object.defineProperty(l,"v3SealReceiptPayload",{enumerable:!0,get:function(){return nn.v3SealReceiptPayload}});var ke=Ea();Object.defineProperty(l,"encodeFragment",{enumerable:!0,get:function(){return ke.encodeFragment}});Object.defineProperty(l,"decodeFragment",{enumerable:!0,get:function(){return ke.decodeFragment}});Object.defineProperty(l,"extractProofToken",{enumerable:!0,get:function(){return ke.extractProofToken}});Object.defineProperty(l,"encodeProofToken",{enumerable:!0,get:function(){return ke.encodeProofToken}});Object.defineProperty(l,"decodeShareCredential",{enumerable:!0,get:function(){return ke.decodeShareCredential}});Object.defineProperty(l,"sealBytesForPublicShare",{enumerable:!0,get:function(){return ke.sealBytesForPublicShare}});Object.defineProperty(l,"openPublicShare",{enumerable:!0,get:function(){return ke.openPublicShare}});Object.defineProperty(l,"wrapFragmentForShortLink",{enumerable:!0,get:function(){return ke.wrapFragmentForShortLink}})});import{McpServer as wd}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as vd}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as h}from"zod";import{z as ge}from"zod";import{readdirSync as Ur,readFileSync as Hr,statSync as Sn}from"node:fs";import{join as Ki}from"node:path";var Ir=[{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"}],Nr=/node_modules\/|\.next\/|\.test\.|\.spec\.|__tests__\/|\.env\.example$|\.nodata-proof\.json$|\.git\//,ui=[{name:"lodash",below:"4.17.21",severity:"critical",cve:"CVE-2021-23337",desc:"Command injection via template"},{name:"minimist",below:"1.2.6",severity:"critical",cve:"CVE-2021-44906",desc:"Prototype pollution"},{name:"json5",below:"2.2.2",severity:"high",cve:"CVE-2022-46175",desc:"Prototype pollution"},{name:"express",below:"4.19.2",severity:"high",cve:"CVE-2024-29041",desc:"Open redirect"},{name:"path-to-regexp",below:"6.3.0",severity:"high",cve:"CVE-2024-45296",desc:"ReDoS"},{name:"sanitize-html",below:"2.12.1",severity:"high",cve:"CVE-2024-21501",desc:"XSS bypass"},{name:"dompurify",below:"3.0.9",severity:"high",cve:"CVE-2024-45801",desc:"mXSS"},{name:"jsonwebtoken",below:"9.0.0",severity:"critical",cve:"CVE-2022-23529",desc:"Key confusion attack"},{name:"jose",below:"4.15.5",severity:"high",cve:"CVE-2024-28176",desc:"DoS via JWE"},{name:"axios",below:"1.6.0",severity:"high",cve:"CVE-2023-45857",desc:"CSRF cookie leak"},{name:"node-fetch",below:"2.6.7",severity:"high",cve:"CVE-2022-0235",desc:"Header leak on redirect"},{name:"serialize-javascript",below:"6.0.2",severity:"critical",cve:"CVE-2024-11831",desc:"XSS via serialization"},{name:"xml2js",below:"0.6.0",severity:"high",cve:"CVE-2023-0842",desc:"Prototype pollution"},{name:"next",below:"14.1.1",severity:"high",cve:"CVE-2024-34350",desc:"SSRF via headers"},{name:"sharp",below:"0.32.6",severity:"high",cve:"CVE-2023-4863",desc:"libwebp heap overflow"},{name:"multer",below:"1.4.5",severity:"high",cve:"CVE-2022-24434",desc:"Prototype pollution"},{name:"tough-cookie",below:"4.1.3",severity:"medium",cve:"CVE-2023-26136",desc:"Prototype pollution"},{name:"semver",below:"7.5.4",severity:"medium",cve:"CVE-2022-25883",desc:"ReDoS"},{name:"ip",below:"2.0.1",severity:"critical",cve:"CVE-2024-29415",desc:"SSRF bypass via octal IP"},{name:"tar",below:"6.2.1",severity:"high",cve:"CVE-2024-28863",desc:"DoS via path traversal"}];function pi(e,t){let n=a=>a.replace(/^[^0-9]*/,"").split(".").map(i=>parseInt(i,10)||0),r=n(e),o=n(t);for(let a=0;a<3;a++){if((r[a]||0)<(o[a]||0))return!0;if((r[a]||0)>(o[a]||0))return!1}return!1}function Cr(e){let t=[],n;try{n=JSON.parse(e)}catch{return t}let r={...n.dependencies??{},...n.devDependencies??{}};for(let[o,a]of Object.entries(r)){let i=(a||"").replace(/^[\^~>=<\s]+/,""),s=ui.find(c=>c.name===o&&pi(i,c.below));s&&t.push({name:o,version:i,vuln:s})}return t}var fi=[{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"}],hi=[{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"}],yi=/^(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 Te(e){if(!e)return null;let t=e.trim();if(yi.test(t)||/^name$/i.test(t))return null;let n=t.replace(/[\s-]+/g,"_");for(let r of[...hi,...fi])if(r.pattern.test(t)||r.pattern.test(n))return{type:r.type,label:r.label};return null}var hn={id:"critical",financial:"critical",medical:"critical",biometric:"critical",minor_data:"critical",sensitive_personal:"critical",email:"high",phone:"high",name:"high",address:"high",dob:"high",tracking:"medium",location:"medium"};function Dt(e){let t=String(e??"").replace(/\D/g,"");if(t.length===0||t.length>9)return!1;let n=t.padStart(9,"0"),r=0;for(let o=0;o<9;o++){let a=parseInt(n[o]??"0",10)*(o%2+1);a>9&&(a-=9),r+=a}return r%10===0&&parseInt(n,10)>0}var nt=/(?:\+972[\s-]?|0)(?:5[0-9]|[2-4]|[89])(?:[\s-]?\d){7}/g;var rt=/\bIL\d{2}\s?(?:\d{4}\s?){4}\d{3}\b/g;function mi(e){let t=String(e??"").replace(/\D/g,"");if(t.length<12||t.length>19)return!1;let n=0,r=!1;for(let o=t.length-1;o>=0;o-=1){let a=parseInt(t[o]??"0",10);r&&(a*=2,a>9&&(a-=9)),n+=a,r=!r}return n%10===0}function gi(e){let t=String(e??"").replace(/\s/g,"").toUpperCase();if(!/^[A-Z]{2}\d{2}[A-Z0-9]{10,30}$/.test(t))return!1;let n=t.slice(4)+t.slice(0,4),r=0;for(let o of n){let a=o>="A"&&o<="Z"?String(o.charCodeAt(0)-55):o;for(let i of a)r=(r*10+Number(i))%97}return r===1}var pn="(?<!\\d)(?<!\\d[.,])",fn="(?!\\d)(?![.,]\\d)",yn=[{subkind:"israeli_id",severity:"high",pattern:new RegExp(`${pn}\\d{9}${fn}`,"g"),validate:Dt,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(`${pn}[2-6][ -]?(?:\\d[ -]?){11,17}\\d${fn}`,"g"),validate:mi,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:gi,hint:"Bank account in IBAN form (mod-97 verified) in plaintext."},{subkind:"israeli_phone",severity:"medium",pattern:new RegExp(`${pn}(?:\\+972[- ]?|0)(?:[57]\\d|[2-489])[- ]?\\d{3}[- ]?\\d{4}${fn}`,"g"),validate:e=>{let t=e.replace(/\D/g,"").replace(/^972/,"0");return/^0[57]\d{8}$/.test(t)?!0:/^0[2-489]\d{7}$/.test(t)&&(/[- ]/.test(e)||e.startsWith("+972"))},hint:"Israeli phone number in plaintext."}];function Rr(e){let t=[];for(let n of yn){n.pattern.lastIndex=0;let r=new Set,o,a=0;for(;(o=n.pattern.exec(e))!==null&&(a+=1,!(a>2e5));){let i=o[0];if(n.validate(i)&&r.add(i.replace(/[\s-]/g,"")),r.size>=1e5)break}r.size>0&&t.push({subkind:n.subkind,severity:n.severity,hint:n.hint,count:r.size})}return t}function je(e,t){let n=[],r="",o=!1;for(let a=0;a<e.length;a++){let i=e[a];o?i==='"'&&e[a+1]==='"'?(r+='"',a++):i==='"'?o=!1:r+=i:i==='"'?o=!0:i===t?(n.push(r),r=""):r+=i}return n.push(r),n}import{inflateRawSync as Ti}from"node:zlib";import{inflateSync as _i}from"node:zlib";var mn=new Set([".pdf"]),$r=8*1024*1024;function bi(e){let t=e.toString("latin1"),n=new Map,r=/(\d+)\s+(\d+)\s+obj\b/g,o;for(;(o=r.exec(t))!==null;){let a=Number(o[1]),i=r.lastIndex,s=t.indexOf("endobj",i);if(s<0)continue;let c=t.indexOf("stream",i),d,u=null;if(c>=0&&c<s){d=t.slice(i,c);let p=c+6;t[p]==="\r"&&(p+=1),t[p]===`
16
+ `&&(p+=1);let f=t.indexOf("endstream",p);f>p&&(u=e.subarray(p,f))}else d=t.slice(i,s);n.set(a,{num:a,dict:d,stream:u})}return n}function Si(e){let t=e.toString("latin1").replace(/\s/g,"");t.startsWith("<~")&&(t=t.slice(2));let n=t.indexOf("~>");n>=0&&(t=t.slice(0,n));let r=[],o=0,a=0;for(let i of t){if(i==="z"&&a===0){r.push(0,0,0,0);continue}let s=i.charCodeAt(0)-33;if(s<0||s>84)return null;o=o*85+s,a+=1,a===5&&(r.push(o>>>24&255,o>>>16&255,o>>>8&255,o&255),o=0,a=0)}if(a>0){for(let s=a;s<5;s+=1)o=o*85+84;let i=[o>>>24&255,o>>>16&255,o>>>8&255,o&255];for(let s=0;s<a-1;s+=1)r.push(i[s]??0)}return Buffer.from(r)}function wi(e){let t=e.toString("latin1").replace(/\s/g,"").split(">")[0]??"",n=t.length%2?t+"0":t;return/^[0-9A-Fa-f]*$/.test(n)?Buffer.from(n,"hex"):null}function vi(e){let t=/\/Filter\s*(\[[^\]]*\]|\/\w+)/.exec(e);return!t||!t[1]?[]:[...t[1].matchAll(/\/(\w+)/g)].map(n=>n[1]??"")}function Kr(e){if(!e.stream)return null;let t=e.stream;for(let n of vi(e.dict)){let r=null;if(n==="FlateDecode")try{r=_i(t)}catch{return null}else if(n==="ASCII85Decode")r=Si(t);else if(n==="ASCIIHexDecode")r=wi(t);else return null;if(r===null)return null;t=r}return t.toString("latin1")}function Ei(e){let t=new Map,n=1,r=/begincodespacerange([\s\S]*?)endcodespacerange/.exec(e);if(r&&r[1]){let c=/<([0-9A-Fa-f]+)>/.exec(r[1]);c&&c[1]&&c[1].length>=4&&(n=2)}let o=c=>{let d="";for(let u=0;u+3<c.length+1;u+=4){let p=parseInt(c.slice(u,u+4),16);Number.isFinite(p)&&p>0&&(d+=String.fromCharCode(p))}return d},a=/beginbfchar([\s\S]*?)endbfchar/g,i;for(;(i=a.exec(e))!==null;){let c=/<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]*)>/g,d;for(;(d=c.exec(i[1]??""))!==null;)t.set(parseInt(d[1]??"0",16),o(d[2]??""))}let s=/beginbfrange([\s\S]*?)endbfrange/g;for(;(i=s.exec(e))!==null;){let c=i[1]??"",d=/<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]+)>\s*<([0-9A-Fa-f]*)>/g,u;for(;(u=d.exec(c))!==null;){let p=parseInt(u[1]??"0",16),f=parseInt(u[2]??"0",16),y=parseInt((u[3]??"0").slice(0,4)||"0",16);if(!(f-p>65535))for(let b=p;b<=f;b+=1)t.set(b,String.fromCharCode(y+(b-p)))}}return{map:t,bytes:n}}function ki(e){let t=new Map,n=new Map,r=[];for(let o of e.values()){let a=/\/Font\s*<<([\s\S]*?)>>/.exec(o.dict);a?.[1]&&r.push(a[1]);let i=/\/Font\s+(\d+)\s+\d+\s+R/.exec(o.dict);if(i){let s=e.get(Number(i[1]));s&&r.push(s.dict)}}for(let o of r){let a=/\/([^\s/<>[\]()]+)\s+(\d+)\s+\d+\s+R/g,i;for(;(i=a.exec(o))!==null;)n.set(i[1]??"",Number(i[2]))}for(let[o,a]of n){let i=e.get(a);if(!i)continue;let s=/\/ToUnicode\s+(\d+)\s+\d+\s+R/.exec(i.dict);if(!s)continue;let c=e.get(Number(s[1]));if(!c)continue;let d=Kr(c);d&&t.set(o,Ei(d))}return t}function jr(e){let t=[];for(let n=0;n<e.length;n+=1){let r=e[n];if(r!=="\\"){t.push(r.charCodeAt(0)&255);continue}let o=e[n+1];if(o===void 0)break;if(o>="0"&&o<="7"){let i="",s=n+1;for(;s<e.length&&i.length<3&&e[s]>="0"&&e[s]<="7";)i+=e[s],s+=1;t.push(parseInt(i,8)&255),n=s-1;continue}let a={n:10,r:13,t:9,b:8,f:12};t.push(a[o]??o.charCodeAt(0)&255),n+=1}return t}function Mr(e){if(e.length<2||e[0]!==254||e[1]!==255)return null;let t="";for(let n=2;n+1<e.length;n+=2)t+=String.fromCharCode((e[n]??0)<<8|(e[n+1]??0));return t}function Br(e,t){let n=Mr(e);if(n!==null)return n;if(!t)return e.map(o=>String.fromCharCode(o)).join("");let r="";if(t.bytes===2)for(let o=0;o+1<e.length;o+=2){let a=(e[o]??0)<<8|(e[o+1]??0);r+=t.map.get(a)??""}else for(let o of e)r+=t.map.get(o)??String.fromCharCode(o);return r}function xi(e,t){let n="",r,o=/\/([^\s/<>[\]()]+)\s+[\d.]+\s+Tf|\((?:\\.|[^\\)])*\)|<[0-9A-Fa-f\s]*>|TJ|Tj|'|"/g,a,i="";for(;(a=o.exec(e))!==null;){let s=a[0];if(s.endsWith("Tf")){r=t.get(a[1]??"");continue}if(s==="TJ"||s==="Tj"||s==="'"||s==='"'){i&&(n+=i+`
17
+ `,i="");continue}if(s.startsWith("("))i+=Br(jr(s.slice(1,-1)),r);else if(s.startsWith("<")){let c=s.slice(1,-1).replace(/\s+/g,""),d=[];for(let u=0;u+1<c.length;u+=2)d.push(parseInt(c.slice(u,u+2),16));i+=Br(d,r)}}return i&&(n+=i+`
18
+ `),n}function Ai(e,t){let n=e.toString("latin1"),r=/\/Info\s+(\d+)\s+\d+\s+R/.exec(n),o=r?t.get(Number(r[1]))?.dict:void 0;if(!o)return"";let a=[],i=/\/(Author|Title|Subject|Keywords|Creator|Producer)\s*(\((?:\\.|[^\\)])*\)|<[0-9A-Fa-f\s]*>)/g,s;for(;(s=i.exec(o))!==null;){let c=s[2]??"";if(c.startsWith("(")){let d=jr(c.slice(1,-1));a.push(Mr(d)??d.map(u=>String.fromCharCode(u)).join(""))}else{let d=c.slice(1,-1).replace(/\s+/g,""),u="";if(d.toUpperCase().startsWith("FEFF"))for(let p=4;p+3<d.length+1;p+=4)u+=String.fromCharCode(parseInt(d.slice(p,p+4),16));else for(let p=0;p+1<d.length;p+=2)u+=String.fromCharCode(parseInt(d.slice(p,p+2),16));a.push(u)}}return a.join(`
19
+ `)}function Lr(e){if(!e.subarray(0,8).toString("latin1").startsWith("%PDF-")||e.toString("latin1",0,Math.min(e.length,4096)).includes("/Encrypt"))return null;let n=bi(e);if(n.size===0)return null;let r=ki(n),o=[];o.push(Ai(e,n));let a=0,i=0,s=!1;for(let c of n.values()){if(!c.stream||/\/Subtype|\/Type\s*\/(XObject|Font|Metadata)|\/FontFile/.test(c.dict))continue;let d=Kr(c);if(d===null||!/(TJ|Tj)\b/.test(d))continue;let u=xi(d,r);if(u.trim().length!==0){if(i+=1,a+u.length>$r){o.push(u.slice(0,Math.max(0,$r-a))),s=!0;break}o.push(u),a+=u.length}}return i===0?null:{text:o.join(`
20
+ `),truncated:s,streams:i}}var Fr=new Set([".xlsx",".xlsm",".docx",".pptx"]),gn=8*1024*1024,Pi=101010256,Di=33639248,Oi=67324752;function _n(e){let t=Math.min(e.length,67584),n=-1;for(let i=e.length-22;i>=e.length-t&&i>=0;i-=1)if(e.readUInt32LE(i)===Pi){n=i;break}if(n<0)return null;let r=e.readUInt16LE(n+10),o=e.readUInt32LE(n+16);if(o>=e.length)return null;let a=[];for(let i=0;i<r&&!(o+46>e.length||e.readUInt32LE(o)!==Di);i+=1){let s=e.readUInt16LE(o+10),c=e.readUInt32LE(o+20),d=e.readUInt32LE(o+24),u=e.readUInt16LE(o+28),p=e.readUInt16LE(o+30),f=e.readUInt16LE(o+32),y=e.readUInt32LE(o+42),b=e.subarray(o+46,o+46+u).toString("utf8");a.push({name:b,method:s,compSize:c,uncompSize:d,localHeaderOffset:y}),o+=46+u+p+f}return a}function bn(e,t){let n=t.localHeaderOffset;if(n+30>e.length||e.readUInt32LE(n)!==Oi)return null;let r=e.readUInt16LE(n+26),o=e.readUInt16LE(n+28),a=n+30+r+o,i=a+t.compSize;if(i>e.length)return null;let s=e.subarray(a,i);try{if(t.method===0)return Buffer.from(s);if(t.method===8)return Ti(s)}catch{return null}return null}function Ii(e,t){return bn(e,t)?.toString("utf8")??null}var Ni={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&apos;":"'"};function Me(e){return e.replace(/&(amp|lt|gt|quot|apos);/g,t=>Ni[t]??t).replace(/&#(\d+);/g,(t,n)=>{let r=Number(n);return r>0&&r<1114112?String.fromCodePoint(r):""}).replace(/&#x([0-9a-fA-F]+);/g,(t,n)=>{let r=parseInt(n,16);return r>0&&r<1114112?String.fromCodePoint(r):""})}function Ci(e){return Me(e.replace(/<[^>]*>/g,`
9
21
  `)).replace(/\n{2,}/g,`
10
- `)}function ct(e,t,n){let a=new RegExp(`<${t}\\b[^>]*\\b${n}="([^"]*)"`,"g"),i=[],o;for(;(o=a.exec(e))!==null;)o[1]&&i.push(ye(o[1]));return i}function lt(e,t){let n=[];for(let a of t)(a==="docProps/core.xml"||a==="docProps/app.xml")&&n.push(a);if(e===".xlsx"||e===".xlsm")for(let a of t)(a==="xl/sharedStrings.xml"||a==="xl/workbook.xml"||/^xl\/worksheets\/sheet\d+\.xml$/.test(a)||/^xl\/comments\d*\.xml$/.test(a))&&n.push(a);else if(e===".docx")for(let a of t)(a==="word/document.xml"||/^word\/(header|footer|footnotes|endnotes|comments)\d*\.xml$/.test(a))&&n.push(a);else if(e===".pptx")for(let a of t)/^ppt\/(slides|notesSlides)\/(slide|notesSlide)\d+\.xml$/.test(a)&&n.push(a);return n}function dt(e,t){let n=it(e);if(!n||n.length===0)return null;let a=new Map(n.map(d=>[d.name,d])),i=lt(t,n.map(d=>d.name));if(i.length===0)return null;let o=[],r=[],s=0,l=!1;for(let d of i){if(s>=q){l=!0;break}let p=a.get(d);if(!p)continue;let f=at(e,p);if(f===null)continue;let E=st(f);if(d==="xl/workbook.xml"){let P=ct(f,"sheet","name");P.length&&(E+=`
11
- `+P.join(`
12
- `))}s+E.length>q&&(E=E.slice(0,Math.max(0,q-s)),l=!0),E.trim().length!==0&&(o.push(E),r.push(d),s+=E.length)}return o.length===0?null:{text:o.join(`
13
- `),truncated:l,parts:r}}function _e(e,t){if(me.has(t))return dt(e,t);if(J.has(t)){let n=ge(e);return n?{text:n.text,truncated:n.truncated,parts:[`pdf:${n.streams}-streams`]}:null}return null}var ve=new Set([...me,...J]);var ee=10,j=5e3,ut=64*1024*1024,te=32*1024,ft=new Set([".exe",".dll",".so",".dylib",".msi",".bin",".iso",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".bmp",".tif",".tiff",".webp",".ico",".mp3",".mp4",".mov",".avi",".mkv",".wav",".flac",".ogg",".psd",".ai",".fla",".dwg",".dxf",".sqlite",".sqlite3",".db",".pyc",".class"]),ht=new Set(["node_modules",".git",".hg",".svn"]),gt=[{re:/\b\d{3}-\d{2}-\d{4}\b/,kind:"pii_unencrypted",subkind:"ssn",severity:"high",hint:"US Social Security Number pattern in plaintext."},{re:/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i,kind:"pii_unencrypted",subkind:"email",severity:"low",hint:"Email addresses in plaintext."},{re:/(passport|teudat.?zehut|(?<![א-ת])תעודת.?זהות(?![א-ת])|(?<![א-ת])ת["'׳״]?\.?ז(?![א-ת]))/i,kind:"pii_unencrypted",subkind:"passport_keyword",severity:"medium",hint:"Filename / content references passport / national-ID keyword."}],mt=[{re:/(salary|payroll|משכורת|ssn|social.?security|passport|דרכון|תעודת.?זהות)/i,kind:"pii_unencrypted",subkind:"sensitive_filename",severity:"medium",hint:"Filename suggests sensitive PII content."},{re:/\.(env|env\.local|pem|key|p12|pfx)$/i,kind:"pii_unencrypted",subkind:"secret_file",severity:"high",hint:"File extension implies secret / credential bundle in plaintext."}];function yt(e){let t=e.lastIndexOf(".");return t<0?"":e.slice(t).toLowerCase()}async function ne(e){let t=Date.now(),n=[],a=[],i=0,o=0,r={hit_file_cap:!1,hit_depth_cap:!1,max_files:j,max_depth:ee,skipped_by_extension:0,documents_extracted:0,documents_truncated:0,documents_unreadable:0,files_too_large:0,files_sampled_only:0,sample_bytes:te};function s(y){return(y.startsWith(e.target_path)?y.slice(e.target_path.length).replace(/^[\\/]+/,""):y).replace(/\\/g,"/")}function l(y,g,h,v,S){let m=s(y);m!==""&&a.push({target_id:e.target_id,path:m,kind:g,size_bytes:h,modified_at:v?v.toISOString():null,child_count:S})}function d(y,g){n.push({target_id:e.target_id,relative_path:y,finding_kind:g.kind,finding_subkind:g.subkind,severity:g.severity,remediation_hint:g.hint})}function p(y,g,h,v,S){n.push({target_id:e.target_id,relative_path:y,finding_kind:g,finding_subkind:v,severity:h,remediation_hint:S})}function f(y,g){if(i+=1,i>j){r.hit_file_cap=!0;return}let h=s(y);for(let u of mt)u.re.test(g)&&d(h,u);let v=yt(g);if(ft.has(v)){r.skipped_by_extension+=1;return}let S=ve.has(v),m=0;try{m=Q(y).size}catch{return}if(S&&m>ut){r.files_too_large+=1;return}let w;try{let u=Se(y,{flag:"r"});w=S?u:u.subarray(0,te)}catch{return}o+=1;let T;if(S){let u=_e(w,v);if(!u){r.documents_unreadable+=1;return}T=u.text,r.documents_extracted+=1,u.truncated&&(r.documents_truncated+=1)}else{let u=0;for(let _=0;_<w.length;_+=1)w[_]===0&&(u+=1);if(w.length>0&&u/w.length>.05)return;T=w.toString("utf8"),m>te&&(r.files_sampled_only+=1)}let k=new Set;for(let u of gt)if(u.re.test(T)){let _=`${u.subkind}::${h}`;k.has(_)||(k.add(_),d(h,u))}for(let u of le(T)){let _=`validated::${u.subkind}::${h}`;k.has(_)||(k.add(_),p(h,"pii_unencrypted",u.severity,u.subkind,`${u.hint} ${u.count} distinct value${u.count===1?"":"s"} in this file.`))}if(!se.test(h)){let u=T.split(`
14
- `),_=Math.min(u.length,2e3);for(let b=0;b<_;b++){let x=u[b];if(!x)continue;let C=x.trimStart();if(!(C.startsWith("//")||C.startsWith("/*")||C.startsWith("*")||C.startsWith("#"))&&!/process\.env/.test(x)&&!/\$\{[A-Z_]+/.test(x)){for(let $ of oe)if($.pattern.test(x)){let N=`secret::${$.id}::${h}::${b+1}`;if(k.has(N))break;k.add(N),p(h,"hardcoded_secret",$.severity,$.id,`Looks like a ${$.name} hardcoded near line ${b+1}. Move to an env var or secret manager.`);break}}}}if(g==="package.json"&&!h.includes("node_modules"))try{let u=Se(y,"utf8"),_=ce(u);for(let b of _){let x=`vuln::${b.name}::${h}`;k.has(x)||(k.add(x),p(h,"vulnerable_dependency",b.vuln.severity,b.name,`${b.name}@${b.version} is below ${b.vuln.below} (${b.vuln.cve} \xB7 ${b.vuln.desc}). Bump to ${b.vuln.below} or higher.`))}}catch{}if(v===".csv"||v===".tsv"){let u=v===".tsv"?" ":",",_=T.split(/\r?\n/);if(_.length>0){let b=X(_[0]??"",u),x=_.slice(1,51).map(C=>X(C??"",u));b.forEach((C,$)=>{let N=(C??"").trim();if(!N)return;let O=G(N)?.type??null;if(!O){let D=[];for(let Le of x){let V=Le[$];if(V&&V.trim().length>0&&D.push(V),D.length>=50)break}let L=P(D);L&&(O=L)}if(O){let D=Z[O]??"medium",L=`header::${h}::${N}::${O}`;if(k.has(L))return;k.add(L),p(h,"pii_header_match",D,`${O}:${N}`,`Column "${N}" looks like ${O} data. Wrap with envelope or move to a vault-backed reference.`)}})}}if(v===".json"&&!g.endsWith(".nodata-proof.json"))try{let u=JSON.parse(T),_=Array.isArray(u)?u[0]:u;if(_&&typeof _=="object")for(let b of Object.keys(_)){let x=G(b);if(x){let C=Z[x.type]??"medium",$=`jsonkey::${h}::${b}::${x.type}`;if(k.has($))continue;k.add($),p(h,"pii_header_match",C,`${x.type}:${b}`,`JSON key "${b}" looks like ${x.type} data.`)}}}catch{}/\.(txt|log|md|csv|tsv|json|jsonl|xml|html?|yaml|yml|sql)$/i.test(g)&&E(T,h,k)}function E(y,g,h){let v=y.split(`
15
- `),S=Math.min(v.length,1e3),m=-1,w=-1,T=-1;for(let k=0;k<S;k++){let u=v[k]??"";if(T<0){let _=u.match(/\b\d{9}\b/);_&&F(_[0])&&(T=k+1)}if(m<0&&(U.lastIndex=0,U.test(u)&&(m=k+1)),w<0&&(B.lastIndex=0,B.test(u)&&(w=k+1)),T>0&&m>0&&w>0)break}T>0&&!h.has(`ilid::${g}`)&&(h.add(`ilid::${g}`),p(g,"israeli_id_value","critical",`near_line:${T}`,`Israeli ID with valid Luhn checksum detected near line ${T}. Strong signal that real customer IDs are in plaintext.`)),m>0&&!h.has(`ilphone::${g}`)&&(h.add(`ilphone::${g}`),p(g,"israeli_phone_value","high",`near_line:${m}`,`Israeli phone number detected near line ${m}.`)),w>0&&!h.has(`iliban::${g}`)&&(h.add(`iliban::${g}`),p(g,"israeli_iban_value","critical",`near_line:${w}`,`Israeli IBAN (IL prefix) detected near line ${w}.`))}function P(y){if(y.length===0)return null;let g=0,h=0,v=0;for(let m of y)typeof m=="string"&&(F(m)&&g++,U.lastIndex=0,U.test(m)&&h++,B.lastIndex=0,B.test(m)&&v++);let S=y.length;return g/S>=.3?"id":h/S>=.3?"phone":v/S>=.3?"financial":null}function R(y,g){if(g>ee){r.hit_depth_cap=!0;return}if(i>j){r.hit_file_cap=!0;return}let h;try{h=be(y)}catch{return}for(let v of h){if(i>j)return;let S=pt(y,v),m;try{m=Q(S)}catch{continue}if(!m.isSymbolicLink())if(m.isDirectory()){if(ht.has(v))continue;let w=null;try{w=be(S).length}catch{w=null}l(S,"folder",null,m.mtime??null,w),R(S,g+1)}else m.isFile()&&(l(S,"file",m.size,m.mtime??null,null),f(S,v))}}let z;try{z=Q(e.target_path).isDirectory()}catch{z=!1}return z?(e.log.info("folder-scanner: starting",{target_label:e.target_label,target_path:e.target_path,max_files:j,max_depth:ee}),R(e.target_path,0),{target_id:e.target_id,target_label:e.target_label,target_path:e.target_path,files_walked:i,files_inspected:o,duration_ms:Date.now()-t,findings:n,inventory:a,coverage:r}):{target_id:e.target_id,target_label:e.target_label,target_path:e.target_path,files_walked:0,files_inspected:0,duration_ms:Date.now()-t,findings:[],inventory:[],coverage:r,error:"target_path_not_found_or_not_directory"}}var re={info(){}};var ke={critical:4,high:3,medium:2,low:1,info:0};function ie(e){let t=[];if(t.push(`Scanned "${e.target_label||e.target_path}" on this machine \u2014 nothing left your computer.
16
- `),e.error)return t.push(`Could not scan: ${e.error}`),t.join(`
17
- `);t.push(`WALKED ${e.files_walked} files (${e.files_inspected} inspected) in ${e.duration_ms}ms`);let n=e.findings??[],a={};for(let s of n)a[s.severity]=(a[s.severity]??0)+1;let i=["critical","high","medium","low","info"].filter(s=>a[s]).map(s=>`${a[s]} ${s}`).join(" \xB7 ");if(t.push(`EXPOSURE ${n.length} findings${i?" \u2014 "+i:""}
18
- `),n.length===0)t.push(`No hardcoded secrets or unencrypted PII found in the files scanned. Clean.
19
- `);else{let s=[...n].sort((d,p)=>(ke[p.severity]??0)-(ke[d.severity]??0));t.push("TOP EXPOSURES:");for(let d of s.slice(0,8))t.push(` \u2717 [${d.severity.toUpperCase()}] ${d.finding_subkind||d.finding_kind} \u2014 ${d.relative_path}`);s.length>8&&t.push(` \u2026 and ${s.length-8} more.`),t.push("");let l=s.find(d=>d.remediation_hint);l?.remediation_hint&&t.push(`FIRST FIX ${l.remediation_hint}
20
- `)}let o=e.coverage,r=[];return o?.hit_file_cap&&r.push(`stopped at the ${o.max_files}-file cap`),o?.hit_depth_cap&&r.push(`folders deeper than ${o.max_depth} levels were not descended`),o?.files_too_large&&r.push(`${o.files_too_large} file(s) too large to read`),o?.documents_unreadable&&r.push(`${o.documents_unreadable} document(s) unreadable`),r.length&&t.push(`COVERAGE ${r.join("; ")}.`),t.join(`
21
- `)}import{homedir as bt,hostname as $e}from"node:os";import{join as Re,resolve as M,basename as St}from"node:path";import{existsSync as K,readFileSync as Pe,writeFileSync as kt,mkdirSync as wt,chmodSync as Et}from"node:fs";import{spawn as xt}from"node:child_process";import{generateKeyPairSync as At,createPrivateKey as Tt,sign as It,randomBytes as Ct}from"node:crypto";var ae="1.1.0",Ne=Re(bt(),".nodata"),H=Re(Ne,"credentials.json");function $t(){try{if(!K(H))return null;let e=JSON.parse(Pe(H,"utf8"));if(!e)return null;let t=e.device&&typeof e.device.private_key_pkcs8_b64=="string",n=typeof e.api_key=="string"&&e.api_key;return t||n?e:null}catch{return null}}function we(e){wt(Ne,{recursive:!0});let t=JSON.stringify({...e,saved_at:new Date().toISOString()},null,2);kt(H,t,{mode:384});try{Et(H,384)}catch{}}var Rt=`nodata-mcp v${ae} \u2014 NoData MCP server
22
+ `)}function Ri(e,t,n){let r=new RegExp(`<${t}\\b[^>]*\\b${n}="([^"]*)"`,"g"),o=[],a;for(;(a=r.exec(e))!==null;)a[1]&&o.push(Me(a[1]));return o}function $i(e,t){let n=[];for(let r of t)(r==="docProps/core.xml"||r==="docProps/app.xml")&&n.push(r);if(e===".xlsx"||e===".xlsm")for(let r of t)(r==="xl/sharedStrings.xml"||r==="xl/workbook.xml"||/^xl\/worksheets\/sheet\d+\.xml$/.test(r)||/^xl\/comments\d*\.xml$/.test(r))&&n.push(r);else if(e===".docx")for(let r of t)(r==="word/document.xml"||/^word\/(header|footer|footnotes|endnotes|comments)\d*\.xml$/.test(r))&&n.push(r);else if(e===".pptx")for(let r of t)/^ppt\/(slides|notesSlides)\/(slide|notesSlide)\d+\.xml$/.test(r)&&n.push(r);return n}function Bi(e,t){let n=_n(e);if(!n||n.length===0)return null;let r=new Map(n.map(d=>[d.name,d])),o=$i(t,n.map(d=>d.name));if(o.length===0)return null;let a=[],i=[],s=0,c=!1;for(let d of o){if(s>=gn){c=!0;break}let u=r.get(d);if(!u)continue;let p=Ii(e,u);if(p===null)continue;let f=Ci(p);if(d==="xl/workbook.xml"){let y=Ri(p,"sheet","name");y.length&&(f+=`
23
+ `+y.join(`
24
+ `))}s+f.length>gn&&(f=f.slice(0,Math.max(0,gn-s)),c=!0),f.trim().length!==0&&(a.push(f),i.push(d),s+=f.length)}return a.length===0?null:{text:a.join(`
25
+ `),truncated:c,parts:i}}function ot(e,t){if(Fr.has(t))return Bi(e,t);if(mn.has(t)){let n=Lr(e);return n?{text:n.text,truncated:n.truncated,parts:[`pdf:${n.streams}-streams`]}:null}return null}var Ot=new Set([...Fr,...mn]);var wn=10,at=5e3,ji=64*1024*1024,vn=32*1024,Mi=new Set([".exe",".dll",".so",".dylib",".msi",".bin",".iso",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".bmp",".tif",".tiff",".webp",".ico",".mp3",".mp4",".mov",".avi",".mkv",".wav",".flac",".ogg",".psd",".ai",".fla",".dwg",".dxf",".sqlite",".sqlite3",".db",".pyc",".class"]),Li=new Set(["node_modules",".git",".hg",".svn"]),Fi=[{re:/\b\d{3}-\d{2}-\d{4}\b/,kind:"pii_unencrypted",subkind:"ssn",severity:"high",hint:"US Social Security Number pattern in plaintext."},{re:/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i,kind:"pii_unencrypted",subkind:"email",severity:"low",hint:"Email addresses in plaintext."},{re:/(passport|teudat.?zehut|(?<![א-ת])תעודת.?זהות(?![א-ת])|(?<![א-ת])ת["'׳״]?\.?ז(?![א-ת]))/i,kind:"pii_unencrypted",subkind:"passport_keyword",severity:"medium",hint:"Filename / content references passport / national-ID keyword."}],Ui=[{re:/(salary|payroll|משכורת|ssn|social.?security|passport|דרכון|תעודת.?זהות)/i,kind:"pii_unencrypted",subkind:"sensitive_filename",severity:"medium",hint:"Filename suggests sensitive PII content."},{re:/\.(env|env\.local|pem|key|p12|pfx)$/i,kind:"pii_unencrypted",subkind:"secret_file",severity:"high",hint:"File extension implies secret / credential bundle in plaintext."}];function Hi(e){let t=e.lastIndexOf(".");return t<0?"":e.slice(t).toLowerCase()}async function it(e){let t=Date.now(),n=[],r=[],o=0,a=0,i={hit_file_cap:!1,hit_depth_cap:!1,max_files:at,max_depth:wn,skipped_by_extension:0,documents_extracted:0,documents_truncated:0,documents_unreadable:0,files_too_large:0,files_sampled_only:0,sample_bytes:vn};function s(S){return(S.startsWith(e.target_path)?S.slice(e.target_path.length).replace(/^[\\/]+/,""):S).replace(/\\/g,"/")}function c(S,_,v,E,m){let g=s(S);g!==""&&r.push({target_id:e.target_id,path:g,kind:_,size_bytes:v,modified_at:E?E.toISOString():null,child_count:m})}function d(S,_){n.push({target_id:e.target_id,relative_path:S,finding_kind:_.kind,finding_subkind:_.subkind,severity:_.severity,remediation_hint:_.hint})}function u(S,_,v,E,m){n.push({target_id:e.target_id,relative_path:S,finding_kind:_,finding_subkind:E,severity:v,remediation_hint:m})}function p(S,_){if(o+=1,o>at){i.hit_file_cap=!0;return}let v=s(S);for(let x of Ui)x.re.test(_)&&d(v,x);let E=Hi(_);if(Mi.has(E)){i.skipped_by_extension+=1;return}let m=Ot.has(E),g=0;try{g=Sn(S).size}catch{return}if(m&&g>ji){i.files_too_large+=1;return}let A;try{let x=Hr(S,{flag:"r"});A=m?x:x.subarray(0,vn)}catch{return}a+=1;let C;if(m){let x=ot(A,E);if(!x){i.documents_unreadable+=1;return}C=x.text,i.documents_extracted+=1,x.truncated&&(i.documents_truncated+=1)}else{let x=0;for(let I=0;I<A.length;I+=1)A[I]===0&&(x+=1);if(A.length>0&&x/A.length>.05)return;C=A.toString("utf8"),g>vn&&(i.files_sampled_only+=1)}let P=new Set;for(let x of Fi)if(x.re.test(C)){let I=`${x.subkind}::${v}`;P.has(I)||(P.add(I),d(v,x))}for(let x of Rr(C)){let I=`validated::${x.subkind}::${v}`;P.has(I)||(P.add(I),u(v,"pii_unencrypted",x.severity,x.subkind,`${x.hint} ${x.count} distinct value${x.count===1?"":"s"} in this file.`))}if(!Nr.test(v)){let x=C.split(`
26
+ `),I=Math.min(x.length,2e3);for(let R=0;R<I;R++){let B=x[R];if(!B)continue;let W=B.trimStart();if(!(W.startsWith("//")||W.startsWith("/*")||W.startsWith("*")||W.startsWith("#"))&&!/process\.env/.test(B)&&!/\$\{[A-Z_]+/.test(B)){for(let J of Ir)if(J.pattern.test(B)){let he=`secret::${J.id}::${v}::${R+1}`;if(P.has(he))break;P.add(he),u(v,"hardcoded_secret",J.severity,J.id,`Looks like a ${J.name} hardcoded near line ${R+1}. Move to an env var or secret manager.`);break}}}}if(_==="package.json"&&!v.includes("node_modules"))try{let x=Hr(S,"utf8"),I=Cr(x);for(let R of I){let B=`vuln::${R.name}::${v}`;P.has(B)||(P.add(B),u(v,"vulnerable_dependency",R.vuln.severity,R.name,`${R.name}@${R.version} is below ${R.vuln.below} (${R.vuln.cve} \xB7 ${R.vuln.desc}). Bump to ${R.vuln.below} or higher.`))}}catch{}if(E===".csv"||E===".tsv"){let x=E===".tsv"?" ":",",I=C.split(/\r?\n/);if(I.length>0){let R=je(I[0]??"",x),B=I.slice(1,51).map(W=>je(W??"",x));R.forEach((W,J)=>{let he=(W??"").trim();if(!he)return;let Ae=Te(he)?.type??null;if(!Ae){let et=[];for(let oi of B){let un=oi[J];if(un&&un.trim().length>0&&et.push(un),et.length>=50)break}let tt=y(et);tt&&(Ae=tt)}if(Ae){let et=hn[Ae]??"medium",tt=`header::${v}::${he}::${Ae}`;if(P.has(tt))return;P.add(tt),u(v,"pii_header_match",et,`${Ae}:${he}`,`Column "${he}" looks like ${Ae} data. Wrap with envelope or move to a vault-backed reference.`)}})}}if(E===".json"&&!_.endsWith(".nodata-proof.json"))try{let x=JSON.parse(C),I=Array.isArray(x)?x[0]:x;if(I&&typeof I=="object")for(let R of Object.keys(I)){let B=Te(R);if(B){let W=hn[B.type]??"medium",J=`jsonkey::${v}::${R}::${B.type}`;if(P.has(J))continue;P.add(J),u(v,"pii_header_match",W,`${B.type}:${R}`,`JSON key "${R}" looks like ${B.type} data.`)}}}catch{}/\.(txt|log|md|csv|tsv|json|jsonl|xml|html?|yaml|yml|sql)$/i.test(_)&&f(C,v,P)}function f(S,_,v){let E=S.split(`
27
+ `),m=Math.min(E.length,1e3),g=-1,A=-1,C=-1;for(let P=0;P<m;P++){let x=E[P]??"";if(C<0){let I=x.match(/\b\d{9}\b/);I&&Dt(I[0])&&(C=P+1)}if(g<0&&(nt.lastIndex=0,nt.test(x)&&(g=P+1)),A<0&&(rt.lastIndex=0,rt.test(x)&&(A=P+1)),C>0&&g>0&&A>0)break}C>0&&!v.has(`ilid::${_}`)&&(v.add(`ilid::${_}`),u(_,"israeli_id_value","critical",`near_line:${C}`,`Israeli ID with valid Luhn checksum detected near line ${C}. Strong signal that real customer IDs are in plaintext.`)),g>0&&!v.has(`ilphone::${_}`)&&(v.add(`ilphone::${_}`),u(_,"israeli_phone_value","high",`near_line:${g}`,`Israeli phone number detected near line ${g}.`)),A>0&&!v.has(`iliban::${_}`)&&(v.add(`iliban::${_}`),u(_,"israeli_iban_value","critical",`near_line:${A}`,`Israeli IBAN (IL prefix) detected near line ${A}.`))}function y(S){if(S.length===0)return null;let _=0,v=0,E=0;for(let g of S)typeof g=="string"&&(Dt(g)&&_++,nt.lastIndex=0,nt.test(g)&&v++,rt.lastIndex=0,rt.test(g)&&E++);let m=S.length;return _/m>=.3?"id":v/m>=.3?"phone":E/m>=.3?"financial":null}function b(S,_){if(_>wn){i.hit_depth_cap=!0;return}if(o>at){i.hit_file_cap=!0;return}let v;try{v=Ur(S)}catch{return}for(let E of v){if(o>at)return;let m=Ki(S,E),g;try{g=Sn(m)}catch{continue}if(!g.isSymbolicLink())if(g.isDirectory()){if(Li.has(E))continue;let A=null;try{A=Ur(m).length}catch{A=null}c(m,"folder",null,g.mtime??null,A),b(m,_+1)}else g.isFile()&&(c(m,"file",g.size,g.mtime??null,null),p(m,E))}}let k;try{k=Sn(e.target_path).isDirectory()}catch{k=!1}return k?(e.log.info("folder-scanner: starting",{target_label:e.target_label,target_path:e.target_path,max_files:at,max_depth:wn}),b(e.target_path,0),{target_id:e.target_id,target_label:e.target_label,target_path:e.target_path,files_walked:o,files_inspected:a,duration_ms:Date.now()-t,findings:n,inventory:r,coverage:i}):{target_id:e.target_id,target_label:e.target_label,target_path:e.target_path,files_walked:0,files_inspected:0,duration_ms:Date.now()-t,findings:[],inventory:[],coverage:i,error:"target_path_not_found_or_not_directory"}}var st={info(){}};var Le={critical:4,high:3,medium:2,low:1,info:0},An=["critical","high","medium","low","info"];function En(e,t,n){let r=e.get(t)??{key:t,total:0,worst:"info",bySeverity:{}};r.total+=1,r.bySeverity[n.severity]=(r.bySeverity[n.severity]??0)+1,(Le[n.severity]??0)>(Le[r.worst]??0)&&(r.worst=n.severity),e.set(t,r)}function kn(e){return[...e.values()].sort((t,n)=>(Le[n.worst]??0)-(Le[t.worst]??0)||n.total-t.total||t.key.localeCompare(n.key))}function Pe(e){let t=e.findings??[],n={},r=new Map,o=new Map,a=new Map;for(let s of t){n[s.severity]=(n[s.severity]??0)+1;let c=s.finding_subkind&&!/^near_line/.test(s.finding_subkind)?s.finding_subkind:"";En(r,c||s.finding_kind,s);let d=s.relative_path.replace(/\\/g,"/"),u=d.includes("/")?d.slice(0,d.indexOf("/")):".";En(o,u,s),En(a,d,s)}let i=kn(a);return{total:t.length,bySeverity:n,byType:kn(r),byFolder:kn(o),byFile:i,filesWithFindings:i.map(s=>s.key)}}function ae(e){return e.replace(/[&<>"']/g,t=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[t])}function xn(e,t,n){let r=`<tr><th>${ae(n)}</th><th>total</th>${An.map(a=>`<th class="${a}">${a}</th>`).join("")}</tr>`,o=t.map(a=>`<tr><td class="k">${ae(a.key)}</td><td>${a.total}</td>${An.map(i=>`<td>${a.bySeverity[i]??""}</td>`).join("")}</tr>`).join("");return`<h2>${ae(e)} <span class="n">${t.length}</span></h2><table>${r}${o}</table>`}function Tn(e,t=Pe(e)){let n=An.filter(s=>t.bySeverity[s]).map(s=>`<span class="pill ${s}">${t.bySeverity[s]} ${s}</span>`).join(" "),r=e.coverage,o=[];r?.hit_file_cap&&o.push(`stopped at the ${r.max_files}-file cap`),r?.hit_depth_cap&&o.push(`folders deeper than ${r.max_depth} levels were not descended`),r?.files_too_large&&o.push(`${r.files_too_large} file(s) too large to read`),r?.documents_unreadable&&o.push(`${r.documents_unreadable} document(s) unreadable`);let a=[...e.findings??[]].sort((s,c)=>(Le[c.severity]??0)-(Le[s.severity]??0)),i=a.map(s=>`<tr><td><span class="pill ${s.severity}">${s.severity}</span></td><td>${ae(s.finding_subkind||s.finding_kind)}</td><td class="k">${ae(s.relative_path)}</td><td class="h">${ae(s.remediation_hint??"")}</td></tr>`).join("");return`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
28
+ <title>NoData scan \xB7 ${ae(e.target_label||e.target_path)}</title>
29
+ <style>
30
+ body{margin:0;background:#FAF7F0;color:#1a1a1a;font:14px/1.5 Inter,Heebo,system-ui,sans-serif}
31
+ main{max-width:1100px;margin:0 auto;padding:28px 18px 60px}
32
+ h1{font-size:22px;margin:0 0 4px}h2{font-size:16px;margin:28px 0 8px}.n{color:#8A6B2D;font-weight:500}
33
+ .sub{color:#666;margin:0 0 14px}table{border-collapse:collapse;width:100%;background:#fff;border:1px solid #E9E1D2}
34
+ th,td{padding:6px 9px;border-bottom:1px solid #F0EADF;text-align:left;vertical-align:top}th{font-size:12px;color:#666;background:#FBF8F2}
35
+ td.k{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;word-break:break-all}td.h{color:#555;font-size:12.5px}
36
+ .pill{display:inline-block;border-radius:999px;padding:1px 9px;font-size:12px;font-weight:600;background:#eee}
37
+ .critical{color:#8b1c1c}.pill.critical{background:#fde2e2}.high{color:#9a4b00}.pill.high{background:#feecd9}
38
+ .medium{color:#7a6400}.pill.medium{background:#fbf3cf}.low{color:#445}.pill.low{background:#eef0f4}
39
+ .note{margin-top:18px;color:#666;font-size:12.5px}
40
+ </style></head><body><main>
41
+ <h1>Scan \xB7 ${ae(e.target_label||e.target_path)}</h1>
42
+ <p class="sub">${ae(e.target_path)} \xB7 ${e.files_walked} files walked, ${e.files_inspected} inspected in ${e.duration_ms} ms \xB7 ran on this machine, nothing uploaded</p>
43
+ <p><strong>${t.total}</strong> findings ${n}</p>
44
+ ${o.length?`<p class="note">Coverage: ${ae(o.join("; "))}.</p>`:""}
45
+ ${xn("By type",t.byType,"type")}
46
+ ${xn("By folder",t.byFolder,"folder")}
47
+ ${xn("By file",t.byFile,"file")}
48
+ <h2>Every finding <span class="n">${a.length}</span></h2>
49
+ <table><tr><th>severity</th><th>type</th><th>file</th><th>what to do</th></tr>${i}</table>
50
+ <p class="note">Content-free: this report lists where and what kind \u2014 never a matched value.</p>
51
+ </main></body></html>`}var Vr={israeli_id:"[ID]",credit_card:"[CARD]",iban:"[IBAN]",israeli_phone:"[PHONE]",email:"[EMAIL]"},Vi=/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g,Gi=[...yn].sort((e,t)=>+(t.subkind==="iban")-+(e.subkind==="iban"));function Pn(e,t,n=1){e[t]=(e[t]??0)+n}function ye(e,t={}){let n=e;for(let r of Gi)r.pattern.lastIndex=0,n=n.replace(r.pattern,o=>r.validate(o)?(Pn(t,r.subkind),Vr[r.subkind]??`[${r.subkind.toUpperCase()}]`):o);return n=n.replace(Vi,()=>(Pn(t,"email"),Vr.email)),{text:n,counts:t,columnsHidden:[]}}function Gr(e,t){return e.includes(t)||e.includes('"')||e.includes(`
52
+ `)?`"${e.replace(/"/g,'""')}"`:e}function qi(e){let t=(e.match(/\t/g)??[]).length,n=(e.match(/;/g)??[]).length,r=(e.match(/,/g)??[]).length;return t>r&&t>=n?" ":n>r?";":","}function Dn(e,t){let n=e.split(/\r?\n/),r=t??qi(n[0]??""),o=je(n[0]??"",r),a=o.map(c=>Te(c)),i={},s=[o.map(c=>Gr(c,r)).join(r)];for(let c of n.slice(1)){if(c===""){s.push(c);continue}let d=je(c,r).map((u,p)=>{let f=a[p];return f&&u.trim()!==""?(Pn(i,`column:${f.type}`),`[${f.type.toUpperCase()}]`):ye(u,i).text});s.push(d.map(u=>Gr(u,r)).join(r))}return{text:s.join(`
53
+ `),counts:i,columnsHidden:o.filter((c,d)=>a[d])}}import{deflateRawSync as Wi}from"node:zlib";var Ji=/^xl\/(pivotCache|charts|externalLinks)\//,zi=10;function Yi(e,t,n=1){e[t]=(e[t]??0)+n}function zr(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Yr(e){let t=e.replace(/<rPh\b[\s\S]*?<\/rPh>/g,""),n="";for(let r of t.matchAll(/<t(?:\s[^>]*)?>([\s\S]*?)<\/t>/g))n+=r[1];return Me(n)}function Xi(e){return e?[...e.matchAll(/<si\b[^>]*>([\s\S]*?)<\/si>|<si\b[^>]*\/>/g)].map(t=>Yr(t[1]??"")):[]}var qr=/<c\b([^>]*?)(?:\/>|>([\s\S]*?)<\/c>)/g;function It(e,t){let n=new RegExp(`\\b${t}="([^"]*)"`).exec(e);return n?n[1]:null}function Wr(e,t){if(e.type==="s"){let r=/<v>([^<]*)<\/v>/.exec(e.inner);return r?t[Number(r[1])]??null:null}if(e.type==="inlineStr"){let r=/<is>([\s\S]*?)<\/is>/.exec(e.inner);return r?Yr(r[1]):null}if(e.type==="b"||e.type==="e")return null;let n=/<v>([^<]*)<\/v>/.exec(e.inner);return n?Me(n[1]):null}function Jr(e,t){return`<c${e.replace(/\s*\bt="[^"]*"/,"")} t="inlineStr"><is><t xml:space="preserve">${zr(t)}</t></is></c>`}var Zi=(()=>{let e=new Uint32Array(256);for(let t=0;t<256;t+=1){let n=t;for(let r=0;r<8;r+=1)n=n&1?3988292384^n>>>1:n>>>1;e[t]=n>>>0}return e})();function Qi(e){let t=4294967295;for(let n=0;n<e.length;n+=1)t=Zi[(t^e[n])&255]^t>>>8;return(t^4294967295)>>>0}function Xr(e){let t=[],n=[],r=0;for(let i of e){let s=Buffer.from(i.name,"utf8"),c=i.name.endsWith("/"),d=c?Buffer.alloc(0):Wi(i.data),u=c?0:8,p=c?0:Qi(i.data),f=Buffer.alloc(30);f.writeUInt32LE(67324752,0),f.writeUInt16LE(20,4),f.writeUInt16LE(2048,6),f.writeUInt16LE(u,8),f.writeUInt32LE(p,14),f.writeUInt32LE(d.length,18),f.writeUInt32LE(i.data.length,22),f.writeUInt16LE(s.length,26),t.push(f,s,d);let y=Buffer.alloc(46);y.writeUInt32LE(33639248,0),y.writeUInt16LE(20,4),y.writeUInt16LE(20,6),y.writeUInt16LE(2048,8),y.writeUInt16LE(u,10),y.writeUInt32LE(p,16),y.writeUInt32LE(d.length,20),y.writeUInt32LE(i.data.length,24),y.writeUInt16LE(s.length,28),y.writeUInt32LE(r,42),n.push(y,s),r+=f.length+s.length+d.length}let o=Buffer.concat(n),a=Buffer.alloc(22);return a.writeUInt32LE(101010256,0),a.writeUInt16LE(e.length,8),a.writeUInt16LE(e.length,10),a.writeUInt32LE(o.length,12),a.writeUInt32LE(r,16),Buffer.concat([...t,o,a])}function On(e){let t=_n(e);if(!t||t.length===0||t.some(f=>Ji.test(f.name)))return null;let n=new Map;for(let f of t){if(f.name.endsWith("/")){n.set(f.name,Buffer.alloc(0));continue}let y=bn(e,f);if(!y)return null;n.set(f.name,y)}let r=[...n.keys()].filter(f=>/^xl\/worksheets\/sheet\d+\.xml$/.test(f));if(r.length===0)return null;let o=n.get("xl/sharedStrings.xml")?.toString("utf8")??null,a=Xi(o),i=new Set,s={},c=new Set;for(let f of r){let y=n.get(f).toString("utf8"),b=[];for(let E of y.matchAll(qr)){let m=It(E[1],"r"),g=m?/^([A-Z]+)(\d+)$/.exec(m):null;if(!g)return null;b.push({full:E[0],attrs:E[1],inner:E[2]??"",col:g[1],row:Number(g[2]),type:It(E[1],"t")??"n"})}let k=[...new Set(b.map(E=>E.row))].sort((E,m)=>E-m).slice(0,zi),S=-1,_=new Map;for(let E of k){let m=new Map;for(let g of b.filter(A=>A.row===E)){let A=Wr(g,a),C=A?Te(A):null;C&&(m.set(g.col,C.type),c.add(A.trim()))}if(m.size>0){S=E;for(let[g,A]of m)_.set(g,A);break}}let v=y.replace(qr,(E,m,g)=>{let A=It(m,"r"),[,C,P]=/^([A-Z]+)(\d+)$/.exec(A),x={full:E,attrs:m,inner:g??"",col:C,row:Number(P),type:It(m,"t")??"n"},I=Wr(x,a),R=()=>{if(x.type==="s"){let J=/<v>([^<]*)<\/v>/.exec(x.inner);J&&i.add(Number(J[1]))}return E};if(I===null||I.trim()==="")return R();let B=_.get(C);if(B&&x.row>S)return Yi(s,`column:${B}`),Jr(m,`[${B.toUpperCase()}]`);let W=ye(I,s);return W.text===I?R():Jr(m,W.text)});n.set(f,Buffer.from(v,"utf8"))}if(o){let f=-1,y=o.replace(/<si\b[^>]*>[\s\S]*?<\/si>|<si\b[^>]*\/>/g,b=>(f+=1,i.has(f)?b:"<si><t></t></si>"));n.set("xl/sharedStrings.xml",Buffer.from(y,"utf8"))}for(let f of[...n.keys()].filter(y=>/^xl\/comments\d*\.xml$/.test(y))){let b=n.get(f).toString("utf8").replace(/(<t(?:\s[^>]*)?>)([\s\S]*?)(<\/t>)/g,(k,S,_,v)=>{let E=ye(Me(_),s);return`${S}${zr(E.text)}${v}`});n.set(f,Buffer.from(b,"utf8"))}let d=n.get("docProps/core.xml");if(d){let f=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(f,"utf8"))}let u=n.has("xl/calcChain.xml"),p=t.map(f=>f.name).filter(f=>!(u&&f==="xl/calcChain.xml"));if(u)for(let f of["[Content_Types].xml","xl/_rels/workbook.xml.rels"]){let y=n.get(f);y&&n.set(f,Buffer.from(y.toString("utf8").replace(/<(Override|Relationship)\b[^>]*calcChain[^>]*\/>/g,""),"utf8"))}return{bytes:Xr(p.map(f=>({name:f,data:n.get(f)}))),counts:s,columnsHidden:[...c]}}var re=Or(fo(),1);import{homedir as Ds}from"node:os";import{basename as Kt,dirname as $t,extname as Os,join as ut,resolve as Bt}from"node:path";import{existsSync as dt,mkdirSync as Is,readFileSync as Ns,rmSync as Cs,statSync as Kn,writeFileSync as jn}from"node:fs";import{pathToFileURL as Fn}from"node:url";var G=(e,t=!1)=>({content:[{type:"text",text:e}],...t?{isError:t}:{}}),ho=ut(Ds(),".nodata","reports"),Mn=25;function Un(e){return/\.ndc$/i.test(e)||/\.clean\.[A-Za-z0-9]+$/.test(e)}function Rs(){return new Date().toISOString().replace(/[:.]/g,"-").slice(0,19)}function $s(e){return e.replace(/[^A-Za-z0-9_-]+/g,"_").slice(0,60)||"folder"}async function yo(e){return it({target_id:"mcp",target_label:Kt(e),target_path:e,log:st})}function Ln(e,t){let n=e.slice(0,t).map(r=>` ${String(r.total).padStart(6)} ${r.worst.padEnd(8)} ${r.key}`);return e.length>t&&n.push(` \u2026 ${e.length-t} more in the full report`),n.join(`
54
+ `)}function Bs(e,t,n,r){if(e.error)return`Could not scan ${e.target_path}: ${e.error}`;let o=["critical","high","medium","low","info"].filter(i=>t.bySeverity[i]).map(i=>`${t.bySeverity[i]} ${i}`).join(" \xB7 "),a=[`SCAN ${e.target_path}`,` ${r} \xB7 ran on this machine, nothing uploaded`,` ${e.files_walked} files walked, ${e.files_inspected} inspected, ${e.duration_ms} ms`,"",`FOUND ${t.total} findings${o?" \u2014 "+o:""} in ${t.filesWithFindings.length} files`];return t.total>0&&(a.push("","BY TYPE (all)",Ln(t.byType,100)),a.push("","BY FOLDER",Ln(t.byFolder,10)),a.push("","WORST FILES",Ln(t.byFile,12))),n&&a.push("","FULL REPORT (every finding, content-free) \u2014 open in a browser:",` ${Fn(n).href}`),t.total>0&&a.push("","NEXT \u2014 same workspace:",` \xB7 LOCK the ${t.filesWithFindings.length} files with findings: nodata_protect path: "${e.target_path}" (asks before it changes anything)`,' \xB7 WORK on a clean copy (values replaced by [CARD], [ID] \u2026): nodata_redact path: "<file>"'," \xB7 A database table instead of files: nodata_register_table \u2192 nodata_grant"),a.join(`
55
+ `)}function mo(e,t){e.registerTool("nodata_scan_folder",{description:"SEE what's sensitive. Scans a LOCAL folder for hardcoded secrets and unencrypted PII (checksum-validated Israeli ID, Luhn credit card, IBAN, phones), reading PDF and Office files too, entirely on this machine. Returns the WHOLE result \u2014 counts by type, by folder and by file \u2014 and writes a full content-free HTML report (every finding) to ~/.nodata/reports, with a link to open it. Then offers the next step in the same workspace: nodata_protect (lock the files with findings) or nodata_redact (a clean copy to work on). Call this when the user asks to scan/audit/check a folder.",inputSchema:{path:ge.string().optional().describe("Folder to scan. Default: the directory the server runs in.")}},async({path:r})=>{let o=Bt((r??".").trim()||".");if(!dt(o))return G(`No folder found at: ${o}`);try{let a=await yo(o),i=Pe(a),s=null;return a.error||(Is(ho,{recursive:!0}),s=ut(ho,`scan-${$s(Kt(o))}-${Rs()}.html`),jn(s,Tn(a,i),{mode:384})),G(Bs(a,i,s,t()))}catch(a){return G(`Scan failed: ${a instanceof Error?a.message:String(a)}`,!0)}}),e.registerTool("nodata_protect",{description:"LOCK files: seal each one to this device's key as <file>.ndc (AES-256-GCM, the key never leaves this machine; the same format as `nodata protect`, so `nodata open` opens it too). Given a folder, seals only the files the scan finds exposure in; given a file, seals that file. ASKS FIRST: without confirm:true it only lists what would be sealed and changes nothing \u2014 show that list to the user and call again with confirm:true only after they approve. Writes a local receipt (hashes, seal ids) under <folder>/.nodata/receipts. remove:true also deletes the plaintext originals.",inputSchema:{path:ge.string().describe("File or folder to protect."),confirm:ge.boolean().optional().describe("true = do it. Omit to preview."),remove:ge.boolean().optional().describe("Delete the plaintext originals after sealing. Default false.")}},async({path:r,confirm:o,remove:a})=>{let i=Bt(r);if(!dt(i))return G(`Not found: ${i}`,!0);let s=Kn(i).isDirectory(),c;if(s?c=Pe(await yo(i)).filesWithFindings.map(k=>ut(i,k)).filter(k=>dt(k)&&Kn(k).isFile()&&!Un(k)):c=i.endsWith(".ndc")?[]:[i],c.length===0)return G(`Nothing to seal in ${i} \u2014 no file with findings.`);if(!o){let b=c.slice(0,Mn).map(k=>` \xB7 ${k}`);return c.length>Mn&&b.push(` \u2026 and ${c.length-Mn} more`),G([`PREVIEW \u2014 nothing changed yet. ${t()}`,`Would seal ${c.length} file(s) to this device's key${a?" and DELETE the plaintext originals":" (originals kept)"}:`,...b,"","Ask the user to approve, then call nodata_protect again with confirm: true."].join(`
56
+ `))}let{key:d,created:u}=re.ensureDeviceKey(),p=[];for(let b of c)p.push(await re.sealFile(b,d)),a&&Cs(b);let f=s?i:$t(i),y=re.writeLocalReceipt(f,{action:"protect",kid:d.kid,removed_plaintext:!!a,files:p,extra:{approved_by:t(),surface:"mcp"}});return G([`SEALED ${p.length} file(s) \u2014 ${t()}${u?" \xB7 a new device key was created at ~/.nodata/device-key.json (back it up: without it these files cannot be opened)":""}`,`device key id: ${d.kid}`,a?"Plaintext originals deleted.":"Originals are still in place \u2014 run again with remove: true to leave only the sealed copies.",`Receipt (hashes + seal ids, content-free): ${Fn(y).href}`,'Open one again: nodata_open path: "<file>.ndc"'].join(`
57
+ `))}),e.registerTool("nodata_open",{description:"RELEASE a sealed file: open <file>.ndc back to its original next to it (never overwrites), with this device's key, and check its hash matches what was sealed. ASKS FIRST: without confirm:true it only says what would be opened. Writes a local receipt.",inputSchema:{path:ge.string().describe("The .ndc file to open."),confirm:ge.boolean().optional().describe("true = open it. Omit to preview.")}},async({path:r,confirm:o})=>{let a=Bt(r),i=dt(a)?re.readManifest(a):null;if(!i)return G(`Not a NoData sealed file: ${a}`,!0);if(!o)return G(`PREVIEW \u2014 nothing changed yet. ${t()}
58
+ Would open "${i.orig}" (sealed ${i.sealed_at}, device key ${i.kid}) as plaintext next to ${a}.
59
+ Ask the user to approve, then call nodata_open again with confirm: true.`);let s=await re.openFile(a);if(!s.ok){let d=s.error==="wrong_key"?"this device's key is not the one it was sealed to":s.error==="no_device_key"?"this machine has no device key (~/.nodata/device-key.json)":s.error;return G(`Could not open ${a}: ${d}.`,!0)}let c=re.writeLocalReceipt($t(a),{action:"open",kid:i.kid,removed_plaintext:!1,files:[{path:s.outPath,ndc:a,sha256:s.sha256,sealId:i.token.split(":").pop()??""}],extra:{approved_by:t(),surface:"mcp",hash_matches:s.intact}});return G([`OPENED ${s.outPath} \u2014 ${t()}`,s.intact?"Hash matches what was sealed \u2014 the file is unaltered.":"WARNING: hash differs from the sealed record.",`Receipt: ${Fn(c).href}`].join(`
60
+ `))}),e.registerTool("nodata_redact",{description:"WORK on the rest: make a clean copy of a file with every sensitive value replaced by a typed token ([CARD], [ID], [IBAN], [PHONE], [EMAIL]); in CSV/TSV and Excel a column whose header names personal data (name, address, account number\u2026) is hidden whole, so rows and columns still line up. Same detectors as the scan. In Excel (.xlsx) the same column rule applies per sheet and the copy stays a workbook with its formatting. The original is untouched; the copy is written next to it as <name>.clean.<ext> (Word/PowerPoint/PDF \u2192 .clean.txt). return_text:true also returns the clean text (up to 60 KB) so it can be analysed right here \u2014 it contains no detected value.",inputSchema:{path:ge.string().describe("The file to redact (csv, tsv, txt, md, json, log, docx, xlsx, pptx, pdf)."),return_text:ge.boolean().optional().describe("Also return the clean text for analysis.")}},async({path:r,return_text:o})=>{let a=Bt(r);if(!dt(a)||!Kn(a).isFile())return G(`Not a file: ${a}`,!0);let i=Os(a).toLowerCase(),s=Ns(a),c,d=i||".txt",u="",p=i===".xlsx"||i===".xlsm"?On(s):null;if(p){let y=ut($t(a),`${Kt(a,i)}.clean${i}`);return jn(y,p.bytes,{mode:384}),c={text:ot(p.bytes,i)?.text??"",counts:p.counts,columnsHidden:p.columnsHidden},G(n(y,c,o))}if((i===".xlsx"||i===".xlsm")&&(u="This workbook has pivot tables, charts or external links, which keep their own copies of the values \u2014 the clean copy is plain text, not a workbook."),i===".csv"||i===".tsv")c=Dn(s.toString("utf8"),i===".tsv"?" ":void 0);else if(Ot.has(i)){let y=ot(s,i);if(!y)return G(`Could not read the text of ${a}.`,!0);c=ye(y.text),d=".txt"}else c=ye(s.toString("utf8"));let f=ut($t(a),`${Kt(a,i)}.clean${d}`);return jn(f,c.text,{mode:384}),G(n(f,c,o,u))});function n(r,o,a,i=""){let s=Object.entries(o.counts).sort((d,u)=>u[1]-d[1]).map(([d,u])=>` ${String(u).padStart(6)} ${d}`),c=[`CLEAN COPY ${r} \u2014 ${t()} \xB7 original untouched`,i,s.length?`Replaced:
61
+ ${s.join(`
62
+ `)}`:"Nothing sensitive detected \u2014 the copy equals the original text.",o.columnsHidden.length?`Columns hidden whole: ${o.columnsHidden.join(", ")}`:""].filter(Boolean);return a&&c.push("",`--- clean text${o.text.length>6e4?" (first 60000 chars)":""} ---`,o.text.slice(0,6e4)),c.join(`
63
+ `)}}var on=Or(Ta(),1);import{z as Ke}from"zod";import{createHash as Jl}from"node:crypto";import{existsSync as gr,mkdirSync as zl,readFileSync as Na,readdirSync as Yl,statSync as Pa,writeFileSync as Xl}from"node:fs";import{homedir as Zl}from"node:os";import{basename as mr,extname as Ql,join as Ca,resolve as ed}from"node:path";var X=(e,t=!1)=>({content:[{type:"text",text:e}],...t?{isError:t}:{}}),rn=Ca(Zl(),".nodata","shares"),td=12*1024*1024,nd={".pdf":"application/pdf",".txt":"text/plain",".csv":"text/csv",".md":"text/markdown",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation"};function Ra(e){return Ca(rn,`${e.replace(/[^a-f0-9]/gi,"")}.json`)}function Da(e){let t=Ra(e);if(!gr(t))return null;try{return JSON.parse(Na(t,"utf8"))}catch{return null}}function Oa(e){let t=e.match(/\/lock\/open\/([a-f0-9]{8,64})/i);return(t?t[1]:e.trim()).toLowerCase()}async function Ia(e,t,n){let r=await fetch(e,{method:"POST",headers:{"content-type":"application/json",...n?{authorization:`Bearer ${n}`}:{}},body:JSON.stringify(t)});return{status:r.status,body:await r.json().catch(()=>({}))}}function $a(e,t,n,r){e.registerTool("nodata_send",{description:"SEND a file as a governed link: encrypted on this machine (post-quantum hybrid), stored by NoData only as ciphertext \u2014 the key rides in the link's #fragment, which NoData never receives. Expires after ttl and after max_opens opens; can be burned (nodata_burn) at any time, after which nobody can open it again. Filed under your organization with a signed receipt and a proof_url. ASKS FIRST: without confirm:true it only shows what would be sent. Returns the link to hand to the recipient.",inputSchema:{path:Ke.string().describe("The file to send (up to 12 MB)."),ttl_hours:Ke.number().optional().describe("Hours until the link expires. Default 72, max 168 (7 days)."),max_opens:Ke.number().optional().describe("Opens allowed before it burns itself. Default 3, max 1000."),confirm:Ke.boolean().optional().describe("true = send it. Omit to preview.")}},async({path:o,ttl_hours:a,max_opens:i,confirm:s})=>{let c=ed(o);if(!gr(c)||!Pa(c).isFile())return X(`Not a file: ${c}`,!0);let d=Pa(c).size;if(d>td)return X(`${mr(c)} is ${(d/1048576).toFixed(1)} MB; a governed link carries up to 12 MB.`,!0);let u=Math.round(Math.min(Math.max(a??72,1/60),168)*3600),p=Math.round(Math.min(Math.max(i??3,1),1e3));if(!s)return X([`PREVIEW \u2014 nothing sent yet. ${r()}`,`Would send "${mr(c)}" (${(d/1024).toFixed(1)} KB) as a governed link:`," \xB7 encrypted here; NoData stores only ciphertext and never gets the key",` \xB7 expires in ${(u/3600).toFixed(u<3600?2:0)} h, or after ${p} open(s)`," \xB7 revocable any time with nodata_burn; every open is counted","","Ask the user to approve, then call nodata_send again with the same arguments and confirm: true."].join(`
64
+ `));let f=Na(c),y=mr(c),b=nd[Ql(c).toLowerCase()]??"application/octet-stream",k=await(0,on.sealBytesForPublicShare)({bytes:f,filename:y,contentType:b,ttlSeconds:u,server:t}),S=await(0,on.wrapFragmentForShortLink)(k.fragment),_;try{_=await Ia(`${t}/api/lock/public/issue`,{formatVersion:3,lockboxId:k.lockboxId,containerB64:Buffer.from(k.container).toString("base64"),filename:y,contentType:b,ttlSeconds:u,maxOpens:p,wrappedFragmentB64:S.wrappedFragmentB64,wrapIvB64:S.wrapIvB64},await n())}catch(m){return X(`Could not reach NoData: ${m instanceof Error?m.message:String(m)}`,!0)}if(_.status>=400||_.body.ok!==!0)return X(`Send refused (HTTP ${_.status}): ${JSON.stringify(_.body)}`,!0);let v=String(_.body.id),E={id:v,file:c,filename:y,sha256:Jl("sha256").update(f).digest("hex"),link:`${t}/lock/open/${v}#${S.wrapKeyB64Url}`,wrap_key_b64url:S.wrapKeyB64Url,expires_at:String(_.body.expiresAt??""),max_opens:p,sent_by:r(),sent_at:new Date().toISOString(),receipt_id:_.body.receipt_id??null,proof_url:_.body.proof_url??null};return zl(rn,{recursive:!0}),Xl(Ra(v),JSON.stringify(E,null,2)+`
65
+ `,{mode:384}),X([`SENT "${y}" \u2014 ${r()}`,"Link (give this to the recipient; anyone holding it can open it until it expires or is burned):",` ${E.link}`,`Expires ${E.expires_at} \xB7 max ${p} open(s) \xB7 id ${v}`,E.proof_url?`Proof (signed receipt, public): ${E.proof_url}`:"No receipt: the link was not attributed to an organization.",`Check it: nodata_link_status id: "${v}" \xB7 Revoke it: nodata_burn id: "${v}"`].join(`
66
+ `))}),e.registerTool("nodata_link_status",{description:"STATUS of links sent with nodata_send: opens so far, expiry, whether burned. Pass an id or link for one; omit to list every link sent from this machine.",inputSchema:{id:Ke.string().optional().describe("Share id or /lock/open link. Omit to list all.")}},async({id:o})=>{let a=o?[Oa(o)]:gr(rn)?Yl(rn).filter(s=>s.endsWith(".json")).map(s=>s.slice(0,-5)):[];if(a.length===0)return X("No links sent from this machine yet. Send one with nodata_send.");let i=[`LINKS \u2014 ${r()}`];for(let s of a.slice(0,50)){let c=Da(s),d={};try{let p=await fetch(`${t}/api/lock/public/status/${s}`);d=await p.json().catch(()=>({})),p.status===404&&(d={missing:!0})}catch{d={unreachable:!0}}let u=d.missing?"not found":d.unreachable?"status unavailable":d.burned?"BURNED":d.expired?"expired":"live";i.push(` ${s} ${u.padEnd(10)} opens ${d.openCount??"?"}/${d.maxOpens??c?.max_opens??"?"} expires ${d.expiresAt??c?.expires_at??"?"} ${c?c.filename:""}`)}return X(i.join(`
67
+ `))}),e.registerTool("nodata_burn",{description:"BURN a link sent with nodata_send: the stored ciphertext is zeroed, so nobody \u2014 the recipient, a forwarded copy, NoData \u2014 can open it again. Irreversible. ASKS FIRST: without confirm:true it only says what would be burned. Returns the signed burn receipt and its proof_url.",inputSchema:{id:Ke.string().describe("Share id or the /lock/open link."),confirm:Ke.boolean().optional().describe("true = burn it. Omit to preview.")}},async({id:o,confirm:a})=>{let i=Oa(o),s=o.match(/#([A-Za-z0-9_-]{43})/)?.[1],c=Da(i),d=c?.wrap_key_b64url??s;if(!d)return X(`No burn key for ${i} on this machine. Pass the full link (it carries the key after #), or burn it from the machine that sent it.`,!0);if(!a)return X(`PREVIEW \u2014 nothing burned yet. ${r()}
68
+ Would burn ${c?`"${c.filename}" `:""}(${i}). After this NOBODY can open it again \u2014 irreversible.
69
+ Ask the user to approve, then call nodata_burn again with confirm: true.`);let u;try{u=await Ia(`${t}/api/lock/public/burn/${i}`,{wrapKeyB64Url:d})}catch(p){return X(`Could not reach NoData: ${p instanceof Error?p.message:String(p)}`,!0)}return u.status>=400||u.body.ok!==!0?X(`Burn refused (HTTP ${u.status}): ${JSON.stringify(u.body)}`,!0):X([`BURNED ${i} \u2014 ${r()}. The ciphertext is zeroed; the link is dead for everyone.`,u.body.proof_url?`Proof (signed receipt, public): ${u.body.proof_url}`:""].filter(Boolean).join(`
70
+ `))})}import{z as an}from"zod";import xe from"node:crypto";var _r=Buffer.from([78,68,67,49]),rd=2,br=36,At=32,od=64,ad=12,id=16,sd=4096,cd=256,Ba=32,Sr=8,ld=1;async function dd(){let[{CipherSuite:e,HkdfSha256:t},{DhkemX25519HkdfSha256:n},{Chacha20Poly1305:r}]=await Promise.all([import("@hpke/core"),import("@hpke/dhkem-x25519"),import("@hpke/chacha20poly1305")]);return new e({kem:new n,kdf:new t,aead:new r})}function wr(e){let t=new Uint8Array(e.length);return t.set(e),t.buffer}async function ud(e,t){let n=t.trim();if(n.includes("-----BEGIN PUBLIC KEY-----")){let o=n.replace(/-----BEGIN PUBLIC KEY-----/,"").replace(/-----END PUBLIC KEY-----/,"").replace(/\s+/g,"");return e.kem.deserializePublicKey(wr(Buffer.from(o,"base64")))}let r=Buffer.from(n.replace(/-/g,"+").replace(/_/g,"/"),"base64");if(r.length!==32)throw new Error(`master pubkey must be a 32-byte X25519 key, got ${r.length} bytes`);return e.kem.deserializePublicKey(wr(r))}function pd(e){let t=xe.createPublicKey({key:e,format:"pem"}).export({format:"der",type:"spki"});if(t.length<At)throw new Error("unexpected Ed25519 SPKI DER length");return t.subarray(t.length-At)}function fd(e){return xe.createHash("sha256").update(e,"utf8").digest().subarray(0,Sr)}async function Ka(e){let t=Buffer.from(e.filename,"utf8");if(t.length>sd)throw new Error("filename too long");let n=Buffer.from(e.contentType,"utf8");if(n.length>cd)throw new Error("content-type too long");let r=e.receiptId??xe.randomUUID(),o=Buffer.from(r,"utf8");if(o.length!==br)throw new Error("receiptId must be a 36-char canonical UUID");let a=pd(e.issuerPubkeyPem);if(a.length!==At)throw new Error("issuer pubkey must be 32 bytes");let i=xe.randomBytes(32),s=xe.randomBytes(ad),c=xe.createCipheriv("aes-256-gcm",i,s),d=Buffer.concat([c.update(e.fileBytes),c.final()]),u=c.getAuthTag();if(u.length!==id)throw new Error("unexpected GCM tag length");let p=xe.createHash("sha256").update(e.fileBytes).digest(),f=await dd(),y=await ud(f,e.recipientPubkeyB64),b=await f.createSenderContext({recipientPublicKey:y}),k=Buffer.from(b.enc),S=Buffer.from(await b.seal(wr(i))),_=fd(e.recipientPubkeyB64),v=1+Sr+2+k.length+2+S.length,E=_r.length+1+br+At+2+t.length+2+n.length+8+Ba+v,m=Buffer.alloc(E),g=0;_r.copy(m,g),g+=_r.length,m[g++]=rd,o.copy(m,g),g+=br,a.copy(m,g),g+=At,m.writeUInt16LE(t.length,g),g+=2,t.copy(m,g),g+=t.length,m.writeUInt16LE(n.length,g),g+=2,n.copy(m,g),g+=n.length,m.writeBigUInt64LE(BigInt(e.issuedAt??Date.now()),g),g+=8,p.copy(m,g),g+=Ba,m[g++]=ld,_.copy(m,g),g+=Sr,m.writeUInt16LE(k.length,g),g+=2,k.copy(m,g),g+=k.length,m.writeUInt16LE(S.length,g),g+=2,S.copy(m,g),g+=S.length;let A=xe.sign(null,m,e.issuerPrivateKey);if(A.length!==od)throw new Error("header signature must be 64 bytes");let C=Buffer.concat([m,A,s,u,d]),P={relative_path:"",plaintext_sha256:p.toString("hex"),size_bytes:e.fileBytes.length,lockbox_id:e.lockboxId??null,ndc_version:2,recovery_alg:1,recovery_master_fp:_.toString("hex"),header_sig_b64:A.toString("base64"),content_key_b64:i.toString("base64")};return{ndcBytes:C,report:P}}import{createPrivateKey as ja,createPublicKey as Ma,generateKeyPairSync as hd}from"node:crypto";import{existsSync as Er,mkdirSync as yd,readFileSync as Ua,rmSync as md,statSync as sn,writeFileSync as Ha}from"node:fs";import{homedir as La}from"node:os";import{basename as Tt,extname as gd,join as kr,resolve as _d}from"node:path";var ue=(e,t=!1)=>({content:[{type:"text",text:e}],...t?{isError:t}:{}}),Pt="mcp-archive",vr=25,Fa=25*1024*1024,bd={".pdf":"application/pdf",".txt":"text/plain",".csv":"text/csv",".md":"text/markdown",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation"},Sd={critical:"restricted",high:"confidential",medium:"internal",low:"internal",info:"internal"};function Va(e,t){if(e){let o=ja({key:Buffer.from(e,"base64"),format:"der",type:"pkcs8"});return{privateKey:o,publicPem:Ma(o).export({format:"pem",type:"spki"}),label:`device ${t??""}`.trim()}}let n=kr(La(),".nodata","issuer-ed25519.json");if(Er(n)){let o=JSON.parse(Ua(n,"utf8")).private_pem,a=ja(o);return{privateKey:a,publicPem:Ma(a).export({format:"pem",type:"spki"}),label:"this machine"}}let r=hd("ed25519");return yd(kr(La(),".nodata"),{recursive:!0}),Ha(n,JSON.stringify({private_pem:r.privateKey.export({format:"pem",type:"pkcs8"})},null,2)+`
71
+ `,{mode:384}),{privateKey:r.privateKey,publicPem:r.publicKey.export({format:"pem",type:"spki"}),label:"this machine"}}function Ga(e,t,n,r){e.registerTool("nodata_wrap",{description:"WRAP files into your organization's sovereign archive (a zero-knowledge capsule): each file is encrypted ON THIS MACHINE to the public half of your org master key \u2014 the 12 words from signup \u2014 and only ciphertext is uploaded. NoData can never open it; your 12 words (or recovery file) always can, even if this computer is lost or NoData is offline. Each document gets a signed receipt and proof_url. Given a folder, wraps the files the scan finds exposure in (classified by severity); given a file, wraps that file. ASKS FIRST: without confirm:true it only lists what would be wrapped. keep_local:true (default) also writes <file>.capsule.ndc next to the original; remove:true deletes the plaintext originals after a successful upload.",inputSchema:{path:an.string().describe("File or folder to wrap."),confirm:an.boolean().optional().describe("true = wrap it. Omit to preview."),keep_local:an.boolean().optional().describe("Also keep <file>.capsule.ndc next to the original. Default true."),remove:an.boolean().optional().describe("Delete plaintext originals after upload. Default false.")}},async({path:o,confirm:a,keep_local:i,remove:s})=>{let c=_d(o);if(!Er(c))return ue(`Not found: ${c}`,!0);let d;if(sn(c).isDirectory()?d=Pe(await it({target_id:"mcp",target_label:Tt(c),target_path:c,log:st})).byFile.map(g=>({path:kr(c,g.key),classification:Sd[g.worst]??"internal"})):d=[{path:c,classification:"confidential"}],d=d.filter(m=>Er(m.path)&&sn(m.path).isFile()&&!Un(m.path)),d.length===0)return ue(`Nothing to wrap in ${c} \u2014 no file with findings.`);let u=d.filter(m=>sn(m.path).size>Fa);d=d.filter(m=>sn(m.path).size<=Fa);let p=await t.get("/api/v1/recovery/pubkey");if(p.status===401||p.status===403)return ue(`Not authorized to read the org key (HTTP ${p.status}). Connect with nodata_connect.`,!0);let f=typeof p.body.pubkeyB64=="string"?p.body.pubkeyB64:null;if(!f)return ue(`Your organization has no master key yet \u2014 the 12-word recovery setup was not completed, so there is nothing to wrap to.
72
+ Finish it once in the console (Recovery setup), then wrap again. NoData never sees the words.`,!0);if(!a){let m=d.slice(0,vr).map(g=>` \xB7 [${g.classification}] ${g.path}`);return d.length>vr&&m.push(` \u2026 and ${d.length-vr} more`),ue([`PREVIEW \u2014 nothing wrapped yet. ${r()}`,`Would wrap ${d.length} file(s) into the "${Pt}" capsule, sealed to your org master key (fingerprint ${p.body.fingerprint??"?"}):`,...m,u.length?`Skipped (over 25 MB): ${u.map(g=>Tt(g.path)).join(", ")}`:"",`Encrypted here; only ciphertext is uploaded. Opens with your 12 words \u2014 never with NoData.${s?" Plaintext originals WILL BE DELETED after upload.":""}`,"","Ask the user to approve, then call nodata_wrap again with the same arguments and confirm: true."].filter(Boolean).join(`
73
+ `))}let y=await t.get("/api/v1/capsules");if(y.status>=400)return ue(`Could not list capsules (HTTP ${y.status}): ${JSON.stringify(y.body)}`,!0);let k=(y.body.capsules??[]).find(m=>m.slug===Pt);if(k&&k.key_mode!=="zk")return ue(`A "${Pt}" capsule exists but is not zero-knowledge (key_mode ${String(k.key_mode)}) \u2014 refusing to wrap into it.`,!0);if(!k){let m=await t.post("/api/v1/capsules",{handle:Pt,display_name:"MCP archive",key_mode:"zk",capsule_pubkey:f});if(m.status>=400)return ue(`Could not create the archive capsule (HTTP ${m.status}): ${JSON.stringify(m.body)}`,!0);k=m.body}let S=String(k.slug??k.capsule_id??"");if(!S)return ue(`Capsule id missing in ${JSON.stringify(k)}`,!0);let _=n(),v=[],E=[];for(let m of d){let g=Ua(m.path),{ndcBytes:A,report:C}=await Ka({fileBytes:g,filename:Tt(m.path),contentType:bd[gd(m.path).toLowerCase()]??"application/octet-stream",recipientPubkeyB64:f,issuerPrivateKey:_.privateKey,issuerPubkeyPem:_.publicPem}),P=await t.post(`/api/v1/capsules/${encodeURIComponent(S)}/documents`,{title:Tt(m.path),ndc_b64:A.toString("base64"),classification:m.classification,plaintext_sha256:C.plaintext_sha256,size_bytes:C.size_bytes});if(P.status>=400||P.body.ok!==!0){E.push(` \u2717 ${m.path} \u2014 HTTP ${P.status}: ${JSON.stringify(P.body).slice(0,200)}`);continue}i!==!1&&Ha(`${m.path}.capsule.ndc`,A,{mode:384}),s&&md(m.path),v.push(` \u2713 [${m.classification}] ${Tt(m.path)}${P.body.proof_url?` proof: ${P.body.proof_url}`:""}`)}return ue([`WRAPPED ${v.length}/${d.length} into "${Pt}" \u2014 ${r()} \xB7 signed by ${_.label}`,...v,...E,"Sealed to your org master key: NoData stores ciphertext only and cannot open it. Your 12 words (or recovery file) open every document.",i!==!1?"Local copies: <file>.capsule.ndc next to each original.":"",s?"Plaintext originals deleted (only for files that uploaded).":""].filter(Boolean).join(`
74
+ `),E.length>0&&v.length===0)})}import{homedir as Xa,hostname as Za}from"node:os";import{join as cn,resolve as xr}from"node:path";import{existsSync as Tr,readFileSync as Qa,writeFileSync as ei,mkdirSync as ti,chmodSync as Ed}from"node:fs";import{spawn as kd}from"node:child_process";import{generateKeyPairSync as xd,createPrivateKey as Ad,sign as Td,randomBytes as Pd}from"node:crypto";var Pr="1.3.1",ni=cn(Xa(),".nodata"),ln=cn(ni,"credentials.json");function Dd(){try{if(!Tr(ln))return null;let e=JSON.parse(Qa(ln,"utf8"));if(!e)return null;let t=e.device&&typeof e.device.private_key_pkcs8_b64=="string",n=typeof e.api_key=="string"&&e.api_key;return t||n?e:null}catch{return null}}function qa(e){ti(ni,{recursive:!0});let t=JSON.stringify({...e,saved_at:new Date().toISOString()},null,2);ei(ln,t,{mode:384});try{Ed(ln,384)}catch{}}var Od=`nodata-mcp v${Pr} \u2014 NoData MCP server
22
75
 
23
76
  ADMIN mode: nodata-mcp --api-key sk_live_...
24
77
  AGENT mode: nodata-mcp --grant-token ndca-...
@@ -27,12 +80,15 @@ import{McpServer as _t}from"@modelcontextprotocol/sdk/server/mcp.js";import{Stdi
27
80
 
28
81
  Env vars: NODATA_API_KEY \xB7 NODATA_GRANT_TOKEN \xB7 NODATA_BASE_URL
29
82
  Get a free API key: https://www.nodatacapsule.com/developers/get-started
30
- Mint a grant token: POST /api/v1/governance/grant (or the nodata_grant tool).`;function Pt(e){let t="",n="",a="https://www.nodatacapsule.com";for(let r=0;r<e.length;r++)e[r]==="--api-key"&&e[r+1]?t=e[++r]:e[r]==="--grant-token"&&e[r+1]?n=e[++r]:e[r]==="--base-url"&&e[r+1]?a=e[++r]:e[r]==="--help"||e[r]==="-h"?(console.log(Rt),process.exit(0)):e[r]==="--version"||e[r]==="-v"?(console.log(ae),process.exit(0)):e[r].startsWith("--")&&console.error(`nodata-mcp: unknown option '${e[r]}' (see --help)`);let i=t||n?"flag":"none";!t&&process.env.NODATA_API_KEY&&(t=process.env.NODATA_API_KEY,i="env"),!n&&process.env.NODATA_GRANT_TOKEN&&(n=process.env.NODATA_GRANT_TOKEN,i==="none"&&(i="env")),process.env.NODATA_BASE_URL&&(a=process.env.NODATA_BASE_URL);let o;if(!t&&!n){let r=$t();r&&(!process.env.NODATA_BASE_URL&&a==="https://www.nodatacapsule.com"&&r.base_url&&(a=r.base_url),r.device?(o=r.device,i="stored"):r.api_key&&(t=r.api_key,i="stored"))}return a=a.replace(/\/+$/,""),{apiKey:t,grantToken:n,baseUrl:a,credentialSource:i,device:o}}var Ee=3e4;async function Oe(e,t){let n;try{n=await fetch(e,{...t,signal:AbortSignal.timeout(Ee)})}catch(i){return{ok:!1,status:0,body:{error:i instanceof Error&&i.name==="TimeoutError"?`Request timed out after ${Ee/1e3}s: ${e}`:`Network error reaching ${e}: ${i instanceof Error?i.message:String(i)}`}}}let a;try{a=await n.json()}catch{a={error:`Non-JSON response (HTTP ${n.status})`}}return{ok:n.ok,status:n.status,body:a}}async function De(e){if(typeof e=="string")return{token:e};try{return{token:await e()}}catch(t){return{error:{ok:!1,status:0,body:{error:`Could not obtain an access token: ${t instanceof Error?t.message:String(t)}`}}}}}async function A(e,t,n,a){let i=await De(t);return"error"in i?i.error:Oe(`${e}${n}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i.token}`},body:JSON.stringify(a)})}async function xe(e,t,n,a){let i=await De(t);if("error"in i)return i.error;let o=new URL(`${e}${n}`);for(let[r,s]of Object.entries(a))s!==void 0&&s!==""&&o.searchParams.set(r,s);return Oe(o.toString(),{method:"GET",headers:{Authorization:`Bearer ${i.token}`}})}function I(e){let t=JSON.stringify(e.body,null,2);return e.ok?{content:[{type:"text",text:t}]}:{content:[{type:"text",text:`Error (HTTP ${e.status}):
31
- ${t}`}],isError:!0}}function Nt(e){let t=e?[M(e)]:[M(".env.local"),M(".env")];if(e&&!K(t[0]))return{error:`env file not found: ${t[0]}`};let n={},a=[];for(let o of t)if(K(o)){a.push(o);for(let r of Pe(o,"utf8").split(/\r?\n/)){let s=r.match(/^\s*(?:export\s+)?([A-Z0-9_]+)\s*=\s*(.*)\s*$/);!s||s[1]in n||(n[s[1]]=s[2].replace(/^(['"])(.*)\1$/,"$2").trim())}}let i=o=>{for(let r of o){let s=n[r]??process.env[r];if(s)return{name:r,value:s}}};return{url:i(["SUPABASE_URL","NEXT_PUBLIC_SUPABASE_URL","VITE_SUPABASE_URL","EXPO_PUBLIC_SUPABASE_URL"]),anon:i(["SUPABASE_ANON_KEY","NEXT_PUBLIC_SUPABASE_ANON_KEY","VITE_SUPABASE_ANON_KEY","EXPO_PUBLIC_SUPABASE_ANON_KEY","SUPABASE_PUBLISHABLE_KEY","NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY"]),jwt:i(["SUPABASE_JWT_SECRET","JWT_SECRET"]),files:a}}function Ot(e){try{let n=(e.startsWith("ndca-")?e.slice(5):e).split(".")[1];return n?JSON.parse(Buffer.from(n.replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")).handle??null:null}catch{return null}}var Dt=5*6e4;function Lt(){let{publicKey:e,privateKey:t}=At("ed25519"),n=e.export({format:"der",type:"spki"}),a=t.export({format:"der",type:"pkcs8"});return{publicKeyHex:n.subarray(-32).toString("hex"),privateKeyPkcs8B64:a.toString("base64")}}function Ut(e,t){let n=Tt({key:Buffer.from(e,"base64"),format:"der",type:"pkcs8"});return It(null,Buffer.from(t,"utf8"),n).toString("base64")}function Bt(){let e=$e().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,20)||"device";return`${/^[a-z]/.test(e)?e:`d-${e}`}-${Ct(3).toString("hex")}`.slice(0,32)}async function jt(e,t,n,a,i){let o=await A(e,t,"/api/v1/attest/devices",{handle:n,label:a,ed25519_pubkey_hex:i});if(o.ok){let r=o.body.org_id??"";return r?{ok:!0,orgId:r}:{ok:!1,status:o.status,error:"enroll response missing org_id"}}return{ok:!1,status:o.status,error:o.body?.error??`HTTP ${o.status}`}}async function Ft(e,t){let n=await A(e,"","/api/v1/attest/challenge",{org_id:t.org_id,handle:t.handle});if(!n.ok)throw new Error(`challenge: ${n.body?.error??`HTTP ${n.status}`}`);let{challenge:a,nonce:i}=n.body;if(!a||!i)throw new Error("challenge response malformed");let o=Ut(t.private_key_pkcs8_b64,a),r=await A(e,"","/api/v1/attest",{org_id:t.org_id,handle:t.handle,nonce:i,signature:o});if(!r.ok)throw new Error(`attest: ${r.body?.error??`HTTP ${r.status}`}`);let s=r.body;if(!s.allowed||!s.access_token)throw new Error(`attestation rejected: ${s.reason??"denied"}`);return{token:s.access_token,expiresAtMs:s.expires_at?Date.parse(s.expires_at):Date.now()+15*6e4}}function Mt(e,t){let n=null;return async()=>((!n||Date.now()>=n.expiresAtMs-Dt)&&(n=await Ft(e,t)),n.token)}function Ae(e,t,n){e.registerTool("nodata_register_table",{description:"Register one of your own tables as AI-agent-readable. This writes POLICY only: it declares which columns are sensitive (released per-column only if their ciphertext exists) and which are plaintext metadata. It does NOT encrypt or change anything in the user's database \u2014 never tell the user their data is now encrypted. Relay the response's `message` and `next_steps` verbatim. After this, grants can target the table.",inputSchema:{table_name:c.string().describe("Your SQL table name"),encrypted_columns:c.array(c.string()).describe("Columns stored as <col>_ct/_iv/_tag triplets"),plaintext_columns:c.array(c.string()).optional().describe("Plaintext metadata/filter columns"),classification_column:c.string().optional().describe("Plaintext column carrying the classification value")}},async({table_name:a,encrypted_columns:i,plaintext_columns:o,classification_column:r})=>{let s=await A(t,n,"/api/v1/governance/tables",{table_name:a,encrypted_columns:i,plaintext_columns:o??[],classification_column:r});return I(s)}),e.registerTool("nodata_connect_source",{description:"Connect the user's own Supabase project as the data source for their registered tables, so granted agents can read metadata through NoData. Reads the project URL, anon key and JWT secret from the user's LOCAL env file (e.g. .env.local) and sends them directly to NoData \u2014 never ask the user to paste a key or secret into the chat, and never print them. Only allowed_tables are readable (deny-by-default).",inputSchema:{allowed_tables:c.array(c.string()).describe("Tables agents may read through this source"),env_file:c.string().optional().describe("Path to the env file holding the Supabase keys (default: .env.local, then .env in the working directory)"),source_url:c.string().optional().describe("Override the project URL (https://<ref>.supabase.co) if the env file lacks it")}},async({allowed_tables:a,env_file:i,source_url:o})=>{let r=Nt(i);if("error"in r)return{content:[{type:"text",text:`Error: ${r.error}`}],isError:!0};let s=o??r.url?.value,l=[s?null:"project URL (SUPABASE_URL / NEXT_PUBLIC_SUPABASE_URL)",r.anon?null:"anon key (SUPABASE_ANON_KEY / NEXT_PUBLIC_SUPABASE_ANON_KEY)",r.jwt?null:"JWT secret (SUPABASE_JWT_SECRET \xB7 Supabase \u2192 Settings \u2192 API \u2192 JWT secret)"].filter(Boolean);if(l.length>0)return{content:[{type:"text",text:`Not sent. Missing in ${r.files.join(", ")||"the environment"}: ${l.join("; ")}.
32
- Ask the user to add them to that file themselves (not in this chat), then call this tool again.`}],isError:!0};let d=await A(t,n,"/api/connector/secrets",{source_url:s,allowed_tables:a,anon_key:r.anon.value,jwt_secret:r.jwt.value}),p={read_from:r.files,variables_used:[r.url?.name,r.anon.name,r.jwt.name].filter(Boolean)};return I({...d,body:{...d.body,...p}})}),e.registerTool("nodata_grant",{description:"Issue ONE AI agent a claim-scoped grant over your data \u2014 claims, not blanket access. Returns a grant_token (shown once) the agent presents to read. Denied columns never decrypt. For one agent over several tables pass `tables` in a single call \u2014 do NOT call this once per table, that creates a separate agent each time.",inputSchema:{agent:c.string().describe("Agent label (becomes its handle)"),tables:c.array(c.object({table:c.string(),columns:c.array(c.string()).describe("Columns the agent may read in this table"),where:c.record(c.string(),c.union([c.string(),c.number(),c.boolean()])).optional()})).optional().describe("Several tables for the same agent. When set, table/columns/where are ignored."),table:c.string().optional().describe("Single target table (default agent_demo_records)"),columns:c.array(c.string()).optional().describe("Columns the agent may read (single-table form)"),where:c.record(c.string(),c.union([c.string(),c.number(),c.boolean()])).optional().describe("Equality filter (plaintext cols only)"),classifications:c.array(c.string()).optional().describe("Allowed classification values; empty = no gating"),ttl_seconds:c.number().optional().describe("Token lifetime (default 30d, max 1y)")}},async({agent:a,tables:i,table:o,columns:r,where:s,classifications:l,ttl_seconds:d})=>{let p=await A(t,n,"/api/v1/governance/grant",{agent:a,...i?{tables:i}:{table:o,columns:r,where:s},classifications:l,ttl_seconds:d});return I(p)}),e.registerTool("nodata_revoke",{description:"Revoke an agent's grant by handle (kills all its active credentials) or by a specific jti. Revocation is mathematics \u2014 the next read 401s and any cached data is governance-dead.",inputSchema:{handle:c.string().optional().describe("Agent handle to revoke"),jti:c.string().optional().describe("Specific credential jti to revoke"),reason:c.string().optional()}},async({handle:a,jti:i,reason:o})=>{let r=await A(t,n,"/api/v1/governance/revoke",{handle:a,jti:i,reason:o});return I(r)}),e.registerTool("nodata_encrypt",{description:"Encrypt a sensitive field value using Capsule Blind Relay. Returns ciphertext. NoData stores nothing \u2014 the key is embedded in the ciphertext for YOU to store.",inputSchema:{field:c.string(),value:c.string(),context:c.string().optional()}},async({field:a,value:i,context:o})=>{let r={field:a,value:i};return o&&(r.context=o),I(await A(t,n,"/api/v1/encrypt",r))}),e.registerTool("nodata_decrypt",{description:"Decrypt a Capsule ciphertext back to plaintext (aes256gcm:v1:iv:cipher:key format).",inputSchema:{ciphertext:c.string(),field:c.string().optional(),requester:c.string().optional()}},async({ciphertext:a,field:i,requester:o})=>{let r={ciphertext:a};return i&&(r.field=i),o&&(r.requester=o),I(await A(t,n,"/api/v1/decrypt",r))}),e.registerTool("nodata_deliver",{description:"Create a burn-after-read secure link for delivering sensitive content. Returns a view URL and OTP.",inputSchema:{content:c.string(),to:c.string().optional(),maxViews:c.number().optional(),ttl:c.string().optional(),burn:c.boolean().optional()}},async({content:a,to:i,maxViews:o,ttl:r,burn:s})=>{let l={content:a};return i&&(l.to=i),o!==void 0&&(l.maxViews=o),r&&(l.ttl=r),s!==void 0&&(l.burn=s),I(await A(t,n,"/api/v1/deliver",l))}),e.registerTool("nodata_evidence",{description:"Field-level encrypt/decrypt/deliver events (field_access_log). Requires the Engine scope on the key. For the signed decision-receipt chain \u2014 grants, agent reads, denials \u2014 use nodata_proofs instead, which every org key can call. Metadata only.",inputSchema:{from:c.string().optional(),to:c.string().optional(),action:c.string().optional(),limit:c.number().optional()}},async({from:a,to:i,action:o,limit:r})=>{let s={from:a,to:i,action:o,limit:r!==void 0?String(r):void 0};return I(await xe(t,n,"/api/v1/evidence",s))}),e.registerTool("nodata_proofs",{description:"List your organization's signed proofs: every grant, agent read and denial, newest first. Content-free (labels, hashes, timestamps). Each proof can be verified by anyone, without an account, by POSTing its receipt_id to /api/access/verify. The response's `plan` says which proof types the user's plan includes and which need an upgrade (with the plan name) \u2014 relay it as is.",inputSchema:{receipt_id:c.string().optional().describe("Fetch one proof by id"),surface:c.string().optional().describe("Filter, e.g. 'governance.grant', 'agent.read'"),decision:c.string().optional().describe("Filter: 'grant' | 'allow' | 'deny' | 'revoke'"),from:c.string().optional().describe("ISO timestamp"),to:c.string().optional().describe("ISO timestamp"),limit:c.number().optional().describe("1..1000, default 50")}},async({receipt_id:a,surface:i,decision:o,from:r,to:s,limit:l})=>I(await xe(t,n,"/api/v1/proofs",{receipt_id:a,surface:i,decision:o,from:r,to:s,limit:l!==void 0?String(l):void 0})))}function Kt(e,t,n){let a=Ot(n);a||console.error("nodata-mcp: warning \u2014 could not derive an agent handle from the grant token (expected ndca-<jwt> with a 'handle' claim). nodata_decide/nodata_retrieve will work; nodata_read/nodata_use will fail until a valid grant token is provided."),e.registerTool("nodata_decide",{description:"Ask whether this agent MAY reach a resource, WITHOUT reading it. Returns a decision (allow / degrade / deny), the reachable column subset, an access-distance cost, and a signed proof \u2014 never any data. Use it to plan: check reachability before you retrieve. Hard-scoped to this server's grant token.",inputSchema:{table:c.string().describe("Table to check (must be in your grant)"),columns:c.array(c.string()).describe("Columns you want to reach"),where:c.record(c.string(),c.union([c.string(),c.number(),c.boolean()])).optional().describe("Equality filter (readable columns only)")}},async({table:i,columns:o,where:r})=>{let s=await A(t,n,"/api/access/decide",{resource:{table:i,columns:o,where:r},intent:"read"});return I(s)}),e.registerTool("nodata_retrieve",{description:"Retrieve prompt-ready context for a resource, filtered to exactly what this agent may see. Denied columns are never decrypted; the response includes an accounting of what was withheld (columns + estimated tokens saved) and a signed proof. Prefer this over a raw read when assembling an LLM prompt. Hard-scoped to this server's grant token.",inputSchema:{table:c.string().describe("Table to retrieve from (must be in your grant)"),columns:c.array(c.string()).describe("Columns to include in context"),where:c.record(c.string(),c.union([c.string(),c.number(),c.boolean()])).optional(),top_k:c.number().optional().describe("Max rows (default 50, max 200)")}},async({table:i,columns:o,where:r,top_k:s})=>{let l=await A(t,n,"/api/access/retrieve",{resource:{table:i,columns:o,where:r},top_k:s});return I(l)}),e.registerTool("nodata_read",{description:"Read governed data within this agent's grant. You may only request columns your grant allows \u2014 denied columns never decrypt server-side, and every read emits a cryptographic receipt. This tool is hard-scoped to the grant token this server was started with.",inputSchema:{table:c.string().describe("Table to read (must be in your grant)"),columns:c.array(c.string()).describe("Columns to read (must be in your grant)"),where:c.record(c.string(),c.union([c.string(),c.number(),c.boolean()])).optional(),limit:c.number().optional().describe("Max rows (default 50, max 200)")}},async({table:i,columns:o,where:r,limit:s})=>{if(!a)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let l=await A(t,n,`/api/agents/${encodeURIComponent(a)}/read`,{table:i,columns:o,where:r,limit:s});return I(l)}),e.registerTool("nodata_use",{description:"Invoke a pre-registered capability (deploy, send, charge, query, \u2026) WITHOUT receiving the secret. The Capsule injects the sealed credential server-side and returns only the result. You may invoke only capabilities your grant allows; the secret never reaches you. Hard-scoped to the grant token this server was started with.",inputSchema:{capability:c.string().describe("Capability name to invoke (must be in your grant, e.g. 'deploy-prod')"),params:c.record(c.string(),c.unknown()).optional().describe("Allowlisted params; unknown keys are dropped server-side"),resource_key:c.string().optional().describe("Optional folder/resource the action targets (enforced against corpus scope)")}},async({capability:i,params:o,resource_key:r})=>{if(!a)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let s=await A(t,n,`/api/agents/${encodeURIComponent(a)}/use`,{capability:i,params:o,resource_key:r});return I(s)}),e.registerTool("nodata_code_advise",{description:"Ask the blind code advisor to diagnose/fix a bug in a code capsule WITHOUT seeing its source. You receive guidance + a targeted diff + an exposure proof (source never left the boundary); the source is never returned to you. Requires the capsule owner to have granted this agent (scope.fabric_developers). Hard-scoped to this server's grant token.",inputSchema:{capsule_id:c.string().describe("The code capsule to advise on (you must be granted on it)"),question:c.string().optional().describe("What to fix / improve, in natural language"),note:c.string().optional().describe("Extra context for the advisor"),error:c.object({message:c.string().optional(),stack:c.string().optional(),kind:c.string().optional()}).optional().describe("An error the code produced, to guide the fix"),steer:c.string().optional().describe("A steer on a refine turn (e.g. 'no, round half-up')"),prior_diff:c.string().optional().describe("The previously proposed diff, to refine")}},async({capsule_id:i,question:o,note:r,error:s,steer:l,prior_diff:d})=>{if(!a)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let p=await A(t,n,`/api/agents/${encodeURIComponent(a)}/code-capsule/${encodeURIComponent(i)}/advise`,{question:o,note:r,error:s,steer:l,prior_diff:d});return I(p)}),e.registerTool("nodata_code_patch",{description:"Submit a fix to a code capsule as a SIGNED, queued patch WITHOUT seeing its source. Provide a raw unified `diff`, or a whole-file `replace` ({path, content}) that is diffed server-side against the sealed source. The source is never persisted or returned; you get back a patch id, the diff hash, and a receipt. Requires a capsule grant (scope.fabric_developers). Hard-scoped to this server's grant token.",inputSchema:{capsule_id:c.string().describe("The code capsule to patch (you must be granted on it)"),summary:c.string().optional().describe("Short human-readable summary of the fix"),diff:c.string().optional().describe("A raw unified diff (advanced)"),replace:c.object({path:c.string(),content:c.string()}).optional().describe("Whole-file replacement; the diff is synthesized server-side against sealed source")}},async({capsule_id:i,summary:o,diff:r,replace:s})=>{if(!a)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let l=await A(t,n,`/api/agents/${encodeURIComponent(a)}/code-capsule/${encodeURIComponent(i)}/patch`,{summary:o,diff:r,replace:s});return I(l)})}var Te=`WHAT NODATA DOES \u2014 in one line:
83
+ Mint a grant token: POST /api/v1/governance/grant (or the nodata_grant tool).`;function Id(e){let t="",n="",r="https://www.nodatacapsule.com";for(let i=0;i<e.length;i++)e[i]==="--api-key"&&e[i+1]?t=e[++i]:e[i]==="--grant-token"&&e[i+1]?n=e[++i]:e[i]==="--base-url"&&e[i+1]?r=e[++i]:e[i]==="--help"||e[i]==="-h"?(console.log(Od),process.exit(0)):e[i]==="--version"||e[i]==="-v"?(console.log(Pr),process.exit(0)):e[i].startsWith("--")&&console.error(`nodata-mcp: unknown option '${e[i]}' (see --help)`);let o=t||n?"flag":"none";!t&&process.env.NODATA_API_KEY&&(t=process.env.NODATA_API_KEY,o="env"),!n&&process.env.NODATA_GRANT_TOKEN&&(n=process.env.NODATA_GRANT_TOKEN,o==="none"&&(o="env")),process.env.NODATA_BASE_URL&&(r=process.env.NODATA_BASE_URL);let a;if(!t&&!n){let i=Dd();i&&(!process.env.NODATA_BASE_URL&&r==="https://www.nodatacapsule.com"&&i.base_url&&(r=i.base_url),i.device?(a=i.device,o="stored"):i.api_key&&(t=i.api_key,o="stored"))}return r=r.replace(/\/+$/,""),{apiKey:t,grantToken:n,baseUrl:r,credentialSource:o,device:a}}var Wa=3e4;async function ri(e,t){let n;try{n=await fetch(e,{...t,signal:AbortSignal.timeout(Wa)})}catch(o){return{ok:!1,status:0,body:{error:o instanceof Error&&o.name==="TimeoutError"?`Request timed out after ${Wa/1e3}s: ${e}`:`Network error reaching ${e}: ${o instanceof Error?o.message:String(o)}`}}}let r;try{r=await n.json()}catch{r={error:`Non-JSON response (HTTP ${n.status})`}}return{ok:n.ok,status:n.status,body:r}}async function dn(e){if(typeof e=="string")return{token:e};try{return{token:await e()}}catch(t){return{error:{ok:!1,status:0,body:{error:`Could not obtain an access token: ${t instanceof Error?t.message:String(t)}`}}}}}async function H(e,t,n,r){let o=await dn(t);return"error"in o?o.error:ri(`${e}${n}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.token}`},body:JSON.stringify(r)})}async function Ar(e,t,n,r){let o=await dn(t);if("error"in o)return o.error;let a=new URL(`${e}${n}`);for(let[i,s]of Object.entries(r))s!==void 0&&s!==""&&a.searchParams.set(i,s);return ri(a.toString(),{method:"GET",headers:{Authorization:`Bearer ${o.token}`}})}function U(e){let t=JSON.stringify(e.body,null,2);return e.ok?{content:[{type:"text",text:t}]}:{content:[{type:"text",text:`Error (HTTP ${e.status}):
84
+ ${t}`}],isError:!0}}function Nd(e){let t=e?[xr(e)]:[xr(".env.local"),xr(".env")];if(e&&!Tr(t[0]))return{error:`env file not found: ${t[0]}`};let n={},r=[];for(let a of t)if(Tr(a)){r.push(a);for(let i of Qa(a,"utf8").split(/\r?\n/)){let s=i.match(/^\s*(?:export\s+)?([A-Z0-9_]+)\s*=\s*(.*)\s*$/);!s||s[1]in n||(n[s[1]]=s[2].replace(/^(['"])(.*)\1$/,"$2").trim())}}let o=a=>{for(let i of a){let s=n[i]??process.env[i];if(s)return{name:i,value:s}}};return{url:o(["SUPABASE_URL","NEXT_PUBLIC_SUPABASE_URL","VITE_SUPABASE_URL","EXPO_PUBLIC_SUPABASE_URL"]),anon:o(["SUPABASE_ANON_KEY","NEXT_PUBLIC_SUPABASE_ANON_KEY","VITE_SUPABASE_ANON_KEY","EXPO_PUBLIC_SUPABASE_ANON_KEY","SUPABASE_PUBLISHABLE_KEY","NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY"]),jwt:o(["SUPABASE_JWT_SECRET","JWT_SECRET"]),files:r}}function Cd(e){try{let n=(e.startsWith("ndca-")?e.slice(5):e).split(".")[1];return n?JSON.parse(Buffer.from(n.replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")).handle??null:null}catch{return null}}var Rd=5*6e4;function $d(){let{publicKey:e,privateKey:t}=xd("ed25519"),n=e.export({format:"der",type:"spki"}),r=t.export({format:"der",type:"pkcs8"});return{publicKeyHex:n.subarray(-32).toString("hex"),privateKeyPkcs8B64:r.toString("base64")}}function Bd(e,t){let n=Ad({key:Buffer.from(e,"base64"),format:"der",type:"pkcs8"});return Td(null,Buffer.from(t,"utf8"),n).toString("base64")}function Kd(){let e=Za().toLowerCase().replace(/[^a-z0-9-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,20)||"device";return`${/^[a-z]/.test(e)?e:`d-${e}`}-${Pd(3).toString("hex")}`.slice(0,32)}async function jd(e,t,n,r,o){let a=await H(e,t,"/api/v1/attest/devices",{handle:n,label:r,ed25519_pubkey_hex:o});if(a.ok){let i=a.body.org_id??"";return i?{ok:!0,orgId:i}:{ok:!1,status:a.status,error:"enroll response missing org_id"}}return{ok:!1,status:a.status,error:a.body?.error??`HTTP ${a.status}`}}async function Md(e,t){let n=await H(e,"","/api/v1/attest/challenge",{org_id:t.org_id,handle:t.handle});if(!n.ok)throw new Error(`challenge: ${n.body?.error??`HTTP ${n.status}`}`);let{challenge:r,nonce:o}=n.body;if(!r||!o)throw new Error("challenge response malformed");let a=Bd(t.private_key_pkcs8_b64,r),i=await H(e,"","/api/v1/attest",{org_id:t.org_id,handle:t.handle,nonce:o,signature:a});if(!i.ok)throw new Error(`attest: ${i.body?.error??`HTTP ${i.status}`}`);let s=i.body;if(!s.allowed||!s.access_token)throw new Error(`attestation rejected: ${s.reason??"denied"}`);return{token:s.access_token,expiresAtMs:s.expires_at?Date.parse(s.expires_at):Date.now()+15*6e4}}function Ld(e,t){let n=null;return async()=>((!n||Date.now()>=n.expiresAtMs-Rd)&&(n=await Md(e,t)),n.token)}function Fd(e,t){let n=cn(Xa(),".nodata","approvals");ti(n,{recursive:!0});let r=cn(n,`${new Date().toISOString().replace(/[:.]/g,"-").slice(0,19)}-${e}.json`);return ei(r,JSON.stringify({kind:e,approved_at:new Date().toISOString(),...t},null,2)+`
85
+ `,{mode:384}),r}function Ud(e,t,n,r){e.registerTool("nodata_register_table",{description:"Register one of your own tables as AI-agent-readable. This writes POLICY only: it declares which columns are sensitive (released per-column only if their ciphertext exists) and which are plaintext metadata. It does NOT encrypt or change anything in the user's database \u2014 never tell the user their data is now encrypted. Relay the response's `message` and `next_steps` verbatim. After this, grants can target the table.",inputSchema:{table_name:h.string().describe("Your SQL table name"),encrypted_columns:h.array(h.string()).describe("Columns stored as <col>_ct/_iv/_tag triplets"),plaintext_columns:h.array(h.string()).optional().describe("Plaintext metadata/filter columns"),classification_column:h.string().optional().describe("Plaintext column carrying the classification value")}},async({table_name:o,encrypted_columns:a,plaintext_columns:i,classification_column:s})=>{let c=await H(t,n,"/api/v1/governance/tables",{table_name:o,encrypted_columns:a,plaintext_columns:i??[],classification_column:s});return U(c)}),e.registerTool("nodata_connect_source",{description:"Connect the user's own Supabase project as the data source for their registered tables, so granted agents can read metadata through NoData. Reads the project URL, anon key and JWT secret from the user's LOCAL env file (e.g. .env.local) and sends them directly to NoData \u2014 never ask the user to paste a key or secret into the chat, and never print them. Only allowed_tables are readable (deny-by-default).",inputSchema:{allowed_tables:h.array(h.string()).describe("Tables agents may read through this source"),env_file:h.string().optional().describe("Path to the env file holding the Supabase keys (default: .env.local, then .env in the working directory)"),source_url:h.string().optional().describe("Override the project URL (https://<ref>.supabase.co) if the env file lacks it")}},async({allowed_tables:o,env_file:a,source_url:i})=>{let s=Nd(a);if("error"in s)return{content:[{type:"text",text:`Error: ${s.error}`}],isError:!0};let c=i??s.url?.value,d=[c?null:"project URL (SUPABASE_URL / NEXT_PUBLIC_SUPABASE_URL)",s.anon?null:"anon key (SUPABASE_ANON_KEY / NEXT_PUBLIC_SUPABASE_ANON_KEY)",s.jwt?null:"JWT secret (SUPABASE_JWT_SECRET \xB7 Supabase \u2192 Settings \u2192 API \u2192 JWT secret)"].filter(Boolean);if(d.length>0)return{content:[{type:"text",text:`Not sent. Missing in ${s.files.join(", ")||"the environment"}: ${d.join("; ")}.
86
+ Ask the user to add them to that file themselves (not in this chat), then call this tool again.`}],isError:!0};let u=await H(t,n,"/api/connector/secrets",{source_url:c,allowed_tables:o,anon_key:s.anon.value,jwt_secret:s.jwt.value}),p={read_from:s.files,variables_used:[s.url?.name,s.anon.name,s.jwt.name].filter(Boolean)};return U({...u,body:{...u.body,...p}})}),e.registerTool("nodata_grant",{description:"Issue ONE AI agent a claim-scoped grant over your data \u2014 claims, not blanket access. Returns a grant_token (shown once) the agent presents to read. Denied columns never decrypt. For one agent over several tables pass `tables` in a single call \u2014 do NOT call this once per table, that creates a separate agent each time. ASKS FIRST: without confirm:true it returns the exact policy change and grants nothing \u2014 show it to the user and call again with confirm:true only after they approve. On confirm, a copy of the approval (who, what, when, the receipt and its proof_url \u2014 never the token) is kept in ~/.nodata/approvals.",inputSchema:{agent:h.string().describe("Agent label (becomes its handle)"),tables:h.array(h.object({table:h.string(),columns:h.array(h.string()).describe("Columns the agent may read in this table"),where:h.record(h.string(),h.union([h.string(),h.number(),h.boolean()])).optional()})).optional().describe("Several tables for the same agent. When set, table/columns/where are ignored."),table:h.string().optional().describe("Single target table (default agent_demo_records)"),columns:h.array(h.string()).optional().describe("Columns the agent may read (single-table form)"),where:h.record(h.string(),h.union([h.string(),h.number(),h.boolean()])).optional().describe("Equality filter (plaintext cols only)"),classifications:h.array(h.string()).optional().describe("Allowed classification values; empty = no gating"),ttl_seconds:h.number().optional().describe("Token lifetime (default 30d, max 1y)"),confirm:h.boolean().optional().describe("true = grant it. Omit to preview the policy change.")}},async({agent:o,tables:a,table:i,columns:s,where:c,classifications:d,ttl_seconds:u,confirm:p})=>{let f={agent:o,...a?{tables:a}:{table:i??"agent_demo_records",columns:s,where:c},classifications:d,ttl_seconds:u};if(!p){let k=(a??[{table:i??"agent_demo_records",columns:s??[],where:c}]).map(_=>` \xB7 ${_.table}: ${(_.columns??[]).join(", ")||"(no columns)"}${_.where?` where ${JSON.stringify(_.where)}`:""}`),S=u?`${Math.round(u/86400*10)/10} days`:"30 days (default)";return{content:[{type:"text",text:[`POLICY CHANGE \u2014 PREVIEW, nothing granted yet. Requested by ${r()}`,`Agent "${o}" would be able to read ONLY:`,...k,`Classifications: ${d?.length?d.join(", "):"not gated"}`,`Valid for: ${S}. Every other column stays sealed and every read is receipted.`,"","Ask the user to approve this change, then call nodata_grant again with the same arguments and confirm: true."].join(`
87
+ `)}]}}let y=await H(t,n,"/api/v1/governance/grant",f);if(y.ok){let b=y.body,k=Fd("grant",{approved_by:r(),request:f,result:{handle:b.handle,agent_id:b.agent_id,expires_at:b.expires_at,grant_receipt_id:b.grant_receipt_id,proof_url:b.proof_url}});y.body.approval_copy=k}return U(y)}),e.registerTool("nodata_policy",{description:"The POLICY BOARD: every AI agent in the organization and exactly what it can reach \u2014 tables, columns, classifications \u2014 plus status. Deny-by-default: an agent with no grant reaches nothing. Change it with nodata_grant (asks for approval first) and nodata_revoke (immediate). Content-free: names only, never a value.",inputSchema:{}},async()=>{let o=await Ar(t,n,"/api/v1/agents",{});if(!o.ok)return U(o);let i=o.body.agents??[],s=[`POLICY BOARD \u2014 ${r()}`,`${i.length} agent(s). Deny-by-default: no grant \u21D2 no access.`,""];for(let c of i){let d=c.scope,u=d?d.grants===0?"reaches nothing":`${d.tables_allowed.join(", ")||"(tables)"} \u2192 ${d.columns_allowed.join(", ")||"(no columns)"} \xB7 classifications: ${d.unrestricted_classifications?"not gated":d.classifications_allowed.join(", ")||"none"}`:"scope unavailable";s.push(` ${String(c.handle??c.name).padEnd(24)} ${String(c.status??"").padEnd(8)} ${u}`)}return s.push("",'Change: nodata_grant (preview \u2192 approve) \xB7 nodata_revoke handle: "<agent>" (immediate) \xB7 proofs: nodata_proofs'),{content:[{type:"text",text:s.join(`
88
+ `)}]}}),e.registerTool("nodata_revoke",{description:"Revoke an agent's grant by handle (kills all its active credentials) or by a specific jti. Revocation is mathematics \u2014 the next read 401s and any cached data is governance-dead.",inputSchema:{handle:h.string().optional().describe("Agent handle to revoke"),jti:h.string().optional().describe("Specific credential jti to revoke"),reason:h.string().optional()}},async({handle:o,jti:a,reason:i})=>{let s=await H(t,n,"/api/v1/governance/revoke",{handle:o,jti:a,reason:i});return U(s)}),e.registerTool("nodata_encrypt",{description:"Encrypt a sensitive field value using Capsule Blind Relay. Returns ciphertext. NoData stores nothing \u2014 the key is embedded in the ciphertext for YOU to store.",inputSchema:{field:h.string(),value:h.string(),context:h.string().optional()}},async({field:o,value:a,context:i})=>{let s={field:o,value:a};return i&&(s.context=i),U(await H(t,n,"/api/v1/encrypt",s))}),e.registerTool("nodata_decrypt",{description:"Decrypt a Capsule ciphertext back to plaintext (aes256gcm:v1:iv:cipher:key format).",inputSchema:{ciphertext:h.string(),field:h.string().optional(),requester:h.string().optional()}},async({ciphertext:o,field:a,requester:i})=>{let s={ciphertext:o};return a&&(s.field=a),i&&(s.requester=i),U(await H(t,n,"/api/v1/decrypt",s))}),e.registerTool("nodata_deliver",{description:"Create a burn-after-read secure link for delivering sensitive content. Returns a view URL and OTP.",inputSchema:{content:h.string(),to:h.string().optional(),maxViews:h.number().optional(),ttl:h.string().optional(),burn:h.boolean().optional()}},async({content:o,to:a,maxViews:i,ttl:s,burn:c})=>{let d={content:o};return a&&(d.to=a),i!==void 0&&(d.maxViews=i),s&&(d.ttl=s),c!==void 0&&(d.burn=c),U(await H(t,n,"/api/v1/deliver",d))}),e.registerTool("nodata_evidence",{description:"Field-level encrypt/decrypt/deliver events (field_access_log). Requires the Engine scope on the key. For the signed decision-receipt chain \u2014 grants, agent reads, denials \u2014 use nodata_proofs instead, which every org key can call. Metadata only.",inputSchema:{from:h.string().optional(),to:h.string().optional(),action:h.string().optional(),limit:h.number().optional()}},async({from:o,to:a,action:i,limit:s})=>{let c={from:o,to:a,action:i,limit:s!==void 0?String(s):void 0};return U(await Ar(t,n,"/api/v1/evidence",c))}),e.registerTool("nodata_proofs",{description:"List your organization's signed proofs: every grant, agent read and denial, newest first. Content-free (labels, hashes, timestamps). Each proof can be verified by anyone, without an account, by POSTing {proof_id: <its receipt_id>} to /api/access/verify. The response's `plan` says which proof types the user's plan includes and which need an upgrade (with the plan name) \u2014 relay it as is.",inputSchema:{receipt_id:h.string().optional().describe("Fetch one proof by id"),surface:h.string().optional().describe("Filter, e.g. 'governance.grant', 'agent.read'"),decision:h.string().optional().describe("Filter: 'grant' | 'allow' | 'deny' | 'revoke'"),from:h.string().optional().describe("ISO timestamp"),to:h.string().optional().describe("ISO timestamp"),limit:h.number().optional().describe("1..1000, default 50")}},async({receipt_id:o,surface:a,decision:i,from:s,to:c,limit:d})=>U(await Ar(t,n,"/api/v1/proofs",{receipt_id:o,surface:a,decision:i,from:s,to:c,limit:d!==void 0?String(d):void 0})))}function Hd(e,t,n){let r=Cd(n);r||console.error("nodata-mcp: warning \u2014 could not derive an agent handle from the grant token (expected ndca-<jwt> with a 'handle' claim). nodata_decide/nodata_retrieve will work; nodata_read/nodata_use will fail until a valid grant token is provided."),e.registerTool("nodata_decide",{description:"Ask whether this agent MAY reach a resource, WITHOUT reading it. Returns a decision (allow / degrade / deny), the reachable column subset, an access-distance cost, and a signed proof \u2014 never any data. Use it to plan: check reachability before you retrieve. Hard-scoped to this server's grant token.",inputSchema:{table:h.string().describe("Table to check (must be in your grant)"),columns:h.array(h.string()).describe("Columns you want to reach"),where:h.record(h.string(),h.union([h.string(),h.number(),h.boolean()])).optional().describe("Equality filter (readable columns only)")}},async({table:o,columns:a,where:i})=>{let s=await H(t,n,"/api/access/decide",{resource:{table:o,columns:a,where:i},intent:"read"});return U(s)}),e.registerTool("nodata_retrieve",{description:"Retrieve prompt-ready context for a resource, filtered to exactly what this agent may see. Denied columns are never decrypted; the response includes an accounting of what was withheld (columns + estimated tokens saved) and a signed proof. Prefer this over a raw read when assembling an LLM prompt. Hard-scoped to this server's grant token.",inputSchema:{table:h.string().describe("Table to retrieve from (must be in your grant)"),columns:h.array(h.string()).describe("Columns to include in context"),where:h.record(h.string(),h.union([h.string(),h.number(),h.boolean()])).optional(),top_k:h.number().optional().describe("Max rows (default 50, max 200)")}},async({table:o,columns:a,where:i,top_k:s})=>{let c=await H(t,n,"/api/access/retrieve",{resource:{table:o,columns:a,where:i},top_k:s});return U(c)}),e.registerTool("nodata_read",{description:"Read governed data within this agent's grant. You may only request columns your grant allows \u2014 denied columns never decrypt server-side, and every read emits a cryptographic receipt. This tool is hard-scoped to the grant token this server was started with.",inputSchema:{table:h.string().describe("Table to read (must be in your grant)"),columns:h.array(h.string()).describe("Columns to read (must be in your grant)"),where:h.record(h.string(),h.union([h.string(),h.number(),h.boolean()])).optional(),limit:h.number().optional().describe("Max rows (default 50, max 200)")}},async({table:o,columns:a,where:i,limit:s})=>{if(!r)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let c=await H(t,n,`/api/agents/${encodeURIComponent(r)}/read`,{table:o,columns:a,where:i,limit:s});return U(c)}),e.registerTool("nodata_use",{description:"Invoke a pre-registered capability (deploy, send, charge, query, \u2026) WITHOUT receiving the secret. The Capsule injects the sealed credential server-side and returns only the result. You may invoke only capabilities your grant allows; the secret never reaches you. Hard-scoped to the grant token this server was started with.",inputSchema:{capability:h.string().describe("Capability name to invoke (must be in your grant, e.g. 'deploy-prod')"),params:h.record(h.string(),h.unknown()).optional().describe("Allowlisted params; unknown keys are dropped server-side"),resource_key:h.string().optional().describe("Optional folder/resource the action targets (enforced against corpus scope)")}},async({capability:o,params:a,resource_key:i})=>{if(!r)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let s=await H(t,n,`/api/agents/${encodeURIComponent(r)}/use`,{capability:o,params:a,resource_key:i});return U(s)}),e.registerTool("nodata_code_advise",{description:"Ask the blind code advisor to diagnose/fix a bug in a code capsule WITHOUT seeing its source. You receive guidance + a targeted diff + an exposure proof (source never left the boundary); the source is never returned to you. Requires the capsule owner to have granted this agent (scope.fabric_developers). Hard-scoped to this server's grant token.",inputSchema:{capsule_id:h.string().describe("The code capsule to advise on (you must be granted on it)"),question:h.string().optional().describe("What to fix / improve, in natural language"),note:h.string().optional().describe("Extra context for the advisor"),error:h.object({message:h.string().optional(),stack:h.string().optional(),kind:h.string().optional()}).optional().describe("An error the code produced, to guide the fix"),steer:h.string().optional().describe("A steer on a refine turn (e.g. 'no, round half-up')"),prior_diff:h.string().optional().describe("The previously proposed diff, to refine")}},async({capsule_id:o,question:a,note:i,error:s,steer:c,prior_diff:d})=>{if(!r)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let u=await H(t,n,`/api/agents/${encodeURIComponent(r)}/code-capsule/${encodeURIComponent(o)}/advise`,{question:a,note:i,error:s,steer:c,prior_diff:d});return U(u)}),e.registerTool("nodata_code_patch",{description:"Submit a fix to a code capsule as a SIGNED, queued patch WITHOUT seeing its source. Provide a raw unified `diff`, or a whole-file `replace` ({path, content}) that is diffed server-side against the sealed source. The source is never persisted or returned; you get back a patch id, the diff hash, and a receipt. Requires a capsule grant (scope.fabric_developers). Hard-scoped to this server's grant token.",inputSchema:{capsule_id:h.string().describe("The code capsule to patch (you must be granted on it)"),summary:h.string().optional().describe("Short human-readable summary of the fix"),diff:h.string().optional().describe("A raw unified diff (advanced)"),replace:h.object({path:h.string(),content:h.string()}).optional().describe("Whole-file replacement; the diff is synthesized server-side against sealed source")}},async({capsule_id:o,summary:a,diff:i,replace:s})=>{if(!r)return{content:[{type:"text",text:"Error: could not derive agent handle from grant token."}],isError:!0};let c=await H(t,n,`/api/agents/${encodeURIComponent(r)}/code-capsule/${encodeURIComponent(o)}/patch`,{summary:a,diff:i,replace:s});return U(c)})}var Ja=`WHAT NODATA DOES \u2014 in one line:
33
89
  Give any agent real power over your data, without the power to leak it.
34
90
  (Possession is not permission: it can hold the key and still not read what you didn't allow.)
35
- `,Ht=`TURN THE DATA TOOLS ON \u2014 3 steps, about a minute, once:
91
+ `,Vd=`TURN THE DATA TOOLS ON \u2014 3 steps, about a minute, once:
36
92
 
37
93
  1. GET A KEY call nodata_connect (no arguments)
38
94
  -> opens the signup in your browser: email + company (~30s), a 12-word
@@ -45,42 +101,46 @@ Ask the user to add them to that file themselves (not in this chat), then call t
45
101
  3. ACTIVATE type /mcp (or restart Claude Code) so the tools load.
46
102
 
47
103
  COMING BACK LATER? Nothing to redo \u2014 it starts ready. If the tools look missing, just /mcp.
48
- `,zt=`NOW \u2014 TURN YOUR DATA INTO AN AGENT THAT CAN'T LEAK, in 3 asks (just say them in plain words):
49
-
50
- 1. SEE what's sensitive run nodata_scan_folder \u2014 scans a local folder right here, nothing
51
- uploads (or open https://www.nodatacapsule.com/ai-folder in a browser).
52
-
53
- 2. CHOOSE what to release say "let <agent> read name + plan on <table>, hide the rest"
54
- -> I run nodata_register_table + nodata_grant; the agent gets a token.
55
-
56
- 3. PROVE & control the agent now reads ONLY those columns \u2014 the rest never decrypt.
57
- "what did it see?" -> nodata_evidence \xB7 "cut it off" -> nodata_revoke
58
-
59
- Also: a secret even NoData can't read -> nodata_encrypt, then hand it over once -> nodata_deliver.
60
- `,Vt=`WHAT YOU CAN DO \u2014 scoped to your grant; you reach only what it allows, the rest never decrypts:
104
+ `,Gd=`YOUR WORKSPACE \u2014 say it in plain words; anything that changes files or policy asks you first:
105
+
106
+ 1. SEE "scan <folder>" -> nodata_scan_folder: the whole result + a full HTML report,
107
+ on this machine, nothing uploads.
108
+ 2. LOCK "lock what it found" -> nodata_protect: seals those files to this device (.ndc).
109
+ 3. WORK "clean copy of <file>" -> nodata_redact: values become [CARD], [ID] \u2026 \u2014 analyse the rest.
110
+ 4. RELEASE "open <file>.ndc" -> nodata_open, hash-checked.
111
+ 5. POLICY "who can read what?" -> nodata_policy \xB7 change it: nodata_grant (preview, then approve)
112
+ \xB7 nodata_revoke (immediate).
113
+ 6. PROVE "show me the proofs" -> nodata_proofs: every grant / read / deny, each with a proof_url.
114
+ 7. SEND "send <file> to \u2026" -> nodata_send: a governed link \u2014 revocable (nodata_burn), opens counted
115
+ (nodata_link_status), NoData never holds the key.
116
+ 8. ARCHIVE "archive <folder>" -> nodata_wrap: sealed to your 12-word org key; NoData can never open it.
117
+
118
+ Database tables: nodata_register_table + nodata_connect_source, then nodata_grant.
119
+ One secret value: nodata_encrypt, hand it over once: nodata_deliver.
120
+ `,qd=`WHAT YOU CAN DO \u2014 scoped to your grant; you reach only what it allows, the rest never decrypts:
61
121
 
62
122
  1. PLAN nodata_decide "may I reach X?" -> allow / partial / deny + a signed proof. No data moves.
63
123
  2. PULL nodata_retrieve prompt-ready context, allowed fields only, with a receipt.
64
124
  (nodata_read for raw governed rows.)
65
125
  3. ACT nodata_use run a capability with a secret injected server-side \u2014 you never see it.
66
- `,Ie=`STUCK? There's always a next step:
126
+ `,za=`STUCK? There's always a next step:
67
127
  - Don't see the nodata_* tools? They load when the client starts \u2014 type /mcp or restart.
68
128
  (Expected, not an error.)
69
129
  - No MCP at all? The same governance runs from one curl, or the guided page:
70
130
  https://www.nodatacapsule.com/developers/get-started
71
- `;function Ce(e){return e==="setup"?`You're connected to NoData \u2014 but there's NO key yet, so the data tools are still off.
131
+ `;function Ya(e){return e==="setup"?`You're connected to NoData \u2014 but there's NO key yet, so the data tools are still off.
72
132
 
73
133
  `:e==="agent"?`You're connected to NoData, scoped to one grant token.
74
134
 
75
135
  `:`You're connected to NoData (admin mode). You don't memorize commands \u2014 just ask in plain words.
76
136
 
77
- `}function Wt(e){if(e==="setup")return Ce(e)+Te+`
78
- `+Ht+`
79
- `+Ie;let t=e==="agent"?Vt:zt;return Ce(e)+Te+`
137
+ `}function Wd(e){if(e==="setup")return Ya(e)+Ja+`
138
+ `+Vd+`
139
+ `+za;let t=e==="agent"?qd:Gd;return Ya(e)+Ja+`
80
140
  `+t+`
81
- `+Ie}function Yt(e,t){e.registerTool("nodata_get_started",{description:"Call this FIRST (no arguments). NoData in one line: what you can achieve \u2014 an agent that cannot leak, a look at what is already exposed, a secret we cannot read \u2014 with the single next step for each, and how to recover if the tools or MCP seem stuck. If the user asks what NoData can do, how to start, or why the tools are missing, call this and relay it.",inputSchema:{}},async()=>({content:[{type:"text",text:Wt(t)}]}))}var Gt="/capsule-api/register";function Zt(e){let t=process.platform==="win32",n=process.platform==="darwin"?"open":t?"cmd":"xdg-open",a=t?["/c","start","",e]:[e];try{let i=xt(n,a,{stdio:"ignore",detached:!0});return i.on("error",()=>{}),i.unref(),!0}catch{return!1}}function Xt(e,t){e.registerTool("nodata_connect",{description:"Switch NoData's data tools on. Step 1: call with NO arguments to open the free signup in a browser (email + company, ~30s \u2014 also where your 12-word recovery phrase + email verification happen); it shows an ORG KEY once. Step 2: call this tool again with that key as `api_key` and it is saved on this machine, so every later start comes up ready with nothing to retype. Step 3: type /mcp (or restart) so the client loads the tools.",inputSchema:{api_key:c.string().optional().describe("The org key shown once at signup (ndp_\u2026 or sk_\u2026). Omit on the first call to open signup.")}},async({api_key:n})=>{let a=(n??"").trim();if(!a){let p=t+Gt;return{content:[{type:"text",text:(Zt(p)?`STEP 1 of 3 \u2014 opened the NoData signup in your browser:
141
+ `+za}function Jd(e,t){e.registerTool("nodata_get_started",{description:"Call this FIRST (no arguments). NoData in one line: what you can achieve \u2014 an agent that cannot leak, a look at what is already exposed, a secret we cannot read \u2014 with the single next step for each, and how to recover if the tools or MCP seem stuck. If the user asks what NoData can do, how to start, or why the tools are missing, call this and relay it.",inputSchema:{}},async()=>({content:[{type:"text",text:Wd(t)}]}))}var zd="/capsule-api/register";function Yd(e){let t=process.platform==="win32",n=process.platform==="darwin"?"open":t?"cmd":"xdg-open",r=t?["/c","start","",e]:[e];try{let o=kd(n,r,{stdio:"ignore",detached:!0});return o.on("error",()=>{}),o.unref(),!0}catch{return!1}}function Xd(e,t){e.registerTool("nodata_connect",{description:"Switch NoData's data tools on. Step 1: call with NO arguments to open the free signup in a browser (email + company, ~30s \u2014 also where your 12-word recovery phrase + email verification happen); it shows an ORG KEY once. Step 2: call this tool again with that key as `api_key` and it is saved on this machine, so every later start comes up ready with nothing to retype. Step 3: type /mcp (or restart) so the client loads the tools.",inputSchema:{api_key:h.string().optional().describe("The org key shown once at signup (ndp_\u2026 or sk_\u2026). Omit on the first call to open signup.")}},async({api_key:n})=>{let r=(n??"").trim();if(!r){let u=t+zd;return{content:[{type:"text",text:(Yd(u)?`STEP 1 of 3 \u2014 opened the NoData signup in your browser:
82
142
  `:`STEP 1 of 3 \u2014 open the NoData signup in your browser:
83
- `)+p+`
143
+ `)+u+`
84
144
 
85
145
  There, about a minute:
86
146
  - email + company (a personal email is fine for the sandbox)
@@ -89,21 +149,14 @@ There, about a minute:
89
149
 
90
150
  STEP 2 \u2014 come back and call this tool again with the key:
91
151
  nodata_connect api_key: "<the key you copied>"
92
- and I'll save it so you never paste it again. (Then STEP 3: type /mcp to activate.)`}]}}if(!/^(ndp_|sk_)/.test(a))return{content:[{type:"text",text:`That doesn't look like a NoData org key (it should start with ndp_ or sk_).
93
- Copy the key shown once on the signup page and try again: nodata_connect api_key: "ndp_\u2026".`}]};let{publicKeyHex:i,privateKeyPkcs8B64:o}=Lt(),r=Bt(),s=$e()||"this device",l=await jt(t,a,r,s,i);if(l.ok){try{we({device:{org_id:l.orgId,handle:r,label:s,private_key_pkcs8_b64:o,public_key_hex:i},base_url:t})}catch(p){return{content:[{type:"text",text:"Enrolled the device, but couldn't save it locally: "+(p instanceof Error?p.message:String(p))}]}}return{content:[{type:"text",text:`STEP 2 done \u2014 this device is enrolled as "${s}" (${r}), and only its PRIVATE key is
152
+ and I'll save it so you never paste it again. (Then STEP 3: type /mcp to activate.)`}]}}if(!/^(ndp_|sk_)/.test(r))return{content:[{type:"text",text:`That doesn't look like a NoData org key (it should start with ndp_ or sk_).
153
+ Copy the key shown once on the signup page and try again: nodata_connect api_key: "ndp_\u2026".`}]};let{publicKeyHex:o,privateKeyPkcs8B64:a}=$d(),i=Kd(),s=Za()||"this device",c=await jd(t,r,i,s,o);if(c.ok){try{qa({device:{org_id:c.orgId,handle:i,label:s,private_key_pkcs8_b64:a,public_key_hex:o},base_url:t})}catch(u){return{content:[{type:"text",text:"Enrolled the device, but couldn't save it locally: "+(u instanceof Error?u.message:String(u))}]}}return{content:[{type:"text",text:`STEP 2 done \u2014 this device is enrolled as "${s}" (${i}), and only its PRIVATE key is
94
154
  saved at ~/.nodata/credentials.json (readable only by you). The org key you pasted was NOT
95
155
  stored: every start now proves possession by signing a fresh challenge and gets a 15-minute token.
96
156
 
97
- STEP 3 \u2014 type /mcp (or restart Claude Code) and the admin tools appear. Next time: nothing to do.`}]}}let d=l.status===404||l.status===0;try{we({api_key:a,key_prefix:a.slice(0,12),base_url:t})}catch(p){return{content:[{type:"text",text:"Couldn't save locally: "+(p instanceof Error?p.message:String(p))+`
157
+ STEP 3 \u2014 type /mcp (or restart Claude Code) and the admin tools appear. Next time: nothing to do.`}]}}let d=c.status===404||c.status===0;try{qa({api_key:r,key_prefix:r.slice(0,12),base_url:t})}catch(u){return{content:[{type:"text",text:"Couldn't save locally: "+(u instanceof Error?u.message:String(u))+`
98
158
  As a fallback, pass it on launch: claude mcp add nodata --env NODATA_API_KEY=<your key> -- npx @nodatachat/mcp`}]}}return{content:[{type:"text",text:(d?`STEP 2 done \u2014 saved your key on this machine (device attestation isn't available on this
99
- server yet, so this is the key-at-rest path). `:`STEP 2 done \u2014 saved your key on this machine (device enrollment didn't succeed: ${l.error}). `)+`Every future start loads it automatically \u2014 no re-register, no re-paste.
100
-
101
- STEP 3 \u2014 type /mcp (or restart Claude Code) and the admin tools appear. Next time: nothing to do.`}]}})}function Jt(e){let t=ie(e);return e.error?t:t+`
102
-
103
- GOVERN what it surfaced \u2014 same journey, inside this command:
104
- \xB7 CHOOSE what an agent may read: nodata_register_table then nodata_grant (denied columns never decrypt)
105
- \xB7 PROVE every access afterwards: nodata_evidence
159
+ server yet, so this is the key-at-rest path). `:`STEP 2 done \u2014 saved your key on this machine (device enrollment didn't succeed: ${c.error}). `)+`Every future start loads it automatically \u2014 no re-register, no re-paste.
106
160
 
107
- Want a standalone deep scan any time? npx @nodatachat/nodata scan <folder> (this same engine).`}function qt(e){e.registerTool("nodata_scan_folder",{description:"SEE what's sensitive before you govern it. Scans a LOCAL folder for hardcoded secrets and unencrypted PII (checksum-validated \u2014 Israeli ID / Luhn credit-card / IBAN) with NoData's deep content scanner, reading PDFs and Office files too, ENTIRELY on this machine \u2014 nothing uploads, no credential needed. Returns the findings by file and severity plus the first fix, then points at nodata_register_table + nodata_grant to govern what it found. If the user asks to scan / audit / check a folder or repo for sensitive data, secrets, or exposure, call this.",inputSchema:{path:c.string().optional().describe("Folder to scan (absolute or relative). Default: the directory the server runs in.")}},async({path:t})=>{let n=(t??".").trim()||".",a=M(n);if(!K(a))return{content:[{type:"text",text:`No folder found at: ${a}
108
- Pass an existing path, e.g. nodata_scan_folder path: "."`}]};try{let i=await ne({target_id:"mcp",target_label:St(a),target_path:a,log:re});return{content:[{type:"text",text:Jt(i)}]}}catch(i){return{content:[{type:"text",text:`Scan failed: ${i instanceof Error?i.message:String(i)}`}],isError:!0}}})}async function Qt(){let{apiKey:e,grantToken:t,baseUrl:n,credentialSource:a,device:i}=Pt(process.argv.slice(2)),o=t?"agent":e||i?"admin":"setup",r=new _t({name:o==="agent"?"NoData (agent-scoped)":o==="setup"?"NoData (setup)":"NoData",version:ae});i?Ae(r,n,Mt(n,i)):e&&Ae(r,n,e),t&&Kt(r,n,t),Yt(r,o),o!=="agent"&&qt(r),o==="setup"?(Xt(r,n),console.error(`nodata-mcp: no credential given \u2014 running in setup mode (data tools disabled).
109
- Call nodata_connect (opens signup, enrolls this device), or pass --api-key / --grant-token. See --help.`)):i?console.error(`nodata-mcp: loaded device identity "${i.label}" (${i.handle}) \u2014 attest mode; tokens are minted per session.`):a==="stored"&&console.error("nodata-mcp: loaded saved credential from ~/.nodata/credentials.json (admin mode).");let s=new vt;await r.connect(s)}Qt().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
161
+ STEP 3 \u2014 type /mcp (or restart Claude Code) and the admin tools appear. Next time: nothing to do.`}]}})}async function Zd(){let{apiKey:e,grantToken:t,baseUrl:n,credentialSource:r,device:o}=Id(process.argv.slice(2)),a=t?"agent":e||o?"admin":"setup",i=new wd({name:a==="agent"?"NoData (agent-scoped)":a==="setup"?"NoData (setup)":"NoData",version:Pr}),s=()=>o?`device "${o.label}" (${o.handle}) \xB7 org ${o.org_id}`:e?`org key ${e.slice(0,12)}\u2026`:"not connected \u2014 local only",c=o?Ld(n,o):e||null;if(c){Ud(i,n,c,s),$a(i,n,async()=>{let p=await dn(c);if("error"in p)throw new Error("no usable org credential \u2014 run nodata_connect");return p.token},s);let u=async(p,f,y)=>{let b=await dn(c);if("error"in b)return{status:401,body:{error:"no usable org credential \u2014 run nodata_connect"}};let k=await fetch(`${n}${f}`,{method:p,headers:{authorization:`Bearer ${b.token}`,...y?{"content-type":"application/json"}:{}},...y?{body:JSON.stringify(y)}:{}});return{status:k.status,body:await k.json().catch(()=>({}))}};Ga(i,{get:p=>u("GET",p),post:(p,f)=>u("POST",p,f)},()=>Va(o?.private_key_pkcs8_b64,o?.label),s)}t&&Hd(i,n,t),Jd(i,a),a!=="agent"&&mo(i,s),a==="setup"?(Xd(i,n),console.error(`nodata-mcp: no credential given \u2014 running in setup mode (data tools disabled).
162
+ Call nodata_connect (opens signup, enrolls this device), or pass --api-key / --grant-token. See --help.`)):o?console.error(`nodata-mcp: loaded device identity "${o.label}" (${o.handle}) \u2014 attest mode; tokens are minted per session.`):r==="stored"&&console.error("nodata-mcp: loaded saved credential from ~/.nodata/credentials.json (admin mode).");let d=new vd;await i.connect(d)}Zd().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodatachat/mcp",
3
- "version": "1.1.0",
3
+ "version": "1.3.1",
4
4
  "description": "NoData MCP server: connect any MCP client (Claude Code, Codex, Cursor, VS Code) to the NoData Information Access Processor. Governed access for AI agents, with a verifiable proof for every decision.",
5
5
  "bin": {
6
6
  "nodata-mcp": "dist/index.js"
@@ -12,11 +12,19 @@
12
12
  "prepublishOnly": "npm run build"
13
13
  },
14
14
  "dependencies": {
15
+ "@hpke/chacha20poly1305": "^1.8.0",
16
+ "@hpke/core": "^1.9.0",
17
+ "@hpke/dhkem-x25519": "^1.8.0",
15
18
  "@modelcontextprotocol/sdk": "^1.29.0",
19
+ "@noble/curves": "^2.2.0",
20
+ "@noble/hashes": "^2.2.0",
21
+ "@noble/post-quantum": "^0.5.0",
16
22
  "zod": "^4.0.0"
17
23
  },
18
24
  "devDependencies": {
25
+ "@nodatachat/crypto": "^0.2.0",
19
26
  "@nodatachat/folder-scan": "^1.0.0",
27
+ "@nodatachat/protect": "^2.0.0",
20
28
  "@types/node": "^22.0.0",
21
29
  "esbuild": "^0.27.4",
22
30
  "tsx": "^4.0.0",