(collaboration) build the version history from the activity api

The version history has been dead since the migration. It listed S3 object
versions of the legacy `{pk}/file` key, and nothing writes that key any more,
so every document's list has been frozen at its migration date; restoring one
was a stub that closed the modal and did nothing, while still promising that
the document would be replaced.

It now reads the collaboration server, which is what keeps the history: the
list comes from `activity`, a selected version is previewed from `changeset`
as the document stood at that moment, and restoring one is a `rollback`.

A version is a minute of editing — changes less than a minute apart become
one, and none spans more than a minute. The collaboration server groups only
changes by the same author, so the browser merges what is left across authors:
a version is a moment in the document, not a moment in one person's editing.
Both are needed, and both use the same rule.

This grants `history.rollback` to editors, which is the first time a browser
may change the past rather than read it, and publishes the rollback route.
A reader is refused it twice over — the collaboration server treats it as a
dead grant without document write access, and the endpoint is withheld as well.
Mutations refuse where reads clamp, so a rollback reaching further back than
the history a user was granted is rejected rather than trimmed: nobody can
undo work that predates their own access, and a rollback with no bound at all
is refused outright. `prune`, which erases, stays granted to nobody. Restoring
is not destructive: it appends a change that undoes another, so what it
replaced stays in the history and can be restored again.

The backend's version endpoints are untouched and now have no caller. They are
marked deprecated with the condition for removing them, since until a document
has been replayed by `migrate_documents` they hold the only record of what it
looked like before it moved.

Also fixes the e2e helper that waited for the removed content endpoint, so it
never returned, and the three version tests that hung behind it.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
This commit is contained in:
Kevin Jahns
2026-09-22 16:02:07 +02:00
committed by Manuel Raynaud
parent 4a373f69df
commit 9b4c40fbee
24 changed files with 867 additions and 386 deletions
+25
View File
@@ -1814,6 +1814,31 @@ class DocumentViewSet(
"""
Return the document's versions but only those created after the user got access
to the document
DEPRECATED — nothing calls this any more, and it can be removed once the
migration to the collaboration server is finished.
The collaboration server is the source of truth for document history and
keeps it itself; the version history in the frontend is built from its
`activity` and `changeset` routes, bounded by the same date this method
applies (`user_access_since`, which the collaboration server is handed to
bound what it serves). What this endpoint lists is S3 object versions of
the legacy `{pk}/file` key, and nothing writes that key any more — the
content endpoint that used to went away with the migration — so the list
is frozen at each document's migration date and gains no further entries.
Removing it is safe once every document has had its real history replayed
into the collaboration server by `manage.py migrate_documents`; until
then these versions are the only record of what a soft-migrated document
looked like before it moved. `versions_detail` and
`Document.get_versions_slice` are kept for the same reason and go at the
same time.
The `versions_list` ability still gates the history menu item in the
frontend, and correctly: it is `has_access_role`, which is exactly the
condition under which `user_access_since` is not None and the
collaboration server grants a history — so the gate and the grant cannot
disagree.
"""
user = request.user
if not user.is_authenticated: