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

ddna-reader

v0.2.0

Published

Read-only tools for .ddna envelope inspection, validation, and verification

Readme

ddna-reader

Read-only tools for inspecting, validating, and verifying .ddna envelopes.

What This Package Does

  • Inspect .ddna envelope contents in human-readable or JSON format
  • Validate envelope structure against the expected schema
  • Verify Ed25519 cryptographic signatures (eddsa-jcs-2022 cryptosuite)
  • Read governance metadata, EDM payload structure, and proof details

What This Package Does NOT Do

For Certified (Level 3) attestation on Extended or Full profile artifacts, see deepadata.com.

Installation

npm install ddna-reader

Or use directly with npx:

npx ddna-reader inspect <file>
npx ddna-reader verify <file>

CLI Usage

Inspect an envelope

Display envelope contents in human-readable format:

ddna-reader inspect envelope.ddna

Output as JSON:

ddna-reader inspect envelope.ddna --json

Validate structure

Check if an envelope has valid structure (schema validation only):

ddna-reader validate envelope.ddna

Treat warnings as errors:

ddna-reader validate envelope.ddna --strict

Verify signature

Verify the cryptographic signature on an envelope:

ddna-reader verify envelope.ddna

Output as JSON (for scripting):

ddna-reader verify envelope.ddna --json

Example JSON output:

{
  "verified": true,
  "signer_did": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
  "created": "2026-04-21T10:00:00Z",
  "errors": []
}

Exit codes:

  • 0 - Verification succeeded
  • 1 - Verification failed or error occurred

Library Usage

Basic inspection

import {
  inspect,
  inspectEnvelope,
  inspectJson,
  validateStructure,
} from 'ddna-reader';

// Read a .ddna file
const envelope = JSON.parse(fs.readFileSync('artifact.ddna', 'utf-8'));

// Get human-readable inspection
const output = inspect(envelope);
console.log(output);

// Get structured inspection result
const result = inspectEnvelope(envelope);
console.log(result.jurisdiction);
console.log(result.schemaVersion);

// Validate structure only
const validation = validateStructure(envelope);
if (validation.valid) {
  console.log('Structure is valid');
} else {
  console.log('Errors:', validation.errors);
}

Verification

import { verify, verifySync } from 'ddna-reader';

const envelope = JSON.parse(fs.readFileSync('artifact.ddna', 'utf-8'));

// Async verification (recommended)
const result = await verify(envelope);
if (result.valid) {
  console.log('Verified by:', result.verificationMethod);
  console.log('Signed at:', result.created);
} else {
  console.log('Verification failed:', result.reason);
}

// Sync verification (did:key only)
const syncResult = verifySync(envelope);

Verification with did:web (injected resolver)

By default, did:key signatures verify offline. For did:web signatures, you must provide a resolver function:

import { verify, didToPublicKey } from 'ddna-reader';

const result = await verify(envelope, {
  didResolver: async (did) => {
    // Handle did:key locally
    if (did.startsWith('did:key:')) {
      const didPart = did.split('#')[0];
      return didToPublicKey(didPart);
    }

    // Handle did:web via HTTP fetch
    if (did.startsWith('did:web:')) {
      const domain = did.slice(8).split('#')[0].replace(/:/g, '/');
      const url = `https://${domain}/.well-known/did.json`;
      const doc = await fetch(url).then(r => r.json());

      // Extract public key from DID document
      const vm = doc.verificationMethod?.find(
        (m: any) => m.id === did || m.id === `${did.split('#')[0]}#${did.split('#')[1]}`
      );
      if (!vm?.publicKeyMultibase) {
        throw new Error('No public key found in DID document');
      }
      // Decode multibase key (implementation depends on format)
      return decodeMultibaseKey(vm.publicKeyMultibase);
    }

    throw new Error(`Unsupported DID method: ${did}`);
  }
});

This pattern keeps the library offline-capable while allowing callers to provide their own network policy.

Verification options

const result = await verify(envelope, {
  // Clock skew tolerance (default: 5 minutes)
  clockSkewMs: 10 * 60 * 1000,

  // Skip timestamp validation
  skipTimestampCheck: true,

  // Custom DID resolver (required for did:web)
  didResolver: async (did) => { /* ... */ },
});

Envelope Structure

A .ddna envelope contains three components:

{
  "ddna_header": {
    "ddna_version": "1.1",
    "created_at": "2026-02-19T10:00:00Z",
    "edm_version": "0.7.0",
    "jurisdiction": "GDPR",
    "consent_basis": "consent",
    "exportability": "allowed",
    "retention_policy": { ... }
  },
  "edm_payload": {
    "meta": { ... },
    "core": { ... },
    "constellation": { ... },
    "governance": { ... }
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "verificationMethod": "did:key:z6Mk...",
    "proofPurpose": "assertionMethod",
    "proofValue": "z..."
  }
}

Architecture

The .ddna envelope format uses W3C Data Integrity Proofs with Ed25519 signatures.

  • Sealing (Level 2 - Sealed) is open: anyone can seal artifacts with their own Ed25519 keys using ddna-tools
  • Verification is open: anyone can verify signatures using this package
    • did:key verification works offline
    • did:web verification requires a caller-provided resolver
  • Certification (Level 3 - Certified) is commercial: DeepaData provides third-party attestation for Extended and Full profile artifacts

Verification vs. Registry Lookup

| Operation | ddna-reader (OSS) | /v1/verify (API) | |-----------|-------------------|------------------| | Signature verification | ✓ | ✓ | | Structure validation | ✓ | ✓ | | Registry lookup | ✗ | ✓ | | Conformance attestation | ✗ | ✓ |

Timestamp Attestation

The proof.created timestamp is signer-attested per W3C Data Integrity, not independently timestamped via RFC 3161. This means:

  • The timestamp indicates when the signer claims to have signed
  • For legal non-repudiation requiring trusted timestamping, use the DeepaData API

Related

License

MIT