Commit Graph
2312 Commits
Author SHA1 Message Date
Anthony LCandManuel Raynaud 6f0bdc7fb3 🔥(frontend) remove "can-edit" mechanism
We will not block anymore the users not connected
to the collaboration server from editing the document,
we will have an HTTP fallback instead, so we can
remove the "can-edit" mechanism and the related code.
2026-08-13 12:08:26 +02:00
dc76f9001b 🔒️(collaboration) harden the create-ydoc endpoint
Address the findings of an adversarial review of the new endpoint:

- Only the backend admin token may attribute content to another user via
  the X-User-Id header. The endpoint uses the default access purpose, so
  any editor with update ability can call it — honoring the header for
  them would let an editor forge the attribution history of the first
  revision (the websocket path likewise stamps the server-side
  identity). Regular callers now always author as themselves; verified:
  an editor session posting X-User-Id gets its own userid stamped.

- Reject non-main ?branch= requests (400). Cookie users are main-only
  via getAccessType, but the admin token bypasses it and could seed an
  orphan (org, docid, branch) room no user-facing path reads — while
  dodging the branch-scoped 409 existence check.

- Correct the concurrent-create comment: two racing creates merge as
  independently generated updates (fresh clientIDs), so the seeded
  content appears twice — user-visible duplication, not merely a
  doubly-attributed revision. Still accepted (Django creates each doc
  once and a duplicated seed is user-fixable), but the tradeoff is now
  stated accurately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-08-13 12:08:25 +02:00
349f0928fd (collaboration) add create-ydoc endpoint on yhub
Python cannot call yhub's built-in PATCH ydoc api because its body must
be lib0-any encoded - a lib0-specific binary framing with no
implementation outside javascript. The new endpoint
POST /collaboration/create-ydoc/v1/{org}/{docid} accepts the raw binary
Yjs update (pycrdt get_update() / Y.encodeStateAsUpdate output) as
application/octet-stream, so Django can seed a document's initial state
with a plain requests.post(url, data=raw_bytes) - needed by the
server-side creation flows (file import, create-for-owner, duplication,
template instantiation) whose yhub rooms currently stay empty until the
first browser connects.

Strict create semantics: 409 when the room already has content
(checked via getDoc, covering persisted state and uncompacted stream
messages; yhub has no atomic create, concurrent creates merge via CRDT
and never corrupt). The initial content is attributed to the optional
X-User-Id header, else to the caller's identity. Access uses the
default purpose, i.e. standard document write access like the built-in
ydoc routes: the admin JWT, or a user session with update ability.
Malformed updates map to 400 (the compute worker rejects them and the
pool replaces the thread), empty updates to 400, bodies over 10MiB to
413.

Gotcha worth noting: req.bytes() resolves to a Node Buffer, but yhub's
compute-task schema validates with lib0's exact-constructor Uint8Array
check, so the body is re-viewed as a plain Uint8Array before it is
handed to the compute pool.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-08-13 12:08:25 +02:00
Anthony LCandManuel Raynaud 921e4c3968 🛂(backend) add audience to jwt
Add audience to the jwt, scoping the token to it
prevents an admin JWT issued for another backend
service from being replayed against y-provider.
2026-08-13 12:08:25 +02:00
Anthony LCandManuel Raynaud 65e27305d2 🔥(helm) remove occurences of Y_PROVIDER_API_KEY
Y_PROVIDER_API_KEY is no longer used in the codebase,
so we can remove it from the helm chart and the documentation.
We adapt the documentation to use the new JWT conversion
mechanism instead.
2026-08-13 12:08:24 +02:00
Anthony LCandManuel Raynaud 23e03cc69d 🛂(y-provider) verify jwt token instead of the shared api key
The /api/convert route no longer accepts the Y_PROVIDER_API_KEY shared
secret. It now verifies the admin JWT signed by Django against the
JWKS published on its /api/v1.0/jwks endpoint.
2026-08-13 12:08:24 +02:00
Anthony LCandManuel Raynaud 2a46427c86 🛂(django) use jwt token for converter services
The Y_PROVIDER_API_KEY shared secret is replaced by a
signed admin JWT when Django calls the y-provider
conversion endpoint.
2026-08-13 12:08:24 +02:00
49089c3b3b (collaboration) add admin reset-connections endpoint on yhub 0.4.0
Add POST /collaboration/reset-connections/v1/{org}/{docid} (optional
X-User-Id header) to yhub-server. It distributes yhub recheckAuth: every
server re-runs the access check per matching connection and closes only
those whose access actually changed (close code 4401), so unaffected
clients see no reconnect churn. The endpoint authenticates with the
RS256 admin JWT issued by JWTService, verified against the backend JWKS
(new jose dependency); the admin token acts as the "system" user and is
the only principal granted the reset-connections access purpose. The
backend does not trigger it on permission changes yet - that wiring
comes separately, now that CollaborationService is gone.

