v0.4 Conformance-Tier Stack. [PREVIEW] sections cover features still under working-group development. v0.3 remains the stable published reference.

Universal Manifest v0.4 — EXT-OPT

Optional-Feature Profiles

This document:
/spec/v0.4/ext-opt/
Document set:
Universal Manifest v0.4 (Conformance-Tier Stack)
Latest stable version:
https://universalmanifest.net/spec/v0.3/
History:
https://universalmanifest.net/spec/ (version index and changelog)
Editors:
Universal Manifest Working Group

This is a companion profile to the Universal Manifest v0.4 Base specification. It collects the capabilities that are not rungs on the trust-tier ladder but are independently optional — features a conformance claim adds orthogonally to its tier. Read the Base first; this document assumes its terminology, envelope, and evaluation sequence.

Each part below is self-contained. The Base names each of these features and points here; nothing in this document changes the Tier-0/Tier-1 conformance surface. Parts marked PREVIEW are under working-group review and revisable before the schema locks.

EXT-OPT: Optional-Feature Profiles

Companion to: Base specification (Tier-0 / Tier-1 Core). Registry categories: spans domain, signature, and others (per feature).

Contents


O1. Abstract Data Model & Format Independence

The Base names the abstract data model and treats JSON-LD as the reference encoding; this part specifies the model in full, the production-rule contract, the CBOR-LD compact encoding, and the conformance and context-integrity production details.

O1.1. Abstract Data Model

A Universal Manifest is defined in two layers. The abstract data model specifies the manifest's types, properties, and semantics independently of any serialization. A production rule specifies how that abstract model is written into — and read back from — a concrete wire format. This separation, modeled on W3C DID Core [DID-CORE], lets the manifest gain new encodings without changing what a manifest means. Member definitions and examples are presented in the JSON-LD reference encoding as an editorial convenience, not a normative restriction: every requirement stated in terms of a JSON-LD member applies to the corresponding abstract property in any conformant encoding.

The abstract data model describes a manifest as a map of abstract properties to values, using the format-agnostic core data types of [INFRA]. The abstract properties constituting a Universal Manifest (each production rule defines how a name is expressed in its format):

  • type (set of strings, REQUIRED) — MUST include um:Manifest. Expressed as @type in JSON-LD.
  • id (string, REQUIRED) — globally unique opaque identifier. Expressed as @id.
  • contextReference (list, REQUIRED) — reference to the term definitions fixing property meaning. Expressed as @context in JSON-LD; carried as a compression context reference in CBOR-LD.
  • manifestVersion (string, REQUIRED); subject (string, REQUIRED); issuedAt, expiresAt (datetime, REQUIRED).
  • facets (list, OPTIONAL); claims, consents, pointers, devices (lists, OPTIONAL); requiredTrustTier (integer, OPTIONAL).
  • signature (map, REQUIRED) — integrity proof over the payload.
  • presentationProof (map, OPTIONAL); livenessAttestation (map, OPTIONAL) — credential-binding members (EXT-T1).
  • actorState (map, OPTIONAL, PREVIEW); postQuantumSignature (map, OPTIONAL, PREVIEW — EXT-T2).

The semantics of these properties — the evaluation sequence, the tiered trust model, consent matching, signature verification, and all conformance obligations — are defined against this abstract data model and do not depend on which production rule serialized a given manifest. Extensions and future versions that define new root-level members MUST define them as abstract properties with a representation in each production rule they are used with; unknown members are preserved as unprocessed entries. A receipt-class manifest (Base §3.3.2) additionally carries the receipt field surface of Base §3.3.1 as abstract properties under the same name-per-production mapping rule. The integrity proof is computed over the bytes of a specific production (O1.5), so a signature is bound to one encoding: converting a signed manifest between encodings requires re-signing; the meaning is preserved across encodings, the signature bytes are not.

O1.2. Production Rules

A production rule is a bidirectional mapping between the abstract data model and a concrete byte representation. Production serializes; consumption parses back. A production rule MUST: (1) define a media type identifying the encoding; (2) specify how each abstract property is represented, including required and optional properties; (3) guarantee that consumption of a produced representation yields an abstract manifest equal to the original (lossless round-trip) for all properties defined by this specification. This specification defines two production rules: JSON-LD (reference) and CBOR-LD (compact). Future versions or profiles MAY define additional production rules (e.g., plain-JSON or COSE-based) without altering the abstract data model. Evaluators MUST NOT assume the absence of a production rule from this list means a manifest is non-conformant; they reject representations whose media type or encoding they do not support, exactly as they reject unsupported signature profiles.

O1.3. JSON-LD Production Rule (Reference Encoding)

The JSON-LD production rule is the reference encoding and the default for interoperation. A manifest in this encoding is a JSON-LD document [JSON-LD] as described in Base §1.2§1.6. Media type application/um+ld+json (also valid application/ld+json). The mapping is direct: abstract type, id, contextReference@type, @id, @context; all other abstract properties → JSON members of the same name; abstract datetimes → RFC 3339 [RFC3339] strings; integers/decimals/booleans/strings/lists/maps → their JSON counterparts (JSON numbers for integers and decimals, JSON true/false for booleans). A lone @context string is consumed as a one-element contextReference list; producers SHOULD emit the array form (normalization does not affect the signature, which covers the concrete bytes of the consumed production).

O1.4. CBOR-LD Production Rule (Compact Encoding)

The CBOR-LD production rule is a second, compact binary encoding defined to demonstrate that the abstract data model is genuinely format-independent. It targets constrained channels — QR codes, NFC tags, low-bandwidth/embedded transports — where JSON-LD verbosity is costly. Media type application/um+cbor-ld. CBOR-LD [CBOR-LD] compresses a JSON-LD document into CBOR [RFC8949] by using the manifest's JSON-LD context to replace string term names with compact integer tokens:

  1. Production (encode). Begin with the JSON-LD production; using the context identified by contextReference, map each defined term to its integer token, then emit as CBOR. The contextReference is carried as a context identifier (not inlined term strings).
  2. Consumption (decode). Read the context identifier, load the corresponding context, reverse the integer-to-term mapping, and reconstruct the JSON-LD document; interpreting it under O1.3 yields the abstract manifest.

This mapping is bidirectional and semantically lossless for all abstract properties: a manifest produced in CBOR-LD and then consumed MUST yield the same abstract manifest as the JSON-LD production from which it was derived. Conformance is identical across the two encodings; only the bytes on the wire differ. CBOR-LD decoding requires the manifest's context to be available to the decoder; deployments on offline or constrained channels SHOULD pre-provision the context for the relevant version, since it cannot be assumed retrievable at decode time. Term tokenization is deterministic only when both parties use the same context version, which the versioned namespace makes explicit.

Signing (candidate per-production rule). The CBOR-LD production is signed under its own production rule, per the per-production architecture of O1.5 — a Profile-A analogue defined against the CBOR bytes:

  • Signing input. Starting from the CBOR-LD document, remove the same signing-input exclusions as Base §1.6.3 — the signature property and, when present, presentationProof and postQuantumSignature — then encode the result under the Core Deterministic Encoding Requirements of RFC 8949 §4.2.1 [RFC8949]. The signing input is those deterministic-encoding bytes. This parallels Profile A exactly — parse the consumed production, remove the exclusions, canonicalize, sign or verify — with CBOR deterministic encoding playing the role JCS plays for JSON.
  • Algorithm and profile identity. Ed25519 over that input. The signature object carries the same members as Profile A (Base §1.6.2), with the candidate canonicalization value "CBOR-RFC8949-CDE"; the algorithm + canonicalization pair ("Ed25519" + "CBOR-RFC8949-CDE") identifies the profile per Base §1.6.5.
  • Verification. A verifier of a consumed CBOR-LD manifest recomputes the signing input from the bytes it consumed — parse, remove the exclusions, re-encode deterministically — and verifies against them, never against another production's bytes (O1.6).

Because the signing input is the tokenized form, the signature is bound to the context version that fixes the token mapping; the pinned-context and context-hash disciplines of O1.7 therefore apply before signing or verifying. Prohibited implementation (explicit). Verifying a manifest's JSON-LD-production signature against bytes reconstructed from a consumed CBOR-LD document is prohibited: O1.6 requires verifying the integrity proof against the bytes of the production actually consumed, and O1.5 forbids a signature from traveling across a re-encoding. A manifest converted from JSON-LD to CBOR-LD MUST be re-signed under this rule before it is presented in CBOR-LD (and symmetrically, a manifest re-encoded back to JSON-LD is re-signed under Profile A). With this rule stated, a signed — hence conformant — CBOR-LD manifest is constructible by design, as O1.4's identical-conformance sentence requires; the rule remains a candidate until wire freeze.

Preview: A complete CBOR-LD profile — the registered context-to-token table, finalization of the candidate signature production above, and conformance fixtures — will be finalized after working-group review. Input is requested on whether CBOR-LD is the right compact encoding to standardize first.

O1.5. Signing and Production

