LWS Protocol

W3C Editor's Draft

More details about this document
This version:
https://w3c.github.io/lws-protocol/
Latest published version:
https://www.w3.org/TR/@@/
Latest editor's draft:
https://w3c.github.io/lws-protocol/
History:
Commit history
Editors:
Jesse Wright
Erich Bremer
Former editors:
Sarven Capadisli
Justin Bingham
Dmitri Zagidulin
Ruben Verborgh
Tim Berners-Lee
Kjetil Kjernsmo
Feedback:
GitHub w3c/lws-protocol (pull requests, new issue, open issues)

Abstract

[@@ from charter]

The Linked Web Storage Protocol specification aims to provide applications with secure and permissioned access to externally stored data in an interoperable way.

The Linked Web Storage Protocol does/does not include protocol details for integration with identity layers and mechanisms; access management and data integrity; notifications about resource changes; and authorization mechanisms.

Status of This Document

This is a preview

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://w3c.github.io/lws-protocol/ for the Editor's draft.

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index.

This is an unofficial proposal.

This document was published by the Linked Web Storage Working Group as an Editor's Draft.

Publication as an Editor's Draft does not imply endorsement by W3C and its Members.

This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 18 August 2025 W3C Process Document.

For Editors

This section is non-normative.

List of TODOs and ideas in flux to enable editors to communicate asynchronously.

Resources

Tactics

1. Document Conventions

This section is non-normative.

2. Introduction

2.1 Resource Access

The LWS Protocol defines standard interactions by which a some party can make some resources available to some agents.

2.2 Security and Privacy

A resource manager may keep a served resource private, may make it publicly available to anyone, or may limited its visibility to a constrained set of requesting agents.

2.3 Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

A LWS REST Server is an HTTP server [rfc9112] that complies with all of the relevant "MUST" statements in this specification. Specifically, the relevant normative "MUST" statements in Sections 999 REST Binding of this document MUST be respected.

A LWS REST Client is an HTTP client [rfc9112] that complies with all of the relevant "MUST" statements in this specification. Specifically, the relevant normative "MUST" statements in Sections 999 REST Binding of this document MUST be respected.

3. Terminology

The terms "authorization server" and "client" are defined by the OAuth 2.0 Authorization Framework [RFC6749].

The terms "end-user" and "issuer" are defined by OpenID Connect Core 1.0 [OPENID-CONNECT-CORE].

This specificaiton defines the following terms:

This specification defines operations on served resources, the resulting change of state, and a response indended to give the requesting agent requested infomation or inform them of the outcome of the operation. An operation is any of the following actions that can be performed on a served resource:

The folowing section will describe the semantics and responses of these operations but the following core responses apply to any operation:

4. Authentication

This section defines a mechanism for identifying agents and end users that interact with a linked web storage server. This specification does not mandate a particular format for an authentication credential, though it does describe how existing identity systems can be used in conjunction with the linked web storage authorization framework.

4.1 Authentication Credential Data Model

The data model described in this section outlines the requirements for any concrete serialization of an authentication credential.

An authentication credential MUST include tamper evident claims about a subject, including:

4.2 Authentication Credential Validation

Validation of an authentication credential requires a trust relationship between the verifier and issuer of the credential. This trust relationship MAY be established through an out-of-band mechanism. Any additional mechanisms for establishing trust between a verifier and an issuer are outlined in specific authentication suites.

An authentication credential MUST be signed. It is RECOMMENDED that the signature uses asymmetric cryptography.

4.3 Authentication Credential Type Identifiers

Each authentication suite MUST be associated with a token type URI. An authentication suite SHOULD use a URI defined in the IANA "OAuth URI" registry.

5. Authorization

Linked Web Storage describes a mechanism for persisting and managing protected data on the Web. Authorization is the mechanism by which agents request and present access tokens in order to access this protected data.

5.1 Roles

The roles in LWS authorization are the same as those defined by OAuth 2.0 Section 1.1 [RFC6749]: resource owner, resource server, client (called in this specification authorization client to avoid ambiguity), and authorization server. A storage server is a type of resource server that also conforms to the LWS storage specification.

5.2 Protocol Flow

This specification describes the interaction between a client and an authorization server as well as the interaction between a client and a conforming storage server.

The interaction between the authorization server and the storage server is out of scope of this specification. The authorization server may be the same server as the storage server or it may be a separate entity.

5.2.1 Authorization Server Discovery

All protected resources managed by a storage server require a valid access token, generated by a trusted authorization server. A client can discover the location of a trusted authorization server by making an unauthorized HTTP request to a protected resource.

A storage server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header field containing at least one conforming challenge. A conforming challenge will include the parameters described below:

  • as_uri REQUIRED — The value of this parameter is a URI identifying the authorization server where a client can retrieve an access token. The value of this parameter will be the same as the iss claim of a valid access token.
  • realm REQUIRED — The value of this parameter is a URI indicating the scope of protection. This value will be included in the audience (aud) claim of an access token. A client MUST verify that the URI of the originating request is logically contained within the realm presented in this response.

Other headers and parameters MAY be included.

An example 401 response is included below.

HTTP/2 401 Unauthorized
Link: <https://storage.example/storage_1/metadata>; rel="storageDescription"
WWW-Authenticate: Bearer as_uri="https://authorization.example",
                realm="https://storage.example/storage_1",
                error="invalid_token"

5.2.2 Authorization Server Metadata

An authorization server MUST provide a metadata resource to allow clients to discover endpoint locations and capabilities as described in [RFC8414]. This metadata resource MUST be available at a URL with the path /.well-known/lws-configuration.

An authorization server SHOULD advertise the subject tokens that it supports by including a subject_token_types_supported entry in the server metadata document. This entry is a JSON array containing a list of valid subject_token_type values that can be supplied at the authorization server's token endpoint.

An example authorization server metadata resource is included below.

