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

@owlmeans/basic-envelope

v0.1.1

Published

A lightweight cryptographic message envelope library for OwlMeans Common applications. This package provides secure message wrapping, signing, and verification capabilities using Ed25519 cryptographic signatures, designed as an alternative to JWT/JWE toke

Readme

@owlmeans/basic-envelope

A lightweight cryptographic message envelope library for OwlMeans Common applications. This package provides secure message wrapping, signing, and verification capabilities using Ed25519 cryptographic signatures, designed as an alternative to JWT/JWE tokens with enhanced security and simplicity.

Overview

The @owlmeans/basic-envelope package enables secure message transmission and storage by providing:

  • Message Envelopes: Lightweight containers for messages with built-in expiration and type identification
  • Cryptographic Signing: Ed25519 signature support for message authentication and integrity
  • Flexible Serialization: Multiple output formats including wrapped strings and tokenized representations
  • TTL Support: Time-to-live functionality for automatic message expiration
  • Type Safety: Full TypeScript support with generic message types

This package is particularly useful for creating secure authentication tokens, signed API requests, and encrypted inter-service communication.

Installation

npm install @owlmeans/basic-envelope

Core Concepts

Envelope Structure

An envelope is a container that wraps a message with metadata including:

  • Type identifier: Categorizes the message purpose
  • Message payload: The actual data (string or object)
  • Signature: Optional cryptographic signature for verification
  • Timestamp: Creation time for ordering and TTL calculations
  • TTL: Time-to-live for automatic expiration

Envelope Kinds

The package supports different serialization formats:

  • Wrap: Base64-encoded JSON representation
  • Token: Compact tokenized format for transmission

API Reference

Factory Functions

The package uses factory functions for object creation following OwlMeans Common conventions:

makeEnvelopeModel<T>(type, kind?): EnvelopeModel<T>

Creates an envelope model for wrapping and managing messages with cryptographic capabilities.

import { makeEnvelopeModel, EnvelopeKind } from '@owlmeans/basic-envelope'

// Create a new envelope
const envelope = makeEnvelopeModel<UserData>('user-session')

// Create from existing wrapped envelope
const wrappedEnvelope = makeEnvelopeModel('eyJ0IjoiZXhhbXBsZSIsLi4u', EnvelopeKind.Wrap)

// Create from tokenized envelope
const tokenizedEnvelope = makeEnvelopeModel('example:msg:signature', EnvelopeKind.Token)

Parameters:

  • type: string - Type identifier for new envelopes, or serialized envelope for reconstruction
  • kind: EnvelopeKind (optional) - Specifies format when reconstructing from serialized data

Returns: EnvelopeModel instance with methods for message management and cryptographic operations

Generic Type Parameter:

  • T: Type of the message payload (defaults to string)

Core Interfaces

Envelope

Core envelope structure containing message and metadata.

interface Envelope {
  t: string           // Type identifier for categorizing messages
  msg: string         // Base64-encoded message content
  sig?: string        // Optional cryptographic signature
  dt: number          // Creation timestamp (milliseconds)
  ttl: number | null  // Time-to-live in milliseconds (null = no expiration)
}

Properties:

  • t: Message type identifier used for categorization and routing
  • msg: Base64-encoded message payload (automatically encoded by envelope methods)
  • sig: Optional Ed25519 signature for message authentication and integrity verification
  • dt: Creation timestamp used for ordering and TTL calculations (milliseconds since epoch)
  • ttl: Time-to-live for automatic expiration, null indicates no expiration

EnvelopeModel<T>

Factory-created envelope manager providing comprehensive message operations and cryptographic functions.

interface EnvelopeModel<T extends {} | string = string> {
  envelope: Envelope
  
  // Message management methods
  send<M extends T>(msg: M, ttl?: number | null): EnvelopeModel
  message<M extends T>(preserve?: boolean): M
  type(): string
  
  // Serialization methods
  wrap(): string
  tokenize(): string
  
