Multijoueur — identité, appartenance et présence
Control Center fonctionne pour un opérateur seul, mais le modèle qui le sous-tend est multi-acteurs dès le départ. Les humains et les agents échangent des messages dans les mêmes espaces, modifient les mêmes tickets et figurent sur la même liste de participants. Rendre cela sûr et compréhensible se ramène à trois décisions : qui compte comme acteur, ce qui contrôle l’accès et quel état est partagé durablement plutôt que simplement diffusé en direct.
Les principaux : les utilisateurs et les agents sont des acteurs à parts égales
Section intitulée « Les principaux : les utilisateurs et les agents sont des acteurs à parts égales »Tout ce qui consigne « qui a fait ceci » — messages, tickets, revues, plans,
journaux d’exécution, entrées d’audit — se résout par un principal, une
union scellée de UserPrincipal et AgentPrincipal dotée d’une forme compacte
sur le fil (user:<id> / agent:<id>). L’attribution ne réduit jamais N
humains (ou N agents) à un seul compte sentinelle, de sorte qu’une revue
laissée par un agent et une revue laissée par une personne se distinguent
partout où elles apparaissent.
Parce que le principal est l’unité d’identité, il est aussi l’unité de confinement :
- Les limites de débit s’appliquent par principal, et non par session. Le garde-fou anti-inondation des appels d’outils à distance établit son budget par utilisateur, et non par connexion : tous les appareils d’un membre puisent dans une même fenêtre glissante partagée (120 appels par minute, dont au plus 30 peuvent modifier l’état), de sorte qu’ouvrir trois appareils ne triple le quota de quiconque et qu’un membre bruyant ne peut pas affamer les autres.
- L’annulation s’applique par principal. Le journal d’actions de chaque client n’enregistre que les modifications effectuées par son principal. Vous pouvez annuler votre propre modification de ticket avec ⌘Z, mais vous ne pouvez pas annuler celle d’un collègue — au moment où vous la voyez, la voie durable l’a déjà résolue (voir plus bas).
L’appartenance est la frontière d’accès, et non la clé d’appairage
Section intitulée « L’appartenance est la frontière d’accès, et non la clé d’appairage »Deux identifiants distincts répondent à deux questions distinctes. La clé d’appairage (voir Contrôle à distance et mobile) authentifie un appareil auprès du serveur. L’appartenance autorise l’utilisateur de cet appareil à agir à l’intérieur d’un espace de travail. Un appareil appairé dont l’utilisateur ne détient aucune appartenance dans un espace de travail ne peut ni le lire ni le modifier.
L’appartenance est constituée d’une ligne par couple (espace de travail, utilisateur), stockée dans le fichier de base de données propre à cet espace de travail — ainsi, « qui se trouve dans cet espace de travail ? » est une lecture à portée ordinaire, tandis que la question inverse, « dans quels espaces de travail suis-je ? », s’étend nécessairement sur plusieurs fichiers et constitue l’une des rares diffusions sanctionnées entre espaces de travail. C’est ce que le sélecteur d’espace de travail exécute avant qu’un espace de travail ait été choisi.
Chaque ligne porte un rôle issu d’une échelle de cinq niveaux classés par rang :
| Rôle | Peut |
|---|---|
owner |
Contrôle total, y compris la suppression de l’espace de travail ; exactement un par espace de travail |
admin |
Gérer les membres, les invitations, les paramètres et les opérations destructrices |
member |
Lecture-écriture au quotidien : messages, tickets, exécutions d’agents |
viewer |
Lecture seule dans tout l’espace de travail ; des motifs d’exclusion de secrets masquent les chemins correspondants sur les surfaces porteuses de code |
guest |
Le même plancher de lecture seule que le rôle viewer, au rang le plus bas de l’échelle |
Chaque décision d’accès se ramène à « le rôle de l’appelant est-il au moins
X ? ». Le plancher est dérivé du type de l’opération, à moins que celle-ci n’en
déclare un explicitement : une lecture exige guest, une modification exige
member, une opération destructive exige admin. Les listes de contrôle
d’accès par objet, au-delà des autorisations par dépôt décrites ci-dessous, sont
délibérément hors périmètre.
Les invitations sont le moyen d’accorder l’appartenance, depuis Paramètres →
Espace de travail → Membres. Un administrateur génère un code à usage unique
(sous forme de lien ou de QR code) qui expire après sept jours par défaut ; le
serveur ne stocke que le hachage SHA-256 du code, et le code lui-même n’est
affiché qu’une seule fois. L’utiliser provisionne l’utilisateur à la volée
(JIT), enregistre l’appartenance au rôle de l’invitation (jamais owner — la
propriété se transfère explicitement, jamais par invitation) et enchaîne avec
l’appairage de l’appareil. Les identifiants d’appareil émis après l’appairage
sont eux-mêmes limités à 30 jours, de sorte qu’un appairage n’est pas une clé
permanente.
Les autorisations par dépôt se situent sous l’appartenance. Comme le serveur
détient des copies de travail complètes, l’appartenance à un espace de travail
ne doit jamais, à elle seule, accorder plus de privilèges que la forge : chaque
surface porteuse de code — fichiers, diffs, revue de PR, recherche de code —
vérifie l’autorisation du membre sur ce dépôt. Les autorisations sont définies
par triplet (espace de travail, utilisateur, dépôt) et classées none → read
→ review → write, où write signifie diriger des exécutions d’agents qui
écrivent dans le dépôt. L’absence de ligne signifie none ; les propriétaires
et les administrateurs détiennent implicitement write sur chaque dépôt lié et
ne portent aucune ligne.
Deux voies pour l’état de collaboration
Section intitulée « Deux voies pour l’état de collaboration »Control Center répartit l’état partagé en deux voies aux règles de durabilité opposées, parce que les deux types d’état échouent de manières opposées.
La voie éphémère de la présence
Section intitulée « La voie éphémère de la présence »La présence — qui est en ligne, où chacun se trouve, ce que chacun est en train
d’écrire, ce qu’un agent fait à l’instant — ne vaut rien dès qu’elle est
périmée. Si elle était persistée, chaque reconnexion devrait réconcilier « la
base de données dit que Sam modifie ce ticket » avec la réalité. C’est pourquoi
la présence n’est jamais écrite dans la base de données. Elle réside dans un
concentrateur de présence en mémoire sur le serveur : les clients publient
avec presence.update, les pairs s’abonnent avec presence.watch, et les
entrées expirent automatiquement après trois battements de cœur manqués (les
battements ont lieu toutes les 10 secondes ; le concentrateur balaie toutes les
5 secondes). Il n’y a rien à réconcilier — seulement à laisser expirer.
Deux propriétés rendent cette voie fiable :
- L’identité provient de la session, jamais des arguments du client. Le
serveur associe l’appareil authentifié de la connexion à un identifiant
d’utilisateur ; un client ne peut jamais mettre à jour que sa propre présence,
de sorte que personne ne peut usurper le statut ou le locus d’un autre
participant. Une mise à jour
offlineexplicite (déconnexion ou bascule d’invisibilité) supprime immédiatement l’entrée. - La liste des participants passe par le concentrateur du serveur. Les pairs n’échangent jamais leur présence directement, de sorte que chaque participant voit la même liste, quelle que soit la topologie. Les agents n’ont pas de client ; le serveur synthétise donc leurs entrées à partir de l’état des exécutions en direct — réflexion, en cours, bloqué sur une barrière d’approbation, terminé — une seule exécution représentative décidant de l’état et du locus d’un agent, pour que des exécutions simultanées ne fassent pas osciller la liste.
La diffusion est étagée par consommateur : le poste de bureau et le Web empruntent un palier complet (au plus une émission de la liste toutes les 100 ms), le téléphone un palier de synthèse (toutes les 500 ms), pour que des mises à jour à la cadence du curseur ne fassent pas fondre la PWA.
Le locus d’un participant — l’endroit où il se trouve actuellement, jusqu’à
l’artefact près — est une union scellée : Space, File (dépôt + chemin + ligne
facultative), Pr, Ticket, PlanNode. Tous les locus n’ont pas de destination
vers laquelle sauter : il n’existe pas de route de visionneuse de fichiers, de
sorte qu’un locus File s’affiche comme une étiquette plutôt que comme une
destination. La voie transporte aussi des revendications souples (« Sam
modifie ce ticket », « un agent détient cet arbre de travail ») : la visibilité
des conflits, pas des verrous. Les types de locus inconnus sont interprétés
comme null, de sorte qu’un ancien client n’affiche tout simplement pas ce qu’il
ne comprend pas.
La voie durable partagée
Section intitulée « La voie durable partagée »Les enregistrements qui doivent survivre — tickets, document Notes partagé de l’espace, messages — empruntent le chemin opposé : faisant autorité, ordonnés et persistés. Les modifications simultanées se résolvent par le dernier écrivain l’emporte (LWW) selon l’ordre de réception par le serveur, jamais selon les horloges des clients. La résolution est délibérément à grain fin : les modifications de ticket se font par colonne, de sorte que deux personnes modifiant des champs différents du même ticket aboutissent toutes les deux et qu’aucune n’écrase l’autre (les transitions de flux de travail conservent plutôt un verrouillage optimiste) ; le document Notes de l’espace ne forme qu’une seule colonne, de sorte que tout le document suit le LWW, les revendications souples de la voie de présence rendant la modification simultanée visible plutôt que verrouillée. Ce n’est délibérément pas un CRDT — la charge de la preuve incombe au CRDT, et le LWW selon l’ordre de réception, conjugué à des revendications visibles, couvre les schémas de collaboration réels.
« Dernier écrivain » désigne l’ordre de réception par le serveur, jamais une horloge de client — un ordinateur portable dont l’horloge est décalée ne peut pas gagner une modification qu’il a perdue. Derrière la voie durable se trouve le flux de synchronisation : des déclencheurs SQLite ajoutent chaque modification à un journal des modifications propre à l’espace de travail à l’intérieur de la transaction d’écriture, en allouant un numéro de séquence monotone propre à l’espace de travail dans la même transaction que la modification elle-même. Un service du serveur suit ce journal et le transforme en trames delta versionnées, dans l’ordre de la séquence. Les clients passent des instantanés complets aux deltas ; une lacune dans la séquence fait retomber le magasin concerné en mode instantané plutôt que d’appliquer des trames de façon erronée.
Suivre, guider, prendre le contrôle, rendre la main
Section intitulée « Suivre, guider, prendre le contrôle, rendre la main »La voie de présence n’est pas qu’une liste de participants — elle pilote les verbes de collaboration :
- Mode suivi. Cliquez sur un participant et votre client suit son locus, en naviguant à mesure que lui navigue. Le suivi dure « jusqu’à ce que vous agissiez » : dès que vous naviguez de votre propre chef, le suivi se détache. Une bannière que l’on peut fermer annonce quand un autre participant met en avant (présente) un espace où vous vous trouvez.
- Guider. Un message adressé à un agent en cours d’exécution est mis en file comme consigne de pilotage ; l’agent le relit avant de reprendre son tour suivant, de sorte que vous pouvez corriger le cap d’une exécution en plein vol sans l’interrompre.
- Prendre le contrôle. Prendre le contrôle d’une conversation met en pause chaque exécution active à sa prochaine frontière de tour nette (une exécution Claude Code, qui n’a pas de frontière sûre, est arrêtée) derrière un instantané git par tour, de sorte que la prise de contrôle est réversible. Un marqueur durable bloque les nouveaux lancements dans l’espace et survit à un redémarrage du serveur — le serveur ne reprend jamais automatiquement par-dessus la modification à moitié terminée d’un humain. Un seul éditeur actif par arbre de travail constitue une revendication souple : une deuxième prise de contrôle est visible et refusée, et non fusionnée en silence.
- Rendre la main. Rendre le contrôle publie dans l’espace un résumé structuré du diff de l’arbre de travail, le met en file comme consigne de pilotage pour les exécutions en pause, les reprend et efface le marqueur.
Le cadran d’autonomie
Section intitulée « Le cadran d’autonomie »Le guidage et la prise de contrôle sont des interventions a posteriori. Le cadran d’autonomie est le réglage permanent : défini par espace et par agent, depuis l’en-tête de l’espace, il décide de ce qui se produit quand un agent atteint une action soumise à autorisation.
| Niveau | Valeur transmise | Effet sur un appel d’outil soumis à autorisation |
|---|---|---|
| Proposer uniquement | proposeOnly |
Refusé d’emblée, avec une raison que l’agent est chargé de relayer — il peut décrire l’action, mais pas l’exécuter |
| Agir avec approbation | actWithApproval |
La barrière d’approbation à refus par défaut : une confirmation est présentée à un opérateur connecté, et l’absence d’approbateur vaut refus |
| Agir librement | actFreely |
Préapprouvé, sauf lorsqu’une règle de garde-fou deny stricte s’applique — une règle de refus l’emporte toujours |
| (non défini) | null |
Identique à « agir avec approbation » : la valeur par défaut du serveur |
Deux éléments échappent au cadran, dans les deux sens. Le verbe de sortie propre
à un mode est épinglé et ne peut jamais être refusé, quoi que dise le cadran — le
mode orchestrate a déjà été structurellement incapable d’émettre son seul
livrable parce qu’un préréglage refusait la classe d’effets que ce verbe
déclare. Et un deny strict provenant des garde-fous d’action ne peut pas être
annulé par actFreely.
Aucune régression en solo
Section intitulée « Aucune régression en solo »Tout cela est additif. Le flux de travail d’un opérateur en solo ne change pas : avec un seul humain et aucun agent, le concentrateur de présence n’a rien à diffuser, de sorte que la voie émet son instantané initial puis reste inactive sans aucun trafic ; la mécanique LWW et de synchronisation demeure le même chemin à écrivain unique qu’elle a toujours été ; et la clé d’appairage reste l’identifiant d’appareil qu’elle a toujours été. L’appartenance constitue déjà la frontière d’accès — avec un seul humain, il y a une seule ligne de propriétaire et aucun élément d’interface propre à la liste des participants.
Concepts connexes
Section intitulée « Concepts connexes »- Espaces de travail et isolation : la frontière que l’appartenance fait respecter
- Contrôle à distance et mobile : le volet identité de la clé d’appairage et de l’identifiant d’appareil
- Le modèle d’agent : la part agent de l’union des principals
- Cycle de vie du lancement d’un agent : les exécutions que le guidage et la prise de contrôle mettent en pause et reprennent
- Garde-fous : la politique de classes d’effets avec laquelle le cadran d’autonomie se combine
- Événements de domaine : le bus sur lequel circulent les mises à jour en direct