yhub is upgraded to 0.4.0 and serves every route under the
/collaboration/ prefix (server.apiPrefix): the websocket moves to
/collaboration/ws/v1/docs, and the built-in document apis are meant to
be publicly exposed alongside it, with reset-connections as the one
backend-internal exception.

Also harden websocket auth: fail closed when the backend errors (only a
genuine 401/403 falls back to the anonymous identity, so a signed-in
editor can never hide from a targeted recheck under an anon userid) and
tolerate small clock skew when verifying the cached admin token.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-08-13 12:08:23 +02:00
Manuel Raynaud 27c1f8d1b4 🔥(backend) remove CollaborationService and can-edit endpoint
The CollaborationService was doing nothing since we started the
migration to yhub, all the code using it is now removed. Also the
`can-edit` endpoint and all the safeguard mechanism relying on the
presence of other users connected to the websocket will not be used
anymore, it will be possible to replace all of this with yhub, so all
this code is also removed.
2026-08-13 12:08:23 +02:00
Manuel Raynaud 7cbee2f26a 🔥(ci) remove checking print statement in lint-git
Since we use ruff, it is not needed anymore to check the presence of
print statement, the rule T201 is already doing it in a more performant
way.
2026-08-13 12:08:23 +02:00
Manuel Raynaud 1cb1c23ffe 🔧(dev) generate the JWT signing key when bootstrapping the dev stack
Thw private key needed to generate a jwt token will be mandatory. In
order to ease the development we want to automate its generation
2026-08-13 12:08:22 +02:00
Manuel Raynaud 58e577b0cc (backend) add a method to create a dedicated admin token
For now the only token we will need is ont with the admin claim set to
True. To not repeat the creation of this token again and again, we
created a dedicated method to issue this token in the JWTService class.
2026-08-13 12:08:22 +02:00
Manuel Raynaud cb58076edd (backend) publish the JWT public key on a JWKS endpoint
The yhub service will need our public key in order to validate the jwt
token we will used. We choose to expose a jwks endpoint as it is a
standard wat to do this.
2026-08-13 12:08:20 +02:00
Manuel Raynaud 7ea52473dc (backend) add a service generating cached RS256 JWT tokens
We want to generate jwt token using the RS256 algotrithm. This token
will be used for internal call with the yhub service.
2026-08-13 12:07:30 +02:00
Kevin JahnsandManuel Raynaud 4e893efb57 📄(collaboration) add license notice for yhub-server directory
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-08-13 12:04:18 +02:00
Kevin JahnsandManuel Raynaud 63e793a58b ♻️(collaboration) switch collaboration server from hocuspocus to yhub
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
2026-08-13 12:04:16 +02:00
fch-aaandAnthony LC 2da4ae2298 🐛(frontend) refresh pins after document deletion and restoration
Favorite relationships persist across soft deletion, while the sidebar keeps
a stale cached list until reload. Invalidate the favorites query after deletion
and restoration so deleted documents disappear immediately and their pins
return when restored.

Signed-off-by: fch-aa <21101725+fch-aa@users.noreply.github.com>
2026-08-13 10:00:42 +02:00
risk-alt 87e59e78fa 🐛(helm) show the database error while jobs wait for it to be ready
The migrate and createsuperuser jobs polled `manage.py check` with its
output sent to /dev/null, then printed "Database not ready" whatever
the reason. Any failure the check reports, a missing setting or a bad
credential for instance, looked like a database that had not started
yet, and the job looped forever without a single clue in its logs.

The check output is now captured and printed on each failed attempt,
along with the attempt number, so the reason the job is still waiting
is readable with kubectl logs. The retry behaviour is unchanged.

Applied to both jobs in the chart values and in the dev and feature
helmfile environments. The chart README table is regenerated
accordingly.

Signed-off-by: risk-alt <aldu6974@gmail.com>
2026-08-11 22:49:37 +02:00
risk-altandAnthony LC 44c51ff7bf 💄(frontend) use the same highlight color for cells and moves
Blocknote highlights the selected table cells with #c8c8ff66 and draws
the drop cursor of a moved block with #ddeeff: two different colors,
both out of the palette.

Use --c--contextuals--background--semantic--brand--tertiary for both, and
for the drop indicator of a moved table row or column which was #adf.
The cell overlay is blended with multiply because it is drawn on top of
the cell content while the token is opaque.

Signed-off-by: risk-alt <aldu6974@gmail.com>
2026-08-11 17:19:00 +02:00
Anthony LC c389a3c83d 🐛(y-provider) fix sentry init
Sentry should actually be initialized
before the app is created. We now start sentry
before starting the app server.
2026-08-11 15:29:06 +02:00
risk-altandAnthony LC 28438fdd92 🐛(frontend) export images embedded with a relative url
Images embedded with a relative url such as /assets/logo.png were routed
through the CORS proxy: the same origin check used a substring match on
window.location.hostname, which a relative url never contains. The
backend rejects those urls with a 400 as it only validates absolute
http(s) urls.

Resolve the url against the current origin instead, so relative and
absolute same origin urls are fetched directly. This also stops matching
unrelated external urls that merely contain the hostname, and replaces
the "base64" substring check by an explicit data: scheme check.

exportResolveFileUrl now checks response.ok as well: fetch() only
rejects on network errors, so the 400 payload was returned as a blob and
embedded in the export instead of falling back to the url.

Signed-off-by: risk-alt <aldu6974@gmail.com>
2026-08-10 12:12:39 +02:00
renovate[bot]andGitHub c9e32e34e8 ⬆️(dependencies) update dompurify to v3.4.13 [SECURITY] 2026-08-09 13:56:58 +00:00
Anthony LC b4b5f9fc2c (e2e) fix flakiness with language tests
When tests were run in parallel, the language tests
could introduce flakiness due to a switch to the
default language not being completed before the
next test started.
2026-08-07 10:47:49 +02:00
Anthony LC 58f70e0d2c 🔒️(js) fix security warning
- brace-expansion
- svgo
- postcss
- undici
- sharp
2026-08-07 09:16:33 +02:00
Anthony LC f8c4d2b619 🚨(frontend) adapt code to ui-kit v0.28
ui-kit v0.28 breaks some UI components.
This commit updates the relevant files to ensure
compatibility with the new version of ui-kit.
We update the cunningham-tokens.css and
cunningham-tokens.ts files to reflect the changes
in the design tokens.
2026-08-06 17:44:34 +02:00
Anthony LC c37e9b162f ⬆️(dependencies) update js dependencies 2026-08-06 17:44:21 +02:00
Julien Maupetit b297d79c32 🐛(backend) ignore CSPs for API docs in development
With Content Security Policies activated, swagger (and redoc)
auto-generated API documentation is no longer accessible even locally.
To restore this feature, we've excluded CSP for related URLs only in
the `Development` configuration.
2026-08-05 10:39:48 +02:00
Nathan Panchout b956be12e5 (frontend) cover present from block
Exercise block-to-slide mapping and the editor side-menu action.

Keep coverage scoped to starting the presenter from a block.
2026-08-04 17:49:24 +02:00
Nathan Panchout 7aa5935872 (frontend) start the presentation from a block
Add a "Present" item to the block side menu that opens the presenter on
the slide containing that block. Map any block id (incl. nested or
divider ids) to its rendered content slide.

Closes #2470
2026-08-04 17:49:24 +02:00
renovate[bot]andGitHub d2dc74c0f9 ⬆️(dependencies) update postcss to v8.5.23 [SECURITY]
PostCSS: Path Traversal in Previous Source Map Auto-Loading (sourceMappingURL) 
leads to Arbitrary .map File Disclosure
GHSA-r28c-9q8g-f849

PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled 
sourceMappingURL reads arbitrary .map files when from is unset
CVE-2026-69153 / GHSA-fxqj-rqcc-2cmp
2026-08-04 15:03:17 +02:00
Manuel Raynaud 1e56b5e162 ⬆️(backend) upgrade pylint to version 4.0.6
pylint-django is now compatible with latest version of pylint, we can
upgrade it safely.
2026-08-04 10:16:51 +02:00
Manuel Raynaud f7d06e45e5 🚨(backend) lint code with new ruff 0.16
New ruff version need to lint the code again and adapt exceptions
2026-08-04 10:16:51 +02:00
Manuel Raynaud a57fb7cbde ♻️(backend) remove deprecation warning from pydantic-ai library
Since pydantic-ai has ben upgraded deprecation warning were present in
the logs. This commint change how the instrumentation is enabled to be
compatible with hoe pydantic-ai manage it. Also prompt system are
ignored when they come from the front, like we are doing and dropped. To
maintain the system prompt we use the instruction parameter instead.
2026-08-04 10:16:51 +02:00
Manuel Raynaud 050591e2ee ⬆️(backend) upgrade pydantic-ai-slim and remove mistralai
We upgraded pydantic-ai-slim to the latest version and add mistral has
extra dependency. Doing this, the direct dependance to mistral can be
removed and will be managed with pidantic-ai-slim package. The import of
mistralai has changed, we have to updagre them from mistralai to
mistralai.client
2026-08-04 10:16:50 +02:00
Manuel Raynaud 7439e3f94c 🔧(backend) allow all python 3.14 versions
We don't want to restrict to the higher 3.14 version but for all
available 3.14 versions.
2026-08-04 10:16:50 +02:00
Manuel Raynaud a711e93314 ⬆️(docker) upgrade to python 3.14.6
We want to upgrade to version 3.14 of python.
2026-08-04 10:16:50 +02:00
renovate[bot]andManuel Raynaud 0f823b50fb ⬆️(dependencies) update python dependencies 2026-08-04 10:16:49 +02:00
Florent Chehab edf26d6321 (backend) conditional email notification in server to server api
Add send_notification_email flag (defaults to True) on
the ServerCreateDocumentSerializer so that we can bypass
sending the email notification when creating a document
with the server to server API.

Signed-off-by: Florent Chehab <flo@nextmile.fr>
2026-08-03 10:54:31 +02:00
renovate[bot]andGitHub eed828d8c7 ⬆️(dependencies) update js-yaml to v5.2.2 [SECURITY] 2026-07-28 19:42:08 +00:00
virgile-devandGitHub 61c2183390 📝(docs) update readme (#2508)
Reflect new features and update screenshots

Signed-off-by: virgile-deville <virgile.deville@beta.gouv.fr>
2026-07-23 09:39:19 +00:00
renovate[bot]andGitHub 845f134a51 ⬆️(dependencies) update next to v16.2.11 [SECURITY] 2026-07-23 02:11:03 +00:00
Nathan Panchout 9c3bc8ac60 (frontend) cover presenter share links
Exercise direct present links, copied slide URLs, and mobile behavior.

Keep the e2e slice scoped to the share-link workflow.
2026-07-22 11:16:35 +02:00
Nathan Panchout 33ca348b02 (frontend) open and share a presentation at a given slide
Support ?view=present&slide=N deep-links (clamped, URL kept in sync) and
a "Copy link to slide" action in the floating bar. Ignore the deep-link
on mobile.

Closes #2397
2026-07-22 11:16:35 +02:00
Anthony LC b689ee59a6 🙈(project) add AI config to gitignore
Add github AI config to gitignore.
AI instructions can be quite subjective and can be
a source of bias, so we don't commit them to the repo
yet.
2026-07-21 14:57:29 +02:00
Anthony LC c9bacaeb5e 🚨(y-provider) adapt build command to tsc-alias upgrade
Recent upgrade of tsc-alias introduced a breaking
change in the build command, which now requires the
`--project` flag to specify the path to the
tsconfig file.
2026-07-21 14:57:28 +02:00
Anthony LC ba0a80cdef ⬆️(dependency) upgrade fetch-mock to 12.6.0
Previous version had security vulnerabilities,
better to upgrade to the latest version.
We had to adapt tests to the new version of fetch-mock.
2026-07-21 14:57:28 +02:00
Anthony LC b550a4543b 🔒️(js) fix security warning
- brace-expansion
- body-parser
2026-07-21 14:57:28 +02:00
Anthony LC b17df9971c 📌(dependencies) add @gouvfr-lasuite/cunningham-react resolution
@gouvfr-lasuite/ui-kit pin @gouvfr-lasuite/cunningham-react,
so multiple versions of
@gouvfr-lasuite/cunningham-react were being installed,
which was causing issues.
We pin the version to 4.3.1, forcing all packages to
use the same version.
2026-07-21 14:57:28 +02:00
Anthony LC 11efa78088 ⬇️(dependency) downgrade ai packages to previous version
Blocknote is not compatible with the latest version
of the ai packages:
- @ai-sdk/openai
- ai
Better to downgrade to the previous version until the
compatibility issue is resolved.
2026-07-21 14:25:32 +02:00
Anthony LC a63049b398 🚨(prettier) automatic new prettier formatting
We upgraded prettier in a previous commit. Some files
were not formatted with the new prettier version.
This commit applies the new prettier formatting to
those files.
2026-07-21 14:25:32 +02:00