  // Cryptographic methods
  sign(key: KeyPairModel, kind?: EnvelopeKind): Promise<string>
  verify(key: KeyPairModel): Promise<boolean>
}

EnvelopeModel Methods Reference

Message Management Methods

send<M extends T>(msg: M, ttl?: number | null): EnvelopeModel

Sets the message content and optional TTL, with automatic encoding based on message type.

// Send a string message
envelope.send('Hello, World!')

// Send an object with 1-hour TTL
envelope.send({ userId: '123', action: 'login' }, 3600000)

// Send with no expiration
envelope.send(messageData, null)
  • Purpose: Encodes and stores message data in the envelope with optional expiration
  • Behavior:
    • String messages are stored directly
    • Objects are JSON-serialized then Base64-encoded automatically
    • Updates TTL if provided, maintains existing TTL if not specified
  • Parameters:
    • msg: M: Message payload extending type T
    • ttl?: number | null: Time-to-live in milliseconds, null for no expiration
  • Returns: The same EnvelopeModel instance for method chaining
  • Throws: No exceptions - handles all message types gracefully

message<M extends T>(preserve?: boolean): M

Retrieves and decodes the message content from the envelope.

// Get decoded object message
const userData = envelope.message<UserData>()

// Get raw string message without decoding
const rawMessage = envelope.message<string>(true)
  • Purpose: Extracts the original message from the envelope with configurable decoding
  • Behavior:
    • Default (preserve false): Attempts JSON parsing followed by Base64 decoding
    • Preserve mode (preserve true): Returns raw message string without processing
    • Gracefully falls back to string if JSON parsing fails
  • Parameters:
    • preserve?: boolean: If true, returns raw message without decoding
  • Returns: Decoded message of type M
  • Error Handling: Silent fallback to string type on decode errors

type(): string

Returns the type identifier of the envelope for message categorization.

const messageType = envelope.type() // e.g., 'user-session'
  • Purpose: Provides access to the envelope's type identifier
  • Returns: String identifier used for message routing and categorization
  • Use Cases: Message dispatching, route determination, debugging

Serialization Methods

wrap(): string

Serializes the envelope to a Base64-encoded JSON string for secure transmission.

const wrappedEnvelope = envelope.wrap()
// Returns: "eyJ0IjoiZXhhbXBsZSIsIm1zZyI6IkhlbGxvIiwiZHQiOjE2Mzk..."

// Can be reconstructed later
const restored = makeEnvelopeModel(wrappedEnvelope, EnvelopeKind.Wrap)
  • Purpose: Creates a wrapped representation suitable for storage or secure transmission
  • Behavior: JSON-serializes the complete envelope then Base64-encodes the result
  • Returns: Base64-encoded envelope string
  • Use Cases: Database storage, HTTP headers, secure URL parameters
  • Security: Preserves all envelope data including signatures

tokenize(): string

Creates a compact token format for efficient transmission and parsing.

const token = envelope.tokenize()
// Returns: "user-session:SGVsbG8gV29ybGQ:signature_if_present"

// Reconstruct from token
const restored = makeEnvelopeModel(token, EnvelopeKind.Token)
  • Purpose: Creates a human-readable, compact token representation
  • Behavior: Combines type, message, and signature with colon separators
  • Format: type:base64_message:signature (signature omitted if not present)
  • Returns: Compact token string
  • Use Cases: API tokens, authentication headers, URL fragments, debugging
  • Advantages: Easily parseable, more compact than wrapped format

Cryptographic Methods

sign(key: KeyPairModel, kind?: EnvelopeKind): Promise<string>

Signs the envelope with Ed25519 cryptographic signature for authentication and integrity.

import { makeKeyPairModel } from '@owlmeans/basic-keys'

const keyPair = makeKeyPairModel()
await keyPair.generate()

// Sign and get signature only
const signature = await envelope.sign(keyPair)

// Sign and get wrapped envelope
const signedWrapped = await envelope.sign(keyPair, EnvelopeKind.Wrap)

