Commit Graph
2496 Commits
Author SHA1 Message Date
Manuel Raynaud 6c9a319a83 (backend) add opt-in prometheus metrics on /metrics
We want to export metrics to prometheus. We install for this
django-prometheus. By default the feature is disabled and must be
explicitly enabled. A complete documentation is available in
documentation/metrics.md
2026-09-21 14:48:42 +02:00
Manuel Raynaud 5acd4c2902 🔧(tilt) run two valkey sentinel instances through valkey-operator
We need to use valkey instead of an old redis version. We decided to use
the operator https://github.com/chideat/valkey-operator/ and configure
it in both feature and dev environments.
2026-09-21 14:48:41 +02:00
Manuel Raynaud ca2e05de22 ⬆️(yhub) align @y/y dependency
we have to import @y/y dependency, we use it in the migration part of
the application and @y/hub is also using it. This can lead to a
situation where 2 versions of @y/y are installed, this is not something
we want.
2026-09-21 14:48:41 +02:00
Anthony LCandManuel Raynaud 8ed721f0c6 ✈️(frontend) add tree offline support
The doc tree can now be accessed offline, allowing
users to view and interact with the document
hierarchy even without an internet connection.
2026-09-21 14:48:40 +02:00
Anthony LCandManuel Raynaud d0b97b5754 ✈️(frontend) add offline support with yhub
The offline support couldn't work with the existing
implementation anymore, because there is no request
to get or save data anymore, everything is handled
with web sockets.
In order to support offline functionality, we
leveraged y-indexeddb to store and synchronize
local changes, ensuring that the application remains
functional even when offline.
2026-09-21 14:48:40 +02:00
Anthony LCandManuel Raynaud 8e80b96e8c 🔧(collaboration) make the version history granularity configurable
Version grouping used a hard-coded 60s window, and its
timestamps are minted server-side.
We now expose COLLABORATION_VERSION_GRANULARITY_MS
through /config, read it in useDocActivity.

By doing so, we can control the granularity of
version history with settings, it can be adjusted as
needed. It will help us to test different version
history granularities in our e2e tests.
2026-09-21 14:48:40 +02:00
Anthony LCandManuel Raynaud f85418e895 🧱(e2e) add yhub-e2e service
Add yhub-e2e service to the Docker Compose setup.
It will test yhub with the production image.
2026-09-21 14:48:39 +02:00
Anthony LCandManuel Raynaud 2438c639ec 🔊(CHANGELOG) update the changelog to keep it standard
Recent commits changed the way the changelog is
filled, so this commit updates the changelog to
keep it standard.
2026-09-21 14:48:37 +02:00
Anthony LCandManuel Raynaud ec3506a20b 🎨(yhub) split server.ts into focused modules
Divide server.ts into 3 focused modules:

- config.ts: every environment variable the server reads, parsed and
  validated at import time,
- backend.ts: the calls made to the Docs Django backend, the token
  signing and the JWKS both ends verify each other with,
- api.ts: the custom REST endpoints mounted under /collaboration/.

server.ts keeps only what wires these together: the auth plugin and its
legacy-store seed (which closes over the yhub instance), the persistence
plugins, the worker events and the createYHub call.

The AppAuthInfo identity shape moves to yhub.ts so server.ts and api.ts
can share it without importing from each other.

Tests follow the split: config.spec.ts and backend.spec.ts are new,
server.spec.ts narrows to the composition root's boot contract. No
behaviour change.
2026-09-21 14:48:00 +02:00
Anthony LCandManuel Raynaud 7084e5a42d 🏷️(yhub) migrate yhub-server to typescript
Convert the yhub-server source and tests from plain JS/mjs to
TypeScript: move sources under src/, add tsconfig, tsconfig.build,
eslint flat config and nodemon config, and update the Dockerfile,
compose and CI workflow for the build step.
2026-09-21 14:48:00 +02:00
Anthony LCandManuel Raynaud 5174485a58 📦️(yhub) switch yhub-server to yarn
Every other package in this repository is installed
with yarn; yhub-server was the only one on npm,
with its own package-lock.json.
To ensure consistency it now uses yarn like the rest
of the project.

