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

atproto-plc

v0.2.0

Published

did-method-plc implementation for ATProto with WASM support

Downloads

12

Readme

plc-audit WASM Implementation

This is a JavaScript implementation of the plc-audit binary that uses WebAssembly for cryptographic operations. It fetches and validates DID audit logs from plc.directory.

Prerequisites

  • Rust (stable toolchain)
  • wasm-pack - Install with: cargo install wasm-pack
  • Node.js (v18 or later) - For running the JavaScript tool

Building

1. Build the WASM Module

From the project root directory:

# Build WASM module with wasm feature
wasm-pack build --target nodejs --out-dir wasm/pkg --features wasm

# Or use the provided build script
./wasm/build.sh

This will:

  • Compile the Rust library to WebAssembly
  • Generate JavaScript bindings
  • Create a wasm/pkg/ directory with the WASM module and TypeScript definitions

2. Install Node.js Dependencies

cd wasm
npm install

Usage

The JavaScript version supports the same command-line interface as the Rust binary:

Basic Validation

Validate a DID and show detailed output:

node plc-audit.js did:plc:z72i7hdynmk6r22z27h6tvur

Verbose Mode

Show all operations and detailed cryptographic validation steps:

node plc-audit.js did:plc:z72i7hdynmk6r22z27h6tvur --verbose
# or
node plc-audit.js did:plc:z72i7hdynmk6r22z27h6tvur -v

Output includes:

  • Operation index and CID
  • Creation timestamp
  • Operation type (Genesis/Update)
  • Previous operation reference
  • Step-by-step chain linkage validation
  • Detailed signature verification with rotation key tracking

Quiet Mode

Only show validation result (useful for scripts):

node plc-audit.js did:plc:z72i7hdynmk6r22z27h6tvur --quiet
# or
node plc-audit.js did:plc:z72i7hdynmk6r22z27h6tvur -q

Output: ✅ VALID or error message

Custom PLC Directory

Use a custom PLC directory server:

node plc-audit.js did:plc:example --plc-url https://custom.plc.directory

What is Validated?

The WASM version performs the same comprehensive validation as the Rust binary:

  1. DID Format Validation

    • Checks prefix is did:plc:
    • Verifies identifier is exactly 24 characters
    • Ensures only valid base32 characters (a-z, 2-7)
  2. Chain Linkage Verification

    • First operation must be genesis (prev = null)
    • Each subsequent operation's prev field must match previous operation's CID
    • No breaks in the chain
  3. Cryptographic Signature Verification

    • Each operation's signature is verified using rotation keys
    • Genesis operation establishes initial rotation keys
    • Later operations can rotate keys
    • Identifies which specific rotation key verified each signature

Example Output

Standard Mode

🔍 Fetching audit log for: did:plc:z72i7hdynmk6r22z27h6tvur
   Source: https://plc.directory

📊 Audit Log Summary:
   Total operations: 4
   Genesis operation: bafyreigp6shzy6dlcxuowwoxz7u5nemdrkad2my5zwzpwilcnhih7bw6zm
   Latest operation: bafyreifn4pkect7nymne3sxkdg7tn7534msyxcjkshmzqtijmn3enyxm3q

🔐 Validating operation chain...
✅ Validation successful!

📄 Final DID State:
   Rotation keys: 2
     [0] did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg
     [1] did:key:zQ3shpKnbdPx3g3CmPf5cRVTPe1HtSwVn5ish3wSnDPQCbLJK

Verbose Mode

Shows detailed step-by-step validation:

Step 1: Chain Linkage Validation
================================
  [1] Checking prev reference...
      Expected: bafyreigp6shzy6dlcxuowwoxz7u5nemdrkad2my5zwzpwilcnhih7bw6zm
      Actual:   bafyreigp6shzy6dlcxuowwoxz7u5nemdrkad2my5zwzpwilcnhih7bw6zm
      ✅ Match - chain link valid
  [2] Checking prev reference...
      Expected: bafyreihmuvr3frdvd6vmdhucih277prdcfcezf67lasg5oekxoimnunjoq
      Actual:   bafyreihmuvr3frdvd6vmdhucih277prdcfcezf67lasg5oekxoimnunjoq
      ✅ Match - chain link valid
  ...

✅ Chain linkage validation complete

