Test: cross-implementation interop corpus (jsonld.js RDFC-1.0 goldens) - #40
Merged
Conversation
…dens) Compares this processor's RDF output against goldens generated by jsonld.js over realistic VC 2.0 / OBv3 documents — the safety net the W3C suite does not provide. The suite has no fixture where an embedded node @context defines a type-scoped context (the PR #38 bug shape), and internal round-trips cannot catch a consistently-wrong processor: both sides recompute the same wrong quads and only an external verifier sees the signature break. - 5 cases: minimal PR #38 shape, VC 2.0 credential, the incident VC-in-VP shape, OBv3 achievement, and VC 2.0 @context:null isolation. - Goldens are RDFC-1.0 canonical N-Quads (the bytes eddsa-rdfc-2022 signs), regenerated offline-deterministically via tests/Interop/regenerate.sh (pinned node container; vendored contexts only; jsonld.js safe mode on unless a case opts out with a note). - Comparison is dataset equality up to blank-node isomorphism (goldens use _:c14n0, we emit _:b0), with a quad-level diff on failure. - vc-context-null-isolation is a documented KNOWN deviation with xfail semantics: activateTypeScopedContexts() falls back to the document context, leaking a presentation-level type-scoped context into a credential isolated by @context:null (one extra fullName quad vs jsonld.js). The case starts failing the suite the moment the fallback is removed, so the entry cannot outlive the fix. Runs as part of the Unit testsuite (341 passed, 1 skipped). W3C suite unchanged (1287 passed, 15 xfail-skipped). Pint + PHPStan (max) clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
4 tasks
skydudie
added a commit
that referenced
this pull request
Aug 13, 2026
…ntext only (#41) ## Proposed changes **Problem** — the two spec deviations left in `Expansion::activateTypeScopedContexts()` after #38: 1. **`documentBase` fallback**: a type-scoped context defined only at the *document* level could still activate inside a node whose context had been reset. In the VC 2.0 `verifiableCredential` `@context: null` isolation shape, a presentation-level type-scoped context (`Individual`) leaked into the isolated embedded credential and emitted a quad no conformant processor derives: ``` + <did:example:subject-456> <https://vocab.example.org/credentials#fullName> "Jane Citizen" _:b0 . ``` (the exact diff vs jsonld.js from the `vc-context-null-isolation` interop case, which was listed as a known deviation in #40). Notably the `Individual` type quad itself was *not* emitted — the scoped context activated for a type that couldn't even expand to an IRI there. 2. **`findTypeDefRecursive()`**: the recursive walk through nested `@context` entries in the document context. Dead weight since #38 — its stated use case (a type like `DataIntegrityProof` defined inside an imported security context) is handled by property-scoped context activation, which has already made the type visible in the active context by the time the typed node is entered. **Fix** — per JSON-LD 1.1 exp. §5.5 step 11, the type resolves against the **active context** (the type-scoped snapshot) and nothing else. Both fallbacks removed; net −54/+? lines in `Expansion.php`. **Evidence the fallbacks were dead weight (beyond the fixed case)** - W3C suite unchanged: 1287 passed, 15 xfail-skipped — zero regressions across expand/compact/flatten/toRdf/fromRdf/frame. - Full unit suite: the only test that changed behavior was the interop xfail guard, which **flipped green the moment the fallback was removed** — exactly as designed in #40 — and is delisted here (`INTEROP_KNOWN_DEVIATIONS` is now empty). **Tests** - New expansion unit test pinning the isolation behavior (document-level type-scoped context must NOT activate after a property-scoped `@context: null` reset; the unexpandable type stays `"Thing"`, `label` drops). Expectations generated with jsonld.js 8.3.3; confirmed red against `main`'s `Expansion.php`. - `vc-context-null-isolation` interop case now passes for real: our canonical N-Quads for the VC 2.0 isolation shape are dataset-identical to jsonld.js. - Unit: 343 passed, 0 skipped (was 341 + 1 skip). Pint + PHPStan (max) clean. ## Jira ticket link - N/A ## Checklist - [x] New unit test red on `main`, green with the fix - [x] W3C conformance suite unchanged (verified in Linux container; CI covers it) - [x] Interop corpus fully green, known-deviations list emptied - [x] Pint + PHPStan pass ## Further comments - Behavior change is quad-*removing* for the isolation shape (quads that only this library emitted, never conformant verifiers). Standard VC/VP documents — where embedded credentials carry their own `@context`, as the VC 2.0 spec requires — are unaffected: the active-context lookup (#38) already resolves their types. Same caveat as #38 applies to any artifacts signed by pre-fix versions of this library over the (non-conformant) isolation shape. - Completes the follow-up plan from #40, which was merged specifically to guard this change.
4 tasks
skydudie
added a commit
that referenced
this pull request
Aug 13, 2026
## Proposed changes Prepares the repo for submission to the [W3C JSON-LD 1.1 implementation report](https://w3c.github.io/json-ld-api/reports/) (we'd be the first PHP implementation listed) and retires the development-phase framing from the README. **README rewrite** - Removed the scaffolding: placeholder badge comments ("wired up in PR 1.2 / Phase 6"), the `Scope (delivered)` checkbox tracker (its content is the conformance matrix), and the v0.42.0 comparison-methodology footnotes. - Restructured as: highlights → installation → usage → conformance → interoperability → development notes. New sections for the interop corpus (#40) and the implementation report. - Fixed the install instruction (`composer require accredifysg/php-json-ld:^1.0` → unconstrained; we're on 2.1.0). - Conformance matrix refreshed against the current W3C suite: fromRdf is now 50/54 (upstream added `#t0028`, which we pass), totals **1,287/1,302**. **W3C EARL implementation report** - `reports/php-json-ld-earl.ttl` — generated from the v2.1.0 W3C suite run: **1,275 assertions, 1,262 passed, 13 failed** (failures reported explicitly, unlike most submissions). `specVersion: json-ld-1.0` tests are excluded to match the consolidated report's JSON-LD 1.1 scope (same as prior submissions, e.g. w3c/json-ld-api#652). - `scripts/generate-earl-report.php` — regenerates the report from a `--log-junit` run of the W3C testsuite, so future releases refresh it with two commands (documented in the README). Verified: the report ingests into the W3C `earl-report` toolchain with zero warnings and renders as *PHP-JSON-LD / Accredify / PHP*. **Supporting changes** - `tests/w3c` submodule bumped to current upstream head, so `composer test:w3c` reproduces the README/report numbers exactly (previously pinned pre-`#t0028`: 1,286/1,301). - CHANGELOG: backfilled the missing **2.1.0** section (the tag was cut without one — it covers #38/#39/#40/#41) and recorded this PR's additions under Unreleased. ## Jira ticket link - N/A ## Checklist - [x] Unit suite green (346 passed, includes interop corpus) - [x] W3C suite green against the bumped submodule (1,287 passed / 15 xfail-skipped) - [x] Pint + PHPStan pass - [x] EARL report validates (rdflib) and ingests into the earl-report gem with zero warnings ## Further comments - Once this merges, the identical `.ttl` gets submitted as a PR to `w3c/json-ld-api` (branch already prepared), giving the submission a canonical in-repo artifact to reference.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes
Problem
@contextdefines a type carrying a scoped@context— verified by scanning every input fixture in the expand/toRdf/compact/flatten suites.Fix: a third safety net — pin the reference implementation's output
tests/Interop/: 5 realistic VC 2.0 / OBv3 documents whose RDF output is compared against goldens generated by jsonld.js 8.3.3 with RDFC-1.0 canonicalization — the exact quad set aneddsa-rdfc-2022proof is computed over.embedded-node-type-scoped-contextminimal-vc-v2vp-embedded-vc-scoped-claims@context, type-scopedIndividual/CorporateEntityclaims,@container:@graphblank-node graphsobv3-achievementvc-context-null-isolationverifiableCredential@context:nullisolation — known deviation, see belowDesign properties
./tests/Interop/regenerate.sh(pinned node container). jsonld.js safe mode stays on unless a case opts out viacase.jsonwith a mandatory note — so a fixture that silently drops terms cannot produce a golden by accident. Generator version + quad counts recorded infixtures/goldens.json._:c14n0, the processor emits_:b0), with a+/-quad diff on failure. Same approach as the W3C toRdf harness.Known deviation (guards the next fix)
vc-context-null-isolationdocuments a residual spec deviation, empirically confirmed by this corpus:Expansion::activateTypeScopedContexts()still falls back to the document-level context, so a presentation-level type-scoped context leaks into a credential isolated by the VC 2.0@context:nullreset — one extrafullNamequad vs jsonld.js (which drops the undefined term, per spec).KnownBlockers: skipped while it diverges, fails the suite the moment it matches, so removing thedocumentBasefallback (planned follow-up) must also delist it.Tests
Unittestsuite (no CI changes): 341 passed, 1 skipped (the documented deviation).Jira ticket link
Checklist
Further comments
tests/W3cvstests/w3ccollide); verified in a Linux container — CI covers it as usual.example-individual-v1.jsonldis an invented context modelling the incident's credential shape.documentBasefallback +findTypeDefRecursive()fromactivateTypeScopedContexts(); this corpus (specificallyvc-context-null-isolation) is the regression guard for that change.