FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Track: LWS protocol conformance (Oct 2026 drafts) — core vs plugin split, Touchstone as acceptance test · Issue #621 · JavaScriptSolidServer/JavaScriptSolidServer · GitHub

Repository navigation

Track: LWS protocol conformance (Oct 2026 drafts) — core vs plugin split, Touchstone as acceptance test #621

Open

Description

Status (14 Oct 2026): the LWS implementation lives in linkedwebstorage/lwsd — a JSS plugin — and it passes 196 of 203 Touchstone tests (0 failed, 7 inapplicable: 3 SAML, 4 optional preconditions). Conformant. Per-module results: lwsd README → Touchstone. Landed in lwsd#10. What remains on this issue is the host-pod side (#622, #624/#604, #615, #625); #628 (QUERY in the host) is WONTFIX.

Umbrella tracker for implementing the W3C Linked Web Storage (LWS) protocol in JSS against the current editor's drafts — core WD of 5 Oct 2026, CID auth WD of 21 Sep 2026 — with Touchstone as the acceptance test.

Supersedes #87 (--lws-mode, written against the Jan 2026 draft) and #89 (minimal LWS server — the ecosystem now has reference servers). Continues the auth work from #319 / #386.

Where JSS stands

JSS covers the authentication suite reasonably well — CID v1 profiles, a self-signed LWS-CID JWT verifier (src/auth/lws-cid.js, docs/lws.md) — but implements none of the core protocol surface: no storage description, lws+json containers, pagination, linksets, merge-patch, Depth, problem+json, authorization server / token exchange, access grants or webhooks.

Two things have changed since our trackers were written:

  1. The auth model moved. The April FPWD let the self-signed CID JWT be the Bearer credential, which is what lws-cid.js does. The current draft has the client present a subject token (CID / did:key / OIDC) to the storage's authorization server, which exchanges it (RFC 8693) for an at+jwt; resources only ever see the at+jwt. Our verifier is now the legacy shape.
  2. There are now two complete reference points to measure against (below).

Reference implementations

Jesse Wright — CSS

  • jeswr/LinkedWebStorage — @solid/community-server-lws, a Components.js plugin for CSS v8. LWS alone or Solid+LWS dual mode, WAC or ACP. Touchstone core 116/116, webhook 11/11, auth 23/23.
  • Review PRs in his fork: jeswr/CommunitySolidServer#124 (v7) and #126 (v8). The PR body is the best single description of what a full implementation needs, including the ambiguity choices (storage URI = root container, */* behaviour in dual mode, Bearer-with-webid-claim → Solid-OIDC, public storage description, grants only add to WAC/ACP).
  • Core hooks he needed upstream, all small: CSS #2267 (conditions on description resources), #2268 (identifiers on default handlers so they can be extended), #2269 (ETags for .meta), #2270 (412 instead of 304 on failed If-Match for GET/HEAD).
  • jeswr/lws-solid-diff — spec-level diff Solid Protocol vs LWS 1.0.

Erich Bremer — Touchstone and friends

  • ebremer/touchstone — conformance harness. 101 YAML-LD tests, 296-requirement catalog covering core, all three auth suites, webhooks, type index and search. Ships as a Docker image and a GitHub Action (ebremer/touchstone/.github/actions/lws-conformance@master); EARL/HTML/JUnit reports.
  • ebremer/lws-server — Java reference server (Jakarta servlets).
  • ebremer/lws-client — clients in 11 languages including JS; useful for interop tests.
  • ebremer/lws-authn — Keycloak extension, all four auth suites.
  • ebremer/lws-fuse, ebremer/lws-drupal.

Core vs plugin split

The JSS plugin seam (src/plugins.js, #206) is route-prefix based, so the split falls out naturally: the parts that touch every LDP response go in core; the parts that are their own services go in a plugin (jss-plugin-lws), given four small new seams that are useful to other plugins regardless.

Core (small, mostly spec-independent) Plugin — works with today's API Plugin — needs a new seam
412 on failed If-Match / If-Unmodified-Since for GET/HEAD (cf. CSS #2270) Authorization server: /.well-known/lws-configuration, RFC 8693 token exchange, JWKS, at+jwt issuance api.auth.registerVerifier() — so pod resources accept the plugin's at+jwt
ETags on .meta / description resources (cf. CSS #2269) /.notifications/lws/ subscription routes, RFC 9421-signed webhook delivery api.events.on('change') — resource change feed for webhooks
Link rel="https://www.w3.org/ns/lws#storage", up, type, linkset on responses Access request / grant documents under .lws/requests/ and .lws/grants/ api.wac.registerReader() — grants add permissions to WAC
application/lws+cid storage description on pod root did:key subject tokens (#86) api.headers.link() / root onSend — add link relations on every response
application/lws+json containers + ?page=N pagination application/problem+json on its own routes
.meta as RFC 9264 linkset + JSON Merge Patch (RFC 7386)
DELETE with Depth: infinity
application/problem+json for LDP errors

A caution from Jesse's dual-mode work: he had to pick what application/ld+json on a container returns and fails two Touchstone conneg MUSTs as a result. JSON-LD is JSS's native container format, so this collision is sharper for us — likely needs an explicit LWS-vs-Solid default per deployment.

Plan

Related

#319 #386 #86 #535 #206 #87 #89

Activity

  1. added
    enhancementNew feature or request
    pluginCould be implemented as a plugin (#206); core/plugin line defined in #564
    on Oct 14, 2026
  2. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    First Touchstone baseline (14 Oct 2026)

    Run against JSS 0.0.220 as an open target (single-user, public-write root ACL, no capabilities declared), Touchstone at 5c49679 (last commit before ebremer/touchstone#2 broke the image build; fix in ebremer/touchstone#3). Log: https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/actions/runs/38605553311 — that was a one-off on Actions; the ongoing scoreboard is a local script, see the checklist.

    203 tests — 12 passed, 41 failed, 11 cantTell, 139 inapplicable. Verdict: NOT conformant, 39 MUSTs failed or cantTell.

    Manifest passed failed cantTell
    core/conditional_requests 6 3 –
    core/data_resources 4 12 –
    core/containers 2 16 –
    core/discovery – 1 5
    core/linksets – 9 –
    core/notifications – – 5
    core/access_grants – – 1
    auth/* (3 suites), webhooks, grants, type index – – – (inapplicable, need Authentication capability)

    Passed: conditional-get-304, conditional-get-container-304, conditional-get-stale-validator-200, conditional-put-stale-if-match-412, conditional-delete-stale-if-match-412, update-changes-strong-etag, data-resource-range-request, data-resource-accept-ranges, updateDataResource, create-post-twice-distinct, container-conneg-vary, delete-container-recursive.

    Reading it: the LDP basics (ETags, conditionals, ranges, PUT/POST) carry over. Five of the six discovery outcomes are cantTell because the harness derives ${storage} from Link rel="https://www.w3.org/ns/lws#storage" and we don't send it — so that single header is the first thing to land; it turns a manifest from untestable into testable. Then application/lws+json containers (16 container failures) and linksets (9).

  3. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    Correction: the plugin half already exists — lwsd

    linkedwebstorage/lwsd (npm lwsd, July 2026) is a JSS plugin — lws/plugin.js mounted at /lws via --plugin — that implements most of the surface this issue lists: application/lws+json containers with pagination, storage description, linksets, content PATCH, 428/412 conditionals, 404 on PUT-create, Depth: infinity, problem+json, type index + search, webhooks with RFC 9421 signatures, access requests/grants with an ODRL engine, did:key + CID self-issued JWTs. Its own suite is 72 checks across 4 batteries, plus linkedwebstorage/test-suite (62 EARL tests).

    Verified today: 72/72 pass unmodified on JSS 0.0.220. Its CONFORMANCE.md findings C1–C14 are the real seam list and pre-date this issue; #603, #604, #615, #597 came out of it. (#623 closed as a dup of #603.)

    So the plan changes: rather than build core LWS features into JSS, bring lwsd up to the current drafts and run Touchstone against it at /lws/, then upstream only what the plugin provably can't do (C2 response decoration → #625, C3 owning /, C6 config channel → #615, grants on host pods → #624/#604).

    Spec drift lwsd needs to absorb (July 7832003 → Oct 14, 38 commits)

    Smoke test against the current plugin (JSS 0.0.220, --public)

    Run-root POST → 201 with up/type/linkset links ✅; lws+json container ✅; storage description with verificationMethod ✅; PUT-create 404 ✅; unconditional PUT 428, If-Match 204 ✅; 404 as problem+json ✅; Depth: infinity 204 ✅. Two things Touchstone will trip on immediately: the old storageDescription rel (the harness derives ${storage} from lws#storage), and relative Location headers (legal, but worth making absolute).

  4. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    First lwsd upgrade PR: linkedwebstorage/lwsd#10 — lws#storage link on every GET/HEAD/401, storage URI serves the CID-shaped description as application/lws+cid (root container via lws+json), StorageRoot service, absolute Location, plus scripts/touchstone.sh to run Touchstone against /lws/. 76/76 of its own checks on jss 0.0.220. CONFORMANCE.md there now carries the July → Oct drift list as the upgrade checklist.

  5. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    lwsd scoreboard, 14 Oct 2026 (linkedwebstorage/lwsd#10, two commits)

    Touchstone 5c49679, open target, 203 tests, jss 0.0.220:

    bare JSS lwsd before lwsd + discovery lwsd + JSON Patch / Content-Type / linkset fixes
    passed 12 (not run) 50 64
    failed 41 14 0
    cantTell 11 0 0
    inapplicable 139 139 139
    verdict 39 MUST failed/cantTell 10 MUST failed conformant

    Everything an unauthenticated target can be tested on now passes: discovery, containers, data resources, conditional requests, linksets, notifications shape, grant endpoint shape. The 139 inapplicable tests are the three authn suites, access grants and webhooks — they need alice/bob tokens, i.e. the token-exchange authorization server (now RFC 9728 discovery as of w3c/lws-protocol#256). That's the next real chunk; the remaining drift items (did:key → CID path, HTTP QUERY for search, dcterms envelopes) are smaller.

  6. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    lwsd now has an embedded authorization server (linkedwebstorage/lwsd#10, commit 3): token exchange, at+jwt, RFC 9728 discovery. Touchstone with Authentication declared: 109 passed / 18 failed / 76 inapplicable (was 64 / 0 / 139 as an open target). auth/cid 11/11, authorization_server 9/9, storage_authorization 11/11. Failures: 15 = type search still GET/POST instead of HTTP QUERY, 3 = access-grant details.

  7. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    lwsd is Touchstone-conformant (linkedwebstorage/lwsd#10, four commits): --auth run with Authentication, ReachableFixtures and HarnessIssuedTokens — 196 passed, 0 failed, 0 cantTell, 7 inapplicable (3 SAML, 4 optional-behaviour preconditions). All three auth suites except SAML, the authorization server, storage authorization, access grants, webhooks, index/search, and every core manifest.

    Host-API findings for the plugin seams here:

  8. melvincarvalho commented on Oct 14, 2026

    ContributorAuthor

    linkedwebstorage/lwsd#10 is merged (master, still 0.0.3 — version bump and npm publish later). README there carries the Touchstone status table. #628 (host-level QUERY) closed WONTFIX; the plugin keeps its contained shim. Remaining on this tracker is the host-pod side only: #622, #624/#604, #625, #615.

  9. melvincarvalho commented on Oct 21, 2026

    ContributorAuthor

    Status, 21 Oct 2026 — Touchstone re-baselined on the 19 Oct drafts (221 tests).

    The harness moved to WD-lws10-core-20261019 on 19 Oct (RFC 9728-only discovery, the LWS profile for content negotiation, and a new §9.6 Moving resources between containers). Against that, lwsd's head fell to 197 / 221 with two MUST failures: patching a linkset's up link was ignored with 204, where the draft now requires either a refusal or a move.

    Fixed in linkedwebstorage/lwsd@b92c694 — moving resources implemented (data resources and containers, atomic rename, delete + create authorization, 409 on bad destinations / cycles / removed up link, one Move activity, MoveResource capability with preservesIdentifier: false since jss identifiers are paths: 200 + Content-Location + 301 on the old identifiers), plus the LWS profile in JSON-LD and Turtle.

    Touchstone cd01608: 210 / 221 passed, 0 failed, 11 inapplicable — conformant (3 SAML, 3 move choices this storage does not make, 5 optional preconditions). Report: https://github.com/linkedwebstorage/lwsd/tree/gh-pages/reports/touchstone/2026-10-21-master-cd01608. Tracker (independent runs): https://ebremer.com/lws/conformance.

    Nothing new needed from JSS core for this round; the plugin API covered the move (a rename under the plugin's own data root). One observation for the seams list: a path-addressed host cannot preserve identifiers on a move (lwsd CONFORMANCE.md C16) — only an opaque-identifier storage could advertise preservesIdentifier: true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpluginCould be implemented as a plugin (#206); core/plugin line defined in #564

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL