diff --git a/README.md b/README.md index a147b8c..95c4b59 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ To see the most recent HTML rendered version of the specification from this repo - [`authn-saml`](lws10-authn-saml/): SAML 2.0 Authentication Suite - [`authn-ssi-cid`](lws10-authn-ssi-cid): Self-signed Controlled Identifier Authentication Suite - [`authn-ssi-did-key`](lws10-authn-ssi-did-key): Self-signed `did:key` Authentication Suite -- [`notifications`](lws10-notifications/): Notifications +- [`notifications-webhook`](lws10-notifications-webhook/): Notification Suite: Webhooks - [`searchindex`](lws10-searchindex/): Search and Type Index Services diff --git a/lws10-core/Notifications.html b/lws10-core/Notifications.html new file mode 100644 index 0000000..e315188 --- /dev/null +++ b/lws10-core/Notifications.html @@ -0,0 +1,355 @@ +

+ This section defines a mechanism for clients to receive timely updates about changes to + resources managed by a linked web storage server. This specification defines a common + notification data model and a subscription mechanism; specific delivery channels are + described in separate notification suite specifications. +

+ +
+

Notification Discovery

+ +

+ A storage MAY support notifications. A storage that supports notifications MUST + advertise a service object in the service array of its storage description + resource with type equal to NotificationService. +

+ +

+ The service object MUST include a serviceEndpoint property whose value + is the URI of the subscription endpoint. The service object MUST include a + subscriptionType property whose value is an array of strings, each + identifying a supported subscription type. +

+ +

+ Additional properties MAY be present on the service object. +

+ +
+{
+  "@context": ["https://www.w3.org/ns/lws/v1"],
+  "id": "https://storage.example/",
+  "type": "Storage",
+  "service": [{
+    "type": "NotificationService",
+    "serviceEndpoint": "https://notification.example/subscriptions",
+    "subscriptionType": [
+      "WebhookSubscription"
+    ]
+  }]
+}
+  
+ +

+ A server is not required to support all subscription types. The + subscriptionType array advertises exactly which types are available. +

+
+ +
+

Notification Data Model

+ +

+ A notification is represented as a JSON-LD document with a + Notification type. The envelope carries metadata about the delivery + context and wraps an Activity Streams 2.0 [[ACTIVITYSTREAMS-CORE]] [[ACTIVITYSTREAMS-VOCABULARY]] + activity describing the event. +

+ +
+

Envelope Properties

+ +

+ A notification envelope has the following properties: +

+ + + +
+{
+  "@context": [
+    "https://www.w3.org/ns/lws/v1",
+    "https://www.w3.org/ns/activitystreams"
+  ],
+  "type": "Notification",
+  "storage": "https://storage.example/",
+  "activity": {
+    "id": "ec4dcc48-6581-4232-81c9-584525a98693",
+    "type": ["Delete"],
+    "object": {
+      "id": "https://storage.example/alice/notes/shopping.txt",
+      "type": ["DataResource"]
+    },
+    "origin": "https://storage.example/alice/notes/",
+    "published": "2026-03-26T10:30:00Z"
+  }
+}
+    
+
+ +
+

Activity Properties

+ +

+ Each activity object within the activity property MUST conform to the + Activity Streams 2.0 data model and MUST include the following properties: +

+ + + +

+ The following properties are OPTIONAL: +

+ + +
+ +
+

Activity Types

+ +

+ A server MUST support the following Activity Streams 2.0 activity types to + indicate LWS resource changes: +

+ + + +

+ Other activity types MAY also be supported. +

+
+ +
+

Batching Notifications

+ +

+ A server MAY combine multiple activities into a single notification envelope by + providing an array of activity objects as the value of the activity + property. +

+ +
+{
+  "@context": [
+    "https://www.w3.org/ns/lws/v1",
+    "https://www.w3.org/ns/activitystreams"
+  ],
+  "type": "Notification",
+  "storage": "https://storage.example/",
+  "activity": [
+    {
+      "id": "a1b2c3d4-5678-9abc-def0-1234567890ab",
+      "type": ["Create"],
+      "object": {
+        "id": "https://storage.example/alice/notes/meeting.txt",
+        "type": ["DataResource"]
+      },
+      "target": "https://storage.example/alice/notes/",
+      "published": "2026-03-26T10:30:00Z"
+    },
+    {
+      "id": "b2c3d4e5-6789-abcd-ef01-234567890abc",
+      "type": ["Update"],
+      "object": {
+        "id": "https://storage.example/alice/profile",
+        "type": ["DataResource"]
+      },
+      "published": "2026-03-26T10:30:01Z"
+    }
+  ]
+}
+    
+
+
+ +
+

Subscriptions

+ +

+ To receive notifications, a subscriber creates a subscription by sending + an authenticated POST request to the serviceEndpoint of the + NotificationService. The request body MUST conform to the + application/lws+json media type. +

+ +
+

Subscription Request

+ +

+ A subscription request MUST contain the following fields: +

+ + + +

+ A subscription request MAY contain additional fields as required by the specific + subscription type. +

+ +
+POST /subscriptions HTTP/2
+Host: notification.example
+Authorization: Bearer <access-token>
+Content-Type: application/lws+json
+
+{
+  "@context": ["https://www.w3.org/ns/lws/v1"],
+  "type": "WebhookSubscription",
+  "topic": [
+    "https://storage.example/alice/notes/",
+    "https://storage.example/alice/profile"
+  ],
+  "inbox": "https://receiver.example/hooks/lws"
+}
+    
+
+ +
+

Subscription Scope

+ +

+ A subscription to a container is recursive: the subscriber receives + notifications for the container itself and for all resources transitively contained + in that container. A subscription to a data resource applies only to that + individual resource. +

+
+ +
+

Subscription Authorization

+ +

+ A server MUST enforce resource authorization when creating a subscription. + If a subscriber does not have the equivalent of read access to all resources + listed in the topic array, the server MUST reject the subscription + request. +

+ +

+ Authorization MUST also be enforced at notification delivery time. A server MUST + NOT deliver a notification about a resource that the subscriber is + not authorized to read at the time the event occurs. This applies to all resources + within the scope of a subscription, including resources in subcontainers. +

+ +

+ If the subscriber's access to a resource or container within the scope of a + subscription is revoked after the subscription is created, the server + MUST stop delivering notifications for the affected resources. The server SHOULD + NOT terminate the entire subscription unless the subscriber has lost + access to all resources in the topic array. +

+ +

+ Subscription-time authorization verifies that a subscriber has a legitimate + basis for receiving notifications. Delivery-time authorization ensures that + notifications remain consistent with the subscriber's current permissions, + accounting for authorization changes that may occur after the subscription + was created. +

+
+ +
+

Subscription Response

+ +

+ The response to a successful subscription creation request MUST conform to the + application/lws+json media type and MUST contain the following fields: +

+ + +
+ +
+

Subscription Type Identifiers

+

+ Each notification suite MUST be associated with a subscription type string. + The subscription type string is used in the subscriptionType array of a + NotificationService and in the type field of a subscription request. +

+
+
diff --git a/lws10-core/Privacy-Considerations.html b/lws10-core/Privacy-Considerations.html index b7b6445..bf13873 100644 --- a/lws10-core/Privacy-Considerations.html +++ b/lws10-core/Privacy-Considerations.html @@ -41,3 +41,25 @@

Access Requests and Grants

+
+

Notifications

+ + +
+ diff --git a/lws10-core/Security-Considerations.html b/lws10-core/Security-Considerations.html index 21a1f0f..2b90b2a 100644 --- a/lws10-core/Security-Considerations.html +++ b/lws10-core/Security-Considerations.html @@ -56,3 +56,20 @@

Access Requests and Grants

+
+

Notifications

+ + +
+ diff --git a/lws10-core/index.html b/lws10-core/index.html index 01c7427..1c3dead 100644 --- a/lws10-core/index.html +++ b/lws10-core/index.html @@ -199,6 +199,10 @@

