Skip to content

emotional-data-model/ddna-reader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.8.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

About

Inspect and validate .ddna envelopes — the open reader for EDM affective records

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages