From fcfea4b8edfdeb08ad69da0ac2c2861fe34e0aaa Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Fri, 28 Aug 2026 16:42:00 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(collaboration)=20show=20a=20user=20th?= =?UTF-8?q?e=20history=20since=20they=20got=20access?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The collaboration server's activity and changeset routes are opened to the browser, so a document's editing history can be read from where it actually lives now. What a user may see of it is bounded to the moment they were given access to the document: joining a document that has been written for a year does not hand them the year. That rule is not new. It is the one the version endpoints have always applied - "only those created after the user got access to the document" - and the date is the same one: the earliest access the user holds on the document or on any of its ancestors, so sharing a folder shares its subtree from that moment. It was computed twice in the backend, differently, and exposed nowhere. It is now a single annotation, user_access_since, that the version endpoints and the collaboration server both read, the latter through the document detail response it already fetches to authorize a connection. The bound is applied server-side and silently: a client asks for whatever range it likes and receives only its own share, so there is no bound for it to get wrong and none it can widen. It is a stored date rather than a wall-clock-relative one, which is what keeps it stable across a websocket re-check, and it is never zero - the one value that would also unlock a full-history connection. A reader who reaches a document through its link alone holds no access and so has no date to bound a history with. They get none, which is why the backend has always refused them their versions. rollback and prune stay refused to everyone: restoring a version is a separate decision. Signed-off-by: Kevin Jahns --- CHANGELOG.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59e72fc53..87919d99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,14 +20,25 @@ and this project adheres to ### Added -- ✨(collaboration) grant the browser only the two routes it uses. The +- ✨(collaboration) let a user read the document's editing history from the + moment they were given access to it. The collaboration server's `activity` and + `changeset` routes are opened to the browser, bounded per user to the earliest + access they hold on the document or on one of its ancestors — the same cut-off + the version endpoints have always applied, now computed once in the backend + (`user_access_since`) and applied by the collaboration server as well. The + bound is enforced server-side and silently: a client asks for whatever range it + likes and receives only its own share. A reader who reaches a document through + its link alone holds no access and so has no date to bound a history with, and + gets none — as they never did + +- ✨(collaboration) grant the browser only the routes it uses. The collaboration server now answers what a caller may do with a document as a permission object, facet by facet, and enforces every facet itself. A browser - is granted the websocket and the document route the http fallback polls, and - nothing else — the history, activity, changeset, rollback and prune routes, - every backend-internal endpoint, and any endpoint a future release adds are - refused to it. `create-ydoc` in particular was reachable by any signed-in - editor and is now the backend's alone. The backend's admin token keeps full + is granted the websocket, the document route the http fallback polls and the + two history routes, and nothing else — rollback, prune, every backend-internal + endpoint, and any endpoint a future release adds are refused to it. + `create-ydoc` in particular was reachable by any signed-in editor and is now + the backend's alone. The backend's admin token keeps full access, minus the irreversible content erasure that the new version exposes over http for the first time