The integrity proof is computed over the canonical bytes of a specific production. Signature Profile A (Base §1.6) is defined against the JSON-LD production: the signing input is the JCS-canonicalized JSON-LD document with the signing-input exclusions removed (the signature property and, when present, presentationProof and postQuantumSignature); the production consumed for signing is constrained to I-JSON with duplicate member names rejected (Base §1.6.3), which is what makes the JCS input well-defined. Each production rule MUST either reuse a profile defined against the abstract model or specify how the integrity proof is computed over its own canonical bytes, so a verifier can recompute the signing input deterministically. Both production rules defined by this specification have a stated integrity-proof computation: Signature Profile A for JSON-LD, and the candidate Profile-A analogue over RFC 8949 Core Deterministic Encoding bytes for CBOR-LD (O1.4). Because a signature is bound to the bytes of one production, a manifest re-encoded under a different production rule MUST be re-signed under that production's signing rule. (Working-group note: whether a future profile should sign a canonicalization of the abstract model — making one signature portable across encodings — is the strategic open question of the format-independence design; this draft builds in per-production signing, and the abstract-model option stands as the recorded question for the next version.)

O1.6. Conformance to the Abstract Data Model

The behavioral requirements of Base §4.1§4.3 are stated against the abstract data model and apply identically regardless of encoding. A conformant implementation MUST support at least one production rule and SHOULD support the JSON-LD reference encoding; MUST consume supported representations into the abstract data model before applying behavioral requirements; MUST reject an unsupported encoding rather than misinterpreting it; MUST preserve every abstract property across a production/consumption round-trip when it both produces and consumes an encoding; and MUST verify the integrity proof against the bytes of the production it consumed. Supporting only the JSON-LD reference encoding is sufficient for full conformance; supporting CBOR-LD is OPTIONAL.

Carrying external standards (informative). The same wrapper discipline extends beyond UM's own encodings. A manifest can carry — as a facet or claim value — or point to (via pointers) an artifact governed by another standard: C2PA content-credential material [C2PA], an OGC GeoPose payload [OGC-GEOPOSE] (O14), a W3C Verifiable Credential, or a comparable external artifact. Universal Manifest complements such carrier and provenance standards; it does not replace them. The carried artifact travels unmodified — UM never re-signs, transforms, or reinterprets its bytes — and it remains independently verifiable under its own standard's rules: a receiver performs two independent checks, the UM envelope evaluation defined by this document set and the carried standard's own verification, and passing one never substitutes for the other. An evaluator that has verified the UM envelope has not thereby verified the carried artifact; absent a registered carry profile, a carried standard the evaluator cannot evaluate is preserved as sealed/opaque or unprocessed content under the existing fail-closed baselines (Base §3.3.1), never reported as verified. A dedicated external-standard-carry profile — a registered carried-standard verification-result receipt field and an unknown-carried-standard disposition value — is a registered-profile candidate (O6) whose wire shape is not defined by this draft.

O1.7. Context Integrity (production detail)

Term meanings — and, for CBOR-LD, tokenization — depend on the content of the versioned namespace context. The manifest signature covers the context reference (the URI string), not the context document content: if the served context changes or an attacker controls its resolution, term semantics and CBOR-LD round-trips can change silently under a still-valid signature. To prevent this, the versioned namespace URI identifies an immutable context: once published, the context document for a version MUST NOT change. Evaluators SHOULD ship or pin the context for each supported version rather than fetching it at evaluation time, and MUST NOT fetch contexts from untrusted resolvers at verification time. CBOR-LD deployments MUST use the pinned context, since tokenization correctness depends on byte-identical context versions on both sides. (The Base states the evaluator-facing requirement in Base §6.10; this is the production/encoding detail.)

Hash computation. The context content hash named by Base §6.10 and reproduced in Base Appendix B is a multihash [MULTIFORMATS]; the multihash function MUST be SHA-256 (multihash function code 0x12) for v0.4, the same function required for the receipt-chain prevHash. The hash input is the exact published byte sequence of the versioned context document — its UTF-8 text with LF (U+000A) line endings and a single trailing LF — with no re-serialization, JSON canonicalization, whitespace normalization, or transcoding applied before hashing. Where the hash appears in text-bearing positions it is expressed as a multibase base58btc string (z prefix); binary positions MAY carry the raw multihash bytes. The hash is encoding-independent and pins the context for every production rule: a JSON-LD evaluator verifies it before trusting term definitions (Base §6.10), and a CBOR-LD deployment MUST verify it over those identical bytes before deriving or applying a term-token table (O1.4).


O2. statusRef Resolution Schema

This part specifies the resolution protocol for the signature.statusRef field (Base §1.6.6, Base §3.4). signature.statusRef resolves the status of the manifest instance identified by manifestId; it does not convey the revocation status of any key (key revocation is determined separately via the key's DID document verification-method state, or a claimProof entry's own statusRef). These distinct objects of revocation MUST NOT be conflated.

O2.1. Resolution Procedure

When signature.statusRef is present and the evaluator implements revocation-aware verification, the evaluator MUST: (1) issue an HTTP GET to the statusRef URI; (2) if it has a cached response, SHOULD include its most recently stored cursor in an If-None-Match header (subject to the revocationCursor floor below); (3) the status endpoint MUST respond with content type application/json; (4) the evaluator MUST parse the response and evaluate the status field. statusRef URIs MUST use https; status responses carry no independent signature, so authenticated transport is the only integrity protection — evaluators MUST NOT resolve a statusRef over plaintext and MUST treat a non-HTTPS statusRef as unreachable. Status endpoints SHOULD return an ETag equal to the current cursor; a 304 Not Modified means status is unchanged. The holder-embedded signature.revocationCursor is the issuance-time floor: an evaluator whose cached response is older than revocationCursor MUST revalidate, and the response cursor supersedes it thereafter.

O2.2. Response Schema