{
    "issuer": "https://authorization.example",
    "grant_types_supported": [
        "urn:ietf:params:oauth:grant-type:token-exchange"],
    "token_endpoint": "https://authorization.example/token",
    "jwks_uri": "https://authorization.example/jwks",
    "claims_supported": [
        "sub",
        "iss",
        "client_id",
        "aud"],
    "response_types_supported": [
        "token"],
    "subject_token_types_supported": [
        "urn:ietf:params:oauth:token-type:jwt",
        "urn:ietf:params:oauth:token-type:id-token"]
}

5.2.3 Token Exchange

An LWS authorization server is a conforming OAuth 2.0 authorization server, capable of issuing access tokens to a client for use with a storage server. In order to issue an access token, a client must first present a valid subject token, such as an authentication credential, to the authorization server via OAuth 2.0 Token Exchange [RFC8693].

5.2.3.1 Request

The authorization server's token endpoint MUST support the urn:ietf:params:oauth:grant-type:token-exchange grant type, as described in OAuth 2.0 Token Exchange [RFC8693].

When performing the token exchange grant type, the following additional requirements apply:

  • The resource parameter is REQUIRED. The value of this parameter MUST be a URI and will be used to populate the aud (audience) claim in the resulting access token. The supplied value will be the same as the realm parameter response in a WWW-Authenticate challenge. The authorization server MUST reject any request in which the resource parameter identifies an unknown or untrusted storage.
  • The subject_token parameter is REQUIRED. The value of this parameter MUST include a valid subject token, such as an authentication credential.
  • Before returning an access token to the client, the authorization server MUST successfully validate all presented tokens.

Non-normative example of a token request (the subject_token parameter has been truncated).

POST /token HTTP/1.1
Host: authorization.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&resource=https%3A%2F%2Fstorage.example%2Fstorage_1
&subject_token=eyJ0eXAiOiJhcytqd3QiLCJhbGciO...fiK51VwhsxJ-siBMR-YFiA
&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aid_token
5.2.3.2 Response

If the token request is valid and the client is authorized to make the request, the authorization server response MUST conform to Section 5.1 from the OAuth 2.0 Authorization Framework [RFC6749]. The resulting access token MUST conform to the JSON Web Token Profile for OAuth 2.0 Access Tokens [RFC9068].

In addition, the access token must meet the following requirements:

  • sub (subject) — REQUIRED. This claim MUST be a URI identifying the agent performing the operation
  • iss (issuer) — REQUIRED. This claim MUST be the URI of the authorization server
  • client_id (client id) — REQUIRED. This claim MUST be a URI identifying the client.
  • aud (audience) — REQUIRED. This claim MUST include the URI supplied by the client in the resource parameter. This value will be used to restrict the entities for which the access token is valid. This will be the same value as provided by a storage server in the realm parameter of a WWW-Authenticate challenge.
  • exp (expiration) — REQUIRED. Authorization servers SHOULD issue tokens with short lifetimes (RECOMMENDED: 300 seconds or less) to limit exposure from token theft.
  • iat (issued at) — REQUIRED.
  • jti (JWT ID) — REQUIRED.

A non-normative example of a successful token response is included below.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token":"eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso",
    "token_type":"Bearer",
    "expires_in":3600
}

All invalid or unauthorized requests MUST result in an error response as described in Section 5.2 in the OAuth 2.0 Authorization Framework [RFC6749].

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
    "error":"invalid_request"
}
5.2.3.3 Example access token

This section is non-normative.

An example access token issued by an authorization server is included below.

{
  "kid": "ec51c6b2",
  "kty": "EC",
  "alg": "ES256",
  "crv": "P-256",
  "typ": "at+jwt"
}
.
{
  "sub": "https://id.example/agent",
  "iss": "https://authorization.example",
  "client_id": "https://app.example/id",
  "aud": "https://storage.example",
  "exp": 1735686300,
  "iat": 1735686000,
  "jti": "550e8400-e29b-41d4-a716-446655440000"
}
.
signature

5.2.4 Token Validation by a Storage Server

Once a client is in possession of an access token, it will present this token to a storage server. The storage server is responsible for verifying this token before performing any operation.

5.2.4.1 Presentation

A client MUST present an access token to a storage server using the Authorization header with an authentication scheme as defined in [RFC6750].

Authorization: Bearer eyJ0eXAiOiJhcytqd3QiLCJhbGciOiJFUzI1NiIs...DeWt4QuZXso
5.2.4.2 Validation

A storage server MUST validate an access token by performing the following checks, rejecting the request upon any failure:

  • JWT Signature Validation: Verify the JWT signature using the authorization server's public key retrieved from the jwks_uri specified in the authorization server metadata. Storage servers SHOULD cache these keys and MUST support key rotation.
  • Issuer Validation: Verify the iss claim matches the expected authorization server identifier.
  • Audience Validation: Verify the aud claim contains exactly one value and this value is a URI identifying the storage server which logically contains the target resource.
  • Temporal Validation, subject to an allowable clock skew between systems.
    • Verify the current time is before the exp (expiration) claim.
    • Verify the current time is not before the nbf (not before) claim, if present.
    • Verify that the iat (issued at) claim is not in the future.

If validation fails, the storage server MUST return 401 Unauthorized with a WWW-Authenticate header containing an appropriate error parameter (e.g., invalid_token, invalid_request, or insufficient_scope).

If the token is otherwise valid but an authorization policy does not allow the requested operation, the storage server MUST reject the request.

6. Discovery

6.1 Storage Description Resource

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

6.1.1 Data Model

  • id - the id property is REQUIRED. Its value MUST be a URI that identifies the storage.
  • type - the type property is REQUIRED. Its value MUST be a string that equals Storage or a set of strings that contains an item equal to Storage (case-sensitive).
  • capability - the capability property is OPTIONAL. Its value MUST be a set of capabilities, where each capability is described by a map containing the following properties. Additional properties MAY be present.
    • id - the id property is OPTIONAL. If present, its value MUST be a URI.
    • type - the type property is REQUIRED. Its value MUST be a string or a set of strings.
  • service - the service property is REQUIRED. Its value MUST be a set of services, where each service is described by a map containing the following properties. Additional properties MAY be present.
    • id - the id property is OPTIONAL. If present, its value MUST be a URI.
    • type - the type property is REQUIRED. Its value MUST be a string or a set of strings.
    • serviceEndpoint - the serviceEndpoint property is REQUIRED. Its value MUST be a URI.
