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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@smartledger/envelope

v1.0.0

Published

Canonical SignedResponse/SignedEnvelope schema for verifiable AI outputs and content provenance

Readme

@smartledger/envelope

Simple, verifiable content signing for any application.

A lightweight signing primitive that wraps content with cryptographic proof. Use it to build verifiable AI responses, signed documents, authenticated API calls, or audit trails.


Quick Start

import { createAppIdentity } from '@smartledger/envelope';

// Create an identity (in-memory keys)
const identity = await createAppIdentity({ name: 'MyCoolApp' });

// Sign anything
const signed = await identity.signJson({ message: "Hello, world!" });

// Verify anything  
const result = await identity.verifyJson(signed);
console.log('Valid:', result.valid); // true

Keys are ephemeral (in-memory) by default. For persistence, see Storage Examples below.


What It Does

This package provides:

  1. SignedEnvelope format - A standard schema for signed content
  2. Simple API - One-line setup, easy signing/verification
  3. Post-quantum support - ML-DSA-87 (NIST FIPS 204) by default
  4. Flexible - Works with any JSON-serializable data

What It Doesn't Do

This is a primitive, not a complete application. It doesn't include:

  • ❌ Persistent key storage (but see examples for how to add it)
  • ❌ DID generation or resolution
  • ❌ Verifiable Credentials
  • ❌ Blockchain integration
  • ❌ KYC or identity verification

Those features belong in your application or separate packages. This library gives you the cryptographic foundation to build them.


Use Cases

Verifiable AI Responses

import OpenAI from 'openai';

const identity = await createAppIdentity({ name: 'MyAI' });
const openai = new OpenAI();

const response = await openai.chat.completions.create({
  model: 'gpt-4',
  messages: [{ role: 'user', content: 'Explain quantum computing' }]
});

// Sign the AI response
const signed = await identity.signJson(response, {
  contentType: 'ai-response'
});

// Now you have cryptographic proof of what your AI said and when

Signed Content / Blog Posts

const identity = await createAppIdentity({ name: 'MyBlog' });

const post = {
  title: "Why Cryptography Matters",
  content: "...",
  author: "Alice",
};

const signedPost = await identity.signJson(post, {
  contentType: 'blog-post'
});

// Readers can verify authenticity
// Authors can't deny writing it
// Editors can't change it without detection

Microservice Authentication

// Service A signs requests
const serviceA = await createAppIdentity({ name: 'ServiceA' });
const request = await serviceA.signJson({
  action: 'process-payment',
  amount: 100,
});

// Service B verifies before processing
const result = await serviceB.verifyJson(request);
if (result.valid && result.creator === 'ServiceA') {
  // Process - we know it's really from ServiceA
}

Audit Trails with Chain of Custody

import { createEnvelopeChain } from '@smartledger/envelope';

const original = await identity.signJson(
  { status: 'draft', content: '...' }
);

// Link revision to original
const revision = await createEnvelopeChain(
  identity.getSDK(),
  identity.keyId,
  { status: 'reviewed', content: '...' },
  original,
  { creator: 'reviewer' }
);

// revision.meta.parentId === hash(original)
// Full provenance chain preserved

Features

🔐 Post-Quantum Ready

Uses ML-DSA-87 (NIST FIPS 204) by default - quantum-resistant signatures:

const identity = await createAppIdentity({
  name: 'MyApp',
  algorithm: 'ml-dsa-87'  // Default
});

Or use ECDSA for Bitcoin compatibility:

const identity = await createAppIdentity({
  name: 'MyApp',
  algorithm: 'bsv-ecdsa-secp256k1'
});

📜 Chain of Custody

Link envelopes to create verifiable revision chains:

const updated = await createEnvelopeChain(
  sdk, keyId, updatedData, originalEnvelope,
  { creator: 'editor' }
);
// updated.meta.parentId === hash(originalEnvelope)

🔗 Extensible Metadata

Add custom metadata for your use case:

const signed = await createSignedEnvelope(sdk, keyId, data, {
  creator: 'MyApp',
  contentType: 'invoice',
  metadata: {
    invoiceNumber: 'INV-001',
    customField: 'anything'
  }
});

Envelope Format

The SignedEnvelope is a simple, universal format:

interface SignedEnvelope<T> {
  payload: T;              // Your actual data
  
  meta: {
    version: string;       // Schema version
    creator: string;       // Who created it
    createdAt: string;     // ISO 8601 timestamp
    contentType?: string;  // Optional type hint
    parentId?: string;     // Optional parent hash
    // ... custom fields
  };
  
  _signature: {
    algorithm: string;     // e.g., 'ml-dsa-87'
    keyId: string;         // Key identifier
    publicKey: string;     // Base64 public key (embedded for verification)
    signature: string;     // Base64 signature
    timestamp: string;     // When signed
  };
}

This format can be:

  • Stored in databases (MongoDB, Postgres, etc.)
  • Sent over HTTP/WebSocket
  • Saved to files
  • Verified years later

