{"_id":"@demystify/ai-guardrails","_rev":"2-2b4ec25c0606cdfa1d0b61273fdfa5b3","name":"@demystify/ai-guardrails","dist-tags":{"latest":"0.3.1"},"versions":{"0.3.0":{"name":"@demystify/ai-guardrails","version":"0.3.0","keywords":["llm","guardrails","pii","dpdp","prompt-injection","india","aadhaar","redaction"],"author":{"name":"Demystify Systems"},"license":"MIT","_id":"@demystify/ai-guardrails@0.3.0","maintainers":[{"name":"demystifier09","email":"me@demystifysystem.com"}],"homepage":"https://github.com/demystify-systems/ai-services-tools/tree/main/packages/ai-guardrails","bugs":{"url":"https://github.com/demystify-systems/ai-services-tools/issues"},"dist":{"shasum":"9e5977691a47237915cbddff06247e5fa57c89d6","tarball":"https://registry.npmjs.org/@demystify/ai-guardrails/-/ai-guardrails-0.3.0.tgz","fileCount":5,"integrity":"sha512-UjlM3HLDXDQJnrfaBAZZSbzDc52D69KvOfuwOW7wC1XFnncMo01oRDuzlPtR27ikBmnj0RGTuy+55DjwLbujoA==","signatures":[{"sig":"MEUCIHtNzcYVeps8ox9dNozEyRHdpP9igyL26F9yQ2kZVTQvAiEA5V5ycGujbYqdYvUyvm27oXwtN5pBjs60ab7oi19rgQQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17340},"main":"./dist/index.js","type":"module","_from":"file:demystify-ai-guardrails-0.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint . && prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","test":"vitest run","build":"tsup","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\""},"_npmUser":{"name":"demystifier09","email":"me@demystifysystem.com"},"_resolved":"/tmp/d80cdd8c354e7264f985ce1fe3e7717f/demystify-ai-guardrails-0.3.0.tgz","_integrity":"sha512-UjlM3HLDXDQJnrfaBAZZSbzDc52D69KvOfuwOW7wC1XFnncMo01oRDuzlPtR27ikBmnj0RGTuy+55DjwLbujoA==","repository":{"url":"git+https://github.com/demystify-systems/ai-services-tools.git","type":"git","directory":"packages/ai-guardrails"},"_npmVersion":"10.9.8","description":"Input/output safety for LLM calls: checksum-gated Indian PII detection and redaction (Aadhaar/PAN/GSTIN/IFSC/phone/account), prompt-injection detection scoped to untrusted spans, and a configurable policy. Zero dependencies, offline, pure. Leaf package.","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.17.0","vitest":"^3.0.0","prettier":"^3.4.2","@eslint/js":"^9.17.0","typescript":"~5.7.2","@types/node":"^22.10.2","typescript-eslint":"^8.18.1","@vitest/coverage-v8":"^3.0.0","@stryker-mutator/core":"^9.6.1","@stryker-mutator/vitest-runner":"^9.6.1"},"_npmOperationalInternal":{"tmp":"tmp/ai-guardrails_0.3.0_1786507699406_0.7404984183036825","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@demystify/ai-guardrails","version":"0.3.1","description":"Input/output safety for LLM calls: checksum-gated Indian PII detection and redaction (Aadhaar/PAN/GSTIN/IFSC/phone/account), prompt-injection detection scoped to untrusted spans, and a configurable policy. Zero dependencies, offline, pure. Leaf package.","license":"MIT","author":{"name":"Demystify Systems"},"homepage":"https://github.com/demystify-systems/ai-services-tools/tree/main/packages/ai-guardrails","repository":{"type":"git","url":"git+https://github.com/demystify-systems/ai-services-tools.git","directory":"packages/ai-guardrails"},"type":"module","engines":{"node":">=22"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"devDependencies":{"@eslint/js":"^9.17.0","@stryker-mutator/core":"^9.6.1","@stryker-mutator/vitest-runner":"^9.6.1","@types/node":"^22.10.2","@vitest/coverage-v8":"^3.0.0","eslint":"^9.17.0","prettier":"^3.4.2","tsup":"^8.3.5","typescript":"~5.7.2","typescript-eslint":"^8.18.1","vitest":"^3.0.0"},"publishConfig":{"access":"public"},"keywords":["llm","guardrails","pii","dpdp","prompt-injection","india","aadhaar","redaction"],"scripts":{"build":"tsup","lint":"eslint . && prettier --check \"src/**/*.ts\" \"test/**/*.ts\"","format":"prettier --write \"src/**/*.ts\" \"test/**/*.ts\"","test":"vitest run"},"_id":"@demystify/ai-guardrails@0.3.1","bugs":{"url":"https://github.com/demystify-systems/ai-services-tools/issues"},"_integrity":"sha512-d7cu4PaUp+9bTpkQkOseG05gD+54LL7NsMX6bhX76l0B75Oof/VeX4UuPwt2VG4pCyMGbED78gwSAd3mvOAkgw==","_resolved":"/tmp/738d43ce401652cd0767ecd1745687c5/demystify-ai-guardrails-0.3.1.tgz","_from":"file:demystify-ai-guardrails-0.3.1.tgz","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-d7cu4PaUp+9bTpkQkOseG05gD+54LL7NsMX6bhX76l0B75Oof/VeX4UuPwt2VG4pCyMGbED78gwSAd3mvOAkgw==","shasum":"ed6469cc24fd18b58b1b5ee7bc0f968a02bdfe4d","tarball":"https://registry.npmjs.org/@demystify/ai-guardrails/-/ai-guardrails-0.3.1.tgz","fileCount":5,"unpackedSize":17393,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCg/AbM5ZeOb9zJII89nS2ph9b98OzMaKfz7t/cqmGbnQIgDR8LoZrlHF8+eIERoepQDo/tTR5RXrN3XvMXCGH5FDE="}]},"_npmUser":{"name":"demystifier09","email":"me@demystifysystem.com"},"directories":{},"maintainers":[{"name":"demystifier09","email":"me@demystifysystem.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai-guardrails_0.3.1_1787129289648_0.7265318588355787"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-12T04:08:19.254Z","modified":"2026-08-19T08:48:09.996Z","0.3.0":"2026-08-12T04:08:19.555Z","0.3.1":"2026-08-19T08:48:09.794Z"},"bugs":{"url":"https://github.com/demystify-systems/ai-services-tools/issues"},"author":{"name":"Demystify Systems"},"license":"MIT","homepage":"https://github.com/demystify-systems/ai-services-tools/tree/main/packages/ai-guardrails","keywords":["llm","guardrails","pii","dpdp","prompt-injection","india","aadhaar","redaction"],"repository":{"type":"git","url":"git+https://github.com/demystify-systems/ai-services-tools.git","directory":"packages/ai-guardrails"},"description":"Input/output safety for LLM calls: checksum-gated Indian PII detection and redaction (Aadhaar/PAN/GSTIN/IFSC/phone/account), prompt-injection detection scoped to untrusted spans, and a configurable policy. Zero dependencies, offline, pure. Leaf package.","maintainers":[{"name":"demystifier09","email":"me@demystifysystem.com"}],"readme":"# @demystify/ai-guardrails — input/output safety for LLM calls\n\nPII detection and redaction before text reaches a prompt, plus prompt-injection\ndetection scoped to untrusted spans.\n\nPure, **zero runtime dependencies**, offline, no clock, no model call. Safe to run\nsynchronously in front of every prompt on a serverless path.\n\n## Install\n\n```bash\npnpm add @demystify/ai-guardrails\n```\n\n## Quickstart\n\n```ts\nimport { guardUntrusted } from \"@demystify/ai-guardrails\";\n\n// OCR'd invoice text, about to be interpolated into a prompt.\nconst { text, spans, hasFindings } = guardUntrusted(ocrText);\n\ntext;            // PII masked, ready for the prompt\nspans[0].pii;    // [{ kind: \"gstin\", … }, { kind: \"phone_in\", … }]\nspans[0].flagged // true if the document tried to talk to your model\n```\n\nMulti-span, when you are assembling a prompt from mixed sources:\n\n```ts\nimport { applyPolicy } from \"@demystify/ai-guardrails\";\n\nconst result = applyPolicy(\n  [\n    { text: systemInstructions, trust: \"trusted\" },\n    { text: ocrText,            trust: \"untrusted\" },\n    { text: whatsappBody,       trust: \"untrusted\" },\n  ],\n  { onInjection: \"strip\" },\n);\n```\n\n## Two design decisions worth knowing\n\n### 1. Trust is per-span, never per-message\n\nYour own system prompt legitimately contains override-shaped language (\"ignore any\nprevious formatting instructions\"). Scanning a whole prompt flags it, and a detector\nthat cries wolf on your own instructions gets switched off. So:\n\n- **`untrusted`** — OCR'd documents, inbound WhatsApp/email bodies, retrieved pages,\n  user-uploaded CSVs. Scanned for injection.\n- **`trusted`** — your system instructions. Not scanned.\n- Unlabelled spans default to **untrusted**: a span whose provenance nobody recorded\n  is not one to take on faith.\n\n**PII is redacted in every span regardless.** Trust is about instruction authority, not\nabout whether an Aadhaar number may be sent to a provider.\n\n### 2. Detection is checksum-gated\n\nA detector that fires on every 12-digit run redacts invoice numbers, order ids and\nconcatenated phone numbers as if they were Aadhaar. A team whose real data keeps\ngetting mangled turns redaction off, and a guardrail that is off protects nothing.\n\n| Identifier | Gate |\n|---|---|\n| Aadhaar | Verhoeff check digit + first digit 2–9 (UIDAI issues no 0/1 prefixes) |\n| GSTIN | mod-36 check character, valid state code, **and** a valid embedded PAN |\n| PAN | structure + holder-type character (4th char) |\n| IFSC | structure (no checksum exists) |\n| Phone (IN) | `+91` / leading-`0` / bare, spaced or hyphenated |\n| Email | structure |\n| Bank account | 9–18 digits — **the one detector that must guess.** Runs last, claims only spans no other detector took, and can be disabled via `piiKinds`. |\n\nGSTIN embeds a PAN, so ordering is the resolution rule: the first detector to claim a\nspan wins.\n\nMasks keep the last four digits where that is permitted and useful — UIDAI allows\ndisplaying the last four of an Aadhaar, and \"which account was that?\" is unanswerable\nwithout them. A PAN is removed whole; no part of it is safe to show.\n\n## Injection signals\n\n`instruction_override` · `role_impersonation` · `exfiltration` · `tool_coercion` ·\n`delimiter_break` · `encoded_payload`\n\nThe score saturates toward 1 rather than summing past it, and each signal counts\n**once** — fifty copies of the same trick is one trick. Default threshold `0.4`.\n\n`onInjection`: `annotate` (default, you decide) · `block` (refuse the input) ·\n`strip` (drop the flagged span).\n\n> **This is heuristic and says so.** It raises the cost of an attack; it does not make\n> injection impossible. The durable defence is never granting an untrusted span\n> authority in the first place — keep it in a user-role message, never a system one,\n> and never let it choose a tool.\n\n## DPDP posture\n\nThe contract is **raw PII never reaches a provider**, which is stronger and far more\ntestable than a retention promise. Redaction happens before the prompt is built, not\nbefore the log is written.\n\nFindings carry the matched `value` so callers can act on it. **Do not log that field.**\n\n## Testing\n\n```bash\npnpm test    # 33 tests\n```\n\n100% statements / 94% branches. The negative tests matter most: an ordinary amount, a\nyear, an invoice number and a PAN-shaped reference that fails the holder-type rule must\nall survive untouched.\n\n## Status\n\nNew in the Demystify substrate — nothing in the federation had PII redaction or\ninjection defence before this. A Python twin (`demystify-ai-guardrails`) is next: the\nextraction worker is Python and OCR'd text reaching a prompt is exactly the untrusted\nspan this package exists for.\n\nMIT.\n","readmeFilename":"README.md"}