npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nebutra/vault

v0.1.1

Published

> **Status: Foundation** — Type definitions, factory pattern, and provider stubs are complete. Provider implementations require external service credentials to activate. See inline TODOs for integration points.

Readme

Status: Foundation — Type definitions, factory pattern, and provider stubs are complete. Provider implementations require external service credentials to activate. See inline TODOs for integration points.

@nebutra/vault

Application-layer secrets vault with envelope encryption for secure storage of customer credentials, API keys, OAuth tokens, and certificates.

Features

  • Envelope Encryption — Unique Data Encryption Key (DEK) per secret, with Key Encryption Key (KEK) rotation
  • Two Backends — AWS KMS (production) or local HKDF-based derivation (dev/self-hosted)
  • Provider Agnostic — Switch between KMS and local without changing application code
  • Tenant Isolation — Optional tenant ID support for multi-tenant systems
  • Key Rotation — Rotate individual secrets or the KEK itself

Installation

pnpm add @nebutra/vault

Quick Start

import { getVault } from "@nebutra/vault";

// Auto-detects provider from environment
const vault = await getVault();

// Encrypt a secret
const encrypted = await vault.encrypt("my-api-key-12345", {
  metadata: {
    name: "stripe_api_key",
    type: "api_key",
  },
});

// Decrypt it back
const plaintext = await vault.decrypt(encrypted);
console.log(plaintext); // "my-api-key-12345"

Architecture

Envelope Encryption

Each secret is encrypted using a two-layer encryption scheme:

┌─────────────────────────────────────┐
│ Root Key (AWS KMS or Master Key)    │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ Key Encryption Key (KEK)            │  ← Encrypts DEKs
│ AWS KMS: Managed by KMS             │
│ Local: Derived via HKDF from master │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ Data Encryption Keys (DEK)          │  ← One per secret
│ AWS KMS: Generated by GenerateKey   │
│ Local: Random 32-byte key           │
└────────────┬────────────────────────┘
             │
             ▼
┌─────────────────────────────────────┐
│ Secret Payload (AES-256-GCM)        │  ← Your API key, token, etc.
└─────────────────────────────────────┘

AWS KMS Provider

Uses AWS Key Management Service for KEK operations:

  • Encrypt: GenerateDataKey returns plaintext DEK + KMS-encrypted DEK
  • Decrypt: Decrypt recovers plaintext DEK from KMS-encrypted version
  • Rotate: Generate new DEK, re-encrypt secret, discard old DEK
  • KEK Rotation: AWS KMS CMK automatic rotation (configured in AWS console)
import { createVault } from "@nebutra/vault";

const vault = await createVault({
  provider: "aws-kms",
  keyId: "arn:aws:kms:us-east-1:123456789012:key/12345678-...",
  region: "us-east-1",
});

const encrypted = await vault.encrypt("secret-token");
const plaintext = await vault.decrypt(encrypted);

Local Provider

Derives KEK from a master key using HKDF (suitable for dev/self-hosted):

  • Encrypt: Derive KEK → generate random DEK → encrypt DEK with KEK → encrypt secret with DEK
  • Decrypt: Derive KEK → decrypt DEK with KEK → decrypt secret with DEK
  • Rotate: Same as AWS KMS
  • KEK Rotation: Increment version number; future secrets use new version, old ones remain decryptable
import { createVault } from "@nebutra/vault";

const vault = await createVault({
  provider: "local",
  masterKey: "my-ultra-secret-master-key-32-chars-min",
});

const encrypted = await vault.encrypt("secret-token");
const plaintext = await vault.decrypt(encrypted);

API

createVault(config?: VaultConfig)

Create an explicit vault provider instance.

// AWS KMS
const vault = await createVault({
  provider: "aws-kms",
  keyId: process.env.AWS_KMS_KEY_ID,
  region: "us-east-1",
});

// Local
const vault = await createVault({
  provider: "local",
  masterKey: process.env.VAULT_MASTER_KEY,
});

getVault()

Get or create the default singleton vault provider. Auto-detects backend from environment.

const vault = await getVault();

vault.encrypt(plaintext, options?)

Encrypt a plaintext secret.

interface EncryptOptions {
  id?: string;              // Auto-generated if omitted
  tenantId?: string;        // For multi-tenant systems
  metadata?: {
    name: string;
    type: "api_key" | "oauth_token" | "credential" | "certificate" | "generic";
    expiresAt?: string;     // ISO-8601 datetime
  };
}

const encrypted = await vault.encrypt("my-secret-api-key", {
  id: "secret_abc123",
  tenantId: "tenant_xyz",
  metadata: {
    name: "stripe_live_key",
    type: "api_key",
    expiresAt: "2026-12-31T23:59:59Z",
  },
});

// Returns:
{
  id: "secret_abc123",
  ciphertext: "...",          // base64
  encryptedDek: "...",        // base64
  iv: "...",                  // base64
  authTag: "...",             // base64
  keyVersion: 1,
  algorithm: "aes-256-gcm",
  tenantId: "tenant_xyz",
  metadata: { ... },
  createdAt: "2026-03-29T...",
}

