{"_id":"@agentlair/vault-crypto","name":"@agentlair/vault-crypto","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@agentlair/vault-crypto","version":"0.1.0","description":"Client-side encryption for AgentLair Vault. Zero-knowledge AES-256-GCM + HKDF. Works in Node, Bun, Deno, and browsers.","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsc","test":"bun test"},"keywords":["agentlair","vault","encryption","aes-gcm","hkdf","zero-knowledge","web-crypto","agent","secrets"],"author":{"name":"AgentLair"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/piiiico/agentlair-vault-crypto.git"},"homepage":"https://agentlair.dev","engines":{"node":">=18.0.0"},"devDependencies":{"typescript":"^5.9.3"},"gitHead":"d7b0522e2aab9e07c5736549ba3495afec819418","_id":"@agentlair/vault-crypto@0.1.0","bugs":{"url":"https://github.com/piiiico/agentlair-vault-crypto/issues"},"_nodeVersion":"24.3.0","_npmVersion":"11.11.1","dist":{"integrity":"sha512-G8eZ5rsNlDrmhbz4CKT3vElR91mdxRfwsKSDObjgqSQKsALFAekMg3sReqc7vtqVuIQPv+pcjnPPhP6oCyqg9Q==","shasum":"bf6104bd847efc2cc1c445264eda7da2abfd9c9d","tarball":"https://registry.npmjs.org/@agentlair/vault-crypto/-/vault-crypto-0.1.0.tgz","fileCount":6,"unpackedSize":31224,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC9g3U0Lg6vnfFkwQKWbJwwf67wSmrY8yWcrHPh+KvmkwIhAKLRv1LbahJhtoJWDgmNZI7lTcuO00Khdh2d6EG2muzB"}]},"_npmUser":{"name":"piiiico","email":"pico@amdal.dev"},"directories":{},"maintainers":[{"name":"piiiico","email":"pico@amdal.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vault-crypto_0.1.0_1773612709756_0.050063705688526916"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-15T22:11:49.648Z","0.1.0":"2026-03-15T22:11:49.926Z","modified":"2026-03-15T22:11:50.572Z"},"maintainers":[{"name":"piiiico","email":"pico@amdal.dev"}],"description":"Client-side encryption for AgentLair Vault. Zero-knowledge AES-256-GCM + HKDF. Works in Node, Bun, Deno, and browsers.","homepage":"https://agentlair.dev","keywords":["agentlair","vault","encryption","aes-gcm","hkdf","zero-knowledge","web-crypto","agent","secrets"],"repository":{"type":"git","url":"git+https://github.com/piiiico/agentlair-vault-crypto.git"},"author":{"name":"AgentLair"},"bugs":{"url":"https://github.com/piiiico/agentlair-vault-crypto/issues"},"license":"MIT","readme":"# @agentlair/vault-crypto\n\nClient-side encryption for [AgentLair Vault](https://agentlair.dev). Zero-knowledge — your secrets are encrypted before they leave your runtime. AgentLair stores opaque blobs and can never read your plaintext.\n\n**No dependencies.** Uses only the Web Crypto API (built into Node ≥18, Bun, Deno, and browsers).\n\n## Install\n\n```bash\n# npm\nnpm install @agentlair/vault-crypto\n\n# Bun\nbun add @agentlair/vault-crypto\n\n# Deno (no install needed)\nimport { VaultCrypto } from 'npm:@agentlair/vault-crypto';\n```\n\n## Quick Start\n\n```typescript\nimport { VaultCrypto } from '@agentlair/vault-crypto';\n\n// 1. Generate a master seed (do this once per agent)\nconst seed = VaultCrypto.generateSeed();\nconst vc = VaultCrypto.fromSeed(seed);\n\n// 2. Encrypt a secret\nconst ciphertext = await vc.encrypt('sk-openai-abc123', 'openai-key');\n\n// 3. Store it in AgentLair Vault\nawait fetch('https://agentlair.dev/v1/vault/openai-key', {\n  method: 'PUT',\n  headers: {\n    'Authorization': 'Bearer al_live_...',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({ ciphertext }),\n});\n\n// 4. Later — retrieve and decrypt\nconst res = await fetch('https://agentlair.dev/v1/vault/openai-key', {\n  headers: { 'Authorization': 'Bearer al_live_...' },\n});\nconst { ciphertext: stored } = await res.json();\nconst plaintext = await vc.decrypt(stored, 'openai-key');\n// plaintext === 'sk-openai-abc123'\n```\n\n## API\n\n### `VaultCrypto.generateSeed()`\n\nGenerate a cryptographically random 32-byte master seed.\n\n```typescript\nconst seed = VaultCrypto.generateSeed(); // Uint8Array (32 bytes)\n```\n\nStore this seed securely — or back it up with a passphrase (see [Backup & Recovery](#backup--recovery)).\n\n---\n\n### `VaultCrypto.fromSeed(masterSeed)`\n\nCreate a `VaultCrypto` instance from a 32-byte seed.\n\n```typescript\n// From Uint8Array\nconst vc = VaultCrypto.fromSeed(seed);\n\n// From hex string (e.g., stored in an env var)\nconst vc = VaultCrypto.fromSeed('a3f1...'); // 64-char hex\n```\n\n---\n\n### `VaultCrypto.fromPassphrase(passphrase, salt?)`\n\nDerive a `VaultCrypto` instance from a human-memorable passphrase.\n\nUses PBKDF2-SHA-256 with 600,000 iterations. Deterministic: the same passphrase always produces the same master seed, enabling recovery without storing the seed.\n\n```typescript\nconst vc = await VaultCrypto.fromPassphrase('correct-horse-battery-staple');\n```\n\n> **Note:** For automated agents, prefer `generateSeed()` + `fromSeed()`. Use `fromPassphrase` for human operators or as the recovery passphrase that wraps a random seed.\n\n---\n\n### `vc.encrypt(plaintext, keyName?)`\n\nEncrypt a string. Returns a base64url-encoded ciphertext.\n\n```typescript\nconst ciphertext = await vc.encrypt('my-secret-value', 'vault-key-name');\n```\n\n- **`keyName`** (optional, default: `'default'`): The name of the vault key. Used for per-key derivation — different key names produce different AES keys, so you can only decrypt with the correct key name.\n- Each call produces a different ciphertext (random 12-byte IV). The same plaintext encrypted twice yields different ciphertexts.\n\n---\n\n### `vc.decrypt(ciphertext, keyName?)`\n\nDecrypt a ciphertext produced by `encrypt()`. Returns the original string.\n\n```typescript\nconst plaintext = await vc.decrypt(ciphertext, 'vault-key-name');\n```\n\nThrows if the ciphertext is tampered, the key name is wrong, or the seed is different.\n\n---\n\n### `vc.seedHex()`\n\nGet the master seed as a 64-character hex string (for backup or env var storage).\n\n```typescript\nconst hex = vc.seedHex();\n// Store in .env: VAULT_SEED=a3f1...\n```\n\n---\n\n## Backup & Recovery\n\nIf the agent's container dies and the seed is lost, you can recover using a passphrase. The recommended pattern:\n\n### 1. Back up the seed\n\n```typescript\nconst seed = VaultCrypto.generateSeed();\nconst vc = VaultCrypto.fromSeed(seed);\n\n// Encrypt the seed with a human-memorable passphrase\nconst seedBackup = await vc.encryptSeedBackup('operator-passphrase');\n\n// Store the backup in Vault under the reserved key '_master_seed_backup'\nawait fetch('https://agentlair.dev/v1/vault/_master_seed_backup', {\n  method: 'PUT',\n  headers: { 'Authorization': 'Bearer al_live_...', 'Content-Type': 'application/json' },\n  body: JSON.stringify({ ciphertext: seedBackup }),\n});\n```\n\n### 2. Recover after container loss\n\n```typescript\n// 1. Request a recovery link via email\nawait fetch('https://agentlair.dev/v1/vault/recover', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ email: 'operator@example.com' }),\n});\n\n// 2. Click the magic link → you get back all encrypted entries, including _master_seed_backup\n\n// 3. Restore the VaultCrypto instance from the backup\nconst restoredVc = await VaultCrypto.decryptSeedBackup(seedBackup, 'operator-passphrase');\n\n// 4. All secrets are now accessible again\nconst apiKey = await restoredVc.decrypt(openaiKeyCiphertext, 'openai-key');\n```\n\n### `vc.encryptSeedBackup(passphrase)`\n\nEncrypt the master seed with a passphrase for storage in Vault.\n\n```typescript\nconst backup = await vc.encryptSeedBackup('my-recovery-passphrase');\n```\n\n### `VaultCrypto.decryptSeedBackup(encryptedBackup, passphrase)`\n\nRestore a `VaultCrypto` instance from a seed backup.\n\n```typescript\nconst restored = await VaultCrypto.decryptSeedBackup(backup, 'my-recovery-passphrase');\n```\n\n---\n\n## Crypto Primitives\n\n| Operation | Algorithm |\n|---|---|\n| Per-key derivation | HKDF-SHA-256, info = `agentlair:vault:v1:{keyName}` |\n| Encryption | AES-256-GCM, 12-byte random IV |\n| Ciphertext format | base64url(IV[12] \\|\\| ciphertext+tag[N]) |\n| Passphrase → seed | PBKDF2-SHA-256, 600,000 iterations, salt = `agentlair-vault-v1` |\n\nAll primitives are from the **Web Crypto API** (no external dependencies). Works identically across Node ≥18, Bun, Deno, and modern browsers.\n\n---\n\n## Node.js Example\n\n```typescript\nimport { VaultCrypto } from '@agentlair/vault-crypto';\n\nconst vc = VaultCrypto.fromSeed(process.env.VAULT_SEED!);\nconst plaintext = await vc.decrypt(storedCiphertext, 'db-password');\n```\n\n## Bun Example\n\n```typescript\nimport { VaultCrypto } from '@agentlair/vault-crypto';\n\nconst vc = await VaultCrypto.fromPassphrase(Bun.env.VAULT_PASSPHRASE!);\nconst ciphertext = await vc.encrypt(process.env.OPENAI_KEY!, 'openai');\n```\n\n## Deno Example\n\n```typescript\nimport { VaultCrypto } from 'npm:@agentlair/vault-crypto';\n\nconst vc = VaultCrypto.fromSeed(Deno.env.get('VAULT_SEED')!);\nconst secret = await vc.decrypt(ciphertext, 'my-key');\n```\n\n## Browser Example\n\n```typescript\nimport { VaultCrypto } from '@agentlair/vault-crypto';\n\n// Generate and show seed to user (prompt them to save it)\nconst seed = VaultCrypto.generateSeed();\nconst vc = VaultCrypto.fromSeed(seed);\nconsole.log('Save your seed:', vc.seedHex());\n```\n\n---\n\n## License\n\nMIT © [AgentLair](https://agentlair.dev)\n","readmeFilename":"README.md","_rev":"1-810e2f0bf1876be8776c860e54981600"}