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 data domain 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 data product that provided this path (e.g. employee, employer). |
source_entity | The data-domain object type where the traversal starts (e.g. Person, Organization). |
traversal_path | The path array that was consumed, as a serialised form. For a direct business term 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 object model and data domain 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 business-term 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 object type, so by-term 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 data-domain business term'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 data-domain business term is canonical, and its governance metadata flows down the tiers and into the wire forms without being retyped at each layer:
- Selective disclosure. The data-domain business term'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 data domain and flowed through. The verifier requests exactly the claims the DCQL names, derived from the same channel. - Data classification. The
overlays.classificationoverlay on the data-domain business term (itspiiflag andspecialCategorymarker) travels with the business term 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 data domain's business-term metadata. - Governance overlays. Retention, legal basis, and jurisdiction constraints are authored once in the data domain's
governanceblock and per-business-term governance overlays. They flow into every credential design and DCQL query derived from that data domain, rather than being re-specified on each artifact.
The point: governance is authored once at the data domain (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 data domain (L1) is versioned; publishing a revised data domain increments the version.
- An object model (L2) pins one data-domain version per referenced data domain via
domainRefs(each entry carriesdataDomainIdanddataDomainVersion). The Acme Employee object model v1 pins data domain v1. - A data product (L3) pins the object-model version it was authored against via
objectModelRef.objectModelVersion. - A VC channel (L4) pins the data-product version via the product-backed channel's wire field
setRef.dataProductVersion. The two channels in the walkthrough (Employee SD-JWT and Business Card mdoc) each pin data product 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 data product v1 keeps rendering the v1 business-term shape even after the data domain and object model 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 data domain, 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-modeling.v1. With no license features set, the unbounded default applies and every gated write passes. See Enterprise license.
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.
- Data-domain shell. A data-domain shell was created with a name, owner party reference, and governance overlays (jurisdictions, data classification scheme, controller). Five object types 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 relationship types were added:
residentialAddressfrom Person to Address andemploymentfrom Employee to Employer. The data domain was published and resolved. - Object model. An object model was created over the published data domain, 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 object model 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.
- Data product. A data product was created over the published object model, selecting nine traversal paths: six direct employee business terms (
given_name,family_name,employee_id,job_title,employment_status,email), two relationship traversals (residentialAddress.postal_codeandresidentialAddress.country), and one employer business term (legal_name). An override narrowedemployment_statusto the active and suspended codes. The data product 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 data-product 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 data-product version and the same branding. - OID4VCI issuance channel. An issuance channel was created composing both VC channels by reference. It has no data-product reference; it carries the
credentialConfigurationIdand offer configuration. - Two designs from channels. The issuer rendered each credential design by posting a
channelRef, alias, and hosting mode. 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 (license-gated, 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 through its configured grant, authorization code for the Employee credential and pre-authorized code for the Business Card, 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