Skip to content

How to Adopt Universal Manifest

This guide helps you evaluate Universal Manifest (UM) and choose the right level of adoption for your system. Whether you are building a social platform, an IoT edge device, a metaverse engine, or a credential verification service, this document takes you from “what is this?” to “I can use this.”

Universal Manifest is for any team building a system that needs to receive, produce, or exchange portable state about an entity (a person, a device, a venue, an organization). If your system does any of the following, UM is relevant:

  • Receives identity or credential data from external systems
  • Needs to verify claims (roles, permissions, proof of personhood) from untrusted sources
  • Operates in offline or edge environments where calling home for every verification is impractical
  • Manages privacy and consent across system boundaries
  • Produces portable profiles that other systems consume

You do not need to adopt the entire specification at once. UM is designed for progressive adoption through five tiers. Start where it makes sense and go deeper when you need more.

Each tier builds on the previous one. You can stop at any tier and still get value.

What you do: Validate @type (must include um:Manifest), enforce the TTL validity window (issuedAt/expiresAt), and treat unknown fields as opaque. Safely ignore anything you do not recognize.

What you get: Forward-compatible manifest ingestion. Your system can accept any UM manifest — present or future — without breaking when new fields or shard types are added.

Effort: A few hours. Any JSON parser in any language. No dependencies on the TypeScript reference implementation or any specific library.

Implementation checklist:

  1. Parse the manifest as JSON
  2. Confirm @type includes um:Manifest (may be a string or array)
  3. Confirm all required fields are present: @context, @id, @type, manifestVersion, subject, issuedAt, expiresAt
  4. Enforce TTL: reject if now > expiresAt; recommended: reject if issuedAt > expiresAt
  5. Ignore unknown top-level properties, unknown shard shapes, unknown claim/consent/pointer types

Resources:


What you do: In addition to Tier 0 parsing, read the pointers array and follow the URLs you understand to fetch canonical content from authoritative sources (Solid Pods, ActivityPub actors, Matrix identities, or any stable URL).

What you get: Access to rich, authoritative data without it being embedded in the manifest. The manifest stays small; your system fetches what it needs from the source of truth.

Effort: Moderate. Requires HTTP fetching logic and awareness of the pointer name conventions in the well-known names registry.

Implementation checklist:

  1. Everything from Tier 0
  2. Iterate over pointers entries
  3. For each pointer with a name your system recognizes, fetch the url
  4. Handle fetch failures gracefully (the pointer’s target may be temporarily unavailable)
  5. Ignore pointers with unrecognized names

Resources:


What you do: In addition to Tier 1, read and render known shards. A shard is a named, composable sub-document inside the manifest (for example, publicProfile, deviceRegistration, crossWorldProfile, venuePolicy).

What you get: Full projection capability. Your system renders a meaningful view of the manifest subject — a profile card, a device status panel, a venue policy display — using the shard data it understands. Each consumer projects the same manifest into the view appropriate to its surface.

Effort: Moderate to significant, depending on how many shard types you support. Each shard type requires its own rendering logic.

Implementation checklist:

  1. Everything from Tier 1
  2. Iterate over shards entries
  3. For each shard with a name your system recognizes, extract and render the entity data
  4. If a shard has a ref URI, optionally fetch the referenced data for richer rendering
  5. Ignore shards with unrecognized names or entity types

Resources:


What you do: In addition to Tier 2, enforce cryptographic signature verification and strict TTL enforcement. When a manifest carries a v0.2 signature, verify it using the specified algorithm and canonicalization scheme. Reject manifests that fail verification.

What you get: Tamper detection and authenticity proof. Your system can trust that a manifest was issued by the claimed source and has not been modified in transit. This is the tier required for security-sensitive use cases.

Effort: Significant. Requires implementing or integrating JCS (RFC 8785) canonicalization and Ed25519 signature verification. These are widely available as libraries in most languages.

Implementation checklist:

  1. Everything from Tier 2
  2. If signature is present:
    • Confirm signature.algorithm === "Ed25519" and signature.canonicalization === "JCS-RFC8785"
    • Obtain the public key from signature.publicKeySpkiB64 (embedded) or by resolving signature.keyRef (external)
    • Remove the signature property from the manifest object
    • Canonicalize the remaining object using JCS (RFC 8785)
    • Verify the Ed25519 signature over the canonical bytes
    • Reject the manifest if verification fails
  3. Optionally check signature.statusRef for revocation status

Resources:


What you do: Produce signed manifests for your own subjects (users, devices, venues, organizations). Manage UMID generation, key material, TTL policy, consent correctness, and manifest lifecycle (rotation, expiration, revocation).

What you get: Full participation in the UM ecosystem. Your system is a first-class manifest producer. Other systems at any adoption tier can consume your manifests.

Effort: Substantial. Requires key management, signing infrastructure, UMID generation, and TTL policy decisions.

Implementation checklist:

  1. Generate a unique @id for each manifest (recommended: urn:uuid:<uuidv4>)
  2. Set subject to a stable identifier URI (recommended: a DID, but any URI works)
  3. Set appropriate issuedAt and expiresAt timestamps (short TTLs are recommended for safety)
  4. Populate shards, claims, consents, devices, and pointers as needed
  5. Sign the manifest using the v0.2 signature profile:
    • Remove the signature property
    • Canonicalize with JCS (RFC 8785)
    • Sign with Ed25519
    • Attach the signature object with algorithm, canonicalization, keyRef or publicKeySpkiB64, created, and value
  6. Publish or deliver the manifest (via resolver, direct transfer, QR code, Bluetooth, or any transport)

Resources:


Minimum viable adoption (Tier 0 walkthrough)

Section titled “Minimum viable adoption (Tier 0 walkthrough)”

If you want to start today with the smallest possible investment, here is what to do:

Step 1: Read a manifest. Open a stub manifest example and parse it with your language’s JSON library. Identify the seven required fields.

Step 2: Validate the structure. Use the JSON Schema to validate the manifest structure programmatically. Every major programming language has a JSON Schema validator library.

Step 3: Enforce TTL. Check expiresAt against the current time. If the manifest has expired, reject it. This is a MUST requirement.

Step 4: Ignore what you do not recognize. If the manifest contains shards, claims, pointers, or other fields your system does not understand, ignore them. Do not fail on unknown fields. This is a MUST requirement.

Step 5: Test against conformance fixtures. Run your implementation against the conformance fixture set. Your parser must accept all valid fixtures and reject all invalid fixtures.

That is Tier 0. Your system is now a conformant UM consumer.

Use this decision tree:

  1. Do you only need to accept and pass through manifests? — Tier 0
  2. Do you need to fetch data from external sources referenced in the manifest? — Tier 1
  3. Do you need to render or display specific manifest content to users? — Tier 2
  4. Do you need to verify that manifests have not been tampered with? — Tier 3
  5. Do you need to create and sign manifests for your own subjects? — Tier 4

Most systems start at Tier 0 or Tier 1 and move deeper when the use case demands it.

TierKey resources
Tier 0Spec v0.1, Conformance v0.1, JSON Schema, Fixture examples
Tier 1Well-known names registry, Integration catalog
Tier 2Concepts — Shards, Stub manifests
Tier 3Spec v0.2, Conformance v0.2, Signed fixtures
Tier 4Spec v0.2, Conformance v0.2, Resolver conformance

Cross-cutting resources:

Q: Do I need to use TypeScript or Node.js?

No. Universal Manifest is a specification, not a library. The TypeScript reference implementation exists for convenience, but you can implement the spec in any programming language. The specification, conformance requirements, and test fixtures are all language-neutral.

Q: How much of the spec do I need to implement?

Only as much as your adoption tier requires. Tier 0 (parse-only) requires understanding seven JSON fields and enforcing a timestamp check. You can be a conformant consumer in an afternoon.

Q: Is UM stable enough to build on?

v0.1 is stable and has production infrastructure live (documentation site, resolver service, conformance fixtures). v0.2 (signature profile) is in draft. The project follows semantic versioning: once a version’s artifacts are published, they never change. Breaking changes require a new version.

Q: What if I need a feature that does not exist yet?

Shards and pointers are the extension mechanism. You can define custom shard names and pointer names for your domain without waiting for spec changes. The well-known names registry documents the conventions. Unknown names are ignored by other consumers, so your extensions will not break anyone.

Q: How does UM relate to W3C Verifiable Credentials?

UM is a container that can carry VCs as claims within shards. Think of a VC as a single stamp in a passport; UM is the passport. They are complementary, not competing.

Q: How does UM relate to DID methods?

UM recommends DIDs for subject identifiers but does not require them. Any stable URI works. The project supports did:key, did:web, and did:plc as initial integration targets, with extension lanes for additional methods like did:chia.

Q: Where can I get help?