JLWS Core Protocol normative-statement companion
type: CompanionDocument
companion of: JLWS Core Protocol — A Clean-Slate Linked Web Storage Design
created: 2026-07-06
was attributed to: me
description: Extracted with AI assistance (Claude Fable 5, Anthropic) from the pinned spec source; awaiting review by the human editor, like the spec itself.
extraction note: The namespace-alias MUST (JLWSC-NS-1) lives inside a 'Divergence from lws10-core' note div — a container ReSpec renders as informative. It is vectored (containers/post-create-container-namespace-alias, discovery/storage-description-link-on-get) and clearly intended normatively. Errata candidate: move the alias rule out of the note.
extraction note: 'This personal draft MUST NOT mint or squat identifiers in the w3.org namespace' (#namespace note) is an editorial self-obligation about the document, not an implementation requirement; not modelled.
extraction note: The POST error shapes (#http-create-post: 'the server responds 404; on a naming conflict the server assigns a different URI or responds 409') are indicative — no BCP 14 keyword — yet vectored (containers/post-to-missing-container-404, containers/post-slug-conflict). Errata candidate: 'responds' -> 'MUST respond'.
extraction note: The GET read-back sentence (#http-read, 'GET on a data resource returns its stored representation with the stored media type …') is indicative; the byte-exactness MUST lives in #content-transformation (JLWSC-CT-3, vectored by resources/byte-exact-roundtrip).
extraction note: The validation-failure error shapes (#rs-validation: 'On validation failure the server responds 401 with an appropriate error parameter. If the token is valid but the operation is not allowed: 403 … otherwise 404') are indicative; the 404/403 oracle rule is normative in #oracle-freedom (JLWSC-OF-1), and the 401 error-parameter half is vectored (auth/challenge-rejected-token-error) via the keywordless RFC 6750 incorporation in #authz-discovery. Errata candidate: give both a keyword; the MUST NOT half is JLWSC-AD-3.
extraction note: The #identity-documents SSRF incorporation ('All server-side dereferencing performed during validation is subject to the SSRF requirements of #ssrf') is keywordless; the operative MUSTs are JLWSC-SSRF-1..3. Errata candidate.
extraction note: 'issuers SHOULD serve CIDs with caching headers that make such caching effective' (#identity-documents) and 'Issuers of authentication credentials are responsible for validating client identifiers and MAY use this mechanism …' (#client-identity) bind identity-document publishers and credential issuers — parties outside the declared conformance classes; not modelled. Errata candidate: declare the class or mark informative.
extraction note: The WebAuthn wire-contract packaging (#suite-webauthn, 'packaged for presentation as an RFC 8693 subject_token exactly as specified by the wire contract of WEBAUTHN-REAUTH') is keywordless, yet its fail-closed decode is vectored (auth/webauthn-bundle-decode-ok, auth/webauthn-bundle-noncanonical-b64url-rejected). Errata candidate: 'packaged' -> a MUST.
extraction note: The SSE 'source' member ('The subscription response includes source: the event-stream URL') and the WebSocket 'receiveFrom' member ('The subscription response includes receiveFrom: a wss: URL — a capability URL with the same binding, entropy, expiry, and revocation requirements as SSE capability-URL mode') are keywordless, yet vectored (notifications/sse-subscription-returns-source, notifications/websocket-subscription-returns-receivefrom; wired here to JLWSC-SUB-3). Errata candidate: 'includes' -> 'MUST include'; the WebSocket capability-URL requirements inherit JLWSC-SSE-2 only by simile.
extraction note: 'A subscription to a container is recursive: events for the container and all descendants.' and 'Paginated responses use status 200.' and 'When paginated, items contains the current page while id, type, and totalItems reflect the whole (visible) membership.' are keywordless definitional prose; not modelled.
extraction note: The webhook delivery-side SSRF sentence ('Delivery-side SSRF discipline applies to the storage server's outbound POST: inbox URIs are untrusted input.') is keywordless incorporation of #ssrf; not modelled (JLWSC-SSRF-1..3 carry the MUSTs).
extraction note: Four of the six #ssrf bullets (Scheme, Address policy, Rebinding, Caps) carry no keyword of their own — normative only via the umbrella 'Every such fetch MUST apply all of the following' (JLWSC-SSRF-1, whose comment enumerates them); the Redirects and No-credential-forwarding bullets carry their own keywords (JLWSC-SSRF-2/3).
extraction note: #versioning-slot ('Version resources are read-only and subject to the same authorization as their originals at read time') is a keywordless companion-slot reservation; not modelled (the Versioning companion will carry the requirements).

JLWS server
type: ConformanceClass
defined by: conformance

JLWS client
type: ConformanceClass
defined by: conformance

JLWS authorization server
type: ConformanceClass
defined by: conformance

notification server
type: ConformanceClass
defined by: conformance

PoP-capable server
type: ConformanceClass
defined by: conformance

webhook receiver
type: ConformanceClass
defined by: webhook-binding

storage description document
type: ConformanceClass
defined by: discovery-model

access document (ODRL request/grant)
type: ConformanceClass
defined by: odrl-profile

authentication credential
type: ConformanceClass
defined by: credential-model

storage controller
type: ConformanceClass
defined by: terminology

gap-deferred
type: TestGap
description: Deterministic and vectorable but not yet written (GAPS.md 'vectorable, deferred'): strong-ETag / weak-If-Match probes, HEAD-error header mirror, client-ID metadata document shapes, falsely-advertised capability probes, guarded-delete If-Match, group semantics, VC-receipt status, discovery-oracle enumeration, CORS shapes, self-signed-CID and did:key offline validation, and similar. These statements are the suite's next-tranche backlog.

gap-pure-permission
type: TestGap
description: 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 their own statements where the text gives them force.

gap-client-conduct
type: TestGap
description: Client-side conduct not observable from server-side data vectors (GAPS.md 'client-behavioural'); a client-under-test harness tranche is deferred. Where a counterpart server rejection is mandated, the server-side statement carries the vector.

gap-deployment-policy
type: TestGap
description: Deployment policy: the trigger (a server-determined threshold, policy, or sizing choice) cannot be forced by a portable harness (GAPS.md 'deployment-policy'). Vectorable for implementations exposing the relevant knob.

gap-stateful-temporal
type: TestGap
description: Spans multiple observations over time, concurrency, or a streaming connection; a request/response vector cannot express it (GAPS.md 'stateful/temporal' — SSE resumption/reset, delivery cessation on revocation, immediate-revocation propagation).

gap-network-trust
type: TestGap
description: Governs live-network interaction or whom to trust (GAPS.md 'network/trust'): suite credential validation dereferences live documents (CID, OIDC discovery, JWKS), TLS/certificate behaviour, and outbound-fetch discipline need a live harness or an instrumented network observer, not a data vector.

gap-meta
type: TestGap
description: Meta-requirement whose evidence is the behaviour of the whole suite (the HTTP binding itself, RFC 9110 semantics): no single vector pins it; every HTTP-suite case exercises it.

gap-companion-planned
type: TestGap
description: The surface belongs to a planned companion specification (query services, versioning); the core only reserves slots and fixes invariants the companion's own suite must pin (GAPS.md 'companion-planned').

JLWSC-NS-1
type: Requirement
statement: implementations MUST also accept the corresponding https://www.w3.org/ns/lws# URI as an equivalent alias, preserving interoperability with Working-Draft implementations.
comment: Condition: wherever this specification requires a https://w3id.org/jeswr/lws# URI in a link relation or type position. NOTE: the sentence sits inside a divergence note div (see the extraction notes — errata candidate).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: namespace
test case: case.json

JLWSC-CONF-1
type: Requirement
statement: a server MUST NOT advertise a capability, service, or profile it does not implement.
comment: The advertise-implies-implement rule every capability leans on. Vectors exercise advertised features positively (e.g. rdf-transform/advertised-conneg-honoured for one pair); no vector yet probes a falsely-advertised capability.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: conformance
test gap: gap-deferred

JLWSC-RC-1
type: Requirement
statement: a server MUST NOT require any particular content type or structure of data-resource content.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: resource-classes
test case: case.json

JLWSC-RC-2
type: Requirement
statement: A server MAY enforce media-type or size policy per storage
requirement level: MAY
requirement subject: JLWS server
testability: Premature
comment: Deployment-policy permission; the trigger cannot be forced portably.
anchor: resource-classes
test gap: gap-deployment-policy

JLWSC-RC-3
type: Requirement
statement: MUST advertise any such restriction as problem details on rejection.
comment: Subject of the fragment: a server enforcing a media-type/size policy (JLWSC-RC-2). The problem-details envelope itself is pinned by errors/problem-details-on-4xx; the policy trigger cannot be forced.
requirement level: MUST
requirement subject: JLWS server
testability: Premature
anchor: resource-classes
test gap: gap-deployment-policy

JLWSC-CVD-1
type: Requirement
statement: A resource MUST be exactly one of container or data resource.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: container-vs-data
test case: case.json

JLWSC-CVD-2
type: Requirement
statement: A server MUST NOT serve client-authored content as the representation of a container
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: container-vs-data
test case: case.json

JLWSC-CTN-1
type: Requirement
statement: Servers MUST include a Link header with rel="up" pointing to the parent container in responses to GET and HEAD requests on any non-root resource.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: containment
test case: case.json

JLWSC-CTN-2
type: Requirement
statement: clients MUST NOT be able to modify it directly; membership changes occur only as a side effect of resource creation, deletion, and (where supported) move.
comment: 'It' = a container's server-managed items list. Server-enforced impossibility (the server rejects the attempt), so bound to the server.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: containment
test case: case.json

JLWSC-CTN-3
type: Requirement
statement: when a resource is created in a container, the server MUST atomically add it to that container's items list.
comment: The sequential membership update is black-box observable; the 'atomically' qualifier under concurrency is not (GAPS.md 'stateful/temporal') — it is TLC-checked at the design level instead (formal/tla/JlwsContainment.tla: MembershipExact/NoOrphans hold under AtomicSpec; the split-phase implementation the MUST forbids is refuted in one step). The create-side membership vector is deferred; the delete side is pinned (JLWSC-CTN-4).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: containment
formal model: JlwsContainment.tla
test gap: gap-deferred

JLWSC-CTN-4
type: Requirement
statement: when a resource is deleted, the server MUST atomically remove it from its parent container's items list.
comment: Sequential before/after pinned by the vector; concurrency atomicity is not black-box observable — TLC-checked at the design level (formal/tla/JlwsContainment.tla: split-phase deletion leaves a dangling member, an existence oracle).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: containment
formal model: JlwsContainment.tla
test case: case.json

JLWSC-CTN-5
type: Requirement
statement: every non-root resource MUST be reachable from the storage root through the containment hierarchy.
comment: Universal state invariant ('no orphans'): spot-checkable per resource but not enumerable black-box over all server behaviour; audit-level.
requirement level: MUST
requirement subject: JLWS server
testability: AccountableExistence
anchor: containment

JLWSC-CTN-6
type: Requirement
statement: a container MUST NOT directly or indirectly contain itself.
comment: State invariant ('no cycles'); a move-supporting server exposes a rejectable probe (move a container into its own descendant), otherwise audit-level.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: AccountableExistence
anchor: containment

JLWSC-PA-1
type: Requirement
statement: The URI of every resource MUST be the URI of its parent container extended by exactly one non-empty path segment (for containers, followed by a terminating /).
comment: The create vectors assert path-aligned Location values; the universal quantifier over all minted URIs is not black-box enumerable (GAPS.md). The keywordless 'The storage root's URI is the prefix of every resource URI in the storage.' is this rule's transitive consequence.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: path-alignment
test case: case.json

JLWSC-PA-2
type: Requirement
statement: Container URIs MUST end in /; data-resource URIs MUST NOT.
comment: Two levels in one sentence; operative sub-clause here is 'Container URIs MUST end in /' (split — see JLWSC-PA-3).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: path-alignment
test case: case.json

JLWSC-PA-3
type: Requirement
statement: Container URIs MUST end in /; data-resource URIs MUST NOT.
comment: Operative sub-clause here is 'data-resource URIs MUST NOT [end in /]'.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: path-alignment
test gap: gap-deferred

JLWSC-MA-1
type: Requirement
statement: MUST include the identifiers of all member resources to which that agent has access
comment: Subject of the fragment: the complete container listing (the union of the items arrays across all pages), for an agent with read access to the container.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: membership-authorization
test case: case.json

JLWSC-MA-2
type: Requirement
statement: The representation MUST NOT include members the agent has no access to
comment: The fail-closed listing rule (divergence D12 from the Working Draft's permissive MAY).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: membership-authorization
test case: case.json

JLWSC-MA-3
type: Requirement
statement: totalItems MUST count only the members visible to the requesting agent (across the whole collection, not the current page).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: membership-authorization
test case: case.json

JLWSC-CP-1
type: Requirement
statement: A container representation MUST include:
comment: The REQUIRED members enumerated by the following list: id (the container's URI), type ("Container"), totalItems (integer count of members disclosable to the requesting agent), items (flat array of member descriptions; empty array when empty; current page only when paginated).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: container-properties
test case: case.json

JLWSC-CP-2
type: Requirement
statement: Each member description MUST include id and type
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: container-properties
test case: case.json

JLWSC-CP-3
type: Requirement
statement: It SHOULD include size (bytes) and modified (ISO 8601), and MUST include mediaType for data resources.
comment: 'It' = each member description. Operative sub-clause here is the SHOULD (size/modified); split — see JLWSC-CP-4.
requirement level: SHOULD
requirement subject: JLWS server
testability: Enforceable
anchor: container-properties
test gap: gap-deferred

JLWSC-CP-4
type: Requirement
statement: It SHOULD include size (bytes) and modified (ISO 8601), and MUST include mediaType for data resources.
comment: Operative sub-clause here is 'MUST include mediaType for data resources'.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: container-properties
test case: case.json

JLWSC-CP-5
type: Requirement
statement: SHOULD be exact, and MAY be approximate only when the approximation is computed exclusively from the caller-visible view — never derived from an unfiltered membership total, which would leak the existence of hidden members
comment: Subject of the fragment: totalItems. Operative sub-clause here is 'SHOULD be exact'; split — see JLWSC-CP-6.
requirement level: SHOULD
requirement subject: JLWS server
testability: Enforceable
anchor: container-properties
test gap: gap-deferred

JLWSC-CP-6
type: Requirement
statement: SHOULD be exact, and MAY be approximate only when the approximation is computed exclusively from the caller-visible view — never derived from an unfiltered membership total, which would leak the existence of hidden members
comment: Operative sub-clause here is the constrained MAY: how an approximation is computed is internal (a caller-visible-derived approximation is indistinguishable black-box from a leaky one), so accountability only.
requirement level: MAY
requirement subject: JLWS server
testability: AccountableExistence
anchor: container-properties

JLWSC-CMT-1
type: Requirement
statement: Container representations (and the storage description) MUST be available as application/ld+json; profile="https://w3id.org/jeswr/lws/v1".
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: container-media-type
test case: case.json

JLWSC-CMT-2
type: Requirement
statement: Servers MUST also answer requests for application/lws+json, application/ld+json, and application/json with the identical payload bytes — only the Content-Type header varies
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: container-media-type
test case: case.json

JLWSC-CMT-3
type: Requirement
statement: Servers MAY offer additional serialisations (e.g. text/turtle) via content negotiation
comment: The RDF Content Transformation companion makes exercised support advertisable and precise (its companion carries the exercised contract).
requirement level: MAY
requirement subject: JLWS server
testability: Premature
anchor: container-media-type
test gap: gap-pure-permission

JLWSC-PAG-1
type: Requirement
statement: Servers SHOULD paginate container listings whose membership exceeds a server-determined threshold.
requirement level: SHOULD
requirement subject: JLWS server
testability: Premature
anchor: pagination
test gap: gap-deployment-policy

JLWSC-PAG-2
type: Requirement
statement: paginated responses MUST carry rel="first", MUST carry rel="next" on all but the last page, MUST omit rel="next" on the last page, MAY carry rel="prev" and rel="last"
comment: Condition: the listing is paginated — a server-determined threshold the harness cannot force portably; vectorable for implementations exposing a threshold knob (GAPS.md). The keywordless 'Paginated responses use status 200.' and the whole-membership totalItems sentence ride with this rule.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: pagination
test gap: gap-deployment-policy

JLWSC-PAG-3
type: Requirement
statement: page URIs are opaque — clients SHOULD NOT construct or modify them.
requirement level: SHOULDNOT
requirement subject: JLWS client
testability: Premature
anchor: pagination
test gap: gap-client-conduct

JLWSC-MD-1
type: Requirement
statement: For each resource, the server MUST make its metadata available as a standalone linkset resource per !RFC9264, available as application/linkset+json, discoverable via a Link header with rel="linkset" on GET/HEAD responses.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata
test case: case.json

JLWSC-MD-2
type: Requirement
statement: Linkset updates MUST be atomic with the associated resource operations.
comment: Concurrency atomicity: exercisable only by nondeterministic race probing, not deterministic vectors — TLC-checked at the design level (formal/tla/JlwsContainment.tla models the membership-projection half: a resource operation and its metadata update in one step).
requirement level: MUST
requirement subject: JLWS server
testability: AccountableExistence
anchor: metadata
formal model: JlwsContainment.tla

JLWSC-MD-3
type: Requirement
statement: Deleting a resource MUST delete its linkset resource.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata
test case: case.json

JLWSC-MU-1
type: Requirement
statement: Servers MUST support PATCH on the linkset resource with application/merge-patch+json (!RFC7386) and MUST advertise it via Accept-Patch
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata-updates
test case: case.json

JLWSC-MU-2
type: Requirement
statement: PUT and additional patch formats are OPTIONAL and MUST be advertised via Allow / Accept-Patch when supported.
comment: Operative obligation: the advertisement duty when supported (the OPTIONAL half is a permission).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata-updates
test gap: gap-deferred

JLWSC-MU-3
type: Requirement
statement: Linkset GET/HEAD responses MUST carry an ETag; successful updates MUST rotate it.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata-updates
test case: case.json

JLWSC-MU-4
type: Requirement
statement: A PUT or PATCH on a linkset resource without If-Match MUST be rejected with 428 Precondition Required (!RFC6585); a stale If-Match MUST be rejected with 412 Precondition Failed.
comment: The linkset instance of the strict conditional-write discipline; lost-update freedom under it is TLC-checked (formal/tla/JlwsConditionalUpdate.tla).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata-updates
formal model: JlwsConditionalUpdate.tla
test case: case.json

JLWSC-MU-5
type: Requirement
statement: Servers MUST reject attempts to modify system-managed links (e.g. with a problem details response of type https://w3id.org/jeswr/lws/problems/system-managed-metadata).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: metadata-updates
test case: case.json

JLWSC-OP-1
type: Requirement
statement: is the only binding defined here and is REQUIRED for conformance
comment: Subject of the fragment: the HTTP binding (#http-binding); the sentence opens 'The HTTP binding in is …' — the empty ReSpec cross-reference vanishes in the normalized text. Meta-requirement: every HTTP-suite vector is its evidence.
requirement level: MUST
requirement subject: JLWS server
requirement subject: JLWS client
testability: Enforceable
anchor: operations
test gap: gap-meta

JLWSC-HG-1
type: Requirement
statement: Servers MUST implement HTTP semantics per !RFC9110 and SHOULD implement caching per !RFC9111.
comment: Operative sub-clause here is the RFC 9110 MUST; meta-requirement exercised by the whole suite.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-general
test gap: gap-meta

JLWSC-HG-2
type: Requirement
statement: Servers MUST implement HTTP semantics per !RFC9110 and SHOULD implement caching per !RFC9111.
comment: Operative sub-clause here is the RFC 9111 caching SHOULD (deployment policy, GAPS.md).
requirement level: SHOULD
requirement subject: JLWS server
testability: Premature
anchor: http-general
test gap: gap-deployment-policy

JLWSC-HG-3
type: Requirement
statement: Every GET/HEAD response for a storage resource MUST carry an ETag, the rel="linkset", rel="up" (non-root), and rel="type" links, and the storage-description link
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-general
test case: case.json

JLWSC-HG-4
type: Requirement
statement: These entity-tags MUST be strong
comment: A weak validator can never satisfy the If-Match strong-comparison discipline; not-W/-prefixed assertion + weak-If-Match rejection case is vectorable, deferred (GAPS.md).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-general
test gap: gap-deferred

JLWSC-HG-5
type: Requirement
statement: All 4xx and 5xx responses MUST carry an !RFC9457 problem details body (application/problem+json), except where HTTP semantics do not permit response content
comment: The sentence continues with the HEAD header-mirror and 304 carve-outs (the HEAD-error mirror vector is deferred — GAPS.md). Divergence D17: the Working Draft SHOULDs problem details.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-general
test case: case.json

JLWSC-HG-6
type: Requirement
statement: Storage-quota exhaustion MUST be reported as 507 Insufficient Storage.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-general
test case: case.json

JLWSC-HG-7
type: Requirement
statement: Servers MUST reject request targets containing path-traversal sequences (.., %2e%2e, and equivalents) before any authorization matching
comment: Only the rejection is black-box observable; the before-authorization ordering is internal (GAPS.md 'network/trust').
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-general
test case: case.json

JLWSC-POST-1
type: Requirement
statement: the server MAY decline the hint on conflict or naming policy.
comment: 'The hint' = the Slug header. The conflict half is pinned by containers/post-slug-conflict; the naming-policy trigger is a deployment choice.
requirement level: MAY
requirement subject: JLWS server
testability: Premature
anchor: http-create-post
test gap: gap-deployment-policy

JLWSC-POST-2
type: Requirement
statement: To create a container, the client MUST include Link: <https://w3id.org/jeswr/lws#Container>; rel="type"
requirement level: MUST
requirement subject: JLWS client
testability: Enforceable
anchor: http-create-post
test case: case.json

JLWSC-POST-3
type: Requirement
statement: the w3.org/ns/lws#Container alias MUST be accepted
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-post
test case: case.json
restates: JLWSC-NS-1

JLWSC-POST-4
type: Requirement
statement: server-managed metadata MUST be generated by the server and MUST NOT be overridable by client links.
comment: The preceding permission ('Clients MAY seed user-managed metadata via Link headers') rides this sentence; operative obligation here is the not-overridable rule.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-post
test gap: gap-deferred

JLWSC-POST-5
type: Requirement
statement: On success the server MUST return 201 Created with the new URI in Location and the rel="up", rel="linkset", and rel="type" links.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-post
test case: case.json

JLWSC-POST-6
type: Requirement
statement: Resource, metadata, and membership creation MUST be atomic.
comment: Concurrency atomicity; the sequential effects are pinned by the create vectors, the atomicity itself is not black-box observable — TLC-checked at the design level (formal/tla/JlwsContainment.tla).
requirement level: MUST
requirement subject: JLWS server
testability: AccountableExistence
anchor: http-create-post
formal model: JlwsContainment.tla

JLWSC-PUT-1
type: Requirement
statement: Servers MUST support creation by PUT to the desired resource URI carrying If-None-Match: *
comment: Divergence D2 (idempotent create). The keywordless 'On success: 201 Created, with the same links and atomicity requirements as POST-create.' rides this rule and is asserted by the vector.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-put
test case: case.json

JLWSC-PUT-2
type: Requirement
statement: the server MUST NOT auto-create intermediate containers
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-put
test case: case.json

JLWSC-PUT-3
type: Requirement
statement: MUST respond 409 Conflict (problem type …/problems/missing-parent) when the parent does not exist.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-put
test case: case.json

JLWSC-PUT-4
type: Requirement
statement: If the target already exists, the server MUST respond 412 Precondition Failed and MUST NOT modify the resource — making retries safe.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-put
test case: case.json

JLWSC-PUT-5
type: Requirement
statement: Creation via PUT MUST carry If-None-Match: *.
comment: Client-side duty; its server-side counterpart rejection is JLWSC-PUT-6 (vectored).
requirement level: MUST
requirement subject: JLWS client
testability: Enforceable
anchor: http-create-put
test gap: gap-client-conduct

JLWSC-PUT-6
type: Requirement
statement: when its target URI does not identify an existing resource, the server MUST respond 428 Precondition Required (!RFC6585) rather than create the resource.
comment: 'Its' = an unconditional PUT (one carrying neither If-None-Match: * nor If-Match) — never a create; with the existing-resource 428 rule (JLWSC-UPD-1), every PUT in JLWS is explicitly conditional.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-create-put
test case: case.json

JLWSC-PUT-7
type: Requirement
statement: A URI ending in / creates a container (the request body MUST be empty); otherwise a data resource is created from the body and Content-Type.
requirement level: MUST
requirement subject: JLWS server
requirement subject: JLWS client
testability: Enforceable
anchor: http-create-put
test case: case.json

JLWSC-RD-1
type: Requirement
statement: Servers MUST support range requests (!RFC9110 Section 14) for data resources.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-read
test case: case.json

JLWSC-RD-2
type: Requirement
statement: Servers MUST support HEAD, returning GET's headers without a body.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-read
test case: case.json

JLWSC-RD-3
type: Requirement
statement: Servers MUST support conditional GET (If-None-Match; If-Modified-Since) answering 304 Not Modified when applicable.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-read
test case: case.json

JLWSC-UPD-1
type: Requirement
statement: it MUST reject an unconditional PUT to an existing resource (one carrying neither If-Match nor If-None-Match: *) with 428 Precondition Required, and a stale If-Match with 412 Precondition Failed.
comment: 'It' = a server supporting ETags for the resource (which it MUST — JLWSC-HG-3). The content-resource stale-412 case is deferred; the linkset counterpart is vectored (JLWSC-MU-4). The rdf-transform suite re-pins the 428 rule on RDF-readable resources (unconditional-put-still-428). The lost-update threat this discipline closes is TLC-checked: formal/tla/JlwsConditionalUpdate.tla (NoLostUpdate holds under StrictSpec; a server accepting unconditional overwrites is refuted in three steps).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-update
formal model: JlwsConditionalUpdate.tla
test case: case.json

JLWSC-UPD-2
type: Requirement
statement: Servers MUST support application/merge-patch+json (!RFC7386) for JSON-family data resources and for linkset resources
comment: The linkset half is vectored (JLWSC-MU-1); the JSON-family content-PATCH half is deferred.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-update
test case: case.json
test gap: gap-deferred

JLWSC-UPD-3
type: Requirement
statement: support for further formats (per media type) MUST be advertised via Accept-Patch and the PatchSupport capability
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-update
test case: case.json

JLWSC-UPD-4
type: Requirement
statement: RDF patch formats are defined by the RDF Content Transformation companion and MUST NOT be advertised without it.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: http-update
test case: case.json

JLWSC-UPD-5
type: Requirement
statement: PUT/PATCH on a resource URI modifies content only, never the linkset, except under the explicit Prefer: set-linkset mechanism of LWS10-CORE Update Resource, which servers MAY implement.
comment: Operative keyword is the MAY (Prefer: set-linkset optional); the content-only/never-the-linkset separation is the sentence's keywordless body. The Prefer mechanism vector is deferred (GAPS.md).
requirement level: MAY
requirement subject: JLWS server
testability: Enforceable
anchor: http-update
test gap: gap-deferred

JLWSC-DEL-1
type: Requirement
statement: The parent container's ETag MUST change.
comment: Condition: a successful DELETE ('DELETE removes a resource, its linkset, and its membership entry atomically; on success 204 No Content.' — the removal effects are pinned by the same vector and JLWSC-MD-3).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-delete
test case: case.json

JLWSC-DEL-2
type: Requirement
statement: DELETE on a non-empty container without recursion MUST be rejected with 409 Conflict.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-delete
test case: case.json

JLWSC-DEL-3
type: Requirement
statement: servers advertising the RecursiveDelete capability MUST honour it, deleting the subtree atomically.
comment: The preceding 'Servers MAY support recursive deletion; clients request it with Depth: infinity (!RFC4918)' permission rides this rule.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-delete
test case: case.json

JLWSC-DEL-4
type: Requirement
statement: Clients MAY (and SHOULD, for guarded deletes) send If-Match; servers MUST honour it.
comment: Operative obligation: servers MUST honour a DELETE If-Match. Guarded-delete vector deferred.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-delete
test gap: gap-deferred

JLWSC-MV-1
type: Requirement
statement: Servers advertising the MoveResource capability MUST implement move as follows
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-move
test case: case.json

JLWSC-MV-2
type: Requirement
statement: On success the server MUST: (a) assign the resource a new URI path-aligned under the destination container, preserving the final path segment unless it conflicts; (b) atomically update both containers' membership; (c) respond 200 with the new URI in Location; and (d) SHOULD answer subsequent requests for the old URI with 308 Permanent Redirect for an implementation-defined period.
comment: Operative sub-clauses here are the MUSTs (a)-(c); the (d) SHOULD is split as JLWSC-MV-3.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: http-move
test case: case.json

JLWSC-MV-3
type: Requirement
statement: On success the server MUST: (a) assign the resource a new URI path-aligned under the destination container, preserving the final path segment unless it conflicts; (b) atomically update both containers' membership; (c) respond 200 with the new URI in Location; and (d) SHOULD answer subsequent requests for the old URI with 308 Permanent Redirect for an implementation-defined period.
comment: Operative sub-clause here is (d): the 308 window is implementation-defined and temporal (GAPS.md 'stateful/temporal + deployment-policy').
requirement level: SHOULD
requirement subject: JLWS server
testability: Premature
anchor: http-move
test gap: gap-deployment-policy

JLWSC-CRED-1
type: Requirement
statement: An authentication credential MUST include tamper-evident claims:
comment: The REQUIRED claims enumerated by the following list: subject (absolute URI of the agent), issuer (absolute URI of the issuing entity), client (identifier for the client application). The WebAuthn suite's credential serialization is exercised by the linked wire-contract decode vectors; suite-generic credential-shape cases (self-signed CID, did:key) are deferred (GAPS.md).
requirement level: MUST
requirement subject: authentication credential
testability: Enforceable
anchor: credential-model
test case: case.json
test gap: gap-deferred

JLWSC-CRED-2
type: Requirement
statement: audience restriction (RECOMMENDED) — a list of values that SHOULD include an authorization server identifier.
requirement level: SHOULD
requirement subject: authentication credential
testability: Enforceable
anchor: credential-model
test gap: gap-deferred

JLWSC-CRED-3
type: Requirement
statement: A credential MUST be signed
requirement level: MUST
requirement subject: authentication credential
testability: Enforceable
anchor: credential-model
test gap: gap-deferred

JLWSC-CRED-4
type: Requirement
statement: JWT-serialised credentials MUST NOT use the none algorithm.
comment: The linked vector pins the same rule at the access-token validation seam (alg none rejected); a credential-side case is part of the deferred suite-validation tranche.
requirement level: MUSTNOT
requirement subject: authentication credential
testability: Enforceable
anchor: credential-model
test case: case.json

JLWSC-CRED-5
type: Requirement
statement: asymmetric signatures are RECOMMENDED
requirement level: SHOULD
requirement subject: authentication credential
testability: Enforceable
anchor: credential-model
test gap: gap-deferred

JLWSC-CRED-6
type: Requirement
statement: Each authentication suite MUST be associated with a token-type URI, preferably one registered in the IANA OAuth URI registry
comment: A constraint on suite definitions (the four shipped suites each declare theirs); auditable against the suite texts rather than a wire exchange.
requirement level: MUST
requirement subject: JLWS authorization server
testability: AccountableExistence
anchor: credential-model

JLWSC-CRED-7
type: Requirement
statement: authorization servers SHOULD advertise supported suites via subject_token_types_supported in their RFC 8414 metadata
comment: SHOULD rather than MUST for the privacy reason in #privacy-considerations (a self-hosting individual may not wish to advertise their authentication technology).
requirement level: SHOULD
requirement subject: JLWS authorization server
testability: Enforceable
anchor: credential-model
test case: case.json

JLWSC-ID-1
type: Requirement
statement: In the absence of a pre-existing trust relationship, a verifier MUST dereference the credential's subject URI and obtain a valid CID whose id equals the subject identifier
comment: Suite validation dereferences live documents (GAPS.md 'network/trust'); the self-signed-CID and did:key offline-verifiable halves are a deferred tranche.
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: identity-documents
test gap: gap-network-trust

JLWSC-ID-2
type: Requirement
statement: Verifiers SHOULD cache CID-derived keys respecting HTTP caching metadata
requirement level: SHOULD
requirement subject: JLWS authorization server
testability: AccountableExistence
comment: Caching behaviour spans observations over time (GAPS.md 'network/trust + stateful').
anchor: identity-documents

JLWSC-SUITE-1
type: Requirement
statement: a conforming JLWS authorization server MUST implement at least one.
comment: 'One' = an authentication suite. Evidenced functionally by any successful suite-authenticated exchange; the exchange vectors abstract the credential as pre-validated, so a live-suite case is deferred.
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: suites
test gap: gap-network-trust

JLWSC-SUITE-WA-1
type: Requirement
statement: the authorization server validates the assertion against the credential public key registered for the subject and MUST enforce challenge freshness, origin/RP-ID binding, and signature-counter or device-attestation policy per WebAuthn Level 3.
comment: The OP-side verification matrix (origin/RP-ID binding, signCount policy, challenge freshness/replay) belongs to solid-webauthn-reauth-spec's planned vectors (GAPS.md); the wire-contract decode is pinned here (see JLWSC-CRED-1's vectors), and the issued-token PoP-binding consequence by the linked case.
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: suite-webauthn
test case: case.json
test gap: gap-network-trust

JLWSC-CLID-1
type: Requirement
statement: Client identifiers SHOULD be absolute URIs dereferencing to an OAuth Client ID Metadata Document
comment: Divergence D8 (plain-JSON client documents replace Solid-OIDC's JSON-LD CIDs). Accept/reject document-shape cases are vectorable, deferred (GAPS.md).
requirement level: SHOULD
requirement subject: JLWS client
testability: Enforceable
anchor: client-identity
test gap: gap-deferred

JLWSC-AD-1
type: Requirement
statement: A storage server generating a 401 Unauthorized response MUST send a WWW-Authenticate challenge containing:
comment: The REQUIRED members enumerated by the following list: resource_metadata (the RFC 9728 §5.1 metadata URI) and realm (an absolute URI indicating the scope of protection — the token-exchange resource parameter and the access token's aud).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: authz-discovery
test case: case.json

JLWSC-AD-2
type: Requirement
statement: A client MUST verify that the URI of the originating request is logically contained within the presented realm before using it
requirement level: MUST
requirement subject: JLWS client
testability: Enforceable
anchor: authz-discovery
test case: case.json

JLWSC-AD-3
type: Requirement
statement: a challenge answering a request that bore no credentials — as in the example above — MUST NOT include an error parameter.
comment: RFC 6750 §3.1 discipline; the positive half (error carried only for a rejected presented token) is keywordless incorporation — see the extraction notes — and pinned by auth/challenge-rejected-token-error.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: authz-discovery
test case: case.json

JLWSC-AD-4
type: Requirement
statement: The protected resource metadata document (!RFC9728 Section 2) MUST include resource and authorization_servers (the trusted authorization servers — the storage server manages this canonical list), and MUST include the extension member jlws_storage_description: the URI of the storage description resource.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: authz-discovery
test case: case.json

JLWSC-AD-5
type: Requirement
statement: Authorization server metadata is served per !RFC8414 at its registered well-known URI (/.well-known/oauth-authorization-server), and SHOULD include subject_token_types_supported listing the authentication suites accepted at the token endpoint.
requirement level: SHOULD
requirement subject: JLWS authorization server
testability: Enforceable
anchor: authz-discovery
test case: case.json
restates: JLWSC-CRED-7

JLWSC-TE-1
type: Requirement
statement: The authorization server's token endpoint MUST support urn:ietf:params:oauth:grant-type:token-exchange
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: token-exchange
test case: case.json

JLWSC-TE-2
type: Requirement
statement: The resource parameter is REQUIRED, MUST be an absolute URI, populates the access token's aud, and equals the challenge's realm.
requirement level: MUST
requirement subject: JLWS authorization server
requirement subject: JLWS client
testability: Enforceable
anchor: token-exchange
test case: case.json

JLWSC-TE-3
type: Requirement
statement: The authorization server MUST reject a resource identifying an unknown or untrusted storage.
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: token-exchange
test case: case.json

JLWSC-TE-4
type: Requirement
statement: The subject_token parameter is REQUIRED and carries a valid authentication credential; subject_token_type names its suite.
requirement level: MUST
requirement subject: JLWS client
requirement subject: JLWS authorization server
testability: Enforceable
anchor: token-exchange
test case: case.json

JLWSC-TE-5
type: Requirement
statement: The authorization server MUST validate all presented tokens before issuing.
comment: Subject-token validation is suite-specific and dereferences live documents (GAPS.md 'network/trust'); the resource-parameter handling is pinned separately (JLWSC-TE-2/3).
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: token-exchange
test gap: gap-network-trust

JLWSC-AT-1
type: Requirement
statement: The issued access token MUST conform to !RFC9068 (at+jwt) with:
comment: The REQUIRED claims enumerated by the following list: sub, iss, client_id, aud (exactly one value — JLWSC-AT-2), exp, iat, jti.
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: access-token
test case: case.json

JLWSC-AT-2
type: Requirement
statement: aud — REQUIRED; exactly one value: the absolute URI supplied as resource.
comment: Divergence D11: single-valued aud everywhere for access tokens (where the replay risk lives).
requirement level: MUST
requirement subject: JLWS authorization server
testability: Enforceable
anchor: access-token
test case: case.json

JLWSC-AT-3
type: Requirement
statement: a suite's subject token, e.g. an OIDC ID token, may carry multi-valued aud as its suite specifies, and MUST NOT be rejected for that.
comment: The single-aud constraint binds ACCESS tokens, not authentication credentials; a multi-aud subject-token acceptance case is deferred.
requirement level: MUSTNOT
requirement subject: JLWS authorization server
testability: Enforceable
anchor: access-token
test gap: gap-deferred

JLWSC-AT-4
type: Requirement
statement: exp — REQUIRED; lifetimes of 300 seconds or less are RECOMMENDED;
comment: Operative sub-clause here is the RECOMMENDED lifetime ceiling (the exp REQUIRED half is part of JLWSC-AT-1's claim list).
requirement level: SHOULD
requirement subject: JLWS authorization server
testability: Enforceable
anchor: access-token
test case: case.json

JLWSC-RAR-1
type: Requirement
statement: Authorization servers MAY evaluate fine-grained requests and encode the decision in an authorization_details claim
comment: RFC 9396 rich authorization (divergence D16), with the approved/deferred duality; the exercised contract is pinned by the linked cases.
requirement level: MAY
requirement subject: JLWS authorization server
testability: Enforceable
anchor: rar
test case: case.json

JLWSC-RAR-2
type: Requirement
statement: A storage server MUST NOT treat an authorization_details claim as widening access beyond its own policy: the claim can only narrow.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: rar
test case: case.json

JLWSC-PB-1
type: Requirement
statement: A JLWS server MUST accept Bearer presentation for every realm except one it has designated proof-of-possession-required
comment: The Bearer baseline (design principle 3 / divergence D9): PoP is negotiated on top, never a reversal.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: presentation-bearer
test case: case.json

JLWSC-PP-1
type: Requirement
statement: A server MAY additionally offer sender-constrained presentation, advertised through its RFC 9728 protected resource metadata
comment: The two defined profiles are DPoP (RFC 9449) and DPoP-SK; their own normative statements are companioned in dpop-sk-spec's companion, and the composed surface is pinned by the dpop-sk vector suite here.
requirement level: MAY
requirement subject: PoP-capable server
testability: Enforceable
anchor: presentation-pop
test case: case.json

JLWSC-PP-2
type: Requirement
statement: A server MAY, by deployment policy, require a proof-of-possession profile for a designated realm
requirement level: MAY
requirement subject: PoP-capable server
testability: Premature
comment: Deployment-policy permission; its concrete signal when exercised is JLWSC-PP-3/4 (vectored).
anchor: presentation-pop
test gap: gap-deployment-policy

JLWSC-PP-3
type: Requirement
statement: the realm's protected resource metadata MUST set dpop_bound_access_tokens_required: true
comment: Condition: the realm is designated PoP-required. The same member governs DPoP-SK (established FROM a DPoP-bound token), so no separate required-member exists.
requirement level: MUST
requirement subject: PoP-capable server
testability: Enforceable
anchor: presentation-pop
test case: case.json

JLWSC-PP-4
type: Requirement
statement: The realm's 401 challenges MUST list only the required profile's scheme(s) (e.g. WWW-Authenticate: DPoP … per !RFC9449 Section 7.1), omitting the Bearer scheme.
requirement level: MUST
requirement subject: PoP-capable server
testability: Enforceable
anchor: presentation-pop
test case: case.json

JLWSC-RSV-1
type: Requirement
statement: A storage server MUST validate a presented access token by, in order (jeswr/lws-keycloak spec/authz.md §4.4.2): Signature — verify the JWT signature against the authorization server's JWKS (from its RFC 8414 metadata); cache keys; support rotation; reject alg: none and unexpected algorithms.
comment: The lead-in MUST governs the ordered list; step 1 (Signature) carries no keyword of its own, so the quote spans lead-in + step. JWKS caching / key rotation are stateful network behaviour (GAPS.md); the rejection halves are vectored.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-2
type: Requirement
statement: iss MUST match a member of the storage server's explicit trusted-issuer allowlist
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-3
type: Requirement
statement: aud MUST contain exactly one value, an absolute URI that logically contains the target resource.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-4
type: Requirement
statement: Logical containment is evaluated over parsed, normalized URIs (!RFC3986 Section 6) — never by raw string prefix: the audience and the target MUST have the same origin (scheme, host, port), and the audience's path MUST equal the target's path or be an ancestor of it on complete /-delimited segment boundaries.
comment: The segment-boundary rule that defeats the …/alicemalicious sibling trap; security-critical.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-5
type: Requirement
statement: Multi-tenant deployments MUST scope acceptance to the current storage (the tenant-replay rule, spec/authz.md §7.5.1).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-6
type: Requirement
statement: Temporal — exp in the future, nbf (if present) passed, iat not in the future; clock skew tolerance of at most 60 seconds is RECOMMENDED; tokens with exp more than one hour ahead MUST be rejected.
comment: Operative sub-clauses here are the temporal checks (governed by the JLWSC-RSV-1 lead-in MUST) and the one-hour-exp MUST; the skew RECOMMENDED is split as JLWSC-RSV-7.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-7
type: Requirement
statement: Temporal — exp in the future, nbf (if present) passed, iat not in the future; clock skew tolerance of at most 60 seconds is RECOMMENDED; tokens with exp more than one hour ahead MUST be rejected.
comment: Operative sub-clause here is the ≤60 s clock-skew RECOMMENDED.
requirement level: SHOULD
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test gap: gap-deferred

JLWSC-RSV-8
type: Requirement
statement: when the token is PoP-bound (cnf present), the corresponding proof MUST be validated per the profile in use, and the token MUST NOT be accepted bare.
comment: Operative sub-clause here is the proof-validation MUST; the plain-DPoP proof matrix is RFC 9449's own test surface (GAPS.md), and the DPoP-SK attestation matrix is pinned by the dpop-sk suite (linked).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-RSV-9
type: Requirement
statement: when the token is PoP-bound (cnf present), the corresponding proof MUST be validated per the profile in use, and the token MUST NOT be accepted bare.
comment: Operative sub-clause here is 'the token MUST NOT be accepted bare' — the Bearer baseline is never weakened by a PoP binding.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: rs-validation
test case: case.json

JLWSC-CR-1
type: Requirement
statement: A client MUST verify realm containment before requesting a token for it
requirement level: MUST
requirement subject: JLWS client
testability: Enforceable
anchor: client-rules
test case: case.json
restates: JLWSC-AD-2

JLWSC-CR-2
type: Requirement
statement: A client MUST NOT present a token whose aud does not logically contain the target resource, MUST NOT present a token with more than one aud value, and SHOULD NOT share a token with any party other than the storage server it is scoped to.
comment: Operative sub-clauses here are the two MUST NOTs (presentation discipline). Client conduct is auditable against a client-under-test transcript; the server-side counterparts are JLWSC-RSV-3 (vectored).
requirement level: MUSTNOT
requirement subject: JLWS client
testability: AccountableExistence
anchor: client-rules

JLWSC-CR-3
type: Requirement
statement: A client MUST NOT present a token whose aud does not logically contain the target resource, MUST NOT present a token with more than one aud value, and SHOULD NOT share a token with any party other than the storage server it is scoped to.
comment: Operative sub-clause here is the SHOULD NOT (token sharing) — not wire-observable at all.
requirement level: SHOULDNOT
requirement subject: JLWS client
testability: Premature
anchor: client-rules
test gap: gap-client-conduct

JLWSC-CR-4
type: Requirement
statement: A client SHOULD NOT proactively obtain tokens from an authorization server before receiving a 401 challenge for a resource in that realm
comment: Defence against the colluding-RS/AS intent probe (#sec-collusion); auditable against a client transcript.
requirement level: SHOULDNOT
requirement subject: JLWS client
testability: AccountableExistence
anchor: client-rules

JLWSC-CR-5
type: Requirement
statement: Clients SHOULD cache tokens and reuse them proactively for further resources logically contained in the token's aud during its lifetime.
requirement level: SHOULD
requirement subject: JLWS client
testability: AccountableExistence
anchor: client-rules

JLWSC-ODRL-1
type: Requirement
statement: Documents are JSON-LD using the ODRL context plus the JLWS context, and MUST declare profile equal to https://w3id.org/jeswr/lws/access-profile/odrl-1
comment: Per PR #109, an unprofiled ODRL document is not a conforming access document.
requirement level: MUST
requirement subject: access document (ODRL request/grant)
testability: Enforceable
anchor: odrl-profile
test case: case.json

JLWSC-ODRL-2
type: Requirement
statement: Each rule MUST have exactly one action and exactly one target
comment: Singular per rule (PR #109); compose multiple rules for multiple actions/targets.
requirement level: MUST
requirement subject: access document (ODRL request/grant)
testability: Enforceable
anchor: odrl-profile
test case: case.json

JLWSC-ODRL-3
type: Requirement
statement: The inclusion is one-directional: a grant of odrl:modify also permits the narrower jlws:create and jlws:append operations, but a create-only or append-only grant MUST NOT be widened to modify.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-ODRL-4
type: Requirement
statement: An enforcement layer that does not understand a profile-defined action MUST NOT honour a rule granting it (fail closed — an unknown action grants nothing)
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-ODRL-5
type: Requirement
statement: When multiple constraints are present, all MUST be satisfied.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-ODRL-6
type: Requirement
statement: An enforcement layer that cannot evaluate a constraint MUST treat it as unsatisfied (fail closed).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-ODRL-7
type: Requirement
statement: A server's enforcement MUST compute access decisions equivalent to the rule set: a request is permitted exactly when at least one recorded grant derives a permit justification for it, and denied otherwise — deny is the closed-world absence of any permit derivation at decision time (default deny).
comment: The rule set semantics/access-decision.n3 is the profile's normative, executable decision function (Notation3, run under EYE); test-suite/tools/oracle-access.mjs executes it over every evaluate-access vector and the two must never disagree. This gives the target-matcher and public-assignee semantics (formerly a keywordless-definitional-prose extraction note) normative force through the rule set.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-ODRL-8
type: Requirement
statement: A prohibition rule that matches the request MUST deny the request under that grant, regardless of an otherwise-matching permission of the same grant.
comment: Decision-time composition of a grant carrying odrl:prohibition alongside odrl:permission (semantics/access-decision.n3 rules M/N/D). Matching uses the identical assignee/action/target/constraint predicates a permission match uses (rule M), so a prohibition of a DIFFERENT assignee/action/target, or with one of its own constraints unsatisfied, does not participate — obligation-for-different-action-not-blocking pins the analogous non-matching case for obligation; the suite has no matching-scope negative case of its own for prohibition beyond the adversarial regression probes in test-suite/test/access-oracle.test.mjs (non-vectored per the harness's evaluate-access-is-oracle-reproduced discipline). Composition is per grant, never global — a prohibition recorded in a different grant does not affect this grant's permit derivation, matching the per-grant structure of revocation (JLWSC-GR-5).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-ODRL-9
type: Requirement
statement: An obligation rule that matches the request MUST make the matching permission of the same grant not exercisable; this profile version defines no wire representation of duty fulfilment, so a matching obligation MUST always be treated as unverifiable at decision time.
comment: Decision-time composition of a grant carrying odrl:obligation alongside odrl:permission (semantics/access-decision.n3 rules M/O/D); matching uses the same rule-M predicates as prohibition (JLWSC-ODRL-8) and permission. Because no field of the document shape asserts a duty was performed, EVERY matching obligation is unmet under this profile version — unmet-obligation-fail-closed pins the positive (blocking) case, obligation-for-different-action-not-blocking pins that a non-matching obligation of the same grant does not participate (composition is scoped by matching, not a blanket veto on the grant carrying the rule kind). Duty-fulfilment/discharge tracking itself remains an unrepresented gap for a future profile version (test-vectors/GAPS.md).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: odrl-profile
formal model: access-decision.n3
test case: case.json

JLWSC-GE-1
type: Requirement
statement: Servers SHOULD deliver notification of new requests and of grant creation/revocation to the affected agents' inboxes or subscriptions
comment: Behavioural emission (GAPS.md): what a server publishes as a side effect, auditable rather than vectorable.
requirement level: SHOULD
requirement subject: JLWS server
testability: AccountableExistence
anchor: grant-endpoints

JLWSC-GR-1
type: Requirement
statement: A grant records what the storage controller decided; the server MUST realise that decision in its internal enforcement:
comment: Grants are records, not tokens (never presented as authorization tokens); the record binds observable behaviour, not internals.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: grants-are-records
formal model: access-decision.n3
test case: case.json

JLWSC-GR-2
type: Requirement
statement: Grant creation and revocation MUST be reflected in that decision state within a bounded, documented interval (SHOULD be immediate), and MUST be reflected before the server acknowledges the operation that changed the grant record
comment: Operative sub-clauses here are the bounded-documented-interval MUST (the bound is a documented artifact — audit; the reflection temporal) and the acknowledgment barrier (reflection completes before the grant operation's response returns — creation and revocation alike). TLC-checked at the design level: formal/tla/JlwsRevocation.tla SingleClockSpec (BoundedStaleness + StalenessConverges for the interval; AckCreate/AckRevoke gated on the decision state, AckedCreateReflected + NoUseAfterAckedRevocation for the barrier).
requirement level: MUST
requirement subject: JLWS server
testability: AccountableExistence
anchor: grants-are-records
formal model: JlwsRevocation.tla

JLWSC-GR-3
type: Requirement
statement: Grant creation and revocation MUST be reflected in that decision state within a bounded, documented interval (SHOULD be immediate), and MUST be reflected before the server acknowledges the operation that changed the grant record
comment: Operative sub-clause here is the SHOULD-be-immediate recommendation (the formal model's Bound = 0).
requirement level: SHOULD
requirement subject: JLWS server
testability: AccountableExistence
anchor: grants-are-records
formal model: JlwsRevocation.tla

JLWSC-GR-4
type: Requirement
statement: Request enforcement and every derived view — container listings, totalItems, type indexes, query results, notification delivery filtering — MUST evaluate against the same decision state
comment: The single-clock rule (the LWS-SEARCHINDEX-ED live-authorization rule generalised to every authorization-observing surface). Replaces the TLC-refuted two-clocks predecessor text (enforcement bounded-interval vs derived-views immediate), whose split-clock window contradicted oracle-freedom — DECISIONS.md D22; formal/tla/JlwsRevocation.tla (NoOracleWindow violated on SplitClockSpec, SurfacesAgree by construction on SingleClockSpec). Temporal (GAPS.md 'stateful/temporal'); the steady-state enforcement half is pinned by the listing/oracle vectors (JLWSC-MA-2, JLWSC-OF-2).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: grants-are-records
formal model: JlwsRevocation.tla
test gap: gap-stateful-temporal

JLWSC-GR-6
type: Requirement
statement: A grant change MUST NOT be observable through one surface while another surface still answers from the prior state.
comment: The no-split-clock-window rule — the observable half of JLWSC-GR-4. TLC exhibits the forbidden window under the refuted predecessor discipline (formal/tla/JlwsRevocation-window.cfg: CreateImmediateAck, Propagate, RevokeImmediateAck reaches directly-readable-but-already-delisted; -createack.cfg shows the creation-direction twin) and the single-clock discipline excludes it by construction.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: grants-are-records
formal model: JlwsRevocation.tla
test gap: gap-stateful-temporal

JLWSC-GR-7
type: Requirement
statement: after a revocation is acknowledged, the server MUST NOT honor any request on the authority of the revoked grant and MUST NOT expose through any derived view what only that grant made visible
comment: The acknowledgment barrier: the response to the grant-record operation is the synchronization point, so a confirmed revocation means revoked on every surface. TLC-checked (NoUseAfterAckedRevocation and AckedNeverEnforced hold on SingleClockSpec; the predecessor immediate-ack discipline violates both — formal/tla/JlwsRevocation-ackwindow.cfg).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: grants-are-records
formal model: JlwsRevocation.tla
test gap: gap-stateful-temporal

JLWSC-GR-5
type: Requirement
statement: Enforcement composes over the whole record: revoking one grant MUST NOT deny a request that another recorded grant still permits — deny is the closed-world absence, at decision time, of every covering grant
comment: Structural revocation composition: under the decision function (JLWSC-ODRL-7 / semantics/access-decision.n3) a permit is derivable from ANY recorded grant, so revocation removes one justification, never the composition. The naive reading 'revocation implies denial' is not expressible in the rule set, and TLC refutes it as an action property (NaiveRevocationDenies, formal/tla/JlwsRevocation-naive.cfg — the counterexample is the revoke-one-covering-grant-still-permitted vector).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: grants-are-records
formal model: access-decision.n3
formal model: JlwsRevocation.tla
test case: case.json

JLWSC-VC-1
type: Requirement
statement: A storage controller MAY issue an access grant additionally as a W3C Verifiable Credential
requirement level: MAY
requirement subject: storage controller
testability: Premature
anchor: consent-receipts
test gap: gap-pure-permission

JLWSC-VC-2
type: Requirement
statement: Revocation of the grant MUST be reflected in the credential's status mechanism.
comment: Condition: the VC consent-receipt option is exercised. Status-mechanism reflection is deterministic once issued; vector deferred.
requirement level: MUST
requirement subject: JLWS server
requirement subject: storage controller
testability: Enforceable
anchor: consent-receipts
test gap: gap-deferred

JLWSC-DLG-1
type: Requirement
statement: Servers MAY support delegated grants
requirement level: MAY
requirement subject: JLWS server
testability: Premature
anchor: delegation
test gap: gap-pure-permission

JLWSC-DLG-2
type: Requirement
statement: a delegated grant MUST NOT exceed its parent in actions, targets, constraints, or duration
comment: Condition: delegation is supported. Chain semantics (monotonic narrowing, expiry/revocation propagation, cycle rejection) follow the delegation-chain model implemented in SOLID-ODRL; covered by the solid-odrl delegation vectors in agentic-solid-conformance, adopted by reference (spec #test-vectors appendix).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: delegation
test case: odrl-delegation

JLWSC-GRP-1
type: Requirement
statement: Servers MAY advertise a GroupService
requirement level: MAY
requirement subject: JLWS server
testability: Premature
anchor: groups
test gap: gap-pure-permission

JLWSC-GRP-2
type: Requirement
statement: membership changes MUST take effect like grant changes
comment: Condition: a GroupService is advertised. Group-semantics vectors are deferred.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: groups
test gap: gap-deferred

JLWSC-GRP-3
type: Requirement
statement: Cyclic group membership MUST be rejected.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: groups
test gap: gap-deferred

JLWSC-DB-1
type: Requirement
statement: All responses to GET and HEAD requests targeting storage resources MUST include a Link header targeting the storage description with rel="https://w3id.org/jeswr/lws#storageDescription"
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: discovery-binding
test case: case.json

JLWSC-DB-2
type: Requirement
statement: servers SHOULD include it on 401 responses to guide unauthenticated clients
comment: 'It' = the storage-description Link header.
requirement level: SHOULD
requirement subject: JLWS server
testability: Enforceable
anchor: discovery-binding
test gap: gap-deferred

JLWSC-DB-3
type: Requirement
statement: The document MUST be readable by any agent that can read the storage root, and MAY be public.
comment: 'The document' = the storage description resource.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: discovery-binding
test gap: gap-deferred

JLWSC-DB-4
type: Requirement
statement: the verificationMethod key material that notification keyid values resolve to MUST nonetheless be fetchable without storage credentials
comment: Condition: the storage description is not public AND the storage delivers signed webhook notifications. 'A webhook receiver is not a storage client and cannot be assumed to hold read access; a signature it cannot verify is a signature it will be tempted to skip.'
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: discovery-binding
test gap: gap-deployment-policy

JLWSC-DM-1
type: Requirement
statement: id — REQUIRED; the storage's URI;
requirement level: MUST
requirement subject: storage description document
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-DM-2
type: Requirement
statement: type — REQUIRED; includes Storage;
requirement level: MUST
requirement subject: storage description document
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-DM-3
type: Requirement
statement: conformsTo — REQUIRED; an array of protocol version URIs the storage implements
comment: Convention adopted from fedreg:StorageDescription (FEDREG) — federations can index JLWS storages natively.
requirement level: MUST
requirement subject: storage description document
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-DM-4
type: Requirement
statement: service — REQUIRED; a set of {id?, type, serviceEndpoint, …} entries, including one of type StorageDescription whose serviceEndpoint is the document's own URL;
comment: Extension services use absolute URIs; the a2a-rdf AgentInteractionService entry is the vectored extension example (consumption fail-closes on a non-https endpoint — see JLWSC-SSRF-1).
requirement level: MUST
requirement subject: storage description document
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-DM-5
type: Requirement
statement: verificationMethod — OPTIONAL (REQUIRED for notification servers); the storage's signing keys as !CID-1.0 verification methods
comment: Operative obligation: REQUIRED for notification servers (webhook signature keyid values resolve into this set).
requirement level: MUST
requirement subject: storage description document
requirement subject: notification server
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-DM-6
type: Requirement
statement: Consumers MUST ignore unrecognised capability and service types (forward compatibility).
requirement level: MUST
requirement subject: JLWS client
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-DM-7
type: Requirement
statement: The document MUST validate as a controlled identifier document when verificationMethod is present.
requirement level: MUST
requirement subject: storage description document
testability: Enforceable
anchor: discovery-model
test case: case.json

JLWSC-SUB-1
type: Requirement
statement: The server MUST reject a subscription whose agent lacks read access to every topic
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: subscription-api
test case: case.json

JLWSC-SUB-2
type: Requirement
statement: if the subscriber's read access to a topic is revoked, deliveries for it MUST cease from the same decision state that request enforcement observes
comment: Authorization is enforced at subscription AND delivery time; cessation spans observations over a live channel (GAPS.md 'stateful/temporal'). Delivery filtering is one of the derived surfaces on the #grants-are-records single clock (D22), so the two-clocks window is excluded here too — TLC-checked via formal/tla/JlwsRevocation.tla (the model's derived-view surface abstracts over listings, query results, and delivery filtering alike).
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: subscription-api
formal model: JlwsRevocation.tla
test gap: gap-stateful-temporal

JLWSC-SUB-3
type: Requirement
statement: topic — REQUIRED array of resource URIs
comment: The subscription-creation body contract (authenticated POST to the NotificationService endpoint; type = an advertised subscription type; expires OPTIONAL). The linked binding cases create subscriptions and assert the response contract; the keywordless source/receiveFrom member rules ride them (see the extraction notes).
requirement level: MUST
requirement subject: JLWS client
requirement subject: notification server
testability: Enforceable
anchor: subscription-api
test case: case.json

JLWSC-ENV-1
type: Requirement
statement: Notifications MUST NOT include resource content.
comment: The envelope wraps an AS2 Create/Update/Delete whose object carries the affected resource's id and type only (keywordless shape, asserted by notifications/envelope-valid).
requirement level: MUSTNOT
requirement subject: notification server
testability: Enforceable
anchor: notification-envelope
test case: case.json

JLWSC-ENV-2
type: Requirement
statement: published is REQUIRED; actor MUST be omitted unless the subscriber is authorised to learn it (privacy default of LWS-NOTIFICATIONS-ED).
comment: Operative sub-clause here is 'published is REQUIRED'.
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: notification-envelope
test case: case.json

JLWSC-ENV-3
type: Requirement
statement: published is REQUIRED; actor MUST be omitted unless the subscriber is authorised to learn it (privacy default of LWS-NOTIFICATIONS-ED).
comment: Operative sub-clause here is the actor privacy default.
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: notification-envelope
test case: case.json

JLWSC-ENV-4
type: Requirement
statement: Servers MAY batch multiple activities per delivery.
requirement level: MAY
requirement subject: notification server
testability: Premature
anchor: notification-envelope
test gap: gap-pure-permission

JLWSC-WH-1
type: Requirement
statement: Deliveries MUST be signed with HTTP Message Signatures !RFC9421 covering at least @method, @scheme/@authority/@path (or @target-uri), content-type, and content-digest (!RFC9530).
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: webhook-binding
test case: case.json

JLWSC-WH-2
type: Requirement
statement: The signature's keyid MUST be a URL-with-fragment resolving into the storage description's verificationMethod set
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: webhook-binding
test case: case.json

JLWSC-WH-3
type: Requirement
statement: receivers MUST verify the signature before processing
comment: The receiver-side fetch of the storage description is subject to #ssrf (the sentence's tail embeds a ReSpec cross-reference).
requirement level: MUST
requirement subject: webhook receiver
testability: Enforceable
anchor: webhook-binding
test case: case.json

JLWSC-SSE-1
type: Requirement
statement: the server MUST support at least one of, and the subscription response states which apply
comment: 'At least one of' = the two stream-authentication modes (header mode; capability-URL mode). Streaming behaviour (GAPS.md 'stateful/temporal').
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: sse-binding
test gap: gap-stateful-temporal

JLWSC-SSE-2
type: Requirement
statement: It MUST be bound to the subscription, MUST expire no later than the subscription, MUST be revoked with it, and MUST only be issued over TLS.
comment: 'It' = the capability-URL-mode source URL (single-subscription, unguessable, ≥128 bits of entropy, expiring). The WebSocket receiveFrom URL carries the same requirements by simile (see the extraction notes).
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: sse-binding
test gap: gap-stateful-temporal

JLWSC-SSE-3
type: Requirement
statement: Every event MUST carry an id field.
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: sse-binding
test gap: gap-stateful-temporal

JLWSC-SSE-4
type: Requirement
statement: the server MUST either replay all events after that id (it MUST retain events for a documented retention window) or, when the id has aged out, send a control event of type reset telling the client to re-synchronise state by reading the topics.
comment: Condition: reconnection with Last-Event-ID. GAPS.md names SSE resumption/reset explicitly as un-vectorable (streaming).
requirement level: MUST
requirement subject: notification server
testability: Enforceable
anchor: sse-binding
test gap: gap-stateful-temporal

JLWSC-WS-1
type: Requirement
statement: Servers SHOULD ping periodically; clients re-subscribe (obtaining a fresh receiveFrom) after close or expiry.
comment: There is no replay on this binding; clients needing gapless delivery use SSE or webhooks.
requirement level: SHOULD
requirement subject: notification server
testability: AccountableExistence
anchor: websocket-binding

JLWSC-CT-1
type: Requirement
statement: A server MUST NOT perform transformation it does not advertise, and clients MUST NOT expect any transformation that is not advertised: absent the capability, a data resource has exactly its stored representation.
comment: Operative sub-clause here is the server side.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: content-transformation
test case: case.json

JLWSC-CT-2
type: Requirement
statement: A server MUST NOT perform transformation it does not advertise, and clients MUST NOT expect any transformation that is not advertised: absent the capability, a data resource has exactly its stored representation.
comment: Operative sub-clause here is the client side (feature-detect before relying); the rdf-1 client fail-closed vector pins the RDF instance of this rule (rdf-transform/client-fail-closed-no-advertisement).
requirement level: MUSTNOT
requirement subject: JLWS client
testability: Enforceable
anchor: content-transformation
test case: case.json

JLWSC-CT-3
type: Requirement
statement: reads in the stored media type MUST return the stored bytes exactly (unless normalizes is declared)
comment: The byte-native promise, stated here for the general (transformation-advertising) case; the keywordless #http-read read-back sentence rides it (see the extraction notes).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: content-transformation
test case: case.json

JLWSC-CT-4
type: Requirement
statement: A server MAY offer server-side transformation between representations of a data resource
comment: The exercised contract (advertised pair actually negotiable, Vary: Accept) is pinned by the rdf-1 suite.
requirement level: MAY
requirement subject: JLWS server
testability: Enforceable
anchor: content-transformation
test case: case.json

JLWSC-QS-1
type: Requirement
statement: results MUST be filtered by the requesting agent's live authorization on every request (revocations take effect immediately); counts MUST reflect only the caller-visible view
comment: Invariants normative for any advertised query service; the query companion's own suite must pin them (the rdf-1 suite pins only the SparqlQueryService advertisement condition).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: query-services
test gap: gap-companion-planned

JLWSC-QS-2
type: Requirement
statement: index derivation MAY be eventually consistent but authorization filtering MUST NOT be; and a query service MUST NOT reveal the existence of resources the agent cannot read
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: query-services
test gap: gap-companion-planned

JLWSC-QS-3
type: Requirement
statement: QUERY MUST NOT be the only binding
comment: The type-search service's optional HTTP QUERY binding is additional to the equivalent GET and POST forms (deployment objection, 2026-06-29 minutes).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: query-services
test gap: gap-companion-planned

JLWSC-ST-1
type: Requirement
statement: All protocol interactions MUST use TLS; clients MUST validate server certificates (service identity) per !RFC6125 and follow the TLS configuration recommendations of BCP 195 (!RFC9325).
comment: Operative sub-clause here is the TLS-everywhere MUST (all parties); transport behaviour needs a live harness (GAPS.md 'network/trust').
requirement level: MUST
requirement subject: JLWS server
requirement subject: JLWS client
requirement subject: JLWS authorization server
testability: Enforceable
anchor: sec-transport
test gap: gap-network-trust

JLWSC-ST-2
type: Requirement
statement: All protocol interactions MUST use TLS; clients MUST validate server certificates (service identity) per !RFC6125 and follow the TLS configuration recommendations of BCP 195 (!RFC9325).
comment: Operative sub-clause here is the client certificate-validation MUST (probe: a bad-certificate endpoint must be refused).
requirement level: MUST
requirement subject: JLWS client
testability: Enforceable
anchor: sec-transport
test gap: gap-network-trust

JLWSC-ST-3
type: Requirement
statement: Tokens MUST NOT appear in URLs, browser storage accessible to untrusted scripts, or logs (log truncated/hashed values if needed).
comment: Negative internal property (audit/code-review only). Capability URLs are the deliberate, constrained exception (single-purpose, expiring, revocable, TLS-only — JLWSC-SSE-2).
requirement level: MUSTNOT
requirement subject: JLWS server
requirement subject: JLWS client
requirement subject: JLWS authorization server
testability: AccountableExistence
anchor: sec-transport

JLWSC-SECT-1
type: Requirement
statement: Deployments handling high-value data SHOULD offer — and MAY require — a proof-of-possession profile
comment: Deployment-posture recommendation; auditable, not vectorable (whether data is 'high-value' is a policy judgement).
requirement level: SHOULD
requirement subject: JLWS server
testability: AccountableExistence
anchor: sec-tokens

JLWSC-SECT-2
type: Requirement
statement: Storage servers MUST maintain an explicit allowlist of trusted authorization-server issuers and reject all others
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: sec-tokens
test case: case.json
restates: JLWSC-RSV-2

JLWSC-SECT-3
type: Requirement
statement: Multi-tenant instances MUST NOT accept a token whose aud is scoped outside the current storage (tenant-replay isolation, jeswr/lws-keycloak spec/authz.md §7.5.1).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: sec-tokens
test case: case.json
restates: JLWSC-RSV-5

JLWSC-SECT-4
type: Requirement
statement: Servers MAY maintain a jti replay cache (bounded, sized against DoS) for single-use token policies.
requirement level: MAY
requirement subject: JLWS server
testability: Premature
anchor: sec-tokens
test gap: gap-deployment-policy

JLWSC-SECT-5
type: Requirement
statement: Authentication credentials with unrestricted audiences MUST NOT be presented to untrusted authorization servers
comment: Client presentation conduct; auditable against a client-under-test transcript.
requirement level: MUSTNOT
requirement subject: JLWS client
testability: AccountableExistence
anchor: sec-tokens

JLWSC-SECT-6
type: Requirement
statement: clients SHOULD obtain audience-restricted credentials (RFC 8707 resource indicators, or token exchange) first.
requirement level: SHOULD
requirement subject: JLWS client
testability: AccountableExistence
anchor: sec-tokens

JLWSC-SSRF-1
type: Requirement
statement: Every such fetch MUST apply all of the following:
comment: 'Every such fetch' = outbound requests to attacker-influenced URLs (CID/subject dereferencing, JWKS and metadata fetches, client-ID metadata fetches, webhook inbox delivery, storage-description fetches by webhook receivers). The six bullets: https-only scheme; resolved-address policy rejecting loopback/private/link-local/unique-local/cloud-metadata (IPv4 and IPv6, incl. mapped/compatible forms); DNS pinning (connect to the validated resolved address); no automatic redirects (JLWSC-SSRF-2); response-size/time caps + bounded concurrency; no credential forwarding (JLWSC-SSRF-3). The vectored case pins the fail-closed non-https extension-endpoint half; the network-behaviour halves need an instrumented harness.
requirement level: MUST
requirement subject: JLWS server
requirement subject: JLWS authorization server
requirement subject: webhook receiver
testability: Enforceable
anchor: ssrf
test case: case.json
test gap: gap-network-trust

JLWSC-SSRF-2
type: Requirement
statement: if followed, each hop MUST re-pass the full policy.
comment: Condition: redirects are followed at all (the default is not to follow them automatically).
requirement level: MUST
requirement subject: JLWS server
requirement subject: JLWS authorization server
requirement subject: webhook receiver
testability: Enforceable
anchor: ssrf
test gap: gap-network-trust

JLWSC-SSRF-3
type: Requirement
statement: outbound fetches MUST NOT attach the inbound request's credentials.
requirement level: MUSTNOT
requirement subject: JLWS server
requirement subject: JLWS authorization server
requirement subject: webhook receiver
testability: Enforceable
anchor: ssrf
test gap: gap-network-trust

JLWSC-OF-1
type: Requirement
statement: the server MUST respond 404 (not 403), indistinguishable from a genuinely absent resource
comment: Condition: the agent has no permitted operation on the resource and is not otherwise authorized to learn that it exists. 403 is reserved for agents with partial access (already entitled to know the resource exists).
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: oracle-freedom
test case: case.json

JLWSC-OF-2
type: Requirement
statement: Container listings, totalItems, query results, and notification streams MUST expose only what the requesting agent can read
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: oracle-freedom
test case: case.json
restates: JLWSC-MA-2
restates: JLWSC-MA-3

JLWSC-OF-3
type: Requirement
statement: Servers MUST NOT enumerate, in any discovery surface, the set of link relations or types they index (no discovery oracle — LWS-SEARCHINDEX-ED).
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: oracle-freedom
test gap: gap-deferred

JLWSC-OF-4
type: Requirement
statement: Error responses (including problem details) MUST NOT leak the existence, size, or type of resources the agent cannot read.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: oracle-freedom
test case: case.json

JLWSC-CORS-1
type: Requirement
statement: Servers supporting browser clients MUST validate Origin and use restrictive CORS policies; wildcard credentialed CORS MUST NOT be used.
comment: Operative sub-clause here is the Origin-validation MUST.
requirement level: MUST
requirement subject: JLWS server
testability: Enforceable
anchor: sec-cors
test gap: gap-deferred

JLWSC-CORS-2
type: Requirement
statement: Servers supporting browser clients MUST validate Origin and use restrictive CORS policies; wildcard credentialed CORS MUST NOT be used.
comment: Operative sub-clause here is the wildcard-credentialed-CORS MUST NOT.
requirement level: MUSTNOT
requirement subject: JLWS server
testability: Enforceable
anchor: sec-cors
test gap: gap-deferred

JLWSC-CORS-3
type: Requirement
statement: Servers SHOULD emit X-Content-Type-Options: nosniff on data-resource responses and treat stored content as untrusted when serving to browsers
requirement level: SHOULD
requirement subject: JLWS server
testability: Enforceable
anchor: sec-cors
test gap: gap-deferred

JLWSC-PRIV-1
type: Requirement
statement: authorization servers SHOULD issue tokens containing only what authorization needs
requirement level: SHOULD
requirement subject: JLWS authorization server
testability: AccountableExistence
anchor: privacy-considerations

JLWSC-PRIV-2
type: Requirement
statement: when pseudonymous subject identifiers are used, clients SHOULD request batch issuance and use each token once, preventing the storage server from correlating requests by identifier
requirement level: SHOULD
requirement subject: JLWS client
testability: AccountableExistence
anchor: privacy-considerations

JLWSC-PRIV-3
type: Requirement
statement: an authorization server SHOULD NOT issue the same pseudonymous identifier twice
comment: IP-address and policy-shape correlation remain (the spec's own caveat).
requirement level: SHOULDNOT
requirement subject: JLWS authorization server
testability: Enforceable
anchor: privacy-considerations
test gap: gap-stateful-temporal

JLWSC-PRIV-4
type: Requirement
statement: implementations SHOULD NOT log full tokens, credentials, or capability URLs.
requirement level: SHOULDNOT
requirement subject: JLWS server
requirement subject: JLWS client
requirement subject: JLWS authorization server
testability: AccountableExistence
anchor: privacy-considerations

JLWS Core Protocol — A Clean-Slate Linked Web Storage Design
type: Specification
conformance: conformance
consideration: security-considerations
consideration: privacy-considerations
requirement: JLWSC-NS-1
requirement: JLWSC-CONF-1
requirement: JLWSC-RC-1
requirement: JLWSC-RC-2
requirement: JLWSC-RC-3
requirement: JLWSC-CVD-1
requirement: JLWSC-CVD-2
requirement: JLWSC-CTN-1
requirement: JLWSC-CTN-2
requirement: JLWSC-CTN-3
requirement: JLWSC-CTN-4
requirement: JLWSC-CTN-5
requirement: JLWSC-CTN-6
requirement: JLWSC-PA-1
requirement: JLWSC-PA-2
requirement: JLWSC-PA-3
requirement: JLWSC-MA-1
requirement: JLWSC-MA-2
requirement: JLWSC-MA-3
requirement: JLWSC-CP-1
requirement: JLWSC-CP-2
requirement: JLWSC-CP-3
requirement: JLWSC-CP-4
requirement: JLWSC-CP-5
requirement: JLWSC-CP-6
requirement: JLWSC-CMT-1
requirement: JLWSC-CMT-2
requirement: JLWSC-CMT-3
requirement: JLWSC-PAG-1
requirement: JLWSC-PAG-2
requirement: JLWSC-PAG-3
requirement: JLWSC-MD-1
requirement: JLWSC-MD-2
requirement: JLWSC-MD-3
requirement: JLWSC-MU-1
requirement: JLWSC-MU-2
requirement: JLWSC-MU-3
requirement: JLWSC-MU-4
requirement: JLWSC-MU-5
requirement: JLWSC-OP-1
requirement: JLWSC-HG-1
requirement: JLWSC-HG-2
requirement: JLWSC-HG-3
requirement: JLWSC-HG-4
requirement: JLWSC-HG-5
requirement: JLWSC-HG-6
requirement: JLWSC-HG-7
requirement: JLWSC-POST-1
requirement: JLWSC-POST-2
requirement: JLWSC-POST-3
requirement: JLWSC-POST-4
requirement: JLWSC-POST-5
requirement: JLWSC-POST-6
requirement: JLWSC-PUT-1
requirement: JLWSC-PUT-2
requirement: JLWSC-PUT-3
requirement: JLWSC-PUT-4
requirement: JLWSC-PUT-5
requirement: JLWSC-PUT-6
requirement: JLWSC-PUT-7
requirement: JLWSC-RD-1
requirement: JLWSC-RD-2
requirement: JLWSC-RD-3
requirement: JLWSC-UPD-1
requirement: JLWSC-UPD-2
requirement: JLWSC-UPD-3
requirement: JLWSC-UPD-4
requirement: JLWSC-UPD-5
requirement: JLWSC-DEL-1
requirement: JLWSC-DEL-2
requirement: JLWSC-DEL-3
requirement: JLWSC-DEL-4
requirement: JLWSC-MV-1
requirement: JLWSC-MV-2
requirement: JLWSC-MV-3