Provenance & Operations
The first four pages authored a model and drove the issuer and verifier from it. This page covers what the model gives you operationally: the usage lineage recorded along the way, how governance flows from the catalog into the wire forms, how versioning and pinning behave in practice, and the boundaries that shape the public API surface.
Usage Lineage
Every derivation writes lineage. The issuer's design-from-channel call (Issuing) wrote role = ISSUE rows; the verifier's DCQL author call (Verifying) wrote role = REQUEST rows. Each row in semantic_attribute_usage carries the full path from the consumed traversal entry to the artifact:
| Column | Meaning / values |
|---|---|
role_ref | The role from the attribute set that provided this path (e.g. employee, employer). |
source_entity | The catalog entity where the traversal starts (e.g. Person, Organization). |
traversal_path | The path array that was consumed, as a serialised form. For a direct attribute this is a single-element path (e.g. ["email"]); for a relationship traversal this is the full path (e.g. ["residentialAddress","country"]). |
role | ISSUE (written by the issuer design-from-channel) or REQUEST (written by the DCQL author). |
artifact_kind | CREDENTIAL_DESIGN or DCQL_QUERY. |
artifact_id, artifact_version | The rendered artifact and the version it was captured at. |
channel_id, channel_version | The VC channel (L4) that was rendered. |
The path back to the profile and catalog runs through the channel_id reference on the row, so the lineage table stays compact while remaining fully traceable to the model behind each artifact.
For a relationship traversal, the row records the full traversal_path together with source_entity and role_ref, so a query by attribute path (including traversed paths) still reaches the row. For example, the path ["residentialAddress","country"] sourced from Person via the employee role appears as its own row, distinct from the direct ["country"] path on the Address entity, so by-attribute reasoning can distinguish direct from traversed usage.
The cross-role questions it answers
Because every row carries role_ref, source_entity, traversal_path, role, and the artifact identity, the platform can reason across both roles in ways that opaque per-service stores cannot:
| Question | How lineage answers it |
|---|---|
| Where do we issue a given traversal path? | All role = ISSUE rows where traversal_path matches and source_entity matches. |
| Where do verifiers request a given traversal path? | All role = REQUEST rows for the same path and source entity. |
| Which artifact and channel version consumed a path? | The artifact_id/artifact_version and channel_id/channel_version on every matching row. |
| Which roles and source entities contribute to a given artifact? | All rows for artifact_id = A, grouped by role_ref and source_entity. |
| Which artifacts touch a sensitive or special-category path? | Join rows on the catalog attribute's overlays.classification and other governance overlays. |
In the walkthrough, the Employee design and the multi-credential DCQL both touch email (via role_ref = employee, source_entity = Person, traversal_path = ["email"]). A by-path query for that row returns both the ISSUE-role design row and the REQUEST-role query row. The same applies to the traversed path ["residentialAddress","country"]: the issuer maps it to address.country in the SD-JWT and the verifier requests it in the DCQL, and both facts appear in lineage under the same traversal path. This cross-role reasoning over meaning, security classification, and provenance is the operational deliverable of the enterprise tier.
The provenance read APIs (by-path, by-artifact, by-channel) are part of the VDX platform layer. The EDK writes the semantic_attribute_usage rows on every derivation but does not expose a public REST read endpoint for them.
Governance Flow-Through
The catalog attribute is canonical, and its governance metadata flows down the tiers and into the wire forms without being retyped at each layer:
- Selective disclosure. The catalog attribute's
sdPolicyoverlay (ALWAYS,NEVER, orOPTIONAL-style) is what the VC channel'sclaimMappingsrecords as thedisclosurevalue, and what the issuer design uses to decide which claims are independently disclosable. The wallet can presentgiven_namewithout revealingemployment_statusbecause the policy was set at the catalog and flowed through. The verifier requests exactly the claims the DCQL names, derived from the same channel. - Data classification. The
overlays.classificationoverlay on the catalog attribute (itspiiflag andspecialCategorymarker) travels with the attribute through every derived artifact. An operator can audit which issued credentials and which verifier requests touch personal or special-category data by joining lineage rows against the catalog's attribute metadata. - Governance overlays. Retention, legal basis, and jurisdiction constraints are authored once in the catalog's
governanceblock and per-attribute governance overlays. They flow into every credential design and DCQL query derived from that catalog, rather than being re-specified on each artifact.
The point: governance is authored once at the catalog (L1) and is derived into every downstream artifact rather than retyped per artifact.
Versioning and Pinning in Practice
Each layer is versioned, and each layer pins the version of the layer below it. Resolution and lineage flow through the whole stack:
- A catalog (L1) is versioned; publishing a revised catalog increments the version.
- An attribute profile (L2) pins one catalog version per referenced catalog via
catalogRefs(each entry carriescatalogIdandcatalogVersion). The Acme Employee profile v1 pins catalog v1. - An attribute set (L3) pins the profile version it was authored against via
profileRef.profileVersion. - A VC channel (L4) pins the set version via
setRef.setVersion. The two channels in the walkthrough (Employee SD-JWT and Business Card mdoc) each pin set v1. - A rendered design or authored DCQL captures the VC channel id and version it derived from.
The practical effect: a VC channel authored against set v1 keeps rendering the v1 attribute shape even after the catalog and profile are revised to v2. To adopt v2, you re-author the channel against the new pin. This is what makes derivation deterministic and auditable across a changing model, and it is why issuer and verifier stay in agreement: both derive from the same pinned VC channels.
Because the verifier's DCQL is persisted in the versioned DCQL store and an auth request references a query_id, you can publish a new DCQL version and repoint verifiers to it on a planned cutover, without disturbing in-flight requests. See Verifier Bindings for per-verifier version pinning and scheduled activations.
How This Differs From Hand-Authored Flows
For contrast, the naive flow hand-authors both wire forms: a literal claims[] on the design and a literal credentials[] on the DCQL, each typed independently. The enterprise model inverts this:
- The semantic model drives the wire form; you do not type
claims[]on the design orcredentials[]on the DCQL. - Selective-disclosure policy, data classification, and governance flow from the catalog, not from hand-typed design fields.
- Issuer and verifier agree by construction, because both derive from the same VC channels.
- Usage lineage is recorded, so an operator can audit where any traversal path is issued or requested.
The free-form path still exists for callers that want a hand-written claim list with no model behind it; it is ungated and bypasses derivation and lineage. The layered path is the license-gated, governed default.
Operational Boundaries
Two boundaries are important when reading the walkthrough against a running deployment.
The license gate returns FORBIDDEN only when a license carries a non-empty feature set that omits semantic-attribute-binding. With no license features set, the unbounded default applies and every gated write passes. See the license gate.
Usage lineage is written by the EDK on every derivation. The public read surface for by-path, by-artifact, and by-channel queries is part of the VDX platform layer, so EDK library consumers should treat the lineage store as an internal persistence contract unless they expose their own admin surface.
The Full Sequence
Here is the complete call sequence the reader followed across the pages, in order:
- Operator token. The issuer's embedded authorization server issued an OIDC bearer JWT via auth-code and PKCE. The JWT carries the tenant identity; all subsequent calls pass it as the bearer credential.
- Catalog shell. A catalog shell was created with a name, owner party reference, and governance overlays (jurisdictions, data classification scheme, controller). Five entities were added: Person, Address, and Organization as predefined party types, then Employee as a specialization of Person and Employer as a specialization of Organization. Two relationships were added:
residentialAddressfrom Person to Address andemploymentfrom Employee to Employer. The catalog was published and resolved. - Attribute profile. A profile was created over the published catalog, binding the
employeerole to Person (specializing Employee) and theemployerrole to Organization (specializing Employer), selecting both relationships, and applying a narrow override (employee email made mandatory). The profile was published and resolved. - Branding. A shared credential branding overlay was created with layout, locales, logo, and color scheme. It was published and referenced by both VC channels.
- Attribute set. A set was created over the published profile, selecting nine traversal paths: six direct employee attributes (
given_name,family_name,employee_id,job_title,employment_status,email), two relationship traversals (residentialAddress.postal_codeandresidentialAddress.country), and one employer attribute (legal_name). An override narrowedemployment_statusto the active and suspended codes. The set was published and resolved. - Two VC channels. The Employee SD-JWT channel (
dc+sd-jwt, vcthttps://issuer.acme.example/employee) was created with eight claim mappings that map each set traversal path to a wire claim path, including the relationship traversal["residentialAddress","country"]mapped to["address","country"]. The Business Card mdoc channel (mso_mdoc, doctypeorg.acme.businesscard.1) was created with five claim mappings using namespace-qualified two-segment mdoc paths. Both channels reference the same set version and the same branding. - OID4VCI issuance channel. An issuance channel was created composing both VC channels by reference (no set reference on this artifact). It carries the
credentialConfigurationIdand offer configuration. - Two designs from channels. The issuer rendered each credential design by posting display overlays and an alias alongside a
channelRefpointing at each VC channel. The claims list, selective-disclosure values, credential-type identity, and ordering were all derived. Each call wrote ISSUE-role lineage rows for every consumed traversal path. - Credential offers. One offer was created per credential configuration (a wallet obtains one credential per offer), each returning its own
correlation_idandoffer_uri. An offer URI can be rendered as a QR code, a link, an NFC payload, or a deeplink. - DCQL preview and author. The verifier first previewed a two-credential DCQL from both VC channels (ungated, persists nothing). The verifier then authored and persisted the same query with a
queryId, writing REQUEST-role lineage rows. - Authorization request. The verifier created an auth request referencing the authored
query_id, returning acorrelation_idand anopenid4vp://request_uri. - Holder obtains and presents. The wallet obtained each credential from its own offer via the auth-code grant, then presented both against the two-credential DCQL in a single response (SD-JWT with KB-JWT holder binding; mdoc with DeviceAuth COSE_Sign1 over the OpenID4VP session transcript).
- Poll to verified. The verifier was polled until status reached
authorization_response_verified. The response carriedcredential_claimsfor both credentials, with SD-JWT claims as plain keys and mdoc disclosed elements under their namespace-qualified keys. - Lineage rows. Each design-from-channel render and the authored DCQL write
semantic_attribute_usagerows:ISSUE-role rows from the two designs andREQUEST-role rows from the DCQL, each carryingrole_ref,source_entity, andtraversal_path.
See the per-page sections for the full request and response details at each step.
Next Steps
- Overview: the use case and the mental model, from the top
- Modeling Your World: the world model, the layers, lineage, and license gate in depth
- Related: Credential Design, OpenID4VP Verifier Bindings