diff --git a/lws10-core/Discovery.html b/lws10-core/Discovery.html index 895130e..4849405 100644 --- a/lws10-core/Discovery.html +++ b/lws10-core/Discovery.html @@ -2,7 +2,7 @@

Storage Description Resource

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

diff --git a/lws10-core/IANA-Considerations.html b/lws10-core/IANA-Considerations.html index b64ee10..0e344c9 100644 --- a/lws10-core/IANA-Considerations.html +++ b/lws10-core/IANA-Considerations.html @@ -45,22 +45,22 @@

OAuth Authorization Server Metadata Registry

-

Media Type Registry

+

The application/lws+json Media Type

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

+ +

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

+ +

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

diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md index 7f236f6..e5f1d77 100644 --- a/lws10-core/Operations/create-resource.md +++ b/lws10-core/Operations/create-resource.md @@ -21,11 +21,15 @@ The **create resource** operation adds a new [served resource](#dfn-served-resou * **Conflict:** A resource with the generated identifier already exists, or there is another state conflict. * **Unknown Error:** An unexpected internal error occurred. -New resources are created using POST to a target container URI, with the server assigning the final identifier. Clients MAY suggest a name via the Slug header. Clients MAY provide initial user-managed metadata for the new resource by including one or more Link headers in the POST request, following the syntax of Web Linking in [[RFC8288]]. Server-managed metadata MUST be generated automatically by the server upon creation and MUST NOT be overridden by client-provided links. -On success, return the 201 status code with the new URI in the Location header. The server MUST include Link headers for key server-managed metadata, such as a link to the parent container (rel="partOf"), a link to the ACL resource (rel="acl"), and a link to its dedicated linkset resource (rel="linkset"; type="application/linkset+json"). Additional links SHOULD include rel="type" (indicating Container or DataResource) and rel="mediaType" if applicable. The body MAY be empty or include a minimal representation of the resource. All metadata creation and linking MUST be atomic with the resource creation to maintain consistency. +New resources are created using POST to a target container URI, with the server assigning the final identifier. Clients MAY suggest a name via the `Slug` header. Clients MAY provide initial user-managed metadata for the new resource by including one or more `Link` headers in the POST request, following the syntax of Web Linking in [[RFC8288]]. Server-managed metadata MUST be generated automatically by the server upon creation and MUST NOT be overridden by client-provided links. + +On success, the server MUST return the 201 status code with the new URI in the `Location` header. The server MUST include `Link` headers for key server-managed metadata, including a link to the parent container (`rel="up"`), and a link to the created resource's dedicated linkset resource (`rel="linkset"; type="application/linkset+json"`). Additional links SHOULD include `rel="type"` (indicating `https://www.w3.org/ns/lws#Container` or `https://www.w3.org/ns/lws#DataResource`). The body MAY be empty or include a minimal representation of the resource. All metadata creation and linking MUST be atomic with the resource creation to maintain consistency. **POST (to a container URI)** – *Create with server-assigned name:* -Use POST to add a new resource inside an existing container. The server assigns an identifier to the resource, optionally suggested via the Slug header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources. Clients MUST include a Content-Type header in the request to indicate the media type of the new resource, enabling the server to distinguish between resource types. Specifically, servers MUST interpret the Content-Type as follows: if it matches the LWS-defined media type for containers (application/lws+json), the server creates a Container; otherwise, it creates a DataResource with the specified media type. +Use POST to add a new resource inside an existing container. The server assigns an identifier to the resource, optionally suggested via the `Slug` header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources. Clients indicate the type of resource to create as follows: + +- To create a **Container**, the client MUST include a `Link` header with `rel="type"` pointing to the Container type: `Link: ; rel="type"`. +- To create a **DataResource**, the client includes the resource content in the request body with the appropriate `Content-Type` header. **Example (POST to create a new data resource):** ``` @@ -35,6 +39,7 @@ Authorization: Bearer Content-Type: text/plain Content-Length: 47 Slug: shoppinglist.txt + milk eggs bread @@ -42,39 +47,46 @@ butter apples orange juice ``` -In this example, the client is posting to the container `/alice/notes/`. It provides `text/plain` content (a grocery list) and suggests the name `shoppinglist.txt` for the new resource. If `/alice/notes/` exists and the client is authorized, the server will create a new DataResource (based on the Content-Type), generate associated metadata, and link it via the linkset. +In this example, the client is posting to the container `/alice/notes/`. It provides `text/plain` content (a grocery list) and suggests the name `shoppinglist.txt` for the new resource. If `/alice/notes/` exists and the client is authorized, the server will create a new DataResource and add it to the container's membership. -**Example (Response to POST):** +**Example (Response to POST — Data Resource):** ``` HTTP/1.1 201 Created Location: /alice/notes/shoppinglist.txt Content-Type: text/plain; charset=UTF-8 -ETag: "def789012" Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="partOf" -Link: ; rel="acl" +Link: ; rel="up" Link: ; rel="type" Content-Length: 0 ``` -On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. Include relevant headers such as Content-Type matching the created resource; Content-Length: 0 indicates no body. Server responses MUST use entity tags for responses that contain resource representations or successful responses to HEAD requests, enabling concurrency control in subsequent operations. +On success, return 201 Created with the new URI in the `Location` header. The body may be empty or a minimal representation. If the target container `/alice/notes/` does not exist, the server MUST return a 404 error status unless another status code is more appropriate. -**Creating Containers:** To create a new container via the REST API, a client uses POST to an existing parent container, with the Content-Type header set to the LWS-defined media type `application/lws+json` to indicate container creation. The body MAY be empty. Servers MUST support creation of containers using this media type. For example: +**Creating Containers:** To create a new container, a client uses POST to an existing parent container with a `Link` header indicating the Container type. For example: ``` POST /alice/ HTTP/1.1 Host: example.com Authorization: Bearer -Content-Type: application/lws+json Content-Length: 0 Slug: notes +Link: ; rel="type" +``` + +**Example (Response to POST — container):** +``` +HTTP/1.1 201 Created +Location: /alice/notes/ +Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="up" +Link: ; rel="type" +Content-Length: 0 ``` -This would create a new container at `/alice/notes/`, with server-generated metadata including rel="type" as https://www.w3.org/ns/lws#Container. +This creates a new container at `/alice/notes/`, with server-generated metadata including `rel="type"` as `https://www.w3.org/ns/lws#Container`. **Additional notes on Create (HTTP binding):** * POST is not idempotent. Repeating it may create duplicates; clients SHOULD avoid unintentional retries or use unique identifiers/checks to prevent this. -* Servers MUST distinguish between DataResource and Container types in metadata upon creation, based on the Content-Type header in the request. * Metadata updates are atomic; servers MUST ensure the linkset resource is created and populated with mandatory server-managed fields before returning success. -* For discoverability, servers SHOULD include a Link header with rel="storageDescription" on 401 responses to guide clients without hardcoded URIs. +* For discoverability, servers SHOULD include a `Link` header with `rel="storageDescription"` on 401 responses to guide clients without hardcoded URIs. **Managing and Retrieving Metadata (Related to Creation):** -While metadata is primarily retrieved via read operations, it is generated during creation. Clients can immediately retrieve it post-creation using GET or HEAD on the new resource URI. Clients can use the Prefer header to request inclusion of specific metadata links (via relation types) and attributes. +While metadata is primarily retrieved via read operations, it is generated during creation. Clients can immediately retrieve it post-creation using GET or HEAD on the new resource URI. Clients can use the `Prefer` header to request inclusion of specific metadata links (via relation types) and attributes. diff --git a/lws10-core/Operations/delete-resource.md b/lws10-core/Operations/delete-resource.md index 09806fd..1e4c146 100644 --- a/lws10-core/Operations/delete-resource.md +++ b/lws10-core/Operations/delete-resource.md @@ -8,13 +8,16 @@ Permanently removes a resource and its associated metadata. The delete resource operation is implemented using the HTTP DELETE method, as defined in the abstract operation above. This section specifies the HTTP bindings for inputs, behaviors, and responses. -The DELETE request targets the URI of the resource or container to remove. Clients MAY include an If-Match header with an ETag for concurrency checks, as described in the abstract operation. +The DELETE request targets the URI of the resource or container to remove. Clients MAY include an `If-Match` header with an ETag for concurrency checks. -For non-container resources, the server processes the deletion as specified in the abstract behavior. +**Deletion and Containment:** +When a resource is deleted, the server MUST atomically remove it from its parent container's `items` list. The parent container's `totalItems` count and ETag MUST be updated accordingly. -For container resources, the server defaults to non-recursive deletion. If recursion is desired and supported, clients MUST use the Depth: infinity header, as defined in [[RFC4918]]. Servers that do not support recursion MUST reject such requests with 501 Not Implemented. +For non-container resources, the server removes the resource content, its associated metadata (linkset), and the containment reference in the parent container. -On success, the server MUST respond with 204 No Content. Servers SHOULD support concurrency checks via If-Match with ETags; mismatches MUST yield 412 Precondition Failed. +For container resources, the server defaults to non-recursive deletion. If the container is not empty and recursion is not requested, the server MUST reject the request with 409 Conflict. Servers MAY support recursive deletion of all contained resources within the container that is being deleted. Clients MUST use the `Depth: infinity` header to request for a recursive delete, as defined in [[RFC4918]]. + +On success, the server MUST respond with 204 No Content. Servers SHOULD support conditional requests, as defined in [[RFC9110]]. If the client lacks authorization, the server MUST return 403 Forbidden (if the client's identity is known but permissions are insufficient) or 401 Unauthorized (if no valid authentication is provided). In cases where revealing resource existence poses a security risk, the server MAY return 404 Not Found instead. @@ -24,7 +27,7 @@ DELETE /alice/notes/shoppinglist.txt HTTP/1.1 Authorization: Bearer If-Match: "abc123456" ``` -Assuming the ETag matches and the client is authorized, the server deletes the resource, its metadata, and updates the containing container `/alice/notes/` atomically: +Assuming the ETag matches and the client is authorized, the server deletes the resource, its metadata, and removes it from the parent container `/alice/notes/` atomically: ``` HTTP/1.1 204 No Content ``` diff --git a/lws10-core/Operations/metadata.md b/lws10-core/Operations/metadata.md index 1f9da51..8aacf74 100644 --- a/lws10-core/Operations/metadata.md +++ b/lws10-core/Operations/metadata.md @@ -7,25 +7,27 @@ All metadata in LWS is expressed as a set of typed links originating from a reso - A relation type: A string that defines the nature of the relationship. - Optional target attributes: Additional key-value pairs that further describe the link or the target resource. -Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For containers, metadata includes membership details and supports pagination to handle large sets efficiently. For DataResources, metadata includes representations, each with mediaType and optional sizeInBytes. +Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For Data Resources, metadata includes representations, each with mediaType and optional sizeInBytes. For Containers and Data Resources we consider the link to its parent container resource to be part of the metadata of the resource. + **The Linkset Resource** For each resource in storage, a server MUST make metadata links available as a standalone resource according to [[!RFC9264]]. -- Discovery: A resource's linkset is discoverable via a Link header with the relation rel="linkset". -- Media Type: A linkset resource MUST be available as application/linkset+json. +- Discovery: A resource's linkset is discoverable via a Link header with the relation `rel="linkset"`. +- Media Type: A linkset resource MUST be available as `application/linkset+json`. - Integrity: The 'linkset' link MUST point to a server-managed resource. Updates to the linkset MUST be atomic with associated resource operations to maintain consistency. **Discovering Metadata** Clients discover metadata primarily through Link headers in response to GET or HEAD requests. -- Storage Description: Servers MUST support a Link header with rel="storageDescription" on relevant responses. -- Preferences: Clients MAY use the Prefer header [[!RFC7240]] with the URI https://www.w3.org/ns/lws#PreferLinkRelations to include or omit specific relations. +- Storage Description: Servers MUST support a Link header with `rel="storageDescription"` on relevant responses. +- Containment: Servers MUST include a Link header with `rel="up"` pointing to the parent container for any non-root resource. +- Preferences: Clients MAY use the Prefer header [[!RFC7240]] with the URI `https://www.w3.org/ns/lws#PreferLinkRelations` to include or omit specific relations. **Metadata Types** | Category | Description | |------------|------------| -| System Managed | Maintained by the server; Read-Only. Includes acl, linkset, type, representation, sizeInBytes, modified. | -| Core Metadata | Managed by the client (subject to server restrictions). Includes partOf, contains, title, creator. | +| System Managed | Maintained by the server; Read-Only. Includes `linkset`, `type`, `mediaType`, `size`, `modified`. | +| Core Metadata | Managed by the client (subject to server restrictions). Includes `up`, `items`, `title`, `creator`. | | User-Defined | Custom vocabularies and indexes created by the user. | @@ -34,7 +36,7 @@ Core metadata MAY be modified by clients. To ensure interoperability, servers MU 1. Method Discovery: Servers MUST advertise support for GET and PATCH operations on the linkset resource via the Allow header. -2. Patch Format Discovery: Servers MUST advertise support for JSON Merge Patch [[!RFC7386]] via the Accept-Patch header: Accept-Patch: application/merge-patch+json. +2. Patch Format Discovery: Servers MUST advertise support for JSON Merge Patch [[!RFC7386]] via the Accept-Patch header: `Accept-Patch: application/merge-patch+json`. 3. Optional Methods: Servers MAY support PUT or alternative patch formats; if supported, these MUST be included in the Allow and Accept-Patch headers respectively. @@ -43,10 +45,10 @@ Core metadata MAY be modified by clients. To ensure interoperability, servers MU **Managing Metadata** Metadata is managed by interacting with the resource's associated linkset URI. Servers MUST support concurrency controls for updates. -- Partial Updates (PATCH): This is the primary mechanism for metadata management. Servers MUST support PATCH using application/merge-patch+json. +- Partial Updates (PATCH): This is the primary mechanism for metadata management. Servers MUST support PATCH using `application/merge-patch+json`. - Replacement (PUT): If advertised in the Allow header, a client MAY replace the entire linkset. If the server does not support PUT, it MUST reject the request with 405 Method Not Allowed. -- Restrictions: Servers MAY restrict modifications to specific links (like partOf or contains) to maintain system integrity. If a server restricts partOf modifications, it MUST document this in its conformance statement. +- Restrictions: Servers MAY restrict modifications to specific links (like `up` or `items`) to maintain system integrity. -- Lifecycle: Metadata lifecycles are tied to the described resource; deleting a resource MUST result in the automatic removal of its associated linkset metadata. \ No newline at end of file +- Lifecycle: Metadata lifecycles are tied to the described resource; deleting a resource MUST result in the automatic removal of its associated linkset metadata. diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md index 5d1aa1c..409b7ff 100644 --- a/lws10-core/Operations/read-resource.md +++ b/lws10-core/Operations/read-resource.md @@ -1,14 +1,14 @@ Retrieves the representation of an existing resource or the listing of a container. * **Inputs**: Target identifier and optional parameters. -* **Behavior**: - * For non-container resources, the server returns the resource content. - * For containers, the server returns a listing of member resources. Listings must include core metadata for each member and must be filtered based on the requester's permissions. +* **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. * **Outcome**: The requested representation or a notification of failure. -The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as rel="linkset", rel="acl", rel="partOf", and rel="type". Servers MUST ensure atomicity between the resource state and its metadata during reads. +The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). The behavior differs depending on whether the target URL is a container or a non-container resource (DataResource). Servers MUST distinguish resource types via metadata. All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as `rel="linkset"`, `rel="up"`, and `rel="type"`. Servers MUST ensure atomicity between the resource state and its metadata during reads. -**GET (non-container resource)** – *Retrieve a resource’s content:* +**GET (non-container resource)** – *Retrieve a resource's content:* Send GET to the resource URI for full content (if authorized). Respond with 200 OK, body containing the data, and Content-Type matching the stored media type. Servers MUST support range requests per [[!RFC7233]] for partial retrieval. Responses MUST include an ETag header for concurrency control and caching. **Example (GET a file):** @@ -24,9 +24,9 @@ Content-Type: text/plain; charset=UTF-8 Content-Length: 34 ETag: "abc123456" Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="partOf" -Link: ; rel="acl" +Link: ; rel="up" Link: ; rel="type" + milk cheese bread @@ -36,12 +36,12 @@ chocolate bars hash eggs ``` -The server returned the text content (34 bytes in total, as indicated by `Content-Length`). The content is exactly the stored data in the file. The `ETag: "abc123456"` is a version identifier for caching or concurrency purposes. The response includes Link headers for metadata discoverability, with mandatory fields such as partOf, acl, and type. +The server returned the text content (34 bytes in total, as indicated by `Content-Length`). The content is exactly the stored data in the file. The `ETag: "abc123456"` is a version identifier for caching or concurrency purposes. The response includes Link headers for metadata discoverability, with mandatory fields such as `up` and `type`. -**GET (container resource)** – *List a container’s contents:* -When the target URI corresponds to a container (determined via metadata type), a GET request will return a listing of the container’s members rather than raw content. Servers MUST support pagination for large memberships, using query parameters or headers to return partial listings with links to subsequent pages, responding with 206 Partial Content for paginated responses. Listings MUST include metadata for each member: resource IDs (MUST), types as an array of system and user-defined (MUST), representations with mediaType and optional sizeInBytes (MUST for DataResources), modified timestamps (SHOULD). +**GET (container resource)** – *List a container's contents:* +When the target URI corresponds to a container (determined via metadata type), a GET request returns a listing of the container's members. The response body is a container representation as defined in the [Container Representation](#container-representation) section, using the LWS container media type. The listing includes metadata for each member: resource identifiers (MUST), types (MUST), media types (MUST for DataResources), sizes (SHOULD), and modification timestamps (SHOULD). -**Example (GET a container with JSON-LD):** +**Example (GET a container):** ``` GET /alice/notes/ HTTP/1.1 Authorization: Bearer @@ -50,50 +50,38 @@ Accept: application/ld+json Assuming the container exists and the client has access: ``` HTTP/1.1 200 OK -Content-Type: application/ld+json; profile="https://www.w3.org/ns/lws/v1" +Content-Type: application/lws+json ETag: "container-etag-789" Link: ; rel="linkset"; type="application/linkset+json" -Link: ; rel="partOf" -Link: ; rel="acl" +Link: ; rel="up" Link: ; rel="type" + { - "@context": "https://www.w3.org/ns/lws/context/v1.jsonld", - "@id": "/alice/notes/", - "@type": "Container", + "@context": "https://www.w3.org/ns/lws/v1", + "id": "/alice/notes/", + "type": "Container", "totalItems": 2, - "first": { - "@type": "ContainerPage", - "@id": "/alice/notes/?page=1", - "partOf": "/alice/notes/", - "contains": [ - { - "@id": "/alice/notes/1.txt", - "@type": ["DataResource", "http://example.org/customType"], - "representation": [ - { - "mediaType": "text/plain", - "sizeInBytes": 1024 - } - ], - "modified": "2025-11-24T12:00:00Z" - }, - { - "@id": "/alice/notes/2.txt", - "@type": "DataResource", - "representation": [ - { - "mediaType": "text/plain", - "sizeInBytes": 2048 - } - ], - "modified": "2025-11-24T13:00:00Z" - } - ] - } + "items": [ + { + "type": "DataResource", + "id": "/alice/notes/shoppinglist.txt", + "mediaType": "text/plain", + "size": 47, + "modified": "2025-11-24T12:00:00Z" + }, + { + "type": ["DataResource", "http://example.org/customType"], + "id": "/alice/notes/todo.json", + "mediaType": "application/json", + "size": 2048, + "modified": "2025-11-24T13:00:00Z" + } + ] } ``` -In this example, `/alice/notes/` is a container. The response uses JSON-LD with a normative context, listing members with required metadata. For large containers, the response might include a "next" property and use 206 Partial Content. -In all cases, the server MUST include the following metadata in the response headers: an ETag (representing the listing version, which changes on membership modifications), and Link headers with rel="type" indicating it is a container, rel="linkset", rel="partOf", and rel="acl". +In this example, `/alice/notes/` is a container. The response uses JSON-LD with the LWS context, listing members with required metadata. Each item includes its `type`, `id`, `mediaType`, `size`, and `modified` timestamp as flat properties. + +In all cases, the server MUST include the following metadata in the response headers: an ETag (representing the listing version, which changes on membership modifications), and Link headers with `rel="type"` indicating it is a container, `rel="linkset"` and `rel="up"`. **HEAD (any resource or container)** – *Headers/metadata only:* The LWS server MUST support HEAD [[RFC9110]] for both containers and non-containers, returning the same headers as GET (including ETag, Content-Type, Link for metadata) but without a body. This enables metadata retrieval without transferring content. diff --git a/lws10-core/Operations/rest-table.md b/lws10-core/Operations/rest-table.md index 74a8acf..73570db 100644 --- a/lws10-core/Operations/rest-table.md +++ b/lws10-core/Operations/rest-table.md @@ -2,7 +2,7 @@ This table maps generic LWS [responses](#dfn-responses) (from Section 8) to HTTP status codes and payloads for consistency, incorporating specific scenarios such as pagination, concurrency controls, quota constraints, and metadata integration: | LWS response | HTTP status code | HTTP payload | | ----- | ----- | ----- | -| [Success](#dfn-success) (read or update, returning data) | 200 OK | [Resource representation](#dfn-resource-representation) in the response body (for GET or if PUT/PATCH returns content), along with relevant headers (Content-Type, ETag, Link for metadata such as rel="linkset", rel="acl", rel="parent"). For container listings, include JSON-LD with normative context and member metadata (IDs, types, sizes, timestamps). | +| [Success](#dfn-success) (read or update, returning data) | 200 OK | [Resource representation](#dfn-resource-representation) in the response body (for GET or if PUT/PATCH returns content), along with relevant headers (Content-Type, ETag, Link for metadata such as rel="linkset", rel="up"). For container listings, include JSON-LD with normative context and member metadata (IDs, types, sizes, timestamps). | | [Created](#dfn-created) (new resource) | 201 Created | Typically no response body (or a minimal representation of the new resource). The `Location` header is set to the new resource’s URI. Headers like ETag MUST be included for concurrency; Link headers for server-managed metadata. | | Deleted (no content to return) | 204 No Content | No response body. Indicates the resource was deleted or the request succeeded and there’s nothing else to say. Servers MAY use 410 Gone for permanent deletions. | | Bad Request (invalid input or constraints) | 400 Bad Request | Error details explaining what was wrong. Servers SHOULD use the standard format defined in [[RFC9457]] for structured error responses, such as a JSON object with fields like "type", "title", "status", "detail", and "instance". | diff --git a/lws10-core/Operations/restbinding.md b/lws10-core/Operations/restbinding.md index d799a7e..f7b4d26 100644 --- a/lws10-core/Operations/restbinding.md +++ b/lws10-core/Operations/restbinding.md @@ -1,3 +1,3 @@ For each core operation (create, read, update, delete), we describe the HTTP method(s) to use, required headers or special considerations (including concurrency controls via ETags, content negotiation, and pagination for container listings), and what the server should do and return. Standard HTTP status codes are used to indicate outcomes with additional mappings for scenarios such as quota exceeded (507 Insufficient Storage) or precondition failures (412 Precondition Failed). The binding tries to adhere to HTTP/1.1 and relevant RFCs (such as [[!RFC7231]] for HTTP semantics, [[!RFC7233]] for range requests, [[!RFC5789]] for PATCH, [[!RFC8288]] for Web Linking, and [[!RFC9264]] for Link Sets) so that it integrates naturally with web standards. Discoverability is emphasized through mechanisms like Link headers and WWW-Authenticate headers on 401 responses, avoiding hardcoded URI locations. Metadata integration is required across operations, ensuring atomicity and use of Link Sets for server-managed and user-managed properties. -**Note:** As all examples in this specifications, examples given in this section (HTTP request and response snippets) are **non-normative**, meant to illustrate typical usage. The actual requirements are stated in the descriptive text and tables. Also, while this binding covers HTTP (as the initial target protocol), the LWS operations could in principle be bound to other protocols in the future. Servers SHOULD support content negotiation for formats like JSON-LD (with normative contexts and optional framing for containers) and Turtle, using custom media types such as 'application/lws+json' where appropriate. \ No newline at end of file +**Note:** As all examples in this specifications, examples given in this section (HTTP request and response snippets) are **non-normative**, meant to illustrate typical usage. The actual requirements are stated in the descriptive text and tables. Also, while this binding covers HTTP (as the initial target protocol), the LWS operations could in principle be bound to other protocols in the future. Servers MUST support content negotiation for `application/lws+json`, `application/ld+json`, and `application/json` for container representations (see [Container Media Type](#container-media-type)). Servers MAY additionally support formats like Turtle. \ No newline at end of file diff --git a/lws10-core/container-representation.md b/lws10-core/container-representation.md new file mode 100644 index 0000000..c08256a --- /dev/null +++ b/lws10-core/container-representation.md @@ -0,0 +1,54 @@ +### 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 3bc280c..8ca0791 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -164,6 +164,13 @@

Terminology

capability such as a ZCAP.
  • authentication suite — a defined validation mechanism for a concrete serialization of an authentication credential.
  • +
  • LWS resource — An LWS Resource is 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.
  • +
  • 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.
  • @@ -208,6 +215,11 @@

    Logical Resource Organization

    +
    +

    Container Representation

    +
    +
    +

    Operations

    @@ -237,6 +249,16 @@

    Delete resource

    +
    +

    LWS Media Type

    +
    +
    + +
    +

    JSON-LD Context and Vocabulary

    +
    +
    +

    Resource Identification

    diff --git a/lws10-core/jsonld-context.md b/lws10-core/jsonld-context.md new file mode 100644 index 0000000..7949e1d --- /dev/null +++ b/lws10-core/jsonld-context.md @@ -0,0 +1,62 @@ +### JSON-LD Context and Vocabulary + +#### Normative JSON-LD Context + +Container representations MUST include the following `@context` value: + +``` +"@context": "https://www.w3.org/ns/lws/v1" +``` + +The normative JSON-LD context document defines the mapping between the short property names used in container representations and their full URIs in the LWS and related vocabularies. The context is defined as follows: + +```json +{ + "@context": { + "@version": 1.1, + "@protected": true, + "lws": "https://www.w3.org/ns/lws#", + "as": "https://www.w3.org/ns/activitystreams#", + "schema": "https://schema.org/", + "xs": "http://www.w3.org/2001/XMLSchema#", + "id": "@id", + "type": "@type", + "Container": "lws:Container", + "DataResource": "lws:DataResource", + "items": "lws:items", + "totalItems": "as:totalItems", + "mediaType": "as:mediaType", + "size": { + "@id": "schema:size", + "@type": "xs:long" + }, + "modified": { + "@id": "as:updated", + "@type": "xs:dateTime" + } + } +} +``` + +The context is `@protected`, ensuring that the term definitions cannot be overridden by other contexts. + +#### Vocabulary + +The LWS vocabulary defines the following types and properties used in container representations: + +**Types:** + +| Term | URI | Description | +|------|-----|-------------| +| `Container` | `lws:Container` | A resource that contains other resources | +| `DataResource` | `lws:DataResource` | A data-bearing resource | + +**Properties:** + +| Term | URI | Description | +|------|-----|-------------| +| `items` | `lws:items` | The list of resources contained in a container | +| `totalItems` | `as:totalItems` | The total number of contained resources | +| `mediaType` | `as:mediaType` | The media type of a resource | +| `size` | `schema:size` | The size of a resource in bytes | +| `modified` | `as:updated` | The date-time a resource was last modified | diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md index 2e50798..89143a6 100644 --- a/lws10-core/logicalresourceorganization.md +++ b/lws10-core/logicalresourceorganization.md @@ -1,24 +1,47 @@ -### Logical Resource Organization -This section delineates the abstract data model governing the organization of resources within the Linked Web Storage (LWS) system. It encompasses the structuring of containers and resources, their hierarchical interrelations, the functional semantics of containers as organizational units, rules pertaining to containment, and mechanisms for clients to organize and navigate resource collections. This model establishes the logical namespace of the storage, delineating inter-resource relationships therein, without presupposing any specific identifier structure or semantic implications derived from identifier composition. Logical organization MUST prioritize discoverability and self-descriptive APIs, avoiding hardcoded locations. Containment is represented as metadata to enable multiple containers per resource without URL changes, supporting sharing use cases. All entities MUST have associated metadata resources using Link Sets (RFC 9264), distinguishing server-managed and user-managed data. +### Container Model -### Resource -In LWS, a resource constitutes the fundamental unit of storage and access. Each resource possesses a unique identifier within the system. A resource may encompass data, such as content or structured information, alongside associated metadata, including attributes like type or modification timestamps. Resources MUST be classified as 'DataResource', 'Container', or 'MetadataResource' via metadata types. DataResources MAY have multiple representations; servers MUST track original media types and support reification in metadata using the 'representation' property, which includes 'mediaType' and optional 'sizeInBytes'. +Linked Web Storage organizes resources into containers. A container is a specialized resource that holds references to other resources, called its members. Containers serve +as organizational units, analogous to directories or collections, enabling clients to group, discover, and navigate resources. 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. -### Container -A container is a specialized resource capable of encompassing other resources as members. Containers function as organizational constructs, facilitating the grouping of resources in a manner akin to collections or directories. A container maintains references to its member resources, which may comprise both non-container resources and additional container resources, thereby enabling hierarchical formations. Typically, a container holds minimal intrinsic content beyond metadata or enumerations of its members; its principal role is to aggregate and structure subordinate resources. The storage system's root is designated as a container, serving as the apex organizational unit devoid of a superior parent. Containers MUST support pagination for membership listings using 'ContainerPage' types, with properties such as 'first', 'next', 'prev', and 'last'. Representations MUST use JSON-LD with a specific frame and normative context, optionally advertising content negotiation via 'Vary: Accept' headers. Storage MAY function as a root container, enabling direct writes. +Every LWS storage has a **root container** that serves as the top-level organizational unit. The root container has no parent and acts as the entry point for the storage hierarchy. -### Containment and Hierarchy -With the exception of the root container, every resource is affiliated with precisely one parent container. This affiliation engenders a strict hierarchical structure, manifesting as a tree with a singular root container at its pinnacle. Upon creation within a designated container, a new resource becomes a member of that container, appearing within its membership enumeration. Cycles or multiple parent affiliations are prohibited within this model; a resource cannot concurrently belong to multiple containers without duplication or alternative referencing mechanisms external to the core containment framework. This constraint enhances model simplicity and aligns with conventional organizational paradigms. Containment MUST be modeled as metadata links using 'contains' (from container to member) and 'partOf' (from member to container), allowing transitive queries and multiple hierarchies without slash semantics. Servers MAY support hierarchy arrays for ancestors. +Resources in LWS are classified as either: -### Container Membership Management -Operations involving the creation, deletion, or relocation of resources influence container memberships as follows: -- Upon creation, a new resource is associated with a specified parent container. This association integrates the resource into the parent's membership. -- Deletion of a resource entails its removal from the parent container's membership. Should this render the container devoid of members, it assumes an empty state, potentially permitting its subsequent deletion if warranted. Container deletion typically necessitates an empty state or invokes recursive removal of members. -- The core operations (create, read, update, delete) do not incorporate an explicit relocation or renaming function. To reassign a resource to an alternative container, a client may replicate or recreate the resource in the target location followed by deletion of the original. Implementations may optionally extend non-core operations for relocation or renaming, achievable logically through combined creation and deletion. -Membership is managed via create/delete operations; direct updates to membership listings are server-managed and not client-writable to avoid concurrency issues. +- **Container** — a resource that contains other resources. +- **DataResource** — a data-bearing resource (e.g., a document, image, or structured data file). -### Container Creation -Container instantiation occurs via the standard resource creation operation (Section 7.1), differentiated by an indicator specifying the intent to establish a container rather than a non-container resource. This process yields an empty container amenable to subsequent population with members, including sub-containers to extend the hierarchy. Servers MUST assign identifiers, and empty containers MUST be supported. +### Containment -### Navigating and Listing Resources -Clients navigate the hierarchy through read operations on containers, which yield enumerations of member identifiers. A container's representation furnishes a listing of its members, enabling traversal and discovery of subordinate resources. Listings MUST include metadata for each member, such as resource IDs (MUST), types (array of system and user-defined), representations (MUST for DataResources, including mediaType and optional sizeInBytes), and modified timestamps (SHOULD). \ No newline at end of file +The containment relationship between a resource and its parent container is expressed via the `rel="up"` link relation. Servers MUST include a `Link` header with `rel="up"` pointing to the parent container in responses to GET and HEAD requests on any non-root resource. + +``` +Link: ; rel="up" +``` + +A container's members are listed in its representation using the `items` property. The server manages this list; clients cannot modify it directly. Membership changes occur as a side effect of resource creation and deletion. + +### Containment Integrity + +The server MUST maintain containment integrity at all times: + +- **Creation**: When a new resource is created in a container, the server MUST atomically add the resource to the container's `items` list. +- **Deletion**: When a resource is deleted, the server MUST atomically remove it from its parent container's `items` list. Deleting a container requires the container to be empty, unless recursive deletion is explicitly requested. +- **No orphans**: Every non-root resource MUST be reachable from the root container through the containment hierarchy. +- **No cycles**: A container MUST NOT directly or indirectly contain itself. + +### Resource Identification + +Resources are identified by URIs. The URI of a resource is independent of its position in the containment hierarchy. Servers assign URIs during resource creation and MAY incorporate client hints (e.g., the `Slug` header), but clients SHOULD NOT assume that URI structure reflects containment. + +Containment relationships are expressed through metadata (`rel="up"` links and the `items` property in container representations), not through URI path structure. This separation allows servers flexibility in URI assignment while maintaining a well-defined organizational model. + +### Container Membership and Authorization + +If a client has read access to a container, the container representation MUST include the identifiers for all resources contained in that container 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. + +A client's ability to read a container listing does not imply access to the contained resources themselves, and vice versa. diff --git a/lws10-core/lws-media-type.md b/lws10-core/lws-media-type.md new file mode 100644 index 0000000..5f56618 --- /dev/null +++ b/lws10-core/lws-media-type.md @@ -0,0 +1,15 @@ +### LWS Media Type + +LWS container representation and storage description resource MUST use the media type `application/lws+json`. + +While LWS container representations use JSON-LD conventions, the constraints and requirements for LWS justify the use of a specific media type. Because LWS containers can be considered a restricted profile of JSON-LD, implementations SHOULD consider the `application/ld+json; profile="https://www.w3.org/ns/lws/v1"` media type as equivalent to `application/lws+json`. + +#### Content Negotiation + +Servers MUST support content negotiation for container representations. The response payload MUST be identical regardless of the requested media type — only the `Content-Type` response header varies: + +- If a client requests `application/lws+json`, the server MUST respond with `Content-Type: application/lws+json`. +- If a client requests `application/ld+json`, the server MUST respond with `Content-Type: application/ld+json`. +- If a client requests `application/json`, the server MUST respond with `Content-Type: application/json`. + +In all three cases, the response body is the same JSON-LD document conforming to the LWS container vocabulary. Servers are free to support additional media types (e.g., `text/turtle`) through content negotiation.