diff --git a/.github/workflows/add_prs_and_issues_to_project.yml b/.github/workflows/add_prs_and_issues_to_project.yml index 248ffb3..3e9625b 100644 --- a/.github/workflows/add_prs_and_issues_to_project.yml +++ b/.github/workflows/add_prs_and_issues_to_project.yml @@ -1,19 +1,19 @@ -name: Add pull requests and issues to projects - -on: - pull_request_target: - types: - - opened - issues: - types: - - opened - -jobs: - add-to-project: - name: Add PR and issues to project - runs-on: ubuntu-latest - steps: - - uses: actions/add-to-project@v0.4.1 - with: - project-url: https://github.com/orgs/w3c/projects/153 - github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} +name: Add pull requests and issues to projects + +on: + pull_request_target: + types: + - opened + issues: + types: + - opened + +jobs: + add-to-project: + name: Add PR and issues to project + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v0.4.1 + with: + project-url: https://github.com/orgs/w3c/projects/153 + github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 2d3ac15..42b7add 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ -# Code of Conduct - -All documentation, code and communication under this repository are covered by the [W3C Code of Conduct](https://www.w3.org/policies/code-of-conduct/). +# Code of Conduct + +All documentation, code and communication under this repository are covered by the [W3C Code of Conduct](https://www.w3.org/policies/code-of-conduct/). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 601a4ac..be92ac8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,24 +1,24 @@ -# Linked Web Storage Working Group - -Contributions to this repository are intended to become part of Recommendation-track documents governed by the -[W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/) and -[Document License](https://www.w3.org/copyright/document-license/). To make substantive contributions to specifications, you must either participate -in the relevant W3C Working Group or make a non-member patent licensing commitment. - -If you are not the sole contributor to a contribution (pull request), please identify all -contributors in the pull request comment. - -To add a contributor (other than yourself, that's automatic), mark them one per line as follows: - -``` -+@github_username -``` - -If you added a contributor by mistake, you can remove them in a comment with: - -``` --@github_username -``` - -If you are making a pull request on behalf of someone else but you had no part in designing the -feature, you can remove yourself with the above syntax. +# Linked Web Storage Working Group + +Contributions to this repository are intended to become part of Recommendation-track documents governed by the +[W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/) and +[Document License](https://www.w3.org/copyright/document-license/). To make substantive contributions to specifications, you must either participate +in the relevant W3C Working Group or make a non-member patent licensing commitment. + +If you are not the sole contributor to a contribution (pull request), please identify all +contributors in the pull request comment. + +To add a contributor (other than yourself, that's automatic), mark them one per line as follows: + +``` ++@github_username +``` + +If you added a contributor by mistake, you can remove them in a comment with: + +``` +-@github_username +``` + +If you are making a pull request on behalf of someone else but you had no part in designing the +feature, you can remove yourself with the above syntax. diff --git a/LICENSE.md b/LICENSE.md index d6c89e5..ffebec0 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -All documents in this Repository are licensed by contributors -under the -[W3C Document License](https://www.w3.org/copyright/document-license/). - +All documents in this Repository are licensed by contributors +under the +[W3C Document License](https://www.w3.org/copyright/document-license/). + diff --git a/lws10-core/Operations/create-resource.md b/lws10-core/Operations/create-resource.md new file mode 100644 index 0000000..f84e7fc --- /dev/null +++ b/lws10-core/Operations/create-resource.md @@ -0,0 +1,21 @@ +### Create Resource Operation +The *create resource* operation requests the creation of a new resource on the server. The resource can be a non-container (data) resource or a container (collection) resource. The operation mandates that the server assigns a new identifier within a target container (like creating a new file in a folder); client-specified full identifiers are not supported for creation in this version to ensure server authority over naming and to simplify interactions. + +**Inputs:** +* **Target container identifier:** The identifier of an existing container where the new resource will be created as a member. +* **Resource content:** The content to store in the resource (binary or text). This is optional to allow creation of an empty container or an empty resource. +* **Suggested name:** An optional hint for naming. The server MAY incorporate this if it does not conflict with naming rules or existing resources. +* **Media type:** The MIME media type or format of the content. This helps the server understand how to store and serve the content. It MUST be provided when content is included and MAY be omitted for empty containers. + +**Behavior:** +* The server MUST create a new resource as a member of the specified target container, assigning the identifier (potentially incorporating the suggested name). The new resource is then added to the specified container’s member list via metadata updates. +* Upon creation, servers MUST generate a metadata resource linked via Link Sets (RFC 9264), including mandatory server-managed fields such as type (https://www.w3.org/ns/lws#Container or https://www.w3.org/ns/lws#DataResource), mediaType (if applicable), ACL reference, and partOf (linking to the target container). User-managed metadata MAY be provided by the client, but server-managed fields MUST NOT be overridden. +* The server **MAY** enforce additional constraints on creation, such as size limits, quota checks, or restrictions on allowed media types. If any such constraint is violated, the server will reject the operation with an appropriate error. +* The creation MUST be atomic, including metadata generation and container membership updates—if any step fails, no new resource or metadata is created (or any partial artifacts are cleaned up). The identifier of the newly created resource **MUST** be returned to the client (so the client knows how to refer to it). + +**Possible Responses:** *(on the abstract operation level, not tied to a specific protocol)* +* **Created:** The operation succeeded in creating a new resource. The response includes the new resource’s identifier and possibly a minimal representation or metadata. +* **Bad Request:** The request was malformed or violated constraints. The resource was not created. +* **Not Permitted:** The client is not authorized to create a resource in the target location. +* **Not Found:** The specified target container does not exist or cannot be found. This could also be treated as a type of Bad Request or Not Permitted, depending on the cause. +* **Unknown Error:** An internal server error occurred, or some unexpected condition prevented the creation. This is a catch-all for failures not covered by more specific errors. The response would indicate that the server failed the operation (and ideally include an error message or code). \ No newline at end of file diff --git a/lws10-core/Operations/delete-resource.md b/lws10-core/Operations/delete-resource.md new file mode 100644 index 0000000..9b4f908 --- /dev/null +++ b/lws10-core/Operations/delete-resource.md @@ -0,0 +1,24 @@ +### Delete Resource Operation +The [*delete resource*](https://w3c.github.io/lws-protocol/spec/#dfn-deletion) operation removes an existing resource (or, in some cases, an entire container) from the storage. This operation is akin to deleting a file or folder in a file system. Once completed, the target resource is no longer available for read or update, and its identifier becomes invalid (attempts to access it later should report it as not found, unless it is recreated). Deletes MUST be atomic, including the removal of associated metadata resources and updates to containing container memberships. Metadata lifecycles are tied to the primary resource, with automatic deletion upon resource removal. + +**Inputs**: +* **Target identifier:** The identifier of the resource or container to delete. +* **Optional recursive flag:** Applicable if the target is a container. By default, containers must be empty (no members) to be deleted. If the client explicitly indicates a *recursive delete* (where supported), it signals that the server should delete the container and all of its contents including any sub-containers (akin to `rm -r` on Unix-like OS). This flag must be used with care to avoid accidental mass deletion. +* **Optional concurrency check:** An optional condition to avoid conflicting deletes. This could be an expected version tag or token (for example, a last-known version number or ETag that the client has). Servers MUST support optional concurrency controls failing with Precondition Failed if the resource has changed since the client's last read. + +**Behavior:** +* If the target is a **non-container resource** (a single item), the server will remove that resource from storage. This includes deleting its content and any associated metadata or auxiliary resources. For example, if there are separate metadata files (like access control lists or index entries related to that resource), those MUST also be cleaned up as appropriate. After a successful deletion, any subsequent read or update of that resource by clients should be treated as if the resource has never existed (since it no longer does). +* If the target is a **container resource** (collection), the server will by default only delete it if it has no members (no child resources). This is to prevent accidental deletion of large sets of data. If the container is not empty (the client attempted to delete a non-empty container without explicitly saying it’s okay to also delete everything inside), the server MUST refuse the operation, signaling a conflict. The client then has the responsibility to either start by deleting the members or use an explicit recursive delete (similar to `rm -r`), if the server supports one. Deletes on containers MUST specify recursive or non-recursive behavior (non-recursive as default), failing if non-empty in non-recursive mode. +* If a **recursive delete** is explicitly requested (and supported by the server), the server will attempt to delete the target container and all resources contained within it, potentially including sub-containers and their contents (i.e., the entire sub-tree of that container). If a recursive delete operation fails partway through, the server is not required to roll back the deletions that have already succeeded; i.e., the operation may result in a partially deleted state. The server SHOULD indicate in its error response which resource caused the failure, if possible. Recursive deletion is OPTIONAL for servers; if not supported, servers MUST reject such requests with an appropriate error. It is a dangerous operation, so it MUST be explicit. Some protocols might require a special header or parameter for this. +* Authorization checks: The server must verify that the client has permission to delete the resource (and, if recursive, each contained resource). If not authorized, the server will deny the request; if recursive, the denial might come partway through the process. As with reads, if the client is entirely unauthenticated or not permitted, the server MUST refuse in a way that doesn’t reveal (to outsiders) whether the resource existed at all. Unauthorized deletes MUST not disclose resource existence. +* Upon successful deletion, the target resource is gone. The server should free up any storage associated with it and update any relevant indexes or containing containers. If the resource had specific metadata (like an ACL entry), that metadata MUST also be removed or invalidated. Deleting a container MUST involve updating its containing container to remove the now-deleted child. + +**Possible Responses:** +* **Deleted:** The resource (or container) was successfully deleted. In a concrete protocol this is usually indicated with a confirmation and no content (for example, HTTP 204 No Content). After this response, the client should consider the identifier no longer valid for use unless it’s recreated. Servers MAY indicate permanent removal. +* **Not Found:** The resource does not exist (or is already deleted). The server could not perform any deletion because there was nothing to delete. (Again, for unauthorized requests, the server might also use this response to avoid revealing that the resource existed at all.) +* **Not Permitted:** The client is not allowed to delete the resource. The server refused to perform the deletion. In an HTTP scenario this could be a 403 Forbidden. +* **Conflict:** The target is a container that is not empty, and the client did not request (or the server does not allow) recursive deletion. The server leaves the container and its contents intact, and returns an error indicating that the container has members and cannot be removed as requested. The client would need to handle this by emptying the container or explicitly requesting a recursive delete if supported. +* **Precondition Failed:** A concurrency mismatch occurred. The server rejects the delete without changes. +* **Unknown Error:** The server encountered an unexpected error during the deletion process. The state of the system should remain as before, but the operation failed. The server signals a generic internal error to the client. + +**Note:** When a server denies access (for read, update, delete, etc.) due to authorization, it should do so in a consistent manner. In many cases, a client not authorized to know of a resource’s existence will just get a **Not Found** response instead of **Not Permitted**, to avoid revealing that the resource is there. This is a security consideration that implementations should follow. \ No newline at end of file diff --git a/lws10-core/Operations/read-resource.md b/lws10-core/Operations/read-resource.md new file mode 100644 index 0000000..f31017a --- /dev/null +++ b/lws10-core/Operations/read-resource.md @@ -0,0 +1,20 @@ +### Read Resource Operation +The [*read resource*](https://w3c.github.io/lws-protocol/spec/#dfn-retrieval) operation retrieves a [resource representation](https://w3c.github.io/lws-protocol/spec/#dfn-resource-representation) of an existing resource or the contents of a container. In other words, it is used to **fetch or access data** stored in the system. This operation covers both reading non-container resources and listing the members of container resources (folders/collections). All reads MUST interact with associated metadata resources as defined in Section 9.1, ensuring atomicity and inclusion of Link Sets (RFC 9264) for descriptions. + +**Inputs:** +* **Target identifier:** The unique identifier of the resource or container to read. +* **Optional parameters:** These may include a *preferred format* for the response and/or a *partial range* specifier. For example, a client can request the resource in a specific format or ask for only a portion of the data (such as a byte range or subset), if the protocol supports it. The client might also indicate if it only wants metadata. For containers, parameters MAY include pagination controls or filters for metadata inclusion. + +**Behavior:** +* If the target is a **non-container resource**, the server returns the content of that resource. By default, the content is returned in its stored format (for example, the exact bytes of an image, or the text of a text file). If the client provided an acceptable format list, the server SHOULD honor it. If the server has multiple representations of the resource or can convert the resource to the requested format, it may return the resource in that format. Otherwise, if the requested format is not available, the server will respond with an error (indicating the format is not acceptable). +* If the target is a **container resource**, the server returns a representation of the container’s contents (a **listing of its member resources**). Instead of raw binary content, a container’s “content” is essentially the collection of references to its children. For containers with large memberships, servers MUST support pagination, returning partial listings with links to subsequent pages. Container listings MUST include metadata for each member, such as 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). Servers SHOULD support JSON-LD framing for container responses, using a normative JSON-LD context and optional informative JSON Schema, with a media type like 'application/ld+json; profile="https://www.w3.org/ns/lws/v1"'. The server may format this listing in a suitable manner. By default, if no specific format is requested, the server might return a human-readable HTML or text listing. If a machine-readable format is requested and supported (for example, JSON, XML, or Turtle for RDF), the server can return the listing in that format. Listings MUST be ACL-aware, filtering based on client permissions to ensure privacy. +* The read operation also supports *metadata-only* access. For example, a client might perform a read request that asks for no body (just headers or metadata in HTTP, or an existence check). In such cases the server can respond with just the meta-information (like the fact that the resource exists, its last-modified timestamp, size, etc.) without sending the full content. This is useful for clients to verify existence or check for updates without downloading the entire resource. +* **Authorization checks:** If the client does not have permission to read the target resource or container, the server must refuse the read in a way that does not reveal unauthorized information. Specifically, if a request is unauthorized, the server should respond with an access denial. Depending on the implementation’s security model, it might respond as “Not Permitted” (for an authenticated user who lacks read rights) or even as if the resource does not exist (to an unauthenticated request, so as not to confirm the resource’s existence). In other words, unauthorized reads MUST not disclose resource existence. + +**Possible Responses:** +* **Success:** The operation succeeded. For a non-container resource, the full (or requested range of) content is returned, along with relevant metadata (such as content type, length, and a version tag like an ETag or modification time). For a container, a listing of members (in the default or requested format) is returned. In a protocol like HTTP, a success might be a success with 200 OK and include the representation in the response body. +* **Not Found:** The target resource or container does not exist (or is not available to the client). The read operation could not be performed. (Also note, as mentioned, an unauthorized request might also result in a response that looks like a Not Found to avoid information disclosure.) +* **Not Permitted:** The client’s identity is known but they are not allowed to access this resource. The server refuses to provide the content. In an HTTP binding this could be a 403 Forbidden. No details about the resource should be revealed in the response. +* **Not Acceptable:** The client requested a format or representation that the server cannot provide. The resource exists, but the server could not satisfy the `Accept`/format criteria (for example, the client asked for XML but the resource is an image that can only be served in its binary format). In HTTP this corresponds to 406 Not Acceptable, possibly accompanied by a list of available formats or an explanation. +* **Partial Content:** (If partial range was requested and succeeded, or for paginated container listings.) The server returns a fragment of the resource (with status indicating partial content). This would include appropriate headers indicating the range delivered and total size, or links to subsequent pages for pagination. +* **Unknown Error:** Some internal error occurred while trying to read the resource (e.g., a backend failure). The operation did not succeed, and the server signals a generic error (like HTTP 500 Internal Server Error). \ No newline at end of file diff --git a/lws10-core/Operations/update-resource.md b/lws10-core/Operations/update-resource.md new file mode 100644 index 0000000..f8edd43 --- /dev/null +++ b/lws10-core/Operations/update-resource.md @@ -0,0 +1,24 @@ +### Update Resource Operation +The [*update resource*](https://w3c.github.io/lws-protocol/spec/#dfn-update-resource) operation modifies the contents or state of an existing [served resource](https://w3c.github.io/lws-protocol/spec/#dfn-served-resource). This is typically used to replace the content of a file, patch a document, or update metadata associated with a resource. The update can be done in two ways: by providing a full new content (replace the entire resource) or by providing a partial change (apply a patch to the current content). Updates apply only to non-container resources or container metadata; container membership is managed via create/delete operations on members (as per Section 8.4). + +**Inputs**: +* **Target identifier:** The identifier of the resource to update. (Containers generally cannot be “updated” in the same way; updating a container’s membership is done via create/delete of members rather than an explicit update to the container resource itself, except for changing container-specific metadata if any.) The target must already exist for an update operation to succeed. +* **New content:** The data to be written to the resource. For a full replacement update, this would be the entire new content. For a partial update, this would be some form of patch description containing the changes. The content could be binary or text, depending on the resource type. +* **Optional concurrency check:** An optional condition to avoid conflicting updates. This could be an expected version tag or token (for example, a last-known version number or ETag that the client has). The idea is to prevent **lost updates** – if the resource has been changed by someone else since the client last fetched it, the update operation can detect the mismatch and fail rather than blindly overwriting the other change. In protocols, this might be implemented with mechanisms like “If-Match” headers (HTTP) or other versioning schemes. + +**Behavior:** +* The server will attempt to apply the provided update to the target resource **atomically**. For a full content replacement, this means the old content is entirely replaced with the new content in one step. For a patch, the changes are applied to the current content. In either case, partial updates should be handled such that if the patch cannot be applied, the operation fails cleanly without altering the resource. Partial updates are optional; if supported, they MUST use standards like JSON Merge Patch or SPARQL Update for RDF resources. +* If a concurrency token or version check is provided, the server will compare it against the current version of the resource. If they do not match (meaning the resource was modified since the client last saw it), the server **MUST** reject the update with a conflict error. This prevents unintentional overwrites of others’ changes. Clients are then expected to re-fetch the resource or otherwise reconcile the differences before retrying. Servers MUST support optional concurrency controls, failing with Precondition Failed if the resource has changed since the client's last read. +* The update operation requires proper authorization. If the client is not allowed to modify the resource, the server will deny the operation (typically without revealing whether the resource exists if the client is not supposed to know about it). +* If the resource to be updated does not exist, the server will treat this as an error (usually a “Not Found”). The update operation is only applicable to existing resources. (Some protocols like HTTP PUT combine create/update semantics, but in the logical model here, creating a new resource should be done via the create operation; update assumes a pre-existing target.) +* On success, the resource’s content is changed to the new content (fully replaced or patched). Any relevant metadata (sizeInBytes, modified) is updated accordingly. Updates MUST propagate to associated metadata atomically, preserving server-managed fields. The server ensures the operation is atomic and consistent: other operations should not see a half-updated state. +* The server **MAY** enforce additional constraints on updates, such as size limits, quota checks, or restrictions on allowed media types. If any such constraint is violated, the server will reject the operation with an appropriate error. + +**Possible Responses:** +* **Success:** The resource was successfully updated. The response includes the updated resource’s identifier and possibly a minimal representation or metadata. +* **Not Found:** The specified resource does not exist, so no update can be performed. (If the client is not authorized, this could also be the response to avoid giving away existence; see “Not Permitted.”) +* **Not Permitted:** The client is not authorized to modify this resource. The server refuses the update. (In HTTP this might be 403 Forbidden, or 404 Not Found if we don’t want to reveal that the resource exists to an unauthenticated requester.) +* **Conflict:** The update could not be applied because of a concurrency conflict or an invalid state. For example, if an “edit token” or version check was provided and did not match the current resource version, the server will respond with a conflict indication (the client’s view of the resource is out-of-date). Another example is if a patch document cannot be applied, the server treats it as a conflict or bad request. +* **Precondition Failed:** A concurrency mismatch occurred. The server rejects the update without changes. +* **Bad Request:** The update request was malformed or unacceptable. For instance, the patch syntax could be invalid, or the new content might not conform to expected format constraints, or violate quotas. The server did not attempt any update. +* **Unknown Error:** Some internal error happened during the update attempt (such as a database failure, etc.). The resource remains unchanged (if the server could not complete the operation), and an error is returned indicating a server-side failure. \ No newline at end of file diff --git a/lws10-core/Rest-Binding/metadata.md b/lws10-core/Rest-Binding/metadata.md new file mode 100644 index 0000000..d88da2c --- /dev/null +++ b/lws10-core/Rest-Binding/metadata.md @@ -0,0 +1,71 @@ +### Metadata +This section defines the model for associating metadata with LWS resources. The LWS metadata system is based on the principles of Web Linking [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html), which allows servers to describe the relationships between resources using typed links. Metadata enhances discoverability, supports self-descriptive APIs, and aligns with resource operations, container hierarchies, and REST bindings as outlined in sections 7 and 8. + +**Metadata Model** +All metadata in LWS is expressed as a set of typed links originating from a resource (the link context). Each link consists of: +- A link target: A URI identifying the related resource. +- 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 (e.g., mediaType, title, modified). + +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. + +**The Linkset Resource** +For resources with extensive metadata, an LWS server MUST expose the complete set of links in a separate linkset resource, as defined in [RFC 9264](https://www.rfc-editor.org/rfc/rfc9264.html). A resource's linkset is discovered via a Link header with the relation type linkset. A server MUST have one and only one linkset. The linkset resource itself contains a serialized representation of all links. + +[RFC 9264](https://www.rfc-editor.org/rfc/rfc9264.html) does not require any specific format for the linkset document. It only suggests and defines two formats. For LWS, servers MUST support application/linkset+json linkset serialization. A LWS server MAY implement application/linkset or additional RDF formats such as Turtle via content negotiation. Servers SHOULD use JSON-LD with a normative context for linkset representations to facilitate RDF interpretation and extensibility, reusing existing vocabularies. + +The 'linkset' link MUST point to a server-managed resource with a fixed media type (application/linkset+json or application/linkset), and servers MUST ensure its integrity upon operations like deletions or ACL changes on related resources. For example, if a client attempts to redirect 'linkset' to an arbitrary resource, the server MUST reject this to avoid risks such as dangling links or authorization discrepancies. Clients SHOULD NOT attempt such redirections, as this specification does not define their behavior, and support is OPTIONAL at the server's discretion. Updates to the linkset MUST be atomic with associated resource operations to maintain consistency. + +**Discovering Metadata** +Clients discover a resource's metadata primarily through Link headers returned in response to GET or HEAD requests on the resource's URI. To enhance discoverability, servers MUST support a Link header with rel="storageDescription" on relevant responses, such as 401 Unauthorized, and include a WWW-Authenticate header with parameters directing to the storage metadata. This aligns with self-descriptive principles and avoids hardcoded URI locations. + +To manage response verbosity, servers SHOULD support the Prefer header [RFC 7240](https://www.rfc-editor.org/rfc/rfc7240.html). A client can request the inclusion of descriptive metadata links by sending a Prefer header with the include preference. For LWS, the following preference tokens are defined: +- https://www.w3.org/ns/lws#linkfilter - limits properties that are returned as a link header only. If no linkfilter is specified, all properties are returned as link headers. +- https://www.w3.org/ns/lws#linksetfilter - limits properties that are returned in the linkset only. If no linksetfilter is specified, all properties are returned in the linkset document. + +To provide finer-grained control over the response payload, the include preference MAY be parameterized with a "rels" parameter and/or an "attrs" parameter. The "rels" parameter specifies a space-separated, case-sensitive string of link relation types to filter which links are included in the response. The "attrs" parameter specifies a space-separated, case-sensitive string of link attribute names to control which attributes of the selected links are returned. If the "rels" parameter is provided, only links matching the specified relation types are included; if omitted, all applicable links are considered. If the "attrs" parameter is provided, only the specified attributes are returned for the selected links; if omitted, all available attributes are included. Servers MUST always include the target URI (href) for each link, regardless of the parameters specified. If neither parameter is provided, all applicable links and their attributes are returned. + +A client MAY supply multiple include preferences in a single Prefer header by separating them with a space. This allows for the retrieval of metadata from multiple vocabularies in a single request. Any parameters, such as "prop", are scoped locally to the specific include preference they are attached to. For containers, responses MUST support pagination mechanics and include metadata fields such as resource IDs (MUST), types (array of system and user-defined), sizeInBytes (SHOULD for representations in DataResources), and timestamps (SHOULD), filtered by ACL visibility to ensure privacy. + +**Metadata Types** +LWS defines three classes of metadata - system, core, and user. The terms listed in this section are defined at relevant vocabularies. + +System-Managed - System-managed metadata is maintained by a LWS server and is read-only. A server MUST NOT allow users to manipulate this data. Mandatory fields include acl, linkset, partOf, type, and mediaType. Optional fields include sizeInBytes, modified, and publisher. +| item | defined by | +|------------|------------| +| acl | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| linkset | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| type | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| mediaType | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| https://www.w3.org/ns/lws#sizeInBytes | [lws](https://www.w3.org/ns/lws#) | +| http://purl.org/dc/terms/modified | [dcterms](http://purl.org/dc/terms/) | +| http://purl.org/dc/terms/publisher | [dcterms](http://purl.org/dc/terms/) | + +Clients SHOULD NOT attempt to modify, add, or delete server-managed links, such as those with relation types 'acl' or 'linkset', as these are read-only and maintained exclusively by the server. Attempts to do so may result in errors or undefined behavior. Servers MAY choose to support such operations in limited scenarios, but this specification does not define their semantics or outcomes; clients MUST NOT rely on such support for interoperability. + +To mitigate risks associated with server-managed links, clients MUST handle cases where links become inaccessible or inconsistent gracefully, such as by falling back to default behaviors or retrying discovery. For example, altering the 'linkset' link could lead to dangling references, media-type mismatches, or access control discrepancies. Similarly, modifications to the 'acl' link could compromise security if not strictly prohibited. + +Core Metadata - Core metadata MAY include optional fields such as label, schema, and storage. +| item | defined by | +|------------|------------| +| partOf | [lws](https://www.w3.org/ns/lws#) | +| contains | [lws](https://www.w3.org/ns/lws#) | +| type | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| http://purl.org/dc/elements/1.1/title | [dcelements](http://purl.org/dc/elements/1.1/) | +| http://purl.org/dc/elements/1.1/creator | [dcelements](http://purl.org/dc/elements/1.1/) | +| label | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| schema | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | +| storage | [Link Relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml) | + +**Modifiability Considerations** +Core metadata, such as 'partOf', 'contains', 'type', 'title', and 'creator', MAY be modified by clients via PUT or PATCH operations on the associated linkset resource. However, servers MAY impose restrictions on certain core links to maintain system integrity. For instance, modifying the 'partOf' or 'contains' link to 'move' a resource is OPTIONAL for server implementations, as it may involve complex operations like updating slash-based semantics or decoupling containment meanings. Clients SHOULD NOT assume universal support for such changes and MUST handle server rejections. Servers that do not support modifications to 'partOf' MUST document this in their conformance statements. Metadata lifecycles are tied to the described resource, with automatic deletion upon resource removal. + +User-Defined Metadata +Users MAY create or add additional metadata using existing or custom vocabularies, including user-defined types and indexes. + +**Managing Metadata** +Metadata is managed by modifying a resource's associated linkset resource using PUT or PATCH operations. Servers MUST support concurrency controls for updates. + +Replacing Metadata (PUT): A client can replace the entire set of metadata links by sending a PUT request to the linkset URI with a complete linkset document in the body. + +Partially Updating Metadata (PATCH): A client can add, remove, or modify individual links by sending a PATCH request to the linkset URI. LWS servers SHOULD support a standard patch format, such as JSON Merge Patch [RFC 7396](https://www.rfc-editor.org/rfc/rfc7396.html) (application/merge-patch+json). Servers MAY support SPARQL Update for RDF-based partial updates to enhance flexibility for complex modifications. \ No newline at end of file diff --git a/lws10-core/Rest-Binding/rest-create-resource.md b/lws10-core/Rest-Binding/rest-create-resource.md new file mode 100644 index 0000000..37b5fb4 --- /dev/null +++ b/lws10-core/Rest-Binding/rest-create-resource.md @@ -0,0 +1,123 @@ +### Create Resource (HTTP POST) +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, but servers MUST have authority over naming to ensure uniqueness and compliance with policies. PUT is reserved for updates to existing resources and MUST NOT be used for creation in this version of the specification, to prioritize server-managed identifiers and simplify client-server interactions. 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 - RFC 8288](https://datatracker.ietf.org/doc/html/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 201 Created 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. +**POST (to a container URI)** – *Create with server-assigned name:* +Use POST to add a new resource inside an existing container, letting the server assign or modify the final name (optionally suggested via the Slug header). Send the request to the container's URI with a Content-Type header matching the uploaded data (omit for empty resources like containers) and the new content in the body. The server MAY honor the Slug if it does not conflict with naming rules or existing resources. +**Example (POST to create a new data resource):** +``` +POST /alice/notes/ HTTP/1.1 +Host: example.com +Authorization: Bearer +Content-Type: text/plain +Content-Length: 47 +Slug: shoppinglist.txt +milk +eggs +bread +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 resource, generate associated metadata, and link it via the linkset. +**Example (Response to POST):** +``` +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="type" +Preference-Applied: ... +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 like ETag for concurrency control and Content-Type matching the created resource; Content-Length: 0 indicates no body. Servers MUST support concurrency via ETags in subsequent operations. +If the target container `/alice/notes/` does not exist, the server MUST return an error (HTTP 404 Not Found) because the location to create the resource is invalid. If the client is not authorized to write to that container, the server returns 403 Forbidden. If the request violates any server constraints, the server SHOULD return 400 Bad Request or 507 Insufficient Storage, with a description of the issue in the body if appropriate. +**Creating Containers:** To create a new container via the REST API, a client uses POST to an existing parent container, typically with no body or a Content-Type indicating an empty resource. The server MUST support creation of empty containers. For example: +``` +POST /alice/ HTTP/1.1 +Host: example.com +Authorization: Bearer +Slug: notes +``` +This would create 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 request. +* Metadata updates are atomic; servers MUST ensure the linkset resource is created and populated with mandatory server-managed fields before returning success. +* Clients MAY request content negotiation via Accept headers, but for creation responses, servers SHOULD default to minimal or no body unless specified. +* For discoverability, servers SHOULD include WWW-Authenticate headers on 401 responses with parameters like storageDescription to guide clients without hardcoded URIs. +**Managing and Retrieving Metadata (Related to Creation):** +While metadata is primarily retrieved via read operations (Section 9.3), it is generated during creation. Clients can immediately retrieve it post-creation using GET or HEAD on the new resource URI. As described in Section 9.1, clients can use the Prefer header to request inclusion of specific metadata links (via relation types) and attributes. +Example (GET a newly created resource with specific metadata relations): +The client requests only the linkset, acl, and partOf relations, with all available attributes. +``` +GET /alice/notes/shoppinglist.txt HTTP/1.1 +Host: example.com +Authorization: Bearer +Prefer: include="http://www.w3.org/ns/lws#linkfilter"; rels="linkset acl partOf" +``` +Expected response (showing only the specified relations, with all available attributes such as "href", "rel", "type", and mandatory fields): +``` +HTTP/1.1 200 OK +ETag: "abc123456" +Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="acl" +Link: ; rel="partOf" +Preference-Applied: include="http://www.w3.org/ns/lws#linkfilter"; rels="linkset acl partOf" +... (response body) ... +``` +Example (GET a resource with specific attributes across all links): +The client requests all links but only the "rel" and "type" attributes for them. +``` +GET /alice/notes/shoppinglist.txt HTTP/1.1 +Host: example.com +Authorization: Bearer +Prefer: include="http://www.w3.org/ns/lws#linkfilter"; attrs="rel type" +``` +Expected response (all links included, but only with the specified "rel" and "type" attributes, plus the mandatory "href"): +``` +HTTP/1.1 200 OK +ETag: "abc123456" +Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="acl" +Link: ; rel="partOf" +Link: ; rel="type" +Preference-Applied: include="http://www.w3.org/ns/lws#linkfilter"; attrs="rel type" +... (response body) ... +``` +Example (GET a linkset resource with specific attributes): +If the client then requests the linkset resource itself, it can apply a similar preference (using the linksetfilter directive) to shape the JSON response, for instance by specifying attributes. Servers SHOULD support JSON-LD framing for linkset responses with a normative context. +``` +GET /alice/notes/shoppinglist.txt.meta HTTP/1.1 +Host: example.com +Authorization: Bearer +Accept: application/linkset+json +Prefer: include="http://www.w3.org/ns/lws#linksetfilter"; attrs="rel type" +``` +Expected response (all links included, but only with the specified "rel" and "type" attributes, plus the mandatory "href"): +``` +HTTP/1.1 200 OK +Content-Type: application/linkset+json +ETag: "meta-etag-111" +Preference-Applied: include="http://www.w3.org/ns/lws#linksetfilter"; attrs="rel type" +{ + "linkset": [ + { + "href": "/alice/notes/shoppinglist.txt.acl", + "rel": "acl" + }, + { + "href": "/alice/notes/", + "rel": "partOf", + "type": "application/ld+json" + }, + { + "href": "https://www.w3.org/ns/lws#DataResource", + "rel": "type" + } + ] +} +``` +In this response, the link for rel="acl" does not include a type attribute because it was not present on the server for that link, while the other links include type because it was requested and available. This allows clients to reduce bandwidth and processing load by fetching only the metadata relations and attributes they require. Clients MAY combine "rels" and "attrs" in a single Prefer header for more targeted filtering, such as rels="acl partOf" attrs="rel type", in which case the server applies the relation filter first and then restricts attributes on the resulting links. For privacy, unauthorized metadata fields MUST not disclose resource existence. \ No newline at end of file diff --git a/lws10-core/Rest-Binding/rest-delete-resource.md b/lws10-core/Rest-Binding/rest-delete-resource.md new file mode 100644 index 0000000..415f6aa --- /dev/null +++ b/lws10-core/Rest-Binding/rest-delete-resource.md @@ -0,0 +1,34 @@ +### Delete Resource (HTTP DELETE) +The [delete resource](https://w3c.github.io/lws-protocol/spec/#dfn-deletion) operation removes an existing resource (or, in some cases, an entire container) from the storage. This operation is akin to deleting a file or folder in a file system. Once completed, the target resource is no longer available for read or update, and its identifier becomes invalid (attempts to access it later should report it as not found, unless it is recreated). Servers MUST ensure that deletions are atomic, including the removal of associated metadata resources and updates to containing container memberships. Metadata lifecycles are tied to the primary resource; deleting a resource MUST automatically delete its associated linkset and any server-managed metadata, without allowing independent deletion of metadata. +**DELETE (non-container resource)** – If the requested URI points to a regular resource (not a container), the server will delete that resource and any associated metadata, such as its linkset. On success, the server responds with `204 No Content` (the standard success code for **DELETE** indicating the resource is gone and there’s no further data to return). After this, any **GET** or **HEAD** to that URI should return 404 Not Found (or optionally 410 Gone to indicate permanent removal) unless a new resource is later created at the same URI. The server MUST also delete any auxiliary files or metadata associated with that resource and update the containing container's membership atomically. For example, some servers store access control rules or metadata in sidecar files (like `resource.acl`); those MUST be cleaned up. If the resource did not exist to begin with, the server returns `404 Not Found` for the **DELETE** (because you’re asking to delete something that isn’t there). If the client is not authorized to delete the resource, the server returns `403 Forbidden` (if the client’s identity is known but they lack permission) or possibly `401 Unauthorized` (if no valid auth was provided, prompting for credentials). In some cases, as discussed, a server might also return 404 for unauthorized requests to avoid hinting that the resource exists. Servers SHOULD support concurrency checks via If-Match with ETags for deletes; mismatches yield 412 Precondition Failed. +**Example (DELETE a non-container 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 updates the containing container `/alice/notes/` atomically: +``` +HTTP/1.1 204 No Content +``` +**DELETE (container resource)** – Deleting a container is more restricted. By default, an LWS server requires that a container be empty (no child resources) in order to delete it; non-recursive deletion is the default behavior. This means if a client issues a DELETE on a container that still has members, the server MUST respond with `409 Conflict`. The response MAY include a message indicating the reason. This behavior protects against accidental deletion of large sets of data with a simple request. The client should then either delete the contained resources individually or (if it really intends to remove everything) use an explicit recursive delete mechanism if the server supports one. Upon deletion, the server MUST remove the container's metadata and update any containing container's membership atomically. +**Example (DELETE a non-empty container without recursion):** +``` +DELETE /alice/notes/ HTTP/1.1 +Authorization: Bearer +``` +Assume `/alice/notes/` contains resources (like shoppinglist.txt and others). The server will refuse to delete since it’s not empty: +``` +HTTP/1.1 409 Conflict +Content-Type: text/plain +Cannot delete container /alice/notes/ - container is not empty. +``` +Here a 409 Conflict is returned, possibly with a simple text message. The client then knows it must delete the contents first or try a recursive delete. +LWS implementations MAY support a way to request recursive deletion of a container and all its descendants in one go, using a request header `Depth: infinity` on the **DELETE** request (as in WebDAV [[RFC 4918](https://datatracker.ietf.org/doc/html/rfc4918)]). In LWS, this is OPTIONAL, and the default is non-recursive unless specified. Servers that support recursion MUST verify permissions for all affected resources and SHOULD abort on failures, potentially returning 403 Forbidden or 500 Internal Server Error with details. Advanced implementations MAY return a 207 Multi-Status (WebDAV style) listing what succeeded and failed, but LWS does not require that level of detail in this core spec. If recursion is not supported, servers MUST reject such requests with 501 Not Implemented. +**Example (DELETE a container with recursion, if supported):** +``` +DELETE /alice/notes/ HTTP/1.1 +Authorization: Bearer +Depth: infinity +``` +If the server honors `Depth: infinity` to mean recursive deletion (and the user has rights to everything under `/alice/notes/`), it would proceed to delete all items in `notes/` and then the container itself, including all associated metadata. A success would be `204 No Content` indicating everything is gone. If, say, one file in `notes/` was not deletable (maybe a permission issue on that file), the server might abort and return an error (perhaps 403 or 500 with an explanation). \ No newline at end of file diff --git a/lws10-core/Rest-Binding/rest-read-resource.md b/lws10-core/Rest-Binding/rest-read-resource.md new file mode 100644 index 0000000..b1a2a31 --- /dev/null +++ b/lws10-core/Rest-Binding/rest-read-resource.md @@ -0,0 +1,90 @@ +### Read Resource (HTTP GET / HEAD) +The [read resource](https://w3c.github.io/lws-protocol/spec/#dfn-retrieval) operation requests a [resource representation](https://w3c.github.io/lws-protocol/spec/#dfn-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 9.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. For privacy, unauthorized requests MUST return 404 Not Found without disclosing resource existence, regardless of whether the resource exists. +**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 SHOULD support content negotiation via Accept headers, returning the original format if no alternatives are available or 406 Not Acceptable if the requested format cannot be produced. Servers MUST support range requests per [RFC 7233](https://datatracker.ietf.org/doc/html/rfc7233) for partial retrieval. Responses MUST include an ETag header for concurrency control and caching. +**Example (GET a file):** +``` +GET /alice/notes/shoppinglist.txt HTTP/1.1 +Authorization: Bearer +Accept: text/plain +``` +This requests the content of `/alice/notes/shoppinglist.txt`, indicating that the client wants it in text form. Assuming the resource exists, is text, and the client has access: +``` +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="partOf" +Link: ; rel="acl" +Link: ; rel="type" +milk +cheese +bread +guacamole +soda +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. +**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). Listings MUST be ACL-aware, filtering based on client permissions, but servers SHOULD grant full visibility of readable members if the container is accessible, using sub-containers for finer privacy controls. +By default, in the absence of a specific format requested, the server SHOULD return an HTML page that lists the names (with links) of the resources in the container for human-readable access. For programmatic access, servers SHOULD support content negotiation via Accept headers. For example, Accept: application/ld+json MUST yield a JSON-LD representation using a normative context and optional framing, with a custom media type like application/lws+json; profile="https://www.w3.org/ns/lws/v1". Servers MAY support Accept: text/turtle for RDF Turtle representations. If the server cannot provide the listing in a requested format, it MUST return 406 Not Acceptable. JSON Schema MAY be provided informatively for non-RDF clients. +**Example (GET a container with JSON-LD):** +``` +GET /alice/notes/ HTTP/1.1 +Authorization: Bearer +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" +ETag: "container-etag-789" +Link: ; rel="linkset"; type="application/linkset+json" +Link: ; rel="partOf" +Link: ; rel="acl" +Link: ; rel="type" +{ + "@context": "https://www.w3.org/ns/lws/context/v1.jsonld", + "@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" + } + ] + } +} +``` +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 relevant metadata in the response headers, such as ETag (representing the listing version, which changes on membership modifications) and rel="type" indicating it is a container. Servers SHOULD use Prefer headers for finer control over included metadata, as defined in Section 9.1. +**HEAD (any resource or container)** – *Headers/metadata only:* +The LWS server MUST support [HEAD](https://datatracker.ietf.org/doc/html/rfc9110#name-head) 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. +**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. +**Discoverability and Authorization:** For enhanced discoverability, servers SHOULD include WWW-Authenticate headers on 401 Unauthorized responses with parameters to guide clients without hardcoded URIs. Metadata links SHOULD be included where applicable. Content negotiation SHOULD extend to RDF formats like Turtle for metadata-heavy responses. \ No newline at end of file diff --git a/lws10-core/Rest-Binding/rest-table.md b/lws10-core/Rest-Binding/rest-table.md new file mode 100644 index 0000000..71712b2 --- /dev/null +++ b/lws10-core/Rest-Binding/rest-table.md @@ -0,0 +1,24 @@ +### Summary of HTTP Status Mappings + +This table maps generic LWS [responses](https://w3c.github.io/lws-protocol/spec/#dfn-responses) (from Section 7) 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](https://w3c.github.io/lws-protocol/spec/#dfn-success) Success (read or update, returning data) | 200 OK | [Resource representation](https://w3c.github.io/lws-protocol/spec/#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). | +| Partial Success (paginated or ranged read) | 206 Partial Content | Partial resource representation, with headers like Content-Range or Link rel="next" for pagination. Listings include filtered metadata per ACL visibility. | +| [Created](https://w3c.github.io/lws-protocol/spec/#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. Could be in plain text or a structured format (JSON error object), depending on server. | +| [Unknown requester](https://w3c.github.io/lws-protocol/spec/#dfn-unknown-requester) | 401 Unauthorized | Typically no body or an error message. The response MUST include a `WWW-Authenticate` header with parameters for discoverability and authentication negotiation (per HTTP spec). This indicates the client needs to provide credentials. | +| [Not Permitted](https://w3c.github.io/lws-protocol/spec/#dfn-not-permitted) (forbidden) | 403 Forbidden | An error message or none. Indicates the client’s credentials were accepted but they don’t have rights to perform the operation. | +| Not found | 404 Not Found | Possibly an error message. Indicates the resource (or target URI) does not exist *or* is not accessible. (Servers MUST use 404 in place of 403 for unauthorized reads to avoid revealing the existence of a resource, aligning with privacy considerations.) | +| Not acceptable | 406 Not Acceptable | Typically a short message listing supported formats or indicating that the requested representation cannot be provided. The client may use this information to retry with a different `Accept`. | +| Conflict | 409 Conflict | Explanation of the conflict. The body could include specifics or be empty with just the status reason. | +| Precondition Failed (concurrency) | 412 Precondition Failed | If an `If-Match` or similar header doesn’t match, this status is returned with maybe a brief message. | +| Unsupported Media Type | 415 Unsupported Media Type | If the client sent a format that the server cannot handle (for create or update). The body might list acceptable media types. | +| Insufficient Storage (quota exceeded) | 507 Insufficient Storage | Error details indicating quota or storage constraints violated. Could include current usage information in the body. | +| Internal Server Error [Unknown error](https://w3c.github.io/lws-protocol/spec/#dfn-unknown-error) | 500 Internal Server Error | A generic error message. In a debug or dev mode, the server might include a stack trace or internal details in the body, but in production it should be a generic statement. | + +This mapping table is intended to cover the typical cases, ensuring atomicity with metadata operations and support for discoverability. Note that some status codes above (206, 412, 415, 507) are standard HTTP but were not explicitly enumerated in Section 7’s generic list; they are used here to handle HTTP-specific scenarios (like pagination, conditional requests, media type handling, and quotas). LWS servers should use the most appropriate HTTP status code for each situation to enable clients to react correctly. + +By adhering to these method bindings and status codes, LWS clients and servers can interoperate using HTTP in a predictable, RESTful way. This allows leveraging existing HTTP libraries, tools, and knowledge for building LWS-based systems. \ No newline at end of file diff --git a/lws10-core/Rest-Binding/rest-update-resource.md b/lws10-core/Rest-Binding/rest-update-resource.md new file mode 100644 index 0000000..8236392 --- /dev/null +++ b/lws10-core/Rest-Binding/rest-update-resource.md @@ -0,0 +1,84 @@ +### Update Resource (HTTP PUT / PATCH) +The [update resource](https://w3c.github.io/lws-protocol/spec/#dfn-update-resource) modifies the contents of an existing [served resource](https://w3c.github.io/lws-protocol/spec/#dfn-served-resource) by a **PUT** request (to replace the entire resource) or a **PATCH** request (to apply a partial modification). The client must have write access to the resource’s URL to perform these operations. +Note: This section describes updating a resource's primary content. To update its metadata, see Section 9.3.2. +LWS servers MUST handle PUT and PATCH requests on resource URIs as modifications to the resource content only, with no default impact on the associated linkset. To optionally update both content and metadata in a single atomic operation, clients MAY include Link headers in the PUT/PATCH request to the resource URI and specify the preference 'Prefer: set-linkset' (as defined in RFC 7240). In this case, the server MUST interpret the provided Link headers as a replacement (for PUT) or partial update (for PATCH) to the linkset, in addition to applying the content changes. This behavior is OPTIONAL for servers but, if supported, MUST be invoked explicitly via the Prefer header to prevent unintentional metadata overwrites. Servers that do not support combined updates MUST ignore the preference or respond with 501 Not Implemented. +**PUT (replace full resource)** – Send PUT to the resource URI with new full content in the body and matching Content-Type (generally consistent with existing type). PUT is idempotent for existing resources. For safety, include If-Match with current ETag (per Section 7.3 concurrency); mismatch yields 412 Precondition Failed or 409 Conflict. Without checks, updates are unconditional but risk overwriting concurrent changes. If a server supports `Etags` for a resource, it **MUST** reject unconditional PUT requests that lack an If-Match header with a 428 Precondition Required response. +**Example (PUT to update a resource):** +``` +PUT /alice/personalinfo.json HTTP/1.1 +Authorization: Bearer +Content-Type: application/json +If-Match: "abc123456" +{ +"name": "Alice", +"age": 30, +"city": "New London", +"state": "Connecticut" +} +``` +In this example, the client is updating an existing JSON resource at /alice/personalinfo.json. It includes an If-Match header with the ETag "abc123456" that it presumably got from an earlier GET or HEAD on this resource. The server will compare that to the current ETag; if they match, it proceeds to replace the content with the JSON provided. If they don’t match, the server rejects the update (because the resource was changed by someone else in the meantime). +Successful response: If the update succeeds, the server can respond with 200 OK and possibly include the updated representation or some confirmation (like the new content or a part of it). Alternatively, the server may respond with 204 No Content to indicate success with no body (especially common if no further info needs to be conveyed). In either case, the server **SHOULD** include a new ETag to signify the new version, and maybe a Content-Type if a body is returned. For example: +``` +HTTP/1.1 204 No Content +ETag: "def789012" +``` +This tells the client the update went through and provides the new `ETag`. If the server chose to return the updated content, it might use `200 OK` and include the JSON in the body, along with headers. +* **Error responses:** If the `If-Match` did not match (concurrent modification), the server could return `412 Precondition Failed` (meaning the precondition header failed) or `409 Conflict` – our earlier abstract description used Conflict for concurrency issues, and 409 is a natural mapping for that scenario. If the resource did not exist, a PUT meant as an update will result in `404 Not Found` (unless the intent was to create, but typically clients use PUT for create only when they are sure of what they’re doing, or they use it as upsert without If-Match). If the client is not authorized, `403 Forbidden` (or 401 Unauthorized if no valid credentials were provided). If the request payload is not valid, `400 Bad Request`. +**PATCH (partial update)** – The HTTP PATCH method [[RFC 5789](https://www.rfc-editor.org/rfc/rfc5789.html)] 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 [[RFC 7386](https://datatracker.ietf.org/doc/html/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". +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 [[RFC 7232](https://datatracker.ietf.org/doc/html/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. +Client Responsibilities: +When modifying a linkset resource, a client MUST include an If-Match header containing the most recent Etag it received for that resource. +Processing Rules: +If the If-Match header value does not match the linkset's current Etag, the server MUST reject the request with a 412 Precondition Failed status code. +If the If-Match header is missing from a PUT or PATCH request to a linkset URI, the server MUST reject the request with a 428 Precondition Required status code [[RFC 6585](https://datatracker.ietf.org/doc/html/rfc6585#section-3)]. +Example (PUT to replace a linkset): +A client first fetches the linkset and receives its ETag. +``` +GET /alice/personalinfo.json.meta HTTP/1.1 +Authorization: Bearer +Accept: application/linkset+json +HTTP/1.1 200 OK +Content-Type: application/linkset+json +ETag: "meta-v1" +{ + "linkset": [ + { + "anchor": "/alice/personalinfo.json", + "describedby": [ { "href": "/schemas/personal-info.json" } ] + } + ] +} +``` +The client now wants to add a license. It constructs a new, complete linkset document and sends a PUT request with the If-Match header. +``` +PUT /alice/personalinfo.json.meta HTTP/1.1 +Authorization: Bearer +Content-Type: application/linkset+json +If-Match: "meta-v1" +{ + "linkset": [ + { + "anchor": "/alice/personalinfo.json", + "describedby": [ { "href": "/schemas/personal-info.json" } ], + "license": [ { "href": "https://creativecommons.org/licenses/by/4.0/" } ] + } + ] +} +``` +If successful, the server responds with success and the new ETag. +``` +HTTP/1.1 204 No Content +ETag: "meta-v2" +``` +**Summary of Update Rules** +If you want to change only the content of a resource → PUT/PATCH the resource itself. +If you want to change only the links (metadata) of a resource → PUT/PATCH the resource’s associated linkset resource. +If you want to change both content and links → PUT/PATCH the resource itself, including the appropriate Link headers AND 'Prefer: set-linkset'. Setting both is off by default. \ No newline at end of file diff --git a/lws10-core/Rest-Binding/restbinding.md b/lws10-core/Rest-Binding/restbinding.md new file mode 100644 index 0000000..ff152dc --- /dev/null +++ b/lws10-core/Rest-Binding/restbinding.md @@ -0,0 +1,5 @@ +This section defines how the generic operations and responses from Section 7 are realized over HTTP using RESTful conventions. It specifies the HTTP methods, request formats, and status codes that an [LWS REST Servers](https://w3c.github.io/lws-protocol/spec/#dfn-lws-rest-server) and [LWS REST Clients](https://w3c.github.io/lws-protocol/spec/#dfn-lws-rest-client) should use for interoperability. In other words, it’s a concrete mapping of the abstract operations to HTTP requests and responses. The following assumes an LWS server exposing resources via HTTP URIs, and an LWS client using HTTP methods (GET, POST, PUT, PATCH, DELETE, etc.) to invoke the operations. + +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 (success or various errors), following the semantics outlined in Section 7, 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 [[RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231)] for HTTP semantics, [[RFC 7233](https://datatracker.ietf.org/doc/html/rfc7233)] for range requests, [[RFC 5789](https://www.rfc-editor.org/rfc/rfc5789.html)] for PATCH, [[RFC 8288](https://www.rfc-editor.org/rfc/rfc8288.html)] for Web Linking, and [[RFC 9264](https://www.rfc-editor.org/rfc/rfc9264.html)] 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, as defined in Section 9.1, is required across operations, ensuring atomicity and use of Link Sets for server-managed and user-managed properties. + +**Note:** 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 diff --git a/lws10-core/index.html b/lws10-core/index.html index e35b7f5..9a946b0 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -252,76 +252,43 @@

