JLWS RDF Content Transformation Profile normative-statement companion
Extracted with AI assistance (Claude Fable 5, Anthropic) from the pinned spec source via the spec-normative-analysis lws-rdf-transform inventory; awaiting review by the human editor, like the spec itself.
The core-428 incorporation ('The core's 428 rule applies unchanged: no unconditional overwrite of an existing RDF-readable resource.', #authoritative-bytes) carries no BCP 14 keyword of its own — its force is by incorporation of the JLWS Core #http-update rule; the vector rdf-transform/unconditional-put-still-428 is wired to the core companion's JLWSC-UPD-1. Errata candidate: give the scoping sentence a keyword. (Inventory lws-rdf-transform:authoritative-bytes:07.)
The 415 error shape ('A server that does not accept writes in a given type (including the not-a-source case above) answers 415 with problem details naming the accepted types.', #authoritative-bytes) is indicative — no BCP 14 keyword. Errata candidate: 'answers' -> 'MUST answer'. (Inventory lws-rdf-transform:authoritative-bytes:10.)
The normalizes read-back semantics ('Read-back in the stored media type is graph-isomorphic to what was written but NOT byte-identical', #normalizes) is a keywordless semantics bullet; the deterministic half is JLWSR-NORM-3 and the client half JLWSR-NORM-2. Errata candidate: give the isomorphism clause a MUST. (Inventory lws-rdf-transform:normalizes:02.)
The PATCH ETag-rotation clause ('Applying an RDF patch is a state change like any other: all representation ETags rotate', #rdf-patch) is keywordless — an application of JLWSR-AB-4 to PATCH. Errata candidate. (Inventory lws-rdf-transform:rdf-patch:02.)
The PATCH precondition incorporation ('the precondition discipline of #authoritative-bytes applies to the PATCH request itself', #rdf-patch) is keywordless incorporation of JLWSR-AB-5..6 and the core 428 rule. Errata candidate. (Inventory lws-rdf-transform:rdf-patch:03.)
The derived-views oracle incorporation ('All such derived views remain bound by the core's oracle-freedom invariants', #indexing) is keywordless; the visibility half is stated with an explicit MUST in JLWSR-SP-5, and the core companion carries the oracle-freedom MUSTs. Errata candidate. (Inventory lws-rdf-transform:indexing:04.)
The allowlisted-fetch SSRF incorporation ('the core's SSRF policy (JLWS-CORE Server-side request forgery) applies to any allowlisted fetch.', #security-privacy) is keywordless incorporation; the operative MUSTs live in the core's #ssrf section (core companion JLWSC-SSRF-*). Errata candidate. (Inventory lws-rdf-transform:security-privacy:04.)
JLWS RDF Content Transformation Profile
RDF-transforming server
RDF-aware client
Storage description document (rdf-1 capability entries)
Deterministic and vectorable but not yet written: the suite's GAPS.md defers this tranche (bounded-parser rejection of depth/size bombs, declared-context reuse in JSON-LD compaction, derived-type writes, the RDF PATCH application tranche, stale-412 on the derived representation, falsely-advertised-pair probes). A natural next tranche for test-vectors/vectors/rdf-transform/.
Pure permission: both exercising and not exercising the option are conformant, so no deterministic vector can pin a violation of the permission itself. Constraints on the exercised option are recorded as their own statements where the text gives them normative force.
Client-internal reliance ('depend on', 'rely on') is not wire-observable and the spec mandates no counterpart server rejection; this is interoperability guidance a data vector cannot pin. At most auditable against a client-under-test transcript.
Architecture preference with no observable conformance surface: a normalizes-declaring server is fully conformant, so no vector can distinguish preferring byte-preserving storage from not preferring it.
Not black-box testable: whether an ETag embeds an invertible content digest is a property of ETag construction, not observable from responses (a keyed or random ETag is indistinguishable from a digest-based one), and no evidence artifact is mandated. Auditable only by implementation review.
The operative semantics live in a referenced companion contract (AC-SPARQL per-solution authorization filtering) whose own conformance surface is defined there; this profile pins only the advertisement condition, which is vectored separately.
An RDF-transforming server MUST advertise, in the storage description's capability set, one ContentNegotiation entry per supported source media type
Advertisement duty: an auditor can check the storage description contains the entries, but an unadvertised-yet-supported source type is not externally observable and no rejection path is mandated.
source — REQUIRED; the stored media type the entry applies to.
Condition: a ContentNegotiation entry claims this profile. REQUIRED normalized to MUST; document-shape rule rejectable at the validate-storage-description seam.
target — REQUIRED; the media types derivable from it.
Condition: a ContentNegotiation entry claims this profile. REQUIRED normalized to MUST; the constraint on each target value is JLWSR-CAP-4.
Each MUST be a concrete RDF serialisation of the same abstract syntax
'Each' = each target media type in the entry's target array; the sentence's trailing cross-reference to #round-trip is a ReSpec section link, omitted from the quote. Checkable by a storage-description validator against the registered concrete RDF serialisations.
profile — REQUIRED for entries claiming this profile; the value https://w3id.org/jeswr/lws/transform/rdf-1 pins the transformation semantics
REQUIRED normalized to MUST. A ContentNegotiation entry WITHOUT a profile member is explicitly outside this document (no semantics-preservation claim) — that scoping sentence carries no obligation and is not separately recorded.
OPTIONAL normalized to MAY. The default's behavioural force (absent flag => byte-exact read-back) is certified via JLWSR-AB-1 and JLWSR-NORM-4; the member's presence itself cannot be violated.
The storage description's conformsTo array MUST include https://w3id.org/jeswr/lws/transform/rdf-1 when any entry claims this profile.
Clients MUST NOT attempt transformation-dependent behaviour (RDF conneg, RDF PATCH, SPARQL query) against a storage that does not advertise it; servers MUST NOT advertise pairs they do not implement
Multi-obligation sentence; operative sub-clause here is the client side ('Clients MUST NOT attempt transformation-dependent behaviour … against a storage that does not advertise it'). The feature-detect duty also defines the RDF-aware client conformance class (#conformance). Tagged E on the client-evaluation seam the suite vectors (detect-transform-offer): a fail-open detection verdict is a deterministic violation.
Multi-obligation sentence; operative sub-clause here is 'servers MUST NOT advertise pairs they do not implement' (the JLWS-CORE conformance rule scoped to this capability). The linked vector exercises an advertised pair positively; no vector yet probes a falsely-advertised pair (see the gap).
The derived representation MUST encode an RDF graph (or dataset, for dataset-capable pairs) isomorphic to that of the authoritative representation
Condition: every advertised source -> target pair claiming this profile. Isomorphism per RDF 1.1 Concepts §3.6 (same triples up to blank-node relabelling); the keywordless 'Blank-node identifiers are NOT stable across representations or requests' bullet is this rule's flip side, covered by the blank-node-isomorphism vector.
Transformation MUST NOT apply inference, schema expansion, or vocabulary rewriting: no triples added, none removed.
Relative IRIs MUST be resolved against the resource URI as base, identically in every representation.
For JSON-LD targets: when the authoritative representation is JSON-LD with a declared @context, servers MUST serialise derived JSON-LD using that context
The sentence continues with the no-dereference allowlist gate; its fail-closed halves are JLWSR-RT-5/6. The declared-context-reuse vector is deferred (GAPS.md).
A compacted JSON-LD source declaring a remote context outside that allowlist cannot even be interpreted as an RDF graph without resolving that context, so the server MUST decline the transformation for that resource (406 + problem details, as for an unparseable source) — it MUST NOT resolve the context with a network fetch.
Multi-obligation sentence; operative sub-clause here is 'the server MUST decline the transformation for that resource (406 + problem details)'. The following 'Only when the source is context-independent … may the server transform it' sentence uses lowercase 'may' and restates this rule's complement; not separately recorded.
Multi-obligation sentence; operative sub-clause here is 'it MUST NOT resolve the context with a network fetch' — the SSRF guard, testable at the transform seam with a fetch spy (the vector asserts declined-not-fetched). See also JLWSR-SP-3.
When the source has no context (e.g. Turtle), the server MUST use a documented, stable context or expanded form.
The 'stable' half is mechanically testable (two reads of one state use the same context / expanded form); the 'documented' half is only auditable as the existence of documentation. Tagged E for the stable half; vector deferred.
In every case clients MUST NOT depend on any particular compaction beyond the graph contract.
If the authoritative representation fails to parse under its stored media type, the server MUST answer requests for derived representations with 406 Not Acceptable carrying a problem details body of type https://w3id.org/jeswr/lws/problems/unparseable-source — the stored bytes remain readable in the stored media type.
Operative sub-clause here is the 406 + problem-details answer for derived representations.
Operative sub-clause here is 'the stored bytes remain readable in the stored media type' — the per-resource degradation guarantee ('A byte store never breaks because a transform does'). The em-dash clause carries no keyword of its own; level MUST is the governing sentence's (adjudicated at extraction).
A read in the stored media type MUST return those bytes exactly, unless normalizes is declared for that source type
'Those bytes' = the byte stream accepted at write time (the authoritative representation). Restated with an explicit keyword in JLWSR-NORM-4.
responses vary by representation, so responses to requests subject to transformation MUST carry Vary: Accept.
The ETag returned with a Turtle response and the ETag returned with a JSON-LD response of the same resource state MUST differ, and each MUST change whenever the resource state changes.
Multi-obligation sentence; operative sub-clause here is 'MUST differ' (per-representation entity-tags, RFC 9110 §8.8.3).
Multi-obligation sentence; operative sub-clause here is 'each MUST change whenever the resource state changes' (the ETag rotation matrix).
A server MUST accept an If-Match carrying either the authoritative representation's current ETag or the current ETag of the derived representation the client last read; both name the same resource state.
The lost-update fix: write preconditions evaluate against the representation the ETag names.
'Either' = the If-Match value of either the authoritative or a derived representation. The acceptance side is vectored (JLWSR-AB-5); the stale-412 side is not yet.
a server MAY accept a PUT whose Content-Type is an advertised type reachable from the stored type, but ONLY when the written type is itself advertised as a source in a ContentNegotiation capability (bidirectional coverage).
The testable half is the ONLY-when restriction (a conforming server never accepts a write in a type lacking a source entry — observable as 415); the permission itself cannot be violated. Derived-type-writes vectors are deferred (GAPS.md). The following rationale sentence (stranded stored type) is rationale, not separately recorded.
Servers MUST NOT silently transcode a write into a different stored type unless normalizes is declared.
Such a server MUST declare "normalizes": true on the affected source entry.
'Such a server' = one that cannot preserve written bytes for a media type (e.g. a quad-store-backed server that parses on ingest and reserialises on read). Violation is observable as its contrapositive: a non-byte-identical read-back on a source type whose entry lacks the flag (the JLWSR-AB-1 probe).
clients MUST NOT rely on formatting, comment preservation, prefix labels, or blank-node identifiers.
Condition: normalizes is declared for the source media type. Same sentence as the keywordless isomorphic-read-back semantics (see the extraction notes).
The normalisation MUST be deterministic for a given resource state (two reads without an intervening write return identical bytes), so ETags remain coherent.
Without the flag (the default), byte-exact read-back is a MUST — the core's byte-native promise.
Servers SHOULD prefer byte-preserving storage; normalizes is an honest escape hatch, not the recommended mode.
A server MUST NOT advertise an RDF patch format (application/sparql-update, text/n3 for N3 Patch N3-PATCH) in Accept-Patch or in a PatchSupport capability entry for a media type unless this profile is on for that media type
'N3-PATCH' is the source's citation marker as it appears in the normalized (tag-stripped, ref-unbracketed) text.
a server MAY preserve unaffected formatting but clients MUST NOT rely on it.
Condition: after an RDF patch. Operative sub-clause here is the server permission; preserving or not preserving are both conformant, so no violation is possible.
Condition: after an RDF patch. Operative sub-clause here is 'clients MUST NOT rely on it'.
A server for which this matters SHOULD declare normalizes for patched types.
The recommended artifact (the normalizes flag on the patched type's entry) is auditable in the storage description; whether 'this matters' held for a given server is not.
Patch evaluation MUST be atomic and MUST enforce the same authorization as a content write; conditional patch semantics (e.g. an N3 Patch ?conditions that fails to match) yield 409 Conflict with problem details.
Operative sub-clause here is 'Patch evaluation MUST be atomic': a failing patch leaves the resource (and its ETags) unchanged — observable as all-or-nothing state. The RDF PATCH application tranche is deferred (GAPS.md).
Operative sub-clause here is 'MUST enforce the same authorization as a content write' — security-critical: PATCH is not an authorization bypass.
Operative sub-clause here is 'conditional patch semantics … yield 409 Conflict with problem details' — an indicative error-shape clause (the sentence's MUSTs govern atomicity and authorization); level MUST adjudicated at extraction as a mandated error shape. Errata candidate: 'yield' -> 'MUST yield'.
When this profile is on, the server MAY additionally derive index entries from the parsed RDF content of RDF-readable resources (rdf:type statements and descriptive properties), ranked equally with header-derived entries
The searchindex draft's 'MAY derive from content' hook, made well-defined by this profile's parse contract. The embedded 'ranked equally' constraint is observable only when the optional feature is exercised; the derived views' oracle bounds are JLWSR-SP-5.
The SparqlQueryService (JLWS-CORE Query services) MUST only be advertised when this profile is on
The SparqlQueryService (JLWS-CORE Query services) MUST only be advertised when this profile is on, and its access-control semantics (per-solution authorization filtering) follow AC-SPARQL.
Operative sub-clause here is 'its access-control semantics (per-solution authorization filtering) follow AC-SPARQL' — keywordless incorporation whose operative rules live in the referenced AC-SPARQL contract; the sentence's MUST governs the advertisement condition (JLWSR-IDX-2). Errata candidate: 'follow' -> 'MUST follow'.
Parsers MUST be resource-bounded (document size, triple count, nesting depth, parse time); parse failures are per-resource errors
Operative sub-clause here is the resource-bounding mandate; testable with adversarial size/depth bombs. The suite defers these vectors (GAPS.md: 'bounded-parser rejection of depth/size bombs').
Operative sub-clause here is 'parse failures are per-resource errors …, never server faults' — indicative (no keyword of its own; level MUST adjudicated at extraction); a parse-bomb in one resource yields the 406 unparseable-source path (JLWSR-RT-9) while the server and sibling resources stay healthy. Errata candidate: 'are' -> 'MUST be'.
serialisation and parsing MUST NOT fetch remote documents — no JSON-LD remote @context resolution beyond a server-configured allowlist of cached contexts, no owl:imports, no follow-your-nose.
The no-dereference rule (SSRF guard); the JSON-LD-specific application is JLWSR-RT-5/6. Testable at the transform seam with a network observer on attacker-supplied content.
is bound by the core's oracle-freedom rules, and index visibility MUST match resource read visibility per-agent.
Quote starts mid-sentence because the subject ('the enrichment hook') is followed by an empty ReSpec cross-reference to #indexing. Full clause: the enrichment hook is bound by the core's oracle-freedom rules, and index visibility MUST match resource read visibility per-agent. An agent without read access to a resource must see no content-derived index entries for it.
per-representation ETags MUST NOT embed content digests that let an agent with access to one representation infer bytes of another it cannot read
Condition: representation-scoped authorization extensions are in effect (with resource-scoped authorization all representations share visibility).