✨(collaboration) notify the backend when the worker persists new content

notify the backend when the worker persists new content for
a document, so the lists ordered by `updated_at` follow the edits made on the
collaboration server. The backend serves it on
`POST /api/v1.0/documents/{id}/content-updated/`, authenticated with a short
lived RS256 JWT the collaboration server signs (`aud: "docs-backend"`) and
the backend verifies against the JWKS the collaboration server publishes on
`/collaboration/jwks/v1` — the mirror of the admin token the backend signs to
call it, so no long lived secret is shared and either side can roll its key
on its own
This commit is contained in:
Manuel Raynaud
2026-09-21 14:46:11 +02:00
parent 6f77d73e0e
commit b2be3bd2cb
15 changed files with 939 additions and 30 deletions
+21 -1
View File
@@ -13,6 +13,10 @@ update), `rollback`, `prune`, `changeset` and `activity`, all at `v1`. yhub also
accepts a `branch` query parameter, but our auth plugin only ever grants access
to the `main` branch, so this service never sends it.
A few routes are about the server itself rather than about a document, and
carry no room: `/{prefix}/jwks/{version}` publishes the public keys validating
the tokens yhub signs to call us back.
This service only owns the transport for now, the endpoints are added as we
need them.
"""
@@ -23,7 +27,7 @@ from django.conf import settings
import requests
from core.services.jwt_services import Audiences, JWTService
from core.services.jwt_services import Audiences, JWKSClient, JWTService
logger = logging.getLogger(__name__)
@@ -134,6 +138,22 @@ class YHubService:
)
return f"Bearer {token}"
@property
def jwks_url(self):
"""Return the url yhub publishes its public keys at."""
return f"{self.base_url}/{self.api_prefix}/jwks/{self.api_version}"
@property
def jwks(self):
"""
Return the client of the keys validating the tokens yhub signs.
The mirror of the JWKS we publish for the tokens we sign to call it:
neither side holds a copy of the key of the other, so either can roll
its own without the other being reconfigured.
"""
return JWKSClient(self.jwks_url)
def build_url(self, endpoint, document):
"""Build the url of a document scoped endpoint of the yhub API."""
return (