package-lock.json is replaced by yarn.lock, a packageManager
field is added, and the Dockerfile, CI workflow, Makefile,
helm init-db job and the documentation move from
`npm ci` / `npm run init-db` to
`yarn install --frozen-lockfile` / `yarn init-db`.
2026-09-21 14:48:00 +02:00
Anthony LCandManuel Raynaud d295a08fe8 (yhub) add more tests on yhub-server using vitest
We use vitest in most of our applications,
to ensure consistency and maintainability across our
codebase we are now using vitest for yhub-server as well.
We added more tests on yhub-server.
The tests cover migration, permissions, and server
functionality. We also added a helper file for test
utilities.
2026-09-21 14:47:59 +02:00
Manuel Raynaud fe8d7aaa0f 🔥(backend) remove Document.content
The content is not managed anymore in the Document object nor the django
application. The last piece using it was the versioning API and it has
been deleted previously. There is no more reason to keep code related of
the content in the backend application. The only remaining code is the
`file_key` property in the model. It is kept as a safe guard use by the
clean_document management command. If the file is kept on the bucket,
then the document will be reseed with it the first time the document
will be reopen.
2026-09-21 14:47:59 +02:00
Manuel Raynaud 07433c7c9e ♻️(collab) retrieve history from user access
Previously we added to retrieve document response a new property
user_access_since that contains the date from when the user started to
have access to the document. The way t was made added an other
annotation to the Document queryset making the sql query more and more
complex. We decided to lighten the queryset and expose the access the
user has on the document instead and read the history from the
created_at property.
2026-09-21 14:47:58 +02:00
Manuel Raynaud fc895494c7 🔧(helm) enable collaboration API in dev and feature envs
We want to enable the collaboration API in both dev and feature
environments.
2026-09-21 14:47:58 +02:00
Kevin JahnsandManuel Raynaud 9f4057c4c8 🔧(yhub) align the yhub db credentials with the backend's dev ones
The yhub database ran under its own yhub role. Every other database in
this stack uses the backend's dev credentials, dinum/pass, which is also
what CI already uses for this database; only the database name stays
apart, since it is a separate database on a separate server.

The url the collaboration server connects with moves into the same file,
beside the credentials it repeats, written once rather than twice — the
yhub service reads the file as well. A yhub-postgres.local override is
created like for the other env files, and the healthcheck asks about
POSTGRES_DB and POSTGRES_USER like the other two do instead of naming the
role.

POSTGRES_USER only takes effect on a fresh initdb, so an existing stack
needs its yhub-pgdata volume dropped and `make migrate-yhub` re-run; the
volume holds local document state only.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:58 +02:00
Kevin JahnsandManuel Raynaud bd4c8a5c6c ⬆️(collaboration) upgrade yhub to 0.9.0 and delete superseded blobs
The S3 persistence plugin records the version id of the object it wrote
and names that version when it deletes it. On a versioned bucket - what
a deployment runs - a delete that names no version deletes nothing: it
writes a delete marker and keeps every version underneath. Each
compaction supersedes the blobs of the one before, so what was kept was
every version of every document ever written, a document someone asked
to erase included, still readable by anyone who can list versions. On
AWS this needs s3:DeleteObjectVersion, which a policy granting
s3:DeleteObject alone does not cover.

Blobs are written to the bucket for every branch of a document.

YHUB_S3_PERSISTENCE now governs only whether new blobs are written
there. The plugin itself is attached whenever the YHUB_S3_* settings
name a bucket, on or off, because reading is the half that must never
be taken away: a row pointing at an object is unreadable without the
plugin that wrote it, and yhub reports such a version as having no
content rather than as an error. Turning the toggle off stops the
writing and leaves the reading alone; it is the settings, not the
toggle, that a deployment whose bucket holds anything must keep. Half a
configuration is a startup error naming what is missing, as before.