A status endpoint MUST return a JSON object with manifestId (MUST match the manifest's @id), status (one of "active", "revoked", "suspended"; MUST be present), and updatedAt (RFC 3339; MUST be present). It MAY include reason (human-readable), cursor (opaque; evaluators SHOULD store for conditional requests), and nextCheck (an ISO 8601 duration, e.g. "PT1H", recommending when to next poll; evaluators SHOULD respect it).

O2.3. Status Semantics

  • "active" — signature and credentials remain valid; the evaluator MUST continue evaluation.
  • "revoked" — permanently invalidated by the holder; the evaluator MUST reject with outcome "rejected" and revocationStatus: "revoked".
  • "suspended" — temporarily suspended; the evaluator SHOULD treat as "accepted-with-warnings" and record revocationStatus: "suspended"; MAY apply local policy on whether to process.

O2.4. Error Handling

When the status endpoint is unreachable or errors, evaluators MUST: on 404, record revocationStatus: "unchecked" with reason um:reason:status:endpoint-unknown-manifest; on 503 or network failure, record "unchecked" with reason um:reason:status:endpoint-unavailable and MUST NOT reject the manifest solely because the endpoint is unreachable; on other 4xx/5xx, record "unchecked" with the HTTP status code in the reason. Evaluators in offline mode MUST record "unchecked" with reason um:reason:status:offline. Deployments MAY use a W3C Bitstring Status List endpoint [VC-STATUS] as the statusRef target, provided the evaluator can parse the response into the status semantics above; this is a SHOULD-level alternative that mitigates the status-resolution correlation risk (O5 and the status-resolution correlation consideration in Base §7).

O2.5. Status Endpoint Conformance

A conformant status endpoint (Base §4.6) MUST respond with the response schema and status semantics above (including the status values and the cursor/nextCheck fields), MUST key its response to the manifestId queried, and SHOULD support conditional requests. Resolver conformance (the federated-status class of O5) is deferred pending the working-group decision on whether federation moves to a companion specification.

(Worked example: statusRef response — see Cookbook.)

O2.6. Current Policy-State Profile PREVIEW

Candidate registered profile (candidate identifier um:profile:trust:current-policy-state, registration via O6; the identifier — including its trust category segment — is provisional, since category assignment is a registration-time decision). Design-stage: the members and value tokens below are candidates whose wire shape may change; they are not yet in the published schema.json/schema.jsonld or the conformance fixture suite, and per the Base conformance discipline (Base §4.4) they carry no conformance tests until the design is finalized.

The bounded composition in Base §3.4.1 answers "is this consent/authorization state still current?" from existing machinery. This profile adds the three pieces that composition deliberately leaves open, for deployments that need them. It applies to any governed asset or action — 3D assets, scans, media, digital replicas, embodied-person representations, and agentic actions alike.

Supersession pointer. A status response (O2.2) MAY additionally carry supersededBy — a URI identifying the record (typically a newer manifest instance) that replaces the queried one. supersededBy is meaningful only alongside status: "revoked" or "suspended"; the closed status enum is unchanged, so endpoints and evaluators that do not implement this profile interoperate unmodified (an unrecognized member is ignored). An evaluator implementing this profile SHOULD record the pointer in the receipt (reason um:reason:policy:superseded) and MAY request the successor record from the holder; it MUST NOT treat the superseded record's grants as current. supersededBy is discovery metadata, not a trust grant: like the rest of the status response it carries no independent signature (O2.1), and a successor record confers nothing until it is itself evaluated — signature, TTL, status, consent — under the ordinary evaluation sequence (Base §3.1).

Policy-window taxonomy. A deployment, profile, or consent condition MAY declare a policyWindow (ISO 8601 duration) for a governed action: the maximum age of current-state evidence (a status response, a consent record's validation, a delegation liveness check) the evaluator may act on. Within the window, cached evidence MAY be used, subject to the nextCheck and revocationCursor rules of O2.1. Beyond the window, or when state cannot be resolved at all, the evaluator MUST NOT proceed on stale state and MUST apply the declared unresolved-state disposition: deny (refuse the governed action; the default when no disposition is declared — fail closed) or escalate (withhold automatic processing and route the decision to a designated out-of-band authority; escalation is a refusal-to-proceed-automatically, never a grant). The disposition vocabulary is a registry, extensible via O6.

Policy-window carrier (candidate). A consent-carried policy window is expressed as consent conditions tokens (Base §1.4.4), in the same plain-string condition shape as the route-class:<value> convention (O13.4; O6 registry-token note): policy-window:<duration> (e.g. policy-window:PT1H, the ISO 8601 duration) declares the window for governed actions under that consent entry, and policy-disposition:deny / policy-disposition:escalate declares the unresolved-state disposition (absent a disposition token, deny — the fail-closed default above). At most one policy-window: token and one policy-disposition: token may appear on one entry; an entry carrying more than one of either is unenforceable and fails closed under the Base's condition rule. A deployment- or profile-declared window is configuration, declared out-of-band (for example in the deployment's conformance claim, O11.1, or the profile's registration entry) and evaluated identically. Interoperation degrades safely: to an evaluator that does not implement this profile the tokens are unrecognized conditions, so the governed facet already fails closed under Base §1.4.4 — a non-implementer can never process more than an implementer. Default when no policy window is declared by any carrier: no additional currency bound applies — the existing machinery alone governs (TTL, nextCheck/revocationCursor, consent validity windows, per Base §3.4.1); this profile adds no implicit window.

Reason codes and receipt evidence. This profile registers the reason-code candidates um:reason:policy:superseded, um:reason:policy:unresolved, um:reason:policy:window-expired, and um:reason:policy:escalated (O3.3), and the receipt event-class candidates policy-state-resolved, policy-state-stale, and policy-state-escalated (O3.2), so the disposition of a governed action — resolved, unresolved, stale, superseded, denied, or escalated — is machine-readable in the receipt (Base §3.3).

Honest limits. The profile makes currency decisions auditable and fail-closed; it does not make a status endpoint truthful (transport integrity per O2.1 is the only response-integrity protection), does not erase or relabel state already acted on under a then-valid record (consistent with Base §7.2), and does not by itself provide resolver-operator privacy (see the status-resolution correlation considerations in Base §7).


O3. Receipt as a First-Class Manifest Class PREVIEW

A receipt is itself a first-class manifest class (Base §1.0.1, Base §3.3.2): a signed, portable record that can be chained, retained, and independently verified, carrying the common envelope members with @type including both um:Manifest and um:Receipt, plus the receipt fields of Base §3.3.1. The envelope's subject on a receipt manifest is the evaluator that produced it: the receipt is a record of the evaluator's own processing act, and the manifest it processed is identified by the manifestId receipt field, not by subject (this is the practice the fixture suite and Cookbook already follow). This promotion is additive; an evaluator that only emits inline receipts remains conformant, and the chain-integrity members are OPTIONAL unless a receipt is part of a sequence.

O3.1. Chain Integrity

Receipts in a session or audit sequence form a hash-linked chain. A chained receipt MUST include chainId (a URI identifying the chain; for a bilateral session it MUST equal the sessionId of O4; it is the stable identifier tying a sequence together — exchangeId is per exchange round and does not serve this purpose), seq (a monotonically increasing non-negative integer; the first receipt has seq 0), and prevHash (the hash of the immediately preceding receipt's canonical signing bytes, encoded as a multibase/multihash string [MULTIFORMATS]; the multihash function MUST be SHA-256 for v0.4; omitted for seq 0).

A chained receipt SHOULD be signed with a session-scoped signing key (for example, deviceCapability.sessionSigningKey of O9.2, or another ephemeral key bound to the session) rather than a long-lived identity key, so a receipt chain does not become a long-lived correlator. Because a session-scoped key cannot be authorized through the subject's DID document the way EXT-T1 §T1.5 authorizes manifest-signing keys, a session-scoped receipt-signing key MUST be introduced by a sessionKeyAuthorization — a candidate member of the chain's first (seq 0) receipt manifest, carrying the authorization object inline or a URI resolving to it. The authorization object's candidate shape: sessionKey (REQUIRED — the session public key, as a JWK or a multibase-encoded public key; it MUST be the key that signs the chained receipts, e.g. the deviceCapability.sessionSigningKey); chainId (REQUIRED — MUST equal the chain's chainId); validFrom and validUntil (REQUIRED — RFC 3339; the window within which this key may sign receipts of the chain); and signature (REQUIRED — a Signature Profile A signature over the authorization object, computed by applying the Base §1.6.3 procedure to the object with its own signature member excluded, produced by a key authorized for the evaluator's DID — a key appearing under authentication or assertionMethod in the DID document of the evaluatorId party). A verifier attributing a session-signed chain MUST verify the authorization — the evaluator-key signature, the chainId match, that the chained receipts' signing key equals sessionKey, and that each receipt was signed within the validity window — before attributing the chain to the evaluator; on failure, chain integrity may still verify link by link, but the chain is unattributable and MUST NOT be attributed to the evaluator. Evaluators verifying a chain MUST confirm each seq increments by one without gaps and each prevHash matches the prior receipt; a broken link MUST be reported and the chain after the break treated as unverified.

Verifying an archived chain vs. acting on a receipt. A chained receipt is a durable audit record, and its links age past their manifest TTLs. The freshness gate (Base §3.1.2) and cache eviction (Base §3.2) govern acting on a receipt's content as current state; they do not govern verifying an archived chain. Chain verification — signature validity, seq continuity, prevHash linkage, and the sessionKeyAuthorization — proceeds over expired links unchanged: an auditor records an expired link as expired (its content is stale for action) but MUST NOT treat expiry as a broken link under the broken-link rule above. Deployments retaining chains for audit SHOULD bound retention per Receipt Minimization (Base §7).

O3.2. Typed Event Vocabulary

A receipt manifest MAY carry an events array recording typed lifecycle events. Each event object MUST carry an eventType from the registry below and an at (RFC 3339) timestamp; it MAY carry an event-specific reason (O3.3) and a subjectRef identifying the affected facet, claim, consent, or device. Recognized event classes: manifest-arrived, manifest-verified, manifest-rejected (envelope lifecycle); facet-processed, facet-sealed, facet-consent-denied (facet outcomes); consent-granted, consent-withdrawn, consent-expired (consent transitions); claim-verified, claim-failed, binding-verified, binding-failed (trust outcomes); avatar-retrieved, avatar-substituted (presence/avatar disclosure outcomes; presence is a locator, not authorization); facet-key-rotated, facet-key-shredded (facet-encryption key-lifecycle events — Base §2.3.5); session-unlocked (the opening of an unlock window — O4.5); session-unlock-refused (an unlock or locked-facet access withheld because the asserted assurance class was below the facet's requiredAssuranceClass floor — EXT-T1 §T1.3.3; carries reason um:reason:trust:assurance-insufficient); session-completed (session terminal event). This is a registry, not a closed enumeration: new classes are added through the profile registration mechanism (O6). Evaluators encountering an unrecognized eventType MUST preserve the event but MUST NOT act on it.

Key-lifecycle and unlock events MAY carry an OPTIONAL facetKeyRef field identifying the affected facet-encryption key by its kid as an identifier, never key material. facetKeyRef is distinct from signature.keyRef (the signature-verification key URI) and from the receipt keyRefResolution field — distinct referents, distinct names. A facet-key-shredded event records the emitter's assertion and timing of key destruction, not cryptographic proof that copies are gone; consumers MUST NOT treat it as retroactive revocation (paralleling the Sealed-Entry Forward Secrecy discipline, Base §7.2). Key-rotation/shred histories are bounded by the events array limits of the Base resource limits (Base §6.3: maximum array length 1,000 entries / maximum manifest size 1 MB), so an evaluator is not forced into unbounded replay. Key-lifecycle events are subject to Receipt Minimization (Base §7: carry only facetKeyRef as an identifier, minimum detail) and SHOULD ride session-scoped-signed receipt chains (O3.1), so the shred/rotation stream is not a long-lived cross-interaction correlator.

O3.3. Structured Reason Registry

Receipt reason values (on facet statuses, consent statuses, and events) SHOULD be drawn from a structured reason registry using um:reason:<category>:<code> naming (for example um:reason:consent:withdrawn, um:reason:crypto:no-decryption-key, um:reason:crypto:key-rotated, um:reason:crypto:key-shredded, um:reason:trust:tier-unsupported, um:reason:trust:assurance-insufficient). Structured reasons make receipts machine-comparable. Free-text reasons remain valid where no registry code applies. New reason codes are registered through the profile registration mechanism (O6).

O3.4. Transparency-Log Anchoring (optional)

A receipt manifest MAY be anchored to an append-only transparency log following the Certificate Transparency 2.0 model [RFC9162]. When anchored, the receipt MAY carry a transparencyAnchor object with logId, inclusionProof (a Merkle inclusion proof; its structure is a wire-freeze decision to be bound to the [RFC9162] inclusion-proof structure — log identity, tree size, leaf index, audit path — and until then it is carried as an opaque candidate object), and anchoredAt (RFC 3339). Anchoring is OPTIONAL and does not increase per-event cost for deployments that do not use it; it provides tamper-evident, independently auditable history. Evaluators that do not implement transparency anchoring MUST preserve the transparencyAnchor field without acting on it.

(Worked example: chained receipt manifest with typed events — see Cookbook.)

Preview: Promoting the Receipt to a first-class class — with the seq/prevHash chain, typed event vocabulary, structured reason registry, and optional CT-style anchoring — is built on the editors' default (promote in v0.4; additive). Input is requested on the canonical event-class and reason-code registries and on the hash/multibase encoding for prevHash.


O4. Bilateral Session Model PREVIEW

This part specifies the protocol-layer session model for bilateral exchanges, extending the manifest-level bilateral exchange of Base §6.4.6 with session objects, paired receipt correlation, and exchange identifiers.

O4.1. Session Object

A bilateral session is a time-bounded interaction between two participants who each present and evaluate the other's manifest. A session object MUST contain @type ("um:BilateralSession"), sessionId (a globally unique URI; MUST be present), exchangeId (a correlation identifier shared by both parties in a single exchange round; both include the same exchangeId in their receipts; MUST be present), participants (an array of exactly two participant objects, each with a did and role ∈ {"initiator", "responder"}), initiatedAt (RFC 3339), expiresAt (RFC 3339; evaluators MUST reject session operations after this time), and state. A session comprises exactly one exchange round; a new exchange between the same parties is a new session with new sessionId/exchangeId. sessionId and exchangeId MUST each be generated with at least 128 bits of entropy and MUST NOT encode party identifiers, since both are correlation tokens the parties rely on. Session operations — the acts governed by the session lifecycle and its TTL — are: presenting or accepting a manifest under the session, producing or accepting a receipt bearing the session's exchangeId, and the completion acknowledgment (O4.2). After expiresAt, the session is "expired" and a participant MUST NOT perform or accept any of these under that sessionId/exchangeId; receipts already exchanged remain valid records.

O4.2. Session Lifecycle

States, strictly forward (no return to a previous state): "initiated" (initiator created the session and sent sessionId/exchangeId); "manifests-exchanged" (both presented manifests; each SHOULD reference exchangeId in its presentation context); "receipts-exchanged" (both produced and shared receipts; each receipt MUST include exchangeId); "completed" (both acknowledged the other's receipt); "expired" (TTL elapsed without "completed"; evaluators MUST treat as terminated). "expired" MAY be entered from any active state. The "completed"-state acknowledgment mechanic — how a party signals that it received the counterparty's receipt — is transport-defined (O4.4): a transport binding MAY use a message type, an HTTP response, or an equivalent; the session model requires only that both acknowledgments occur before the session is "completed".

O4.3. Paired Receipt Correlation

A receipt produced as part of a bilateral session MUST include an exchangeId matching the session's, enabling pairing: Party A's receipt (evaluating B's manifest) correlates with Party B's receipt (evaluating A's manifest) via the shared identifier. A receipt exchanged in a bilateral session MUST include evaluatorId and SHOULD carry receiptSignature, so the exchanged receipts are attributable and tamper-evident.

O4.4. Transport Independence

The session model is transport-agnostic. Sessions MAY be conducted over any transport that can carry manifest payloads in a supported production rule — JSON-LD or (once finalized) CBOR-LD on constrained channels: local transports (NFC, BLE, QR scan), network transports (HTTPS, WebSocket), or hybrids. Transport-specific bindings MAY be defined in profile documents. The session object MUST NOT assume any specific transport capability.

O4.5. Unlock Window PREVIEW

An unlock window is a time-bounded grant that opens a holder-enumerated set of facets for a single subject. It is not a um:BilateralSession (O4.1): it has no participants, no exchangeId, and is a single-subject construct. An unlock window is a recognized composition of an existing consent carrying unlock.window in its scope (dot form, per the agent-delegation scope convention of O7), with grantedAt, expiresAt, an optional withdrawnAt, and the enumerated facet set (unlockWindowFacets, defined below). It is not a new manifest object.

The window's consent members. The unlock-window consent is an ordinary consent entry (Base §1.4.4) whose scope contains the unlock.window token, extended by one member this profile defines: unlockWindowFacets — an array of facet @id strings explicitly enumerating the facet set the window opens. unlockWindowFacets is REQUIRED on a consent whose scope contains unlock.window; it MUST be explicit and bounded (literal @id values only — no wildcard or pattern forms), and, like the OPTIONAL unlock-policy members below, it is carried on the consent object inside the signed payload. A consent carrying unlock.window without unlockWindowFacets is malformed for this profile, and the window MUST NOT be opened (fail closed). An entry of unlockWindowFacets that matches no facet of the presented manifest is inert — a window cannot open what is not projected. The consent's facetRef (REQUIRED by the Base consent shape) MUST name one facet of the enumerated set: it designates an anchor member, and the Base's scope/purpose/validity matching applies to the entry as usual — but the set the window opens is governed by unlockWindowFacets, never by facetRef alone. (Wire status: unlockWindowFacets and the unlock-policy members are grade-1 structural PREVIEW — present in the published v0.4 context and, for the enumeration, exercised by a shape fixture — while the enforcement semantics of this part remain revisable, per the two-grade PREVIEW policy.)

An unlock window MUST be sound on the following axes:

  1. Bounded / enumerated facet set. The window MUST explicitly enumerate the facet set it opens (by @id, in unlockWindowFacets — defined above). It MUST NOT open an unbounded or implicit set. This prevents the "one ceremony unlocks everything" anti-pattern that per-facet isolation (Base §2.3.5) exists to prevent.
  2. Never lowers a per-facet floor or isolation. The window MUST NOT lower or bypass any per-facet requiredLiveness floor (EXT-T1 §T1.3.1) or any isolation obligation (Base §2.3.5). A facet whose floor is unmet stays withheld even inside the window.
  3. Re-attestation on freshness decay. When the opening liveness attestation's freshnessClass degrades below a facet's floor during the window, the window MUST require re-attestation for that facet; a single attestation MUST NOT grant a window outliving its freshness class.
  4. Anti-replay binding. The window MUST bind to a fresh presentationProof / nonce (EXT-T1 §T1.2), with audience binding, so static signed bytes cannot be replayed to re-open a window. This is the same anti-replay primitive a write inside the window reuses; a write is additionally per-write replay-guarded (Base §3.1.4).
  5. Fail closed on unobservable lifetime conditions. Idle-timeout and lock-on-sleep are runtime-only conditions the receipt cannot prove; only grantedAt/expiresAt/withdrawnAt are auditable bounds. Where a lifetime condition is unobservable, the evaluator MUST fail closed. The window bounds the authorization window, not in-use plaintext (see the in-use-plaintext note, Base §7.2).
  6. Receipt-side liveness reference. The opening ceremony is recorded as a session-unlocked event in the typed event vocabulary (O3.2), referencing the opening liveness attestation — the liveness reference adds no consent member. The window itself is carried by the unlock.window scope token plus the unlockWindowFacets enumeration and the OPTIONAL unlock-policy members (the consent-object members this profile defines); the receipt-side record adds nothing further to the consent object.

What opening means — the window never substitutes for consent (fail closed). Opening an unlock window is an unlock ceremony plus a time-boxed authorization window; it is not a consent grant. Membership in unlockWindowFacets does not authorize any operation on a facet: each enumerated facet is processed only under a consent entry of its own that governs it — Stage 4 (Base §3.1.4) applies unchanged, so an enumerated facet with no governing consent entry stays "consent-missing" and MUST NOT be processed even while the window is open. What the window adds, for the enumerated set and only within grantedAtexpiresAt (as tightened by the unlock-policy bounds below): (1) the opening ceremony — the fresh presentationProof/liveness binding of axes 3–4 — gating access to locked-tier facets (EXT-T1 §T1.3.3); (2) the time box — outside an open window, a locked-tier facet of the set reverts to locked/withheld even where its own consent entry remains valid; and (3) the auditable record — the session-unlocked event of axis 6. A write inside the window additionally requires its own write-consent and per-write replay guard (Base §3.1.4).

Unlock-policy fields (locked-tier auditability). When an unlock window opens a locked-tier facet (EXT-T1 §T1.3.3), the unlock-window consent MAY additionally carry these OPTIONAL unlock-policy members so the time-boxed grant is auditable and tightly bounded:

  • idleLifetime — an ISO 8601 duration (e.g. "PT10M") after which an idle window SHOULD re-require the unlock gesture;
  • absoluteLifetime — an ISO 8601 duration (e.g. "PT12H") capping the window regardless of activity; it MUST NOT extend the consent's own expiresAt (the consent expiresAt remains the hard auditable bound);
  • lockOnSleep — a boolean; when true, the runtime SHOULD close the window when the device sleeps/locks.

These fields state policy intent and defaults+floor, not a single mandated number: a conformant deployment SHOULD default to a short idle lifetime and a bounded absolute cap (representative practice: a ~10-minute idle timeout with a ~12-hour absolute cap; a software-class unlock that derives a key from a passphrase SHOULD use a memory-hard KDF — e.g. Argon2id with at least 19 MiB of memory — for the software rung). The exact minutes and KDF parameters are tunable policy.

This is additive clarification, not a contradiction of axis 5: idleLifetime, absoluteLifetime, and lockOnSleep are runtime-only conditions whose enforcement the receipt cannot prove. Axis 5 stands — only grantedAt/expiresAt/withdrawnAt are auditable bounds, and where a lifetime condition is unobservable the evaluator MUST fail closed. Declaring these fields commits the runtime to the policy; it does not make the runtime condition retroactively auditable.

(Worked example: bilateral session object — see Cookbook.)

Note (working-group): Whether the session model remains in the core specification or is published as a separate companion specification is open; bilateral sessions are protocol-layer concerns that may evolve independently of the manifest format.


O5. Federation PREVIEW

This part specifies the federation model: how multiple resolver operators coordinate to provide status checks, cache invalidation, and availability across a distributed network.

Resolver coordination. A federated resolver network consists of two or more resolver operators that synchronize manifest status. Resolvers MUST identify themselves using DIDs and MUST establish mutual trust through bilateral attestation: each operator issues an attested claim about the peer's resolver identity — an ordinary attester-asserted claim whose subject is the peer's DID (a candidate identity.peerAttestation claim type, registrable via O6), or an equivalent mutual-attestation pattern. identity.crossDidBinding is not that pattern and MUST NOT be used for peer trust: it asserts that multiple DIDs are controlled by the same entity (Base §6.4.4), which is precisely not the relationship between two independent resolver operators. Resolver discovery is out of scope; deployments MAY use a well-known URI (/.well-known/um-resolvers), a DID service endpoint, or out-of-band configuration.

Status check distribution. When an evaluator resolves a statusRef URI, it MAY query multiple federated resolvers. If any resolver reports "revoked", the evaluator MUST treat the manifest as revoked (revocation is authoritative and overrides other responses). If resolvers disagree, the evaluator MUST act on the most restrictive status received and SHOULD record a warning with reason um:reason:status:federation-inconsistent; the recorded revocationStatus reflects the most restrictive answer received, not "unchecked". The restrictiveness order is "revoked" > "suspended" > "active" (most to least restrictive); "unchecked" is not a member of this order — it is reserved for the case where no resolver returned an answer. If all queried resolvers are unreachable, follow the error handling in O2.4.

Cache invalidation. When a manifest's status changes, the issuing resolver MUST propagate the change to all federated resolvers; the federation SHOULD achieve propagation within 60 seconds for revocation events. During the propagation window, different evaluators may receive different answers. Evaluators SHOULD treat cached status as provisional and re-check per nextCheck.

Availability and failover. The federation uses eventual consistency. Evaluators MAY query any federated resolver, not only the primary statusRef endpoint; if the primary is unavailable, the evaluator SHOULD fall back to alternative resolvers discovered through the federation. In split-brain scenarios, the recorded revocationStatus reflects the most restrictive answer actually received from any reachable resolver, with a um:reason:status:federation-inconsistent warning; "unchecked" is reserved for the case where no resolver returned an answer.

Manifest forwarding. When a manifest is forwarded across federation boundaries, the forwarding agent MUST preserve all fields (unknown fields survive the evaluation sequence). Forwarding metadata MUST NOT be added to the manifest payload, because the payload's bytes are covered by the signature; a forwarding agent MAY convey a forwardedVia array (resolver DIDs in path order) in transport-level metadata or a wrapper object that carries the manifest unmodified (the wrapper's shape is transport-profile-defined; this profile constrains only that the carried manifest bytes are unmodified) — such metadata is informational and MUST NOT affect evaluation. Forwarded manifests MUST be re-verified by the receiving evaluator; the forwarding agent's handling does not substitute for the receiver's own evaluation.

Note (working-group): Whether federation should be published as a separate companion specification is open; it introduces protocol-layer complexity that may evolve independently of the manifest format.


O6. Profile Registration Mechanism PREVIEW

This part defines the formal registration process for new cryptographic, trust, and domain profiles that extend the Universal Manifest specification, following IANA-style registry conventions. It is the mechanism the Base §5 extension model relies on.

Profile identification. Each registered profile MUST have a canonical identifier following um:profile:<category>:<name>. Categories: signature (e.g., um:profile:signature:jcs-ed25519), trust (e.g., um:profile:trust:zkp-bbs-linked-secret, um:profile:trust:locked-tier-portable-unlockEXT-T1 §T1.3.3), domain (domain-specific manifest class profiles, e.g., um:profile:domain:receipt), binding (credential binding profiles, e.g., um:profile:binding:sd-jwt-kb). Each identifier MUST be paired with a human-readable name and version string; identifiers are globally unique and MUST NOT be reused after deprecation. This process also governs the subsidiary value registries referenced elsewhere: receipt event classes (O3.2), receipt reason codes (O3.3), agent-delegation scope values (O7), liveness proofType values (EXT-T1 §T1.3), and additional JWE algorithm pairs (Base §2.4).

Registration process (five steps). (1) Proposal — a profile author submits a specification to the working group via the [UM-RFC] mechanism, including a scope statement, normative requirements (RFC 2119 keywords), security considerations, an interoperability assessment, and at least one conformance test fixture. (2) Review — the working group reviews for completeness, security, and interoperability, and MUST verify the profile does not conflict with existing profiles at the same extension point. (3) Conformance integration — the author provides fixtures; the working group integrates them into the conformance suite. (4) Registration — upon consensus, the profile receives its canonical identifier and is added to the registry. (5) Maintenance — the author maintains the spec and tests; the working group MAY deprecate the profile if maintenance lapses, security issues arise, or a superseding profile is registered.

Conflict resolution. Two profiles defining incompatible semantics for the same extension point MUST NOT both be registered without resolution; the working group MUST resolve by merging, selecting one, or defining a compatibility boundary. Deprecation. The working group MAY mark a profile "deprecated" (with a date and superseding-profile reference); evaluators SHOULD warn on deprecated-profile references but MUST NOT reject manifests solely for referencing one until the profile is declared "sunset" at a major-version boundary. Registry hosting. The registry MUST be published as a standalone document at https://universalmanifest.net/registry/profiles/, updated independently of the specification version; each entry contains the identifier, name, version, status ("active", "deprecated", "sunset"), specification URI, and registration date.

Registry-token representation in the JSON-LD encoding (informative). The published v0.4 context gives the registry-token families used across this document set three distinct JSON-LD shapes, and profile authors should account for them at registration time. (1) Receipt reason codes (um:reason:<category>:<code>, O3.3) ride a plain, uncoerced term — values are inert literal strings, with shipped wire precedent in the conformance fixtures (um:reason:crypto:key-rotated / um:reason:crypto:key-shredded); design-stage candidate families such as the O2.6 um:reason:policy:* and O13.5 um:reason:route:* codes follow that same pattern unchanged if finalized. (2) Consent conditions values — including the O13.4 route-class:<value> candidate convention — are members of an unordered set of plain strings; they undergo no compact-IRI expansion and are compared as opaque tokens. (3) profile identifiers (um:profile:<category>:<name>) are @id-coerced, so a value expands as a compact IRI under the version-independent um: prefix; a registered profile identifier is thereby a globally unique IRI, not a bare label. The term-shape asymmetry — reason codes and conditions as opaque strings, profile identifiers as IRIs — is deliberate at this stage: reason codes and conditions are matched by evaluators as tokens, while profile identifiers name registry entries that benefit from global identity. Whether a design-stage candidate token family enters the versioned context, and in which of these shapes, is a context-terms decision taken at wire freeze through this registration process; appearance of a candidate token in a design-stage draft confers no context registration.

Note (working-group): Whether low-risk profiles (e.g., new domain entity types) should follow a lighter-weight registration with designated expert review instead of full consensus is under evaluation.


O7. Agent-Delegation Scope Registry PREVIEW

This part defines a registry of recognized scope values for the scope field in um:agentDelegation pointers (Base §6.5), with a namespace convention and registration procedure.

Namespace convention. Scope values MUST follow a dot-separated <domain>.<capability> naming (the domain identifies the functional area; the capability the specific authority). Examples: spatial.session, social.messaging, commerce.transaction. Custom scope values defined by profile documents SHOULD use a reverse-DNS prefix to prevent collisions (e.g., com.example.custom-capability).

Core scope values. All evaluators recognizing um:agentDelegation pointers MUST understand these: spatial.session (participate in spatial computing sessions on behalf of the subject); spatial.navigation (navigate spatial environments); social.messaging (send and receive messages); social.presence (represent the subject's presence status); commerce.transaction (initiate transactions, within any spending limits declared by profile-defined members — this specification itself defines no spending-limit member); identity.attestation (present the subject's identity claims to verifiers — does not grant authority to create or modify claims).

Evaluator behavior for unrecognized scopes. An evaluator encountering unrecognized scope values MUST: (1) record them in the receipt; (2) restrict the delegate to only the recognized scopes (the delegate MUST NOT exercise capabilities for unrecognized scopes); (3) if the pointer contains only unrecognized scopes, SHOULD treat the delegation as having no effective scope and record this.

Registration procedure. New scope values are registered through the profile registration mechanism (O6); a registration MUST include the scope string, a description, the domain it governs, and any constraints (e.g., "requires requiredTrustTier >= 1").

(Non-normative: Mastercard's Verifiable Intent pattern — a three-layer SD-JWT structure for bounded-scope agent delegation — is compatible, each layer mapping to a scope constraint. Working-group note: whether scope values should use URI-based naming for stronger uniqueness is under evaluation.)


O8. Category Trust and trustWeight PREVIEW

A recurring failure mode in service directories is treating a self-declared service category (for example "emergency-services" or "verified-merchant") as if it were attested. v0.4 separates the claim of a category from its attestation by splitting the single self-declared category field into four distinct category-trust claim objects and by replacing the v0.1/v0.3 interpretedAs: "hint-only" enum with a typed trustWeight field an evaluator can act on uniformly.

The trustWeight field. Any claim or category-trust object MAY carry a trustWeight field replacing the older interpretedAs: "hint-only" convention. trustWeight is one of: "hint" (self-asserted, unattested; evaluators MUST NOT grant trust-transitive or high-impact authority on a hint-weighted value alone — the typed successor to interpretedAs: "hint-only"); "attested" (backed by a Verifiable Credential or attestation from a named issuer; evaluators verify per the claim-proof process — EXT-T1 §T1.5 — before relying on it); "authoritative" (issued by an identity service provider or registry the evaluator treats as authoritative for the category by local policy). When trustWeight is absent, evaluators MUST default to "hint". Evaluators encountering the deprecated interpretedAs member (from v0.1/v0.3) MUST ignore it; in its absence trustWeight defaults to "hint", preserving the prior interpretedAs: "hint-only" semantics. The interpretedAs member is removed from the v0.4 vocabulary.

Category trust split. The single self-declared category is replaced by four distinct category-trust objects (claim-level objects carried in the claims array, distinguished by their @type; not top-level um:Facet objects), each carrying the common claim members of Base §1.4.3 plus trustWeight, plus the value-carrying members named here: operatorIdentity (the operating entity's identity, signed by an identity service provider — the operator's DID or URI is carried in the base claim subject member, with the attesting provider as issuer; no additional value member is needed; RECOMMENDED for any non-trivial service); serviceCategoryClaim (the self-declared category — a REQUIRED category member, a string naming the category, drawn from a registered category vocabulary where one exists (O6); always trustWeight: "hint" unless paired with a categoryAttestation); categoryAttestation (a Verifiable Credential attesting the category from a recognized authority — carrying the same REQUIRED category member, whose value MUST equal the paired serviceCategoryClaim's category for the pairing to hold; REQUIRED for high-impact categories — defined at the profile level, e.g. emergency, medical, financial, child-directed); urgencyClaim (any urgency/priority assertion — a REQUIRED urgency member, a string token with candidate registry values routine, elevated, emergency (extensible via O6), carried as a separate signed claim so urgency cannot be smuggled in via the category field). Normative rules: an evaluator MUST NOT act on a serviceCategoryClaim for a high-impact category without a verified categoryAttestation (high-impact membership is determined from the category value against the profile-level list); MUST verify categoryAttestation credentials for revocation per O2; and MUST treat operatorIdentity and serviceCategoryClaim as independent. The high-impact category list is profile-level, not fixed by this specification, consistent with eIDAS 2.0 [eIDAS2] assurance-level practice.

Preview: The trustWeight field and the four-way category-trust split are built on the editors' default (adopt trustWeight in v0.4). trustWeight is a small but forward-compatibility-critical wire-shape change; doing it before the wire is fielded avoids a v0.5 break. Input is requested on the high-impact category list and on whether trustWeight should be a closed enum or an extensible vocabulary.


O9. Extended Structural Schemas PREVIEW

The Base names three structural-state extensions as reserved members (Base §1.4.4, §1.4.6, §1.4.7); this part specifies them.

O9.2. Two-Component devices Schema

The devices array (Base §1.4.6) registers hardware endpoints (XR headsets, NFC readers, smart displays, wearable sensors) associated with the subject. v0.3 reserved this member; v0.4 defines device entries as a two-component split mirroring the layered device-attestation models of FIDO, TPM 2.0, WebAuthn [WEBAUTHN] (Level 2 as the normative anchor, with Level 3 refinements in progress), Android Hardware Attestation, and Apple DeviceCheck: a long-lived hardware provenance component and a session-scoped capability component. Separating them lets a session-only manifest advertise device capabilities without leaking a long-lived hardware identifier. Each entry is a device object that MAY carry a deviceAttestation, a deviceCapability, or both; it MUST include a @type of "um:Device" and an @id. The deviceAttestation and deviceCapability sub-objects are device components, not um:Facet objects.

deviceAttestation (long-lived, manufacturer-signed). When present it MUST contain deviceClass (a string, e.g. "xr-headset", "nfc-reader", "wearable-sensor"), modelHash (a hash identifying the model/firmware baseline, suitable for matching against a manufacturer registry without revealing a per-unit serial), and attestation (a Verifiable Credential or platform attestation object signed by the manufacturer or attestation authority — e.g. a WebAuthn/FIDO device attestation or a TPM 2.0 [TPM2] quote; evaluators MUST verify it against a configurable manufacturer trust anchor before relying on the device's hardware claims). It MAY carry manufacturer (DID/URI) and attestedAt (RFC 3339). Because hardware identifiers are long-lived and potentially correlatable, holders SHOULD omit deviceAttestation from session-only or pseudonymous manifests and carry only deviceCapability.

deviceCapability (session-scoped, user-signed). Describes what the device can do for the current session, signed by the subject (or a session-scoped key), not the manufacturer. When present it MAY contain sensors (sensor-class identifiers, e.g. "eye-tracking", "hand-tracking", "depth", "rgb-camera", using OpenXR sensor-class naming), openxrExtensions (OpenXR extension identifiers the device/runtime supports), positioningTier (e.g. "3dof", "6dof", "world-scale"), processingConstraints (compute/thermal/power limits an evaluator should respect), privacyModes (e.g. "on-device-only", "roi-derived-only"), and sessionSigningKey (a session-scoped ephemeral public key used to sign per-session device assertions; MUST NOT be a long-lived hardware identifier; generated per session to avoid cross-session linkage). Evaluators MUST NOT treat deviceCapability claims as hardware-attested unless a corresponding verified deviceAttestation is present on the same entry; absent such attestation, deviceCapability is a self-declared, session-scoped assertion (analogous to a hint-weight claim — O8).

The devices array is part of the signed payload: holders include it when signing, and evaluators MUST include it when recomputing the signing input and MUST NOT discard it before verification or during Arrive-stage unknown-field handling (it is a named structural member). Evaluators that do not implement the device components MUST preserve the array and record entries as present-but-unprocessed.

(Worked example: device entry with both components — see Cookbook.)

Preview: The two-component split is built on the editors' default (define in v0.4), because the wire shape is not yet fielded and this is the most consequential wire-shape decision in this version. Attestation transparency logs for device attestations are out of scope for v0.4 (flagged for v0.5). Input is requested on the sensor-class and OpenXR-extension vocabularies and on session-key generation requirements. Two member-precision decisions are reserved to the wire freeze so they are not lost: the modelHash computation rule (which bytes are hashed — e.g. a manufacturer-published model/firmware descriptor — and the matching procedure against a manufacturer registry) and the sessionSigningKey representation (JWK vs. multibase); until fixed, both are deployment-profiled.

O9.3. actorState Member

The actorState member (Base §1.4.7) is an OPTIONAL top-level object declaring who is operating the session the manifest is presented in: the human principal, a delegated agent, or a hybrid. It bridges the um:agentDelegation pointer (Base §6.5) — which declares that delegation exists — to the session-state semantics of who is currently acting. RECOMMENDED whenever an um:agentDelegation pointer is present.

When present, actorState MUST contain principal (the DID of the human or legal entity the manifest represents; MUST match the manifest subject; an evaluator finding actorState.principal not equal to subject MUST record this as a verification failure and MUST NOT rely on the manifest for delegated-authority decisions). When present, it MAY contain an executor object describing who is operating on the principal's behalf: type (one of "human", "agent", "hybrid"; MUST be present when executor is present); delegateId (the DID of the operating agent; REQUIRED when type is "agent" or "hybrid"); delegationRef (a reference to the um:agentDelegation pointer by @id that authorizes this executor; when present, evaluators MUST confirm the referenced pointer exists, is unexpired, and names delegateId as its delegate); lastVerifiedAt (RFC 3339 of the last interactive verification of the principal; meaningful only when type is "human" or "hybrid"; relates to the liveness model in EXT-T1 §T1.3). When executor is absent, evaluators MUST treat the session as principal-operated (type: "human" with no delegate). A "hybrid" executor MUST be treated as agent-operated by any gate that distinguishes human-operated from agent-operated sessions (for example a human-only-session requirement — Base §6.5.2): partial human participation does not satisfy a human-only gate (fail closed). actorState is additive and non-breaking; v0.3 manifests omit it, and evaluators that do not implement it record it as present-but-unprocessed.

(Worked example: actorState with an agent executor — see Cookbook.)

Preview: Built on the editors' default (add as OPTIONAL, RECOMMENDED with um:agentDelegation). It is a wire-shape addition. Input is requested on whether actorState should become REQUIRED when any delegation pointer is present.


O10. Cryptographic Requirements Summary PREVIEW

This consolidates the cryptographic requirements scattered across the signature profile (Base §1.6), encrypted facets (Base §2.4), the tiered trust model (Base §6.4.2), the ZKP profiles (EXT-T2 §T2.1), the ceremony model (EXT-T3), credential binding (EXT-T1), and post-quantum signatures (EXT-T2 §T2.3) into a single reference. This is a summary; the normative requirement for each algorithm lives in its referenced section, so this table can be updated as profiles are added without editing those sections.

Requirement level Algorithms / cryptosuites Reference
Mandatory-to-implement Ed25519 over JCS-RFC8785 (Signature Profile A); SD-JWT Key Binding (KB-JWT); JWK Thumbprint; ECDH-ES+A256KW / A256GCM for encrypted facets Base §1.6, EXT-T1 §T1.1, Base §2.4
Recommended BBS+ signatures and BBS+ derived proofs (BLS12-381); WebAuthn device/liveness attestation (Level 2 normative anchor, Level 3 refinements in progress) EXT-T2 §T2.1, EXT-T1 §T1.3
Optional (Tier 2 profiles) Groth16 (HD-derivation proofs); BBS+ linked-secret equality proofs EXT-T2 §T2.1
Future FROST threshold Schnorr/Ed25519 [RFC9591]; threshold BBS+; ML-DSA / SLH-DSA / FN-DSA post-quantum signatures EXT-T3, EXT-T2 §T2.3

† Items marked "Optional (Tier 2 profiles)" are optional at the specification level but become mandatory within the named optional profile: Groth16 is REQUIRED for an implementation that supports Profile 2B. The mandatory-to-implement row is likewise scoped to the module that uses each algorithm: Ed25519 over JCS-RFC8785 is unconditional for every implementation; the JWE pair is mandatory for evaluators claiming encrypted-facet support; SD-JWT Key Binding and JWK Thumbprint are mandatory for implementations claiming credential-binding support.

Preview: Built on the editors' default (add as a reference summary). Input is requested on whether any "recommended" item (notably BBS+ for privacy-preserving Tier 2) should be elevated to mandatory-to-implement for v0.4.


O11. Optional-Feature Matrix (consolidated)

This consolidates Base §4.7 with the modules this companion introduces. An implementation that does not implement an optional module still conforms, provided it observes the mandatory baseline behavior for that module.

Feature Conformance Mandatory baseline when not implemented
Encrypted-facet decryption (Base §2.3) OPTIONAL Sealed-entry handling REQUIRED: record present-but-sealed; never infer content.
Revocation-aware verification (O2) RECOMMENDED Record revocationStatus: "unchecked"; do not grant revocation-gated trust.
Credential binding (EXT-T1) OPTIONAL (REQUIRED for Tier 1+) Record holderBindingStatus: "absent"; cap relied-upon claims at Tier 0.
Per-facet floors (requiredLiveness, requiredAssuranceClassEXT-T1 §T1.3.1 / §T1.3.3, PREVIEW) OPTIONAL (PREVIEW) A floor-bearing facet MUST be withheld (recorded assuranceInsufficient, or the unmet-liveness status), never processed — fail closed.
CBOR-LD encoding (O1.4) OPTIONAL Support JSON-LD reference encoding; reject unsupported encodings.
Transparency anchoring (O3.4) OPTIONAL Verify the manifest signature and proofs directly; do not require a transparency log.
Tier-2 cryptographic binding (EXT-T2) OPTIONAL Record "trustTierUnsupported" for Tier-2-required items; do not downgrade.
Tier-3 ceremony (EXT-T3) OPTIONAL Record "trustTierUnsupported" for Tier-3-required items; do not downgrade.
Bilateral session model (O4) OPTIONAL Manifest-level bilateral exchange (Base §6.4.6) still applies.
Federation (O5) OPTIONAL Single-endpoint statusRef resolution (O2) applies.
Current policy-state profile (O2.6, PREVIEW design-stage) OPTIONAL The bounded composition of Base §3.4.1 applies: TTL, statusRef, consent windows, fail-closed.
Represented-person consent profile (O12, PREVIEW design-stage) OPTIONAL Existing fail-closed rules apply: an unrecognized claim type is unprocessable above Tier 0 (Base §1.4.3); an unrecognized or unenforceable consent condition fails closed (Base §1.4.4).
Referral-route attribution profile (O13, PREVIEW design-stage) OPTIONAL An unrecognized pointer type is recorded but not acted on (Base §1.4.5); a consent conditioned on a route class the evaluator cannot verify fails closed (Base §1.4.4).
GeoPose primary pose value profile (O14, PREVIEW design-stage) OPTIONAL A GeoPose-bearing manifest still follows ordinary UM behavior: unknown claims/pointers are preserved but not acted on, unverified provenance caps trust, and missing or unverifiable pose data MUST NOT be invented.

O11.1. Conformance-Claim Contents (candidate template) PREVIEW

Design-stage. Requirements across this document set oblige a deployment to document choices in its conformance claim, but no claim format has been defined. This subsection names the candidate template so those obligations have a single landing place; the claim-document format itself is a registration-time deliverable (O6) and adds no manifest wire member.

A v0.4 conformance claim SHOULD be a published, structured document stating, at minimum:

  1. Identity and class — the implementation and version; the conformance class(es) claimed (evaluator, holder, bilateral participant, status endpoint — Base §4); the production rules supported (O1.2).
  2. Modules and PREVIEW features — which optional modules of the matrix above are implemented, and which PREVIEW features the claim includes (per the two-grade PREVIEW policy; design-stage profiles MUST NOT be claimed — Base §4.4).
  3. Documented deviations and policies — every choice the normative text requires a claim to document: a widened clock-skew tolerance (Base §3.1.2); resource-limit deviations (Base §6.3); purpose-vocabulary hierarchy use (Base §1.4.4); the sensor derivation-implication policy, where a less-derived grant is read as also authorizing more-derived variants (O9.1); and any stricter VP size limits (EXT-T1 §T1.5.1).
  4. Isolation claim — where per-facet isolation is claimed (Base §2.3.5), the declared isolated facet set (the named set, or the deployment rule identifying it); this is the carrier of the conformance-claim flag that section defines.
  5. Suite evidence — the conformance-suite results and the claimed level (Base §4.4).

O13. Signed Referral-Route Attribution and Route-Scoped Disclosure Profile PREVIEW

Candidate registered profile (um:profile:domain:referral-route-attribution, registration via O6). Design-stage: the members and value tokens below are candidates whose wire shape may change; they are not yet in the published schema.json/schema.jsonld or the conformance fixture suite, and per the Base conformance discipline (Base §4.4) they carry no conformance tests until the design is finalized.

O13.1. Scope Boundary

The route by which two parties reach each other — a directory listing, a bulletin, a matching agent, a referral — is today either an unverifiable browser artifact (Referer) or a captive record inside one platform. This profile makes route provenance a signed, portable, minimal evidence layer. The boundary is strict: Universal Manifest is not an advertising network, a marketplace, a payment rail, a pricing engine, a platform-fee enforcement system, or a tax/royalty-distribution authority, and this profile MUST NOT be implemented as one. UM's role ends at evidence, disclosure policy, and receipts: proving a route occurred, letting consent key off the route, and issuing a minimal attribution record that external payment, royalty, or commerce systems MAY honor — without UM moving funds or ranking anything. The browser Referer header MUST NOT be treated as an authoritative route signal.

O13.2. Route Actors and Role Classes

A route actor is the party that listed, matched, introduced, or forwarded the encounter. Candidate role-class registry values: directory, bulletin, utility, matching-agent, delegated-agent, affiliate, platform (extensible via O6). A route actor's authority to act in a role is itself an ordinary UM question: it can carry a claim with claimProof, be scoped by an agent delegation (Base §6.5, O7), and resolve currency via statusRef (O2) — so route authority is revocable and currency-checkable like any other governed state.

O13.3. Signed Route Evidence

Route evidence rides the existing pointers[] member as a candidate pointer type um:routeAttribution (which, like um:agentDelegation, replaces the base target requirement with its own fields — Base §1.4.5). Candidate members:

  • routeActor (REQUIRED) — DID (or service identifier) of the party that listed, matched, introduced, or forwarded the encounter.
  • roleClass (REQUIRED) — one registry value of O13.2.
  • routedAt (REQUIRED) — RFC 3339 timestamp of the route step.
  • audience (REQUIRED) — the destination party of the route step (DID or origin), the same audience-binding discipline as presentationProof (EXT-T1 §T1.2).
  • challenge (OPTIONAL; REQUIRED for interactive presentations) — the verifier-issued nonce of the presentation the route evidence accompanies (the same anti-replay model as presentationProof).
  • prevRouteRef (OPTIONAL) — the @id of the immediately preceding route-attribution entry in a multi-hop route.
  • routeProof (REQUIRED) — the route actor's proof object: proofType (candidate baseline "did-auth" — an Ed25519 signature by a route-actor key), OPTIONAL verificationMethod (a DID URL naming the signing key; when absent, resolution starts from routeActor), and proofValue (base64url, unpadded).

Signing input (candidate layout). routeProof.proofValue is computed over the UTF-8 bytes of the JCS canonicalization (the JSON Canonicalization Scheme already mandatory for Signature Profile A — Base §1.6.1) of the five-element array [subject, roleClass, routedAt, audience, challenge] — the routed manifest's subject string, then the entry's roleClass, routedAt, audience, and challenge values in that order, with challenge the empty string when absent. The routed subject is the manifest subject, not the manifest @id and not a signing-input hash: the route step binds the routed party, is typically minted before the presentation manifest exists, and cannot include that manifest's signing-input hash without circularity — pointers[] lies inside the signing input (Base §1.6.3), unlike the excluded presentationProof. Signing the role and timestamp alongside subject and audience prevents a proof issued in one role from being replayed as evidence of another role, destination, or time.

Key resolution. The proof verifies against a verification method of the route actor: resolve the routeActor DID document and confirm the signing key appears under the assertionMethod verification relationship — the same key-purpose discipline as the EXT-T1 §T1.5.3 table (route attestation is an assertion about the encounter, not an authentication of the actor to the evaluator). Where routeActor is not a DID, verification requires a deployment-pinned key for that service identifier; absent one, the step is unverifiable and is recorded as unverified.

Multi-hop routes. A multi-hop route is a chain of route-attribution entries, each step independently signed; the chain is evidentiary, not hash-linked — order is established by routedAt, with prevRouteRef as the explicit link where timestamps do not suffice (equal or unordered timestamps). An evaluator verifies the steps it needs and records unverifiable steps as unverified rather than inventing route trust; any one verified route entry whose roleClass matches a route-class:<value> condition satisfies that condition (O13.4) — additional unverified entries never defeat a verified match. An unrecognized um:routeAttribution pointer degrades safely under the existing rule: recorded as present, not acted on (Base §1.4.5).

O13.4. Route-Scoped Disclosure

The route someone arrives by can change what they are allowed to see — a public-directory arrival may justify less disclosure than a verified matching-agent introduction. This profile expresses that as consent conditions keyed by route class (candidate condition convention: route-class:<value>, e.g. route-class:verified-directory) on ordinary consent entries (Base §1.4.4). The evaluator matches verified route evidence (O13.3) against the condition; a consent conditioned on a route the evaluator cannot verify fails closed under the existing unrecognized/unenforceable-condition rule. Route-scoped disclosure is an instance of the bounded selective-minimum-disclosure profile (Base §3.1.3, §7.1): the route is part of what the target is allowed to see, never a reason to disclose more than the interaction needs.

O13.5. Attribution Receipts and the Privacy Boundary

When a verified route contributes to a governed action, the evaluator MAY record it with the candidate receipt event class route-attributed and reason codes um:reason:route:credit-recorded, um:reason:route:unverified, um:reason:route:ineligible, um:reason:route:overbroad, and um:reason:route:disclosure-denied (O3.2, O3.3). The proof-to-referrer receipt is the minimal attribution record a route actor receives: its own identity and role class, the session-scoped correlator (exchangeId — inside a bilateral session, the session's own; outside one, a fresh single-use correlator generated for the encounter under the same rules, at least 128 bits of entropy and no party identifiers (O4.1), so attribution receipts pair without requiring a session), the attribution outcome, and a timestamp. It MUST NOT carry the counterparty's identity, sealed fields, transaction contents, prices, or any private buyer data unless that data is independently consented under its own consent entry. A downstream payment, royalty, or commerce system MAY treat the receipt as evidence that a route contributed to an encounter — settlement, splitting, and pricing happen entirely outside UM. Receipt minimization and session-scoped receipt-signing guidance (Base §7, O3.1) apply so attribution records do not become long-lived cross-encounter correlators of the referred party.

O13.6. Honest Limits

The profile proves that a signed route step occurred and was accepted; it does not prove the route actor's marketing caused the encounter, does not prevent route actors from colluding off-manifest, does not rank or price routes, and does not give the referred party unlinkability across encounters (the bounded selective-minimum-disclosure non-claims of Base §7.1 apply; the higher-privacy tracks are EXT-T2).

O14. GeoPose Primary Pose Value Profile PREVIEW

Candidate registered profile (um:profile:domain:geopose-primary-pose, registration via O6). Design-stage: the class, members, and value tokens below are candidates whose wire shape may change; they are not yet in the published schema.json/schema.jsonld or the conformance fixture suite, and per the Base conformance discipline (Base §4.4) they carry no conformance tests until the design is finalized.

O14.1. Scope Boundary

When a Universal Manifest subject is a real-world object, a digital twin, a 3D asset, a scan, a dataset record, a scene element, a vehicle, a sensor observation, or another object whose primary spatial fact is position plus orientation, the primary pose value SHOULD be expressed as an OGC GeoPose 1.0 payload [OGC-GEOPOSE] or a pointer to one. The GeoPose value answers "where is this object, and how is it oriented, in a geographically anchored frame?" Universal Manifest answers "who asserted it, what evidence and policy govern it, what may be disclosed, and what did the evaluator do with it?"

This profile therefore does not redefine GeoPose. OGC GeoPose remains authoritative for the pose data object, its Basic-YPR, Basic-Quaternion, Advanced, Chain, Graph, Regular Time Series, Irregular Time Series, and Stream targets, and their JSON-schema conformance. Universal Manifest carries or references that value inside the UM envelope so signatures, claim proofs, consent, current-state resolution, selective minimum disclosure, asset binding, and receipts can govern use of the pose.

O14.2. Primary Pose Attachment

A manifest implementing this profile identifies the GeoPose value through one of two candidate attachment forms:

  • Inline primary-pose claim. A standard claims[] entry with candidate @type geopose.primary, whose subject is the manifest subject or a dataset-record URI, whose candidate poseValue member (REQUIRED for this claim type) carries exactly one OGC GeoPose JSON data object, and whose claimProof verifies the issuer or measuring system when the pose is relied upon above Tier 0. Because the claim rides the signed payload, the inline form is restricted to static GeoPose targets — Basic-YPR, Basic-Quaternion, Advanced, Chain, Graph, and recorded (complete, bounded) time-series targets: a Stream target has no fixed byte representation to sign, is incoherent inside a signed claim, and MUST NOT be carried inline; streams use the pointer form.
  • Primary-pose pointer. A standard pointers[] entry with candidate pointer type um:geoPosePrimary whose target URI resolves to an OGC GeoPose JSON data object or a signed container that includes one (any target form, including Stream). The pointer SHOULD carry a candidate digest member — a multihash over the exact GeoPose bytes the target resolves to (the multihash function MUST be SHA-256 for v0.4, the same discipline as O1.7 and assetBinding.digest, O12.4) — so the UM signature binds the manifest to the exact pose value, not just to a mutable location. A Stream target, having no fixed bytes, cannot be digest-bound; it remains a live reference whose currency is governed by O14.3.

For dataset use, each record that has its own pose SHOULD have its own record URI and its own primary-pose claim or pointer. A dataset-level manifest MAY also carry a collection-level GeoPose value only when it describes the dataset as a whole; it MUST NOT be treated as the pose of every member record unless the dataset profile states that rule explicitly.

O14.3. Provenance, Time, and Currency

A GeoPose value can be observed, computed, imported, or asserted. The manifest SHOULD state the issuer or measuring system in the ordinary claim issuer/proof path, SHOULD bind the value to capture/measurement provenance when available, and SHOULD record the timestamp or validity interval supplied by the GeoPose payload or the surrounding claim. When current pose is required for a governed action, the evaluator MUST compose the manifest TTL, statusRef, consent windows, the current policy-state profile (O2.6) where implemented, and any domain-specific freshness policy before relying on the pose.

If the GeoPose value governs a represented-person asset (O12), an agentic action, a route-scoped disclosure (O13), or another consent-gated use, the pose is just another governed datum: it is projected only when the viewer/verifier/system/use case is allowed or needs to see it, and the receipt records whether the pose was accepted, withheld, stale, unverifiable, or unprocessed.

O14.4. Honest Limits

This profile makes GeoPose a first-class primary pose value inside the Universal Manifest lifecycle. It does not certify that an OGC GeoPose payload is itself valid unless an OGC GeoPose validator or attester has done so; it does not convert between reference frames; it does not resolve ambiguity in external frame definitions; it does not make a stale pose current; it does not prove the pose corresponds to the depicted asset without separate binding/provenance evidence; and it does not authorize location disclosure without an applicable consent or policy basis. Missing, unverifiable, stale, or withheld GeoPose data MUST be recorded honestly and MUST NOT be inferred.


Appendix OA. Manifest Class Registry Snapshot PREVIEW

This appendix is informative. It snapshots the manifest classes (Base §1.0.1) currently surfaced by integration profiles, to illustrate the polymorphic-envelope model. It does not bind conformance; the authoritative, versioned registry is maintained as a standalone document under the profile registration mechanism (O6). Discriminating members are the members whose presence identifies the class.

Manifest class Discriminating members Purpose
Identity capsule claims[] with identity claim types; holderBinding Portable identity and credential presentation.
Consent record consents[] with um:Consent entries Records permission grants governing facet use.
Device-capability descriptor devices[] with deviceCapability Advertises session-scoped device capabilities.
Device-attestation record devices[] with deviceAttestation Conveys manufacturer-signed hardware provenance.
Receipt @type includes um:Receipt; seq/prevHash Signed, chainable evaluation/audit record.
Cross-DID binding claims[] with identity.crossDidBinding Asserts common control of multiple DIDs.
Agent-delegation capsule pointers[] with um:agentDelegation; actorState Declares delegated session authority and the operating actor.
Encrypted-facet carrier facets[] with encryptionProfile Carries sealed, recipient-scoped payloads.
Category/service descriptor claims[] with operatorIdentity / categoryAttestation types Describes a service with attested category trust.
Bilateral-session record @type um:BilateralSession; exchangeId Correlates a two-party manifest exchange.
Asset-bound consent capsule (candidate, O12) subject = asset URI; representation facet + represented-person consent entry Carries the consent state of the person represented inside a portable asset.
GeoPose-bearing asset or dataset record (candidate, O14) claims[] with geopose.primary or pointers[] with um:geoPosePrimary Carries or references an OGC GeoPose primary pose value for the subject or record.

The snapshot is illustrative and non-exhaustive; integration profiles (e.g., the RP1 integration profile) surface additional classes. A manifest may belong to more than one class at once; the normative rule is in Base §1.0.1. The bilateral-session-record row anticipates a manifest that records a session: the session object of O4.1 is a protocol-layer object, not itself a manifest, so a session-record manifest would carry the common envelope members with @type including both um:Manifest and um:BilateralSession; its class profile is a working-group deliverable.

References

Cited in this profile (full descriptors in the published artifact): [DID-CORE], [INFRA], [JSON-LD], [CBOR-LD], [RFC8949] (CBOR), [RFC3339], [RFC9162] (Certificate Transparency 2.0), [MULTIFORMATS], [VC-STATUS] (Bitstring Status List), [C2PA] (Content Provenance and Authenticity), [UM-RFC], [OGC-GEOPOSE], [eIDAS2], [OPENXR], [WEBAUTHN], [TPM2], [RFC9591] (FROST).


Companion to the Base specification. For worked examples, see the Cookbook.