From 253127429cadf59ffd01109a244e46242f10d7d4 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 11:33:51 +0100 Subject: [PATCH 01/21] feat: integrate core container model into LWS spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- lws10-core/Operations/create-resource.md | 42 ++++++++---- lws10-core/Operations/delete-resource.md | 13 ++-- lws10-core/Operations/metadata.md | 23 +++---- lws10-core/Operations/read-resource.md | 78 ++++++++++------------- lws10-core/Operations/restbinding.md | 2 +- lws10-core/container-media-type.md | 11 ++++ lws10-core/container-representation.md | 73 +++++++++++++++++++++ lws10-core/index.html | 15 +++++ lws10-core/jsonld-context.md | 62 ++++++++++++++++++ lws10-core/logicalresourceorganization.md | 55 ++++++++++------ 10 files changed, 282 insertions(+), 92 deletions(-) create mode 100644 lws10-core/container-media-type.md create mode 100644 lws10-core/container-representation.md create mode 100644 lws10-core/jsonld-context.md diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index 7f236f6..2eecb65 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -21,11 +21,15 @@ The **create resource** operation adds a new [served resource](#dfn-served-resou * **Conflict:** A resource with the generated identifier already exists, or there is another state conflict. * **Unknown Error:** An unexpected internal error occurred. -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. + +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. **POST (to a container URI)** – *Create with server-assigned name:* -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: ; rel="type"`. The request body MAY be empty. +- To create a **DataResource**, the client includes the resource content in the request body with the appropriate `Content-Type` header. **Example (POST to create a new data resource):** ``` @@ -35,6 +39,7 @@ Authorization: Bearer Content-Type: text/plain Content-Length: 47 Slug: shoppinglist.txt + milk eggs bread @@ -42,39 +47,50 @@ butter apples orange juice ``` -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 (based on the Content-Type), generate associated metadata, and link it via the linkset. +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):** ``` HTTP/1.1 201 Created Location: /alice/notes/shoppinglist.txt Content-Type: text/plain; charset=UTF-8 ETag: "def789012" Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="partOf" +Link: ; rel="up" Link: ; rel="acl" Link: ; rel="type" 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. If the target container `/alice/notes/` does not exist, the server MUST return a 404 error status unless another status code is more appropriate. -**Creating Containers:** To create a new container via the REST API, a client uses POST to an existing parent container, with the Content-Type header set to the LWS-defined media type `application/lws+json` to indicate container creation. The body MAY be empty. Servers MUST support creation of containers using this media type. For example: +**Creating Containers:** To create a new container, a client uses POST to an existing parent container with a `Link` header indicating the Container type. For example: ``` POST /alice/ HTTP/1.1 Host: example.com Authorization: Bearer -Content-Type: application/lws+json Content-Length: 0 Slug: notes +Link: ; rel="type" +``` + +**Example (Response to POST — container):** +``` +HTTP/1.1 201 Created +Location: /alice/notes/ +ETag: "container-new-123" +Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="up" +Link: ; rel="acl" +Link: ; rel="type" +Content-Length: 0 ``` -This would create a new container at `/alice/notes/`, with server-generated metadata including rel="type" as https://www.w3.org/ns/lws#Container. +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. -* Servers MUST distinguish between DataResource and Container types in metadata upon creation, based on the Content-Type header in the request. * Metadata updates are atomic; servers MUST ensure the linkset resource is created and populated with mandatory server-managed fields before returning success. -* For discoverability, servers SHOULD include a Link header with rel="storageDescription" on 401 responses to guide clients without hardcoded URIs. +* For discoverability, servers SHOULD include a `Link` header with `rel="storageDescription"` on 401 responses to guide clients without hardcoded URIs. **Managing and Retrieving Metadata (Related to Creation):** -While metadata is primarily retrieved via read operations, it is generated during creation. Clients can immediately retrieve it post-creation using GET or HEAD on the new resource URI. Clients can use the Prefer header to request inclusion of specific metadata links (via relation types) and attributes. +While metadata is primarily retrieved via read operations, it is generated during creation. Clients can immediately retrieve it post-creation using GET or HEAD on the new resource URI. Clients can use the `Prefer` header to request inclusion of specific metadata links (via relation types) and attributes. diff --git a/lws10-core/Operations/delete-resource.md b/lws10-core/Operations/delete-resource.md index 09806fd..ed6ded0 100644 --- a/lws10-core/Operations/delete-resource.md +++ b/lws10-core/Operations/delete-resource.md @@ -8,13 +8,16 @@ Permanently removes a resource and its associated metadata. 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. -For non-container resources, the server processes the deletion as specified in the abstract behavior. +**Deletion and Containment:** +When a resource is deleted, the server MUST atomically remove it from its parent container's `items` list. The parent container's `totalItems` count and ETag MUST be updated accordingly. -For container resources, the server defaults to non-recursive deletion. 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. +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. + +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. If the client lacks authorization, the server MUST return 403 Forbidden (if the client's identity is known but permissions are insufficient) or 401 Unauthorized (if no valid authentication is provided). In cases where revealing resource existence poses a security risk, the server MAY return 404 Not Found instead. @@ -24,7 +27,7 @@ DELETE /alice/notes/shoppinglist.txt HTTP/1.1 Authorization: Bearer If-Match: "abc123456" ``` -Assuming the ETag matches and the client is authorized, the server deletes the resource, its metadata, and updates the containing container `/alice/notes/` atomically: +Assuming the ETag matches and the client is authorized, the server deletes the resource, its metadata, and removes it from the parent container `/alice/notes/` atomically: ``` HTTP/1.1 204 No Content ``` diff --git a/lws10-core/Operations/metadata.md b/lws10-core/Operations/metadata.md index 1f9da51..dd47997 100644 --- a/lws10-core/Operations/metadata.md +++ b/lws10-core/Operations/metadata.md @@ -7,25 +7,26 @@ All metadata in LWS is expressed as a set of typed links originating from a reso - A relation type: A string that defines the nature of the relationship. - 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. **The Linkset Resource** For each resource in storage, a server MUST make metadata links available as a standalone resource according to [[!RFC9264]]. -- Discovery: A resource's linkset is discoverable via a Link header with the relation rel="linkset". -- Media Type: A linkset resource MUST be available as application/linkset+json. +- Discovery: A resource's linkset is discoverable via a Link header with the relation `rel="linkset"`. +- Media Type: A linkset resource MUST be available as `application/linkset+json`. - Integrity: The 'linkset' link MUST point to a server-managed resource. Updates to the linkset MUST be atomic with associated resource operations to maintain consistency. **Discovering Metadata** Clients discover metadata primarily through Link headers in response to GET or HEAD requests. -- Storage Description: Servers MUST support a Link header with rel="storageDescription" on relevant responses. -- Preferences: Clients MAY use the Prefer header [[!RFC7240]] with the URI https://www.w3.org/ns/lws#PreferLinkRelations to include or omit specific relations. +- Storage Description: Servers MUST support a Link header with `rel="storageDescription"` on relevant responses. +- Containment: Servers MUST include a Link header with `rel="up"` pointing to the parent container for any non-root resource. +- Preferences: Clients MAY use the Prefer header [[!RFC7240]] with the URI `https://www.w3.org/ns/lws#PreferLinkRelations` to include or omit specific relations. **Metadata Types** | Category | Description | |------------|------------| -| 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`. | | User-Defined | Custom vocabularies and indexes created by the user. | @@ -34,7 +35,7 @@ Core metadata MAY be modified by clients. To ensure interoperability, servers MU 1. Method Discovery: Servers MUST advertise support for GET and PATCH operations on the linkset resource via the Allow header. -2. Patch Format Discovery: Servers MUST advertise support for JSON Merge Patch [[!RFC7386]] via the Accept-Patch header: Accept-Patch: application/merge-patch+json. +2. Patch Format Discovery: Servers MUST advertise support for JSON Merge Patch [[!RFC7386]] via the Accept-Patch header: `Accept-Patch: application/merge-patch+json`. 3. Optional Methods: Servers MAY support PUT or alternative patch formats; if supported, these MUST be included in the Allow and Accept-Patch headers respectively. @@ -43,10 +44,10 @@ Core metadata MAY be modified by clients. To ensure interoperability, servers MU **Managing Metadata** Metadata is managed by interacting with the resource's associated linkset URI. Servers MUST support concurrency controls for updates. -- Partial Updates (PATCH): This is the primary mechanism for metadata management. Servers MUST support PATCH using application/merge-patch+json. +- Partial Updates (PATCH): This is the primary mechanism for metadata management. Servers MUST support PATCH using `application/merge-patch+json`. - 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. -- Lifecycle: Metadata lifecycles are tied to the described resource; deleting a resource MUST result in the automatic removal of its associated linkset metadata. \ No newline at end of file +- Lifecycle: Metadata lifecycles are tied to the described resource; deleting a resource MUST result in the automatic removal of its associated linkset metadata. diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md index 5d1aa1c..68cb09c 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -1,14 +1,14 @@ Retrieves the representation of an existing resource or the listing of a container. * **Inputs**: Target identifier and optional parameters. -* **Behavior**: - * For non-container resources, the server returns the resource content. +* **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. * **Outcome**: The requested representation or a notification of failure. -The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as rel="linkset", rel="acl", rel="partOf", and rel="type". Servers MUST ensure atomicity between the resource state and its metadata during reads. +The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset"`, `rel="acl"`, `rel="up"`, and `rel="type"`. Servers MUST ensure atomicity between the resource state and its metadata during reads. -**GET (non-container resource)** – *Retrieve a resource’s content:* +**GET (non-container resource)** – *Retrieve a resource's content:* Send GET to the resource URI for full content (if authorized). Respond with 200 OK, body containing the data, and Content-Type matching the stored media type. Servers MUST support range requests per [[!RFC7233]] for partial retrieval. Responses MUST include an ETag header for concurrency control and caching. **Example (GET a file):** @@ -24,9 +24,10 @@ Content-Type: text/plain; charset=UTF-8 Content-Length: 34 ETag: "abc123456" Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="partOf" +Link: ; rel="up" Link: ; rel="acl" Link: ; rel="type" + milk cheese bread @@ -36,12 +37,12 @@ chocolate bars hash eggs ``` -The server returned the text content (34 bytes in total, as indicated by `Content-Length`). The content is exactly the stored data in the file. The `ETag: "abc123456"` is a version identifier for caching or concurrency purposes. The response includes Link headers for metadata discoverability, with mandatory fields such as partOf, acl, and type. +The server returned the text content (34 bytes in total, as indicated by `Content-Length`). The content is exactly the stored data in the file. The `ETag: "abc123456"` is a version identifier for caching or concurrency purposes. The response includes Link headers for metadata discoverability, with mandatory fields such as `up`, `acl`, and `type`. -**GET (container resource)** – *List a container’s contents:* -When the target URI corresponds to a container (determined via metadata type), a GET request will return a listing of the container’s members rather than raw content. Servers MUST support pagination for large memberships, using query parameters or headers to return partial listings with links to subsequent pages, responding with 206 Partial Content for paginated responses. Listings MUST include metadata for each member: resource IDs (MUST), types as an array of system and user-defined (MUST), representations with mediaType and optional sizeInBytes (MUST for DataResources), modified timestamps (SHOULD). +**GET (container resource)** – *List a container's contents:* +When the target URI corresponds to a container (determined via metadata type), a GET request returns a listing of the container's members. The response body is a container representation as defined in the [Container Representation](#container-representation) section, using the LWS container media type. The listing includes metadata for each member: resource identifiers (MUST), types (MUST), media types (MUST for DataResources), sizes (SHOULD), and modification timestamps (SHOULD). -**Example (GET a container with JSON-LD):** +**Example (GET a container):** ``` GET /alice/notes/ HTTP/1.1 Authorization: Bearer @@ -53,47 +54,36 @@ HTTP/1.1 200 OK Content-Type: application/ld+json; profile="https://www.w3.org/ns/lws/v1" ETag: "container-etag-789" Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="partOf" +Link: ; rel="up" Link: ; rel="acl" Link: ; rel="type" + { - "@context": "https://www.w3.org/ns/lws/context/v1.jsonld", - "@id": "/alice/notes/", - "@type": "Container", + "@context": "https://www.w3.org/ns/lws/v1", + "id": "/alice/notes/", + "type": "Container", "totalItems": 2, - "first": { - "@type": "ContainerPage", - "@id": "/alice/notes/?page=1", - "partOf": "/alice/notes/", - "contains": [ - { - "@id": "/alice/notes/1.txt", - "@type": ["DataResource", "http://example.org/customType"], - "representation": [ - { - "mediaType": "text/plain", - "sizeInBytes": 1024 - } - ], - "modified": "2025-11-24T12:00:00Z" - }, - { - "@id": "/alice/notes/2.txt", - "@type": "DataResource", - "representation": [ - { - "mediaType": "text/plain", - "sizeInBytes": 2048 - } - ], - "modified": "2025-11-24T13:00:00Z" - } - ] - } + "items": [ + { + "type": "DataResource", + "id": "/alice/notes/shoppinglist.txt", + "mediaType": "text/plain", + "size": 47, + "modified": "2025-11-24T12:00:00Z" + }, + { + "type": ["DataResource", "http://example.org/customType"], + "id": "/alice/notes/todo.json", + "mediaType": "application/json", + "size": 2048, + "modified": "2025-11-24T13:00:00Z" + } + ] } ``` -In this example, `/alice/notes/` is a container. The response uses JSON-LD with a normative context, listing members with required metadata. For large containers, the response might include a "next" property and use 206 Partial Content. -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"`. **HEAD (any resource or container)** – *Headers/metadata only:* The LWS server MUST support HEAD [[RFC9110]] for both containers and non-containers, returning the same headers as GET (including ETag, Content-Type, Link for metadata) but without a body. This enables metadata retrieval without transferring content. diff --git a/lws10-core/Operations/restbinding.md b/lws10-core/Operations/restbinding.md index d799a7e..f27ac72 100644 --- a/lws10-core/Operations/restbinding.md +++ b/lws10-core/Operations/restbinding.md @@ -1,3 +1,3 @@ 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 SHOULD support content negotiation for formats like JSON-LD (with normative contexts for containers) and Turtle, using the LWS media type `application/ld+json; profile="https://www.w3.org/ns/lws/v1"` for container representations. \ No newline at end of file diff --git a/lws10-core/container-media-type.md b/lws10-core/container-media-type.md new file mode 100644 index 0000000..a3a85ca --- /dev/null +++ b/lws10-core/container-media-type.md @@ -0,0 +1,11 @@ +### Container Media Type + +Container representations MUST be served using the following media type: + +``` +application/ld+json; profile="https://www.w3.org/ns/lws/v1" +``` + +This media type indicates a JSON-LD document conforming to the LWS container vocabulary. Servers MUST use this media type in the `Content-Type` header when responding to requests for container resources. Clients MUST use this media type in the `Content-Type` header when creating new containers. + +Although container representations are valid JSON-LD, clients MAY process them as plain JSON without invoking a full JSON-LD processor. The `@context` property in the representation provides the mapping to the LWS vocabulary, but all property names used in container representations are short, predictable tokens (e.g., `id`, `type`, `items`, `totalItems`) that can be consumed directly as JSON keys. diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md new file mode 100644 index 0000000..077992c --- /dev/null +++ b/lws10-core/container-representation.md @@ -0,0 +1,73 @@ +### Container Representation + +When a client retrieves a container, the server returns a structured representation describing the container and its contents. This section defines the required and optional properties of a container representation. + +#### Container Properties + +A container representation MUST include the following properties: + +- **`id`**: The URI of the container. +- **`type`**: The value `"Container"`. +- **`totalItems`**: An integer indicating the total number of resources contained in the container. +- **`items`**: An array of contained resource descriptions (see below). If the container is empty, this MUST be an empty array. + +#### Contained Resource Description + +Each entry in the `items` array describes a resource contained in the container. A contained resource description MUST include: + +- **`id`**: The URI of the contained resource. +- **`type`**: The type of the resource. MUST be `"DataResource"` or `"Container"`. Servers MAY include additional user-defined types as an array (e.g., `["DataResource", "http://example.org/customType"]`). + +A contained resource description SHOULD include: + +- **`mediaType`**: The media type of the resource (e.g., `"text/plain"`, `"image/jpeg"`). MUST be present for DataResources. +- **`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 + +| Property | Required | Type | Description | +|----------|----------|------|-------------| +| `id` | MUST | URI | Identifier of the container | +| `type` | MUST | String | `"Container"` | +| `totalItems` | MUST | Integer | Total number of contained resources | +| `items` | MUST | Array | List of contained resource descriptions | + +**Contained resource properties:** + +| Property | Required | Type | Description | +|----------|----------|------|-------------| +| `id` | MUST | URI | Identifier of the contained resource | +| `type` | MUST | String or Array | `"DataResource"`, `"Container"`, or array including additional types | +| `mediaType` | MUST (DataResource) | String | Media type of the resource | +| `size` | SHOULD | Integer | Size in bytes | +| `modified` | SHOULD | DateTime | Last modification date-time | + +#### Example Container Representation + +The following example shows a container at `/alice/notes/` containing two resources: + +```json +{ + "@context": "https://www.w3.org/ns/lws/v1", + "id": "/alice/notes/", + "type": "Container", + "totalItems": 2, + "items": [ + { + "type": "DataResource", + "id": "/alice/notes/shoppinglist.txt", + "mediaType": "text/plain", + "size": 47, + "modified": "2025-11-24T12:00:00Z" + }, + { + "type": ["DataResource", "http://example.org/customType"], + "id": "/alice/notes/todo.json", + "mediaType": "application/json", + "size": 2048, + "modified": "2025-11-24T13:00:00Z" + } + ] +} +``` diff --git a/lws10-core/index.html b/lws10-core/index.html index eab0545..15afe78 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -212,6 +212,11 @@

Logical Resource Organization

+
+

Container Representation

+
+
+

Operations

@@ -241,6 +246,16 @@

Delete resource

+
+

Container Media Type

+
+
+ +
+

JSON-LD Context and Vocabulary

+
+
+

Resource Identification

diff --git a/lws10-core/jsonld-context.md b/lws10-core/jsonld-context.md new file mode 100644 index 0000000..7949e1d --- /dev/null +++ b/lws10-core/jsonld-context.md @@ -0,0 +1,62 @@ +### JSON-LD Context and Vocabulary + +#### Normative JSON-LD Context + +Container representations MUST include the following `@context` value: + +``` +"@context": "https://www.w3.org/ns/lws/v1" +``` + +The normative JSON-LD context document defines the mapping between the short property names used in container representations and their full URIs in the LWS and related vocabularies. The context is defined as follows: + +```json +{ + "@context": { + "@version": 1.1, + "@protected": true, + "lws": "https://www.w3.org/ns/lws#", + "as": "https://www.w3.org/ns/activitystreams#", + "schema": "https://schema.org/", + "xs": "http://www.w3.org/2001/XMLSchema#", + "id": "@id", + "type": "@type", + "Container": "lws:Container", + "DataResource": "lws:DataResource", + "items": "lws:items", + "totalItems": "as:totalItems", + "mediaType": "as:mediaType", + "size": { + "@id": "schema:size", + "@type": "xs:long" + }, + "modified": { + "@id": "as:updated", + "@type": "xs:dateTime" + } + } +} +``` + +The context is `@protected`, ensuring that the term definitions cannot be overridden by other contexts. + +#### Vocabulary + +The LWS vocabulary defines the following types and properties used in container representations: + +**Types:** + +| Term | URI | Description | +|------|-----|-------------| +| `Container` | `lws:Container` | A resource that contains other resources | +| `DataResource` | `lws:DataResource` | A data-bearing resource | + +**Properties:** + +| Term | URI | Description | +|------|-----|-------------| +| `items` | `lws:items` | The list of resources contained in a container | +| `totalItems` | `as:totalItems` | The total number of contained resources | +| `mediaType` | `as:mediaType` | The media type of a resource | +| `size` | `schema:size` | The size of a resource in bytes | +| `modified` | `as:updated` | The date-time a resource was last modified | diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 2511553..0c53e86 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -1,24 +1,43 @@ -### Logical Resource Organization -This section delineates the abstract data model governing the organization of resources within the Linked Web Storage (LWS) system. It encompasses the structuring of containers and resources, their hierarchical interrelations, the functional semantics of containers as organizational units, rules pertaining to containment, and mechanisms for clients to organize and navigate resource collections. This model establishes the logical namespace of the storage, delineating inter-resource relationships therein, without presupposing any specific identifier structure or semantic implications derived from identifier composition. Logical organization MUST prioritize discoverability and self-descriptive APIs, avoiding hardcoded locations. Containment is represented as metadata to enable multiple containers per resource without URL changes, supporting sharing use cases. All entities MUST have associated metadata resources using Link Sets (RFC 9264), distinguishing server-managed and user-managed data. +### Container Model -### Resource -In LWS, a resource constitutes the fundamental unit of storage and access. Each resource possesses a unique identifier within the system. A resource may encompass data, such as content or structured information, alongside associated metadata, including attributes like type or modification timestamps. Resources MUST be classified as 'DataResource', 'Container', or 'MetadataResource' via metadata types. DataResources MAY have multiple representations; servers MUST track original media types and support reification in metadata using the 'representation' property, which includes 'mediaType' and optional 'sizeInBytes'. +Linked Web Storage organizes resources into containers. A container is a specialized resource that holds references to other resources, called its members. Containers serve as organizational units, analogous to directories or collections, enabling clients to group, discover, and navigate resources. -### Container -A container represents a specialized resource type capable of encompassing other resources as members. Containers function as organizational constructs, facilitating the grouping of resources in a manner akin to collections or directories. A container maintains references to its member resources, which may comprise both non-container resources and additional container resources, thereby enabling hierarchical formations. Typically, a container holds minimal intrinsic content beyond metadata or enumerations of its members; its principal role is to aggregate and structure subordinate resources. The storage system's root is designated as a container, serving as the apex organizational unit devoid of a superior parent. Containers MUST support pagination for membership listings using 'ContainerPage' types, with properties such as 'first', 'next', 'prev', and 'last'. Representations MUST use JSON-LD with a specific frame and normative context, optionally advertising content negotiation via 'Vary: Accept' headers. Storage MAY function as a root container, enabling direct writes. +Every LWS storage has a **root container** that serves as the top-level organizational unit. The root container has no parent and acts as the entry point for the storage hierarchy. -### Containment and Hierarchy -With the exception of the root container, every resource is affiliated with precisely one parent container. This affiliation engenders a strict hierarchical structure, manifesting as a tree with a singular root container at its pinnacle. Upon creation within a designated container, a new resource becomes a member of that container, appearing within its membership enumeration. Cycles or multiple parent affiliations are prohibited within this model; a resource cannot concurrently belong to multiple containers without duplication or alternative referencing mechanisms external to the core containment framework. This constraint enhances model simplicity and aligns with conventional organizational paradigms. Containment MUST be modeled as metadata links using 'contains' (from container to member) and 'partOf' (from member to container), allowing transitive queries and multiple hierarchies without slash semantics. Servers MAY support hierarchy arrays for ancestors. +Resources in LWS are classified as either: -### Container Membership Management -Operations involving the creation, deletion, or relocation of resources influence container memberships as follows: -- Upon creation, a new resource is associated with a specified parent container. This association integrates the resource into the parent's membership. -- Deletion of a resource entails its removal from the parent container's membership. Should this render the container devoid of members, it assumes an empty state, potentially permitting its subsequent deletion if warranted. Container deletion typically necessitates an empty state or invokes recursive removal of members. -- The core operations (create, read, update, delete) do not incorporate an explicit relocation or renaming function. To reassign a resource to an alternative container, a client may replicate or recreate the resource in the target location followed by deletion of the original. Implementations may optionally extend non-core operations for relocation or renaming, achievable logically through combined creation and deletion. -Membership is managed via create/delete operations; direct updates to membership listings are server-managed and not client-writable to avoid concurrency issues. +- **Container** — a resource that contains other resources. +- **DataResource** — a data-bearing resource (e.g., a document, image, or structured data file). -### 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 -### Navigating and Listing Resources -Clients navigate the hierarchy through read operations on containers, which yield enumerations of member identifiers. A container's representation furnishes a listing of its members, enabling traversal and discovery of subordinate resources. Listings MUST include metadata for each member, such as resource IDs (MUST), types (array of system and user-defined), representations (MUST for DataResources, including mediaType and optional sizeInBytes), and modified timestamps (SHOULD). \ No newline at end of file +LWS enforces a **single containment** model: with the exception of the root container, every resource MUST belong to exactly one parent container. This produces a strict tree structure with the root container at its apex. + +The containment relationship between a resource and its parent container is expressed via the `rel="up"` link relation. 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. + +``` +Link: ; rel="up" +``` + +A container's members are listed in its representation using the `items` property. The server manages this list; clients cannot modify it directly. Membership changes occur as a side effect of resource creation and deletion. + +### Containment Integrity + +The server MUST maintain containment integrity at all times: + +- **Creation**: When a new resource is created in a container, the server MUST atomically add the resource to the container's `items` list. +- **Deletion**: When a resource is deleted, the server MUST atomically remove it from its parent container's `items` list. Deleting a container requires the container to be empty, unless recursive deletion is explicitly requested. +- **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. + +### 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. + +Containment relationships are expressed through metadata (`rel="up"` links and the `items` property in container representations), not through URI path structure. This separation allows servers flexibility in URI assignment while maintaining a well-defined organizational model. + +### Container Membership and Authorization + +A container's member listing is filtered by the requesting agent's permissions. When a client retrieves a container, the response MUST include only those member resources that the client is authorized to discover. The `totalItems` count in the container representation reflects the total number of accessible items for the requesting agent. + +Authorization is enforced per resource. A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. From e8dba98dc086b640abbe3226144bbbe13361d860 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 11:53:23 +0100 Subject: [PATCH 02/21] feat: add container terminology to definitions section Add definitions for container, data resource, root container, and containment to the terminology section. --- lws10-core/index.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lws10-core/index.html b/lws10-core/index.html index 15afe78..f6aa1ac 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -168,6 +168,10 @@

Terminology

capability such as a ZCAP.
  • authentication suite — a defined validation mechanism for a concrete serialization of an authentication credential.
  • +
  • container — a resource that holds references to other resources, called its members. Containers serve as organizational units enabling clients to group, discover, and navigate resources.
  • +
  • data resource — a data-bearing resource such as a document, image, or structured data file.
  • +
  • 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.
  • +
  • containment — the relationship between a container and its member resources, expressed via the items property in container representations and the rel="up" link relation in HTTP headers.
  • From b6bed3d2ae508e916230c35d9cefb2be2767a7eb Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 12:01:09 +0100 Subject: [PATCH 03/21] feat: define application/lws+json as default container media type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- lws10-core/IANA-Considerations.html | 39 +++++++++++++++++++++----- lws10-core/Operations/read-resource.md | 2 +- lws10-core/Operations/restbinding.md | 2 +- lws10-core/container-media-type.md | 18 ++++++++++-- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/lws10-core/IANA-Considerations.html b/lws10-core/IANA-Considerations.html index b64ee10..a8daaef 100644 --- a/lws10-core/IANA-Considerations.html +++ b/lws10-core/IANA-Considerations.html @@ -45,22 +45,33 @@

    OAuth Authorization Server Metadata Registry

    -

    Media Type Registry

    +

    The application/lws+json Media Type

    - This specification registers the application/lws+json media type for identifying documents conforming to the - linked web storage document format. + This specification registers the application/lws+json media type specifically for identifying documents + conforming to the Linked Web Storage container format.

    • - Type Name: application + Type name: application
    • - Subtype Name: lws+json + Subtype name: lws+json
    • - Required parameter: None + Required parameters: None +
    • +
    • + Optional parameters: profile: The profile parameter for the application/lws+json media type allows + one or more profile URIs to be specified. These profile URIs have the identifier semantics defined in [[RFC6906]]. + The "profile" media type parameter MUST be quoted. It contains a non-empty list of space-separated URIs (the profile URIs). +
      +profile-param = "profile=" profile-value
      +profile-value = <"> profile-URI 0*( 1*SP profile-URI ) <">
      +profile-URI   = URI
      +      
      + The "URI" in the above grammar refers to the "URI" as defined in Section 3 of [[RFC3986]].
    • Encoding considerations: Resources that use the application/lws+json media type are required to conform to @@ -68,7 +79,21 @@

      Media Type Registry

      considerations specified in Section 11 of [[RFC8259]].
    • - Contact: W3C Linked Web Storage Working Group public-lws-wg@w3.org + Security considerations: As defined in this specification. +
    • +
    • + Contact: W3C Linked Web Storage Working Group <public-lws-wg@w3.org>
    + +

    + Note that while the Linked Web Storage format uses JSON-LD conventions, there are a number of constraints and additional + requirements for LWS implementations that justify the use of a specific media type. +

    + +

    + Because LWS containers can be considered a restricted profile of JSON-LD, implementations SHOULD consider the + application/ld+json; profile="https://www.w3.org/ns/lws/v1" media type as equivalent to + application/lws+json. +

    diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md index 68cb09c..a419bb2 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -51,7 +51,7 @@ Accept: application/ld+json Assuming the container exists and the client has access: ``` HTTP/1.1 200 OK -Content-Type: application/ld+json; profile="https://www.w3.org/ns/lws/v1" +Content-Type: application/lws+json ETag: "container-etag-789" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" diff --git a/lws10-core/Operations/restbinding.md b/lws10-core/Operations/restbinding.md index f27ac72..f7b4d26 100644 --- a/lws10-core/Operations/restbinding.md +++ b/lws10-core/Operations/restbinding.md @@ -1,3 +1,3 @@ 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 for containers) and Turtle, using the LWS media type `application/ld+json; profile="https://www.w3.org/ns/lws/v1"` for container representations. \ 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 diff --git a/lws10-core/container-media-type.md b/lws10-core/container-media-type.md index a3a85ca..201e3f8 100644 --- a/lws10-core/container-media-type.md +++ b/lws10-core/container-media-type.md @@ -1,11 +1,23 @@ ### Container Media Type -Container representations MUST be served using the following media type: +The default media type for LWS container representations is: ``` -application/ld+json; profile="https://www.w3.org/ns/lws/v1" +application/lws+json ``` -This media type indicates a JSON-LD document conforming to the LWS container vocabulary. Servers MUST use this media type in the `Content-Type` header when responding to requests for container resources. Clients MUST use this media type in the `Content-Type` header when creating new containers. +While LWS container representations use JSON-LD conventions, the constraints and requirements for LWS justify the use of a specific media type. Because LWS containers can be considered a restricted profile of JSON-LD, implementations SHOULD consider the `application/ld+json; profile="https://www.w3.org/ns/lws/v1"` media type as equivalent to `application/lws+json`. + +#### Content Negotiation + +Servers MUST support content negotiation for container representations. The response payload MUST be identical regardless of the requested media type — only the `Content-Type` response header varies: + +- If a client requests `application/lws+json`, the server MUST respond with `Content-Type: application/lws+json`. +- If a client requests `application/ld+json`, the server MUST respond with `Content-Type: application/ld+json`. +- If a client requests `application/json`, the server MUST respond with `Content-Type: application/json`. + +In all three cases, the response body is the same JSON-LD document conforming to the LWS container vocabulary. Servers are free to support additional media types (e.g., `text/turtle`) through content negotiation. + +#### Processing as JSON Although container representations are valid JSON-LD, clients MAY process them as plain JSON without invoking a full JSON-LD processor. The `@context` property in the representation provides the mapping to the LWS vocabulary, but all property names used in container representations are short, predictable tokens (e.g., `id`, `type`, `items`, `totalItems`) that can be consumed directly as JSON keys. From ed3b22e2b694111e903247acb7de50f4ff5210db Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 15:37:17 +0100 Subject: [PATCH 04/21] chore: update terminology --- lws10-core/index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lws10-core/index.html b/lws10-core/index.html index f6aa1ac..0ffd969 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -168,10 +168,13 @@

    Terminology

    capability such as a ZCAP.
  • authentication suite — a defined validation mechanism for a concrete serialization of an authentication credential.
  • -
  • container — a resource that holds references to other resources, called its members. Containers serve as organizational units enabling clients to group, discover, and navigate resources.
  • +
  • LWS resource — An LWS Resource is a subset of information resources whose lifecycle is managed by the LWS storage.
  • +
  • container — 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.
  • data resource — a data-bearing resource such as a document, image, or structured data file.
  • +
  • contained resource — A LWS resource, either a container or a data resource, that is referenced by one or more containers through a containment relationship.
  • 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.
  • containment — the relationship between a container and its member resources, expressed via the items property in container representations and the rel="up" link relation in HTTP headers.
  • +
  • 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.
  • From 3b04b7c561594da8512dcb1d45aa676acd085d3e Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 15:53:04 +0100 Subject: [PATCH 05/21] fix: container listing must include all contained resources 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. --- lws10-core/Operations/manage-containment.md | 86 +++++++++++++++++++++ lws10-core/Operations/read-resource.md | 2 +- lws10-core/logicalresourceorganization.md | 9 ++- 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 lws10-core/Operations/manage-containment.md diff --git a/lws10-core/Operations/manage-containment.md b/lws10-core/Operations/manage-containment.md new file mode 100644 index 0000000..50b1a31 --- /dev/null +++ b/lws10-core/Operations/manage-containment.md @@ -0,0 +1,86 @@ +#### Managing Containment + +When multiple containment is enabled, resources MAY belong to more than one container. This section defines the operations for adding existing resources to containers and removing resources from containers without deleting the resource itself. + +##### Adding a Resource to a Container + +To add an existing resource to a container, a client sends a PATCH request to the target container's linkset resource using the `application/linkset-patch+json` media type. The patch body specifies the containment link to add. + +The server MUST verify that: +- The target container exists and the client is authorized to modify it. +- The resource to be added exists. +- Adding the resource would not create a cycle in the containment graph (no self-containment, no circular ancestry). + +On success, the server responds with 204 No Content. The container's `items` list and `totalItems` count are updated atomically. + +**Example (Add a resource to a container):** +``` +PATCH /alice/shared/.meta HTTP/1.1 +Authorization: Bearer +Content-Type: application/linkset-patch+json +If-Match: "meta-v3" + +{ + "add": { + "linkset": [ + { + "anchor": "/alice/shared/", + "item": [ + { "href": "/alice/notes/shoppinglist.txt" } + ] + } + ] + } +} +``` + +Response: +``` +HTTP/1.1 204 No Content +ETag: "meta-v4" +``` + +After this operation, `/alice/notes/shoppinglist.txt` appears in the `items` listing of both `/alice/notes/` and `/alice/shared/`. The resource now has two `rel="up"` links. + +##### Removing a Resource from a Container + +To remove a resource from a container without deleting the resource, a client sends a PATCH request to the container's linkset resource specifying the containment link to remove. + +The server MUST verify that: +- The target container exists and the client is authorized to modify it. +- The resource is currently a member of the target container. + +**Orphan handling:** If removing the resource from this container would leave it with no parent containers, the server MUST reject the request with 409 Conflict, unless the server supports orphan handling policies (e.g., automatic deletion of orphaned resources or moving them to a designated container). Servers that support automatic orphan handling MUST document their policy. + +On success, the server responds with 204 No Content. + +**Example (Remove a resource from a container):** +``` +PATCH /alice/shared/.meta HTTP/1.1 +Authorization: Bearer +Content-Type: application/linkset-patch+json +If-Match: "meta-v4" + +{ + "remove": { + "linkset": [ + { + "anchor": "/alice/shared/", + "item": [ + { "href": "/alice/notes/shoppinglist.txt" } + ] + } + ] + } +} +``` + +Response: +``` +HTTP/1.1 204 No Content +ETag: "meta-v5" +``` + +##### Concurrency Control + +All containment management operations MUST use optimistic concurrency control. Clients MUST include an `If-Match` header with the current ETag of the container's linkset resource. If the ETag does not match, the server MUST respond with 412 Precondition Failed. If the `If-Match` header is missing, the server MUST respond with 428 Precondition Required. diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md index a419bb2..57e9d5e 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -3,7 +3,7 @@ Retrieves the representation of an existing resource or the listing of a contain * **Inputs**: Target identifier and optional parameters. * **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. * **Outcome**: The requested representation or a notification of failure. The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset"`, `rel="acl"`, `rel="up"`, and `rel="type"`. Servers MUST ensure atomicity between the resource state and its metadata during reads. diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 0c53e86..d8c9573 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -38,6 +38,11 @@ Containment relationships are expressed through metadata (`rel="up"` links and t ### Container Membership and Authorization -A container's member listing is filtered by the requesting agent's permissions. When a client retrieves a container, the response MUST include only those member resources that the client is authorized to discover. The `totalItems` count in the container representation reflects the total number of accessible items for the requesting agent. +If a client has read access to a container, the container representation MUST include the identifiers for all resources contained in that container. -Authorization is enforced per resource. A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. +

    +

    Authorization Considerations

    +

    Servers MAY choose to filter the container listing based on the client's access to individual contained resources. However, implementers should be aware this approach could have significant performance implications and complicates caching. An alternative approach is to use sub-containers with appropriate access controls to organize resources by authorization requirements.

    +
    + +A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. From 310e576da2670b7aaf94b274bb20fb97c23dd831 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 16:00:37 +0100 Subject: [PATCH 06/21] chore: minor changes --- lws10-core/container-media-type.md | 6 +----- lws10-core/container-representation.md | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lws10-core/container-media-type.md b/lws10-core/container-media-type.md index 201e3f8..8bd09b5 100644 --- a/lws10-core/container-media-type.md +++ b/lws10-core/container-media-type.md @@ -1,4 +1,4 @@ -### Container Media Type +### LWS Media Type The default media type for LWS container representations is: @@ -17,7 +17,3 @@ Servers MUST support content negotiation for container representations. The resp - If a client requests `application/json`, the server MUST respond with `Content-Type: application/json`. In all three cases, the response body is the same JSON-LD document conforming to the LWS container vocabulary. Servers are free to support additional media types (e.g., `text/turtle`) through content negotiation. - -#### Processing as JSON - -Although container representations are valid JSON-LD, clients MAY process them as plain JSON without invoking a full JSON-LD processor. The `@context` property in the representation provides the mapping to the LWS vocabulary, but all property names used in container representations are short, predictable tokens (e.g., `id`, `type`, `items`, `totalItems`) that can be consumed directly as JSON keys. diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md index 077992c..9ca0f9c 100644 --- a/lws10-core/container-representation.md +++ b/lws10-core/container-representation.md @@ -29,7 +29,7 @@ A contained resource description SHOULD include: | Property | Required | Type | Description | |----------|----------|------|-------------| | `id` | MUST | URI | Identifier of the container | -| `type` | MUST | String | `"Container"` | +| `type` | MUST | String or Array | Must at least contain the value `"Container"`. | | `totalItems` | MUST | Integer | Total number of contained resources | | `items` | MUST | Array | List of contained resource descriptions | From 650531a13827ebf8f06ac3814c5a87216fc2414c Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 16:10:15 +0100 Subject: [PATCH 07/21] chore: minor changes --- lws10-core/Operations/create-resource.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index 2eecb65..7ce5867 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -28,7 +28,7 @@ On success, return the 201 status code with the new URI in the `Location` header **POST (to a container URI)** – *Create with server-assigned name:* 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: ; rel="type"`. The request body MAY be empty. +- To create a **Container**, the client MUST include a `Link` header with `rel="type"` pointing to the Container type: `Link: ; rel="type"`. - To create a **DataResource**, the client includes the resource content in the request body with the appropriate `Content-Type` header. **Example (POST to create a new data resource):** From fb0627ae5c4ad54d758eca8285bc2826dd1f5263 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 23 Feb 2026 17:04:39 +0100 Subject: [PATCH 08/21] chore: update section 7.5 --- lws10-core/logicalresourceorganization.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index d8c9573..9c7ef2f 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -38,11 +38,11 @@ Containment relationships are expressed through metadata (`rel="up"` links and t ### Container Membership and Authorization -If a client has read access to a container, the container representation MUST include the identifiers for all resources contained in that container. +If a client has read access to a container, the container representation MUST include the identifiers for resources contained in that container. Servers MAY filter the container listing based on the client's access to individual contained resources.

    Authorization Considerations

    -

    Servers MAY choose to filter the container listing based on the client's access to individual contained resources. However, implementers should be aware this approach could have significant performance implications and complicates caching. An alternative approach is to use sub-containers with appropriate access controls to organize resources by authorization requirements.

    +

    Filtering container listings based on individual resource access could have significant performance implications and complicates caching. An alternative approach is to use sub-containers with appropriate access controls to organize resources by authorization requirements.

    A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. From 3b88cd5f28dee5838240a9b5673702469970ede7 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Tue, 24 Feb 2026 08:30:53 +0100 Subject: [PATCH 09/21] chore: remove profile parameter from mediatype --- lws10-core/IANA-Considerations.html | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lws10-core/IANA-Considerations.html b/lws10-core/IANA-Considerations.html index a8daaef..0e344c9 100644 --- a/lws10-core/IANA-Considerations.html +++ b/lws10-core/IANA-Considerations.html @@ -62,17 +62,6 @@

    The application/lws+json Media Type

  • Required parameters: None
  • -
  • - Optional parameters: profile: The profile parameter for the application/lws+json media type allows - one or more profile URIs to be specified. These profile URIs have the identifier semantics defined in [[RFC6906]]. - The "profile" media type parameter MUST be quoted. It contains a non-empty list of space-separated URIs (the profile URIs). -
    -profile-param = "profile=" profile-value
    -profile-value = <"> profile-URI 0*( 1*SP profile-URI ) <">
    -profile-URI   = URI
    -      
    - The "URI" in the above grammar refers to the "URI" as defined in Section 3 of [[RFC3986]]. -
  • Encoding considerations: Resources that use the application/lws+json media type are required to conform to all of the requirements for the application/json media type and are therefore subject to the same encoding From b7769aa94b6dd2d58b65c376a78a12bc05af8e01 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Tue, 24 Feb 2026 08:36:36 +0100 Subject: [PATCH 10/21] chore: remove manage-containment from single containment branch This file belongs in the multiple containment branch, not the single containment base. --- lws10-core/Operations/manage-containment.md | 86 --------------------- 1 file changed, 86 deletions(-) delete mode 100644 lws10-core/Operations/manage-containment.md diff --git a/lws10-core/Operations/manage-containment.md b/lws10-core/Operations/manage-containment.md deleted file mode 100644 index 50b1a31..0000000 --- a/lws10-core/Operations/manage-containment.md +++ /dev/null @@ -1,86 +0,0 @@ -#### Managing Containment - -When multiple containment is enabled, resources MAY belong to more than one container. This section defines the operations for adding existing resources to containers and removing resources from containers without deleting the resource itself. - -##### Adding a Resource to a Container - -To add an existing resource to a container, a client sends a PATCH request to the target container's linkset resource using the `application/linkset-patch+json` media type. The patch body specifies the containment link to add. - -The server MUST verify that: -- The target container exists and the client is authorized to modify it. -- The resource to be added exists. -- Adding the resource would not create a cycle in the containment graph (no self-containment, no circular ancestry). - -On success, the server responds with 204 No Content. The container's `items` list and `totalItems` count are updated atomically. - -**Example (Add a resource to a container):** -``` -PATCH /alice/shared/.meta HTTP/1.1 -Authorization: Bearer -Content-Type: application/linkset-patch+json -If-Match: "meta-v3" - -{ - "add": { - "linkset": [ - { - "anchor": "/alice/shared/", - "item": [ - { "href": "/alice/notes/shoppinglist.txt" } - ] - } - ] - } -} -``` - -Response: -``` -HTTP/1.1 204 No Content -ETag: "meta-v4" -``` - -After this operation, `/alice/notes/shoppinglist.txt` appears in the `items` listing of both `/alice/notes/` and `/alice/shared/`. The resource now has two `rel="up"` links. - -##### Removing a Resource from a Container - -To remove a resource from a container without deleting the resource, a client sends a PATCH request to the container's linkset resource specifying the containment link to remove. - -The server MUST verify that: -- The target container exists and the client is authorized to modify it. -- The resource is currently a member of the target container. - -**Orphan handling:** If removing the resource from this container would leave it with no parent containers, the server MUST reject the request with 409 Conflict, unless the server supports orphan handling policies (e.g., automatic deletion of orphaned resources or moving them to a designated container). Servers that support automatic orphan handling MUST document their policy. - -On success, the server responds with 204 No Content. - -**Example (Remove a resource from a container):** -``` -PATCH /alice/shared/.meta HTTP/1.1 -Authorization: Bearer -Content-Type: application/linkset-patch+json -If-Match: "meta-v4" - -{ - "remove": { - "linkset": [ - { - "anchor": "/alice/shared/", - "item": [ - { "href": "/alice/notes/shoppinglist.txt" } - ] - } - ] - } -} -``` - -Response: -``` -HTTP/1.1 204 No Content -ETag: "meta-v5" -``` - -##### Concurrency Control - -All containment management operations MUST use optimistic concurrency control. Clients MUST include an `If-Match` header with the current ETag of the container's linkset resource. If the ETag does not match, the server MUST respond with 412 Precondition Failed. If the `If-Match` header is missing, the server MUST respond with 428 Precondition Required. From 33b9f194c4521d5989c7cc5c16104d68e85fe452 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 09:55:52 +0100 Subject: [PATCH 11/21] fix: apply suggestions from code review Co-authored-by: Pierre-Antoine Champin --- lws10-core/Operations/create-resource.md | 2 +- lws10-core/logicalresourceorganization.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index 7ce5867..59d8da8 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -23,7 +23,7 @@ The **create resource** operation adds a new [served resource](#dfn-served-resou 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. +On success, the server MUST return the 201 status code with the new URI in the `Location` header. The server MUST include `Link` headers for key server-managed metadata, including a link to the parent container (`rel="up"`), a link to the ACL resource (`rel="acl"`), and a link to the created resource's dedicated linkset resource (`rel="linkset"; type="application/linkset+json"`). Additional links SHOULD include `rel="type"` (indicating `https://www.w3.org/ns/lws#Container` or `https://www.w3.org/ns/lws#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. **POST (to a container URI)** – *Create with server-assigned name:* 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: diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 9c7ef2f..486b0fb 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -38,11 +38,11 @@ Containment relationships are expressed through metadata (`rel="up"` links and t ### Container Membership and Authorization -If a client has read access to a container, the container representation MUST include the identifiers for resources contained in that container. Servers MAY filter the container listing based on the client's access to individual contained resources. +If a client has read access to a container, the container representation MUST include the identifiers for all resources contained in that container to which the client has access. It MAY also contain the identifiers for resources contained in that container to which the client does not have access.

    Authorization Considerations

    -

    Filtering container listings based on individual resource access could have significant performance implications and complicates caching. An alternative approach is to use sub-containers with appropriate access controls to organize resources by authorization requirements.

    +

    Filtering container listings based on individual resource access could have significant performance implications and complicates caching.

    A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. From 2ae645795b4b2888c24123c274ec65884f2ca184 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:01:09 +0100 Subject: [PATCH 12/21] fix: remove acl mentions --- lws10-core/Operations/create-resource.md | 4 +--- lws10-core/Operations/metadata.md | 2 +- lws10-core/Operations/read-resource.md | 8 +++----- lws10-core/Operations/rest-table.md | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index 59d8da8..aa1e58c 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -23,7 +23,7 @@ The **create resource** operation adds a new [served resource](#dfn-served-resou 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, the server MUST return the 201 status code with the new URI in the `Location` header. The server MUST include `Link` headers for key server-managed metadata, including a link to the parent container (`rel="up"`), a link to the ACL resource (`rel="acl"`), and a link to the created resource's dedicated linkset resource (`rel="linkset"; type="application/linkset+json"`). Additional links SHOULD include `rel="type"` (indicating `https://www.w3.org/ns/lws#Container` or `https://www.w3.org/ns/lws#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. +On success, the server MUST return the 201 status code with the new URI in the `Location` header. The server MUST include `Link` headers for key server-managed metadata, including a link to the parent container (`rel="up"`), and a link to the created resource's dedicated linkset resource (`rel="linkset"; type="application/linkset+json"`). Additional links SHOULD include `rel="type"` (indicating `https://www.w3.org/ns/lws#Container` or `https://www.w3.org/ns/lws#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. **POST (to a container URI)** – *Create with server-assigned name:* 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: @@ -57,7 +57,6 @@ Content-Type: text/plain; charset=UTF-8 ETag: "def789012" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" -Link: ; rel="acl" Link: ; rel="type" Content-Length: 0 ``` @@ -81,7 +80,6 @@ Location: /alice/notes/ ETag: "container-new-123" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" -Link: ; rel="acl" Link: ; rel="type" Content-Length: 0 ``` diff --git a/lws10-core/Operations/metadata.md b/lws10-core/Operations/metadata.md index dd47997..33c1827 100644 --- a/lws10-core/Operations/metadata.md +++ b/lws10-core/Operations/metadata.md @@ -25,7 +25,7 @@ Clients discover metadata primarily through Link headers in response to GET or H | Category | Description | |------------|------------| -| System Managed | Maintained by the server; Read-Only. Includes `acl`, `linkset`, `type`, `mediaType`, `size`, `modified`. | +| System Managed | Maintained by the server; Read-Only. Includes `linkset`, `type`, `mediaType`, `size`, `modified`. | | Core Metadata | Managed by the client (subject to server restrictions). Includes `up`, `items`, `title`, `creator`. | | User-Defined | Custom vocabularies and indexes created by the user. | diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md index 57e9d5e..c34562e 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -6,7 +6,7 @@ Retrieves the representation of an existing resource or the listing of a contain * For containers, the server returns a listing of all member resources. Listings must include core metadata for each member. * **Outcome**: The requested representation or a notification of failure. -The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset"`, `rel="acl"`, `rel="up"`, and `rel="type"`. Servers MUST ensure atomicity between the resource state and its metadata during reads. +The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset"`, `rel="up"`, and `rel="type"`. Servers MUST ensure atomicity between the resource state and its metadata during reads. **GET (non-container resource)** – *Retrieve a resource's content:* Send GET to the resource URI for full content (if authorized). Respond with 200 OK, body containing the data, and Content-Type matching the stored media type. Servers MUST support range requests per [[!RFC7233]] for partial retrieval. Responses MUST include an ETag header for concurrency control and caching. @@ -25,7 +25,6 @@ Content-Length: 34 ETag: "abc123456" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" -Link: ; rel="acl" Link: ; rel="type" milk @@ -37,7 +36,7 @@ chocolate bars hash eggs ``` -The server returned the text content (34 bytes in total, as indicated by `Content-Length`). The content is exactly the stored data in the file. The `ETag: "abc123456"` is a version identifier for caching or concurrency purposes. The response includes Link headers for metadata discoverability, with mandatory fields such as `up`, `acl`, and `type`. +The server returned the text content (34 bytes in total, as indicated by `Content-Length`). The content is exactly the stored data in the file. The `ETag: "abc123456"` is a version identifier for caching or concurrency purposes. The response includes Link headers for metadata discoverability, with mandatory fields such as `up` and `type`. **GET (container resource)** – *List a container's contents:* When the target URI corresponds to a container (determined via metadata type), a GET request returns a listing of the container's members. The response body is a container representation as defined in the [Container Representation](#container-representation) section, using the LWS container media type. The listing includes metadata for each member: resource identifiers (MUST), types (MUST), media types (MUST for DataResources), sizes (SHOULD), and modification timestamps (SHOULD). @@ -55,7 +54,6 @@ Content-Type: application/lws+json ETag: "container-etag-789" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" -Link: ; rel="acl" Link: ; rel="type" { @@ -83,7 +81,7 @@ Link: ; rel="type" ``` 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"`. +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"` and `rel="up"`. **HEAD (any resource or container)** – *Headers/metadata only:* The LWS server MUST support HEAD [[RFC9110]] for both containers and non-containers, returning the same headers as GET (including ETag, Content-Type, Link for metadata) but without a body. This enables metadata retrieval without transferring content. diff --git a/lws10-core/Operations/rest-table.md b/lws10-core/Operations/rest-table.md index 74a8acf..73570db 100644 --- a/lws10-core/Operations/rest-table.md +++ b/lws10-core/Operations/rest-table.md @@ -2,7 +2,7 @@ This table maps generic LWS [responses](#dfn-responses) (from Section 8) to HTTP status codes and payloads for consistency, incorporating specific scenarios such as pagination, concurrency controls, quota constraints, and metadata integration: | LWS response | HTTP status code | HTTP payload | | ----- | ----- | ----- | -| [Success](#dfn-success) (read or update, returning data) | 200 OK | [Resource representation](#dfn-resource-representation) in the response body (for GET or if PUT/PATCH returns content), along with relevant headers (Content-Type, ETag, Link for metadata such as rel="linkset", rel="acl", rel="parent"). For container listings, include JSON-LD with normative context and member metadata (IDs, types, sizes, timestamps). | +| [Success](#dfn-success) (read or update, returning data) | 200 OK | [Resource representation](#dfn-resource-representation) in the response body (for GET or if PUT/PATCH returns content), along with relevant headers (Content-Type, ETag, Link for metadata such as rel="linkset", rel="up"). For container listings, include JSON-LD with normative context and member metadata (IDs, types, sizes, timestamps). | | [Created](#dfn-created) (new resource) | 201 Created | Typically no response body (or a minimal representation of the new resource). The `Location` header is set to the new resource’s URI. Headers like ETag MUST be included for concurrency; Link headers for server-managed metadata. | | Deleted (no content to return) | 204 No Content | No response body. Indicates the resource was deleted or the request succeeded and there’s nothing else to say. Servers MAY use 410 Gone for permanent deletions. | | Bad Request (invalid input or constraints) | 400 Bad Request | Error details explaining what was wrong. Servers SHOULD use the standard format defined in [[RFC9457]] for structured error responses, such as a JSON object with fields like "type", "title", "status", "detail", and "instance". | From 0fd4ead0e4af1895d65b939f4794ecc837c90f9b Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:26:51 +0100 Subject: [PATCH 13/21] fix: incorporate feedback --- lws10-core/Operations/create-resource.md | 6 ++---- lws10-core/Operations/delete-resource.md | 6 +++--- lws10-core/Operations/metadata.md | 5 +++-- lws10-core/index.html | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index aa1e58c..e5f1d77 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -49,18 +49,17 @@ orange juice ``` 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 — data resource):** +**Example (Response to POST — Data Resource):** ``` HTTP/1.1 201 Created Location: /alice/notes/shoppinglist.txt Content-Type: text/plain; charset=UTF-8 -ETag: "def789012" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" Link: ; rel="type" 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. 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. If the target container `/alice/notes/` does not exist, the server MUST return a 404 error status unless another status code is more appropriate. **Creating Containers:** To create a new container, a client uses POST to an existing parent container with a `Link` header indicating the Container type. For example: @@ -77,7 +76,6 @@ Link: ; rel="type" ``` HTTP/1.1 201 Created Location: /alice/notes/ -ETag: "container-new-123" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" Link: ; rel="type" diff --git a/lws10-core/Operations/delete-resource.md b/lws10-core/Operations/delete-resource.md index ed6ded0..1e4c146 100644 --- a/lws10-core/Operations/delete-resource.md +++ b/lws10-core/Operations/delete-resource.md @@ -8,16 +8,16 @@ Permanently removes a resource and its associated metadata. 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. **Deletion and Containment:** When a resource is deleted, the server MUST atomically remove it from its parent container's `items` list. The parent container's `totalItems` count and ETag MUST be updated accordingly. For non-container resources, the server removes the resource content, its associated metadata (linkset), and the containment reference in the parent container. -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. +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. Servers MAY support recursive deletion of all contained resources within the container that is being deleted. Clients MUST use the `Depth: infinity` header to request for a recursive delete, as defined in [[RFC4918]]. -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. +On success, the server MUST respond with 204 No Content. Servers SHOULD support conditional requests, as defined in [[RFC9110]]. If the client lacks authorization, the server MUST return 403 Forbidden (if the client's identity is known but permissions are insufficient) or 401 Unauthorized (if no valid authentication is provided). In cases where revealing resource existence poses a security risk, the server MAY return 404 Not Found instead. diff --git a/lws10-core/Operations/metadata.md b/lws10-core/Operations/metadata.md index 33c1827..8aacf74 100644 --- a/lws10-core/Operations/metadata.md +++ b/lws10-core/Operations/metadata.md @@ -7,7 +7,8 @@ All metadata in LWS is expressed as a set of typed links originating from a reso - A relation type: A string that defines the nature of the relationship. - 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. For DataResources, metadata includes media type and size information. +Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For Data Resources, metadata includes representations, each with mediaType and optional sizeInBytes. For Containers and Data Resources we consider the link to its parent container resource to be part of the metadata of the resource. + **The Linkset Resource** For each resource in storage, a server MUST make metadata links available as a standalone resource according to [[!RFC9264]]. @@ -48,6 +49,6 @@ Metadata is managed by interacting with the resource's associated linkset URI. S - 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 `up` or `items`) to maintain system integrity. If a server restricts `up` 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. - Lifecycle: Metadata lifecycles are tied to the described resource; deleting a resource MUST result in the automatic removal of its associated linkset metadata. diff --git a/lws10-core/index.html b/lws10-core/index.html index 0ffd969..d078d1a 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -171,7 +171,7 @@

    Terminology

  • LWS resource — An LWS Resource is a subset of information resources whose lifecycle is managed by the LWS storage.
  • container — 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.
  • data resource — a data-bearing resource such as a document, image, or structured data file.
  • -
  • contained resource — A LWS resource, either a container or a data resource, that is referenced by one or more containers through a containment relationship.
  • +
  • contained resource — A LWS resource, either a container or a data resource, that is referenced by one or more containers through a containment relationship.
  • 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.
  • containment — the relationship between a container and its member resources, expressed via the items property in container representations and the rel="up" link relation in HTTP headers.
  • 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.
  • From d523005aab93c138335c60ff05829a6d5a386480 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:28:31 +0100 Subject: [PATCH 14/21] fix: apply suggestion from @pchampin Co-authored-by: Pierre-Antoine Champin --- lws10-core/container-representation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md index 9ca0f9c..96636a9 100644 --- a/lws10-core/container-representation.md +++ b/lws10-core/container-representation.md @@ -16,7 +16,7 @@ A container representation MUST include the following properties: Each entry in the `items` array describes a resource contained in the container. A contained resource description MUST include: - **`id`**: The URI of the contained resource. -- **`type`**: The type of the resource. MUST be `"DataResource"` or `"Container"`. Servers MAY include additional user-defined types as an array (e.g., `["DataResource", "http://example.org/customType"]`). +- **`type`**: The type of the resource. MUST be `"DataResource"` or `"Container"`, or an array containing at least one of these two strings. Servers MAY include additional user-defined types as URIs (e.g., `["DataResource", "http://example.org/customType"]`). A contained resource description SHOULD include: From 41f0f394e64fb4ecdfc4c83d7c759acbd36170d3 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:37:03 +0100 Subject: [PATCH 15/21] fix: apply suggestion from @pchampin Co-authored-by: Pierre-Antoine Champin --- lws10-core/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lws10-core/index.html b/lws10-core/index.html index d078d1a..3cd44ec 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -168,7 +168,7 @@

    Terminology

    capability such as a ZCAP.
  • authentication suite — a defined validation mechanism for a concrete serialization of an authentication credential.
  • -
  • LWS resource — An LWS Resource is a subset of information resources whose lifecycle is managed by the LWS storage.
  • +
  • LWS resource — An LWS Resource is an information resource whose lifecycle is managed by the LWS storage.
  • container — 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.
  • data resource — a data-bearing resource such as a document, image, or structured data file.
  • contained resource — A LWS resource, either a container or a data resource, that is referenced by one or more containers through a containment relationship.
  • From cb2c892c32a1672e9ec49212b004afd40a83d7b6 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:38:27 +0100 Subject: [PATCH 16/21] fix: incorporate feedback --- lws10-core/container-representation.md | 21 +-------------------- lws10-core/logicalresourceorganization.md | 2 +- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md index 9ca0f9c..ce7faf3 100644 --- a/lws10-core/container-representation.md +++ b/lws10-core/container-representation.md @@ -8,7 +8,7 @@ A container representation MUST include the following properties: - **`id`**: The URI of the container. - **`type`**: The value `"Container"`. -- **`totalItems`**: An integer indicating the total number of resources contained in the container. +- **`totalItems`**: An integer indicating the total number of resources contained in the container which can be disclosed to the client. - **`items`**: An array of contained resource descriptions (see below). If the container is empty, this MUST be an empty array. #### Contained Resource Description @@ -24,25 +24,6 @@ A contained resource description SHOULD include: - **`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 - -| Property | Required | Type | Description | -|----------|----------|------|-------------| -| `id` | MUST | URI | Identifier of the container | -| `type` | MUST | String or Array | Must at least contain the value `"Container"`. | -| `totalItems` | MUST | Integer | Total number of contained resources | -| `items` | MUST | Array | List of contained resource descriptions | - -**Contained resource properties:** - -| Property | Required | Type | Description | -|----------|----------|------|-------------| -| `id` | MUST | URI | Identifier of the contained resource | -| `type` | MUST | String or Array | `"DataResource"`, `"Container"`, or array including additional types | -| `mediaType` | MUST (DataResource) | String | Media type of the resource | -| `size` | SHOULD | Integer | Size in bytes | -| `modified` | SHOULD | DateTime | Last modification date-time | - #### Example Container Representation The following example shows a container at `/alice/notes/` containing two resources: diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 486b0fb..5422c40 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -32,7 +32,7 @@ The server MUST maintain containment integrity at all times: ### 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. +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 SHOULD NOT assume that URI structure reflects containment. Containment relationships are expressed through metadata (`rel="up"` links and the `items` property in container representations), not through URI path structure. This separation allows servers flexibility in URI assignment while maintaining a well-defined organizational model. From 5a60a4be5985c378377b5c1d184bc334cc0905c5 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:45:56 +0100 Subject: [PATCH 17/21] fix: clarify authz relation to read operations --- lws10-core/Operations/read-resource.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md index c34562e..409b7ff 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -3,7 +3,7 @@ Retrieves the representation of an existing resource or the listing of a contain * **Inputs**: Target identifier and optional parameters. * **Behavior**: * For non-container resources, the server returns the resource content. - * For containers, the server returns a listing of all member resources. Listings must include core metadata for each member. + * For containers, the server returns a listing of member resources which MAY be filtered based on authorization. Listings must include core metadata for each member. * **Outcome**: The requested representation or a notification of failure. The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset"`, `rel="up"`, and `rel="type"`. Servers MUST ensure atomicity between the resource state and its metadata during reads. From b1db70eee12901627b4d7116738c2127cd05b421 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 10:50:46 +0100 Subject: [PATCH 18/21] chore: update media type section --- lws10-core/Discovery.html | 2 +- lws10-core/container-representation.md | 2 +- lws10-core/index.html | 6 +++--- lws10-core/{container-media-type.md => lws-media-type.md} | 6 +----- 4 files changed, 6 insertions(+), 10 deletions(-) rename lws10-core/{container-media-type.md => lws-media-type.md} (90%) diff --git a/lws10-core/Discovery.html b/lws10-core/Discovery.html index 895130e..4849405 100644 --- a/lws10-core/Discovery.html +++ b/lws10-core/Discovery.html @@ -2,7 +2,7 @@

    Storage Description Resource

    - A storage description resource provides information a client can use + A storage description resource provides information a client can use when interacting with a storage, including descriptions of capabilities and service endpoints.

    diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md index 41eb2ac..c08256a 100644 --- a/lws10-core/container-representation.md +++ b/lws10-core/container-representation.md @@ -1,6 +1,6 @@ ### Container Representation -When a client retrieves a container, the server returns a structured representation describing the container and its contents. This section defines the required and optional properties of a container representation. +When a client retrieves a container, the server returns a structured container representation describing the container and its contents. This section defines the required and optional properties of a container representation. #### Container Properties diff --git a/lws10-core/index.html b/lws10-core/index.html index 3cd44ec..292fd25 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -253,9 +253,9 @@

    Delete resource

    -
    -

    Container Media Type

    -
    +
    +

    LWS Media Type

    +
    diff --git a/lws10-core/container-media-type.md b/lws10-core/lws-media-type.md similarity index 90% rename from lws10-core/container-media-type.md rename to lws10-core/lws-media-type.md index 8bd09b5..5f56618 100644 --- a/lws10-core/container-media-type.md +++ b/lws10-core/lws-media-type.md @@ -1,10 +1,6 @@ ### LWS Media Type -The default media type for LWS container representations is: - -``` -application/lws+json -``` +LWS container representation and storage description resource MUST use the media type `application/lws+json`. While LWS container representations use JSON-LD conventions, the constraints and requirements for LWS justify the use of a specific media type. Because LWS containers can be considered a restricted profile of JSON-LD, implementations SHOULD consider the `application/ld+json; profile="https://www.w3.org/ns/lws/v1"` media type as equivalent to `application/lws+json`. From e2ab194a1ca1c6b9931fb73a9219d985335a6d69 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 17:08:01 +0100 Subject: [PATCH 19/21] fix: editorial changes --- lws10-core/index.html | 2 +- lws10-core/logicalresourceorganization.md | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lws10-core/index.html b/lws10-core/index.html index 292fd25..cdc4991 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -172,7 +172,7 @@

    Terminology

  • container — 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.
  • data resource — a data-bearing resource such as a document, image, or structured data file.
  • contained resource — A LWS resource, either a container or a data resource, that is referenced by one or more containers through a containment relationship.
  • -
  • 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.
  • +
  • root container — a top-level container in an LWS storage. A root container has no parent and acts as the entry point for the storage hierarchy.
  • containment — the relationship between a container and its member resources, expressed via the items property in container representations and the rel="up" link relation in HTTP headers.
  • 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.
  • diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 5422c40..6f444ea 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -40,9 +40,4 @@ Containment relationships are expressed through metadata (`rel="up"` links and t If a client has read access to a container, the container representation MUST include the identifiers for all resources contained in that container to which the client has access. It MAY also contain the identifiers for resources contained in that container to which the client does not have access. -
    -

    Authorization Considerations

    -

    Filtering container listings based on individual resource access could have significant performance implications and complicates caching.

    -
    - A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. From 96e5016bc792b8d852f2258c31c23b96aaa0c414 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 17:11:50 +0100 Subject: [PATCH 20/21] fix: remove section on single containment --- lws10-core/logicalresourceorganization.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 6f444ea..b8ddb1f 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -9,18 +9,6 @@ Resources in LWS are classified as either: - **Container** — a resource that contains other resources. - **DataResource** — a data-bearing resource (e.g., a document, image, or structured data file). -### Single Containment - -LWS enforces a **single containment** model: with the exception of the root container, every resource MUST belong to exactly one parent container. This produces a strict tree structure with the root container at its apex. - -The containment relationship between a resource and its parent container is expressed via the `rel="up"` link relation. 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. - -``` -Link: ; rel="up" -``` - -A container's members are listed in its representation using the `items` property. The server manages this list; clients cannot modify it directly. Membership changes occur as a side effect of resource creation and deletion. - ### Containment Integrity The server MUST maintain containment integrity at all times: From 0e34292f6d3f493101efa17604db92d435741307 Mon Sep 17 00:00:00 2001 From: Laurens Debackere Date: Mon, 2 Mar 2026 17:11:55 +0100 Subject: [PATCH 21/21] fix: remove section on single containment --- lws10-core/logicalresourceorganization.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index b8ddb1f..3792506 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -9,6 +9,16 @@ Resources in LWS are classified as either: - **Container** — a resource that contains other resources. - **DataResource** — a data-bearing resource (e.g., a document, image, or structured data file). +### Containment + +The containment relationship between a resource and its parent container is expressed via the `rel="up"` link relation. 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. + +``` +Link: ; rel="up" +``` + +A container's members are listed in its representation using the `items` property. The server manages this list; clients cannot modify it directly. Membership changes occur as a side effect of resource creation and deletion. + ### Containment Integrity The server MUST maintain containment integrity at all times: @@ -16,7 +26,7 @@ The server MUST maintain containment integrity at all times: - **Creation**: When a new resource is created in a container, the server MUST atomically add the resource to the container's `items` list. - **Deletion**: When a resource is deleted, the server MUST atomically remove it from its parent container's `items` list. Deleting a container requires the container to be empty, unless recursive deletion is explicitly requested. - **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. +- **No cycles**: A container MUST NOT directly or indirectly contain itself. ### Resource Identification