The dev stack keeps the toggle off and creates its bucket versioned, so
flipping it on exercises what a deployment runs rather than a simpler
case. Its createbuckets job needed fixing to do so: the folded yaml
block joins its lines with a space, so the trailing backslashes reached
the shell as an escaped space glued to the next word and everything
past the first && silently did nothing - the media bucket never had
versioning enabled either.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:57 +02:00
Kevin JahnsandManuel Raynaud 697d88065a (e2e) cover the disconnection of a client whose access changed
The check was dropped during the yhub migration, on the grounds that
`reset_connections` was a no-op. It is not one any more: the backend calls
yhub's reset-connections route, which re-runs the authorization of each
connection and closes the sockets whose access is no longer the one they
were opened with, with the code 4401.

The old check cannot come back as it was. It had the author of the document
change its visibility and waited for the author's own socket to close, which
is what the collaboration server used to do - close every connection to the
document, whatever it was that changed. yhub leaves alone the connections
that are unaffected, and an owner's access is the same before and after, so
the author's socket is now deliberately kept.

The client to watch is therefore another one: the anonymous reader holding
the public link, while the author switches that link from reading to
editing. Their socket goes down and the client comes back on its own.

That the new connection is live is asserted by what flows through it rather
than by the socket being open - the author writes after the change and the
text reaches the reader, with nothing reloaded in between.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:57 +02:00
Kevin JahnsandManuel Raynaud 53615c18d7 (e2e) stop two tests relying on removed api endpoints
The export regression tests injected their fixture by intercepting
`GET /documents/{id}/content/`, and the 401 routing test intercepted the
`PATCH .../content/` a document used to send on the way out. Both endpoints
went with the yhub migration, so the interceptions matched nothing: the
exported document was whatever the two images added to an empty page, and
the 401 page was never reached.

The fixture now goes to the collaboration server, which is the only thing
that holds document content. It is seeded before the editor mounts: its
first block carries the id BlockNote gives the empty paragraph it writes
into any document it opens empty, so seeding an already open document would
leave a stray paragraph in front of the fixture and shift every page. The
reference PDFs are unchanged and still match, page count, text and pixels.

The 401 test reloads rather than navigating to another document, nothing
being sent on the way out any more.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:57 +02:00
Kevin JahnsandManuel Raynaud a74fee21cc (collaboration) show a migrated history save by save
A document's imported past is attributed to `system`, and until now it went
through the same grouping as ordinary editing. That is wrong twice over.

It loses history. Before the migration the editor saved the whole document on
an interval of exactly 60s, each save becoming one version of the legacy file,
and the migration replays them at their original timestamps — so an imported
history arrives as a chain of entries spaced almost exactly the width of the
grouping window. Whether two of them survived as two came down to whether the
round trip that wrote them ran a few milliseconds fast or slow: measured over
simulated sessions, about a third of the chain collapsed. A document whose
saves happened closer together lost far more — four versions two seconds apart
became one.

And it is the wrong question to ask of them. Grouping summarises someone's
editing into the moments that are worth listing; there was no editing session
here, only a record of saves that already happened, and the only honest thing
to do with that is to show it one for one.

`system` is now excluded from grouping on both sides. The collaboration server
takes the exclusion as a parameter, which is what the yhub bump in this commit
is for. The panel applies it again and more strictly: the server declines to
merge an excluded entry into the one before it, having already refused on the
author comparison it makes, while the panel merges across authors and so must
refuse in both directions — an edit made moments after a document was migrated
must not absorb the imported entry beside it, or be absorbed by it.