Example 8: Minimum storage description resource
{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "https://storage.example/",
  "type": "Storage",
  "service": [{
    "type": "StorageDescription",
    "serviceEndpoint": "https://storage.example/description"
  }]
}

6.1.2 Discovery and Binding

All responses to GET and HEAD requests targeting storage resources MUST include a Link header whose target is the URI of the storage description resource, including a relation (rel) parameter whose value equals https://www.w3.org/ns/lws#storageDescription.

When dereferenced, the storage description MUST contain an id property that identifies the storage. In addition, the service property MUST contain a service description whose type equals StorageDescription and whose serviceEndpoint equals the URL of the storage description.

Note

The URI for a storage description can be distinct from the URI identifying a storage, which can be distinct from the storage's root container. These URIs can also be identical, provided that the resulting representation conforms to the requirements outlined in this document.

6.1.3 Storage Capabilities

A storage description may contain descriptions of additional capabilities supported by the storage.

6.1.4 Storage Services

In addition to a StorageDescription service, a storage description resource may contain links to other services connected to a storage. The API definition of these services are outside the scope of this specification.

6.1.5 Storage Description Representation

A storage description resource MUST be serializable with the media type application/lws+json. Other representations MAY be available via content negotiation.

Example 9: Storage description resource
{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "https://storage.example/",
  "type": "Storage",
  "capability": [{
    "type": "https://feature.example/PatchSupport",
    "mediaType": {
      "text/turtle": ["application/sparql-update"],
      "application/n-triples": ["application/sparql-update"],
      "application/linkset+json": ["application/merge-patch+json", "application/json-patch+json"]
    }
  }, {
    "type": "https://feature.example/ResumableUploads"
  }, {
    "type": "https://feature.example/ContentNegotiation",
    "source": "application/ld+json",
    "target": ["text/turtle", "application/n-triples"]
  }, {
    "type": "https://feature.example/ContentNegotiation",
    "source": "image/jpeg",
    "target": ["image/png"]
  ],
  "service": [{
    "type": "NotificationService",
    "serviceEndpoint": "https://storage.example/notification/api"
  }, {
    "type": "TypeIndexService",
    "serviceEndpoint": "https://storage.example/types/api"
  }, {
    "type": "DataSharingService",
    "serviceEndpoint": "https://storage.example/sharing/api"
  }, {
    "type": "StorageDescription",
    "serviceEndpoint": "https://storage.example/description"
  }]
}

7. Logical Resource Organization

The storage system organizes resources into two distinct layers: primary and auxiliary. The two layers are complementary. The primary layer organizes resources spatially and hierarchically, while the auxiliary layer attaches supplementary resources to each node in that hierarchy.

7.1 Primary resource layer

The primary resource layer forms a strict hierarchy rooted at a single root container. Every primary resource except the storage root is contained by one or more parents.

A container is a specialized resource that can contain other resources, called its contained members. Containers serve as organizational units, analogous to directories or collections, enabling clients to group, discover, and navigate resources. A container maintains references to its contained member resources, which may comprise both non-container resources and additional container resources, thereby enabling hierarchical formations. The principal role of a container is to aggregate and structure subordinate resources.

The storage system's root is designated as a container, serving as the apex organizational unit devoid of a superior parent, and acts as the entry point for the storage hierarchy. Storage MAY function as a root container, enabling direct writes.

Servers MUST include a Link header with rel="type" pointing to https://www.w3.org/ns/lws#Container.

Link: <https://www.w3.org/ns/lws#Container>; rel="type"

7.1.1 Containment

The containment relationship between a resource and its parent container is expressed via the rel="up" link relation. Servers MUST include a Link header with rel="up" pointing to the parent container in responses to GET and HEAD requests on any contained resource.

Link: </alice/notes/>; rel="up"

7.2 Auxiliary resource layer

The auxiliary resource layer is flat. Each primary resource owns a local set of auxiliary resources. An auxiliary resource is an LWS resource that is used to provide additional information or functionality related to a unique principal resource. The lifetime of an auxiliary resource is bound to the lifetime of its principal resource. Auxiliary resources do not participate in the containment hierarchy.

7.2.1 Auxiliarity

The auxiliarity relationship between an auxiliary resource and its principal resource is expressed via the rel="principal" link relation. Servers MUST include a Link header with rel="principal" pointing to the principal resource in responses to GET and HEAD requests on any auxiliary resource.

Link: </alice/notes/>; rel="principal"

Along with the general rel="principal" relation from auxiliary resource to its principal resource, an auxiliary resource is linked from the principal resource through a specialized link relation. This specialized relation is called the auxiliaryRel of the auxiliarity. Auxiliary relations are constrained to be functional. For each auxiliaryRel, there MUST be at most one auxiliary resource.

In responses to GET and HEAD requests on any principal resource, servers MUST link to each auxiliary resource with rel value set to the auxiliaryRel of the auxiliarity.

Link: </alice/notes/~manifest.json>; rel="manifest"
Link: </alice/notes/~acl>; rel="acl"

This specification predefines the following auxiliary relations:

  • manifest: Server-managed manifest auxiliary resource (see below)
  • linkset: Server-managed linkset auxiliary resource (see below)
  • acl: ACL auxiliary resource. Server interprets it for access control over the resource.

7.3 Manifest resource

Each primary resource has a unique server-managed auxiliary resource called the manifest resource. A manifest resource holds basic metadata and enumerations of auxiliary members and contained members (for containers) of the principal resource. It has manifest as the specialized auxiliarity relation. That is, servers MUST include a Link header with rel="manifest" pointing to the auxiliary manifest resource in responses to GET and HEAD requests on any primary resource.

Link: </alice/notes~manifest.json>; rel="manifest"

For each primary resource, its auxiliary members are enumerated in its manifest representation using the auxiliaryMap property. Each map entry has the auxiliaryRel value as the key, and description of the corresponding auxiliary resource as the value. Auxiliary membership changes occur as a side effect of auxiliary resource creation and deletion.

For each container, its contained members are listed in its manifest representation using the containedItems property. Containment membership changes occur as a side effect of contained resource creation and deletion.

Manifest resources MUST support pagination for container membership listings using 'ContainerPage' types, with properties such as 'first', 'next', 'prev', and 'last'. Representations MUST use JSON-LD with a specific frame and normative context, optionally advertising content negotiation via 'Vary: Accept' headers.

7.3.1 Manifest integrity

The server MUST maintain manifest integrity at all times:

  • Creation: When a new resource is created in a container, the server MUST atomically add the resource to its manifest's containedItems list. When a new auxiliary resource is created, the server MUST atomically add the corresponding entry to its principal's manifest's auxiliaryMap map.
  • Deletion: When a contained resource is deleted, the server MUST atomically remove it from its parent container's containedItems list. Deleting a container requires the container to be empty, unless recursive deletion is explicitly requested. When an auxiliary resource is deleted, the server MUST atomically remove the corresponding entry from auxiliaryMap in the manifest of its principal resource. When a principal resource is deleted, the server MUST atomically delete all its auxiliary resources including the manifest resource.
  • No orphans: Every resource MUST be either a contained resource reachable from the root container through the containment hierarchy, or an auxiliary resource reachable from a principal resource through an auxiliary relation.
  • No cycles: A container MUST NOT directly or indirectly contain itself.
  • Layer hygiene: A primary resource cannot have other primary resources as its auxiliary resource. An auxiliary resource cannot be a container containing other primary resources.

7.3.2 Manifest membership and Authorization

If a client has read access to a resource, the resource manifest representation MUST include the identifiers for all members either auxiliaries or contained to which the client has access. It MAY also contain the identifiers for contained/auxiliary resources of that resource to which the client does not have access.

A client's ability to read a manifest listing does not imply access to the listed resources themselves, and vice versa.

8. Manifest Representation

8.1 Manifest Representation

When a client retrieves a manifest of a resource, the server returns a structured manifest representation. This section defines the required and optional properties of a manifest representation.

8.1.1 Manifest Properties

A manifest representation MUST include the following properties of the principal resource:

  • id: The URI of the resource.
  • type: The type of the resource. Can be a single string or an array of strings. For all resources, it MUST include "Resource". For containers, it MUST include "Container".
  • totalContainedItems: For a container resource, an integer indicating the total number of resources contained in the resource which can be disclosed to the client.
  • containedItems: For a container resource, an array of contained resource descriptions (see below). If the container is empty, this MUST be an empty array.
  • auxiliaryMap: A map with entries corresponding to each auxiliary relation, with auxiliaryRel as the key and description of the corresponding auxiliary resource as the value.

8.1.2 Resource Description

Each entry in the containedItems array describes a contained member resource. The value of each entry in the auxiliaryMap map describes an auxiliary member resource.

A member resource description MUST include:

  • id: The URI of the member resource.
  • type: The type of the member resource. Can be a single string or an array of strings. For all resources, it MUST include "Resource". For containers, it MUST also include "Container". Servers MAY include additional user-defined types as URIs (e.g., ["Container", "http://example.org/customType"]).

A resource description SHOULD include:

  • mediaType: The media type of the resource (e.g., "text/plain", "image/jpeg"). MUST be present.
  • size: The size of the resource in bytes, expressed as an integer.
  • modified: The date and time the resource was last modified, expressed as an ISO 8601 date-time string.

8.1.3 Example Manifest Representation

The following example shows the manifest of a container at /alice/notes/ containing two resources, and having some auxiliary resources:

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/notes/",
  "type": ["Container", "Resource"],
  "totalContainedItems": 2,
  "containedItems": [
    {
      "id": "/alice/notes/shoppinglist.txt",
      "type": ["Resource"],
      "mediaType": "text/plain",
      "size": 47,
      "modified": "2025-11-24T12:00:00Z"
    },
    {
      "type": ["Resource", "http://example.org/customType"],
      "id": "/alice/notes/todo.json",
      "mediaType": "application/json",
      "size": 2048,
      "modified": "2025-11-24T13:00:00Z"
    }
  ],
  "auxiliaryMap": {
    "manifest":     {
      "id": "/alice/notes/~manifest.json",
      "type": ["Manifest", "Resource"],
      "mediaType": "application/lws+json",
      "modified": "2025-11-24T14:00:00Z",
    },
    "linkset":     {
      "id": "/alice/notes/~linkset.json",
      "type": ["Linkset", "Resource"],
      "mediaType": "application/linkset+json",
      "modified": "2025-11-24T14:00:00Z",
    },
    "acl":     {
      "id": "/alice/notes/~acl",
      "type": ["Resource"],
      "mediaType": "text/turtle",
      "modified": "2025-12-24T15:00:00Z",
    }
  }
}

