Skip to main content
Version: v0.25.0 (Latest)

Modeling Your World

The overview introduced the four layers (L1 catalog, L2 profile, L3 set, L4 channel). This page explains how the model describes an organization's world, how governance flows through every layer, and how wire forms are derived from it. The model is the authoritative source that drives wire forms; the issuer design and the verifier DCQL are both derived from it, not authored beside it.

Four-layer semantic model: L1 catalog declares entities (PREDEFINED and SPECIALIZATION) and first-class relationships; L2 profile binds catalog entities to use-case roles and selects relationships; L3 set is a role-scoped traversal subselection of one profile; L4 channels are the set-bound artifacts that issuer designs and verifier DCQL both derive from.

Modeling Your World

Before any credential is designed, the catalog lets an organization describe its world: the kinds of party it deals with, the attributes those parties carry, and the relationships between them. Everything downstream derives from this, so it is worth modeling deliberately rather than per credential.

The catalog is bound to a Party. Every catalog is owned by a Party through ownerPartyRef. In most organizations that owner is the tenant or the organization itself, though it can just as well be a local subsidiary that keeps its own catalog. Whoever owns it, a catalog is typically used as the organization's single source of truth for its world: one governed place where the meaning, classification, and structure of every attribute is defined once and reused everywhere.

Entities are party types. Each entity in the catalog is a kind of party. The platform ships a rich set of built-in party types, including natural_person, organization, address, and group, alongside platform roles such as identity, credential_template, resource, and user; the partyType token is extensible for anything else your world needs. A PREDEFINED entity names one of these party types and is modelled up front as first-class data.

Specializations are use-case subtypes you do not model up front. In a given use case a natural person may be an employee, a student, or a customer; an organization may be an employer or a supplier. These are SPECIALIZATION entities: each extends a predefined entity with extra attributes for the use case, without the platform having to predefine "student" or "customer" as their own party types. A specialization inherits the attributes of what it specializes and adds its own.

Relationships connect entities. Relationships are first-class: a Person has an Address, an Employee is employed by an Employer. Each relationship has a type and two ends, and each end carries its own cardinality, so the model captures how many addresses a person may have and that the address in that relationship belongs to exactly one resident.

The Four Layers

The model is structured into four layers that build on each other: the Catalog (L1) defines the canonical party types, attributes, and relationships; the Attribute Profile (L2) assembles catalog entities into named use-case roles; the Attribute Set (L3) is a role-scoped traversal subselection of one profile; and Channels (L4) are the set-bound artifacts that both the issuer design and the verifier DCQL derive from. Each layer is versioned and uses the same DRAFT | PUBLISHED lifecycle.

Governance flow from L1 catalog through L2 profile to L3 set and L4 channel: jurisdiction, classification, and sdPolicy values set at the catalog entity flow through role bindings and role-scoped traversal selections, narrowing at each layer but never widening, reaching the wire form with full provenance.

Governance overlays flow through every layer. The four governance overlays on an attribute (classification, processing, residency, assurance) are authored once on the catalog attribute and flow down every layer into the wire form, never retyped per credential. They are grounded in W3C DPV, GDPR, NIST FIPS 199, ISO 27001, and eIDAS2. Personal-data classification is overlays.classification.pii (with specialCategory for Article 9 data); like all governance, it lives in the overlays bag. Each layer may narrow what the layer above admits but never widen it.

What the governance overlays drive

Rendering a set to different output formats is only half of what the rich model does. The governance overlays on each attribute are operational, not decorative: they determine how the platform protects, uses, keeps, and erases the data, and they travel with the value wherever it flows.

  • classification sets the protection posture. The pii flag and specialCategory marker, the ISO 27001 label, and the NIST FIPS 199 impact triad decide how strictly a value is guarded, masked, and access-controlled, and which attributes count as personal or special-category data for audit.
  • processing governs lawful use and lifecycle. Each purpose carries its GDPR Article 6 legal basis and its own retention rule, so the model knows why a value may be used and, through the retention duration, trigger, and action, when it must be cleaned up or erased.
  • residency governs where a value may live: the allowed and denied regions, whether it must stay in-region, and the Chapter V transfer mechanism for any permitted cross-border movement.
  • assurance governs the trust level: the eIDAS level of assurance, the attestation type, and the authentic source the value is asserted against.

Because these travel with the attribute down every layer, the same protection, retention, residency, and assurance rules apply consistently to a form, a PDF, an API payload, and a credential, without being restated per artifact. The model is not just a rendering source; it is where data-handling policy is declared once and enforced everywhere the attribute appears.

How the Wire Forms Are Derived

Wire forms are derivations from VC channels, not a separate authoring tier.

Issuer credential design = a VC channel + issuance-only overlays the channel does not carry (displays, optional alias, hostingMode). Created at POST /api/v1/designs/credentials/fromchannel with channelRef: { channelId, channelVersion }. The claim list, selective-disclosure posture, ordering, and credential-type identity are all derived from the VC channel and its set, profile, and catalog chain. No claims[] or bindings[] are authored on the design itself. Each consumed traversal path writes one ISSUE-role lineage row. See Issuing.

Verifier DCQL query = one or more VC channels. DCQL spans multiple credentials, one credential query per channel, so a single DCQL can request both the Employee SD-JWT and the Business Card mdoc simultaneously. Created at POST /api/v1/oid4vp/dcql/authored with channelRefs: [ { channelId, channelVersion } ]. Each consumed traversal path writes one REQUEST-role lineage row. See Verifying.