Terminology

  • storage controller — an agent that controls all resources in a storage.
  • storage description — an LWS resource that enumerates and describes the storage root along with services and capabilities of a storage. Its representation conforms to the storage description data model.
  • storage root — a container at the root of a containment hierarchy of a storage. The storage root is the only LWS resource that does not have a parent in the LWS containment hierarchy nor a primary resource.
  • +
  • notification — a message describing an event that has occurred on a resource.
  • +
  • subscription — a registration expressing interest in receiving notifications for a given resource or set of resources.
  • +
  • subscriber — the agent that creates a subscription and receives the resulting notifications.
  • +
  • notification suite — a defined delivery mechanism for a concrete channel through which notifications are sent to a subscriber.
  • @@ -279,6 +283,11 @@

    Delete resource

    +
    +

    Notifications

    +
    +
    +

    Access Requests and Grants

    diff --git a/lws10-notifications-webhook/index.html b/lws10-notifications-webhook/index.html new file mode 100644 index 0000000..2d38851 --- /dev/null +++ b/lws10-notifications-webhook/index.html @@ -0,0 +1,398 @@ + + + + + LWS 1.0 Notification Suite: Webhooks + + + + + +
    +

    + This document defines a Webhook-based notification suite for the Linked Web Storage (LWS) + protocol, enabling LWS servers to deliver resource change notifications to registered + endpoints via HTTP POST. +

    +
    +
    +

    + This is an unofficial proposal. +

    +
    + +
    +

    Introduction

    + +

    + The [[!LWS10-CORE|Linked Web Storage]] protocol defines a notification mechanism that + allows clients to subscribe to resource changes and receive updates through various + delivery channels. This document describes the Webhook notification suite — a + server-to-server mechanism whereby the LWS storage server delivers change events to a + registered endpoint via HTTP POST. +

    +
    + +
    + +
    +

    Terminology

    + +

    + The terms "notification", + "subscription", + "subscriber", + "notification suite", + "storage description resource", + and "agent" + are defined by the Linked Web Storage Protocol [[!LWS10-CORE]]. +

    + +

    + The terms "controlled identifier document", "verification method", and "verification + relationship" are defined by Controlled Identifiers 1.0 [[!CID-1.0]]. +

    + +

    + This specification defines the following additional terms: +

    + +
      +
    • + Inbox — a URL controlled by a subscriber or other agent + to which a server delivers notifications via HTTP POST. An inbox is + used whenever the recipient of a notification is a server rather than a client + holding an open connection. +
    • +
    +
    + +
    +

    Creating a Webhook Subscription

    + +

    + When a client creates a webhook notification subscription, the subscription body MUST + include a type field equal to WebhookSubscription. In + addition, a server MUST support the following fields: +

    + +
      +
    • + inbox — REQUIRED. The URI of the inbox to which + notification messages are delivered. +
    • +
    • + expires — OPTIONAL. A datetime value indicating when the + subscription expires. +
    • +
    + +
    +POST /subscriptions HTTP/2
    +Host: notification.example
    +Authorization: Bearer <access-token>
    +Content-Type: application/lws+json
    +
    +{
    +  "@context": ["https://www.w3.org/ns/lws/v1"],
    +  "type": "WebhookSubscription",
    +  "topic": [
    +    "https://storage.example/alice/notes/",
    +    "https://storage.example/alice/profile"
    +  ],
    +  "inbox": "https://receiver.example/hooks/lws",
    +  "expires": "2026-06-09T12:00:00Z"
    +}
    +      
    + +

    + A successful response body has these additional requirements: +

    + +
      +
    • + type — the value of this property MUST be a string equal to + WebhookSubscription. +
    • +
    • + subscription — a URL that can be used to manage the lifecycle of + the subscription. +
    • +
    • + expires — OPTIONAL. A datetime value indicating when the + subscription expires. +
    • +
    + +
    +HTTP/2 200 OK
    +Content-Type: application/lws+json
    +Location: https://notification.example/subscriptions/9e8d7c6b5a4f
    +
    +{
    +  "@context": ["https://www.w3.org/ns/lws/v1"],
    +  "type": "WebhookSubscription",
    +  "subscription": "https://notification.example/subscriptions/9e8d7c6b5a4f",
    +  "expires": "2026-06-09T12:00:00Z"
    +}
    +      
    +
    + +
    +

    Webhook Authentication

    + +

    + When a server delivers a notification to an inbox, the + subscriber needs to verify that the request is authentic. +

    + +

    + A server SHOULD sign each outbound request using HTTP Message Signatures + [[!RFC9421]]. When an inbox receives a signed message, it MUST + verify the signature using the notification server's public key, discoverable via + the storage description resource. +

    + +

    + A server that supports HTTP Message Signatures MUST include the signing key in the + storage description resource. The key MUST be expressed as a verification method + in a verificationMethod array, and MUST be referenced from an + authentication verification relationship, following the Controlled + Identifiers 1.0 [[!CID-1.0]] data model. +

    + +
    +{
    +  "@context": ["https://www.w3.org/ns/lws/v1"],
    +  "id": "https://storage.example/",
    +  "type": "Storage",
    +  "verificationMethod": [{
    +    "id": "https://storage.example/#key-20260320",
    +    "type": "JsonWebKey",
    +    "controller": "https://storage.example/",
    +    "publicKeyJwk": {
    +      "kid": "key-20260320",
    +      "kty": "EC",
    +      "crv": "P-256",
    +      "alg": "ES256",
    +      "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
    +      "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
    +    }
    +  }],
    +  "authentication": ["https://storage.example/#key-20260320"],
    +  "service": [{
    +    "type": "NotificationService",
    +    "serviceEndpoint": "https://notification.example/subscriptions",
    +    "subscriptionType": ["WebhookSubscription"]
    +  }]
    +}
    +      
    + +
    +

    Signature Requirements

    + +

    + A server that signs webhook delivery requests MUST include at least the following + components in the signature base: +

    + +
      +
    • @method — the HTTP method of the request (always POST).
    • +
    • @scheme — prevents downgrade from https to http.
    • +
    • + @authority — the host of the inbox, + preventing delivery to an unintended endpoint. +
    • +
    • + @path — the path component of the inbox URL. +
    • +
    • + content-type — the media type of the request body. +
    • +
    • + content-digest — a digest of the request body, computed + according to [[!RFC9530]]. +
    • +
    + +

    + The Signature-Input field MUST include the created and + keyid parameters. The keyid value MUST correspond to + the id of a key in the verificationMethod array of the + storage description resource. +

    +
    + +
    +

    Signature Verification

    + +

    + To verify a webhook signature, a receiver MUST perform the following steps: +

    + +
      +
    1. + Extract the keyid value from the Signature-Input + field. The keyid value MUST be a URL with a fragment component. +
    2. +
    3. + Remove the fragment component from the keyid URL. The resulting + URL is the storage identifier. +
    4. +
    5. + Dereference the storage identifier to retrieve the storage description resource. + The id property of the top-level document map MUST match the + storage identifier. +
    6. +
    7. + Find the object in the verificationMethod array whose + id property matches either the full keyid URL or the + fragment component of the keyid URL. +
    8. +
    9. + Verify the HTTP Message Signature using the located verification method. +
    10. +
    +
    +
    + +
    +

    Subscription Management

    + +

    + The value of the serviceEndpoint property for a + NotificationService that supports WebhookSubscription + MUST be a URL that supports GET operations to list a subscriber's + active webhook subscriptions. The resulting serialization MUST conform to the requirements + for LWS Containers [[!LWS10-CORE]]. The response SHOULD support LWS Paging. +

    + +

    + Each subscription resource listed in this container MUST support GET + and DELETE operations. A GET request returns the current + state of the subscription. A DELETE request cancels the subscription. +

    +
    + +
    +

    Notification Delivery

    + +

    + The server sends an HTTP POST request to the registered + inbox with the notification envelope as the request body. The + request body MUST conform to the application/lws+json media type. +

    + +
      +
    • + Acknowledgment: A 2xx response indicates successful receipt. +
    • +
    • + Retry: On failure, the server MAY retry delivery. +
    • +
    • + Expiration: After repeated failures, the server MAY deactivate + the subscription. +
    • +
    +
    + +
    +

    Subscription Type Identifier

    + +

    + A Webhook subscription MUST use the WebhookSubscription string + as its subscription type when interacting with the NotificationService. +

    +
    + +
    +

    Security Considerations

    + +
      +
    • + Webhook Verification: Without proper authentication on webhook + deliveries, an attacker could spoof notifications. Subscribers are strongly + encouraged to validate HTTP Message Signatures on all incoming notification requests + using the public key published in the associated storage description resource. +
    • +
    • + Subscription Abuse: Rate limiting and endpoint verification are + suggested to prevent abuse of the subscription mechanism. +
    • +
    • + Signature Replay: A signed webhook request could be captured and + replayed by an attacker. Subscribers are encouraged to check the + created parameter in the Signature-Input field and reject + signatures whose timestamp falls outside a reasonable clock-skew window. +
    • +
    +
    + +
    +

    Privacy Considerations

    + +
      +
    • + Inbox Disclosure: The inbox URL is shared with the + notification server, revealing the existence and location of the subscriber's + receiving endpoint. Subscribers MAY use unique per-subscription inbox URLs + to limit correlation. +
    • +
    +
    + + diff --git a/lws10-notifications/index.html b/lws10-notifications/index.html deleted file mode 100644 index 0b83a96..0000000 --- a/lws10-notifications/index.html +++ /dev/null @@ -1,921 +0,0 @@ - - - - - LWS Notifications - - - - -
    -

    - This document extends the Linked Web Storage (LWS) protocol with a mechanism for clients - to receive timely updates about changes to resources via Webhooks. The specification - defines a common notification data model and is discoverable via the storage description - resource. -

    -
    -
    -

    - This is an unofficial proposal. -

    -
    - -
    -

    Introduction

    - -

    - The [[!LWS-PROTOCOL|Linked Web Storage]] protocol defines a resource-centric storage - system built on HTTP. While the core protocol supports creating, reading, updating, and - deleting resources, it does not define a mechanism for clients to learn about changes - without polling. -

    - -

    - This specification extends LWS with a notification mechanism that allows clients - to subscribe to resource changes and receive updates via Webhooks — a - server-to-server mechanism whereby the LWS storage server delivers change events to a - registered endpoint via HTTP POST. -

    -
    - -
    - -
    -

    Terminology

    - -

    - The terms "storage description resource", "resource manager", "requesting agent", - "container", and "data resource" are defined by [[!LWS-PROTOCOL]]. -

    - -

    - The terms "controlled identifier document", "verification method", and "verification - relationship" are defined by Controlled Identifiers 1.0 [[!CID-1.0]]. -

    - -

    - This specification defines the following additional terms: -

    - -
      -
    • - Notification — a message describing an event that has occurred on - a resource. -
    • -
    • - Subscription — a registration expressing interest in receiving - notifications for a given resource or set of resources. -
    • -
    • - Subscriber — the agent that creates a subscription and - receives the resulting notifications. -
    • -
    • - Inbox — a URL controlled by a subscriber or other agent - to which a server delivers notifications via HTTP POST. An inbox is - used whenever the recipient of a notification is a server rather than a client - holding an open connection. -
    • -
    • - Capability URL — a URL that encodes a subscription scope and - serves as the credential for establishing a notification connection. -
    • -
    -
    - -
    -

    Discovery

    - -

    - A storage MAY support notifications. A storage that supports notifications MUST - advertise a service object in the service array of its storage description - resource with type equal to NotificationService. -

    - -

    - The service object MUST include a serviceEndpoint property whose value - is the URI of the subscription endpoint. The service object MUST include a - subscriptionType property whose value is an array of strings, each - identifying a supported subscription type. -

    - -

    - Additional properties MAY be present on the service object. -

    - -
    -{
    -  "@context": ["https://www.w3.org/ns/lws/v1"],
    -  "id": "https://storage.example/",
    -  "type": "Storage",
    -  "service": [{
    -    "type": "NotificationService",
    -    "serviceEndpoint": "https://notification.example/subscriptions",
    -    "subscriptionType": [
    -      "WebhookSubscription"
    -    ]
    -  }]
    -}
    -      
    - -

    - A server is not required to support all subscription types. The - subscriptionType array advertises exactly which types are available. -

    -
    - -
    -

    Notification Envelope

    - -

    - A notification is represented as a JSON-LD document with a - Notification type. The envelope carries metadata about the delivery - context and wraps an Activity Streams 2.0 [[ACTIVITYSTREAMS-CORE]] [[ACTIVITYSTREAMS-VOCABULARY]] - activity describing the event. -

    - -
    -

    Envelope Properties

    - -

    - A notification envelope has the following properties: -

    - -
      -
    • - type — REQUIRED. The value MUST be the string - Notification. -
    • -
    • - storage — REQUIRED. A URI identifying the LWS storage with - which the notification is associated. -
    • -
    • - activity — REQUIRED. A JSON object or an array of JSON objects, - each conforming to the Activity Streams 2.0 data model, describing the event or - events that occurred. See . -
    • -
    - -
    -{
    -  "@context": [
    -    "https://www.w3.org/ns/lws/v1",
    -    "https://www.w3.org/ns/activitystreams"
    -  ],
    -  "type": "Notification",
    -  "storage": "https://storage.example/",
    -  "activity": {
    -    "id": "ec4dcc48-6581-4232-81c9-584525a98693",
    -    "type": ["Delete"],
    -    "object": {
    -      "id": "https://storage.example/alice/notes/shopping.txt",
    -      "type": ["DataResource"]
    -    },
    -    "origin": "https://storage.example/alice/notes/",
    -    "published": "2026-03-26T10:30:00Z"
    -  }
    -}
    -        
    -
    - -
    -

    Activity Properties

    - -

    - Each activity object within the activity property MUST conform to the - Activity Streams 2.0 data model and MUST include the following properties: -

    - -
      -
    • - id — REQUIRED. A string uniquely identifying the activity. -
    • -
    • - type — REQUIRED. An array of strings containing at least one - Activity Streams 2.0 activity type. -
    • -
    • - object — REQUIRED. A JSON object identifying the resource - that the notification is about. The object MUST include the - following properties: -
        -
      • - id — REQUIRED. The URI of the resource. -
      • -
      • - type — REQUIRED. An array of strings containing at least - one resource type. Values defined by [[!LWS-PROTOCOL]] include - Container and DataResource. Additional type values - MAY be included. -
      • -
      -
    • -
    • - published — REQUIRED. A datetime value conforming to - [[!RFC3339]] indicating when the activity occurred. -
    • -
    - -

    - The following properties are OPTIONAL: -

    - -
      -
    • - actor — a URI identifying the agent that performed the action. -
    • -
    • - target — a URI identifying the container into which the - resource was added. Used with Create activities. -
    • -
    • - origin — a URI identifying the container from which the - resource was removed. Used with Delete activities. -
    • -
    -
    - -
    -

    Activity Types

    - -

    - A server MUST support the following Activity Streams 2.0 activity types to - indicate LWS resource changes: -

    - -
      -
    • - Create — a new resource was created in a container. The - target field indicates the container to which the resource was added. -
    • -
    • - Update — an existing resource's content or metadata was modified. -
    • -
    • - Delete — a resource was removed. The origin field - indicates the container from which the resource was removed. -
    • -
    - -

    - Other activity types MAY also be supported. -

    -
    - -
    -

    Batching Notifications

    - -

    - A server MAY combine multiple activities into a single notification envelope by - providing an array of activity objects as the value of the activity - property. -

    - -
    -{
    -  "@context": [
    -    "https://www.w3.org/ns/lws/v1",
    -    "https://www.w3.org/ns/activitystreams"
    -  ],
    -  "type": "Notification",
    -  "storage": "https://storage.example/",
    -  "activity": [
    -    {
    -      "id": "a1b2c3d4-5678-9abc-def0-1234567890ab",
    -      "type": ["Create"],
    -      "object": {
    -        "id": "https://storage.example/alice/notes/meeting.txt",
    -        "type": ["DataResource"]
    -      },
    -      "target": "https://storage.example/alice/notes/",
    -      "published": "2026-03-26T10:30:00Z"
    -    },
    -    {
    -      "id": "b2c3d4e5-6789-abcd-ef01-234567890abc",
    -      "type": ["Update"],
    -      "object": {
    -        "id": "https://storage.example/alice/profile",
    -        "type": ["DataResource"]
    -      },
    -      "published": "2026-03-26T10:30:01Z"
    -    }
    -  ]
    -}
    -        
    -
    -
    - -
    -

    Subscriptions

    - -

    - To receive notifications, a subscriber creates a subscription by sending - an authenticated POST request to the serviceEndpoint of the - NotificationService. The request body MUST conform to the - application/lws+json media type. -

    - -
    -

    Subscription Request

    - -

    - A subscription request MUST contain the following fields: -

    - -
      -
    • - type — REQUIRED. A string identifying the subscription type. - The value MUST be one of the types listed in the subscriptionType - array of the NotificationService. -
    • -
    • - topic — REQUIRED. An array of URIs identifying the resources - included in the subscription. -
    • -
    - -

    - A subscription request MAY contain additional fields as required by the specific - subscription type. -

    - -
    -POST /subscriptions HTTP/2
    -Host: notification.example
    -Authorization: Bearer <access-token>
    -Content-Type: application/lws+json
    -
    -{
    -  "@context": ["https://www.w3.org/ns/lws/v1"],
    -  "type": "WebhookSubscription",
    -  "topic": [
    -    "https://storage.example/alice/notes/",
    -    "https://storage.example/alice/profile"
    -  ],
    -  "inbox": "https://receiver.example/hooks/lws"
    -}
    -        
    -
    - -
    -

    Subscription Scope

    - -

    - A subscription to a container is recursive: the subscriber receives - notifications for the container itself and for all resources transitively contained - in that container. A subscription to a data resource applies only to that - individual resource. -

    -
    - -
    -

    Subscription Authorization

    - -

    - A server MUST enforce resource authorization when creating a subscription. - If a subscriber does not have the equivalent of read access to all resources - listed in the topic array, the server MUST reject the subscription - request. -

    - -

    - Authorization MUST also be enforced at notification delivery time. A server MUST - NOT deliver a notification about a resource that the subscriber is - not authorized to read at the time the event occurs. This applies to all resources - within the scope of a subscription, including resources in subcontainers. -

    - -

    - If the subscriber's access to a resource or container within the scope of a - subscription is revoked after the subscription is created, the server - MUST stop delivering notifications for the affected resources. The server SHOULD - NOT terminate the entire subscription unless the subscriber has lost - access to all resources in the topic array. -

    - -

    - Subscription-time authorization verifies that a subscriber has a legitimate - basis for receiving notifications. Delivery-time authorization ensures that - notifications remain consistent with the subscriber's current permissions, - accounting for authorization changes that may occur after the subscription - was created. -

    -
    - -
    -

    Subscription Response

    - -

    - The response to a successful subscription creation request MUST conform to the - application/lws+json media type and MUST contain the following fields: -

    - -
      -
    • - type — REQUIRED. A string equal to the subscription type from - the request. -
    • -
    • - subscription — REQUIRED. A URL representing the subscription. -
    • -
    -
    -
    - -
    -

    Webhook Notifications

    - -

    - Webhooks enable server-to-server notification delivery. After a webhook subscription is - created, the LWS storage server delivers notifications to the subscriber's - registered inbox when relevant changes occur. -

    - -
    -

    Creating a Webhook Subscription

    - -

    - When a client creates a webhook notification subscription, the subscription body MUST - include a type field equal to WebhookSubscription. In - addition, a server MUST support the following fields: -

    - -
      -
    • - inbox — REQUIRED. The URI of the inbox to which - notification messages are delivered. -
    • -
    • - expires — OPTIONAL. A datetime value indicating when the - subscription expires. -
    • -
    - -
    -POST /subscriptions HTTP/2
    -Host: notification.example
    -Authorization: Bearer <access-token>
    -Content-Type: application/lws+json
    -
    -{
    -  "@context": ["https://www.w3.org/ns/lws/v1"],
    -  "type": "WebhookSubscription",
    -  "topic": [
    -    "https://storage.example/alice/notes/",
    -    "https://storage.example/alice/profile"
    -  ],
    -  "inbox": "https://receiver.example/hooks/lws",
    -  "expires": "2026-06-09T12:00:00Z"
    -}
    -        
    - -

    - A successful response body has these additional requirements: -

    - -
      -
    • - type — the value of this property MUST be a string equal to - WebhookSubscription. -
    • -
    • - subscription — a URL that can be used to manage the lifecycle of - the subscription. -
    • -
    • - expires — OPTIONAL. A datetime value indicating when the - subscription expires. -
    • -
    - -
    -HTTP/2 200 OK
    -Content-Type: application/lws+json
    -Location: https://notification.example/subscriptions/9e8d7c6b5a4f
    -
    -{
    -  "@context": ["https://www.w3.org/ns/lws/v1"],
    -  "type": "WebhookSubscription",
    -  "subscription": "https://notification.example/subscriptions/9e8d7c6b5a4f",
    -  "expires": "2026-06-09T12:00:00Z"
    -}
    -        
    -
    - -
    -

    Webhook Authentication

    - -

    - When a server delivers a notification to an inbox, the - subscriber needs to verify that the request is authentic. -

    - -

    - A server SHOULD sign each outbound request using HTTP Message Signatures - [[!RFC9421]]. When an inbox receives a signed message, it MUST - verify the signature using the notification server's public key, discoverable via - the storage description resource. -

    - -

    - A server that supports HTTP Message Signatures MUST include the signing key in the - storage description resource. The key MUST be expressed as a verification method - in a verificationMethod array, and MUST be referenced from an - authentication verification relationship, following the Controlled - Identifiers 1.0 [[!CID-1.0]] data model. -

    - -
    -{
    -  "@context": ["https://www.w3.org/ns/lws/v1"],
    -  "id": "https://storage.example/",
    -  "type": "Storage",
    -  "verificationMethod": [{
    -    "id": "https://storage.example/#key-20260320",
    -    "type": "JsonWebKey",
    -    "controller": "https://storage.example/",
    -    "publicKeyJwk": {
    -      "kid": "key-20260320",
    -      "kty": "EC",
    -      "crv": "P-256",
    -      "alg": "ES256",
    -      "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
    -      "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
    -    }
    -  }],
    -  "authentication": ["https://storage.example/#key-20260320"],
    -  "service": [{
    -    "type": "NotificationService",
    -    "serviceEndpoint": "https://notification.example/subscriptions",
    -    "subscriptionType": ["WebhookSubscription"]
    -  }]
    -}
    -        
    - -
    -

    Signature Requirements

    - -

    - A server that signs webhook delivery requests MUST include at least the following - components in the signature base: -

    - -
      -
    • @method — the HTTP method of the request (always POST).
    • -
    • @scheme — prevents downgrade from https to http.
    • -
    • - @authority — the host of the inbox, - preventing delivery to an unintended endpoint. -
    • -
    • - @path — the path component of the inbox URL. -
    • -
    • - content-type — the media type of the request body. -
    • -
    • - content-digest — a digest of the request body, computed - according to [[!RFC9530]]. -
    • -
    - -

    - The Signature-Input field MUST include the created and - keyid parameters. The keyid value MUST correspond to - the id of a key in the verificationMethod array of the - storage description resource. -

    -
    - -
    -

    Signature Verification

    - -

    - To verify a webhook signature, a receiver MUST perform the following steps: -

    - -
      -
    1. - Extract the keyid value from the Signature-Input - field. The keyid value MUST be a URL with a fragment component. -
    2. -
    3. - Remove the fragment component from the keyid URL. The resulting - URL is the storage identifier. -
    4. -
    5. - Dereference the storage identifier to retrieve the storage description resource. - The id property of the top-level document map MUST match the - storage identifier. -
    6. -
    7. - Find the object in the verificationMethod array whose - id property matches either the full keyid URL or the - fragment component of the keyid URL. -
    8. -
    9. - Verify the HTTP Message Signature using the located verification method. -
    10. -
    -
    -
    - -
    -

    Subscription Management

    - -

    - The value of the serviceEndpoint property for a - NotificationService that supports WebhookSubscription - MUST be a URL that supports GET operations to list a subscriber's - active webhook subscriptions. The resulting serialization MUST conform to the requirements - for LWS Containers [[!LWS-PROTOCOL]]. The response SHOULD support LWS Paging. -

    - -

    - Each subscription resource listed in this container MUST support GET - and DELETE operations. A GET request returns the current - state of the subscription. A DELETE request cancels the subscription. -

    -
    - -
    -

    Notification Delivery

    - -

    - The server sends an HTTP POST request to the registered - inbox with the notification envelope as the request body. The - request body MUST conform to the application/lws+json media type. -

    - -
      -
    • - Acknowledgment: A 2xx response indicates successful receipt. -
    • -
    • - Retry: On failure, the server MAY retry delivery. -
    • -
    • - Expiration: After repeated failures, the server MAY deactivate - the subscription. -
    • -
    -
    -
    - -
    -

    Security Considerations

    - -
      -
    • - Webhook Verification: Without proper authentication on webhook - deliveries, an attacker could spoof notifications. Subscribers are strongly - encouraged to validate HTTP Message Signatures on all incoming notification requests - using the public key published in the associated storage description resource. -
    • -
    • - Subscription Abuse: Rate limiting and endpoint verification are - suggested to prevent abuse of the subscription mechanism. -
    • -
    • - Signature Replay: A signed webhook request could be captured and - replayed by an attacker. Subscribers are encouraged to check the - created parameter in the Signature-Input field and reject - signatures whose timestamp falls outside a reasonable clock-skew window. -
    • -
    • - Information Disclosure: Notifications may reveal the existence or - modification patterns of resources. Access control on subscriptions and on individual - notification delivery MUST be consistent with access control on the underlying - resources. -
    • -
    -
    - -
    -

    Privacy Considerations

    - -
      -
    • - Activity Tracking: Notifications inherently reveal when resources - change. Subscribers SHOULD only receive notifications for resources they are - authorized to access. -
    • -
    • - Actor Disclosure: Including the actor property in - notifications reveals who made changes. This may be inappropriate in some contexts. - The actor property SHOULD be omitted by default. Servers MAY make - its inclusion configurable. -
    • -
    • - Timing Analysis: The timing of notifications can reveal usage - patterns even when content is not disclosed. -
    • -
    -
    - -
    -

    Vocabulary

    - -

    - This document defines the following terms in the - https://www.w3.org/ns/lws# namespace: -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    TermURIDescription
    Notificationlws:NotificationNotification envelope type
    NotificationServicelws:NotificationServiceService type for notification discovery
    WebhookSubscriptionlws:WebhookSubscriptionWebhook subscription type
    subscriptionTypelws:subscriptionTypeSupported subscription types on a notification service
    subscriptionlws:subscriptionURL of the subscription resource
    activitylws:activityActivity Streams 2.0 payload within a notification
    topiclws:topicArray of resource URIs included in a subscription
    storagelws:storageURI identifying the LWS storage
    - -

    - This document uses the following terms from external vocabularies, which should be - added to the LWS JSON-LD context. The Activity Streams 2.0 terms are included in - the LWS context with their source IRIs from the - https://www.w3.org/ns/activitystreams# namespace. -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    TermURISource
    Createhttps://www.w3.org/ns/activitystreams#CreateActivity Streams 2.0
    Updatehttps://www.w3.org/ns/activitystreams#UpdateActivity Streams 2.0
    Deletehttps://www.w3.org/ns/activitystreams#DeleteActivity Streams 2.0
    objecthttps://www.w3.org/ns/activitystreams#objectActivity Streams 2.0
    actorhttps://www.w3.org/ns/activitystreams#actorActivity Streams 2.0
    targethttps://www.w3.org/ns/activitystreams#targetActivity Streams 2.0
    originhttps://www.w3.org/ns/activitystreams#originActivity Streams 2.0
    publishedhttps://www.w3.org/ns/activitystreams#publishedActivity Streams 2.0
    verificationMethodhttps://w3id.org/security#verificationMethodControlled Identifiers 1.0
    authenticationhttps://w3id.org/security#authenticationMethodControlled Identifiers 1.0
    controllerhttps://w3id.org/security#controllerControlled Identifiers 1.0
    publicKeyJwkhttps://w3id.org/security#publicKeyJwkControlled Identifiers 1.0
    inboxhttp://www.w3.org/ns/ldp#inboxLinked Data Platform
    expireshttps://schema.org/expiresSchema.org
    -
    - -