Discovery

Operations

+

create resource

-

- Create resource -

- -

- In addition to the core responses, a create operation may produce any of: -

-
    -
  • created - .
  • -
  • more? worthy of a list?
  • -
+

read resource

-

- The read resource operation requests a resource representation. - Draw from Solid Protocol - Reading Resources. -

+

update resource

-

- The update resource modifies the contents of a served resource. - Draw from Solid Protocol - Reading Resources. -

+

delete resource

-

- Delete resource -

+

Logical Resource Organization

-

- Define the data model for logical resource organization within LWS, including how containers are structured, hierarchical relationships between resources, container semantics, containment rules, and the mechanisms for organizing and navigating collections of related resources. This should cover container creation, membership management, and the relationship between containers and the resources they contain. -

+

REST Binding

-

- This strawman mapping of the operations and responses defined above allows LWS REST Servers and LWS REST Clients to communicate over HTTP using REST conventions. -

- -

- The following table maps LWS response to an HTTP status code and payload: -

- - - - - - - - - - - - - -
LWS responseHTTP status codeHTTP payload
success200resource representation
not permitted...
unknown requester...
unknown error...
created201
+
+
+
+
+
+
+
diff --git a/lws10-core/logicalresourceorganization.md b/lws10-core/logicalresourceorganization.md new file mode 100644 index 0000000..2511553 --- /dev/null +++ b/lws10-core/logicalresourceorganization.md @@ -0,0 +1,24 @@ +### 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. + +### 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'. + +### Container +A container represents a specialized resource type capable of encompassing other resources as members. Containers function as organizational constructs, facilitating the grouping of resources in a manner akin to collections or directories. A container maintains references to its member resources, which may comprise both non-container resources and additional container resources, thereby enabling hierarchical formations. Typically, a container holds minimal intrinsic content beyond metadata or enumerations of its members; its principal role is to aggregate and structure subordinate resources. The storage system's root is designated as a container, serving as the apex organizational unit devoid of a superior parent. Containers MUST support pagination for membership listings using 'ContainerPage' types, with properties such as 'first', 'next', 'prev', and 'last'. Representations MUST use JSON-LD with a specific frame and normative context, optionally advertising content negotiation via 'Vary: Accept' headers. Storage MAY function as a root container, enabling direct writes. + +### 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. + +### 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 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. + +### 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 diff --git a/lws10-core/operations.md b/lws10-core/operations.md new file mode 100644 index 0000000..762cfff --- /dev/null +++ b/lws10-core/operations.md @@ -0,0 +1,3 @@ +This section defines the four core operations that a Linked Web Storage (LWS) server **MUST** support. These operations manipulate resources and containers in a transport-independent manner, focusing on semantics rather than implementation details. Each operation specifies inputs, expected behaviors, and possible responses (outcomes). Responses include success indicators, resource representations (where applicable), and error conditions. Implementations **MUST** handle these operations atomically and consistently, meaning each operation either succeeds completely or fails without partial side effects. In case of errors, responses **SHOULD** provide enough detail for agents to understand the issue without leaking sensitive information. All normative requirements are to be interpreted as in \[[RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119)\]. + +All operations MUST interact with associated metadata resources as defined in Section 9.1. Servers MUST distinguish between server-managed metadata and user-managed metadata, ensuring that operations do not alter server-managed metadata without explicit authorization. Metadata updates MUST be atomic with the operation and use Link Sets (RFC 9264) for description. Servers MUST support discoverability through self-descriptive mechanisms, avoiding hardcoded URIs. For read operations on containers, servers MUST support pagination to handle large memberships. Servers MUST support optional concurrency controls, failing with Conflict if the resource has changed since the client's last read. Partial updates (PATCH) are optional; if supported, they MUST use standards like JSON Patch or SPARQL Update for RDF resources. PUT for creation is not supported in this version to ensure server authority over naming; use POST for server-assigned identifiers. \ No newline at end of file diff --git a/w3c.json b/w3c.json index 812a53f..f8c6a93 100644 --- a/w3c.json +++ b/w3c.json @@ -1,5 +1,5 @@ - { - "group": [159634] -, "contacts": ["pchampin"] -, "repo-type": "rec-track" -} + { + "group": [159634] +, "contacts": ["pchampin"] +, "repo-type": "rec-track" +}