9. Operations

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. 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.

For each core operation (create, read, update, delete), we describe the HTTP method(s) to use, required headers or special considerations (including concurrency controls via ETags, content negotiation, and pagination for container listings), and what the server should do and return. Standard HTTP status codes are used to indicate outcomes with additional mappings for scenarios such as quota exceeded (507 Insufficient Storage) or precondition failures (412 Precondition Failed). The binding tries to adhere to HTTP/1.1 and relevant RFCs (such as [RFC7231] for HTTP semantics, [RFC7233] for range requests, [RFC5789] for PATCH, [RFC8288] for Web Linking, and [RFC9264] for Link Sets) so that it integrates naturally with web standards. Discoverability is emphasized through mechanisms like Link headers and WWW-Authenticate headers on 401 responses, avoiding hardcoded URI locations. Metadata integration is required across operations, ensuring atomicity and use of Link Sets for server-managed and user-managed properties.

Note: As all examples in this specifications, examples given in this section (HTTP request and response snippets) are non-normative, meant to illustrate typical usage. The actual requirements are stated in the descriptive text and tables. Also, while this binding covers HTTP (as the initial target protocol), the LWS operations could in principle be bound to other protocols in the future. Servers MUST support content negotiation for application/lws+json, application/ld+json, and application/json for manifest representations (see Manifest Media Type). Servers MAY additionally support formats like Turtle.