Step 2: Cryptographic Signature Validation
==========================================
  [0] Genesis operation - extracting rotation keys
      Rotation keys: 2
        [0] did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg
        [1] did:key:zQ3shpKnbdPx3g3CmPf5cRVTPe1HtSwVn5ish3wSnDPQCbLJK
      ⚠️  Genesis signature cannot be verified (bootstrapping trust)
  [1] Validating signature...
      CID: bafyreihmuvr3frdvd6vmdhucih277prdcfcezf67lasg5oekxoimnunjoq
      Signature: 1mEWzRtFOgeRXH-YCSPTxb990JOXxa__n8Qw6BOKl7Ndm6OFFmwYKiiMqMCpAbxpnGjF5abfIsKc7u3a77Cbnw
      Available rotation keys: 2
        [0] did:key:zQ3shhCGUqDKjStzuDxPkTxN6ujddP4RkEKJJouJGRRkaLGbg
        [1] did:key:zQ3shpKnbdPx3g3CmPf5cRVTPe1HtSwVn5ish3wSnDPQCbLJK
      Parsed verifying keys: 2/2
      ✅ Signature verified with rotation key [1]
         did:key:zQ3shpKnbdPx3g3CmPf5cRVTPe1HtSwVn5ish3wSnDPQCbLJK
  ...

✅ Cryptographic signature validation complete

Architecture

The WASM implementation divides responsibilities:

  • JavaScript (plc-audit.js):

    • Command-line argument parsing
    • HTTP requests to plc.directory
    • Console output formatting
    • Control flow and orchestration
  • WASM (Rust compiled to WebAssembly):

    • DID parsing and validation
    • Operation parsing from JSON
    • Cryptographic signature verification (P-256 and secp256k1)
    • Rotation key management
    • All security-critical operations

Performance

The WASM version has comparable performance to the native Rust binary:

  • WASM module size: ~200KB (optimized)
  • Validation time: ~200-500ms for typical DIDs (4-10 operations)
  • Startup overhead: ~50-100ms for WASM initialization

Troubleshooting

Build Errors

If you encounter build errors:

# Ensure wasm32-unknown-unknown target is installed
rustup target add wasm32-unknown-unknown

# Clean and rebuild
rm -rf wasm/pkg
wasm-pack build --target nodejs --out-dir wasm/pkg --features wasm

Runtime Errors

If you get "Module not found" errors:

# Ensure the WASM module is built
ls wasm/pkg/atproto_plc_bg.wasm

# If missing, rebuild
wasm-pack build --target nodejs --out-dir wasm/pkg --features wasm

Node.js Version

Ensure you're using Node.js v18 or later:

node --version  # Should be v18.0.0 or higher

Comparison with Rust Binary

| Feature | Rust Binary | WASM/JavaScript | |---------|-------------|-----------------| | Performance | Native speed | ~2-3x slower | | Binary Size | 1.5MB | ~200KB WASM | | Dependencies | None (static) | Node.js runtime | | Platform | Per-platform compilation | Universal (runs anywhere with Node.js) | | Use Case | Production servers, CLI | Cross-platform, web integration |

Integration Examples

Use in a Node.js Application

import { WasmDid, WasmOperation, WasmVerifyingKey } from './pkg/atproto_plc.js';

async function validateDid(didString) {
  // Parse DID
  const did = WasmDid.parse(didString);

  // Fetch audit log
  const response = await fetch(`https://plc.directory/${did.did}/log/audit`);
  const auditLog = await response.json();

  // Parse operations
  const operations = auditLog.map(entry => ({
    operation: WasmOperation.fromJson(JSON.stringify(entry.operation)),
    cid: entry.cid,
  }));

  // Validate chain
  for (let i = 1; i < operations.length; i++) {
    const prev = operations[i].operation.prev();
    if (prev !== operations[i - 1].cid) {
      throw new Error('Chain linkage broken');
    }
  }

  return true;
}

Use in Browser (with bundler)

// Build with web target instead
// wasm-pack build --target web --out-dir wasm/pkg --features wasm

import init, { WasmDid } from './pkg/atproto_plc.js';

await init(); // Initialize WASM

const did = WasmDid.parse('did:plc:ewvi7nxzyoun6zhxrhs64oiz');
console.log('Valid DID:', did.did);

License

Dual-licensed under MIT or Apache-2.0, same as the parent library.