Chaque page, chaque composant et chaque site a une salle : un Durable Object YRoom qui synchronise un document Yjs via WebSockets, gère la présence, persiste dans son propre stockage SQLite et fait des points de sauvegarde dans Postgres. La salle est aussi le chemin d'enregistrement de l'éditeur, même quand vous travaillez seul.
Salles
- Les noms sont
page:<pageId>(pages et composants) ousite:<siteId>(liste des pages, classes, jetons, variables, formules). - Les jetons sont vérifiés par salle ; les lecteurs reçoivent le document et la présence, mais leurs mises à jour sont ignorées. Les éditeurs de contenu ne peuvent modifier que du texte.
- Les sockets hibernent : une salle inactive ne coûte donc rien ; la présence survit au réveil grâce aux pièces jointes des sockets.
- Limites : 4 Mio par message, 256 sockets par salle.
import { WebsocketProvider } from 'y-websocket'
const provider = new WebsocketProvider(realtimeUrl + '/rooms', 'page:p_home', ydoc, {
params: { token },
})
Validation côté serveur
Chaque mise à jour est d'abord appliquée à une copie fantôme. Chaque enregistrement qu'elle a touché est relu en JSON et vérifié : schéma du nœud, liaisons uniquement sur les props liables, $model uniquement sur les champs de formulaire, chaque $expr doit s'analyser, forme des workflows. Une mise à jour en échec n'est ni stockée ni relayée, et la connexion de l'expéditeur est fermée avec 4422, un code définitif pour que le client ne la renvoie pas.
Protocole
type 0 sync step1 / step2 / update (relayed to other sockets)
type 1 awareness cursors, selections (relayed to every socket)
type 3 query awareness
type 100 agent update Malla extension: origin byte (0 = ai, 1 = mcp) + Yjs update,
sent only to the sockets of the user an AI/MCP edit acted for
Persistance
- Un journal de mises à jour en ajout seul plus un instantané, compacté à 500 lignes ou 1 Mo, et quand le dernier socket se déconnecte.
- Les salles vides sont amorcées depuis Postgres avant la première synchronisation : un client ne synchronise donc jamais un document vide par-dessus du vrai contenu.
- Les points de sauvegarde dans Postgres sont retentés avec backoff pendant cinq minutes au maximum ; la synchronisation ne les attend jamais.
Modifications de l'IA et de MCP annulables
Les modifications côté serveur arrivent dans la salle via POST /internal/rooms/:room/ops, avec l'utilisateur pour le compte duquel elles sont faites. La salle les applique une seule fois, envoie aux sockets de cet utilisateur une agent update (type 100) et à tous les autres une mise à jour ordinaire. L'éditeur applique les agent updates avec l'origine ai ou mcp, que son gestionnaire d'annulation suit comme une étape distincte. Ainsi, l'utilisateur concerné peut annuler le changement de l'agent, et personne ne peut annuler celui de quelqu'un d'autre.