Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
This repository contains the text of the [Open Cloud Mesh IETF Draft](https://datatracker.ietf.org/doc/draft-ietf-ocm-open-cloud-mesh/), as well as the equivalent [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (fka Swagger) specification for its API rendered as HTML (by [ReDoc](https://github.com/Redocly/redoc)).

The documents are available as follows:

* **Latest official version, 1.3.0**: [RFC-formatted Draft](https://github.com/cs3org/OCM-API/blob/v1.3.0/IETF-RFC.md) | [API spec](https://cs3org.github.io/OCM-API/docs.html?branch=v1.3.0&repo=OCM-API&user=cs3org)
* Development branch: [RFC-formatted Draft](IETF-RFC.md) | [API spec](https://cs3org.github.io/OCM-API/docs.html?branch=develop&repo=OCM-API&user=cs3org)

Expand All @@ -23,11 +24,17 @@ The Open Cloud Mesh API specification is an open source, community-driven projec

If you'd like to contribute, please follow the [Contributing Guidelines](CONTRIBUTING.md) and the [IETF Note Well](https://www.ietf.org/about/note-well/).

## Working Material

Current working material for the `/notifications` endpoint lives under
[`work/notifications/`](work/notifications/README.md).

## History and Changelog

The history of the Open Cloud Mesh project is [available here](HISTORY.md), including links to external material.

Previously released versions ([changelog](CHANGELOG.md)):

* Version 1.2.0: [RFC-formatted Draft](https://github.com/cs3org/OCM-API/blob/v1.2.0/IETF-RFC.md) | [API spec](https://cs3org.github.io/OCM-API/docs.html?branch=v1.2.0&repo=OCM-API&user=cs3org)
* Version 1.1.0: [README](https://github.com/cs3org/OCM-API/blob/v1.1.0/README.md) | [API spec](https://cs3org.github.io/OCM-API/docs.html?branch=v1.1.0&repo=OCM-API&user=cs3org)
* Version 1.0.0: [API spec](https://cs3org.github.io/OCM-API/docs.html?branch=v1.0.0&repo=OCM-API&user=cs3org)
18 changes: 18 additions & 0 deletions work/notifications/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Notifications Work Area

This directory holds the public research notes for the `/notifications`
endpoint in relation to issue `#350`.

The protocol source of truth lives in:

- `IETF-RFC.md`
- `spec.yaml`

This place keeps only the research layer:

- `research/` for implementation notes and cross-platform
observations

Current documents:

- `research/README.md`
1 change: 1 addition & 0 deletions work/notifications/interop/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions work/notifications/proposals/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

19 changes: 19 additions & 0 deletions work/notifications/research/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Notifications Research

This directory keeps the public research notes for `/notifications`.

Current files:

- `nextcloud-server.md`
File-oriented notes from the Nextcloud server inspection
- `nextcloud-talk.md`
Notes on `talk-room` and resource-event use of `/notifications`
- `ocis-reva.md`
Notes on the main non-Nextcloud contrast in this inspection
- `cernbox-reva.md`
Notes on route presence versus notification behavior
- `opencloud-reva.md`
Short notes on the current openCloud / reva notification path

The platform files also keep a small list of the notification types
seen in code and the main send and receive paths for each stack.
50 changes: 50 additions & 0 deletions work/notifications/research/cernbox-reva.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# CERN / cs3org reva Research

Inspected repo: `https://github.com/cs3org/reva`
Inspected source commit:
[`62d31b988cf0f864fafd033e1b939ea7f05ba398`](https://github.com/cs3org/reva/tree/62d31b988cf0f864fafd033e1b939ea7f05ba398)

In this inspection, this repo is mainly relevant for the gap between route
presence and notification behavior.

## What I Saw

In this inspection, the `/ocm/notifications` path can read and log payload
data, and it returns `201 Created`, but it does not look like a receiver that
interprets notification types and applies state transitions.

Outbound notification sending also does not look complete in this tree.
Discovery, by contrast, appears more developed than the notification path
itself.

This combination shows the difference between "this product has an endpoint"
and "this product implements notification behavior that another server can
depend on."

## Notification Types And Code Paths

- The inbound `/ocm/notifications` handler lives in
[`notifications.go`](https://github.com/cs3org/reva/blob/62d31b988cf0f864fafd033e1b939ea7f05ba398/internal/http/services/opencloudmesh/ocmd/notifications.go).
- In this checkout, that file does not decode typed notification requests. It
reads the raw JSON body, logs it, and returns `201 Created`.
- The code comments in
[`notifications.go`](https://github.com/cs3org/reva/blob/62d31b988cf0f864fafd033e1b939ea7f05ba398/internal/http/services/opencloudmesh/ocmd/notifications.go)
mention `SHARE_ACCEPTED`, `SHARE_DECLINED`, `REQUEST_RESHARE`,
`SHARE_UNSHARED`, `RESHARE_UNDO`, and `RESHARE_CHANGE_PERMISSION`, but in
this pass those values were examples only. They were not decoded or acted on.
- Outgoing notification sending is still not wired because
[`client.go`](https://github.com/cs3org/reva/blob/62d31b988cf0f864fafd033e1b939ea7f05ba398/internal/http/services/opencloudmesh/ocmd/client.go)
still has `NewNotification()` unimplemented.
- The route is marked as unprotected ingress in
[`routes.go`](https://github.com/cs3org/reva/blob/62d31b988cf0f864fafd033e1b939ea7f05ba398/internal/http/services/opencloudmesh/ocmd/routes.go).

## What This Shows

This upstream line shows why the spec needs a clearer separation between route
presence and real handling. If a test or a discovery document looks only for
the existence of `/notifications`, it can easily give an incomplete picture of
cross-server behavior.

For that reason, this repo is currently more relevant as context for discovery
behavior and for understanding one part of the wider reva landscape than as a
main reference for notification behavior.
99 changes: 99 additions & 0 deletions work/notifications/research/nextcloud-server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Nextcloud Server Research

Inspected repo: `https://github.com/nextcloud/server.git`
Inspected source commit:
[`f8cc0adefb0703bc5d816b328f2c1d97a40f7e04`](https://github.com/nextcloud/server/tree/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04)

In this inspection, Nextcloud server has a real file-oriented notification
path.

## What I Saw

Nextcloud has a real receive path for `/ocm/notifications`, not only a route.
It accepts known notification types, binds them to existing local share state,
and applies side effects. This gives one clear example of receiver behavior in
deployed code.

For file notifications, `notification.sharedSecret` is the main binding input.
When signatures are available, the server also ties the request back to the
expected remote identity. In other words, Nextcloud already behaves as if
transport authentication and object binding are related but still separate.

The implementation also shows that success bodies can matter. In particular,
`REQUEST_RESHARE` can return response data instead of behaving like a generic
empty acknowledgment.

Another important point is scope: Nextcloud is not using `/notifications` only
for file-share accept and decline flows. The same transport is also used for
calendar sync, which is one reason the spec discussion is now larger than a
small file-share patch.

## Notification Types And Code Paths

- `SHARE_ACCEPTED` and `SHARE_DECLINED` are sent when a remote share is
accepted or declined through
[`External/Manager.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/files_sharing/lib/External/Manager.php).
- `REQUEST_RESHARE`, `SHARE_UNSHARED`, and `RESHARE_UNDO` are sent from
[`Notifications.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/federatedfilesharing/lib/Notifications.php).
- Initial federated file delivery does not use `/notifications`. It still goes
through `/shares` from
[`Notifications.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/federatedfilesharing/lib/Notifications.php).
- The main file receiver lives in
[`CloudFederationProviderFiles.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php).
In this pass it receives `SHARE_ACCEPTED`, `SHARE_DECLINED`,
`SHARE_UNSHARED`, `REQUEST_RESHARE`, `RESHARE_UNDO`, and
`RESHARE_CHANGE_PERMISSION`.
- In that provider, `SHARE_ACCEPTED` and `SHARE_DECLINED` update earlier share
state, `SHARE_UNSHARED` removes an external share if one is found,
`REQUEST_RESHARE` can return `token` and `providerId`, and `RESHARE_UNDO`
undoes an earlier reshare. See
[`CloudFederationProviderFiles.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php).
- `RESHARE_CHANGE_PERMISSION` is present in the receive surface, but the same
provider currently throws `HintException("Updating reshares not allowed")`,
so this type is not working as a real OCM permission-update path here. See
[`CloudFederationProviderFiles.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php).
- `SYNC_CALENDAR` is sent from
[`CalendarFederationNotifier.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/dav/lib/CalDAV/Federation/CalendarFederationNotifier.php)
and received by
[`CalendarFederationProvider.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/dav/lib/CalDAV/Federation/CalendarFederationProvider.php).
Unknown calendar notification types return an empty result there.
- The canonical `/ocm/notifications` controller is
[`cloud_federation_api/lib/Controller/RequestHandlerController.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/cloud_federation_api/lib/Controller/RequestHandlerController.php).
- The older OCS controller still used by some accept, decline, and unshare
flows is
[`federatedfilesharing/lib/Controller/RequestHandlerController.php`](https://github.com/nextcloud/server/blob/f8cc0adefb0703bc5d816b328f2c1d97a40f7e04/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php).

## Limits

Even though Nextcloud is the richest implementation in this inspection, it is
not a simple "copy this into the spec" template.

The behavior is split across several layers. There is a canonical OCM route,
but there are also older OCS fallbacks and app-specific paths. Those paths do
not all return the same status codes or expose the same failure behavior. So
it is easy to describe the implementation as more uniform than it really is.

The resource-type story is also uneven. `file` is clearly present in the common
path. `folder` appears in internal registration, but it does not look settled
enough to treat as a shared starting point yet. `calendar` is real in code, but it
is not as clearly represented in default discovery output as one might expect.

Permission change is another example that needs care. The type appears in the
dispatch surface, but the current file path does not look like a clear OCM path
that another stack could safely target today.

There are also places where a successful response does not necessarily mean a
strong real outcome. For example, some paths can log and continue, and some
unshare handling can become a no-op when no matching local row is found.

## What This Shows

For the spec discussion, Nextcloud server shows that `/notifications` can have
meaningful receiver behavior in deployed code. It also shows that the endpoint
is not only theoretical and that state-transition language is part of the
current implementation picture.

At the same time, this inspection also shows why the current Nextcloud behavior
should not be read as one direct template for the full spec text. Some parts
look broadly reusable, and some parts still look local to this implementation
or to specific apps.
105 changes: 105 additions & 0 deletions work/notifications/research/nextcloud-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Nextcloud Talk Research

Inspected repo: `https://github.com/nextcloud/spreed`
Inspected source commit:
[`76fd45d40827f76619942c9cd0a3323188dc6e42`](https://github.com/nextcloud/spreed/tree/76fd45d40827f76619942c9cd0a3323188dc6e42)

In this inspection, Nextcloud Talk changes the shape of the problem. It does
not create a separate notification transport. Instead, it reuses core
Nextcloud OCM and shows that `/notifications` is already being used as a
resource-event channel, not only as a file-share callback API.

## What I Saw

Talk adds the `talk-room` resource type and uses notifications for room-state
changes, participant updates, and message propagation after the initial share
bootstrap. The initial invite is still an OCM share, but the later lifecycle
depends much more on notifications.

That matters because it becomes much harder to describe `/notifications` as a
flat list of file-share types once a real deployed app is already using it for
resource-specific event traffic.

The receive side still uses shared-secret-based binding, so Talk does not move
fully away from the broader Nextcloud model. But the payloads are much richer
and clearly resource-specific. The endpoint carries room details, participant
details, and message details, not only file-share status changes.

Talk also uses the notification response in an important way. In particular,
`RESOURCE_NOT_FOUND` is not only a log message or an example string. It can
change retry behavior and lead Talk to treat a remote participant or share as
gone.

## Notification Types And Code Paths

- Talk registers its cloud federation provider in
[`Application.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/AppInfo/Application.php).
- Talk advertises `talk-room` and the `talk-v1` follow-up path through
[`ResourceTypeRegisterListener.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/Proxy/TalkV1/Listener/ResourceTypeRegisterListener.php).
- `SHARE_ACCEPTED` and `SHARE_DECLINED` are sent back to the host when an
invited user accepts or declines a room share through
[`FederationManager.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/FederationManager.php)
and
[`BackendNotifier.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/BackendNotifier.php).
- The main inbound receiver lives in
[`CloudFederationProviderTalk.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/CloudFederationProviderTalk.php).
In this pass it receives `SHARE_ACCEPTED`, `SHARE_DECLINED`,
`SHARE_UNSHARED`, `PARTICIPANT_MODIFIED`, `ROOM_MODIFIED`, and
`MESSAGE_POSTED`.
- In that provider, `SHARE_ACCEPTED` updates the stored host-side federated
attendee row, while `SHARE_DECLINED` removes the pending federated attendee
from the host room. See
[`CloudFederationProviderTalk.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/CloudFederationProviderTalk.php).
- `SHARE_UNSHARED` is handled on the invited side. It deletes the stored
invitation and removes the local participant if the room had already been
accepted. See
[`CloudFederationProviderTalk.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/CloudFederationProviderTalk.php).
- `PARTICIPANT_MODIFIED` is intentionally narrow here. In this pass the
receiver only acts on permission changes and `RESEND_CALL`. See
[`CloudFederationProviderTalk.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/CloudFederationProviderTalk.php).
- `ROOM_MODIFIED` is broader. It updates room state such as room name,
description, type, avatar, lobby, permissions, read-only flags, expiration,
pinned state, recording flags, and SIP state. See
[`CloudFederationProviderTalk.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/CloudFederationProviderTalk.php).
- `MESSAGE_POSTED` carries a full message snapshot plus unread counters. It is
used for new messages, and it also covers edit and delete cases. See
[`CloudFederationProviderTalk.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/CloudFederationProviderTalk.php).
- On the sender side, `SHARE_UNSHARED` is sent from
[`BeforeRoomDeletedListener.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/Proxy/TalkV1/Notifier/BeforeRoomDeletedListener.php),
`PARTICIPANT_MODIFIED` from
[`ParticipantModifiedListener.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/Proxy/TalkV1/Notifier/ParticipantModifiedListener.php),
`ROOM_MODIFIED` from
[`RoomModifiedListener.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/Proxy/TalkV1/Notifier/RoomModifiedListener.php),
and `MESSAGE_POSTED` from
[`MessageSentListener.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/Proxy/TalkV1/Notifier/MessageSentListener.php).
- The response body from `/notifications` is part of Talk's state machine in
[`BackendNotifier.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/Federation/BackendNotifier.php).
`RESOURCE_NOT_FOUND` is treated as a real remote state signal, not only as a
log message.
- Failed Talk notifications are retried from `talk_retry_ocm` by
[`RetryNotificationsJob.php`](https://github.com/nextcloud/spreed/blob/76fd45d40827f76619942c9cd0a3323188dc6e42/lib/BackgroundJob/RetryNotificationsJob.php).

## What This Shows

This path makes it clear that the spec needs room for extensions. Even if the
first shared file profile stays small, the current behavior already shows
resource-specific profiles around the common envelope.

It also shows that a notification path may need more than one follow-up
channel. After OCM bootstrap, it advertises and uses `talk-v1` as a companion
path for room and chat behavior. That does not replace `/notifications`, but it
does show that discovery and extension language need more detail than the
current draft gives them.

## Limits

Talk supports the idea of an extension model, but it is not a reason to force
all of Talk's payload details into the common notification contract. Those
details belong to a resource-specific profile if they belong in the spec at
all.

It is also not a reason to treat the current Talk behavior as fully settled.
The code surface is large, the retry logic is detailed, and the behavior still
needs careful reading. So this is better read as "evidence that the endpoint is
already broader than the RFC says" than as "the final extension template is
already clear."
Loading
Loading