Skip to content

Preload Lemmy's JSON-LD context (https://join-lemmy.org/context.json) in @fedify/vocab-runtime #714

@dahlia

Description

@dahlia

Background

@fedify/vocab-runtime ships a handful of JSON-LD contexts as preloaded documents so the default document loader can resolve them without a network round-trip. The current set in packages/vocab-runtime/src/contexts.ts includes ActivityStreams, the w3id.org/security/* family, DID v1, WebFinger, schema.org, GoToSocial, FEP-5711, and http://joinmastodon.org/ns. The joinmastodon entry in particular was added in #631 specifically because the URL never served a real JSON-LD document; Mastodon has always inlined the term definitions, and some ActivityPub implementations (Bonfire was the reported case) still put the bare URL in @context, causing downstream JSON-LD processors to fail with 404 Not Found.

The gap

Every Lemmy-originated activity references https://join-lemmy.org/context.json in its @context array. That URL does serve a document, unlike the joinmastodon case, but join-lemmy.org returns it as Content-Type: application/json without the Link: <...>; rel="http://www.w3.org/ns/json-ld#context" header that @fedify/vocab-runtime's default loader treats as a non-JSON-LD response. The loader rejects the document, so every Lemmy activity (including the inbound Follow that kicks off a subscription) fails to parse before the application's handlers ever run.

Applications that want to interoperate with Lemmy, Mbin, or any other software that uses this context therefore end up writing the same workaround: copy the context file into their own repo, then pass a custom documentLoaderFactory that short-circuits the URL to the bundled copy. The threadiverse tutorial currently in review as #710 spends an entire sub-section, Bundle Lemmy's JSON-LD context, walking readers through about 40 lines of boilerplate to do exactly that. Every non-trivial Lemmy-interoperable Fedify app needs to duplicate it today.

Proposal

Add https://join-lemmy.org/context.json to preloadedContexts, in the same shape as the joinmastodon entry:

  1. Save the current document body at packages/vocab-runtime/src/contexts/join-lemmy.json. The published file is 33 lines at time of writing; it only extends ActivityStreams and w3id.org/security/v1 with Lemmy-specific terms (postingRestrictedToMods, moderators, matrixUserId, and friends) plus a few common co-fediverse extensions (toot:, litepub:, pt:). It does not redefine as: or the bare Public term.
  2. Register it in packages/vocab-runtime/src/contexts.ts under the key https://join-lemmy.org/context.json, with a comment explaining why we preload it (mirror the joinmastodon comment's shape).
  3. Add a CHANGES.md entry under the unreleased @fedify/vocab-runtime section, styled the same as the joinmastodon entry in the 1.3.0 section.

Why this matters now

The threadiverse tutorial is the first piece of Fedify documentation that explicitly walks readers through writing their own document loader. It works, but it's a spike in complexity right in the middle of the Lemmy-compatibility chapter, and the underlying reason ("join-lemmy.org's content-type is wrong") is uninteresting noise for the reader. Preloading the context upstream turns the chapter into a single-line callout ("Lemmy's activities parse without any extra configuration").

Follow-up in the threadiverse tutorial and example

Once this lands, #710 can drop the workaround before it merges:

  • Remove the Bundle Lemmy's JSON-LD context sub-section from docs/tutorial/threadiverse.md under the Making the community actor Lemmy-compatible chapter.
  • Remove federation/lemmy-context.json and the BUNDLED_CONTEXTS/documentLoaderFactory block from federation/index.ts in the paired fedify-dev/threadiverse example.

Both are straightforward deletions; they can be a top-up commit on #710's branch.

Out of scope

  • Tracking upstream changes to the Lemmy context document. If join-lemmy.org ever updates the file, we refresh the bundled copy the same way the GoToSocial context was updated in 1.3.2 (see the CHANGES entry in that section).
  • Adding bundled contexts for other threadiverse implementations (Mbin, Piefed, NodeBB). If they serve their own @context URLs with the same problem, each one can be its own follow-up.

Acceptance criteria

  • packages/vocab-runtime/src/contexts/join-lemmy.json added and committed.
  • https://join-lemmy.org/context.json entry present in the preloadedContexts map with an explanatory comment.
  • CHANGES.md entry added under the unreleased @fedify/vocab-runtime section.
  • The existing preloaded contexts test in packages/vocab-runtime/src/docloader.test.ts still passes (and the new entry is exercised by it).
  • Manual spot-check: a Fedify-powered app receives a raw Lemmy activity and parses it successfully with nothing more than the default document loader.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions