But the WebID profile builder (src/webid/profile.js:56-107) declares the CID vocabulary inline, with a comment explaining exactly why:
"CID v1 vocabulary is declared inline (rather than via an imported context URL) so JSS's JSON-LD → Turtle conneg layer can expand every term without fetching external contexts."
So the two CID-document builders make opposite context choices for the same vocabulary. /private/privkey.jsonld is a pod resource; when conneg'd to Turtle, the external cid/v1 URL is not fetched, so Multikey / controller / publicKeyMultibase / secretKeyMultibase do not expand — the bare-relative-IRI failure mode profile.js describes at lines 95-104. It is therefore not a valid Controlled Identifier document when read as Turtle, which the LWS 1.0 authentication suite requires (the resource MUST be a valid CID-1.0 document).
The LWS WD example uses the external form ["https://www.w3.org/ns/cid/v1"], but JSS's conneg layer deliberately does not fetch external contexts — which is precisely why profile.js inlines. provision.js should do the same.
Proposed fix: make buildOwnerKeyDocument declare the CID terms inline, matching profile.js, with two additions the public profile does not need: secretKeyMultibase, and a type → @type alias (since the doc uses type: "Multikey").
Note for the fix: confirm the canonical IRIs the terms should expand to (profile.js currently maps e.g. Multikey → https://www.w3.org/ns/cid/v1#Multikey; verify that matches what https://www.w3.org/ns/cid/v1 itself expands Multikey to, since CID/Data-Integrity historically use the https://w3id.org/security# namespace). If they differ, that is a separate profile.js correctness question worth resolving in the same pass.
Found while aligning the stack to the did:nostr Multikey/cid shape (cf. #568, nostrcg/did-nostr#90).
src/webid/profile.js sets CID = 'https://www.w3.org/ns/cid/v1#', so it expands them to cid/v1#Multikey etc. These differ, which means:
profile.js's "semantically equivalent to importing cid/v1" comment is inaccurate — its inline profiles expand Multikey / publicKeyMultibase to different IRIs than a real cid/v1 import, so canonical CID / Data-Integrity RDF tooling would not recognize them.
The fix here is therefore not "match profile.js" — that would propagate the divergence. An inline context must map the VM terms to the security# IRIs (i.e. the cid prefix for these terms is https://w3id.org/security#, with publicKeyMultibase/secretKeyMultibase scoped inside Multikey), which is what importing cid/v1 actually yields.
profile.js has the same divergence, so this likely wants resolving in both builders together.
Separately: whether cid/v1 mapping its own terms into the legacy security# namespace (vs cid/v1#) is the right design is a spec-level question, not jss's to decide unilaterally. Flagging so the fix is a deliberate choice rather than a copy of the existing inline context.
Pulling the full canonical mapping (not just Multikey) — the cid/v1 context scatters its term IRIs across three namespaces, none of them a cid namespace:
https://w3id.org/security#authenticationMethod (note: the IRI term differs from the JSON key)
service
https://www.w3.org/ns/did#service
src/webid/profile.js maps all of these via cid: https://www.w3.org/ns/cid/v1#, so every one is mis-mapped — there is no cid/v1# namespace for them. A naive cid → security# swap is also wrong (service is did#, authentication resolves to authenticationMethod).
Two correct fix shapes:
Bundle the published cid/v1 context in JSS's JSON-LD/conneg document loader, then every builder just references the external @context: "https://www.w3.org/ns/cid/v1" (the LWS/spec-blessed form) and conneg resolves it from the local copy. DRY, spec-aligned, no hand-rolled IRIs.
Reproduce the real cid/v1 mappings inline (security# + did#, with the scoped contexts inside Multikey/JsonWebKey) in profile.js and provision.js. Contained, but verbose and easy to get subtly wrong.
Recommend (1) if a context loader / cache already exists.
Activity
melvincarvalho commented on Jun 15, 2026
Resolved the IRI question flagged in the issue body, and it changes the fix.
The canonical https://www.w3.org/ns/cid/v1 context expands these terms into the https://w3id.org/security# namespace, not cid/v1#:
src/webid/profile.js sets CID = 'https://www.w3.org/ns/cid/v1#', so it expands them to cid/v1#Multikey etc. These differ, which means:
Separately: whether cid/v1 mapping its own terms into the legacy security# namespace (vs cid/v1#) is the right design is a spec-level question, not jss's to decide unilaterally. Flagging so the fix is a deliberate choice rather than a copy of the existing inline context.
melvincarvalho commented on Jun 15, 2026
Pulling the full canonical mapping (not just Multikey) — the cid/v1 context scatters its term IRIs across three namespaces, none of them a cid namespace:
src/webid/profile.js maps all of these via cid: https://www.w3.org/ns/cid/v1#, so every one is mis-mapped — there is no cid/v1# namespace for them. A naive cid → security# swap is also wrong (service is did#, authentication resolves to authenticationMethod).
Two correct fix shapes:
Recommend (1) if a context loader / cache already exists.