// Sign and get tokenized envelope  
const signedToken = await envelope.sign(keyPair, EnvelopeKind.Token)
  • Purpose: Provides cryptographic authentication and tamper-detection
  • Behavior:
    • Creates Ed25519 signature of envelope data (excluding existing signature field)
    • Stores signature in envelope.sig property for future verification
    • Returns formatted output based on kind parameter
  • Parameters:
    • key: KeyPairModel: Ed25519 key pair instance for signing
    • kind?: EnvelopeKind: Output format - Wrap, Token, or raw signature (default)
  • Returns: Promise resolving to signature string or formatted envelope
  • Security: Uses industry-standard Ed25519 signatures for cryptographic authenticity
  • Error Handling: Propagates key pair errors (e.g., missing private key)

verify(key: KeyPairModel): Promise<boolean>

Verifies envelope signature and validates TTL expiration for complete authenticity check.

// Verify signature and TTL
const isValid = await envelope.verify(keyPair)

if (isValid) {
  console.log('Envelope is authentic and not expired')
  // Safe to process message
} else {
  console.log('Envelope is invalid or expired - reject')
  // Handle invalid envelope
}
  • Purpose: Validates both cryptographic authenticity and temporal freshness
  • Behavior:
    • Returns false immediately if no signature is present
    • Checks TTL expiration if TTL is set (compares dt + ttl with current time)
    • Verifies Ed25519 signature against envelope data (excluding signature field)
    • All conditions must pass for true result
  • Parameters:
    • key: KeyPairModel: Key pair instance with public key for verification
  • Returns: Promise resolving to boolean validation result
  • Security: Combines cryptographic verification with temporal validation
  • Use Cases: Authentication token validation, message integrity checking

Factory Functions

makeEnvelopeModel<T>(type: string, kind?: EnvelopeKind): EnvelopeModel<T>

Creates a new envelope model instance.

Parameters:

  • type: Type identifier for the envelope
  • kind: Optional kind for deserializing existing envelopes

Returns: EnvelopeModel instance

Example:

import { makeEnvelopeModel } from '@owlmeans/basic-envelope'

// Create new envelope
const envelope = makeEnvelopeModel<UserData>('user-profile')

// Send message
envelope.send({ userId: '123', name: 'John' }, 300000) // 5 minutes TTL

// Get wrapped representation
const wrapped = envelope.wrap()

Constants and Enums

EnvelopeKind

Enumeration defining available envelope serialization formats.

enum EnvelopeKind {
  Wrap = 'wrap',      // Base64-encoded JSON format - secure, complete data preservation
  Token = 'token'     // Compact colon-separated format - human-readable, efficient
}

Usage Guidelines:

  • Use Wrap for secure storage, HTTP headers, or when preserving all metadata is critical
  • Use Token for API tokens, URLs, or when human readability and compactness are important

DEFAULT_TTL

Default time-to-live value applied to new envelopes.

const DEFAULT_TTL = 5 * 60 * 1000  // 5 minutes in milliseconds

Behavior: Applied automatically when creating new envelopes unless explicitly overridden

Error Handling

The basic-envelope package follows OwlMeans Common error handling patterns and integrates with cryptographic operations that may throw errors.

Common Error Scenarios

Key-Related Errors

import { makeKeyPairModel } from '@owlmeans/basic-keys'

try {
  const keyPair = makeKeyPairModel()
  // Error: Attempting to sign without generating keys
  await envelope.sign(keyPair)
} catch (error) {
  console.error('Key operation failed:', error.message)
  // Handle missing private key or key generation errors
}

TTL Validation Errors

// Expired envelope verification
const expiredEnvelope = makeEnvelopeModel('expired-message')
expiredEnvelope.send('data', 1) // 1ms TTL
await new Promise(resolve => setTimeout(resolve, 10)) // Wait for expiration

const isValid = await expiredEnvelope.verify(keyPair)
// Returns false - envelope has expired

Malformed Data Errors

try {
  // Invalid wrapped data
  const malformed = makeEnvelopeModel('invalid-base64', EnvelopeKind.Wrap)
} catch (error) {
  console.error('Failed to parse envelope:', error.message)
}

