Skip to content

rdf/turtle: nested verificationMethod objects dropped from Turtle output #415

@melvincarvalho

Description

@melvincarvalho

Sibling of #389 (array-context) and #390 (@type: '@json'). Surfaced when checking whether test.solid.social's JSON-LD profile and its conneg-converted Turtle form match.

Symptom

When a JSON-LD profile contains a predicate whose values are inline objects (rather than flat IRI references), the conneg-emitted Turtle drops:

  1. The predicate triple connecting the subject to the inline objects
  2. The inline objects' own triples (their @id, @type, attributes)

The authentication predicate survives because it points at a flat IRI. The verificationMethod predicate disappears because its values are full inline-object descriptions.

Reproduction

The on-disk profile at test.solid.social/profile/card.jsonld contains:

{
  "@context": { "...": "...", "verificationMethod": { "@id": "cid:verificationMethod", "@container": "@set" }, "publicKeyMultibase": { "@id": "cid:publicKeyMultibase" }, ... },
  "@id": "https://test.solid.social/profile/card.jsonld#me",
  "verificationMethod": [{
    "id": ".../card.jsonld#nostr-key-1",
    "type": "Multikey",
    "controller": ".../card.jsonld#me",
    "publicKeyMultibase": "fe70102de7ec..."
  }],
  "authentication": [".../card.jsonld#nostr-key-1"]
}

Asking JSS for Turtle:

curl -H 'Accept: text/turtle' https://test.solid.social/profile/card.jsonld

returns (excerpt):

<https://test.solid.social/profile/card.jsonld#me> a foaf:Person, schema:Person;
    ...
    <https://www.w3.org/ns/cid/v1#controller> <.../card.jsonld#me>;
    <https://www.w3.org/ns/cid/v1#service> <.../card.jsonld#oidc>;
    <https://www.w3.org/ns/cid/v1#authentication> <.../card.jsonld#nostr-key-1>.
<https://test.solid.social/profile/card.jsonld#oidc> a <https://www.w3.org/ns/lws#OpenIdProvider>;
    <https://www.w3.org/ns/cid/v1#serviceEndpoint> <https://solid.social/>.

Note:

  • ❌ No cid:verificationMethod predicate on #me at all
  • ❌ No description of #nostr-key-1 (no a Multikey, no controller, no publicKeyMultibase)
  • cid:authentication <.../card.jsonld#nostr-key-1> survives (flat IRI)
  • cid:service <.../card.jsonld#oidc> survives, AND the #oidc resource IS described (because it's referenced as a flat IRI from the subject AND its description is at the top level of the doc, not nested inside service)

So the rule seems to be: predicates whose values are inline objects (vs. flat IRI references with the resource described at the document root) get dropped.

Why this matters

Likely root cause

src/rdf/turtle.js's emitter probably walks the JSON-LD object's top-level keys and emits a triple per predicate-value pair, but doesn't recursively descend into inline-object values to:

  1. Emit the predicate referencing the inline object's @id
  2. Recursively emit the inline object's own triples

Compare to how service works (and survives): the JSON-LD likely has service: [".../card.jsonld#oidc"] as a flat-IRI list AND a top-level #oidc block describing the service endpoint. Two parallel descriptions. The Multikey VM is only declared as an inline object inside verificationMethod — there's no top-level #nostr-key-1 block to fall back to.

Possible fixes

A. Hoist + flatten on serialize: when emitting Turtle, replace inline objects with flat IRI references AND emit a top-level resource block per inline object. This is the standard JSON-LD → flat-N-Quads transformation.

B. Recursive emission: walk inline-object values, emit them as anonymous (or named, if @id present) resource blocks alongside the parent.

C. Switch to a real JSON-LD library: jsonld.js (digitalbazaar) handles this correctly out of the box. JSS's deliberate choice to avoid remote-context fetches (#389) is preserved by passing a pre-resolved local context map.

(C) is the most robust but biggest change. (A) or (B) would unblock the immediate use case.

Acceptance test

After the fix, the Turtle conversion of the test profile must contain:

<.../card.jsonld#me>
    cid:verificationMethod <.../card.jsonld#nostr-key-1>;
    cid:authentication <.../card.jsonld#nostr-key-1>.

<.../card.jsonld#nostr-key-1>
    a cid:Multikey;
    cid:controller <.../card.jsonld#me>;
    cid:publicKeyMultibase "fe70102de7ec...".

(Whitespace + prefix-vs-IRI formatting may vary; the triple set must match.)

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions