Skip to content

L1: LWS application/lws+json container representation + conneg (--lws)#1

Merged
charlesvardeman merged 8 commits into
la3d/lwsfrom
la3d/lws-container
Jun 30, 2026
Merged

L1: LWS application/lws+json container representation + conneg (--lws)#1
charlesvardeman merged 8 commits into
la3d/lwsfrom
la3d/lws-container

Conversation

@charlesvardeman

Copy link
Copy Markdown

L1 — LWS application/lws+json container representation + content negotiation

First layer of the in-process W3C Linked Web Storage (LWS) storage layer for this JSS fork. Purely additive: a new --lws flag enables an application/lws+json container representation served via content negotiation; default LDP/Solid behavior is unchanged (a negative-control test guards it). No PUT/POST semantic changes (the upstream feature/lws-mode PUT restriction was reverted as non-conformant — we don't repeat it).

What it delivers

  • generateLwsContainer() — spec-conformant items[] container (@context: https://www.w3.org/ns/lws/v1, id, type, totalItems, items[] with DataResource/Container typing + mediaType/size/modified).
  • application/lws+json registered in content negotiation (src/rdf/conneg.js).
  • --lws CLI flag + JSS_LWS env + --print-config — full parity with --conneg; request.lwsEnabled decoration.
  • Served in the container-GET path only when --lws AND Accept: application/lws+json — with Link: rel="up" (omitted at the storage root) and the standard container headers (ETag/Allow/Accept-Post) via the shared getAllHeaders helper.
  • Vary: Accept emitted identically across all variants when LWS is negotiable (HTTP cache-correctness).

Base

la3d/main = pristine pin of upstream 0.0.210 (gitHead 0f4287f). 8 commits on top.

Tests

Full suite 993/993 green (baseline 987 + 6 new: container unit, conneg unit, e2e conformance incl. LDP negative control + Vary assertions).

Provenance & review

  • Design of record: lws-pod repo docs/superpowers/specs/2026-06-29-lws-storage-layer-design.md (the "Substrate — RESOLVED" block).
  • Plan: docs/superpowers/plans/2026-06-29-lws-L1-container-conneg.md.
  • Built via subagent-driven development: per-task spec+quality reviews + an opus whole-branch review; the one Important finding (Vary: Accept) was fixed (6e4f16d).

Deferred to L2+

Linkset + Storage Description + /.well-known/lws-configuration; Type Index/Search; ContainerPage pagination; S3 storage backend; --no-lws; HEAD lws+json negotiation parity (TODO(lws-head-parity) marker in place); per-variant 304/ETag.

Merge note: la3d/main is the pristine upstream pin (for rebasing onto future JSS releases) — do not merge this into la3d/main directly. This PR is a review/record artifact; the LWS layer stack (L1–L4) likely wants its own integration branch. Decide the merge model before merging.

🤖 Generated with Claude Code

charlesvardeman and others added 8 commits June 29, 2026 14:37
- Add lws: false default alongside conneg default
- Add JSS_LWS environment variable mapping
- Add lws to BOOLEAN_KEYS set for string coercion
- Add lws line to printConfig() output

Ensures --lws flag behaves identically to --conneg across all config.js layers: defaults, env vars, and print-config display.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…ner branch

- Replace bare Content-Type/Vary header set with getAllHeaders() call so the
  LWS branch emits ETag (for conditional GETs), Allow, Accept-Post, Accept-Patch,
  Accept-Ranges, and CORS headers on par with the LDP container branch.
- Append rel="up" link after getAllHeaders so it joins rather than replaces the
  existing LDP type links.
- Fix negotiated-type computation: call selectContentType when lwsEnabled even
  without conneg (selectContentType already handles application/lws+json
  independently of connegEnabled per the lws-conneg unit test).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…tiable; doc dotfile divergence; mark HEAD-parity TODO

- Extend getVaryHeader (approach a) with lwsEnabled=false parameter so
  it emits Accept in Vary when connegEnabled || mashlibEnabled || lwsEnabled
- Thread lwsEnabled through getResponseHeaders and getAllHeaders in headers.js
- Pass lwsEnabled: request.lwsEnabled at all three container GET sites:
  the 304 short-circuit (resource.js:294), the LWS branch (lws+json),
  and the LDP ld+json fallback branch — all three now emit identical
  Vary: Accept, Authorization, Origin under lws:true,conneg:false
- getAcceptHeaders is unaffected; Turtle/N3 in Accept-Post/Accept-Put
  is still gated on the real connegEnabled only
- Add comment on deliberate dotfile divergence in generateLwsContainer
  (all dotfiles excluded, unlike isHiddenEntry which allows .acl/.meta/.well-known)
- Add TODO(lws-head-parity) in HEAD handler container branch (L2 deferred)
- New lws-conformance assertions: both lws+json and ld+json responses
  carry Vary containing Accept under lws:true,conneg:false server

Co-Authored-By: Claude Opus 4.8 <[email protected]>
charlesvardeman added a commit to LA3D/lws-pod that referenced this pull request Jun 29, 2026
…rryover

L1 (lws+json container + conneg) is complete & merge-ready: la3d/lws-container,
8 commits over la3d/main (0.0.210), PR LA3D/JavaScriptSolidServer#1, 993/993 green.
Updates the START-HERE block: L1 done; merge-model note (la3d/main stays pristine,
use a la3d/lws integration branch); L2 = linkset + Storage Description (track spec
PRs #183/#180); deferred carryover (--no-lws, HEAD parity, pagination, 304/ETag,
unit-test gaps); then L3 (SHACL admission) and L4 (OKF projection rewritten).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@charlesvardeman
charlesvardeman changed the base branch from la3d/main to la3d/lws June 30, 2026 13:04
@charlesvardeman
charlesvardeman merged commit d8166f2 into la3d/lws Jun 30, 2026
@charlesvardeman
charlesvardeman deleted the la3d/lws-container branch June 30, 2026 14:55
charlesvardeman added a commit that referenced this pull request Jul 3, 2026
…rce-error content

Review fixes #1,JavaScriptSolidServer#7,JavaScriptSolidServer#9,JavaScriptSolidServer#12:
- #1 put_typed_resource: declaring the describedby shape is now transactional —
  snapshot the target .meta, MERGE the shape in (don't clobber other keys),
  then roll the .meta back if admission rejects. A rejected write leaves no
  durable side effect and no dangling shape pointer.
- JavaScriptSolidServer#7 call_remote_pod: deep-strip hidden/bidi chars from the federated
  remote_result (least-trusted source) before it enters the model's context.
- JavaScriptSolidServer#9 ResourceError now carries the same isError + content[] teaching shape as a
  tool error, so resources/read failures surface model-readable content, not a
  bare message.
- JavaScriptSolidServer#12 errors.structuredError reuses the toolText envelope.
- Fix a stale mcp.test.js assertion that expected a raw (pre-envelope) body.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
charlesvardeman added a commit that referenced this pull request Jul 3, 2026
Correctness/security: transactional put_typed_resource .meta (#1),
type/describedby + federated-content sanitize (#2/JavaScriptSolidServer#7), container ACL-path
resolution (JavaScriptSolidServer#3), malformed-percent invalid-params (JavaScriptSolidServer#4), bounded read +
truncation signal (JavaScriptSolidServer#5/JavaScriptSolidServer#6), skill read-error not masked (JavaScriptSolidServer#8), resource-error
teaching content (JavaScriptSolidServer#9). Maintainability: single surface registry (JavaScriptSolidServer#11),
helper reuse (JavaScriptSolidServer#12), restored live-gate coverage (JavaScriptSolidServer#10, lws-pod repo).

All fork changes TDD'd in test/mcp-v2-review-fixes.test.js; mcp/lws/wac/acl/
storage/container/handler suites green per-file.
charlesvardeman added a commit that referenced this pull request Jul 11, 2026
…ce gate — no 200 where GET teaches 406

- negotiateHeadFileContentType's legacy JSON-LD branch (~line 1190) was
  still gated on bare isRdfContentType(storedContentType), which includes
  plain application/json — under --lws a stored .json HEAD with
  Accept: text/turtle or Accept: application/ld+json returned a lying 200
  where GET correctly 406-teaches (reviewer-reproduced, final whole-round
  review Important #1)
- fix: mirror GET's ternary (lwsEnabled ? isRdfSourceType : isRdfContentType)
  so under --lws plain JSON falls past the legacy branch to the F3 HEAD
  406-teaching mirror; stored JSON-LD → JSON-LD target still passes;
  --lws-off stays byte-identical (ternary's else arm is the old predicate)
- test/lws-nonrdf-teaching.test.js: two new HEAD/.json cases (Accept:
  text/turtle and Accept: application/ld+json), each asserting HEAD status
  equals the paired GET's 406 and content-type application/problem+json
- verified: targeted 4-file run 33/33 pass; full suite 1437 tests, 1436
  pass, 0 fail, 1 pre-existing skip

Co-Authored-By: Claude Opus 4.8 <[email protected]>
charlesvardeman added a commit that referenced this pull request Jul 13, 2026
…text-free docs (task-6 review #1)

- applyN3Patch detects whether the target document carries an @context and
  passes the verdict into insertTriple: no @context -> the predicate key is
  the full IRI (compactPredicate skipped). On the JavaScriptSolidServer#7 Turtle-family path
  (stored bytes -> expanded JSON-LD, no @context) the compacted keys
  ("rdf:type", "dc:title") re-parsed as literal scheme-IRIs <rdf:type> —
  silent corruption of every common-vocabulary insert.
- Legacy JSON-LD-stored docs (which DO have an @context resolving those
  prefixes) keep the existing compaction behavior byte-identically.
- deleteTriple needs NO symmetric fix: its match already tries the raw key
  first (key === predicate; expanded docs carry full-IRI keys), verified by
  repro and pinned by the new DELETE test. patch.where is parsed but never
  applied, so no compaction assumption there.
- New tests pin both paths TRIPLE-LEVEL via the n3 Parser on an .nt-stored
  doc (N-Triples has no prefix mechanism, so a Turtle round-trip can't
  launder the corrupt CURIE back to the right IRI and mask the bug).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant