From 5d014ff9ad4f6a0636c7dfb543cc7b85c9ff41d3 Mon Sep 17 00:00:00 2001 From: damodara Date: Mon, 30 Mar 2026 15:59:02 +0530 Subject: [PATCH 1/2] introduce auxiliary resources and manifest (#67) --- lws10-core/Operations/create-resource.md | 90 ++++++++++++++++++----- lws10-core/Operations/delete-resource.md | 28 +++++-- lws10-core/Operations/metadata.md | 23 +++--- lws10-core/Operations/read-resource.md | 66 +++++++++++------ lws10-core/Operations/rest-table.md | 2 +- lws10-core/Operations/restbinding.md | 2 +- lws10-core/Operations/update-resource.md | 6 +- lws10-core/container-representation.md | 54 -------------- lws10-core/index.html | 22 ++++-- lws10-core/jsonld-context.md | 20 ++--- lws10-core/logicalresourceorganization.md | 90 ++++++++++++++++------- lws10-core/lws-media-type.md | 8 +- lws10-core/manifest-representation.md | 77 +++++++++++++++++++ 13 files changed, 322 insertions(+), 166 deletions(-) delete mode 100644 lws10-core/container-representation.md create mode 100644 lws10-core/manifest-representation.md diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index e5f1d77..b91fdc5 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -1,15 +1,16 @@ -The **create resource** operation adds a new [served resource](#dfn-served-resource) to an existing [container](#dfn-container). This operation handles both the creation of data resources (files) and sub-containers. +The **create resource** operation adds a new [served resource](#dfn-served-resource) to an existing [patron](#dfn-patron). This operation handles both the creation of contained resources and auxiliary resources. **Inputs:** -* **Target container:** The identifier of the container where the new resource will be created. +* **Target patron:** The identifier of the patron where the new resource will be created either as an auxiliary member or as a contained member if the target is a container. +* **membership link:** The link from the new resource to the target patron. If the new resource is to be a contained member of the container patron, new resource is linked to the patron container via `rel="up"`. If the new resource is to be a auxiliary member of the patron, new resource is linked to the patron via `rel="principal"`, and patron resource is linked to the new resource via the auxiliaryRel of the relation. * **Identity hint:** An optional suggestion for the new resource's identifier. The server may use this hint but is not required to. * **Content:** The initial content and type for the new resource. **Behavior:** -* **Identity generation:** The server determines the final identifier (URI) for the new resource. If an identity hint was provided, the server attempts to incorporate it while ensuring uniqueness and validity within the container. If no hint is provided, the server generates a unique identifier. -* **Container membership update:** The server atomically adds the new resource to the membership listing of the target container. +* **Identity generation:** The server determines the final identifier (URI) for the new resource. If an identity hint was provided, the server attempts to incorporate it while ensuring uniqueness and validity within the scope of the patron resource. If no hint is provided, the server generates a unique identifier. +* **Patron membership update:** The server atomically adds the new resource to the contained/auxiliary membership of the target patron by updating its manifest. It uses the provided membership links to determine the type of membership. * **Metadata initialization:** The server initializes system metadata for the new resource. If the resource has an associated metadata resource it is also initialized. **Possible Responses:** @@ -18,20 +19,26 @@ The **create resource** operation adds a new [served resource](#dfn-served-resou * **Target Not Found:** The specified target container does not exist. * **Not Permitted:** The client's identity is known, but they do not have permission to create resources in this container. * **Unknown Requester:** The server does not recognize the client's identity and requires authentication. -* **Conflict:** A resource with the generated identifier already exists, or there is another state conflict. +* **Conflict:** A resource with the generated identifier already exists, or requested membership is not possible for the target patron (like creating contained member on non-containers, or creating auxiliary resource with already occupied auxiliaryRel, or requesting containment capability on the auxiliary resource to create, etc.), 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. +New resources are created using POST to a target patron resource 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. Server-managed auxiliary resources MUST be generated automatically by the server upon creation of a contained primary resource. -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. +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 patron (via `rel="up"` for contained, via `rel="principal"` for auxiliary), and links to the created resource's Server-managed auxiliary resources (`rel="linkset"; type="application/linkset+json"`). Additional links SHOULD include `rel="type"` (indicating `https://www.w3.org/ns/lws#Container`, `https://www.w3.org/ns/lws#Resource` ,etc). 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: +**POST (to a patron URI)** – *Create with server-assigned name:* +Use POST to add a new resource to an existing patron resource, either as an auxiliary member or contained member if the target is a 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 membership as follows: + +- To create a **Contained member**, the client MUST include a `Link` header with `rel="up"` pointing to the target patron container. +- To create an **Auxiliary member**, the client MUST include a `Link` header with `rel="principal"` pointing to the target principal resource. The client MUST also include a `Link` header with the `anchor` parameter set to the target principal resource, `rel` value set to the required auxiliaryRel, pointing to the new resource to create using an empty URI reference `<>`. + +Clients indicate the containment capability of the contained member 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"`. -- 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):** +**Example (POST to create a new leaf resource):** ``` POST /alice/notes/ HTTP/1.1 Host: example.com @@ -39,6 +46,7 @@ Authorization: Bearer Content-Type: text/plain Content-Length: 47 Slug: shoppinglist.txt +Link: rel="up" milk eggs @@ -47,28 +55,30 @@ 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 and add it to the container's membership. +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. It provides membership link with `rel="up"` pointing to the current container, requesting to be a contained member. If `/alice/notes/` exists and the client is authorized, the server will create a new Resource and add it to the container's membership. -**Example (Response to POST — Data Resource):** +**Example (Response to POST — Leaf Resource):** ``` HTTP/1.1 201 Created Location: /alice/notes/shoppinglist.txt Content-Type: text/plain; charset=UTF-8 Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="manifest"; type="application/lws+json" Link: ; rel="up" -Link: ; rel="type" +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. 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: +**Creating Containers:** To create a new container, a client uses POST to an existing parent container with a `Link` header indicating the Container type, and another `Link` header indicating containement membership. For example: ``` POST /alice/ HTTP/1.1 Host: example.com Authorization: Bearer Content-Length: 0 Slug: notes +Link: rel="up" Link: ; rel="type" ``` @@ -77,15 +87,61 @@ Link: ; rel="type" HTTP/1.1 201 Created Location: /alice/notes/ Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="manifest"; type="application/lws+json" Link: ; rel="up" Link: ; rel="type" Content-Length: 0 ``` -This creates 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/`, and its server-managed auxiliary resources like manifest and linkset, with server-generated metadata including `rel="type"` as `https://www.w3.org/ns/lws#Container`. + +**Example (POST to create a new auxiliary member resource):** +``` +POST /alice/notes/shoppinglist.txt HTTP/1.1 +Host: example.com +Authorization: Bearer +Content-Type: text/turtle +Content-Length: 47 +Slug: shoppinglist.txt.acl +Link: ; rel="principal" +Link: <>; rel="acl"; anchor="/alice/notes/shoppinglist.txt" + +# This box contains an authorization graph +# It describes the conditions required for accessing a resource + +[] + a acp:AccessControlResource ; + acp:resource ex:resourceX ; + acp:accessControl [ + a acp:AccessControl ; + acp:apply [ + a acp:Policy ; + acp:allow acl:Read ; + acp:anyOf [ + a acp:Matcher ; + acp:agent ex:Alice, ex:Bob ; + ] + ] + ] . +``` +In this example, the client is posting to the primary resource `/alice/notes/shoppinglist.txt`, to create an `acl` auxiliary resource. It provides `text/turtle` content (an authorization graph) and suggests the name `shoppinglist.txt.acl` for the new resource. It provides membership link with `rel="principal"` pointing to the principal resource, requesting to be an auxiliary member. It provides a link from the principal resource to the new resource with the `anchor` parameter set to the primary resource URI and the `rel="acl"`, pointing to the new resource to create using an empty URI reference `<>`. If `/alice/notes/shoppinglist.txt` exists and the client is authorized, the server will create a new Resource and add it to the primary resource's auxiliary membership. + +**Example (Response to POST — Auxiliary Resource):** +``` +HTTP/1.1 201 Created +Location: /alice/notes/shoppinglist.txt.acl +Content-Type: text/plain; charset=UTF-8 +Link: ; rel="principal" +Link: <>; rel="acl"; anchor="/alice/notes/shoppinglist.txt" +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. +If the target primary resource `/alice/notes/shoppinglist.txt` does not exist, the server MUST return a 404 error status unless another status code is more appropriate. If the target primary resource `/alice/notes/shoppinglist.txt` already has an auxiliary resource with auxiliaryRel `acl`, the server MUST return a 409 error status unless another status code is more appropriate. + **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. -* Metadata updates are atomic; servers MUST ensure the linkset resource is created and populated with mandatory server-managed fields before returning success. +* Metadata updates are atomic; servers MUST ensure the linkset and manifest resources are 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. **Managing and Retrieving Metadata (Related to Creation):** diff --git a/lws10-core/Operations/delete-resource.md b/lws10-core/Operations/delete-resource.md index 1e4c146..59102c7 100644 --- a/lws10-core/Operations/delete-resource.md +++ b/lws10-core/Operations/delete-resource.md @@ -1,9 +1,10 @@ -Permanently removes a resource and its associated metadata. +Permanently removes a resource and its associated auxiliary resources. * **Inputs**: Target identifier, an optional recursive flag (for containers), and optional concurrency constraints. * **Behavior**: - * For non-container resources, the server removes the content, metadata, and updates the parent container's membership. + * For non-container primary resources, the server removes the content, metadata, all its auxiliary resources, and updates the parent container's containment membership. * For containers, the server typically requires the container to be empty unless a recursive delete is explicitly requested and supported. + * For auxiliary resources, the server removes the content, metadata, and updates the principal resource's auxiliary membership. * **Outcome**: Confirmation of removal or a notification of failure. 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. @@ -11,9 +12,11 @@ The delete resource operation is implemented using the HTTP DELETE method, as de 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. +When a contained resource is deleted, the server MUST atomically remove it from its parent container manifest's `containedItems` list. The parent container manifest's `totalContainedItems` 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. +When an auxiliary resource is deleted, the server MUST atomically remove the corresponding entry from its principal resource manifest's `auxiliaryMap` list, and MUST remove the auxiliarity link from the principal resource's metadata linkset. ETags of the manifest and linkset resources of the principal resource MUST be updated accordingly. + +For all resources, the server removes the resource content. For all primary resources, the server removes its associated auxiliary resources. 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]]. @@ -21,13 +24,13 @@ On success, the server MUST respond with 204 No Content. Servers SHOULD support 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. -**Example (DELETE a non-container resource):** +**Example (DELETE a non-container contained resource):** ``` 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 removes it from the parent container `/alice/notes/` atomically: +Assuming the ETag matches and the client is authorized, the server deletes the resource, its auxiliary resources, and removes it from the parent container `/alice/notes/` by updating its manifest atomically: ``` HTTP/1.1 204 No Content ``` @@ -51,7 +54,18 @@ DELETE /alice/notes/ HTTP/1.1 Authorization: Bearer Depth: infinity ``` -Assuming the server supports recursion and the client has permissions for all contents, the server deletes the container and its descendants atomically: +Assuming the server supports recursion and the client has permissions for all contents, the server deletes the container , its auxiliary resources, and its descendants atomically: +``` +HTTP/1.1 204 No Content +``` + +**Example (DELETE a non-server-managed auxiliary resource):** +``` +DELETE /alice/notes/~acl HTTP/1.1 +Authorization: Bearer +If-Match: "abc123456" +``` +Assuming the ETag matches and the client is authorized, the server deletes the auxiliary resource and removes it from the principal resource `/alice/notes/` by updating its manifest atomically: ``` HTTP/1.1 204 No Content ``` diff --git a/lws10-core/Operations/metadata.md b/lws10-core/Operations/metadata.md index 8aacf74..660f120 100644 --- a/lws10-core/Operations/metadata.md +++ b/lws10-core/Operations/metadata.md @@ -7,32 +7,33 @@ 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 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. +Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For resources with representations, metadata includes representations, each with mediaType and optional sizeInBytes. For contained resources, the link to its parent container resource is part of the metadata of the resource. For auxiliary resources, the link to its principal resource is part of the metadata of the resource. For all primary resources, the links to their auxiliary resources are 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]]. -- Discovery: A resource's linkset is discoverable via a Link header with the relation `rel="linkset"`. +For each primary resource in storage, a server MUST make metadata links available as a standalone auxiliary resource according to [[!RFC9264]]. +- Discovery: A primary 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. +- Integrity: The 'linkset' link MUST point to a server-managed auxiliary 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. -- Containment: Servers MUST include a Link header with `rel="up"` pointing to the parent container for any non-root resource. +- Containment: Servers MUST include a Link header with `rel="up"` pointing to the parent container for any contained resource. +- Auxiliarity: Servers MUST include a Link header with `rel="principal"` pointing to the principal resource for any auxiliary resource. For any principal resource, servers MUST include Link headers for each auxiliary resource with `rel` value set to the auxiliaryRel, pointing to the corresponding auxiliary 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 `linkset`, `type`, `mediaType`, `size`, `modified`. | -| Core Metadata | Managed by the client (subject to server restrictions). Includes `up`, `items`, `title`, `creator`. | +| System Managed | Maintained by the server; Read-Only. Includes `linkset`, `manifest`, `type`, `mediaType`, `size`, `modified`. | +| Core Metadata | Managed by the client (subject to server restrictions). Includes `up`, `principal`, `items`, `title`, `creator`, and other auxiliary resources. | | User-Defined | Custom vocabularies and indexes created by the user. | **Modifiability Considerations** -Core metadata MAY be modified by clients. To ensure interoperability, servers MUST use standard HTTP headers to advertise their capabilities: +Core metadata of primary resources MAY be modified by clients. To ensure interoperability, servers MUST use standard HTTP headers to advertise their capabilities: 1. Method Discovery: Servers MUST advertise support for GET and PATCH operations on the linkset resource via the Allow header. @@ -43,12 +44,12 @@ Core metadata MAY be modified by clients. To ensure interoperability, servers MU [!IMPORTANT] Clients SHOULD NOT assume support for PUT or specific patch formats unless they are advertised in the resource headers and MUST handle 405 Method Not Allowed or 415 Unsupported Media Type responses gracefully. **Managing Metadata** -Metadata is managed by interacting with the resource's associated linkset URI. Servers MUST support concurrency controls for updates. +Metadata is managed by interacting with the primary 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`. - 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. +- Restrictions: Servers MAY restrict modifications to specific links (like `up`, `principal`, `manifest` 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. +- Lifecycle: Metadata lifecycles are tied to the described primary resource; deleting a primary 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 409b7ff..2d04001 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. +Retrieves the representation of an existing resource. * **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 which MAY be filtered based on authorization. Listings must include core metadata for each member. + * The server returns the resource content. + * For manifest resources, the server returns manifest representation with listing of its 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. +The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset", rel="manifest"`, `rel="up"`, `rel="principal"`, 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** – *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):** @@ -25,7 +25,7 @@ Content-Length: 34 ETag: "abc123456" Link: ; rel="linkset"; type="application/linkset+json" Link: ; rel="up" -Link: ; rel="type" +Link: ; rel="type" milk cheese @@ -38,53 +38,71 @@ 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` 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). +**GET (manifest resource)** – *Retrieve a resource's manifest:* +When the target URI corresponds to a manifest resource, a GET request returns a manifest representation as defined in the [Manifest Representation](#manifest-representation) section, using the LWS manifest media type. The manifest includes metadata for each of contained auxiliary members: resource identifiers (MUST), types (MUST), media types (MUST), sizes (SHOULD), and modification timestamps (SHOULD). -**Example (GET a container):** +**Example (GET a manifest):** ``` -GET /alice/notes/ HTTP/1.1 +GET /alice/notes/~manifest HTTP/1.1 Authorization: Bearer -Accept: application/ld+json +Accept: application/lws+json ``` -Assuming the container exists and the client has access: +Assuming the principal resource and the manifest exists and the client has access: ``` HTTP/1.1 200 OK Content-Type: application/lws+json -ETag: "container-etag-789" -Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="up" -Link: ; rel="type" +ETag: "manifest-etag-789" +Link: ; rel="principal"; { "@context": "https://www.w3.org/ns/lws/v1", "id": "/alice/notes/", - "type": "Container", + "type": ["Resource", "Container"], "totalItems": 2, "items": [ { - "type": "DataResource", + "type": "Resource", "id": "/alice/notes/shoppinglist.txt", "mediaType": "text/plain", "size": 47, "modified": "2025-11-24T12:00:00Z" }, { - "type": ["DataResource", "http://example.org/customType"], + "type": ["Resource", "http://example.org/customType"], "id": "/alice/notes/todo.json", "mediaType": "application/json", "size": 2048, "modified": "2025-11-24T13:00:00Z" } - ] + ], + "auxiliaryMap": { + "manifest": { + "id": "/alice/notes/~manifest.json", + "type": ["Manifest", "Resource"], + "mediaType": "application/lws+json", + "modified": "2025-11-24T14:00:00Z", + }, + "linkset": { + "id": "/alice/notes/~linkset.json", + "type": ["Linkset", "Resource"], + "mediaType": "application/linkset+json", + "modified": "2025-11-24T14:00:00Z", + }, + "acl": { + "id": "/alice/notes/~acl", + "type": ["Resource"], + "mediaType": "text/turtle", + "modified": "2025-12-24T15:00:00Z", + } + } } ``` -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 this example, `/alice/notes/` is a container, and `alice/notes/~manifest` is it's manifest auxiliary resource. The response uses JSON-LD with the LWS context, listing contained and auxiliary 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"` and `rel="up"`. +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 if it is a container, `rel="linkset"` and `rel="up"` if it is a contained resource and `rel="principal"` if it is an auxiliary resource. -**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. +**HEAD** – *Headers/metadata only:* +The LWS server MUST support HEAD [[RFC9110]] for all resources in storage, returning the same headers as GET (including ETag, Content-Type, Link for metadata) but without a body. This enables metadata retrieval without transferring content. **Caching and Conditional Requests:** LWS leverages HTTP caching semantics. Servers MUST support conditional requests via If-None-Match (with ETags) or If-Modified-Since headers. If the resource or container listing has not changed, respond with 304 Not Modified to avoid redundant transfers. ETags MUST be provided in all GET/HEAD responses for concurrency and caching support. diff --git a/lws10-core/Operations/rest-table.md b/lws10-core/Operations/rest-table.md index 73570db..8fd1a15 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="up"). 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 manifest representations, 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". | diff --git a/lws10-core/Operations/restbinding.md b/lws10-core/Operations/restbinding.md index f7b4d26..777c30c 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 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 +**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 manifest representations (see [Manifest Media Type](#manifest-media-type)). Servers MAY additionally support formats like Turtle. \ No newline at end of file diff --git a/lws10-core/Operations/update-resource.md b/lws10-core/Operations/update-resource.md index c7f1258..8901bd5 100644 --- a/lws10-core/Operations/update-resource.md +++ b/lws10-core/Operations/update-resource.md @@ -34,13 +34,13 @@ This tells the client the update went through and provides the new `ETag`. If th **PATCH (partial update)** – The HTTP PATCH method [[RFC5789]] allows a client to specify partial modifications to a resource, rather than sending the whole new content. This is useful for large resources where sending the entire content would be inefficient if only a small part changed, or for concurrent editing where you want to apply specific changes. LWS server MUST minimally support JSON Merge Patch (application/merge-patch+json) as defined in [[RFC7386]]. -**Update Resource Metadata (HTTP PUT / PATCH on Linkset)** -A resource's metadata is updated by modifying its corresponding linkset resource, discovered via the Link header with rel="linkset". +**Update Primary Resource Metadata (HTTP PUT / PATCH on Linkset)** +A primary resource's metadata is updated by modifying its corresponding linkset auxiliary resource, discovered via the Link header with rel="linkset". Full Replacement (PUT): A PUT request to the linkset URI with a complete linkset document in the body replaces all metadata for the resource. Partial Update (PATCH): A PATCH request to the linkset URI adds, removes, or modifies specific links. **Concurrency Control for Metadata** -Because a resource's metadata can be modified by multiple actors, preventing concurrent overwrites is critical. To ensure data integrity, LWS servers and clients MUST implement optimistic concurrency control using conditional requests [[RFC7232]] for all PUT and PATCH operations on a linkset resource. +Because a primary resource's metadata can be modified by multiple actors, preventing concurrent overwrites is critical. To ensure data integrity, LWS servers and clients MUST implement optimistic concurrency control using conditional requests [[RFC7232]] for all PUT and PATCH operations on a linkset resource. Server Responsibilities: A server MUST include an Etag header in its responses to GET and HEAD requests for a linkset resource. Upon a successful PUT or PATCH on the linkset, the server MUST generate a new, unique Etag value for the modified linkset and return it in the Etag header of the response. diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md deleted file mode 100644 index c08256a..0000000 --- a/lws10-core/container-representation.md +++ /dev/null @@ -1,54 +0,0 @@ -### 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 - -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 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 - -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"`, 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: - -- **`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. - -#### 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 8ca0791..37ba569 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -165,12 +165,18 @@

Terminology

  • authentication suite — a defined validation mechanism for a concrete serialization of an authentication credential.
  • 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.
  • +
  • container — An LWS resource that has the capability to contain other resources. Containers contain 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.
  • +
  • contained resource — An LWS resource that is related to one or more containers through a containment relationship.
  • +
  • containment — the relationship between a container and its member resources, expressed via the containedItems property in manifest representations and the rel="up" link relation in HTTP headers.
  • 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.
  • +
  • leaf resource — a non-container contained resource.
  • +
  • primary resource — A resource that participates in the containment hierarchy. It can be a root container or contained resource. Every primary resource MUST have exactly one manifest resource.
  • +
  • auxiliary resource — An LWS resource that is used to provide additional information or functionality related to a principal resource. The lifetime of an auxiliary resource is bound to the lifetime of its principal resource. An auxiliary resource can be optionally linked to its principal resource via a specialized relation.
  • +
  • principal resource — An LWS resource that has one or more auxiliary resources. The principal is the resource on whose behalf its auxiliaries exist. Only primary resources can be principals.
  • +
  • auxiliarity — the relationship between a principal resource and its auxiliary resources, expressed via the auxiliaryMap property in manifest representations and the rel="principal" link relation in HTTP headers.
  • +
  • patron resource — The primary resource under which a member directly exists. For an auxiliary member, the patron is its principal. For a contained primary member, the patron is its container.
  • +
  • manifest resource — The auxiliary resource that declares the relationships of a resource to its auxiliary resources and (for containers) its contained resources. Every primary resource MUST have exactly one manifest resource. The manifest resource is linked to its principal resource via a specialized manifest relation.
  • +
  • linkset — An auxiliary resource associated with each LWS primary 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.
  • @@ -215,9 +221,9 @@

    Logical Resource Organization

    -
    -

    Container Representation

    -
    +
    +

    Manifest Representation

    +
    diff --git a/lws10-core/jsonld-context.md b/lws10-core/jsonld-context.md index 7949e1d..08d901f 100644 --- a/lws10-core/jsonld-context.md +++ b/lws10-core/jsonld-context.md @@ -2,13 +2,13 @@ #### Normative JSON-LD Context -Container representations MUST include the following `@context` value: +Manifest 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: +The normative JSON-LD context document defines the mapping between the short property names used in manifest representations and their full URIs in the LWS and related vocabularies. The context is defined as follows: ```json { @@ -21,10 +21,11 @@ The normative JSON-LD context document defines the mapping between the short pro "xs": "http://www.w3.org/2001/XMLSchema#", "id": "@id", "type": "@type", + "Resource": "lws:Resource", "Container": "lws:Container", - "DataResource": "lws:DataResource", - "items": "lws:items", - "totalItems": "as:totalItems", + "containedItems": "lws:containedItems", + "auxiliaryMap": "lws:auxiliaryMap", + "totalContainedItems": "as:totalItems", "mediaType": "as:mediaType", "size": { "@id": "schema:size", @@ -42,21 +43,22 @@ The context is `@protected`, ensuring that the term definitions cannot be overri #### Vocabulary -The LWS vocabulary defines the following types and properties used in container representations: +The LWS vocabulary defines the following types and properties used in manifest representations: **Types:** | Term | URI | Description | |------|-----|-------------| +| `Resource` | `lws:Resource` | An lws conformant resource | | `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 | +| `containedItems` | `lws:containedItems` | The list of resources contained in a container | +| `auxiliaryMap` | `lws:auxiliaryMap` | The map with entries corresponding to auxiliary resources of a resource | +| `totalContainedItems` | `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 89143a6..9edb267 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -1,47 +1,83 @@ -### Container Model +The storage system organizes resources into two distinct layers: primary and auxiliary. The two layers are complementary. The primary layer organizes resources spatially and hierarchically, while the auxiliary layer attaches supplementary resources to each node in that hierarchy. -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. 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. +### Primary resource layer -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. +The primary resource layer forms a strict hierarchy rooted at a single root container. Every primary resource except the storage root is contained by one or more parents. -Resources in LWS are classified as either: +A container is a specialized resource that can contain other resources, called its contained members. Containers serve +as organizational units, analogous to directories or collections, enabling clients to group, discover, and navigate resources. A container maintains references to its contained member resources, +which may comprise both non-container resources and additional container resources, thereby enabling hierarchical formations. The principal role of a container is to aggregate and structure subordinate resources. -- **Container** — a resource that contains other resources. -- **DataResource** — a data-bearing resource (e.g., a document, image, or structured data file). +The storage system's root is designated as a container, serving as the apex organizational unit devoid of a superior parent, and acts as the entry point for the storage hierarchy. Storage MAY function as a root container, enabling direct writes. -### Containment +Servers MUST include a `Link` header with `rel="type"` pointing to `https://www.w3.org/ns/lws#Container`. -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="type" +``` + +#### 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 contained 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. +### Auxiliary resource layer -### Containment Integrity +The auxiliary resource layer is flat. Each primary resource owns a local set of auxiliary resources. An auxiliary resource is an LWS resource that is used to provide additional information or functionality related to a unique principal resource. The lifetime of an auxiliary resource is bound to the lifetime of its principal resource. Auxiliary resources do not participate in the containment hierarchy. -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**: A container MUST NOT directly or indirectly contain itself. +#### Auxiliarity + +The auxiliarity relationship between an auxiliary resource and its principal resource is expressed via the `rel="principal"` link relation. Servers MUST include a `Link` header with `rel="principal"` pointing to the principal resource in responses to GET and HEAD requests on any auxiliary resource. -### Resource Identification +``` +Link: ; rel="principal" +``` + +Along with the general `rel="principal"` relation from auxiliary resource to its principal resource, an auxiliary resource is linked from the principal resource through a specialized link relation. This specialized relation is called the `auxiliaryRel` of the auxiliarity. Auxiliary relations are constrained to be functional. For each `auxiliaryRel`, there MUST be at most one auxiliary resource. + +In responses to GET and HEAD requests on any principal resource, servers MUST link to each auxiliary resource with `rel` value set to the auxiliaryRel of the auxiliarity. + +``` +Link: ; rel="manifest" +Link: ; rel="acl" +``` -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. +This specification predefines the following auxiliary relations: -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. +- `manifest`: Server-managed manifest auxiliary resource (see below) +- `linkset`: Server-managed linkset auxiliary resource (see below) +- `acl`: ACL auxiliary resource. Server interprets it for access control over the resource. + +### Manifest resource + +Each primary resource has a unique server-managed auxiliary resource called the manifest resource. A manifest resource holds basic metadata and enumerations of auxiliary members and contained members (for containers) of the principal resource. It has `manifest` as the specialized auxiliarity relation. That is, servers MUST include a `Link` header with `rel="manifest"` pointing to the auxiliary manifest resource in responses to GET and HEAD requests on any primary resource. + +``` +Link: ; rel="manifest" +``` + +For each primary resource, its auxiliary members are enumerated in its manifest representation using the `auxiliaryMap` property. Each map entry has the auxiliaryRel value as the key, and description of the corresponding auxiliary resource as the value. Auxiliary membership changes occur as a side effect of auxiliary resource creation and deletion. + +For each container, its contained members are listed in its manifest representation using the `containedItems` property. Containment membership changes occur as a side effect of contained resource creation and deletion. + +Manifest resources MUST support pagination for container 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. + +#### Manifest integrity + +The server MUST maintain manifest integrity at all times: + +- **Creation**: When a new resource is created in a container, the server MUST atomically add the resource to its manifest's `containedItems` list. When a new auxiliary resource is created, the server MUST atomically add the corresponding entry to its principal's manifest's `auxiliaryMap` map. +- **Deletion**: When a contained resource is deleted, the server MUST atomically remove it from its parent container's `containedItems` list. Deleting a container requires the container to be empty, unless recursive deletion is explicitly requested. When an auxiliary resource is deleted, the server MUST atomically remove the corresponding entry from `auxiliaryMap` in the manifest of its principal resource. When a principal resource is deleted, the server MUST atomically delete all its auxiliary resources including the manifest resource. +- **No orphans**: Every resource MUST be either a contained resource reachable from the root container through the containment hierarchy, or an auxiliary resource reachable from a principal resource through an auxiliary relation. +- **No cycles**: A container MUST NOT directly or indirectly contain itself. +- **Layer hygiene**: A primary resource cannot have other primary resources as its auxiliary resource. An auxiliary resource cannot be a container containing other primary resources. -### Container Membership and Authorization +#### Manifest 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 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. +If a client has read access to a resource, the resource manifest representation MUST include the identifiers for all members either auxiliaries or contained to which the client has access. It MAY also contain the identifiers for contained/auxiliary resources of that resource to which the client does not have access. -A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. +A client's ability to read a manifest listing does not imply access to the listed resources themselves, and vice versa. diff --git a/lws10-core/lws-media-type.md b/lws10-core/lws-media-type.md index 5f56618..846daba 100644 --- a/lws10-core/lws-media-type.md +++ b/lws10-core/lws-media-type.md @@ -1,15 +1,15 @@ ### LWS Media Type -LWS container representation and storage description resource MUST use the media type `application/lws+json`. +LWS manifest 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`. +While LWS manifest representations use JSON-LD conventions, the constraints and requirements for LWS justify the use of a specific media type. Because LWS manifests 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: +Servers MUST support content negotiation for manifest 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. +In all three cases, the response body is the same JSON-LD document conforming to the LWS manifest vocabulary. Servers are free to support additional media types (e.g., `text/turtle`) through content negotiation. diff --git a/lws10-core/manifest-representation.md b/lws10-core/manifest-representation.md new file mode 100644 index 0000000..2db9462 --- /dev/null +++ b/lws10-core/manifest-representation.md @@ -0,0 +1,77 @@ +### Manifest Representation + +When a client retrieves a manifest of a resource, the server returns a structured manifest representation. This section defines the required and optional properties of a manifest representation. + +#### Manifest Properties + +A manifest representation MUST include the following properties of the principal resource: + +- **`id`**: The URI of the resource. +- **`type`**: The type of the resource. Can be a single string or an array of strings. For all resources, it MUST include "Resource". For containers, it MUST include "Container". +- **`totalContainedItems`**: For a container resource, an integer indicating the total number of resources contained in the resource which can be disclosed to the client. +- **`containedItems`**: For a container resource, an array of contained resource descriptions (see below). If the container is empty, this MUST be an empty array. +- **`auxiliaryMap`**: A map with entries corresponding to each auxiliary relation, with auxiliaryRel as the key and description of the corresponding auxiliary resource as the value. + +#### Resource Description + +Each entry in the `containedItems` array describes a contained member resource. The value of each entry in the `auxiliaryMap` map describes an auxiliary member resource. + +A member resource description MUST include: + +- **`id`**: The URI of the member resource. +- **`type`**: The type of the member resource. Can be a single string or an array of strings. For all resources, it MUST include "Resource". For containers, it MUST also include "Container". Servers MAY include additional user-defined types as URIs (e.g., `["Container", "http://example.org/customType"]`). + +A resource description SHOULD include: + +- **`mediaType`**: The media type of the resource (e.g., `"text/plain"`, `"image/jpeg"`). MUST be present. +- **`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. + +#### Example Manifest Representation + +The following example shows the manifest of a container at `/alice/notes/` containing two resources, and having some auxiliary resources: + +```json +{ + "@context": "https://www.w3.org/ns/lws/v1", + "id": "/alice/notes/", + "type": ["Container", "Resource"], + "totalContainedItems": 2, + "containedItems": [ + { + "id": "/alice/notes/shoppinglist.txt", + "type": ["Resource"], + "mediaType": "text/plain", + "size": 47, + "modified": "2025-11-24T12:00:00Z" + }, + { + "type": ["Resource", "http://example.org/customType"], + "id": "/alice/notes/todo.json", + "mediaType": "application/json", + "size": 2048, + "modified": "2025-11-24T13:00:00Z" + } + ], + "auxiliaryMap": { + "manifest": { + "id": "/alice/notes/~manifest.json", + "type": ["Manifest", "Resource"], + "mediaType": "application/lws+json", + "modified": "2025-11-24T14:00:00Z", + }, + "linkset": { + "id": "/alice/notes/~linkset.json", + "type": ["Linkset", "Resource"], + "mediaType": "application/linkset+json", + "modified": "2025-11-24T14:00:00Z", + }, + "acl": { + "id": "/alice/notes/~acl", + "type": ["Resource"], + "mediaType": "text/turtle", + "modified": "2025-12-24T15:00:00Z", + } + } +} +``` From f79d1c4c97b1660d950ea3302dda9ac052e6d025 Mon Sep 17 00:00:00 2001 From: damodara Date: Wed, 1 Apr 2026 12:56:34 +0530 Subject: [PATCH 2/2] Limit manifest resource to containers alone --- lws10-core/Operations/create-resource.md | 16 +++++----- lws10-core/Operations/delete-resource.md | 8 ++--- lws10-core/Operations/metadata.md | 6 ++-- lws10-core/Operations/read-resource.md | 32 ++++--------------- lws10-core/index.html | 8 ++--- lws10-core/jsonld-context.md | 10 +++--- lws10-core/logicalresourceorganization.md | 26 +++++++-------- lws10-core/lws-media-type.md | 2 +- lws10-core/manifest-representation.md | 39 ++++++----------------- 9 files changed, 51 insertions(+), 96 deletions(-) diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index b91fdc5..5c10b5e 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -10,8 +10,8 @@ The **create resource** operation adds a new [served resource](#dfn-served-resou **Behavior:** * **Identity generation:** The server determines the final identifier (URI) for the new resource. If an identity hint was provided, the server attempts to incorporate it while ensuring uniqueness and validity within the scope of the patron resource. If no hint is provided, the server generates a unique identifier. -* **Patron membership update:** The server atomically adds the new resource to the contained/auxiliary membership of the target patron by updating its manifest. It uses the provided membership links to determine the type of membership. -* **Metadata initialization:** The server initializes system metadata for the new resource. If the resource has an associated metadata resource it is also initialized. +* **Patron membership update:** The server atomically adds the new resource to the contained/auxiliary membership of the target patron by updating its manifest/linkset respectively. It uses the provided membership links to determine the type of membership. +* **Metadata initialization:** The server initializes system metadata for the new resource. If the resource has an associated metadata resource or manifest resource they are also initialized. **Possible Responses:** @@ -32,7 +32,7 @@ Use POST to add a new resource to an existing patron resource, either as an auxi Clients indicate the type of membership as follows: - To create a **Contained member**, the client MUST include a `Link` header with `rel="up"` pointing to the target patron container. -- To create an **Auxiliary member**, the client MUST include a `Link` header with `rel="principal"` pointing to the target principal resource. The client MUST also include a `Link` header with the `anchor` parameter set to the target principal resource, `rel` value set to the required auxiliaryRel, pointing to the new resource to create using an empty URI reference `<>`. +- To create an **Auxiliary member**, the client MUST include a `Link` header with `rel="principal"` pointing to the target principal resource. The client MUST also include a `Link` header with the `anchor` parameter set to the target principal resource, `rel` value set to the required auxiliaryRel, pointing to the new resource to create using an empty URI reference `<>` augmented with `auxiliary=true` parameter. Clients indicate the containment capability of the contained member resource to create as follows: @@ -62,8 +62,8 @@ In this example, the client is posting to the container `/alice/notes/`. It prov HTTP/1.1 201 Created Location: /alice/notes/shoppinglist.txt Content-Type: text/plain; charset=UTF-8 -Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="manifest"; type="application/lws+json" +Link: ; rel="linkset"; type="application/linkset+json; auxiliary=true;" +Link: ; rel="manifest"; type="application/lws+json; auxiliary=true" Link: ; rel="up" Link: ; rel="type" Content-Length: 0 @@ -86,8 +86,8 @@ Link: ; rel="type" ``` HTTP/1.1 201 Created Location: /alice/notes/ -Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="manifest"; type="application/lws+json" +Link: ; rel="linkset"; type="application/linkset+json; auxiliary=true;" +Link: ; rel="manifest"; type="application/lws+json; auxiliary=true;" Link: ; rel="up" Link: ; rel="type" Content-Length: 0 @@ -131,7 +131,7 @@ HTTP/1.1 201 Created Location: /alice/notes/shoppinglist.txt.acl Content-Type: text/plain; charset=UTF-8 Link: ; rel="principal" -Link: <>; rel="acl"; anchor="/alice/notes/shoppinglist.txt" +Link: <>; rel="acl"; anchor="/alice/notes/shoppinglist.txt; auxiliary=true;" Link: ; rel="type" Content-Length: 0 ``` diff --git a/lws10-core/Operations/delete-resource.md b/lws10-core/Operations/delete-resource.md index 59102c7..8bd7179 100644 --- a/lws10-core/Operations/delete-resource.md +++ b/lws10-core/Operations/delete-resource.md @@ -4,7 +4,7 @@ Permanently removes a resource and its associated auxiliary resources. * **Behavior**: * For non-container primary resources, the server removes the content, metadata, all its auxiliary resources, and updates the parent container's containment membership. * For containers, the server typically requires the container to be empty unless a recursive delete is explicitly requested and supported. - * For auxiliary resources, the server removes the content, metadata, and updates the principal resource's auxiliary membership. + * For auxiliary resources, the server removes the content, and updates the principal resource's metadata linkset by removing corresponding auxiliary link. * **Outcome**: Confirmation of removal or a notification of failure. 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. @@ -12,9 +12,9 @@ The delete resource operation is implemented using the HTTP DELETE method, as de 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 contained resource is deleted, the server MUST atomically remove it from its parent container manifest's `containedItems` list. The parent container manifest's `totalContainedItems` count and ETag MUST be updated accordingly. +When a contained resource is deleted, the server MUST atomically remove it from its parent container manifest's `items` list. The parent container manifest's `totalItems` count and ETag MUST be updated accordingly. -When an auxiliary resource is deleted, the server MUST atomically remove the corresponding entry from its principal resource manifest's `auxiliaryMap` list, and MUST remove the auxiliarity link from the principal resource's metadata linkset. ETags of the manifest and linkset resources of the principal resource MUST be updated accordingly. +When an auxiliary resource is deleted, the server MUST atomically remove the corresponding link from its principal resource's metadata linkset. ETags of the manifest and linkset resources of the principal resource MUST be updated accordingly. For all resources, the server removes the resource content. For all primary resources, the server removes its associated auxiliary resources. @@ -65,7 +65,7 @@ DELETE /alice/notes/~acl HTTP/1.1 Authorization: Bearer If-Match: "abc123456" ``` -Assuming the ETag matches and the client is authorized, the server deletes the auxiliary resource and removes it from the principal resource `/alice/notes/` by updating its manifest atomically: +Assuming the ETag matches and the client is authorized, the server deletes the auxiliary resource and removes it from the principal resource `/alice/notes/` by updating its linkset atomically: ``` HTTP/1.1 204 No Content ``` diff --git a/lws10-core/Operations/metadata.md b/lws10-core/Operations/metadata.md index 660f120..d840a67 100644 --- a/lws10-core/Operations/metadata.md +++ b/lws10-core/Operations/metadata.md @@ -7,7 +7,7 @@ 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 resources with representations, metadata includes representations, each with mediaType and optional sizeInBytes. For contained resources, the link to its parent container resource is part of the metadata of the resource. For auxiliary resources, the link to its principal resource is part of the metadata of the resource. For all primary resources, the links to their auxiliary resources are part of the metadata of the resource. +Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For resources with representations, metadata includes representations, each with mediaType and optional sizeInBytes. For contained resources, the link to its parent container resource is part of the metadata of the resource. For auxiliary resources, the link to its principal resource is part of the metadata of the resource. For all primary resources, the links to their auxiliary resources are part of the metadata of the resource. These auxilary links MUST have `auxiliary=true` parameter set. **The Linkset Resource** @@ -20,7 +20,7 @@ For each primary resource in storage, a server MUST make metadata links availabl 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. - Containment: Servers MUST include a Link header with `rel="up"` pointing to the parent container for any contained resource. -- Auxiliarity: Servers MUST include a Link header with `rel="principal"` pointing to the principal resource for any auxiliary resource. For any principal resource, servers MUST include Link headers for each auxiliary resource with `rel` value set to the auxiliaryRel, pointing to the corresponding auxiliary resource. +- Auxiliarity: Servers MUST include a Link header with `rel="principal"` pointing to the principal resource for any auxiliary resource. For any principal resource, servers MUST include Link headers for each auxiliary resource with `rel` value set to the auxiliaryRel, pointing to the corresponding auxiliary resource, augumented with `auxiliary=true` parameter. - 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** @@ -50,6 +50,6 @@ Metadata is managed by interacting with the primary resource's associated linkse - 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`, `principal`, `manifest` or `items`) to maintain system integrity. +- Restrictions: Servers MAY restrict modifications to specific links (like `up`, `principal`, `manifest` or `items`, and auxiliary relations) to maintain system integrity. - Lifecycle: Metadata lifecycles are tied to the described primary resource; deleting a primary 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 2d04001..8384bcd 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -23,7 +23,7 @@ HTTP/1.1 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 34 ETag: "abc123456" -Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="linkset"; auxiliary=true; type="application/linkset+json" Link: ; rel="up" Link: ; rel="type" @@ -38,16 +38,16 @@ 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` and `type`. -**GET (manifest resource)** – *Retrieve a resource's manifest:* -When the target URI corresponds to a manifest resource, a GET request returns a manifest representation as defined in the [Manifest Representation](#manifest-representation) section, using the LWS manifest media type. The manifest includes metadata for each of contained auxiliary members: resource identifiers (MUST), types (MUST), media types (MUST), sizes (SHOULD), and modification timestamps (SHOULD). +**GET (manifest resource)** – *Retrieve a container's manifest:* +When the target URI corresponds to a container manifest resource, a GET request returns a manifest representation as defined in the [Container Manifest Representation](#manifest-representation) section, using the LWS manifest media type. The manifest includes metadata for each of contained members: resource identifiers (MUST), types (MUST), media types (MUST), sizes (SHOULD), and modification timestamps (SHOULD). -**Example (GET a manifest):** +**Example (GET a container manifest):** ``` GET /alice/notes/~manifest HTTP/1.1 Authorization: Bearer Accept: application/lws+json ``` -Assuming the principal resource and the manifest exists and the client has access: +Assuming the container resource and the manifest exists and the client has access: ``` HTTP/1.1 200 OK Content-Type: application/lws+json @@ -74,27 +74,7 @@ Link: ; rel="principal"; "size": 2048, "modified": "2025-11-24T13:00:00Z" } - ], - "auxiliaryMap": { - "manifest": { - "id": "/alice/notes/~manifest.json", - "type": ["Manifest", "Resource"], - "mediaType": "application/lws+json", - "modified": "2025-11-24T14:00:00Z", - }, - "linkset": { - "id": "/alice/notes/~linkset.json", - "type": ["Linkset", "Resource"], - "mediaType": "application/linkset+json", - "modified": "2025-11-24T14:00:00Z", - }, - "acl": { - "id": "/alice/notes/~acl", - "type": ["Resource"], - "mediaType": "text/turtle", - "modified": "2025-12-24T15:00:00Z", - } - } + ] } ``` In this example, `/alice/notes/` is a container, and `alice/notes/~manifest` is it's manifest auxiliary resource. The response uses JSON-LD with the LWS context, listing contained and auxiliary members with required metadata. Each item includes its `type`, `id`, `mediaType`, `size`, and `modified` timestamp as flat properties. diff --git a/lws10-core/index.html b/lws10-core/index.html index 37ba569..5cdbedd 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -167,15 +167,15 @@

    Terminology

  • LWS resource — An LWS Resource is an information resource whose lifecycle is managed by the LWS storage.
  • container — An LWS resource that has the capability to contain other resources. Containers contain 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.
  • contained resource — An LWS resource that is related to one or more containers through a containment relationship.
  • -
  • containment — the relationship between a container and its member resources, expressed via the containedItems property in manifest representations and the rel="up" link relation in HTTP headers.
  • +
  • containment — the relationship between a container and its member resources, expressed via the items property in manifest representations and the rel="up" link relation in HTTP headers.
  • 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.
  • leaf resource — a non-container contained resource.
  • primary resource — A resource that participates in the containment hierarchy. It can be a root container or contained resource. Every primary resource MUST have exactly one manifest resource.
  • auxiliary resource — An LWS resource that is used to provide additional information or functionality related to a principal resource. The lifetime of an auxiliary resource is bound to the lifetime of its principal resource. An auxiliary resource can be optionally linked to its principal resource via a specialized relation.
  • principal resource — An LWS resource that has one or more auxiliary resources. The principal is the resource on whose behalf its auxiliaries exist. Only primary resources can be principals.
  • -
  • auxiliarity — the relationship between a principal resource and its auxiliary resources, expressed via the auxiliaryMap property in manifest representations and the rel="principal" link relation in HTTP headers.
  • +
  • auxiliarity — the relationship between a principal resource and its auxiliary resources, expressed via the rel="principal" link relation in HTTP headers.
  • patron resource — The primary resource under which a member directly exists. For an auxiliary member, the patron is its principal. For a contained primary member, the patron is its container.
  • -
  • manifest resource — The auxiliary resource that declares the relationships of a resource to its auxiliary resources and (for containers) its contained resources. Every primary resource MUST have exactly one manifest resource. The manifest resource is linked to its principal resource via a specialized manifest relation.
  • +
  • container manifest — The auxiliary resource that declares the relationships of a container to its contained resources. Every container MUST have exactly one manifest resource. The manifest resource is linked to its principal container resource via a specialized manifest relation.
  • linkset — An auxiliary resource associated with each LWS primary 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.
  • @@ -222,7 +222,7 @@

    Logical Resource Organization

    -

    Manifest Representation

    +

    Container Manifest Representation

    diff --git a/lws10-core/jsonld-context.md b/lws10-core/jsonld-context.md index 08d901f..c6c4c1d 100644 --- a/lws10-core/jsonld-context.md +++ b/lws10-core/jsonld-context.md @@ -23,9 +23,8 @@ The normative JSON-LD context document defines the mapping between the short pro "type": "@type", "Resource": "lws:Resource", "Container": "lws:Container", - "containedItems": "lws:containedItems", - "auxiliaryMap": "lws:auxiliaryMap", - "totalContainedItems": "as:totalItems", + "items": "lws:items", + "totalItems": "as:totalItems", "mediaType": "as:mediaType", "size": { "@id": "schema:size", @@ -56,9 +55,8 @@ The LWS vocabulary defines the following types and properties used in manifest r | Term | URI | Description | |------|-----|-------------| -| `containedItems` | `lws:containedItems` | The list of resources contained in a container | -| `auxiliaryMap` | `lws:auxiliaryMap` | The map with entries corresponding to auxiliary resources of a resource | -| `totalContainedItems` | `as:totalItems` | The total number of contained resources | +| `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 9edb267..315830c 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -37,13 +37,13 @@ The auxiliarity relationship between an auxiliary resource and its principal res Link: ; rel="principal" ``` -Along with the general `rel="principal"` relation from auxiliary resource to its principal resource, an auxiliary resource is linked from the principal resource through a specialized link relation. This specialized relation is called the `auxiliaryRel` of the auxiliarity. Auxiliary relations are constrained to be functional. For each `auxiliaryRel`, there MUST be at most one auxiliary resource. +Along with the general `rel="principal"` relation from auxiliary resource to its principal resource, an auxiliary resource is linked from the principal resource through a specialized link relation. This specialized relation is called the `auxiliaryRel` of the auxiliarity. This link must also have a parameter `auxiliary` with value set to `true`. Auxiliary relations are constrained to be functional. For each `auxiliaryRel`, there MUST be at most one auxiliary resource. -In responses to GET and HEAD requests on any principal resource, servers MUST link to each auxiliary resource with `rel` value set to the auxiliaryRel of the auxiliarity. +In responses to GET and HEAD requests on any principal resource, servers MUST link to each auxiliary resource with `rel` value set to the auxiliaryRel of the auxiliarity, with a link parameter `auxiliary` set to `true`. ``` -Link: ; rel="manifest" -Link: ; rel="acl" +Link: ; rel="manifest"; auxiliary=true +Link: ; rel="acl" auxiliary=true ``` This specification predefines the following auxiliary relations: @@ -52,17 +52,15 @@ This specification predefines the following auxiliary relations: - `linkset`: Server-managed linkset auxiliary resource (see below) - `acl`: ACL auxiliary resource. Server interprets it for access control over the resource. -### Manifest resource +### Container Manifest resource -Each primary resource has a unique server-managed auxiliary resource called the manifest resource. A manifest resource holds basic metadata and enumerations of auxiliary members and contained members (for containers) of the principal resource. It has `manifest` as the specialized auxiliarity relation. That is, servers MUST include a `Link` header with `rel="manifest"` pointing to the auxiliary manifest resource in responses to GET and HEAD requests on any primary resource. +Each container resource has a unique server-managed auxiliary resource called the manifest resource. A manifest resource holds basic metadata and enumerations of the container's contained members. It has `manifest` as the specialized auxiliarity relation. That is, servers MUST include a `Link` header with `rel="manifest"` pointing to the auxiliary manifest resource in responses to GET and HEAD requests on any container resource. ``` -Link: ; rel="manifest" +Link: ; rel="manifest" ``` -For each primary resource, its auxiliary members are enumerated in its manifest representation using the `auxiliaryMap` property. Each map entry has the auxiliaryRel value as the key, and description of the corresponding auxiliary resource as the value. Auxiliary membership changes occur as a side effect of auxiliary resource creation and deletion. - -For each container, its contained members are listed in its manifest representation using the `containedItems` property. Containment membership changes occur as a side effect of contained resource creation and deletion. +For each container, its contained members are listed in its manifest representation using the `items` property. Containment membership changes occur as a side effect of contained resource creation and deletion. Manifest resources MUST support pagination for container 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. @@ -70,14 +68,14 @@ Manifest resources MUST support pagination for container membership listings usi The server MUST maintain manifest integrity at all times: -- **Creation**: When a new resource is created in a container, the server MUST atomically add the resource to its manifest's `containedItems` list. When a new auxiliary resource is created, the server MUST atomically add the corresponding entry to its principal's manifest's `auxiliaryMap` map. -- **Deletion**: When a contained resource is deleted, the server MUST atomically remove it from its parent container's `containedItems` list. Deleting a container requires the container to be empty, unless recursive deletion is explicitly requested. When an auxiliary resource is deleted, the server MUST atomically remove the corresponding entry from `auxiliaryMap` in the manifest of its principal resource. When a principal resource is deleted, the server MUST atomically delete all its auxiliary resources including the manifest resource. -- **No orphans**: Every resource MUST be either a contained resource reachable from the root container through the containment hierarchy, or an auxiliary resource reachable from a principal resource through an auxiliary relation. +- **Creation**: When a new resource is created in a container, the server MUST atomically add the resource to its manifest's `items` list. +- **Deletion**: When a contained 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 either a contained resource reachable from the root container through the containment hierarchy, or an auxiliary resource reachable from a principal resource through an auxiliary relation. - **No cycles**: A container MUST NOT directly or indirectly contain itself. - **Layer hygiene**: A primary resource cannot have other primary resources as its auxiliary resource. An auxiliary resource cannot be a container containing other primary resources. #### Manifest membership and Authorization -If a client has read access to a resource, the resource manifest representation MUST include the identifiers for all members either auxiliaries or contained to which the client has access. It MAY also contain the identifiers for contained/auxiliary resources of that resource to which the client does not have access. +If a client has read access to a resource, the container manifest representation MUST include the identifiers for all contained members to which the client has access. It MAY also contain the identifiers for contained resources of that resource to which the client does not have access. A client's ability to read a manifest listing does not imply access to the listed resources themselves, and vice versa. diff --git a/lws10-core/lws-media-type.md b/lws10-core/lws-media-type.md index 846daba..8cf282d 100644 --- a/lws10-core/lws-media-type.md +++ b/lws10-core/lws-media-type.md @@ -6,7 +6,7 @@ While LWS manifest representations use JSON-LD conventions, the constraints and #### Content Negotiation -Servers MUST support content negotiation for manifest representations. The response payload MUST be identical regardless of the requested media type — only the `Content-Type` response header varies: +Servers MUST support content negotiation for container manifest 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`. diff --git a/lws10-core/manifest-representation.md b/lws10-core/manifest-representation.md index 2db9462..4598e1c 100644 --- a/lws10-core/manifest-representation.md +++ b/lws10-core/manifest-representation.md @@ -1,20 +1,19 @@ ### Manifest Representation -When a client retrieves a manifest of a resource, the server returns a structured manifest representation. This section defines the required and optional properties of a manifest representation. +When a client retrieves a manifest of a container, the server returns a structured manifest representation. This section defines the required and optional properties of a manifest representation. #### Manifest Properties -A manifest representation MUST include the following properties of the principal resource: +A manifest representation MUST include the following properties of the principal container resource: - **`id`**: The URI of the resource. - **`type`**: The type of the resource. Can be a single string or an array of strings. For all resources, it MUST include "Resource". For containers, it MUST include "Container". -- **`totalContainedItems`**: For a container resource, an integer indicating the total number of resources contained in the resource which can be disclosed to the client. -- **`containedItems`**: For a container resource, an array of contained resource descriptions (see below). If the container is empty, this MUST be an empty array. -- **`auxiliaryMap`**: A map with entries corresponding to each auxiliary relation, with auxiliaryRel as the key and description of the corresponding auxiliary resource as the value. +- **`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. #### Resource Description -Each entry in the `containedItems` array describes a contained member resource. The value of each entry in the `auxiliaryMap` map describes an auxiliary member resource. +Each entry in the `items` array describes a contained member resource. A member resource description MUST include: @@ -29,15 +28,15 @@ A resource description SHOULD include: #### Example Manifest Representation -The following example shows the manifest of a container at `/alice/notes/` containing two resources, and having some auxiliary resources: +The following example shows the manifest of a container at `/alice/notes/` containing two resources: ```json { "@context": "https://www.w3.org/ns/lws/v1", "id": "/alice/notes/", "type": ["Container", "Resource"], - "totalContainedItems": 2, - "containedItems": [ + "totalItems": 2, + "items": [ { "id": "/alice/notes/shoppinglist.txt", "type": ["Resource"], @@ -52,26 +51,6 @@ The following example shows the manifest of a container at `/alice/notes/` conta "size": 2048, "modified": "2025-11-24T13:00:00Z" } - ], - "auxiliaryMap": { - "manifest": { - "id": "/alice/notes/~manifest.json", - "type": ["Manifest", "Resource"], - "mediaType": "application/lws+json", - "modified": "2025-11-24T14:00:00Z", - }, - "linkset": { - "id": "/alice/notes/~linkset.json", - "type": ["Linkset", "Resource"], - "mediaType": "application/linkset+json", - "modified": "2025-11-24T14:00:00Z", - }, - "acl": { - "id": "/alice/notes/~acl", - "type": ["Resource"], - "mediaType": "text/turtle", - "modified": "2025-12-24T15:00:00Z", - } - } + ] } ```