9.1 Metadata

This section defines the model for associating metadata with LWS resources. The LWS metadata system is based on the principles of Web Linking [RFC8288], which allows servers to describe the relationships between resources using typed links. Metadata enhances discoverability, supports self-descriptive APIs, and aligns with resource operations, and container hierarchies.

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:

Metadata distinguishes between resources and their representations, allowing for multiple media types where applicable. For resources with representations, metadata includes representations, each with mediaType and optional sizeInBytes. For contained resources, the link to its parent container resource is part of the metadata of the resource. For auxiliary resources, the link to its principal resource is part of the metadata of the resource. For all primary resources, the links to their auxiliary resources are part of the metadata of the resource.

The Linkset Resource For each primary resource in storage, a server MUST make metadata links available as a standalone auxiliary resource according to [RFC9264].

Discovering Metadata Clients discover metadata primarily through Link headers in response to GET or HEAD requests.

Metadata Types

Category Description
System Managed Maintained by the server; Read-Only. Includes linkset, manifest, type, mediaType, size, modified.
Core Metadata Managed by the client (subject to server restrictions). Includes up, principal, items, title, creator, and other auxiliary resources.
User-Defined Custom vocabularies and indexes created by the user.

Modifiability Considerations Core metadata of primary resources MAY be modified by clients. To ensure interoperability, servers MUST use standard HTTP headers to advertise their capabilities:

  1. Method Discovery: Servers MUST advertise support for GET and PATCH operations on the linkset resource via the Allow header.

  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.

[!IMPORTANT] Clients SHOULD NOT assume support for PUT or specific patch formats unless they are advertised in the resource headers and MUST handle 405 Method Not Allowed or 415 Unsupported Media Type responses gracefully.

Managing Metadata Metadata is managed by interacting with the primary resource's associated linkset URI. Servers MUST support concurrency controls for updates.

9.2 Create resource

The create resource operation adds a new served resource to an existing patron. This operation handles both the creation of contained resources and auxiliary resources.

Inputs:

Behavior:

Possible Responses:

New resources are created using POST to a target patron resource URI, with the server assigning the final identifier. Clients MAY suggest a name via the Slug header. Clients MAY provide initial user-managed metadata for the new resource by including one or more Link headers in the POST request, following the syntax of Web Linking in [RFC8288]. Server-managed metadata MUST be generated automatically by the server upon creation and MUST NOT be overridden by client-provided links. Server-managed auxiliary resources MUST be generated automatically by the server upon creation of a contained primary resource.

On success, the server MUST return the 201 status code with the new URI in the Location header. The server MUST include Link headers for key server-managed metadata, including a link to the patron (via rel="up" for contained, via rel="principal" for auxiliary), and links to the created resource's Server-managed auxiliary resources (rel="linkset"; type="application/linkset+json"). Additional links SHOULD include rel="type" (indicating https://www.w3.org/ns/lws#Container, https://www.w3.org/ns/lws#Resource ,etc). The body MAY be empty or include a minimal representation of the resource. All metadata creation and linking MUST be atomic with the resource creation to maintain consistency.

POST (to a patron URI)Create with server-assigned name: Use POST to add a new resource to an existing patron resource, either as an auxiliary member or contained member if the target is a container. The server assigns an identifier to the resource, optionally suggested via the Slug header. The server MAY honor the Slug header if it does not conflict with naming rules or existing resources.

Clients indicate the type of membership as follows:

Clients indicate the containment capability of the contained member resource to create as follows:

Example (POST to create a new leaf resource):

POST /alice/notes/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Type: text/plain
Content-Length: 47
Slug: shoppinglist.txt
Link: </alice/notes/> rel="up"

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. It provides membership link with rel="up" pointing to the current container, requesting to be a contained member. If /alice/notes/ exists and the client is authorized, the server will create a new Resource and add it to the container's membership.

Example (Response to POST — Leaf Resource):

HTTP/1.1 201 Created
Location: /alice/notes/shoppinglist.txt
Content-Type: text/plain; charset=UTF-8
Link: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/shoppinglist.txt.manifest>; rel="manifest"; type="application/lws+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#Resource>; rel="type"
Content-Length: 0

On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. If the target container /alice/notes/ does not exist, the server MUST return a 404 error status unless another status code is more appropriate.

Creating Containers: To create a new container, a client uses POST to an existing parent container with a Link header indicating the Container type, and another Link header indicating containement membership. For example:

POST /alice/ HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Length: 0
Slug: notes
Link: </alice/> rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"

Example (Response to POST — container):

HTTP/1.1 201 Created
Location: /alice/notes/
Link: </alice/notes/.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/.manifest>; rel="manifest"; type="application/lws+json"
Link: </alice/>; rel="up"
Link: <https://www.w3.org/ns/lws#Container>; rel="type"
Content-Length: 0

This creates a new container at /alice/notes/, and its server-managed auxiliary resources like manifest and linkset, with server-generated metadata including rel="type" as https://www.w3.org/ns/lws#Container.

Example (POST to create a new auxiliary member resource):

POST /alice/notes/shoppinglist.txt HTTP/1.1
Host: example.com
Authorization: Bearer <token>
Content-Type: text/turtle
Content-Length: 47
Slug: shoppinglist.txt.acl
Link: </alice/notes/shoppinglist.txt>; rel="principal"
Link: <>; rel="acl"; anchor="/alice/notes/shoppinglist.txt"

# This box contains an authorization graph
# It describes the conditions required for accessing a resource  

