Package: @uncefact/untp-test-suite v0.1.0 (monorepo uncefact/tests-untp @ d09f538, tag reference-implementation-v0.3.0)
Tier: 3 (RDF / graph validation, trust-chain & claim verification)
Severity: Tier 3 graph verification produces a false negative for every UNTP v0.7.0 credential, regardless of whether matching DCC/DIA credentials are supplied.
Summary
The Tier 3 N3 inference rules and the SPARQL queries in rdf-utils.ts are written
against the 0.6.x UNTP vocabulary namespaces and the 0.6.x data-model shape. When a
v0.7.0 credential is converted to RDF (via its unified context), its triples use the
new https://vocabulary.uncefact.org/untp/... namespace and the restructured 0.7.0 data
model. The query patterns therefore bind nothing, listAllProducts returns [], and the
verification test fails with:
Verifications
✖ should verify all product claims and issuer trust chains
Should find products to verify: expected [] not to be empty
RDF validity (the tag:rdf sub-tests) passes — the credentials convert to valid RDF;
only the inference/verification layer is incompatible.
Reproduction (minimal)
npx untp-test --tag tier3 --trust-did=did:web:example.org ./dpp-0.7.0.json
with any 0.7.0 DPP (unified context https://vocabulary.uncefact.org/untp/0.7.0/context/).
Observed: tag:rdf PASS, inference "succeeded", but listAllProducts → [] →
"expected [] not to be empty".
Root cause — namespace AND data-model drift, not just a prefix swap
src/untp-test/rdf-utils.ts (listAllProducts ~L36–66; second query ~L171–186;
getUnattestedIssuersForProduct ~L262+) and the N3 rules under untp-tests/inference
(*-infer-*.n3) use:
PREFIX dpp: <https://test.uncefact.org/vocabulary/untp/dpp/0/>
PREFIX untp: <https://test.uncefact.org/vocabulary/untp/core/0/>
...
?credential a dpp:DigitalProductPassport .
?credential vc:credentialSubject ?subject .
?subject untp:product ?product . # (A)
?product schemaorg:name ?productName .
?subject untp:conformityClaim ?claim . # (B)
?claim untp:assessmentCriteria ?criterion . # (C)
What a 0.7.0 DPP actually emits as N-quads (real Reeco example, abridged):
<.../dpp/{id}> <https://www.w3.org/2018/credentials#credentialSubject> <.../product/X> .
<.../product/X> a <https://vocabulary.uncefact.org/untp/Product> .
<.../product/X> <https://vocabulary.uncefact.org/untp/performanceClaim> <.../claim/Y> .
<.../claim/Y> <https://vocabulary.uncefact.org/untp/conformityTopic> <.../conformity-topic/Z> .
<.../claim/Y> <https://vocabulary.uncefact.org/untp/referenceCriteria> <.../scheme/W> .
Differences:
| Query assumption (0.6.x) |
0.7.0 reality |
ns https://test.uncefact.org/vocabulary/untp/{core,dpp}/0/ |
ns https://vocabulary.uncefact.org/untp/ |
(A) credentialSubject → untp:product → product node |
no intermediate predicate — credentialSubject is the untp:Product node |
(B) untp:conformityClaim |
untp:performanceClaim |
(C) untp:assessmentCriteria |
untp:referenceCriteria |
dpp:DigitalProductPassport |
untp:DigitalProductPassport (under the unified ns) |
untp:conformityTopic |
untp:conformityTopic (name kept, ns changed) |
So pattern (A) fails first (no untp:product triple), which alone empties the result set;
(B)/(C)/the namespaces compound it. vc:credentialSubject is the only pattern that still
holds.
Suggested fix (direction)
This needs the inference rules and the SPARQL re-modelled to 0.7.0, not just new
prefixes. Concretely:
-
Namespaces — introduce a 0.7.0 vocabulary prefix and use it across the N3 rules and
rdf-utils.ts:
- PREFIX dpp: <https://test.uncefact.org/vocabulary/untp/dpp/0/>
- PREFIX untp: <https://test.uncefact.org/vocabulary/untp/core/0/>
+ PREFIX untp: <https://vocabulary.uncefact.org/untp/>
and ?credential a dpp:DigitalProductPassport → ?credential a untp:DigitalProductPassport.
-
Flatten the product step — credentialSubject is the product in 0.7.0:
- ?credential vc:credentialSubject ?subject .
- ?subject untp:product ?product .
- ?product schemaorg:name ?productName .
+ ?credential vc:credentialSubject ?product .
+ ?product a untp:Product .
+ ?product schemaorg:name ?productName .
-
Rename predicates:
- ?subject untp:conformityClaim ?claim .
- ?claim untp:assessmentCriteria ?criterion .
+ ?product untp:performanceClaim ?claim .
+ ?claim untp:referenceCriteria ?criterion .
(keep untp:conformityTopic, now under the new ns). The DCC-side patterns
(dcc:assessment, dcc:assessedProduct, untp:conformance, …) need the same
0.7.0 review.
-
Given the 0.6.x ↔ 0.7.0 divergence, prefer version-aware rule/query sets (select by
the credential's UNTP version) over editing in place, so 0.6.x credentials keep working.
Not yet validated end-to-end against a full 0.7.0 trust graph (no DCC/DIA on hand). The
property/namespace mapping above is taken directly from the RDF expansion of real 0.7.0
DPPs; the DCC/DIA-side remap should be confirmed once 0.7.0 conformity/anchor samples are
available.
Implementer-side note (Reeco, 2026-06-11)
Verified independently against real UNTP v0.7.0 DPPs (issuer did:web:ia.reeco.eco): after
adding a Reeco extension @context as the third array element, the credentials pass Tier 1
(valid JSON-LD + W3C VC schema) and pass the official UNTP v0.7.0 schema (Tier 2 diagnostic,
via the suite's own createAjvInstance + validateJsonAgainstSchema). The only remaining
failures are strictly suite-side — this issue — i.e. they are not a property of the
credentials under test.
Package:
@uncefact/untp-test-suitev0.1.0 (monorepouncefact/tests-untp@d09f538, tagreference-implementation-v0.3.0)Tier: 3 (RDF / graph validation, trust-chain & claim verification)
Severity: Tier 3 graph verification produces a false negative for every UNTP v0.7.0 credential, regardless of whether matching DCC/DIA credentials are supplied.
Summary
The Tier 3 N3 inference rules and the SPARQL queries in
rdf-utils.tsare writtenagainst the 0.6.x UNTP vocabulary namespaces and the 0.6.x data-model shape. When a
v0.7.0 credential is converted to RDF (via its unified context), its triples use the
new
https://vocabulary.uncefact.org/untp/...namespace and the restructured 0.7.0 datamodel. The query patterns therefore bind nothing,
listAllProductsreturns[], and theverification test fails with:
RDF validity (the
tag:rdfsub-tests) passes — the credentials convert to valid RDF;only the inference/verification layer is incompatible.
Reproduction (minimal)
with any 0.7.0 DPP (unified context
https://vocabulary.uncefact.org/untp/0.7.0/context/).Observed:
tag:rdfPASS, inference "succeeded", butlistAllProducts→[]→"expected [] not to be empty".
Root cause — namespace AND data-model drift, not just a prefix swap
src/untp-test/rdf-utils.ts(listAllProducts~L36–66; second query ~L171–186;getUnattestedIssuersForProduct~L262+) and the N3 rules underuntp-tests/inference(
*-infer-*.n3) use:What a 0.7.0 DPP actually emits as N-quads (real Reeco example, abridged):
Differences:
https://test.uncefact.org/vocabulary/untp/{core,dpp}/0/https://vocabulary.uncefact.org/untp/credentialSubject→untp:product→ product nodecredentialSubjectis theuntp:Productnodeuntp:conformityClaimuntp:performanceClaimuntp:assessmentCriteriauntp:referenceCriteriadpp:DigitalProductPassportuntp:DigitalProductPassport(under the unified ns)untp:conformityTopicuntp:conformityTopic(name kept, ns changed)So pattern (A) fails first (no
untp:producttriple), which alone empties the result set;(B)/(C)/the namespaces compound it.
vc:credentialSubjectis the only pattern that stillholds.
Suggested fix (direction)
This needs the inference rules and the SPARQL re-modelled to 0.7.0, not just new
prefixes. Concretely:
Namespaces — introduce a 0.7.0 vocabulary prefix and use it across the N3 rules and
rdf-utils.ts:and
?credential a dpp:DigitalProductPassport→?credential a untp:DigitalProductPassport.Flatten the product step —
credentialSubjectis the product in 0.7.0:Rename predicates:
(keep
untp:conformityTopic, now under the new ns). The DCC-side patterns(
dcc:assessment,dcc:assessedProduct,untp:conformance, …) need the same0.7.0 review.
Given the 0.6.x ↔ 0.7.0 divergence, prefer version-aware rule/query sets (select by
the credential's UNTP version) over editing in place, so 0.6.x credentials keep working.
Implementer-side note (Reeco, 2026-06-11)
Verified independently against real UNTP v0.7.0 DPPs (issuer
did:web:ia.reeco.eco): afteradding a Reeco extension
@contextas the third array element, the credentials pass Tier 1(valid JSON-LD + W3C VC schema) and pass the official UNTP v0.7.0 schema (Tier 2 diagnostic,
via the suite's own
createAjvInstance+validateJsonAgainstSchema). The only remainingfailures are strictly suite-side — this issue — i.e. they are not a property of the
credentials under test.