Introducing support for Containers in the LWS protocol#81
Conversation
Introduce the container model from the LWS Containers proposal with single containment semantics. Add new sections for container representation, container media type, and JSON-LD context/vocabulary. Update terminology across operations: partOf→up, contains→items, @id→id, @type→type, flatten item properties, adopt new media type (application/ld+json; profile="https://www.w3.org/ns/lws/v1"), and use Link header rel="type" for container creation instead of Content-Type-based type detection.
Add definitions for container, data resource, root container, and containment to the terminology section.
Define application/lws+json as the default media type for container representations, equivalent to application/ld+json with the LWS profile. Servers must return the same payload for application/lws+json, application/ld+json, and application/json — only the Content-Type header varies. Update IANA considerations with profile parameter, security considerations, and equivalence note following the Activity Streams precedent.
A container representation MUST include identifiers for all contained resources when the client has read access. Authorization-based filtering is not required; it is noted as an optional consideration with caveats about performance and caching. Sub-containers with appropriate access controls are suggested as an alternative.
|
|
||
| New resources are created using POST to a target container URI, with the server assigning the final identifier. Clients MAY suggest a name via the Slug header. Clients MAY provide initial user-managed metadata for the new resource by including one or more Link headers in the POST request, following the syntax of Web Linking in [[RFC8288]]. Server-managed metadata MUST be generated automatically by the server upon creation and MUST NOT be overridden by client-provided links. | ||
| On success, return the 201 status code with the new URI in the Location header. The server MUST include Link headers for key server-managed metadata, such as a link to the parent container (rel="partOf"), a link to the ACL resource (rel="acl"), and a link to its dedicated linkset resource (rel="linkset"; type="application/linkset+json"). Additional links SHOULD include rel="type" (indicating Container or DataResource) and rel="mediaType" if applicable. The body MAY be empty or include a minimal representation of the resource. All metadata creation and linking MUST be atomic with the resource creation to maintain consistency. | ||
| New resources are created using POST to a target container URI, with the server assigning the final identifier. Clients MAY suggest a name via the `Slug` header. Clients MAY provide initial user-managed metadata for the new resource by including one or more `Link` headers in the POST request, following the syntax of Web Linking in [[RFC8288]]. Server-managed metadata MUST be generated automatically by the server upon creation and MUST NOT be overridden by client-provided links. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| On success, return the 201 status code with the new URI in the Location header. The server MUST include Link headers for key server-managed metadata, such as a link to the parent container (rel="partOf"), a link to the ACL resource (rel="acl"), and a link to its dedicated linkset resource (rel="linkset"; type="application/linkset+json"). Additional links SHOULD include rel="type" (indicating Container or DataResource) and rel="mediaType" if applicable. The body MAY be empty or include a minimal representation of the resource. All metadata creation and linking MUST be atomic with the resource creation to maintain consistency. | ||
| New resources are created using POST to a target container URI, with the server assigning the final identifier. Clients MAY suggest a name via the `Slug` header. Clients MAY provide initial user-managed metadata for the new resource by including one or more `Link` headers in the POST request, following the syntax of Web Linking in [[RFC8288]]. Server-managed metadata MUST be generated automatically by the server upon creation and MUST NOT be overridden by client-provided links. | ||
|
|
||
| On success, return the 201 status code with the new URI in the `Location` header. The server MUST include `Link` headers for key server-managed metadata, such as a link to the parent container (`rel="up"`), a link to the ACL resource (`rel="acl"`), and a link to its dedicated linkset resource (`rel="linkset"; type="application/linkset+json"`). Additional links SHOULD include `rel="type"` (indicating `Container` or `DataResource`). The body MAY be empty or include a minimal representation of the resource. All metadata creation and linking MUST be atomic with the resource creation to maintain consistency. |
There was a problem hiding this comment.
ACL wording is probably old copy-paste things
There was a problem hiding this comment.
I suggest to not state "Container or DataResource" but instead "https://www.w3.org/ns/lws#Container or https://www.w3.org/ns/lws#DataResource"
|
This was discussed during the #lws meeting on 23 February 2026. View the transcriptw3c/lws-protocol#81laurens: more details about 81 bendm: the phrasing is quite strict right now laurens: correct; there was a lot of discussions about the original proposal being to flexible bendm: there is a MUST at some place, then a note says "MAY chose not to" laurens: typically, for spec text we would describe the minimum requirements <Zakim> acoburn, you wanted to ask about stictness and extensibility acoburn: to echo what bendm was saying, laurens: PR 81 supports only single containment. PR 83 softens it and adds the option to have multiple-containment. acoburn: great; woudl be good to comment that in the PR. pchampin: +1 on being prescriptive but also to echo Ben's concern <TallTed> If that NOTE is retained, such MUSTs SHOULD be changed to SHOULD. laurens: this is some more work needed on this section laurens: moving on to the section on Container Representation acoburn: I don't have a strong opinion on this laurens: I think we can modify that subsequently, once we have some implementation experience pchampin: +1 about conneg: one should be able to get JSON or JSON-LD, not sure it should be part of IANA considerations laurens: this is not in the IANA section, rather it is in the MediaType section laurens: it would be good is everyone could review this PR and comment on it <pchampin> s/subrobpic/subtopic/g <Zakim> acoburn, you wanted to ask about recursive delete acoburn: related to recursion; in my experience at Inrupt, there is a UX issue here. |
| Use POST to add a new resource inside an existing container. The server assigns an identifier to the resource, optionally suggested via the `Slug` header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources. Clients indicate the type of resource to create as follows: | ||
|
|
||
| - To create a **Container**, the client MUST include a `Link` header with `rel="type"` pointing to the Container type: `Link: <https://www.w3.org/ns/lws#Container>; rel="type"`. | ||
| - To create a **DataResource**, the client includes the resource content in the request body with the appropriate `Content-Type` header. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
This is one of those things that the user will want to do in one step ("{put|copy|mov} this folder and all its contents there"), which the software may need to do in several (create a container named xyz at location bcd, and put each of these documents inside it; and (for a move) after all that has succeeded, delete the originals).
Several pieces of ACID consideration come into play. We should NOT try to reinvent specifications for all these processes and activities, but learn from the wheels that already exist, and re-implement the things that have been previously specified.
There was a problem hiding this comment.
(I just saw next comment about #87 , we can continue there 👌 )
| In this example, the client is posting to the container `/alice/notes/`. It provides `text/plain` content (a grocery list) and suggests the name `shoppinglist.txt` for the new resource. If `/alice/notes/` exists and the client is authorized, the server will create a new DataResource and add it to the container's membership. | ||
|
|
||
| **Example (Response to POST):** | ||
| **Example (Response to POST — data resource):** |
There was a problem hiding this comment.
I suggest to consistently use the same term and capitalization (for easier searching in the spec doc). So maybe consistently use "Data Resource" (two words, title caps), so we can also differentiate our search with the rel-type URI?
| Content-Length: 0 | ||
| ``` | ||
| On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. Include relevant headers such as Content-Type matching the created resource; Content-Length: 0 indicates no body. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. | ||
| On success, return 201 Created with the new URI in the `Location` header. The body may be empty or a minimal representation. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. |
There was a problem hiding this comment.
Should we consistently write return statements as MUSTs for the server?
On success, the server MUST return
201 Created[...]
| ``` | ||
| On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. Include relevant headers such as Content-Type matching the created resource; Content-Length: 0 indicates no body. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. | ||
| On success, return 201 Created with the new URI in the `Location` header. The body may be empty or a minimal representation. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. | ||
| If the target container `/alice/notes/` does not exist, the server MUST return a 404 error status unless another status code is more appropriate. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
(auto-creation of target containers is probably also an optional capability, cfr the discussion of multi-parent containment of today)
There was a problem hiding this comment.
MUST [...] unless is a sign of multiple steps having been compressed into one. This often has some utility for humans, but it is a terrible way to specify software algorithms. Without reviewing the completeness or correctness of the analysis above, I will simply suggest that such compressed steps be de-compressed and each such algorithmic expression be stated with complete atomicity.
There was a problem hiding this comment.
Given that this is not a section of the spec which was modified in this PR I would propose to split this off into a separate issue.
| This creates a new container at `/alice/notes/`, with server-generated metadata including `rel="type"` as `https://www.w3.org/ns/lws#Container`. | ||
|
|
||
| **Additional notes on Create (HTTP binding):** | ||
| * POST is not idempotent. Repeating it may create duplicates; clients SHOULD avoid unintentional retries or use unique identifiers/checks to prevent this. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Humans rarely discuss recursive create or recursive delete, except in context of UNIX-like environments, and even there, recursive delete is only spoken of in context of specific implementations. Humans want to "delete this folder and everything in it", or "(copy or move) this folder and all its contents to that other location".
I do not think that recursive create and/or recursive delete should be tied together, because they do not really reflect the same capability, especially once they get described with full algorithmic steps. I may be proven wrong when such expression exists, but until that point I strongly believe that each activity should be explored only as itself, as I think it very likely that some implementation(s) will not support both of these conceptual features.
There was a problem hiding this comment.
@bjdmeest Could you maybe raise a separate issue clarifying what you mean by "recursive creation"?
| The delete resource operation is implemented using the HTTP DELETE method, as defined in the abstract operation above. This section specifies the HTTP bindings for inputs, behaviors, and responses. | ||
|
|
||
| The DELETE request targets the URI of the resource or container to remove. Clients MAY include an If-Match header with an ETag for concurrency checks, as described in the abstract operation. | ||
| The DELETE request targets the URI of the resource or container to remove. Clients MAY include an `If-Match` header with an ETag for concurrency checks, as described in the abstract operation. |
There was a problem hiding this comment.
I think mentions of 'abstract operation' is no longer relevant?
| For non-container resources, the server removes the resource content, its associated metadata (linkset), and the containment reference in the parent container. | ||
|
|
||
| On success, the server MUST respond with 204 No Content. Servers SHOULD support concurrency checks via If-Match with ETags; mismatches MUST yield 412 Precondition Failed. | ||
| For container resources, the server defaults to non-recursive deletion. If the container is not empty and recursion is not requested, the server MUST reject the request with 409 Conflict. If recursion is desired and supported, clients MUST use the `Depth: infinity` header, as defined in [[RFC4918]]. Servers that do not support recursion MUST reject such requests with 501 Not Implemented. |
There was a problem hiding this comment.
501 gives the impression that the server is not spec-compliant (but spec-aware). Why not either 500 or 405 and assume 'support for recursion' is an additional capability?
There was a problem hiding this comment.
In general, if a client supplies a header that is not supported by a server, the server simply ignores it. I would suggest aligning this behavior with general practice.
This file belongs in the multiple containment branch, not the single containment base.
| | System Managed | Maintained by the server; Read-Only. Includes acl, linkset, type, representation, sizeInBytes, modified. | | ||
| | Core Metadata | Managed by the client (subject to server restrictions). Includes partOf, contains, title, creator. | | ||
| | System Managed | Maintained by the server; Read-Only. Includes `acl`, `linkset`, `type`, `mediaType`, `size`, `modified`. | | ||
| | Core Metadata | Managed by the client (subject to server restrictions). Includes `up`, `items`, `title`, `creator`. | |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| |------------|------------| | ||
| | System Managed | Maintained by the server; Read-Only. Includes acl, linkset, type, representation, sizeInBytes, modified. | | ||
| | Core Metadata | Managed by the client (subject to server restrictions). Includes partOf, contains, title, creator. | | ||
| | System Managed | Maintained by the server; Read-Only. Includes `acl`, `linkset`, `type`, `mediaType`, `size`, `modified`. | |
| - Replacement (PUT): If advertised in the Allow header, a client MAY replace the entire linkset. If the server does not support PUT, it MUST reject the request with 405 Method Not Allowed. | ||
|
|
||
| - Restrictions: Servers MAY restrict modifications to specific links (like partOf or contains) to maintain system integrity. If a server restricts partOf modifications, it MUST document this in its conformance statement. | ||
| - Restrictions: Servers MAY restrict modifications to specific links (like `up` or `items`) to maintain system integrity. If a server restricts `up` modifications, it MUST document this in its conformance statement. |
There was a problem hiding this comment.
First time 'conformance statement' is mentioned
| In all cases, the server MUST include the following metadata in the response headers: an ETag (representing the listing version, which changes on membership modifications), and Link headers with rel="type" indicating it is a container, rel="linkset", rel="partOf", and rel="acl". | ||
| In this example, `/alice/notes/` is a container. The response uses JSON-LD with the LWS context, listing members with required metadata. Each item includes its `type`, `id`, `mediaType`, `size`, and `modified` timestamp as flat properties. | ||
|
|
||
| In all cases, the server MUST include the following metadata in the response headers: an ETag (representing the listing version, which changes on membership modifications), and Link headers with `rel="type"` indicating it is a container, `rel="linkset"`, `rel="up"`, and `rel="acl"`. |
|
|
||
| ### Container Creation | ||
| Container instantiation occurs via the standard resource creation operation (Section 7.1), differentiated by an indicator specifying the intent to establish a container rather than a non-container resource. This process yields an empty container amenable to subsequent population with members, including sub-containers to extend the hierarchy. Servers MUST assign identifiers, and empty containers MUST be supported. | ||
| ### Single Containment |
There was a problem hiding this comment.
As said during the call: I would refrain from restricting too much: instead, specify minimal MUSTs that do not preclude the option for multiple containment, but also not necessarily mention it already. Now this feels too strict: multiple-containment conformant servers should also 100% fulfill the requirements that are described below
There was a problem hiding this comment.
Move this to a separate PR and leave out the single containment text.
pchampin
left a comment
There was a problem hiding this comment.
I have reviewed everything except the section about Operations.
| Use POST to add a new resource inside an existing container. The server assigns an identifier to the resource, optionally suggested via the Slug header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources. Clients MUST include a Content-Type header in the request to indicate the media type of the new resource, enabling the server to distinguish between resource types. Specifically, servers MUST interpret the Content-Type as follows: if it matches the LWS-defined media type for containers (application/lws+json), the server creates a Container; otherwise, it creates a DataResource with the specified media type. | ||
| Use POST to add a new resource inside an existing container. The server assigns an identifier to the resource, optionally suggested via the `Slug` header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources. Clients indicate the type of resource to create as follows: | ||
|
|
||
| - To create a **Container**, the client MUST include a `Link` header with `rel="type"` pointing to the Container type: `Link: <https://www.w3.org/ns/lws#Container>; rel="type"`. The request body MAY be empty. |
There was a problem hiding this comment.
this partially addresses #77 but I'm still concerned about "the request body MAY be empty". I would rather have MUST here.
If that remains a MAY, we should therefore specify which content-type is allowed, and with which constraints (we can not let clients post arbitrary application/lws+json for creating a container, e.g. trying to pre-populate the container).
| - **Container** — a resource that contains other resources. | ||
| - **DataResource** — a data-bearing resource (e.g., a document, image, or structured data file). |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
@pchampin Essentially auxiliary resources like in Soild. The notion is important, so as to have general and extendible specification over operations over them. See #67
OTOH, Adding this as a category in above list may be is a category error. The distinction b/w containers and non-cotainers (data resources here) is about their intrinsic property of mereological capability. While distinction b/w primary resources and auxiliary/metadata resources is about their extrinsic property of their place in the layout relative to other resources. Thus that could be other axis of categorization based on place. Which has 3 categories of (storage root, contained, auxiliary/metadata).
There was a problem hiding this comment.
@damoo yes, basically what I'm after is re-introducing the notion of "auxiliary resource" as defined by Solid.
You are also not wrong about the "category error", but I would argue the current list is already more than just about mereology. A data resource is not any kind of leaf (i.e. non-container resource), but is the intersection of leaf and of your contained category... (granted, the current definition is not explicit about it, but I assume that this was the intent).
Another way to look at it is to consider two dimensions: whether a resource can contain other resources (container/leaf), and whether a resource is created/deleted by the server or by a client's request.
| server-managed | client-managed | |
|---|---|---|
| container | storage root | contained container |
| leaf | auxiliary resource | data resource |
The "storage root" category being a singleton (at least for each storage), I find it acceptable to present it as a special case of the more general category of "container", rather than as a separate category.
There was a problem hiding this comment.
@pchampin , Why I am after those semantics is: I want an "auxiliary container"/"metadata container" to hold METS metadatata with it's xml linking to other rdf metadata files in that container. Thus being container resource and metadata resource need not be mutually exclusive.
There was a problem hiding this comment.
I'm sorry, I really don't understand your comment here. What is METS metadata? what has xml to do with this?
| - **No orphans**: Every non-root resource MUST be reachable from the root container through the containment hierarchy. | ||
| - **No cycles**: The containment hierarchy MUST form a tree. A container MUST NOT directly or indirectly contain itself. |
There was a problem hiding this comment.
Noting that these two points are direct consequences of the "7.2 Single Containment", so it is a bit odd to repeat that here in the current state of the doc.
That being said, if (when?) 7.2 is relaxed to allow some implementations to support multiple-containment, then they will make sense. As I am in favor of eventually relaxing 7.2, let's keep them here for the moment :)
|
|
||
| A contained resource description SHOULD include: | ||
|
|
||
| - **`mediaType`**: The media type of the resource (e.g., `"text/plain"`, `"image/jpeg"`). MUST be present for DataResources. |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| - **`size`**: The size of the resource in bytes, expressed as an integer. | ||
| - **`modified`**: The date and time the resource was last modified, expressed as an ISO 8601 date-time string. | ||
|
|
||
| #### Property Summary |
There was a problem hiding this comment.
this table is barely more concise than the text above, and creates redundancy (which is error prone during maintenance).
I would rather remove it (but can live with it if I have to).
| For each core operation (create, read, update, delete), we describe the HTTP method(s) to use, required headers or special considerations (including concurrency controls via ETags, content negotiation, and pagination for container listings), and what the server should do and return. Standard HTTP status codes are used to indicate outcomes with additional mappings for scenarios such as quota exceeded (507 Insufficient Storage) or precondition failures (412 Precondition Failed). The binding tries to adhere to HTTP/1.1 and relevant RFCs (such as [[!RFC7231]] for HTTP semantics, [[!RFC7233]] for range requests, [[!RFC5789]] for PATCH, [[!RFC8288]] for Web Linking, and [[!RFC9264]] for Link Sets) so that it integrates naturally with web standards. Discoverability is emphasized through mechanisms like Link headers and WWW-Authenticate headers on 401 responses, avoiding hardcoded URI locations. Metadata integration is required across operations, ensuring atomicity and use of Link Sets for server-managed and user-managed properties. | ||
|
|
||
| **Note:** As all examples in this specifications, examples given in this section (HTTP request and response snippets) are **non-normative**, meant to illustrate typical usage. The actual requirements are stated in the descriptive text and tables. Also, while this binding covers HTTP (as the initial target protocol), the LWS operations could in principle be bound to other protocols in the future. Servers SHOULD support content negotiation for formats like JSON-LD (with normative contexts and optional framing for containers) and Turtle, using custom media types such as 'application/lws+json' where appropriate. No newline at end of file | ||
| **Note:** As all examples in this specifications, examples given in this section (HTTP request and response snippets) are **non-normative**, meant to illustrate typical usage. The actual requirements are stated in the descriptive text and tables. Also, while this binding covers HTTP (as the initial target protocol), the LWS operations could in principle be bound to other protocols in the future. Servers MUST support content negotiation for `application/lws+json`, `application/ld+json`, and `application/json` for container representations (see [Container Media Type](#container-media-type)). Servers MAY additionally support formats like Turtle. No newline at end of file |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| - Optional target attributes: Additional key-value pairs that further describe the link or the target resource. | ||
|
|
||
| Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For containers, metadata includes membership details and supports pagination to handle large sets efficiently. For DataResources, metadata includes representations, each with mediaType and optional sizeInBytes. | ||
| Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For containers, metadata includes membership details. For DataResources, metadata includes media type and size information. |
There was a problem hiding this comment.
"metadata includes membership details"
This is confusing. The paragraph above says that "All metadata in LWS is expressed as a set of typed link", which is not the case of membership detail. So membership details is not "metadata" as defined here.
Furthermore, as the membership details are part of the representation of the container, they indeed feel more like "data" than "metadata".
| @@ -0,0 +1,73 @@ | |||
| ### Container Representation | |||
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
| Use POST to add a new resource inside an existing container. The server assigns an identifier to the resource, optionally suggested via the `Slug` header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources. Clients indicate the type of resource to create as follows: | ||
|
|
||
| - To create a **Container**, the client MUST include a `Link` header with `rel="type"` pointing to the Container type: `Link: <https://www.w3.org/ns/lws#Container>; rel="type"`. | ||
| - To create a **DataResource**, the client includes the resource content in the request body with the appropriate `Content-Type` header. |
There was a problem hiding this comment.
This is one of those things that the user will want to do in one step ("{put|copy|mov} this folder and all its contents there"), which the software may need to do in several (create a container named xyz at location bcd, and put each of these documents inside it; and (for a move) after all that has succeeded, delete the originals).
Several pieces of ACID consideration come into play. We should NOT try to reinvent specifications for all these processes and activities, but learn from the wheels that already exist, and re-implement the things that have been previously specified.
| ``` | ||
| On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. Include relevant headers such as Content-Type matching the created resource; Content-Length: 0 indicates no body. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. | ||
| On success, return 201 Created with the new URI in the `Location` header. The body may be empty or a minimal representation. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. | ||
| If the target container `/alice/notes/` does not exist, the server MUST return a 404 error status unless another status code is more appropriate. |
There was a problem hiding this comment.
MUST [...] unless is a sign of multiple steps having been compressed into one. This often has some utility for humans, but it is a terrible way to specify software algorithms. Without reviewing the completeness or correctness of the analysis above, I will simply suggest that such compressed steps be de-compressed and each such algorithmic expression be stated with complete atomicity.
| This creates a new container at `/alice/notes/`, with server-generated metadata including `rel="type"` as `https://www.w3.org/ns/lws#Container`. | ||
|
|
||
| **Additional notes on Create (HTTP binding):** | ||
| * POST is not idempotent. Repeating it may create duplicates; clients SHOULD avoid unintentional retries or use unique identifiers/checks to prevent this. |
There was a problem hiding this comment.
Humans rarely discuss recursive create or recursive delete, except in context of UNIX-like environments, and even there, recursive delete is only spoken of in context of specific implementations. Humans want to "delete this folder and everything in it", or "(copy or move) this folder and all its contents to that other location".
I do not think that recursive create and/or recursive delete should be tied together, because they do not really reflect the same capability, especially once they get described with full algorithmic steps. I may be proven wrong when such expression exists, but until that point I strongly believe that each activity should be explored only as itself, as I think it very likely that some implementation(s) will not support both of these conceptual features.
| * **Behavior**: | ||
| * For non-container resources, the server returns the resource content. | ||
| * For containers, the server returns a listing of member resources. Listings must include core metadata for each member and must be filtered based on the requester's permissions. | ||
| * For containers, the server returns a listing of all member resources. Listings must include core metadata for each member. |
There was a problem hiding this comment.
This change would seem to violate permissions, as it would require the server to return a listing of "all member resources" including those for which I hold no READ permissions.
Similarly, I think that the preceding line should perhaps say, "the server returns the resource content IFF the requester has READ permissions on that resource."
There was a problem hiding this comment.
We should also be careful of the word "all" here, as that could be construed to mean that paging is not possible
| Content-Length: 0 | ||
| ``` | ||
| On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. Include relevant headers such as Content-Type matching the created resource; Content-Length: 0 indicates no body. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. | ||
| On success, return 201 Created with the new URI in the `Location` header. The body may be empty or a minimal representation. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. |
There was a problem hiding this comment.
Note that ETags should not be part of the successful response to a creation request. See #62
| ``` | ||
| HTTP/1.1 201 Created | ||
| Location: /alice/notes/ | ||
| ETag: "container-new-123" |
There was a problem hiding this comment.
An ETag is for representations. A response with no content should not have an etag header. It will mess with caches
| For non-container resources, the server removes the resource content, its associated metadata (linkset), and the containment reference in the parent container. | ||
|
|
||
| On success, the server MUST respond with 204 No Content. Servers SHOULD support concurrency checks via If-Match with ETags; mismatches MUST yield 412 Precondition Failed. | ||
| For container resources, the server defaults to non-recursive deletion. If the container is not empty and recursion is not requested, the server MUST reject the request with 409 Conflict. If recursion is desired and supported, clients MUST use the `Depth: infinity` header, as defined in [[RFC4918]]. Servers that do not support recursion MUST reject such requests with 501 Not Implemented. |
There was a problem hiding this comment.
In general, if a client supplies a header that is not supported by a server, the server simply ignores it. I would suggest aligning this behavior with general practice.
| On success, the server MUST respond with 204 No Content. Servers SHOULD support concurrency checks via If-Match with ETags; mismatches MUST yield 412 Precondition Failed. | ||
| For container resources, the server defaults to non-recursive deletion. If the container is not empty and recursion is not requested, the server MUST reject the request with 409 Conflict. If recursion is desired and supported, clients MUST use the `Depth: infinity` header, as defined in [[RFC4918]]. Servers that do not support recursion MUST reject such requests with 501 Not Implemented. | ||
|
|
||
| On success, the server MUST respond with 204 No Content. Servers SHOULD support concurrency checks via `If-Match` with ETags; mismatches MUST yield 412 Precondition Failed. |
There was a problem hiding this comment.
For concurrency checks, there is more than just If-Match. I would suggest being more generic here and just refer to conditional requests. See also #62
| * **Behavior**: | ||
| * For non-container resources, the server returns the resource content. | ||
| * For containers, the server returns a listing of member resources. Listings must include core metadata for each member and must be filtered based on the requester's permissions. | ||
| * For containers, the server returns a listing of all member resources. Listings must include core metadata for each member. |
There was a problem hiding this comment.
We should also be careful of the word "all" here, as that could be construed to mean that paging is not possible
|
|
||
| ### Resource Identification | ||
|
|
||
| Resources are identified by URIs. The URI of a resource is independent of its position in the containment hierarchy. Servers assign URIs during resource creation and MAY incorporate client hints (e.g., the `Slug` header), but clients MUST NOT assume that URI structure reflects containment. |
There was a problem hiding this comment.
Is "clients MUST NOT assume ..." too rigid? If another specification builds on LWS but adds requirements related to URI structure, this MUST NOT statement could get in the way. I would at least change it to SHOULD NOT
Co-authored-by: Pierre-Antoine Champin <pierre-antoine@w3.org>
|
This definition of data resource in terminology section precludes non-files - how can that be correct? "data resource — a data-bearing resource such as a document, image, or structured data file." |
| |------------|------------| | ||
| | System Managed | Maintained by the server; Read-Only. Includes acl, linkset, type, representation, sizeInBytes, modified. | | ||
| | Core Metadata | Managed by the client (subject to server restrictions). Includes partOf, contains, title, creator. | | ||
| | System Managed | Maintained by the server; Read-Only. Includes `linkset`, `type`, `mediaType`, `size`, `modified`. | |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
|
" root container — the top-level container in an LWS storage. The root container has no parent and acts as the entry point for the storage hierarchy. " Shouldn't this be plural as in there can be multiple root-level containers. |
|
"linkset — A separate resource associated with each LWS resource that contains the complete set of typed links (metadata) for that resource, as defined in [ RFC9264 ]. The linkset is discovered via a rel="linkset" link relation and can be modified to manage resource relationships, including containment." A linkset is not a separate resource necessarily, that is implementation specific (It would not be a separate resource in the TwinPod case), but it is a separate representation. |
|
7.1.. "Every LWS storage has a root container that serves as " should be has "one or more root containers" |
|
"The root container has no parent " The LWS storage has no parent |
|
Recommend that up includes an array of up resources to root container: "the rel="up" link relation. Servers " |
|
How does it make sense to list things that user has no access to and provide an implementation note specific so some particular implementation? |
| <li><dfn>container</dfn> — An LWS resource that maintains links to a set of contained resources whose lifecycle is governed by the same LWS server. Containers serve as organizational units enabling clients to group, discover, and navigate resources.</li> | ||
| <li><dfn>data resource</dfn> — a data-bearing resource such as a document, image, or structured data file.</li> | ||
| <li><dfn>contained resource</dfn> — A LWS resource, either a <a>container</a> or a <a>data resource</a>, that is referenced by one or more containers through a containment relationship.</li> | ||
| <li><dfn>root container</dfn> — the top-level container in an LWS storage. The root container has no parent and acts as the entry point for the storage hierarchy.</li> |
There was a problem hiding this comment.
Replace this with a top-level container
|
|
||
| <div class="note" role="note"> | ||
| <p><b>Authorization Considerations</b></p> | ||
| <p>Filtering container listings based on individual resource access could have significant performance implications and complicates caching.</p> |
acoburn
left a comment
There was a problem hiding this comment.
As discussed in LWS meeting on 2 Mar, 2026, I voted +1 to merge this
This PR continues on the discussions of the proposed mechanics for containers in LWS.
Changes from the initial discussions
Context
It is part of a series of three PRs:
Preview | Diff