vault.decrypt(encrypted, options?)

Decrypt an encrypted secret.

interface DecryptOptions {
  tenantId?: string;  // Verify tenant ID matches
}

const plaintext = await vault.decrypt(encrypted, {
  tenantId: "tenant_xyz",  // Will throw if mismatch
});

console.log(plaintext);  // "my-secret-api-key"

vault.rotateKey(encrypted)

Rotate a secret in place — generate new DEK, re-encrypt data, return updated secret.

const rotated = await vault.rotateKey(encrypted);
// Same secret, new DEK, updated encryptedDek

vault.rotateKek()

Rotate the Key Encryption Key itself. In AWS KMS, this is automatic; locally, increments version.

await vault.rotateKek();
// Future encryptions use new KEK version, old secrets remain decryptable

vault.generateDek()

Generate a raw plaintext DEK (32 bytes). Useful for manual key management or testing.

const dek = await vault.generateDek();  // Buffer (32 bytes)

vault.close()

Gracefully shut down the provider (closes KMS client, etc.).

await vault.close();

Environment Variables

Auto-Detection

The factory auto-detects the provider from environment:

| Provider | Detection | Env Var | |----------|-----------|---------| | AWS KMS | Highest priority | AWS_KMS_KEY_ID or AWS_KMS_KEY_ARN | | Local | Second priority | VAULT_MASTER_KEY | | None | Throws error | No valid config |

# AWS KMS auto-detection
export AWS_KMS_KEY_ID="arn:aws:kms:us-east-1:123456789012:key/..."
export AWS_REGION="us-east-1"

# Local auto-detection
export VAULT_MASTER_KEY="my-ultra-secret-32-character-key"

# Explicit provider (optional)
export VAULT_PROVIDER="aws-kms"  # or "local"

AWS KMS Environment

AWS_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/12345678-...
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=...    # Optional if using instance profile
AWS_SECRET_ACCESS_KEY=... # Optional if using instance profile

Local Environment

VAULT_MASTER_KEY=your-ultra-secret-master-key-here
# Optional: explicitly enable local provider
VAULT_PROVIDER=local

Schemas (Zod)

Encrypt/decrypt operations use Zod schemas for validation:

import {
  EncryptedSecretSchema,
  SecretMetadataSchema,
} from "@nebutra/vault";

const encrypted = await vault.encrypt("secret");
const validated = EncryptedSecretSchema.parse(encrypted);  // Type-safe

Examples

Multi-Tenant Secrets

const vault = await getVault();

// Store a secret per tenant
const encrypted = await vault.encrypt("stripe-api-key-prod", {
  tenantId: "org_acme",
  metadata: {
    name: "stripe_live",
    type: "api_key",
  },
});

// Decrypt only if tenant matches
const plaintext = await vault.decrypt(encrypted, {
  tenantId: "org_acme",  // ✓ Success
});

// This will throw:
await vault.decrypt(encrypted, {
  tenantId: "org_evil",  // ✗ Tenant mismatch
});

Key Rotation

const vault = await getVault();

// Rotate a single secret
const updated = await vault.rotateKey(encrypted);
// encryptedDek changed, but plaintext is the same

// Rotate the KEK (all future secrets use new KEK version)
await vault.rotateKek();

Custom Provider in Tests

import { setVault, LocalProvider } from "@nebutra/vault";

const testVault = new LocalProvider({
  masterKey: "test-key",
  keyVersion: 1,
});

setVault(testVault);

// Now getVault() returns testVault
const vault = await getVault();

Security Considerations

  • DEK Uniqueness: Each secret gets a unique DEK. Even identical plaintexts produce different ciphertexts.
  • KEK Security: AWS KMS protects the KEK; for local provider, guard VAULT_MASTER_KEY carefully.
  • Rotation: Rotate KEKs periodically; Azure/AWS KMS support automatic rotation policies.
  • Tenant Isolation: Optional tenant ID provides logical separation; ensure it's enforced at the application layer.
  • Audit: Log all encrypt/decrypt operations for compliance (via @nebutra/logger).

Limitations

  • No Built-in Versioning: Store rotatedAt timestamps to track secret age; rotation doesn't auto-expire old versions.
  • Plaintext in Memory: Decrypted secrets exist as plaintext in memory. Clear variables when no longer needed.
  • No Expiration: Use metadata.expiresAt as an application-level hint; vault doesn't auto-reject expired secrets.

Roadmap

  • [ ] Support for Google Cloud KMS
  • [ ] Secret versioning and history
  • [ ] Automatic KEK rotation schedules
  • [ ] Benchmarks and performance tuning
  • [ ] Hardware security module (HSM) support

Testing

pnpm --filter @nebutra/vault typecheck

License

Proprietary — Nebutra Inc.