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

dominion-protocol

v1.0.0

Published

Epoch-based encrypted access control protocol for Nostr

Readme

Dominion Protocol

Nostr: npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2

Your content. Your keys. Your rules. No platform required.

npm CI License: MIT TypeScript

Protocol Spec · NIP Draft · LLM Reference · Contributing

The Problem

Nostr content is either public or NIP-44 encrypted to specific recipients. There is no native mechanism for:

  • Audience tiers — different groups seeing different content (family, close friends, subscribers)
  • Revocable access — removing a recipient's ability to decrypt future content
  • Scalable encryption — encrypting to hundreds of recipients without per-recipient encryption operations

Per-recipient NIP-44 encryption works for DMs but doesn't scale:

| Recipients | NIP-44 approach | Dominion | |-----------|----------------|----------| | 1 | 1 encryption | 1 encryption + 1 key share | | 10 | 10 encryptions | 1 encryption + 10 key shares | | 100 | 100 encryptions | 1 encryption + 100 key shares | | 1,000 | 1,000 encryptions | 1 encryption + 1,000 key shares |

Content is encrypted once with an epoch-based Content Key. Only the lightweight key distribution scales with audience size.

How It Works

Dominion introduces vaults — encrypted content containers on standard Nostr relays:

  1. Derive a Content Key (CK) from your private key, the current epoch, and the tier
  2. Encrypt your content with the CK (AES-256-GCM) and publish to any relay
  3. Distribute the CK to each tier member via NIP-44 encrypted, NIP-59 gift-wrapped events
  4. Rotate — new epoch, new CK. Revoked members don't get the new key

No custom relay software. No middleware. No platform. Just standard Nostr events and proven cryptography.

Use Cases

| Use case | How Dominion helps | |----------|-------------------| | Creator paywall | Encrypt to paying subscribers; revoke on cancellation | | Family sharing | Private family tier; rotate keys weekly | | Close friends | Share selectively without making content public | | Institutional access | Tiered access with automatic key expiry | | Paid newsletters | One encryption operation, unlimited subscribers |

For scenarios requiring instant revocation (custody disputes, institutional SLA), optional warden relays provide true revocation using NIP-42 AUTH.

Install

npm install dominion-protocol

Quick Start

Encrypt Content for a Tier

import { deriveContentKey, contentKeyToHex, getCurrentEpochId, encrypt, decrypt } from 'dominion-protocol';

// Derive this week's Content Key for the "family" tier
const epochId = getCurrentEpochId();  // e.g. "2026-W11"
const ck = deriveContentKey(privateKeyHex, epochId, 'family');

// Encrypt content — one operation regardless of audience size
const ciphertext = encrypt('Hello family!', ck);  // base64 string
const plaintext = decrypt(ciphertext, ck);         // "Hello family!"

Manage Your Vault

import { defaultConfig, addToTier, removeFromTier, revokePubkey } from 'dominion-protocol';

let config = defaultConfig();
config = addToTier(config, 'family', alicePubkey);
config = addToTier(config, 'close_friends', bobPubkey);
config = revokePubkey(config, formerFriendPubkey);  // excluded from next rotation

Distribute Keys via Nostr

import { buildVaultShareEvent } from 'dominion-protocol/nostr';

// Build a kind 30480 vault share (caller handles NIP-44 + NIP-59 wrapping)
const event = buildVaultShareEvent(authorPubkey, recipientPubkey, ckHex, epochId, 'family');

Shamir Secret Sharing

Split Content Keys across multiple parties or relays for redundancy:

import { splitCK, reconstructCK, encodeCKShare, decodeCKShare } from 'dominion-protocol';

const shares = splitCK(ck, 2, 3);           // 2-of-3 threshold
const encoded = shares.map(encodeCKShare);   // ["1:ab12...", "2:cd34...", "3:ef56..."]

const decoded = encoded.slice(0, 2).map(decodeCKShare);
const recovered = reconstructCK(decoded);    // original CK

Architecture

Two-layer exports — use what you need:

  • dominion-protocol — universal crypto primitives. Pure functions, zero Nostr knowledge. Works anywhere.
  • dominion-protocol/nostr — Nostr event builders and parsers. Returns unsigned, unencrypted events. The caller handles NIP-44 encryption and NIP-59 gift wrapping.

Cryptography

| Primitive | Implementation | |-----------|---------------| | Key derivation | HKDF-SHA256 (@noble/hashes) | | Content encryption | AES-256-GCM, 12-byte random IV (@noble/ciphers) | | Secret sharing | Shamir over GF(256), irreducible polynomial 0x11b | | Epoch format | ISO 8601 weeks (YYYY-Www) |

Nostr Integration

| Kind | Type | Purpose | |------|------|---------| | 30480 | Parameterised replaceable | Vault share — epoch CK for a specific recipient | | 30078 | NIP-78 app-specific data | Vault config — self-encrypted tier memberships |

Built on NIP-01, NIP-09, NIP-40, NIP-44, NIP-59, and NIP-78. No new cryptographic primitives.

Protocol Spec

See spec/protocol.md for the full protocol specification, including epoch rotation, tier management, individual grants, revocation, Lightning-gated access, and optional warden relay infrastructure.

Licence

MIT

Support

For issues and feature requests, see GitHub Issues.

If you find Dominion useful, consider sending a tip:

  • Lightning: [email protected]
  • Nostr zaps: npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2