Live editing is unchanged: several edits by one person seconds apart are still
one version.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:56 +02:00
Kevin JahnsandManuel Raynaud 3b13954c81 (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>
2026-09-21 14:47:56 +02:00
Kevin JahnsandManuel Raynaud 800b6189d9 (collaboration) show a user the history since they got access
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 <kevin.jahns@protonmail.com>
2026-09-21 14:47:56 +02:00
Kevin JahnsandManuel Raynaud 576bd5c9ed (collaboration) show a user the history since they got access
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 <kevin.jahns@protonmail.com>
2026-09-21 14:47:55 +02:00
Kevin JahnsandManuel Raynaud 9e81e6de72 ⬆️(collaboration) upgrade yhub to 0.8.0 and adopt its permission model
yhub 0.8.0 retires the 'r' | 'rw' | null access vocabulary. The auth
plugin now answers a typed permission object stating, facet by facet,
what a subject may do with a document, and yhub enforces every facet
itself - on the websocket and on the REST routes alike. Three rules we
wanted but could not express under the old vocabulary become one-line
facets. Our whole access policy now lives in
src/yhub-server/permissions.js, apart from the server so that it can be
read and tested without standing up redis and postgres.

Read-only users no longer share their cursor #2544. A read-only
connection could still propagate awareness updates to everyone else in
the document, even though its document updates were already dropped.
Presence is now a permission of its own, separate from the right to
edit: a reader receives it and never publishes it. The collaboration
server enforces that rather than trusting the editor to stay quiet, so a
modified or stale client changes nothing. The frontend has to know it
too - the http fallback provider has no receive-only mode, so a reader's
provider is built with no awareness instance at all, or its first PATCH
would take a 403 and close it for good.

The browser is granted only the two routes it uses, the websocket and
ydoc for the http fallback. Everything else - history, rollback, prune,
and every backend-internal endpoint - is refused to it, as is any
endpoint a future release adds, because the grant names no wildcard.
create-ydoc in particular was reachable by any signed-in editor and is
now the backend's alone.

Anonymous visitors are given the userid "anonymous" rather than no
identity at all, which is what lets them keep editing public documents:
yhub refuses the upgrade of a caller that holds the write but cannot be
attributed. Their edits share one author.

Room is DocRef throughout, which is a rename of object keys and not only
of types: the worker event payload and the stream message lookup both
carry it, and both fail silently rather than loudly when missed.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:55 +02:00
Kevin JahnsandManuel Raynaud b0be11dd6a 🔥(frontend) remove two dead paths to the Django document api
Document content stopped going through Django when the collaboration
server took it over, and these two are what the move left behind. Both
are unreachable rather than merely unused, so they are removed instead
of being carried forward.

useUpdateDoc sent websocket: true whenever the provider was synced, to
unlock a cache lock the backend used to hold while another user was
connected. That lock is gone - there is no websocket field on the
serializer and nothing reads one - so DRF has been silently dropping the
key. Removing it also drops the store's only isSynced reader.

The service worker still wrote an entry to a doc-content table keyed on
documents/{id}/content/, an endpoint that no longer exists. Nothing ever
read it back: handlerDidErrorRead only ever asks for doc-list and
doc-item. The table is dropped on the next upgrade so it does not linger
in browsers that already have it.

This also clears the five standing typescript errors in the repository,
which were all stale doc-content literals in the tests for the code
being removed.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:55 +02:00
Kevin JahnsandManuel Raynaud 2d53327fdb (collaboration) fall back to http polling when the websocket is blocked
Some networks refuse a websocket upgrade - corporate proxies, captive
portals - and a browser is told nothing more than "the connection
closed", so those users could not edit at all. The editor now runs a
second transport next to the socket, polling the collaboration server's
REST api on the same room, with the same session cookie and the same
authorization, and only while the socket is down. Local changes go out
about a second after the last keystroke and remote ones arrive within
ten seconds, so editing works with visibly more latency rather than not
at all. The socket keeps being retried underneath, so a client that fell
back during an outage returns to it on its own, and nothing is lost in
either direction - both transports publish from the same document.

This makes /collaboration/ydoc/ a route browsers call, so
COLLABORATION_SERVER_ORIGIN is now handed to yhub as its cors
configuration and gates the http routes as well as the websocket.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-09-21 14:47:54 +02:00
Manuel Raynaud 06cbb4cee2 📝(core) update the architecture documentation
We want to update the architecture documentation with YHub and removing
the mention of HocusPocus
2026-09-21 14:47:54 +02:00
Manuel Raynaud c7beb50411 📝(installation) upgrade documentation with yhub instruction
All installation guides are updated to add the instructions about how to
deploy docs with yhub.
2026-09-21 14:47:54 +02:00
Manuel Raynaud 4530c42d0a 📝(upgrade) complete the upgrade guide for yhub
The upgrade between version 5 and next version 6 is not simple. Lot of
breaking changes are made and must be documented to ease the upgrade for
the community.
2026-09-21 14:47:53 +02:00
Manuel Raynaud d0e6fb9350 (yhub) allow optional usage of s3 persistent plugin
Yhub has a s3 persistent plugin, since now we didn't use it but we wanto
to give the possibility to use it optionnaly. To enable it set the
YHUB_S3_PERSISTENCE environment value to true and configure it.
2026-09-21 14:47:53 +02:00
Manuel Raynaud 737fa4404f (backend) allow too migrate a specific document
The management command migrating document to yhub didn't allow to target
a specific document. This can be usefull for debugging purpose but also
to replay the migration of a specific document.
2026-09-21 14:47:53 +02:00
Manuel Raynaud 9191103bf8 ♻️(yhub) replace minio client by S3 sdk
We have some signature errors when using the minio client to list all
the versions of an existing document. To avoid this error we have
decided to use the S3 sdk and allow to configure the signature versino
the user wants. Also, the check on the document size has been removed,
there is no limitation on the document size.
2026-09-21 14:47:52 +02:00
Manuel Raynaud ca9a0c4da1 ♻️(yhub) create dedicated file for environment variables in development
For now the environment variable for yhub were added to the common file.
This number of environment is growing and is specific to yhub so we
decided to create a dedicated file for yhub
2026-09-21 14:47:52 +02:00
Manuel Raynaud c21fdfc20d ♻️(yhub) prefix S3 envirionment variables used by the migration
We want to allow the usage of different buckets when migrating legascy
documents.
2026-09-21 14:47:52 +02:00
Manuel Raynaud 388261ea57 🔧(yhub) allow to configure every createYHub parameters
In the redis section there were still hard coded values, we want to
allow the configurations of this settings. The last part will be the
persistence plugin.
2026-09-21 14:47:51 +02:00
Manuel Raynaud b10a0b9f0c 🔧(thub) allow to configure task concurrency
We want to configure the number of concurrency tasks a work run. For
this a new environment variable YHUB_TASK_CONCURRENCY is added
2026-09-21 14:47:51 +02:00
Manuel Raynaud f4a21c68f0 (yhub) allow to configure yhub worker and server
We want to be able to configure both server and worker, the idea is to
be able to deploy separately the server and the worker and to scale
them.
2026-09-21 14:47:51 +02:00
Manuel Raynaud 81b74e666b (yhub) add custom probes more efficient
The probes used before was using the only one public available endpoint.
This endpoint is the jwks endpoint but it is not an appropriated one.
For the readyness we check that it is possible to connect to postgres
and to redis. for the liveness we made a ping pong just checking the
http connection.
2026-09-21 14:47:50 +02:00
Manuel Raynaud e50a151de9 (helm) deploy new infra using helm
The new infra we have must be configured in the helm chart. This commit
all the missing templates to deploy yhub, it also automate the creation
of the private keys needed by all services.
2026-09-21 14:47:50 +02:00
Manuel Raynaud b0cc166b87 (collaboration) erase content in yhub from clean_document command
The clean_document command makes a reset of a document deleting its
content and all the attachments linked to this subdocument and its
children. The hard delete api in yhub make the room, so the document id,
not usable at all and this is not not what we want. We added a new
custom api in yhub to manage this case, the document is hard deleted and
then the Tombstone to make the room reusable again.
2026-09-21 14:47:50 +02:00
Manuel Raynaud 4932c95600 🐛(frontend) stop reconnecting to the websocket based on the status code
The yhub server returns custom status code when the websocket is not
accessible, like 4401 when an access is removed and 4404 when a document
is deleted. the websocket client now use these custom status code to
stop reconnection forever.
2026-09-21 14:47:48 +02:00
Manuel Raynaud 7da25af160 (backend) wired soft deletion with yhub server
yhub is the source of truth, when a user delete a document, it should
also be deleted in the yhub server. We call the yhub server in the
perform_destroy action but also the restore endpoint of yhub when a
document is restored.
2026-09-21 14:46:15 +02:00
Manuel Raynaud fb3b192112 (yhub) add a restore endpoint
We will use the delete endpoint available in the yhub server with the
soft delete feature in the backend application, but we also need a
restore endpoint and this endpoint is not available in the yhub server.
This commit adds a new custom endpoint implementing the restore action.
2026-09-21 14:46:14 +02:00
Manuel Raynaud 2c302c8476 (backend) add a migrate_documents command
command replaying the legacy content of
the documents into the collaboration server, one call to its migrate endpoint
per document. Resumable and safe to re-run: what became of every document is
recorded (`impress_document_migration`), a server that is unwell is retried
with a backoff and a document it refuses is left for a later run
(`--retry-failed`). Bounded by `--concurrency`, `--rate` and `--limit`, most
recently edited documents first
2026-09-21 14:46:14 +02:00
Manuel Raynaud 04a8dddd69 (backend) correctly reload urls in tests
After removing most of the usage of S3 in the tests, these ones are
faster and make some flakyness more relevant. For example, in tests
related to the external api we have to reload the urls based on the
settings. We now have some race conditions where tests collapsed and
urls are not correctly reloaded.
2026-09-21 14:46:14 +02:00
Manuel Raynaud 1cf231d7a8 ♻️(backend) remove usage of s3 for document.content in tests
Tehe DocumentFactory was always creating a content and this content was
saved on S3. This leads to the creation of huge amount of content in the
S3 storage but not necesseraly used in the tests. In order to keep the
refactor to remove the usage of content from document.content but from
Yhub service, this content is no more generated. It is kept for part of
the code not yet refactor like the versionning feature.
2026-09-21 14:46:13 +02:00
Manuel Raynaud 595acb3618 ♻️(backend) seed the content of the demo documents using yhub
seed the content of the demo documents in the collaboration
server: `create_demo` no longer writes it to the object storage, which
nothing reads anymore, and fails with an explicit message when the
collaboration server is not running rather than building a corpus of
documents that would open empty
2026-09-21 14:46:13 +02:00
Manuel Raynaud b79d4ee6e7 🔥(yhub) remove custom endpoint get-ydoc
We don't need anymore the get-ydoc endpoint to fetch a document content
since yhub 0.5.0 can manage json encoding. We can safely remove it.
2026-09-21 14:46:13 +02:00
Manuel Raynaud d126e641a0 ♻️(backend) take adavantage of yhub 0.5.0 json encoding returns
The version 0.5.0 can manage response format by using accept and
content-type headers. In python we can't use for now the lib0 decoder so
we have to use the json format. When the lib0 decoder will be available
in pycrdt we will use it. So we can now use directly the /ydoc api to
fetch a document content instead the custom api made for this.
2026-09-21 14:46:12 +02:00
Manuel Raynaud a083130bb4 ♻️(backend) duplicate the onboarding sandbox using YHub service
Duplicate the onboarding sandbox document through the
collaboration server: its content is read from there and copied under the
identity of the user the sandbox is created for. A collaboration server that
cannot be reached skips the sandbox, as a missing template already did, and
never fails the signup
2026-09-21 14:46:12 +02:00