[]
  a acp:AccessControlResource ;
  acp:resource ex:resourceX ;
  acp:accessControl [
    a acp:AccessControl ;
    acp:apply [
      a acp:Policy ;
      acp:allow acl:Read ;
      acp:anyOf [
        a acp:Matcher ;
        acp:agent ex:Alice, ex:Bob ;
      ]
    ]
  ] .

In this example, the client is posting to the primary resource /alice/notes/shoppinglist.txt, to create an acl auxiliary resource. It provides text/turtle content (an authorization graph) and suggests the name shoppinglist.txt.acl for the new resource. It provides membership link with rel="principal" pointing to the principal resource, requesting to be an auxiliary member. It provides a link from the principal resource to the new resource with the anchor parameter set to the primary resource URI and the rel="acl", pointing to the new resource to create using an empty URI reference <>. If /alice/notes/shoppinglist.txt exists and the client is authorized, the server will create a new Resource and add it to the primary resource's auxiliary membership.

Example (Response to POST — Auxiliary Resource):

HTTP/1.1 201 Created
Location: /alice/notes/shoppinglist.txt.acl
Content-Type: text/plain; charset=UTF-8
Link: </alice/notes/shoppinglist.txt>; rel="principal"
Link: <>; rel="acl"; anchor="/alice/notes/shoppinglist.txt"
Link: <https://www.w3.org/ns/lws#Resource>; rel="type"
Content-Length: 0

On success, return 201 Created with the new URI in the Location header. The body may be empty or a minimal representation. If the target primary resource /alice/notes/shoppinglist.txt does not exist, the server MUST return a 404 error status unless another status code is more appropriate. If the target primary resource /alice/notes/shoppinglist.txt already has an auxiliary resource with auxiliaryRel acl, the server MUST return a 409 error status unless another status code is more appropriate.

Additional notes on Create (HTTP binding):

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.

9.3 Read resource

Retrieves the representation of an existing resource.

The read resource operation requests a resource representation with HTTP GET requests (and HEAD for header-only requests). All responses MUST integrate with metadata as defined in Section 8.1, including Link headers for key relations such as rel="linkset", rel="manifest", rel="up", rel="principal", and rel="type". Servers MUST ensure atomicity between the resource state and its metadata during reads.

GETRetrieve 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):

GET /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
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: </alice/notes/shoppinglist.txt.meta>; rel="linkset"; type="application/linkset+json"
Link: </alice/notes/>; rel="up"
Link: <https://www.w3.org/ns/lws#Resource>; 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 up and type.

GET (manifest resource)Retrieve a resource's manifest: When the target URI corresponds to a manifest resource, a GET request returns a manifest representation as defined in the Manifest Representation section, using the LWS manifest media type. The manifest includes metadata for each of contained auxiliary members: resource identifiers (MUST), types (MUST), media types (MUST), sizes (SHOULD), and modification timestamps (SHOULD).

Example (GET a manifest):

GET /alice/notes/~manifest HTTP/1.1
Authorization: Bearer <token>
Accept: application/lws+json

Assuming the principal resource and the manifest exists and the client has access:

HTTP/1.1 200 OK
Content-Type: application/lws+json
ETag: "manifest-etag-789"
Link: </alice/notes/>; rel="principal";

{
  "@context": "https://www.w3.org/ns/lws/v1",
  "id": "/alice/notes/",
  "type": ["Resource", "Container"],
  "totalItems": 2,
  "items": [
    {
      "type": "Resource",
      "id": "/alice/notes/shoppinglist.txt",
      "mediaType": "text/plain",
      "size": 47,
      "modified": "2025-11-24T12:00:00Z"
    },
    {
      "type": ["Resource", "http://example.org/customType"],
      "id": "/alice/notes/todo.json",
      "mediaType": "application/json",
      "size": 2048,
      "modified": "2025-11-24T13:00:00Z"
    }
  ],
  "auxiliaryMap": {
    "manifest":     {
      "id": "/alice/notes/~manifest.json",
      "type": ["Manifest", "Resource"],
      "mediaType": "application/lws+json",
      "modified": "2025-11-24T14:00:00Z",
    },
    "linkset":     {
      "id": "/alice/notes/~linkset.json",
      "type": ["Linkset", "Resource"],
      "mediaType": "application/linkset+json",
      "modified": "2025-11-24T14:00:00Z",
    },
    "acl":     {
      "id": "/alice/notes/~acl",
      "type": ["Resource"],
      "mediaType": "text/turtle",
      "modified": "2025-12-24T15:00:00Z",
    }
  } 
}

In this example, /alice/notes/ is a container, and alice/notes/~manifest is it's manifest auxiliary resource. The response uses JSON-LD with the LWS context, listing contained and auxiliary members with required metadata. Each item includes its type, id, mediaType, size, and modified timestamp as flat properties.

In all cases, the server MUST include the following metadata in the response headers: an ETag (representing the listing version, which changes on membership modifications), and Link headers with rel="type" indicating if it is a container, rel="linkset" and rel="up" if it is a contained resource and rel="principal" if it is an auxiliary resource.

HEADHeaders/metadata only: The LWS server MUST support HEAD [RFC9110] for all resources in storage, returning the same headers as GET (including ETag, Content-Type, Link for metadata) but without a body. This enables metadata retrieval without transferring content.

Caching and Conditional Requests: LWS leverages HTTP caching semantics. Servers MUST support conditional requests via If-None-Match (with ETags) or If-Modified-Since headers. If the resource or container listing has not changed, respond with 304 Not Modified to avoid redundant transfers. ETags MUST be provided in all GET/HEAD responses for concurrency and caching support.

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.

9.4 Update resource

Modifies the state of an existing [served resource] via full replacement or a partial patch.

The update resource modifies the contents of an existing 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 <token>
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 got from an earlier GET or HEAD request. 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.

PATCH (partial update) – The HTTP PATCH method [RFC5789] allows a client to specify partial modifications to a resource, rather than sending the whole new content. This is useful for large resources where sending the entire content would be inefficient if only a small part changed, or for concurrent editing where you want to apply specific changes. LWS server MUST minimally support JSON Merge Patch (application/merge-patch+json) as defined in [RFC7386].

