@priventai/core
v0.3.0
Published
AI agent runtime security: context-preserving tokenization, risk scoring, and policy enforcement
Maintainers
Readme
@priventai/core
Early Access. Privent is currently in private rollout. API keys are issued through our access process. Request access →
Runtime security for AI agents. Tokenize PII, secrets, and sensitive data before they reach LLMs; restore the originals only at trusted egress points.
"Customer: [email protected], Card: 4111-1111-1111-1111"
↓ tokenize
"Customer: [EMAIL_001], Card: [CREDIT_CARD_001]"
↓ LLM call
"Reply to [EMAIL_001] about [CREDIT_CARD_001]"
↓ detokenize at trusted sink
"Reply to [email protected] about 4111-1111-1111-1111"The LLM never sees raw secrets. Tokens are reversible, session-scoped, and deterministic within a session.
Features
- Hybrid detection — regex patterns for EMAIL, PHONE, CREDIT_CARD, IBAN, SSN, API_KEY, JWT, AWS_KEY, IP, URL out of the box; pluggable ML extractor.
- Session-scoped vault — same value maps to the same token within a session; cross-session tokens are randomized to block correlation attacks.
- Deep detokenization — walks nested objects, arrays, and strings; cycle-safe.
- Typed error taxonomy —
PriventErrorbase class plus 9 subclasses, each with aretryableflag and JSON serialization that scrubs sensitive fields. - Resilient HTTP client — exponential backoff with jitter, idempotency keys, AbortController-based timeouts.
- Fail-open by default — if Privent Cloud is unreachable, falls back to local regex detection rather than blocking traffic.
- Dual ESM + CJS build with full TypeScript types.
Installation
npm install @priventai/core
# or
pnpm add @priventai/core
# or
yarn add @priventai/coreRequires Node.js 20+.
Quick Start
import { PriventClient } from '@priventai/core';
const client = new PriventClient({
apiKey: process.env.PRIVENT_API_KEY, // request via https://www.privent.ai/request-access — without it, runs in regex-only mode
});
await client.withSession(async ({ vault }) => {
const { tokenizedText } = await client.tokenizer.tokenize(
'Customer: [email protected], Card: 4111111111111111',
vault,
{ kinds: ['EMAIL', 'CREDIT_CARD'] },
);
// tokenizedText === "Customer: [EMAIL_001], Card: [CREDIT_CARD_001]"
const llmResponse = await myLLM.invoke(tokenizedText);
const restored = await client.tokenizer.detokenize(llmResponse, vault);
return restored;
});
// vault.destroy() runs automatically in a finally blockAPI
PriventClient
Main entry point. Wires together a vault, tokenizer, risk scorer, policy engine, and audit logger.
const client = new PriventClient({
apiKey?: string; // defaults to PRIVENT_API_KEY env var
baseUrl?: string; // default: https://api.privent.ai
vaultFactory?: VaultFactory; // default: in-memory
tokenizer?: Tokenizer; // default: HybridTokenizer (regex)
riskScorer?: RiskScorer;
policyEngine?: PolicyEngine;
auditLogger?: AuditLogger;
maxRetries?: number; // default: 2
timeout?: number; // default: 30_000 ms
failPolicy?: 'open' | 'closed'; // default: 'open'
});client.withSession(fn)
Opens a session, gives fn a vault and IDs, and destroys the vault when fn resolves or throws.
const result = await client.withSession(async ({ vault, sessionId, traceId }) => {
// vault: TokenVault — store/retrieve tokens
// sessionId: per-session UUID
// traceId: correlation ID for audit logs
return doWork(vault);
});Tokenizer
const { tokenizedText, entities } = await client.tokenizer.tokenize(text, vault, {
kinds: ['EMAIL', 'PHONE'],
allowList: ['[email protected]'], // never tokenize
denyList: ['internal-project-x'], // always tokenize
customPatterns: [
{ kind: 'PROJECT_CODE', regex: /PROJ-\d{4}/g, confidence: 0.95 },
],
});Token format: [KIND_NNN] — e.g. [EMAIL_001], [CREDIT_CARD_003]
Built-in entity types:
| Kind | Confidence | Notes |
|---|---|---|
| EMAIL | 0.95 | RFC-pragmatic match |
| PHONE | 0.80 | International + national formats |
| CREDIT_CARD | 0.98 | Validated with Luhn checksum |
| IBAN | 0.97 | Country-aware length check |
| SSN | 0.90 | US format |
| API_KEY | 0.88 | Common provider prefixes (sk-, ghp_, xoxb-, …) |
| JWT | 0.98 | Three-segment base64url structure |
| AWS_KEY | 0.99 | AKIA… access key IDs |
| IP_ADDRESS | 0.85 | IPv4 |
| URL | 0.90 | http/https |
detokenizeDeep(value, vault)
Walks any value (string, object, array, Map, Set) and replaces tokens with their originals.
import { detokenizeDeep } from '@priventai/core';
const restored = await detokenizeDeep(
{ email: '[EMAIL_001]', items: ['[PHONE_001]', 'plain text'] },
vault,
);Cycle-safe (uses WeakSet), depth-limited to 64, skips binary buffers, fast-paths strings without [.
Vault
import { InMemoryTokenVault } from '@priventai/core/vault/memory';
const vault = new InMemoryTokenVault('session-1');
await vault.store({ token: '[EMAIL_001]', value: '[email protected]', kind: 'EMAIL', ... });
const entry = await vault.retrieve('[EMAIL_001]');
const same = await vault.findByValue('[email protected]', 'EMAIL'); // determinism
await vault.destroy();Normalization for determinism: EMAIL → lowercase + trim; PHONE, CREDIT_CARD, IBAN → digits only; others → trim.
Errors
import {
PriventError,
PriventConfigError,
PriventAuthError,
PriventRateLimitError,
PriventAPIError,
PriventNetworkError,
PriventTimeoutError,
PriventValidationError,
PriventVaultFullError,
PriventVaultDestroyedError,
} from '@priventai/core';
try {
await client.tokenizer.tokenize(text, vault);
} catch (err) {
if (err instanceof PriventError) {
console.log(err.code, err.retryable, err.toJSON());
}
}toJSON() scrubs sensitive fields so errors are safe to log.
Security Properties
- No persistence by default. The in-memory vault holds entries for the session lifetime only.
- Cross-session randomization. Token IDs are not derived from input value — observing tokens across sessions reveals nothing.
- Bounded vaults. Default cap of 10,000 entries per session prevents unbounded growth.
- Sensitive fields scrubbed in error JSON. API keys, tokens, and entity values are stripped before serialization.
- Idempotency keys on every Cloud request to make retries safe.
Documentation
- Privent Documentation
- Request access — required to obtain a production API key
License
Apache-2.0 © Privent AI
Questions? Contact us at [email protected].