The through-line from semantic model to wire form: a set traversal entry { roleRef: "employee", path: ["residentialAddress", "country"] } maps in the SD-JWT VC channel to claimPath: ["address", "country"], surfaces as a selectively-disclosable verified claim in the issued credential, and is recorded in lineage with its traversal_path value. The verifier's DCQL query carries the same claimPath, so issuer and verifier agree on field identity without any out-of-band coordination.

Provenance chain of the set-bound VC channel: a credential design or DCQL query derives from a VC channel, which pins an attribute set (L3) via setRef, which pins an attribute profile (L2) via profileRef, which pins a semantic catalog (L1) via catalogRefs. Lineage rows carry role_ref, source_entity, and traversal_path, recording which role (ISSUE or REQUEST) consumed which path through which entity chain.

Override and Version-Pinning Precedence

When a value is resolved for a wire form, these layers apply in order. Each layer narrows what the layer above admits; no layer widens it:

  1. Catalog entity attribute (L1) is canonical: valueType, overlays.i18n labels, sdPolicy, governance metadata.
  2. Profile override (L2) is the profile's narrow-only effective value for the override allow-list (conformance, sdPolicy, entryCodesSubset, sensitive, ...). The profile also pins the catalog version via catalogRefs. Anything outside the allow-list reads through to the catalog.
  3. Set override (L3) tightens further per selected (role, path) entry (conformance, cardinality, entryCodesSubset, sensitive). The set pins the profile version via profileRef.
  4. VC channel is selection and mapping only (which traversal entries, which claimPath, which disclosure value). It does not override governance.
  5. Issuer design overlay is issuance-only (displays, alias, hostingMode).

Each layer's version pin is what keeps derivation deterministic: a channel authored against set v2 keeps rendering the v2 shape even after the set is revised to v3.

Usage Lineage

Every render that consumes a traversal path records a usage-lineage row. One row has this shape:

ColumnMeaning / values
role_refThe role that contributed the path (e.g. employee, employer).
source_entityThe entity the path originates from (e.g. Person, Employee).
traversal_pathThe full traversal path as consumed from the set (e.g. ["residentialAddress","country"]).
roleISSUE (written by a design-from-channel render) or REQUEST (written by a DCQL author call).
artifact_kindCREDENTIAL_DESIGN or DCQL_QUERY.
artifact_id, artifact_versionThe rendered artifact and the version it was captured at.
channel_id, channel_versionThe VC channel the render derived from.

The lineage row carries enough identity in role_ref, source_entity, traversal_path, and the channel reference to answer cross-role questions directly, and the path back to the profile and catalog runs through that channel reference.

The issuer's design-from-channel render writes role = ISSUE rows; the verifier's DCQL author call writes role = REQUEST rows. For relationship-traversal paths, the row captures the full traversal, so ["residentialAddress","country"] is one traceable entry.

Because the rows carry the channel identity, the role, and the traversal path together, the platform can answer questions the opaque per-service stores cannot:

  • Which credentials issue, and which verifier requests touch, a given attribute or traversal path?
  • Under which VC channel and at which versions?
  • Which source_entity contributes a given traversal path, and does any verifier request it?

That cross-role reasoning over meaning, classification, and provenance is the deliverable of the enterprise tier. See Provenance & Operations.

The License Gate

Every WRITE in the enterprise tier is gated behind a single license feature, semantic-attribute-binding:

  • Gated: catalog, profile, set, branding, and channel authoring; the issuer design-from-channel render; the verifier DCQL authored call.
  • Never gated: reads (get, list, resolve) and the DCQL preview derivation, which derives a query but persists nothing and records no lineage.
  • Never gated: the free-form / lite channel path in the IDK.

The gate is fail-open by design. Behaviour depends on the deployment's license:

License featuresBehaviour
empty set (unbounded default)no gating applies; every gated write passes
non-empty, contains semantic-attribute-bindinggated writes pass
non-empty, missing semantic-attribute-bindinggated writes return FORBIDDEN

With no license features set (the unbounded default), no gating applies and the FORBIDDEN response does not occur. In VDX, semantic-binding REST operations declare their operation-level license metadata with x-license-protection, and the service command contracts expose matching licenseProtection descriptors. This makes the OpenAPI reference, command registry, and runtime license checks use the same entitlement keys.

See Provenance & Operations.

Pagination

Every list endpoint under /api/attributes/v1/{catalogs,profiles,sets,channels,branding} is paginated and filterable uniformly. A list call accepts these query parameters:

ParameterMeaning
limitPage size, clamped to [1, 100], default 20.
offsetNumber of items to skip.
pageZero-based page index (alternative to offset).
sizePage size (alias of limit).
sortField to sort by, default createdAt.
sortDirectionASC or DESC, default DESC.
per-entity filtersnameContains (case-insensitive substring), status on catalogs/profiles/sets/branding, and channel / setId on channels.

Every list response uses the same paginated envelope:

{
"data": [ /* the page of entities (never a bare top-level array) */ ],
"pagination": {
"limit": 20,
"offset": 0,
"page": 0,
"size": 20,
"total": 7,
"totalPages": 1,
"hasMore": false
}
}

Read the page from .data (always an array, never the top-level object) and the counts from .pagination. The channel list returns .data as an array of ChannelEnvelope items; read .data[].channel for each concrete channel. See Channels for paged list, filter, and sort parameters in action.

Next Steps

  • Catalog (L1): define your catalog shell, add entities and relationships, and publish
  • Issuing: render issuer designs from the VC channels and create the offer
  • Verifying: author the multi-credential DCQL and verify a presentation