Update Primary Resource Metadata (HTTP PUT / PATCH on Linkset) A primary resource's metadata is updated by modifying its corresponding linkset auxiliary resource, discovered via the Link header with rel="linkset". Full Replacement (PUT): A PUT request to the linkset URI with a complete linkset document in the body replaces all metadata for the resource. Partial Update (PATCH): A PATCH request to the linkset URI adds, removes, or modifies specific links.

Concurrency Control for Metadata Because a primary resource's metadata can be modified by multiple actors, preventing concurrent overwrites is critical. To ensure data integrity, LWS servers and clients MUST implement optimistic concurrency control using conditional requests [RFC7232] for all PUT and PATCH operations on a linkset resource. Server Responsibilities: A server MUST include an Etag header in its responses to GET and HEAD requests for a linkset resource. Upon a successful PUT or PATCH on the linkset, the server MUST generate a new, unique Etag value for the modified linkset and return it in the Etag header of the response. 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 [RFC6585]. 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 <token>
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 <token>
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.

9.5 Delete resource

Permanently removes a resource and its associated auxiliary resources.

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.

Deletion and Containment: When a contained resource is deleted, the server MUST atomically remove it from its parent container manifest's containedItems list. The parent container manifest's totalContainedItems count and ETag MUST be updated accordingly.

When an auxiliary resource is deleted, the server MUST atomically remove the corresponding entry from its principal resource manifest's auxiliaryMap list, and MUST remove the auxiliarity link from the principal resource's metadata linkset. ETags of the manifest and linkset resources of the principal resource MUST be updated accordingly.

For all resources, the server removes the resource content. For all primary resources, the server removes its associated auxiliary resources.

For container resources, the server defaults to non-recursive deletion. If the container is not empty and recursion is not requested, the server MUST reject the request with 409 Conflict. Servers MAY support recursive deletion of all contained resources within the container that is being deleted. Clients MUST use the Depth: infinity header to request for a recursive delete, as defined in [RFC4918].

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.

Example (DELETE a non-container contained resource):

DELETE /alice/notes/shoppinglist.txt HTTP/1.1
Authorization: Bearer <token>
If-Match: "abc123456"

Assuming the ETag matches and the client is authorized, the server deletes the resource, its auxiliary resources, and removes it from the parent container /alice/notes/ by updating its manifest atomically:

HTTP/1.1 204 No Content

Example (DELETE a non-empty container without recursion):

DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>

Assuming /alice/notes/ contains resources, the server refuses the deletion:

HTTP/1.1 409 Conflict
Content-Type: text/plain

Cannot delete container /alice/notes/ - container is not empty.

Example (DELETE a container with recursion, if supported):

DELETE /alice/notes/ HTTP/1.1
Authorization: Bearer <token>
Depth: infinity

Assuming the server supports recursion and the client has permissions for all contents, the server deletes the container , its auxiliary resources, and its descendants atomically:

HTTP/1.1 204 No Content

Example (DELETE a non-server-managed auxiliary resource):

DELETE /alice/notes/~acl HTTP/1.1
Authorization: Bearer <token>
If-Match: "abc123456"

Assuming the ETag matches and the client is authorized, the server deletes the auxiliary resource and removes it from the principal resource /alice/notes/ by updating its manifest atomically:

HTTP/1.1 204 No Content

9.6 Summary of HTTP Status Mappings

