From 92d4f0319d2766124a8bfdce019be5412d9e8682 Mon Sep 17 00:00:00 2001
From: Erich Bremer
The storage description advertises only the service endpoints. In particular, the
set of additional indexed relations a server supports is deliberately not
- enumerated there or anywhere else; see .
+ enumerated there or anywhere else; see .
Discovery
GET [TypeIndexService]
are opaque to the client. The body lists the unique types of resources that
currently exist within the storage and that the authenticated user is authorized to
see. This endpoint accepts no query parameters.
+ The Type Index takes no filter, so it is retrieved with a GET. The
+ Type Search Service, which carries a filter, instead uses the HTTP
+ QUERY method [[!RFC10008]] (see ).
+
HTTP/1.1 200 OK Content-Type: application/lws+json @@ -242,39 +255,62 @@-Type Search Service
indexed relations. -- GET [TypeSearchService]
++ - -QUERY [TypeSearchService]
- The
+ +typequery parameter is OPTIONAL and selects resources by their -rdf:type(as declared viarel="type"Linkheaders, - server-intrinsic classes, or content; see ). + A client searches by sending an HTTPQUERYrequest [[!RFC10008]] to the + service endpoint, carrying the filter in the request body as +application/lws+json. The request MUST include aContent-Typeof +application/lws+json; per [[!RFC10008]] a server fails the request if the +Content-Typeis missing or inconsistent with the body (see + ). BecauseQUERYis both safe and idempotent + [[!RFC10008]], a search never alters server state and MAY be repeated, retried, or cached. + Because the filter travels in the body rather than the request URI, it is not subject to the + request-URI length limits that constrain a query string.+{ + "@context": "https://www.w3.org/ns/lws/v1", + "type": [ + ["https://schema.org/Person", "http://xmlns.com/foaf/0.1/Person"], + "https://www.w3.org/ns/lws#DataResource" + ] +} ++- A single
typeparameter MAY carry a comma-separated list of URIs, combined with - logical OR — a resource matches the group if it declares any of the - listed types. Repeating thetypeparameter combines the groups with logical - AND. The filter is therefore a conjunction of disjunctions: -?type=A,B&type=Cselects resources matching(A OR B) AND C. A - request with notypeparameter matches all resources visible to the client. + Thetypekey is OPTIONAL and selects resources by theirrdf:type+ (as declared viarel="type"Linkheaders, server-intrinsic + classes, or content; see ). Its value is an array whose + elements are combined with logical AND; each element is either a single + type URI or an array of type URIs combined with logical OR. The example + above selects resources matching +(schema:Person OR foaf:Person) AND lws:DataResource— the filter is a + conjunction of disjunctions, that is, conjunctive normal form. A request whose body has no +typekey and no relation keys (or only empty groups) matches all resources + visible to the client.- This conjunctive-normal-form filter is the complete query expressiveness of the service. - Servers MAY support nesting, negation, comparison, ordering, or text - matching. A type URI that matches no resource yields no results and MUST NOT be treated as an - error; empty or duplicate groups MUST be ignored. + This conjunctive-normal-form filter is the complete query expressiveness the service is + required to provide. A server MAY support nesting, negation, comparison, ordering, or text + matching, but a portable client MUST NOT rely on any of these. A type URI that matches no + resource yields no results and MUST NOT be treated as an error; empty or duplicate groups + MUST be ignored.
- The
typeparameter is the mandatory baseline and MUST be supported by every server that implements the -TypeSearchService. A server MAY additionally index other descriptive link - relations. Such a relation is filtered by using the relation itself as the query-parameter name - — a registered relation name per [[!RFC8288]] or, for an - extension relation, its URI — with exactly the same conjunctive-normal-form semantics as -type(comma = OR group, repeated parameter = AND group, target values matched against - the link targets the resource declares for that relation). Groups belonging to different relations - are combined with logical AND. Relation targets are derived by the server in the same way as types - (HTTPLinkheaders, server-intrinsic state, or parsed content) and all sources MUST be - treated identically. + Thetypekey is the mandatory baseline and MUST be supported by every server + that implements theTypeSearchService. A server MAY additionally index other + descriptive link relations. Such a relation is filtered by using the relation + itself as a key alongsidetype— a registered relation name per + [[!RFC8288]] or, for an extension relation, its URI — with exactly the same + conjunctive-normal-form semantics astype(a nested array is an OR group, + sibling array elements form AND groups, target values matched against the link targets the + resource declares for that relation). Groups belonging to different relations are combined + with logical AND. Relation targets are derived by the server in the same way as types (HTTP +Linkheaders, server-intrinsic state, or parsed content) and all sources MUST + be treated identically.The set of additional indexed relations is deliberately NOT enumerated by the server — not in @@ -283,54 +319,41 @@
GET [TypeSearchService]
results for that constraint; it MUST NOT be treated as an error, and the two cases MUST be indistinguishable to the client (consistent with the type-matching rule above). Servers MUST NOT index structural or protocol relations, only descriptive relations are eligible. -Clients MUST URL-encode query parameter keys and values.
-Returns
-application/lws+json: A paginatedContainerPagewhose items describe the matching LWS resources. Aside fromtypeand any additional relation parameters described above, no other parameters are defined.A
-ContainerPagereturned by theTypeSearchServiceis a synthetic result set, not a representation of a container resource. TheContainerPagemedia type and pagination model are reused only for client convenience; the response does not identify a container, has no containment relationship to its members, is not retrievable or mutable as a resource, and its membership reflects the query rather than any stored hierarchy. Each item is a resource description carrying at leastidandtype, mirroring a container member; a server MAY include additional descriptive metadata (such asmediaType,size, ormodified) but is not required to. The same applies to thePOSTform.A single-type query (one URI, no comma) matches a resource that declares that type, even if the resource also declares other types.
-A
-typefilter always denotes thetypethe matched resource itself bears; it never denotes the types of a container's members. The native LWS classeshttps://www.w3.org/ns/lws#DataResourceandhttps://www.w3.org/ns/lws#Containerare ordinarytypevalues: filtering on them selects resources that are themselves data resources or containers, respectively (for example?type=https://www.w3.org/ns/lws%23Containermatches container resources, and?type=https://schema.org/Person&type=https://www.w3.org/ns/lws%23DataResourcematches data resources that are alsoschema:Person).- -POST [TypeSearchService]
- -MUST support
-application/lws+jsonbody:-{ - "@context": "https://www.w3.org/ns/lws/v1", - "type": [ - ["https://schema.org/Person", "http://xmlns.com/foaf/0.1/Person"], - "https://www.w3.org/ns/lws#DataResource" - ] -} --
-type: an array whose elements are combined with AND. Each element is either a single type URI or an array of type URIs combined with OR. The example above selects resources matching(schema:Person OR foaf:Person) AND lws:DataResource. This is the same conjunctive-normal-form filter as the GET form, with the same expressiveness ceiling: servers MUST NOT be required to support nesting, negation, comparison, ordering, or text matching. + A successful search returns200(OK) with an +application/lws+jsonContainerPagewhose items describe the + matching LWS resources. The result set is paginated following the standard LWS pagination + model defined by [[!LWS-PROTOCOL]]: page URIs are conveyed inLinkheaders + — not in the response body — are opaque to the client, and are dereferenced to + retrieve subsequent pages. Aside fromtypeand any additional relation keys + described above, no other filter inputs are defined.- The body MAY also include, alongside
type, a key for any other descriptive relation - (a registered relation name per [[!RFC8288]] or an extension relation URI). Each such key takes the same value form astypeand the keys are combined with logical AND, exactly as in the GET form. A relation the server does not index yields no results for that constraint and is indistinguishable from a target value that matches nothing; it MUST NOT be treated as an error. +A
+ContainerPagereturned by theTypeSearchServiceis a synthetic result set, not a representation of a container resource. TheContainerPagemedia type and pagination model are reused only for client convenience; the response does not identify a container, has no containment relationship to its members, is not retrievable or mutable as a resource, and its membership reflects the query rather than any stored hierarchy. Each item is a resource description carrying at leastidandtype, mirroring a container member; a server MAY include additional descriptive metadata (such asmediaType,size, ormodified) but is not required to.+ [[!RFC10008]] permits a response to carry a
-Content-Locationheader field + identifying a resource that represents the query results. Because a Type Search result set + is synthetic and client-specific (see the note above and + ), this specification does not define such a resource; + a server that nonetheless exposes one MUST subject it to the same authorization filtering on + every access and MUST prevent its reuse across clients.Returns a paginated
+ContainerPagewhose items describe the matching LWS resources. Aside fromtypeand additional relation keys, no other parameters are defined.A single-type query (one URI, not enclosed in an array) matches a resource that declares that type, even if the resource also declares other types.
+A
typefilter always denotes thetypethe matched resource itself bears; it never denotes the types of a container's members. The native LWS classeshttps://www.w3.org/ns/lws#DataResourceandhttps://www.w3.org/ns/lws#Containerare ordinarytypevalues: filtering on them selects resources that are themselves data resources or containers, respectively (for example atypeofhttps://www.w3.org/ns/lws#Containermatches container resources, and a filter ofhttps://schema.org/PersonANDhttps://www.w3.org/ns/lws#DataResourcematches data resources that are alsoschema:Person).- @@ -356,7 +385,9 @@Request Equivalence and Errors
++ Errors
-- A server implementing the
TypeSearchServiceMUST support both theGETand -POSTforms. The two forms are equivalent: any filter expressible in one MUST be - expressible in the other, and equivalentGETandPOSTrequests MUST return the same result set. A server MUST NOT impose different expressiveness limits on the two forms, except thatGETrequests are additionally bounded by practical request-URI length limits. -Servers indicate request outcomes using standard HTTP status codes. In particular:
- - A
POSTbody that is not well-formedapplication/lws+json, or whose + A request body that is not well-formedapplication/lws+json, or whosetypeis not an array, or any of whose elements is neither a string nor an array of strings, MUST be rejected with400(Bad Request).- - A
POSTrequest whose entity uses a media type other thanapplication/lws+jsonMUST be rejected with415(Unsupported Media Type). + A request whose entity uses a media type other thanapplication/lws+jsonMUST be rejected with415(Unsupported Media Type); a request that omits theContent-Typeheader field, which [[!RFC10008]] requires a server to reject, MUST be rejected with400(Bad Request).- A
typevalue, or any relation target value, that is not a syntactically valid @@ -338,16 +361,22 @@Request Equivalence and Errors
well-formed URI that matches no resource, and from a relation the server does not index, both of which yield no results and are not errors (see above).- - A pagination reference (a previously issued
nextlink) that the server no longer recognizes or that has expired MUST result in404(Not Found) or410(Gone); clients SHOULD restart the query from the first page. + A filter that is well-formed but exceeds the complexity a server chooses to support + (consistent with the expressiveness ceiling above) MUST be rejected with422(Unprocessable Content) — the status [[!RFC10008]] designates for query content that is understood but cannot be processed. A server MUST NOT silently truncate or otherwise narrow such a filter, as doing so could return a superset of the intended results.- - A filter that exceeds the complexity a server chooses to support (consistent with the - expressiveness ceiling above) MUST be rejected with
400(Bad Request). A server MUST NOT silently truncate or otherwise narrow such a filter, as doing so could return a superset of the intended results. + A pagination reference (a previously issuednextlink) that the server no longer recognizes or that has expired MUST result in404(Not Found) or410(Gone); clients SHOULD restart the query from the first page.- Error responses MAY include a representation describing the problem; this specification does not - define its format. + Error responses MAY include a representation describing the problem; this specification does + not define its format. +
++ A
QUERYresponse is cacheable [[!RFC10008]], and its cache key incorporates the + request body. Because every result set is authorization-filtered and therefore + client-specific, the cross-client caching requirements in + apply.Request Equivalence and Errors
Security and Authorization
- Servers MUST enforce authorization. Responses to GET/POST on
TypeIndexServiceorTypeSearchServiceinclude only types and resource URIs that the authenticated client is explicitly authorized to read. + Servers MUST enforce authorization. Responses from theTypeIndexService(a +GET) and theTypeSearchService(aQUERY) include only + types and resource URIs that the authenticated client is explicitly authorized to read.Unauthorized entries MUST be omitted entirely. A client must not be able to discover the existence of a specific resource instance, or that a specific type exists in the storage at all, if they do not have the required authorization. This implicit filtering yields a dynamically generated, client-specific type index and search result. @@ -371,6 +402,14 @@
Security and Authorization
Authorization filtering MUST be evaluated against the requesting client's current access at the time the request is served, not against any cached or precomputed view. Once an authorization (such as an access grant) is revoked or narrowed, the affected types and resource URIs MUST NOT appear in any subsequent response; the eventual-consistency allowance for type and relation derivation MUST NOT be extended to authorization. A server MAY maintain a derived index for performance, but it MUST apply current authorization as a filter over that index on every request.
++ Because a
QUERYresponse is cacheable by default [[!RFC10008]] and its cache key + is computed over the request body rather than the requesting client, a server MUST ensure that + an authorization-filtered response is never served from a shared cache to a different client. + A server MUST mark such responses so that they are not reused across clients (for example with +Cache-Control: privateorno-store) and MUST vary any cached entry on + the credential that scopes the result. +@@ -398,15 +437,25 @@ Examples
}
+Request -GET /types/search?type=https://schema.org/Person&type=https://www.w3.org/ns/lws%23DataResource +QUERY /types/search +Content-Type: application/lws+json + +{ + "@context": "https://www.w3.org/ns/lws/v1", + "type": [ + "https://schema.org/Person", + "https://www.w3.org/ns/lws#DataResource" + ] +} Response HTTP/1.1 200 OK Content-Type: application/lws+json -Link: <https://example.org/types/search?type=https://schema.org/Person&type=https://www.w3.org/ns/lws%23DataResource&page=1>; rel="first" -Link: <https://example.org/types/search?type=https://schema.org/Person&type=https://www.w3.org/ns/lws%23DataResource&page=2>; rel="next" +Cache-Control: private +Link: <https://example.org/types/search?cursor=8f2a1c>; rel="first" +Link: <https://example.org/types/search?cursor=b71e90>; rel="next" { "@context": "https://www.w3.org/ns/lws/v1", @@ -420,9 +469,15 @@-Examples
}+Request -GET /types/search?type=https://www.w3.org/ns/lws%23Container +QUERY /types/search +Content-Type: application/lws+json + +{ + "@context": "https://www.w3.org/ns/lws/v1", + "type": ["https://www.w3.org/ns/lws#Container"] +} Matches resources whose type includes lws:Container. This does NOT mean "containers that contain something" - the service has no containment query. @@ -440,38 +495,11 @@-Examples
}-Request -POST /types/search -Request Body -{ - "@context": "https://www.w3.org/ns/lws/v1", - "type": [ - "https://schema.org/Person", - "https://www.w3.org/ns/lws#DataResource" - ] -} - -Response -{ - "@context": "https://www.w3.org/ns/lws/v1", - "type": "ContainerPage", - "totalItems": 3, - "items": [ - { "type": ["DataResource", "https://schema.org/Person"], "id": "https://example.org/data/person-4872" }, - { "type": ["DataResource", "https://schema.org/Person"], "id": "https://example.org/data/person-9341" }, - { "type": ["DataResource", "https://schema.org/Person"], "id": "https://example.org/data/person-1123" } - ] -} ---Request (GET form: comma = OR, repeated parameter = AND) -GET /types/search?type=https://schema.org/Person,http://xmlns.com/foaf/0.1/Person&type=https://www.w3.org/ns/lws%23DataResource +Request (nested array = OR group, outer array = AND) +QUERY /types/search +Content-Type: application/lws+json -Equivalent Request (POST form: nested array = OR group, outer array = AND) -POST /types/search -Request Body { "@context": "https://www.w3.org/ns/lws/v1", "type": [ @@ -480,7 +508,7 @@Examples
] } -Both select resources matching (schema:Person OR foaf:Person) AND lws:DataResource. +Selects resources matching (schema:Person OR foaf:Person) AND lws:DataResource. Response { @@ -495,12 +523,10 @@Examples
-Request (GET: type AND a 'describedby' relation; relation name used as the parameter) -GET /types/search?type=https://schema.org/Person&describedby=https://shapes.example/PersonShape +Request (type AND a 'describedby' relation, the relation name used as a key) +QUERY /types/search +Content-Type: application/lws+json -Equivalent Request (POST) -POST /types/search -Request Body { "@context": "https://www.w3.org/ns/lws/v1", "type": ["https://schema.org/Person"], @@ -548,15 +574,17 @@Security Considerations
Resource Exhaustion: Conjunctive filters across multiple types and indexed relations can be expensive to evaluate. Servers are encouraged to bound filter complexity and page sizes and to apply rate limiting, rejecting over-limit - filters with400as required by - rather than narrowing them. + filters with422as required by + rather than narrowing them.
Cache-Control: private or
- no-store) that prevent reuse across clients.
+ Shared Caches: Responses are client-specific by construction, yet a
+ QUERY response is cacheable by default [[RFC10008]] and its cache key is
+ computed over the request body rather than the requesting client. Serving such a response
+ through a shared cache therefore risks delivering one client's authorization-filtered view
+ to another. The cache requirements in exist to
+ prevent this, and deserve particular attention when a shared cache sits in front of the
+ service.
A client searches by sending an HTTP QUERY request [[!RFC10008]] to the
- service endpoint, carrying the filter in the request body as
- application/lws+json. The request MUST include a Content-Type of
- application/lws+json; per [[!RFC10008]] a server fails the request if the
- Content-Type is missing or inconsistent with the body (see
- ). Because QUERY is both safe and idempotent
+ service endpoint, carrying the filter in the request body. The query format is identified
+ by the request's Content-Type header field, which MUST be present; per
+ [[!RFC10008]] a server fails the request if the Content-Type is missing or
+ inconsistent with the body (see ). Every server MUST
+ support the application/lws+json filter defined here as its baseline query
+ format; a server MAY additionally accept other query formats, each identified by its own
+ media type, and the authorization requirements of
+ apply regardless of the format used. Because QUERY is both safe and idempotent
[[!RFC10008]], a search never alters server state and MAY be repeated, retried, or cached.
Because the filter travels in the body rather than the request URI, it is not subject to the
request-URI length limits that constrain a query string.
@@ -353,7 +356,7 @@
type is not an array, or any of whose elements is neither a string nor an array of strings, MUST be rejected with 400 (Bad Request).
application/lws+json MUST be rejected with 415 (Unsupported Media Type); a request that omits the Content-Type header field, which [[!RFC10008]] requires a server to reject, MUST be rejected with 400 (Bad Request).
+ A request whose Content-Type identifies a query format the server does not support MUST be rejected with 415 (Unsupported Media Type); every server supports at least application/lws+json (see ). A request that omits the Content-Type header field, which [[!RFC10008]] requires a server to reject, MUST be rejected with 400 (Bad Request).
type value, or any relation target value, that is not a syntactically valid
From 7e27cbfb5b5c995fe1678df3c7e2fb60be6705f7 Mon Sep 17 00:00:00 2001
From: Erich Bremer Cache-Control: private or no-store) and MUST vary any cached entry on
the credential that scopes the result.
+
+ Any extension query mechanism a server exposes over the storage — for example an
+ alternative query format accepted by the TypeSearchService, or a separate query
+ service — MUST uphold these authorization-filtering requirements and the
+ indistinguishability requirements of this specification, so that no extension can become a
+ discovery oracle for resources or types the client is not authorized to read.
+
+ A server SHOULD advertise the query formats it accepts using the
+ Accept-Query response header field [[!RFC10008]] — for example in
+ response to an OPTIONS request on the service endpoint, whose Allow
+ header also signals that the QUERY method is supported. Accept-Query
+ enumerates only the query-format media types the server understands; it MUST NOT be used to
+ disclose which indexed relations or filter capabilities a server supports, which
+ remain deliberately unobservable (see ). A client that
+ receives a 415 (Unsupported Media Type) response MAY consult its
+ Accept-Query value to select a supported format.
+
{
"@context": "https://www.w3.org/ns/lws/v1",
@@ -356,7 +368,7 @@ Errors
type is not an array, or any of whose elements is neither a string nor an array of strings, MUST be rejected with 400 (Bad Request).
Content-Type identifies a query format the server does not support MUST be rejected with 415 (Unsupported Media Type); every server supports at least application/lws+json (see ). A request that omits the Content-Type header field, which [[!RFC10008]] requires a server to reject, MUST be rejected with 400 (Bad Request).
+ A request whose Content-Type identifies a query format the server does not support MUST be rejected with 415 (Unsupported Media Type), and such a response SHOULD include an Accept-Query header field [[!RFC10008]] listing the query formats the server does accept; every server supports at least application/lws+json (see ). A request that omits the Content-Type header field, which [[!RFC10008]] requires a server to reject, MUST be rejected with 400 (Bad Request).
type value, or any relation target value, that is not a syntactically valid
@@ -447,6 +459,19 @@ +Request +OPTIONS /types/search + +Response +HTTP/1.1 204 No Content +Allow: OPTIONS, QUERY +Accept-Query: application/lws+json + +A server that also accepted other query formats would list them in Accept-Query, +for example: Accept-Query: application/lws+json, application/sparql-query ++
Request QUERY /types/search From e76a7705353eb61b331e84f38e39c5eaa2c7ddf2 Mon Sep 17 00:00:00 2001 From: Erich BremerDate: Fri, 26 Jun 2026 11:09:00 -0400 Subject: [PATCH 05/22] allow alternate formats for other query types --- lws10-searchindex/index.html | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 2decc2b..588b56f 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -335,13 +335,21 @@ QUERY [TypeSearchService]
indistinguishable to the client (consistent with the type-matching rule above). Servers MUST NOT index structural or protocol relations, only descriptive relations are eligible.- A successful search returns
+200(OK) with an + A successful search returns200(OK). The default response is anapplication/lws+jsonContainerPagewhose items describe the - matching LWS resources. The result set is paginated following the standard LWS pagination - model defined by [[!LWS-PROTOCOL]]: page URIs are conveyed inLinkheaders - — not in the response body — are opaque to the client, and are dereferenced to - retrieve subsequent pages. Aside fromtypeand any additional relation keys - described above, no other filter inputs are defined. + matching LWS resources, and every server MUST be able to produce it: a request that sends + noAcceptheader field, or one that admitsapplication/lws+json, + receives this representation. A server MAY honor anAcceptheader field that + requests a different response media type and return the result set in that format instead + [[!RFC10008]]; if it can satisfy none of the media types the request finds acceptable, it + responds406(Not Acceptable) (see ). ++ Whatever the response format, the result set is paginated following the standard LWS + pagination model defined by [[!LWS-PROTOCOL]]: page URIs are conveyed in
Link+ headers — not in the response body — are opaque to the client, and are + dereferenced to retrieve subsequent pages. Aside fromtypeand any additional + relation keys described above, no other filter inputs are defined.A
ContainerPagereturned by theTypeSearchServiceis a synthetic result set, not a representation of a container resource. TheContainerPagemedia type and pagination model are reused only for client convenience; the response does not identify a container, has no containment relationship to its members, is not retrievable or mutable as a resource, and its membership reflects the query rather than any stored hierarchy. Each item is a resource description carrying at leastidandtype, mirroring a container member; a server MAY include additional descriptive metadata (such asmediaType,size, ormodified) but is not required to.@@ -370,6 +378,9 @@
Errors
A request whose +Content-Typeidentifies a query format the server does not support MUST be rejected with415(Unsupported Media Type), and such a response SHOULD include anAccept-Queryheader field [[!RFC10008]] listing the query formats the server does accept; every server supports at leastapplication/lws+json(see ). A request that omits theContent-Typeheader field, which [[!RFC10008]] requires a server to reject, MUST be rejected with400(Bad Request).+ A request whose Acceptheader field excludes every response media type the server can produce for the result set MUST be rejected with406(Not Acceptable) [[!RFC10008]]. Because every server can produce theapplication/lws+jsonContainerPage, a request that omitsAcceptor admits that media type never results in406. +A typevalue, or any relation target value, that is not a syntactically valid absolute URI MUST be rejected with400(Bad Request). This is distinct from a From d868aba345d529a546ee15401a8f6e670a2db536 Mon Sep 17 00:00:00 2001 From: Erich BremerDate: Fri, 26 Jun 2026 13:43:18 -0400 Subject: [PATCH 06/22] Clarify QUERY cache key and Vary: Accept --- lws10-searchindex/index.html | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 588b56f..cd5b373 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -399,10 +399,14 @@ Errors
not define its format.- A
From 19d48cd8b14e50524428e23f9e3ab6a2ca4f3286 Mon Sep 17 00:00:00 2001 From: Erich BremerQUERYresponse is cacheable [[!RFC10008]], and its cache key incorporates the - request body. Because every result set is authorization-filtered and therefore - client-specific, the cross-client caching requirements in - apply. + AQUERYresponse is cacheable [[!RFC10008]]. Because the filter travels in the + request body, it forms part of the cache key itself ([[!RFC10008]], Section 2.7) and cannot + be conveyed through theVaryheader field, which names only request header + fields. A server that negotiates the response representation onAccept(see + ) MUST listAcceptinVaryso that + caches do not reuse a representation across response formats. Because every result set is + authorization-filtered and therefore client-specific, the cross-client caching requirements + in also apply.Date: Fri, 26 Jun 2026 13:49:09 -0400 Subject: [PATCH 07/22] add normative 9110 reference --- lws10-searchindex/index.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index cd5b373..302b6ce 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -267,8 +267,9 @@ QUERY [TypeSearchService]
support theapplication/lws+jsonfilter defined here as its baseline query format; a server MAY additionally accept other query formats, each identified by its own media type, and the authorization requirements of - apply regardless of the format used. BecauseQUERYis both safe and idempotent - [[!RFC10008]], a search never alters server state and MAY be repeated, retried, or cached. + apply regardless of the format used. Because theQUERYmethod is both safe and + idempotent [[!RFC9110]], a property [[!RFC10008]] requires of everyQUERY+ request, a search never alters server state and MAY be repeated, retried, or cached. Because the filter travels in the body rather than the request URI, it is not subject to the request-URI length limits that constrain a query string. @@ -368,7 +369,7 @@QUERY [TypeSearchService]
Errors
- Servers indicate request outcomes using standard HTTP status codes. In particular: + Servers indicate request outcomes using standard HTTP status codes [[!RFC9110]]. In particular:
From 84683b953f034927b5f57e9794fc77efdfb2f094 Mon Sep 17 00:00:00 2001 From: Erich Bremer
- From bb671983b38b6a50ad844d66198c4df499e115e7 Mon Sep 17 00:00:00 2001 From: Erich Bremer
Date: Sat, 27 Jun 2026 20:49:33 -0400 Subject: [PATCH 08/22] Update lws10-searchindex/index.html Co-authored-by: Ted Thibodeau Jr --- lws10-searchindex/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 302b6ce..d457785 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -268,7 +268,7 @@ QUERY [TypeSearchService]
format; a server MAY additionally accept other query formats, each identified by its own media type, and the authorization requirements of apply regardless of the format used. Because theQUERYmethod is both safe and - idempotent [[!RFC9110]], a property [[!RFC10008]] requires of everyQUERY+ idempotent [[!RFC9110]], a property [[!RFC10008]] required of everyQUERYrequest, a search never alters server state and MAY be repeated, retried, or cached. Because the filter travels in the body rather than the request URI, it is not subject to the request-URI length limits that constrain a query string. From 5fdc69e293897bf68edf1dc4566dfb1eb5dea31b Mon Sep 17 00:00:00 2001 From: Erich BremerDate: Wed, 1 Jul 2026 22:18:14 -0400 Subject: [PATCH 09/22] cache privacy no longer covers the TypeIndex --- lws10-searchindex/index.html | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 302b6ce..9d00598 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -228,6 +228,7 @@ GET [TypeIndexService]
HTTP/1.1 200 OK Content-Type: application/lws+json +Cache-Control: private Link: <https://example.org/types/index?page=1>; rel="first" Link: <https://example.org/types/index?page=2>; rel="next" Link: <https://example.org/types/index?page=4>; rel="last" @@ -434,12 +435,15 @@Security and Authorization
Authorization filtering MUST be evaluated against the requesting client's current access at the time the request is served, not against any cached or precomputed view. Once an authorization (such as an access grant) is revoked or narrowed, the affected types and resource URIs MUST NOT appear in any subsequent response; the eventual-consistency allowance for type and relation derivation MUST NOT be extended to authorization. A server MAY maintain a derived index for performance, but it MUST apply current authorization as a filter over that index on every request.- Because a
QUERYresponse is cacheable by default [[!RFC10008]] and its cache key - is computed over the request body rather than the requesting client, a server MUST ensure that - an authorization-filtered response is never served from a shared cache to a different client. - A server MUST mark such responses so that they are not reused across clients (for example with -Cache-Control: privateorno-store) and MUST vary any cached entry on - the credential that scopes the result. + Responses from both services are authorization-filtered and therefore client-specific, yet + both are cacheable by default: aTypeIndexServiceresponse under the ordinary + HTTP caching rules forGET[[!RFC9110]], and aTypeSearchService+ response per [[!RFC10008]], whose cache key is computed over the request body rather than + the requesting client. A server MUST ensure that an authorization-filtered response from + either service is never served from a shared cache to a different client. A server MUST mark + such responses so that they are not reused across clients (for example with +Cache-Control: privateorno-store) and MUST vary any cached entry + on the credential that scopes the result.Any extension query mechanism a server exposes over the storage — for example an @@ -460,6 +464,7 @@
Examples
Response HTTP/1.1 200 OK Content-Type: application/lws+json +Cache-Control: private Link: <https://example.org/types/index?page=1>; rel="first" Link: <https://example.org/types/index?page=2>; rel="next" Link: <https://example.org/types/index?page=4>; rel="last" @@ -629,12 +634,14 @@Security Considerations
rather than narrowing them.- - Shared Caches: Responses are client-specific by construction, yet a -
QUERYresponse is cacheable by default [[RFC10008]] and its cache key is - computed over the request body rather than the requesting client. Serving such a response - through a shared cache therefore risks delivering one client's authorization-filtered view - to another. The cache requirements in exist to - prevent this, and deserve particular attention when a shared cache sits in front of the + Shared Caches: Responses from both services are client-specific by + construction, yet both are cacheable by default: aTypeIndexService+GETresponse under the ordinary HTTP caching rules [[RFC9110]], and a +TypeSearchServiceQUERYresponse per [[RFC10008]], whose cache + key is computed over the request body rather than the requesting client. Serving either + through a shared cache risks delivering one client's authorization-filtered view to + another. The cache requirements in exist to prevent + this, and deserve particular attention when a shared cache sits in front of either service.Date: Wed, 1 Jul 2026 22:21:23 -0400 Subject: [PATCH 10/22] clarify that server-issued opaque page URIs may carry whatever they like --- lws10-searchindex/index.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 9d00598..92f94e1 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -219,7 +219,11 @@ GET [TypeIndexService]
are conveyed inLinkheaders—not in the response body—and are opaque to the client. The body lists the unique types of resources that currently exist within the storage and that the authenticated user is authorized to - see. This endpoint accepts no query parameters. + see. This specification defines no query parameters for the endpoint: a client + requests the advertisedserviceEndpointURI as-is, and any parameters + appearing in server-issued pagination URIs (such as?page=in the + example below) are server-internal parts of those opaque URIs, not part of this + interface.The Type Index takes no filter, so it is retrieved with a
From bd19131596d90c3a0a7cab8b89ff13e508408e47 Mon Sep 17 00:00:00 2001 From: Erich BremerGET. The Type Search Service, which carries a filter, instead uses the HTTP From 96c113c588ea7565b121b10930ce50d28197badf Mon Sep 17 00:00:00 2001 From: Erich BremerDate: Wed, 1 Jul 2026 22:23:07 -0400 Subject: [PATCH 11/22] fix grammer --- lws10-searchindex/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 92f94e1..369b7dc 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -272,9 +272,9 @@ QUERY [TypeSearchService]
support theapplication/lws+jsonfilter defined here as its baseline query format; a server MAY additionally accept other query formats, each identified by its own media type, and the authorization requirements of - apply regardless of the format used. Because theQUERYmethod is both safe and - idempotent [[!RFC9110]], a property [[!RFC10008]] requires of everyQUERY- request, a search never alters server state and MAY be repeated, retried, or cached. + apply regardless of the format used. TheQUERYmethod is both safe and + idempotent [[!RFC10008]], in the sense those terms are defined by [[!RFC9110]]: a + search never alters server state and MAY be repeated, retried, or cached. Because the filter travels in the body rather than the request URI, it is not subject to the request-URI length limits that constrain a query string.Date: Wed, 1 Jul 2026 22:26:41 -0400 Subject: [PATCH 12/22] adjust 422 claim --- lws10-searchindex/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 369b7dc..77e2370 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -394,7 +394,7 @@ Errors
A filter that is well-formed but exceeds the complexity a server chooses to support - (consistent with the expressiveness ceiling above) MUST be rejected with 422(Unprocessable Content) — the status [[!RFC10008]] designates for query content that is understood but cannot be processed. A server MUST NOT silently truncate or otherwise narrow such a filter, as doing so could return a superset of the intended results. + (consistent with the expressiveness ceiling above) MUST be rejected with422(Unprocessable Content), the status [[!RFC9110]] defines and [[!RFC10008]] suggests for a query that is understood but cannot be processed due to its actual contents. A server MUST NOT silently truncate or otherwise narrow such a filter, as doing so could return a superset of the intended results.A pagination reference (a previously issued nextlink) that the server no longer recognizes or that has expired MUST result in404(Not Found) or410(Gone); clients SHOULD restart the query from the first page. From 6487d3165b808a614177b60c8a96c46db2cc6de0 Mon Sep 17 00:00:00 2001 From: Erich BremerDate: Wed, 1 Jul 2026 22:33:25 -0400 Subject: [PATCH 13/22] add Authroization header to examples --- lws10-searchindex/index.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index 77e2370..ee2cdc2 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -230,6 +230,11 @@ GET [TypeIndexService]
QUERYmethod [[!RFC10008]] (see ).+Request +GET /types/index +Authorization: Bearer <token> + +Response HTTP/1.1 200 OK Content-Type: application/lws+json Cache-Control: private @@ -464,6 +469,7 @@Examples
Request GET /types/index +Authorization: Bearer <token> Response HTTP/1.1 200 OK @@ -500,6 +506,7 @@Examples
Request QUERY /types/search +Authorization: Bearer <token> Content-Type: application/lws+json { @@ -532,6 +539,7 @@Examples
Request QUERY /types/search +Authorization: Bearer <token> Content-Type: application/lws+json { @@ -558,6 +566,7 @@Examples
Request (nested array = OR group, outer array = AND) QUERY /types/search +Authorization: Bearer <token> Content-Type: application/lws+json { @@ -585,6 +594,7 @@Examples
Request (type AND a 'describedby' relation, the relation name used as a key) QUERY /types/search +Authorization: Bearer <token> Content-Type: application/lws+json { From 4ca89dffc2d067af4502f5e277b7d5c4a1daea06 Mon Sep 17 00:00:00 2001 From: Erich BremerDate: Wed, 1 Jul 2026 22:38:17 -0400 Subject: [PATCH 14/22] fix shortname --- lws10-searchindex/index.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lws10-searchindex/index.html b/lws10-searchindex/index.html index ee2cdc2..806d071 100644 --- a/lws10-searchindex/index.html +++ b/lws10-searchindex/index.html @@ -25,9 +25,9 @@ group: "lws", maxTocLevel: 3, localBiblio: { - "LWS-PROTOCOL": { - title: "LWS Protocol", - href: "https://www.w3.org/TR/lws-core/", + "LWS10-CORE": { + title: "Linked Web Storage Protocol 1.0", + href: "https://www.w3.org/TR/lws10-core/", publisher: "W3C", status: "FPWD", }, @@ -65,7 +65,7 @@ Introduction
- The [[!LWS-PROTOCOL|Linked Web Storage]] protocol defines a resource-centric storage + The [[!LWS10-CORE|Linked Web Storage]] protocol defines a resource-centric storage system built on HTTP. While the core protocol supports creating, reading, updating, and deleting resources, and containers enumerate the resources they contain, it does not define a mechanism for a client to learn which kinds of resources exist within a @@ -89,7 +89,7 @@
Terminology
The terms "storage", "storage description resource", "container", "data resource", - "resource manager", and "requesting agent" are defined by [[!LWS-PROTOCOL]]. + "resource manager", and "requesting agent" are defined by [[!LWS10-CORE]].
@@ -215,7 +215,7 @@
Type Index Service
GET [TypeIndexService]
Returns a paginated
TypeIndexasapplication/lws+json, - following the standard LWS pagination model defined by [[!LWS-PROTOCOL]]: page URIs + following the standard LWS pagination model defined by [[!LWS10-CORE]]: page URIs are conveyed inLinkheaders—not in the response body—and are opaque to the client. The body lists the unique types of resources that currently exist within the storage and that the authenticated user is authorized to @@ -357,7 +357,7 @@QUERY [TypeSearchService]
Whatever the response format, the result set is paginated following the standard LWS - pagination model defined by [[!LWS-PROTOCOL]]: page URIs are conveyed in
Link+ pagination model defined by [[!LWS10-CORE]]: page URIs are conveyed inLinkheaders — not in the response body — are opaque to the client, and are dereferenced to retrieve subsequent pages. Aside fromtypeand any additional relation keys described above, no other filter inputs are defined. @@ -724,7 +724,7 @@Vocabulary
This document also uses the terms
Storage,ContainerPage,service,serviceEndpoint,totalItems, and -itemsdefined by [[!LWS-PROTOCOL]] and the LWS JSON-LD context. +itemsdefined by [[!LWS10-CORE]] and the LWS JSON-LD context.