From 59f61fe7c80e9650cd769ee08f002a9b8baf55e2 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Sat, 7 Nov 2026 09:00:00 +0000 Subject: [PATCH 1/9] docs(ocm): handle unknown notifications Signed-off-by: Mahdi Baghbani --- IETF-OCM.md | 38 +++++- spec.yaml | 375 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 368 insertions(+), 45 deletions(-) diff --git a/IETF-OCM.md b/IETF-OCM.md index af36fbf..f3ab473 100644 --- a/IETF-OCM.md +++ b/IETF-OCM.md @@ -1409,9 +1409,11 @@ request: ## Fields -* REQUIRED notificationType (string) - it MUST be one of the - registered values listed in the "OCM Notification Types" - registry (see [IANA Considerations](#iana-considerations)). +* REQUIRED notificationType (string) - a Sending Server MUST use one + of the registered values listed in the "OCM Notification Types" + registry (see [IANA Considerations](#iana-considerations)). See + [Receiver Processing](#receiver-processing) for values that a + Receiving Server does not know. * REQUIRED senderDomain (string) - the OCM Server Address of the sender. A Receiving Server SHOULD use this information to verify the HTTP message signature and validate the underlying share or @@ -1434,6 +1436,36 @@ Registry. For each notification type, a specific format MAY be defined for the optional notification object. In the sections below, the base Notification types are detailed along with their specific payload. +## Receiver Processing + +Because the set of Notification types is extensible, a Receiving +Server can receive a `notificationType` value that it does not know, +for instance a type registered after it was implemented, or a type +defined by another implementer. A Receiving Server processes a +notification as follows: + +* If the request body is not a JSON object, or the `notificationType` + field is missing or is not a string, the Receiving Server MUST + reject the request with HTTP 400. +* If the `notificationType` is not known to the Receiving Server, it + SHOULD accept and ignore the notification, and respond with HTTP + 201. It MUST NOT apply the payload requirements of any other + Notification type to it, and it MUST NOT reject it merely because + its type is not known. +* If the `notificationType` is known to the Receiving Server, the + payload MUST be validated according to the definition of that type. + A payload that lacks a field REQUIRED for that type, or carries a + field with an invalid value, MUST NOT be treated as a notification + of an unknown type, and SHOULD be rejected with HTTP 400. For + compatibility with earlier versions of this specification, a + Receiving Server MAY accept a known type in a deprecated layout, + e.g. with the deprecated top-level `providerId` instead of the one + in the `notification` object, provided that it does not guess any + value that the payload omits. +* A Receiving Server that knows a `notificationType` but does not + implement it, for instance a request it never fulfills, MAY + respond with HTTP 501. + ## Share Acceptance and Updating A notification MAY be sent by a recipient to let the provider know that diff --git a/spec.yaml b/spec.yaml index 430848f..bdb853f 100644 --- a/spec.yaml +++ b/spec.yaml @@ -209,6 +209,77 @@ paths: application/json: schema: $ref: "#/components/schemas/NewNotification" + examples: + contactWasRemoved: + summary: A user removed a single contact + value: + notificationType: CONTACT_REMOVED + shareType: user + senderDomain: alice.example.org + notification: + message: Alice removed Bob from her contacts + user: + userId: alice@alice.example.org + targetUserId: bob@bob.example.org + shareWasAccepted: + summary: A recipient accepted a share + value: + notificationType: SHARE_ACCEPTED + resourceType: file + shareType: user + senderDomain: receiver.example.org + notification: + message: Recipient accepted the share + file: + providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 + shareWasAcceptedWithSecret: + summary: A recipient accepted a share, including the optional sharedSecret + value: + notificationType: SHARE_ACCEPTED + resourceType: file + senderDomain: receiver.example.org + notification: + sharedSecret: hfiuhworzwnur98d3wjiwhr + file: + providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 + shareWasUnshared: + summary: A provider removed a share + value: + notificationType: SHARE_UNSHARED + resourceType: file + senderDomain: sender.example.org + notification: + file: + providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 + userLeft: + summary: A user left the sending server + value: + notificationType: USER_REMOVED + shareType: user + senderDomain: alice.example.org + notification: + message: User left the system + user: + userId: alice@alice.example.org + mlsWelcome: + summary: A notification type defined in another specification + value: + notificationType: MLS_WELCOME + shareType: federation + senderDomain: cloud.example.org + notification: + federation: + mlsGroupId: 51dc30ddc473d43a6011e9ebba6ca770 + userId: bob@cloud.example.org + content: base64 MLS welcome + customType: + summary: An implementer-defined notification type + value: + notificationType: EXAMPLE_CUSTOM_EVENT + resourceType: file + senderDomain: sender.example.org + notification: + message: Something happened description: The JSON object with a new notification required: true responses: @@ -219,8 +290,11 @@ paths: the actual notification. "400": description: > - Bad request due to invalid parameters, e.g. when `notificationType` is - invalid, not known or missing. + Bad request due to invalid parameters, e.g. when the body is not a + JSON object, when `notificationType` is missing, or when the payload + of a known notification type is invalid. A notification type that the + receiver does not know is not an error: the receiver SHOULD accept + and ignore it. content: application/json: schema: @@ -1141,49 +1215,266 @@ components: `providerId` of the underlying resource, and in case of `user`, `group`, or `federation` share types, it MUST contain at least the `userId`, `groupId`, or `mlsGroupId` of the underlying recipient, respectively. - example: - legacyShareWasAccepted: - notificationType: SHARE_ACCEPTED - resourceType: file - providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 - notification: - message: Recipient accepted the share - sharedSecret: hfiuhworzwnur98d3wjiwhr - shareWasAccepted: - notificationType: SHARE_ACCEPTED - resourceType: file - shareType: user - senderDomain: sender.example.org - notification: - message: Recipient accepted the share + allOf: + - description: > + A notification MUST include either the `resourceType` or the + `shareType`, or both when relevant. + anyOf: + - required: + - resourceType + - required: + - shareType + - description: > + A CONTACT_REMOVED notification MUST satisfy its specific payload + requirements. + anyOf: + - properties: + notificationType: + not: + enum: + - CONTACT_REMOVED + - $ref: "#/components/schemas/ContactRemovedNotification" + - anyOf: + - $ref: "#/components/schemas/ShareStateNotification" + - $ref: "#/components/schemas/ReshareRequestNotification" + - $ref: "#/components/schemas/ShareRequestNotification" + - $ref: "#/components/schemas/UserRemovedNotification" + - $ref: "#/components/schemas/GroupRemovedNotification" + - $ref: "#/components/schemas/ContactRemovedNotification" + - $ref: "#/components/schemas/NotificationOfOtherType" + ShareStateNotification: + type: object + description: > + Payload requirements of the SHARE_ACCEPTED, SHARE_DECLINED, + SHARE_UNSHARED and SHARE_CHANGE_PERMISSION notifications. + required: + - notificationType + - resourceType + - notification + properties: + notificationType: + type: string + enum: + - SHARE_ACCEPTED + - SHARE_DECLINED + - SHARE_UNSHARED + - SHARE_CHANGE_PERMISSION + notification: + type: object + required: + - file + properties: + file: + type: object + required: + - providerId + properties: + providerId: + type: string + description: > + The identifier assigned by the Sending Server to the + underlying share in a previous Share Creation Notification. + permissions: + type: array + items: + type: string + ReshareRequestNotification: + type: object + description: Payload requirements of the REQUEST_RESHARE notification. + required: + - notificationType + - resourceType + - notification + properties: + notificationType: + type: string + enum: + - REQUEST_RESHARE + notification: + type: object + required: + - file + properties: + file: + type: object + required: + - providerId + - shareWith + properties: + providerId: + type: string + shareWith: + type: string + permissions: + type: array + items: + type: string + ShareRequestNotification: + type: object + description: > + Payload requirements of the REQUEST_SHARE notification, which + omits the `shareType`. + required: + - notificationType + - resourceType + - notification + properties: + notificationType: + type: string + enum: + - REQUEST_SHARE + notification: + type: object + required: + - file + properties: file: - providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 - contactWasRemoved: - notificationType: CONTACT_REMOVED - shareType: user - senderDomain: alice.example.org - notification: - message: User is not a trusted contact any longer + type: object + required: + - owner + - shareWith + - shareId + - permissions + properties: + owner: + type: string + shareWith: + type: string + shareId: + type: string + permissions: + type: array + items: + type: string + not: + required: + - shareType + UserRemovedNotification: + type: object + description: > + Payload requirements of the USER_REMOVED notification, which + omits the `resourceType`. + required: + - notificationType + - shareType + - notification + properties: + notificationType: + type: string + enum: + - USER_REMOVED + notification: + type: object + required: + - user + properties: user: - userId: alice@alice.example.org - targetUserId: bob@bob.example.org - userLeft: - notificationType: USER_REMOVED - shareType: user - senderDomain: alice.example.org - notification: - message: User left the system + type: object + required: + - userId + properties: + userId: + type: string + not: + required: + - resourceType + GroupRemovedNotification: + type: object + description: > + Payload requirements of the GROUP_REMOVED notification, which + omits the `resourceType`. + required: + - notificationType + - shareType + - notification + properties: + notificationType: + type: string + enum: + - GROUP_REMOVED + notification: + type: object + required: + - group + properties: + group: + type: object + required: + - groupId + properties: + groupId: + type: string + not: + required: + - resourceType + NotificationOfOtherType: + type: object + description: > + Any notification type other than those with specific payload + requirements above, e.g. a newly registered or implementer-defined + type. Such notifications only need to satisfy the generic envelope, + and a receiver that does not know their type SHOULD accept and + ignore them. A notification of a known type with an invalid payload + cannot match this schema. + properties: + notificationType: + type: string + not: + enum: + - SHARE_ACCEPTED + - SHARE_DECLINED + - SHARE_UNSHARED + - SHARE_CHANGE_PERMISSION + - REQUEST_RESHARE + - REQUEST_SHARE + - USER_REMOVED + - CONTACT_REMOVED + - GROUP_REMOVED + ContactRemovedNotification: + type: object + description: > + Payload requirements of the CONTACT_REMOVED notification, which + omits the `resourceType` and identifies both users of the removed + contact. + required: + - notificationType + - shareType + - notification + properties: + notificationType: + type: string + enum: + - CONTACT_REMOVED + shareType: + type: string + enum: + - user + notification: + type: object + required: + - user + properties: user: - userId: alice@alice.example.org - mlsWelcome: - notificationType: MLS_WELCOME - shareType: federation - senderDomain: cloud.example.org - notification: - federation: - mlsGroupId: 51dc30ddc473d43a6011e9ebba6ca770 - userId: bob@cloud.example.org - content: base64 MLS welcome + type: object + required: + - userId + - targetUserId + properties: + userId: + description: > + OCM Address of the user of the sending server who removed + the contact. Its host part is the `senderDomain`. + allOf: + - $ref: "#/components/schemas/OCMAddress" + targetUserId: + description: > + OCM Address of the user of the receiving server who was + removed from the contacts. + allOf: + - $ref: "#/components/schemas/OCMAddress" + not: + required: + - resourceType OCMServerAddress: type: string minLength: 1 From 1ab267020262dbe587c34294ac0f38d4179e9299 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Sat, 7 Nov 2026 13:00:00 +0000 Subject: [PATCH 2/9] docs(ocm): constrain notification fields Signed-off-by: Mahdi Baghbani --- spec.yaml | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/spec.yaml b/spec.yaml index bdb853f..a88744b 100644 --- a/spec.yaml +++ b/spec.yaml @@ -1271,13 +1271,14 @@ components: properties: providerId: type: string + minLength: 1 description: > The identifier assigned by the Sending Server to the underlying share in a previous Share Creation Notification. permissions: type: array items: - type: string + $ref: "#/components/schemas/NotificationPermission" ReshareRequestNotification: type: object description: Payload requirements of the REQUEST_RESHARE notification. @@ -1303,12 +1304,13 @@ components: properties: providerId: type: string + minLength: 1 shareWith: - type: string + $ref: "#/components/schemas/OCMAddress" permissions: type: array items: - type: string + $ref: "#/components/schemas/NotificationPermission" ShareRequestNotification: type: object description: > @@ -1337,15 +1339,16 @@ components: - permissions properties: owner: - type: string + $ref: "#/components/schemas/OCMAddress" shareWith: - type: string + $ref: "#/components/schemas/OCMAddress" shareId: type: string + minLength: 1 permissions: type: array items: - type: string + $ref: "#/components/schemas/NotificationPermission" not: required: - shareType @@ -1374,7 +1377,7 @@ components: - userId properties: userId: - type: string + $ref: "#/components/schemas/OCMAddress" not: required: - resourceType @@ -1404,6 +1407,7 @@ components: properties: groupId: type: string + minLength: 1 not: required: - resourceType @@ -1484,6 +1488,15 @@ components: fragment. Compare the complete value after lowercasing, preserving explicit ports and all other spelling. example: cloud.example.org:8443 + NotificationPermission: + type: string + description: > + A permission value as defined for the `webdav` protocol of a Share + Creation Notification. + enum: + - read + - write + - share OCMAddress: type: string minLength: 1 From fe9155df21080993ba8d2b28d76b64238fd3c9cc Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Sat, 7 Nov 2026 17:00:00 +0000 Subject: [PATCH 3/9] docs(ocm): validate notification envelopes Signed-off-by: Mahdi Baghbani --- IETF-OCM.md | 17 ++++++++--------- spec.yaml | 8 +++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/IETF-OCM.md b/IETF-OCM.md index f3ab473..6f62b0a 100644 --- a/IETF-OCM.md +++ b/IETF-OCM.md @@ -1444,9 +1444,11 @@ for instance a type registered after it was implemented, or a type defined by another implementer. A Receiving Server processes a notification as follows: -* If the request body is not a JSON object, or the `notificationType` - field is missing or is not a string, the Receiving Server MUST - reject the request with HTTP 400. +* If the request body is not a JSON object, the `notificationType` + field is missing or is not a non-blank string, the `senderDomain` + is not a FQDN (see [Fields](#fields)), or neither a non-empty + `resourceType` nor a non-empty `shareType` is present, the Receiving + Server MUST reject the request with HTTP 400. * If the `notificationType` is not known to the Receiving Server, it SHOULD accept and ignore the notification, and respond with HTTP 201. It MUST NOT apply the payload requirements of any other @@ -1456,12 +1458,9 @@ notification as follows: payload MUST be validated according to the definition of that type. A payload that lacks a field REQUIRED for that type, or carries a field with an invalid value, MUST NOT be treated as a notification - of an unknown type, and SHOULD be rejected with HTTP 400. For - compatibility with earlier versions of this specification, a - Receiving Server MAY accept a known type in a deprecated layout, - e.g. with the deprecated top-level `providerId` instead of the one - in the `notification` object, provided that it does not guess any - value that the payload omits. + of an unknown type, and SHOULD be rejected with HTTP 400. The + deprecated top-level `providerId` never replaces a field required in + the `notification` object. * A Receiving Server that knows a `notificationType` but does not implement it, for instance a request it never fulfills, MAY respond with HTTP 501. diff --git a/spec.yaml b/spec.yaml index a88744b..dd7fa94 100644 --- a/spec.yaml +++ b/spec.yaml @@ -291,8 +291,9 @@ paths: "400": description: > Bad request due to invalid parameters, e.g. when the body is not a - JSON object, when `notificationType` is missing, or when the payload - of a known notification type is invalid. A notification type that the + JSON object, when `notificationType`, `senderDomain` or both + `resourceType` and `shareType` are missing or invalid, or when the + payload of a known notification type is invalid. A notification type that the receiver does not know is not an error: the receiver SHOULD accept and ignore it. content: @@ -1195,7 +1196,8 @@ components: type: string description: > Optional unique identifier of the underlying resource. This property - is now deprecated, in favor of including it in the notification object. + is now deprecated, in favor of including it in the notification object, + and it never replaces a field required there. notification: type: object description: > From a3bec947e28ef2342a6bc1b57079a55af93fb5a7 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Sun, 8 Nov 2026 10:00:00 +0000 Subject: [PATCH 4/9] docs(ocm): validate senders and notification types Signed-off-by: Mahdi Baghbani --- IETF-OCM.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/IETF-OCM.md b/IETF-OCM.md index 6f62b0a..e06e650 100644 --- a/IETF-OCM.md +++ b/IETF-OCM.md @@ -1446,9 +1446,13 @@ notification as follows: * If the request body is not a JSON object, the `notificationType` field is missing or is not a non-blank string, the `senderDomain` - is not a FQDN (see [Fields](#fields)), or neither a non-empty + is not a valid `host [":" port]` (see [Fields](#fields)), or + neither a non-empty `resourceType` nor a non-empty `shareType` is present, the Receiving Server MUST reject the request with HTTP 400. +* A non-blank string has at least one character that is not Unicode + White_Space. The `notificationType` is compared exactly as sent; it + is not trimmed or case folded. * If the `notificationType` is not known to the Receiving Server, it SHOULD accept and ignore the notification, and respond with HTTP 201. It MUST NOT apply the payload requirements of any other From 882b433075ce409fe8f351e70f559209a5b9ded6 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Sun, 8 Nov 2026 16:00:00 +0000 Subject: [PATCH 5/9] docs(ocm): align contact notification schemas Signed-off-by: Mahdi Baghbani --- spec.yaml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/spec.yaml b/spec.yaml index dd7fa94..a7b3c6c 100644 --- a/spec.yaml +++ b/spec.yaml @@ -319,7 +319,8 @@ paths: "501": description: > The receiver doesn't support notifications, the resource type is not - supported. + supported, or the receiver knows the notification type but does not + implement it. content: application/json: schema: @@ -1160,6 +1161,9 @@ components: uri: extuser@cloud.example.org:/7c084226-d9a1-11e6-bf26-cec0c932ce01 NewNotification: type: object + description: > + Known notification types must satisfy their specific payload constraints. + Other types satisfy only the generic envelope and are ignored. required: - notificationType - senderDomain @@ -1226,16 +1230,6 @@ components: - resourceType - required: - shareType - - description: > - A CONTACT_REMOVED notification MUST satisfy its specific payload - requirements. - anyOf: - - properties: - notificationType: - not: - enum: - - CONTACT_REMOVED - - $ref: "#/components/schemas/ContactRemovedNotification" - anyOf: - $ref: "#/components/schemas/ShareStateNotification" - $ref: "#/components/schemas/ReshareRequestNotification" From d9c0f436fb485a8b9f93797ce50830f4850a6d78 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Mon, 9 Nov 2026 09:00:00 +0000 Subject: [PATCH 6/9] docs(ocm): validate departure payloads Signed-off-by: Mahdi Baghbani --- IETF-OCM.md | 7 +++---- spec.yaml | 11 +++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/IETF-OCM.md b/IETF-OCM.md index e06e650..e157798 100644 --- a/IETF-OCM.md +++ b/IETF-OCM.md @@ -1593,10 +1593,9 @@ shareType matched it. The recipient of such notification SHOULD reciprocally remove that peer from the list of trusted users, along with any related shares. -For these cases, a notification payload is to be formed such that the -`resourceType` MUST be omitted, the `shareType` is set to the affected -shareType being removed, such as `user` or `group`, and the -`notificationType` MUST be one of: +The `resourceType` MUST be omitted. The `shareType` MUST be `group` +for "GROUP_REMOVED" and `user` for "CONTACT_REMOVED" or "USER_REMOVED". +The `notificationType` MUST be one of: - "CONTACT_REMOVED", to inform that a single user contact was removed from the list of trusted contacts by the peer user. - "USER_REMOVED", to inform that a user left or was removed from the diff --git a/spec.yaml b/spec.yaml index a7b3c6c..36fa86f 100644 --- a/spec.yaml +++ b/spec.yaml @@ -1362,6 +1362,10 @@ components: type: string enum: - USER_REMOVED + shareType: + type: string + enum: + - user notification: type: object required: @@ -1374,6 +1378,9 @@ components: properties: userId: $ref: "#/components/schemas/OCMAddress" + not: + required: + - targetUserId not: required: - resourceType @@ -1391,6 +1398,10 @@ components: type: string enum: - GROUP_REMOVED + shareType: + type: string + enum: + - group notification: type: object required: From ad78034ddc1547d89f9f8c6bdf212fc777491949 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Mon, 9 Nov 2026 13:00:00 +0000 Subject: [PATCH 7/9] docs(ocm): clarify notification processing Signed-off-by: Mahdi Baghbani --- IETF-OCM.md | 76 ++++------ spec.yaml | 418 +++++++--------------------------------------------- 2 files changed, 80 insertions(+), 414 deletions(-) diff --git a/IETF-OCM.md b/IETF-OCM.md index e157798..61cc978 100644 --- a/IETF-OCM.md +++ b/IETF-OCM.md @@ -1409,11 +1409,10 @@ request: ## Fields -* REQUIRED notificationType (string) - a Sending Server MUST use one - of the registered values listed in the "OCM Notification Types" - registry (see [IANA Considerations](#iana-considerations)). See - [Receiver Processing](#receiver-processing) for values that a - Receiving Server does not know. +* REQUIRED notificationType (string) - a non-empty string, compared + exactly as sent. A Sending Server MUST use a value in the "OCM + Notification Types" registry (see [IANA + Considerations](#iana-considerations)). * REQUIRED senderDomain (string) - the OCM Server Address of the sender. A Receiving Server SHOULD use this information to verify the HTTP message signature and validate the underlying share or @@ -1422,9 +1421,6 @@ request: notification is about (e.g., `file`). * OPTIONAL shareType (string) - the type of recipient this notification is about (e.g., `user`). -* OPTIONAL providerId (string) - the identifier assigned by the - Sending Server to the underlying share, if applicable. This - field is _deprecated_ and SHOULD NOT be used. * OPTIONAL notification (object) - optional additional parameters, depending on the notification and the resource type. @@ -1438,36 +1434,23 @@ Notification types are detailed along with their specific payload. ## Receiver Processing -Because the set of Notification types is extensible, a Receiving -Server can receive a `notificationType` value that it does not know, -for instance a type registered after it was implemented, or a type -defined by another implementer. A Receiving Server processes a -notification as follows: - -* If the request body is not a JSON object, the `notificationType` - field is missing or is not a non-blank string, the `senderDomain` - is not a valid `host [":" port]` (see [Fields](#fields)), or - neither a non-empty - `resourceType` nor a non-empty `shareType` is present, the Receiving - Server MUST reject the request with HTTP 400. -* A non-blank string has at least one character that is not Unicode - White_Space. The `notificationType` is compared exactly as sent; it - is not trimmed or case folded. -* If the `notificationType` is not known to the Receiving Server, it - SHOULD accept and ignore the notification, and respond with HTTP - 201. It MUST NOT apply the payload requirements of any other - Notification type to it, and it MUST NOT reject it merely because - its type is not known. -* If the `notificationType` is known to the Receiving Server, the - payload MUST be validated according to the definition of that type. - A payload that lacks a field REQUIRED for that type, or carries a - field with an invalid value, MUST NOT be treated as a notification - of an unknown type, and SHOULD be rejected with HTTP 400. The - deprecated top-level `providerId` never replaces a field required in - the `notification` object. -* A Receiving Server that knows a `notificationType` but does not - implement it, for instance a request it never fulfills, MAY - respond with HTTP 501. +Before applying a notification, the receiver MUST validate its envelope, +payload and identity bindings. The OpenAPI schemas express structural +constraints; address syntax and peer bindings also require validation. + +* A malformed envelope MUST receive HTTP 400. It requires a non-empty + `notificationType`, a valid `senderDomain`, and at least one of + `resourceType` or `shareType` as a non-empty string. Optional fields, + when present, MUST have their defined types. +* A receiver SHOULD accept and ignore a valid unknown notification + type. It MUST NOT reject it merely because the type is unknown, or + apply another type's payload requirements to it. +* A known type MUST satisfy its defined payload requirements. Malformed + known notifications MUST receive HTTP 400 and MUST NOT pass through + the unknown-type path. Deprecated fields cannot replace required + payload fields. +* A receiver MAY return HTTP 501 for a known, valid notification type + whose operation it does not implement. ## Share Acceptance and Updating @@ -1593,9 +1576,10 @@ shareType matched it. The recipient of such notification SHOULD reciprocally remove that peer from the list of trusted users, along with any related shares. -The `resourceType` MUST be omitted. The `shareType` MUST be `group` -for "GROUP_REMOVED" and `user` for "CONTACT_REMOVED" or "USER_REMOVED". -The `notificationType` MUST be one of: +For these cases, a notification payload is to be formed such that the +`resourceType` MUST be omitted, the `shareType` is set to the affected +shareType being removed, such as `user` or `group`, and the +`notificationType` MUST be one of: - "CONTACT_REMOVED", to inform that a single user contact was removed from the list of trusted contacts by the peer user. - "USER_REMOVED", to inform that a user left or was removed from the @@ -2125,12 +2109,10 @@ the values that MAY appear in the "notificationType" field of an OCM notification sent to the "/notifications" endpoint (see [Notifications](#notifications)). -The "Scope" field indicates whether the notification refers to a -Resource, in which case the "providerId" field is REQUIRED in the -payload, or to a Recipient, i.e. to the shareType in a -[Share Creation Notification](#share-creation-notification), in which -case a corresponding identifier such as "userId" is REQUIRED in the -payload. +The "Scope" field indicates whether the notification concerns a +Resource or a Recipient. The notification type defines its required +payload: existing-share events use `file.providerId`, whereas +"REQUEST_SHARE" uses the request fields defined above. Registration Policy: Specification Required [RFC8126] diff --git a/spec.yaml b/spec.yaml index 36fa86f..9cc8941 100644 --- a/spec.yaml +++ b/spec.yaml @@ -209,77 +209,6 @@ paths: application/json: schema: $ref: "#/components/schemas/NewNotification" - examples: - contactWasRemoved: - summary: A user removed a single contact - value: - notificationType: CONTACT_REMOVED - shareType: user - senderDomain: alice.example.org - notification: - message: Alice removed Bob from her contacts - user: - userId: alice@alice.example.org - targetUserId: bob@bob.example.org - shareWasAccepted: - summary: A recipient accepted a share - value: - notificationType: SHARE_ACCEPTED - resourceType: file - shareType: user - senderDomain: receiver.example.org - notification: - message: Recipient accepted the share - file: - providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 - shareWasAcceptedWithSecret: - summary: A recipient accepted a share, including the optional sharedSecret - value: - notificationType: SHARE_ACCEPTED - resourceType: file - senderDomain: receiver.example.org - notification: - sharedSecret: hfiuhworzwnur98d3wjiwhr - file: - providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 - shareWasUnshared: - summary: A provider removed a share - value: - notificationType: SHARE_UNSHARED - resourceType: file - senderDomain: sender.example.org - notification: - file: - providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 - userLeft: - summary: A user left the sending server - value: - notificationType: USER_REMOVED - shareType: user - senderDomain: alice.example.org - notification: - message: User left the system - user: - userId: alice@alice.example.org - mlsWelcome: - summary: A notification type defined in another specification - value: - notificationType: MLS_WELCOME - shareType: federation - senderDomain: cloud.example.org - notification: - federation: - mlsGroupId: 51dc30ddc473d43a6011e9ebba6ca770 - userId: bob@cloud.example.org - content: base64 MLS welcome - customType: - summary: An implementer-defined notification type - value: - notificationType: EXAMPLE_CUSTOM_EVENT - resourceType: file - senderDomain: sender.example.org - notification: - message: Something happened description: The JSON object with a new notification required: true responses: @@ -290,12 +219,8 @@ paths: the actual notification. "400": description: > - Bad request due to invalid parameters, e.g. when the body is not a - JSON object, when `notificationType`, `senderDomain` or both - `resourceType` and `shareType` are missing or invalid, or when the - payload of a known notification type is invalid. A notification type that the - receiver does not know is not an error: the receiver SHOULD accept - and ignore it. + Bad request due to invalid parameters, e.g. when `notificationType` is + invalid, not known or missing. content: application/json: schema: @@ -319,8 +244,7 @@ paths: "501": description: > The receiver doesn't support notifications, the resource type is not - supported, or the receiver knows the notification type but does not - implement it. + supported. content: application/json: schema: @@ -1161,18 +1085,17 @@ components: uri: extuser@cloud.example.org:/7c084226-d9a1-11e6-bf26-cec0c932ce01 NewNotification: type: object - description: > - Known notification types must satisfy their specific payload constraints. - Other types satisfy only the generic envelope and are ignored. required: - notificationType - senderDomain properties: notificationType: type: string + minLength: 1 description: > - A notification type that is understandable for both humans and - machines, providing information about an event. + A non-empty notification type, compared exactly as sent. + A receiver accepts and ignores valid unknown types; known + types must satisfy their own payload requirements. Any value registered in the OCM IANA Registry for notification types MAY be used here. Implementers MAY define additional custom types, provided that they are registered in the OCM IANA Registry. @@ -1184,6 +1107,7 @@ components: key material and verify the HTTP Message Signature. resourceType: type: string + minLength: 1 description: > Resource type, according to the OCM IANA Registry for resource types. E.g. file, folder, calendar, contact, etc. Implementers MAY define @@ -1191,17 +1115,12 @@ components: respective OCM IANA Registry. shareType: type: string + minLength: 1 description: > Share type, according to the OCM IANA Registry for share types. E.g. user, group, federation, etc. Implementers MAY define additional custom types, provided that they are registered in the respective OCM IANA Registry. - providerId: - type: string - description: > - Optional unique identifier of the underlying resource. This property - is now deprecated, in favor of including it in the notification object, - and it never replaces a field required there. notification: type: object description: > @@ -1215,277 +1134,51 @@ components: additionalProperties: type: object description: > - This object MUST be keyed with the resource type or share type of this - notification. It contains its payload and it can vary according to the - implementers. In case of `file` resources, it MUST contain at least the - `providerId` of the underlying resource, and in case of `user`, `group`, - or `federation` share types, it MUST contain at least the `userId`, - `groupId`, or `mlsGroupId` of the underlying recipient, respectively. - allOf: - - description: > - A notification MUST include either the `resourceType` or the - `shareType`, or both when relevant. - anyOf: - - required: - - resourceType - - required: - - shareType - - anyOf: - - $ref: "#/components/schemas/ShareStateNotification" - - $ref: "#/components/schemas/ReshareRequestNotification" - - $ref: "#/components/schemas/ShareRequestNotification" - - $ref: "#/components/schemas/UserRemovedNotification" - - $ref: "#/components/schemas/GroupRemovedNotification" - - $ref: "#/components/schemas/ContactRemovedNotification" - - $ref: "#/components/schemas/NotificationOfOtherType" - ShareStateNotification: - type: object - description: > - Payload requirements of the SHARE_ACCEPTED, SHARE_DECLINED, - SHARE_UNSHARED and SHARE_CHANGE_PERMISSION notifications. - required: - - notificationType - - resourceType - - notification - properties: - notificationType: - type: string - enum: - - SHARE_ACCEPTED - - SHARE_DECLINED - - SHARE_UNSHARED - - SHARE_CHANGE_PERMISSION - notification: - type: object - required: - - file - properties: - file: - type: object - required: - - providerId - properties: - providerId: - type: string - minLength: 1 - description: > - The identifier assigned by the Sending Server to the - underlying share in a previous Share Creation Notification. - permissions: - type: array - items: - $ref: "#/components/schemas/NotificationPermission" - ReshareRequestNotification: - type: object - description: Payload requirements of the REQUEST_RESHARE notification. - required: - - notificationType - - resourceType - - notification - properties: - notificationType: - type: string - enum: - - REQUEST_RESHARE - notification: - type: object - required: - - file - properties: - file: - type: object - required: - - providerId - - shareWith - properties: - providerId: - type: string - minLength: 1 - shareWith: - $ref: "#/components/schemas/OCMAddress" - permissions: - type: array - items: - $ref: "#/components/schemas/NotificationPermission" - ShareRequestNotification: - type: object - description: > - Payload requirements of the REQUEST_SHARE notification, which - omits the `shareType`. - required: - - notificationType - - resourceType - - notification - properties: - notificationType: - type: string - enum: - - REQUEST_SHARE - notification: - type: object - required: - - file - properties: + Additional payload objects keyed by resource type or share type. + Required fields are defined by the notification type. + example: + legacyShareWasAccepted: + notificationType: SHARE_ACCEPTED + resourceType: file + providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 + notification: + message: Recipient accepted the share + sharedSecret: hfiuhworzwnur98d3wjiwhr + shareWasAccepted: + notificationType: SHARE_ACCEPTED + resourceType: file + shareType: user + senderDomain: sender.example.org + notification: + message: Recipient accepted the share file: - type: object - required: - - owner - - shareWith - - shareId - - permissions - properties: - owner: - $ref: "#/components/schemas/OCMAddress" - shareWith: - $ref: "#/components/schemas/OCMAddress" - shareId: - type: string - minLength: 1 - permissions: - type: array - items: - $ref: "#/components/schemas/NotificationPermission" - not: - required: - - shareType - UserRemovedNotification: - type: object - description: > - Payload requirements of the USER_REMOVED notification, which - omits the `resourceType`. - required: - - notificationType - - shareType - - notification - properties: - notificationType: - type: string - enum: - - USER_REMOVED - shareType: - type: string - enum: - - user - notification: - type: object - required: - - user - properties: + providerId: 7c084226-d9a1-11e6-bf26-cec0c932ce01 + contactWasRemoved: + notificationType: CONTACT_REMOVED + shareType: user + senderDomain: alice.example.org + notification: + message: User is not a trusted contact any longer user: - type: object - required: - - userId - properties: - userId: - $ref: "#/components/schemas/OCMAddress" - not: - required: - - targetUserId - not: - required: - - resourceType - GroupRemovedNotification: - type: object - description: > - Payload requirements of the GROUP_REMOVED notification, which - omits the `resourceType`. - required: - - notificationType - - shareType - - notification - properties: - notificationType: - type: string - enum: - - GROUP_REMOVED - shareType: - type: string - enum: - - group - notification: - type: object - required: - - group - properties: - group: - type: object - required: - - groupId - properties: - groupId: - type: string - minLength: 1 - not: - required: - - resourceType - NotificationOfOtherType: - type: object - description: > - Any notification type other than those with specific payload - requirements above, e.g. a newly registered or implementer-defined - type. Such notifications only need to satisfy the generic envelope, - and a receiver that does not know their type SHOULD accept and - ignore them. A notification of a known type with an invalid payload - cannot match this schema. - properties: - notificationType: - type: string - not: - enum: - - SHARE_ACCEPTED - - SHARE_DECLINED - - SHARE_UNSHARED - - SHARE_CHANGE_PERMISSION - - REQUEST_RESHARE - - REQUEST_SHARE - - USER_REMOVED - - CONTACT_REMOVED - - GROUP_REMOVED - ContactRemovedNotification: - type: object - description: > - Payload requirements of the CONTACT_REMOVED notification, which - omits the `resourceType` and identifies both users of the removed - contact. - required: - - notificationType - - shareType - - notification - properties: - notificationType: - type: string - enum: - - CONTACT_REMOVED - shareType: - type: string - enum: - - user - notification: - type: object - required: - - user - properties: + userId: alice@alice.example.org + targetUserId: bob@bob.example.org + userLeft: + notificationType: USER_REMOVED + shareType: user + senderDomain: alice.example.org + notification: + message: User left the system user: - type: object - required: - - userId - - targetUserId - properties: - userId: - description: > - OCM Address of the user of the sending server who removed - the contact. Its host part is the `senderDomain`. - allOf: - - $ref: "#/components/schemas/OCMAddress" - targetUserId: - description: > - OCM Address of the user of the receiving server who was - removed from the contacts. - allOf: - - $ref: "#/components/schemas/OCMAddress" - not: - required: - - resourceType + userId: alice@alice.example.org + mlsWelcome: + notificationType: MLS_WELCOME + shareType: federation + senderDomain: cloud.example.org + notification: + federation: + mlsGroupId: 51dc30ddc473d43a6011e9ebba6ca770 + userId: bob@cloud.example.org + content: base64 MLS welcome OCMServerAddress: type: string minLength: 1 @@ -1495,15 +1188,6 @@ components: fragment. Compare the complete value after lowercasing, preserving explicit ports and all other spelling. example: cloud.example.org:8443 - NotificationPermission: - type: string - description: > - A permission value as defined for the `webdav` protocol of a Share - Creation Notification. - enum: - - read - - write - - share OCMAddress: type: string minLength: 1 From 4b106870ecd3848755427e9f1f74aa550a5eb652 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Mon, 9 Nov 2026 17:00:00 +0000 Subject: [PATCH 8/9] docs(ocm): align notification error descriptions Signed-off-by: Mahdi Baghbani --- spec.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec.yaml b/spec.yaml index 9cc8941..7b2f16e 100644 --- a/spec.yaml +++ b/spec.yaml @@ -219,8 +219,8 @@ paths: the actual notification. "400": description: > - Bad request due to invalid parameters, e.g. when `notificationType` is - invalid, not known or missing. + Invalid notification envelope or malformed payload for a known + notification type. content: application/json: schema: @@ -243,8 +243,8 @@ paths: does not have rights to access it. "501": description: > - The receiver doesn't support notifications, the resource type is not - supported. + Notifications or the requested operation are not implemented + by the receiver. content: application/json: schema: From a5c8826b6ab019806fa2b590fcaa8852e41f1c86 Mon Sep 17 00:00:00 2001 From: Mahdi Baghbani Date: Mon, 9 Nov 2026 18:00:00 +0000 Subject: [PATCH 9/9] docs(ocm): preserve deprecated providerId Signed-off-by: Mahdi Baghbani --- IETF-OCM.md | 22 +++++++++------------- spec.yaml | 7 +++++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/IETF-OCM.md b/IETF-OCM.md index 61cc978..e8697ed 100644 --- a/IETF-OCM.md +++ b/IETF-OCM.md @@ -1421,6 +1421,9 @@ request: notification is about (e.g., `file`). * OPTIONAL shareType (string) - the type of recipient this notification is about (e.g., `user`). +* OPTIONAL providerId (string) - the identifier assigned by the + Sending Server to the underlying share, if applicable. This + field is _deprecated_ and SHOULD NOT be used. * OPTIONAL notification (object) - optional additional parameters, depending on the notification and the resource type. @@ -1435,20 +1438,14 @@ Notification types are detailed along with their specific payload. ## Receiver Processing Before applying a notification, the receiver MUST validate its envelope, -payload and identity bindings. The OpenAPI schemas express structural -constraints; address syntax and peer bindings also require validation. +payload and identity bindings. -* A malformed envelope MUST receive HTTP 400. It requires a non-empty - `notificationType`, a valid `senderDomain`, and at least one of - `resourceType` or `shareType` as a non-empty string. Optional fields, - when present, MUST have their defined types. +* Malformed envelopes and malformed payloads for known notification + types MUST receive HTTP 400. Deprecated fields cannot replace required + payload fields. * A receiver SHOULD accept and ignore a valid unknown notification type. It MUST NOT reject it merely because the type is unknown, or apply another type's payload requirements to it. -* A known type MUST satisfy its defined payload requirements. Malformed - known notifications MUST receive HTTP 400 and MUST NOT pass through - the unknown-type path. Deprecated fields cannot replace required - payload fields. * A receiver MAY return HTTP 501 for a known, valid notification type whose operation it does not implement. @@ -2110,9 +2107,8 @@ notification sent to the "/notifications" endpoint (see [Notifications](#notifications)). The "Scope" field indicates whether the notification concerns a -Resource or a Recipient. The notification type defines its required -payload: existing-share events use `file.providerId`, whereas -"REQUEST_SHARE" uses the request fields defined above. +Resource or a Recipient. Each notification type defines its required +payload. Registration Policy: Specification Required [RFC8126] diff --git a/spec.yaml b/spec.yaml index 7b2f16e..967f0b9 100644 --- a/spec.yaml +++ b/spec.yaml @@ -1094,8 +1094,6 @@ components: minLength: 1 description: > A non-empty notification type, compared exactly as sent. - A receiver accepts and ignores valid unknown types; known - types must satisfy their own payload requirements. Any value registered in the OCM IANA Registry for notification types MAY be used here. Implementers MAY define additional custom types, provided that they are registered in the OCM IANA Registry. @@ -1121,6 +1119,11 @@ components: E.g. user, group, federation, etc. Implementers MAY define additional custom types, provided that they are registered in the respective OCM IANA Registry. + providerId: + type: string + description: > + Optional unique identifier of the underlying resource. This property + is now deprecated, in favor of including it in the notification object. notification: type: object description: >