This table maps generic LWS 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 (read or update, returning data) 200 OK Resource representation in the response body (for GET or if PUT/PATCH returns content), along with relevant headers (Content-Type, ETag, Link for metadata such as rel="linkset", rel="up"). For manifest representations, include JSON-LD with normative context and member metadata (IDs, types, sizes, timestamps).
Created (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".

10. LWS Media Type

10.1 LWS Media Type

LWS manifest representation and storage description resource MUST use the media type application/lws+json.

While LWS manifest representations use JSON-LD conventions, the constraints and requirements for LWS justify the use of a specific media type. Because LWS manifests can be considered a restricted profile of JSON-LD, implementations SHOULD consider the application/ld+json; profile="https://www.w3.org/ns/lws/v1" media type as equivalent to application/lws+json.

10.1.1 Content Negotiation

Servers MUST support content negotiation for manifest representations. The response payload MUST be identical regardless of the requested media type — only the Content-Type response header varies:

  • 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 manifest vocabulary. Servers are free to support additional media types (e.g., text/turtle) through content negotiation.

11. JSON-LD Context and Vocabulary

11.1 JSON-LD Context and Vocabulary

11.1.1 Normative JSON-LD Context

Manifest representations MUST include the following @context value:

"@context": "https://www.w3.org/ns/lws/v1"

The normative JSON-LD context document defines the mapping between the short property names used in manifest representations and their full URIs in the LWS and related vocabularies. The context is defined as follows:

{
  "@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",
    "Resource": "lws:Resource",
    "Container": "lws:Container",
    "containedItems": "lws:containedItems",
    "auxiliaryMap": "lws:auxiliaryMap",
    "totalContainedItems": "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.

11.1.2 Vocabulary

The LWS vocabulary defines the following types and properties used in manifest representations:

Types:

Term URI Description
Resource lws:Resource An lws conformant resource
Container lws:Container A resource that contains other resources

Properties:

Term URI Description
containedItems lws:containedItems The list of resources contained in a container
auxiliaryMap lws:auxiliaryMap The map with entries corresponding to auxiliary resources of a resource
totalContainedItems as:totalItems The total number of contained resources
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

12. Resource Identification

Define how resources are identified and addressed within the LWS Protocol, including URI schemes, resource naming conventions, and resolution mechanisms. This section may be moved within another section; e.g. Resource Access

this left intentionally blank

13. Unstable Features

The features described in this section are being drafted to ground discussions and may be removed if there is:

this left intentionally blank

13.1 Profile Negotiation on Resources

Define mechanisms for content negotiation based on profiles, allowing clients to request specific representations or views of resources (e.g., JSON-LD contexts, different RDF serializations, or application-specific profiles).

this left intentionally blank

13.2 Notifications

Define notification mechanisms that allow clients to be informed of changes to resources, including subscription models, event formats, and delivery mechanisms.

this left intentionally blank

13.3 Inbox

Define inbox resources with specific semantics within LWS, including message posting, retrieval, and management capabilities for asynchronous communication patterns.

this left intentionally blank

14. Portability Considerations

Describe considerations for ensuring LWS implementations can work across different platforms, environments, and storage backends while maintaining interoperability - and provide affordances to enable change in storage providers

this left intentionally blank

15. Security Considerations

This section is non-normative.

Formal security considerations section covering threat models, security requirements, and implementation guidance for secure LWS deployments.

The recommendations described in Best Current Practice for OAuth 2.0 Security [RFC9700] apply to this specification.

15.1 Transport Security

This section is non-normative.

Transport Layer Security (TLS) is an important mechanism to prevent against tampering, spoofing, and information disclosure. TLS-protected communication can be verified according to [RFC6125]. Implementation security considerations can be found in "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)" [RFC9325].

15.2 Token Security

This section is non-normative.

Bearer tokens and digital credentials are vulnerable to theft and replay. Mitigations include using a reasonably short lifetime, binding tokens to a particular audience, and storing tokens securely.

16. Privacy Considerations

This section is non-normative.

Privacy implications of the LWS Protocol, including data minimization, user consent, and privacy-preserving implementation patterns.

Credentials carry information about users and agents. While digital signatures can protect against tampering, it is possible for clients or third parties to read the values inside an unencrypted credential.

As a result, credential issuers are encouraged to create tokens that contain only the information necessary for authentication or authorization, and to avoid including sensitive attributes unless required.

In general, it is an anti-pattern to write unencrypted credential data to a log. In cases where this is necessary, implementations can truncate or hash a credential to preserve the privacy of the credential subject.

When using pseudonymous identifiers in JWTs, a storage server may still be able to correlate requests from the same agent over time. To preserve user privacy in this case, a client application can request a batch issuance of JWTs where each JWT is used only one time. This does not prevent the storage server from using other information such as similarities in JWT content or originating IP address to correlate requests. When using pseudonymous identifiers, the authorization server will need to be careful not to issue the same identifier more than once.

17. IANA Considerations

This section is non-normative.

17.1 well-known URI Registry

This specification adds the following value to the "Well-Known URIs" registry established by RFC 5785 [RFC5785].

17.2 OAuth Authorization Server Metadata Registry

This specification adds the following value to the "OAuth Authorization Server Metadata" registry established by [RFC8414].

17.3 The application/lws+json Media Type

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.

A. References

A.1 Normative references

[OPENID-CONNECT-CORE]
OpenID Connect Core 1.0 incorporating errata set 2. N. Sakimura; J. Bradley; M. Jones; B. de Medeiros; C. Mortimore. OpenID Foundation. 15 December 2023. Final. URL: https://openid.net/specs/openid-connect-core-1_0.html
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC4918]
HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV). L. Dusseault, Ed. IETF. June 2007. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4918
[RFC5789]
PATCH Method for HTTP. L. Dusseault; J. Snell. IETF. March 2010. Proposed Standard. URL: https://httpwg.org/specs/rfc5789.html
[RFC6585]
Additional HTTP Status Codes. M. Nottingham; R. Fielding. IETF. April 2012. Proposed Standard. URL: https://httpwg.org/specs/rfc6585.html
[RFC6749]
The OAuth 2.0 Authorization Framework. D. Hardt, Ed. IETF. October 2012. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6749
[RFC6750]
The OAuth 2.0 Authorization Framework: Bearer Token Usage. M. Jones; D. Hardt. IETF. October 2012. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6750
[RFC7231]
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. R. Fielding, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7231.html
[RFC7232]
Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests. R. Fielding, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7232.html
[RFC7233]
Hypertext Transfer Protocol (HTTP/1.1): Range Requests. R. Fielding, Ed.; Y. Lafon, Ed.; J. Reschke, Ed. IETF. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7233.html
[RFC7240]
Prefer Header for HTTP. J. Snell. IETF. June 2014. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7240
[RFC7386]
JSON Merge Patch. P. Hoffman; J. Snell. IETF. October 2014. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7386
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8288]
Web Linking. M. Nottingham. IETF. October 2017. Proposed Standard. URL: https://httpwg.org/specs/rfc8288.html
[RFC8414]
OAuth 2.0 Authorization Server Metadata. M. Jones; N. Sakimura; J. Bradley. IETF. June 2018. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8414
[RFC8693]
OAuth 2.0 Token Exchange. M. Jones; A. Nadalin; B. Campbell, Ed.; J. Bradley; C. Mortimore. IETF. January 2020. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8693
[RFC9068]
JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens. V. Bertocci. IETF. October 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9068
[RFC9110]
HTTP Semantics. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
[rfc9112]
HTTP/1.1. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9112.html
[RFC9264]
Linkset: Media Types and a Link Relation Type for Link Sets. E. Wilde; H. Van de Sompel. IETF. July 2022. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9264
[RFC9457]
Problem Details for HTTP APIs. M. Nottingham; E. Wilde; S. Dalal. IETF. July 2023. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9457

A.2 Informative references

[RFC5785]
Defining Well-Known Uniform Resource Identifiers (URIs). M. Nottingham; E. Hammer-Lahav. IETF. April 2010. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc5785
[RFC6125]
Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS). P. Saint-Andre; J. Hodges. IETF. March 2011. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6125
[RFC8259]
The JavaScript Object Notation (JSON) Data Interchange Format. T. Bray, Ed. IETF. December 2017. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC9325]
Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS). Y. Sheffer; P. Saint-Andre; T. Fossati. IETF. November 2022. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc9325
[RFC9700]
Best Current Practice for OAuth 2.0 Security. T. Lodderstedt; J. Bradley; A. Labunets; D. Fett. IETF. January 2025. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc9700