Installation

npm install @smartledger/envelope

Requires:

  • @smartledger/keys (automatically installed)
  • @smartledger/crypto (automatically installed)

Storage Examples

In-Memory (Default)

Keys are ephemeral - perfect for testing or short-lived processes:

const identity = await createAppIdentity({ name: 'TestApp' });
// Keys lost when process exits

File-Based Storage

Implement your own KeyStorage class (see @smartledger/crypto for interface):

import { createKeySDK } from '@smartledger/keys';
import { KeyRegistry } from '@smartledger/crypto';
import { FileKeyStorage } from './storage'; // Your implementation

const sdk = createKeySDK({
  keyRegistry: new KeyRegistry(new FileKeyStorage('./keys'))
});

const identity = await createAppIdentity({
  name: 'MyApp',
  sdk  // Use your SDK with persistence
});

See /examples/file-storage/ for a complete implementation.

Database Storage

Similar pattern - implement KeyStorage for your database:

import { MongoKeyStorage } from './storage'; // Your implementation

const sdk = createKeySDK({
  keyRegistry: new KeyRegistry(new MongoKeyStorage(mongoClient))
});

const identity = await createAppIdentity({ name: 'MyApp', sdk });

See /examples/mongodb-storage/ for a complete implementation.


API Reference

High-Level API (Recommended)

createAppIdentity(options)

Create a signing identity:

const identity = await createAppIdentity({
  name: 'MyApp',             // Required: app/agent name
  algorithm: 'ml-dsa-87',    // Optional: 'ml-dsa-87' | 'bsv-ecdsa-secp256k1'
  sdk: customSDK,            // Optional: provide your own SDK with custom storage
  existingKeyId: 'key-123'   // Optional: use existing key
});

signJson(appName, data, options?)

Convenience function for one-shot signing:

const signed = await signJson('MyApp', { message: "Hello!" });

Note: Uses a global SDK instance. Keys persist across calls within the same process but are lost when the process exits.

verifyJson(envelope)

Convenience function for one-shot verification:

const result = await verifyJson(receivedEnvelope);

Verifies envelopes created with signJson() in the same process.

Low-Level API (Advanced)

createSignedEnvelope(sdk, keyId, payload, options)

Full control over envelope creation:

import { createKeySDK } from '@smartledger/keys';
import { createSignedEnvelope } from '@smartledger/envelope';

const sdk = createKeySDK();
const key = await sdk.createKey('agent', { primarySignatureSuite: 'ml-dsa-87' });

const envelope = await createSignedEnvelope(sdk, key.meta.keyId, data, {
  creator: 'my-agent',
  contentType: 'custom-type',
  metadata: { custom: 'fields' },
  anchor: { chain: 'bitcoin', txId: '0x...', timestamp: '...' }
});

verifySignedEnvelope(sdk, envelope, options?)

Full control over verification:

const result = await verifySignedEnvelope(sdk, envelope, {
  maxAge: 86400000,         // Reject if older than 24h
  expectedCreator: 'alice', // Reject if not from alice
});

Utility Functions

import {
  extractPayload,
  getEnvelopeMeta,
  hasPQSignature,
  hasAnchor,
  createEnvelopeChain
} from '@smartledger/envelope';

// Extract payload without verification (use with caution)
const data = extractPayload(envelope);

// Get metadata
const meta = getEnvelopeMeta(envelope);

// Check capabilities
const hasPQ = hasPQSignature(envelope);      // false (not implemented yet)
const hasChain = hasAnchor(envelope);         // true if anchor present

// Create linked envelope
const child = await createEnvelopeChain(sdk, keyId, data, parent, options);

Philosophy

Digital content should answer four questions:

  1. WHO - Cryptographically proven creator
  2. WHAT - Content hash for tamper detection
  3. WHEN - Timestamp (ISO 8601)
  4. HOW - Algorithm + public key for verification

This envelope format provides all four. The format is simple and can be verified years later.


Testing

cd packages/envelope
npm test

78 tests covering:

  • Envelope creation and verification
  • Helper functions
  • Type definitions
  • Real-world scenarios (AI, blogs, microservices)
  • Chain of custody
  • Tampering detection

Roadmap

Current (v1.0.0)

  • ✅ SignedEnvelope format
  • ✅ ML-DSA-87 and ECDSA support
  • ✅ Chain of custody
  • ✅ Simple API
  • ✅ 78 comprehensive tests

Future

  • [ ] Embedded public key verification (verify without SDK)
  • [ ] JWS/JWT compatibility layer
  • [ ] DID document generation
  • [ ] Dual-signing (ECDSA + ML-DSA)
  • [ ] On-chain anchor verification
  • [ ] Browser bundle

License

MIT - See LICENSE


Author

Gregory Ward (Codenlighten)
Founder: Codenlighten.org
Co-founder & CTO: SmartLedger.Technology


Related Packages


Status: 🚧 Alpha - API Stable, Features Complete, Tests Pending

The cryptographic nervous system for verifiable AI.