Error Types and Handling

The package gracefully handles various error conditions:

  1. Silent Fallbacks: Message decoding errors fall back to string representation
  2. Validation Failures: Verification methods return false rather than throwing
  3. Key Errors: Cryptographic errors are propagated from the key pair implementation
  4. Parse Errors: Malformed envelope data results in constructor exceptions

Advanced Usage Examples

Authentication Token System

import { makeEnvelopeModel, EnvelopeKind } from '@owlmeans/basic-envelope'
import { makeKeyPairModel } from '@owlmeans/basic-keys'

// Setup authentication system
const authKeys = makeKeyPairModel()
await authKeys.generate()

// Create authentication token
const sessionEnvelope = makeEnvelopeModel<SessionData>('user-session')
const sessionData = {
  userId: 'user123',
  permissions: ['read', 'write'],
  loginTime: Date.now()
}

// Sign and create token with 1-hour expiration
const authToken = await sessionEnvelope
  .send(sessionData, 3600000)
  .sign(authKeys, EnvelopeKind.Token)

console.log('Auth token:', authToken)
// user-session:eyJ1c2VySWQ...base64...:signature

// Later: verify token
const receivedEnvelope = makeEnvelopeModel(authToken, EnvelopeKind.Token)
const isValidToken = await receivedEnvelope.verify(authKeys)

if (isValidToken) {
  const session = receivedEnvelope.message<SessionData>()
  console.log('Valid session for user:', session.userId)
} else {
  console.log('Invalid or expired token')
}

Secure Message Transmission

// Sender side
const messageEnvelope = makeEnvelopeModel<ApiRequest>('api-request')
const apiRequest = {
  method: 'POST',
  endpoint: '/users',
  data: { name: 'John Doe', email: '[email protected]' }
}

// Create signed message with 30-second TTL
const signedMessage = await messageEnvelope
  .send(apiRequest, 30000)
  .sign(senderKeys, EnvelopeKind.Wrap)

// Transmit wrapped message
await sendToServer(signedMessage)

// Receiver side
const receivedEnvelope = makeEnvelopeModel(signedMessage, EnvelopeKind.Wrap)

// Verify authenticity and freshness
if (await receivedEnvelope.verify(senderKeys)) {
  const request = receivedEnvelope.message<ApiRequest>()
  // Process authenticated API request
  console.log('Processing request:', request.method, request.endpoint)
} else {
  // Reject unauthenticated or expired request
  throw new Error('Invalid request signature or expired')
}

Multi-Format Message Exchange

// Create message once
const dataEnvelope = makeEnvelopeModel<UserProfile>('user-profile')
dataEnvelope.send({
  id: '123',
  name: 'Alice Smith',
  preferences: { theme: 'dark', notifications: true }
})

// Generate multiple formats for different use cases
const forDatabase = dataEnvelope.wrap()        // Secure storage
const forUrl = dataEnvelope.tokenize()         // URL transmission
const forHeaders = await dataEnvelope.sign(keys, EnvelopeKind.Wrap) // Signed secure

// Each format can be reconstructed to the same data
const fromDb = makeEnvelopeModel(forDatabase, EnvelopeKind.Wrap)
const fromUrl = makeEnvelopeModel(forUrl, EnvelopeKind.Token)
const fromHeaders = makeEnvelopeModel(forHeaders, EnvelopeKind.Wrap)

// All contain the same user profile data
console.log('Same data:', 
  fromDb.message<UserProfile>().id === 
  fromUrl.message<UserProfile>().id &&
  fromHeaders.message<UserProfile>().id
)

Integration Patterns

Express.js Middleware

import express from 'express'
import { makeEnvelopeModel, EnvelopeKind } from '@owlmeans/basic-envelope'

// Authentication middleware using envelope tokens
const authenticateToken = (serverKeys) => async (req, res, next) => {
  const authHeader = req.headers.authorization
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing auth token' })
  }

  try {
    const token = authHeader.substring(7)
    const envelope = makeEnvelopeModel(token, EnvelopeKind.Token)
    
    if (await envelope.verify(serverKeys)) {
      req.user = envelope.message()
      next()
    } else {
      res.status(401).json({ error: 'Invalid or expired token' })
    }
  } catch (error) {
    res.status(400).json({ error: 'Malformed token' })
  }
}

const app = express()
app.use('/api', authenticateToken(serverKeys))

React Hook Integration

import { useState, useEffect } from 'react'
import { makeEnvelopeModel, EnvelopeKind } from '@owlmeans/basic-envelope'

// Custom hook for secure message handling
function useSecureMessage<T>(initialMessage?: T) {
  const [envelope] = useState(() => makeEnvelopeModel<T>('react-state'))
  const [message, setMessage] = useState<T | null>(initialMessage || null)

  const updateMessage = (newMessage: T, ttl?: number) => {
    envelope.send(newMessage, ttl)
    setMessage(newMessage)
  }

  const getSecureToken = async (keys) => {
    return await envelope.sign(keys, EnvelopeKind.Token)
  }

  const verifyMessage = async (token: string, keys) => {
    try {
      const received = makeEnvelopeModel(token, EnvelopeKind.Token)
      if (await received.verify(keys)) {
        const data = received.message<T>()
        setMessage(data)
        return true
      }
    } catch (error) {
      console.error('Message verification failed:', error)
    }
    return false
  }

  return { message, updateMessage, getSecureToken, verifyMessage }
}

Security Considerations

Cryptographic Security

  1. Key Management: Use @owlmeans/basic-keys for proper Ed25519 key generation and management
  2. Signature Verification: Always verify signatures before processing messages in production
  3. TTL Usage: Implement appropriate TTL values to prevent replay attacks
  4. Key Rotation: Regularly rotate signing keys and update verification keys

Data Protection

  1. Sensitive Data: Avoid including sensitive data in message types or identifiers
  2. Message Encoding: Automatic Base64 encoding provides basic obfuscation but not encryption
  3. Transmission Security: Use HTTPS/TLS for envelope transmission over networks
  4. Storage Security: Encrypt wrapped envelopes before database storage

Validation Best Practices

  1. Input Validation: Validate envelope data before processing messages
  2. Type Safety: Use TypeScript generics for compile-time message type checking
  3. Error Handling: Implement proper error handling for verification failures
  4. Audit Logging: Log envelope verification results for security monitoring

Performance Considerations

Memory Usage

  • Large Messages: Consider message size impact on memory usage
  • Batch Operations: Process multiple envelopes efficiently rather than individually
  • Key Caching: Cache key pairs to avoid repeated generation operations

Serialization Performance

  • Format Selection: Choose appropriate format (wrap vs token) based on use case
  • Compression: Consider compression for large messages before envelope wrapping
  • JSON Parsing: Message decoding involves JSON parsing - optimize for large objects

Best Practices

  1. TTL Management: Set appropriate TTL values based on use case security requirements
  2. Type Safety: Always use TypeScript generics for compile-time message validation
  3. Error Handling: Implement comprehensive error handling for all envelope operations
  4. Key Management: Use proper key generation and storage practices from @owlmeans/basic-keys
  5. Format Selection: Choose envelope format (wrap vs token) based on transmission requirements
  6. Verification: Always verify envelopes in production environments before processing
  7. Logging: Implement appropriate logging for debugging without exposing sensitive data

Package Structure

Following OwlMeans Common library structure:

  • types: TypeScript interfaces (Envelope, EnvelopeModel)
  • model: Factory functions (makeEnvelopeModel)
  • consts: Constants and enumerations (EnvelopeKind, DEFAULT_TTL)
  • helper: Utility functions for envelope operations
  • utils: Internal utilities for serialization and parsing

Dependencies

This package depends on:

  • @owlmeans/basic-keys - Ed25519 key pair management for cryptographic operations
  • @scure/base - Base64 and UTF-8 encoding utilities
  • uuid - UUID generation (if needed for message identification)

Related Packages