Rigs
Des faits, rien de plus. Pour le modèle qui les sous-tend, consultez Rigs et enceintes; pour ouvrir une machine, suivez le guide.
Surfaces et backends
Section intitulée “Surfaces et backends”| Surface | Pilote | Backend | Valeur | Sortie réseau confinée |
|---|---|---|---|---|
| Terminal (exec) | Un interpréteur de commandes sur le canal exec de la VM | microVM | smolvm |
Oui |
| Navigateur | Chromium sans interface (CDP), Firefox (WebDriver BiDi) ou WebKit (W3C WebDriver) | microVM | smolvm |
Oui |
| Ordinateur | Bureau X11 : entrée par l’hyperviseur, capture par l’agent de l’invité | QEMU | qemu-hvf (macOS), qemu-kvm (Linux), qemu-tcg (solution de repli non accélérée, jamais choisie automatiquement) |
Oui |
| Android | Android par ADB | Émulateur de Google | android-emulator |
Non — l’émulateur gère son propre réseau |
| iOS | Simulateur iOS par WebDriverAgent | CoreSimulator | ios-simulator |
Non — le réseau suit le Mac hôte |
Le terminal et la surface computer_use partagent la valeur de surface
computer; le terminal se distingue par son marqueur d’image exec et n’est
jamais réutilisé comme bureau pilotable (ni l’inverse). Une conversation
réutilise une même machine terminale.
Moteurs de navigateur
Section intitulée “Moteurs de navigateur”| Moteur | Valeur | Protocole | Vue en direct | Images fixes |
|---|---|---|---|---|
| Chromium | chromium (par défaut) |
Chrome DevTools Protocol | Diffusion d’écran — le navigateur pousse les images à mesure que la page se redessine | JPEG |
| Firefox | firefox |
WebDriver BiDi | Images fixes interrogées périodiquement (BiDi n’a pas de diffusion d’écran), plafonnées à 6 images/s | JPEG |
| WebKit | webkit |
W3C WebDriver (classique) | Images fixes interrogées périodiquement, transcodées par le ffmpeg de l’hôte | PNG |
Un rig exécute un seul moteur pendant toute sa vie. Une même conversation peut contenir un rig par moteur, ce qui rend possible la comparaison côte à côte : ouvrir « Firefox (VM) » à côté de « Chromium (VM) » donne deux machines, et fermer l’une laisse l’autre en marche.
Passez engine à rig.open ou à l’outil browser_use. Un nom inconnu est
refusé plutôt que remplacé par la valeur par défaut — demander un navigateur et
en obtenir silencieusement un autre répond à une question de compatibilité par
la mauvaise réponse.
Limites propres à chaque moteur, énoncées plutôt que contournées :
- Firefox n’a pas de rechargement contournant le cache (il rejette carrément
ignoreCachede BiDi), de sorte qu’un rechargement forcé est un rechargement normal. - WebKit n’a pas non plus de rechargement contournant le cache, ni de flux de
console (la sortie est capturée en interceptant
console.*après chaque navigation, de sorte que tout ce qui est consigné pendant le chargement est manqué — chaque extraction de console le dit), et nécessiteffmpegsur l’hôte pour sa vue en direct. - Ni l’un ni l’autre n’expose d’arbre d’accessibilité de plateforme par son
protocole, de sorte que
extract (a11y)renvoie une approximation dérivée du DOM, étiquetée comme telle. - Ni l’un ni l’autre ne peut recevoir un véritable dépôt de fichier; un champ de fichier peut tout de même être pointé vers des chemins à l’intérieur de la machine.
Images de machines
Section intitulée “Images de machines”| Surface | Image | Récupération |
|---|---|---|
| Terminal | ubuntu:24.04, épinglée par empreinte |
Automatiquement au premier démarrage, par le réseau protégé de la machine elle-même |
| Navigateur (Chromium, Firefox, WebKit) | debian:trixie-slim, épinglée par empreinte, plus les paquets propres au moteur |
Automatiquement au premier démarrage, puis mise en cache sous forme de pack préchauffé |
| Ordinateur | Une image de bureau qcow2 avec Chromium, Firefox, WebKit et le même socle d’outils CLI de type exécuteur hébergé par GitHub que celui que préchauffe le terminal | Importer sous Paramètres → Serveur → Rigs (téléchargements épinglés par somme de contrôle lorsqu’ils sont publiés) |
| Android | Images système de Google | Par le SDK Android |
| iOS | Un environnement d’exécution de simulateur Xcode plus WebDriverAgent épinglé par somme de contrôle | L’environnement d’exécution par Xcode; passerelle d’automatisation depuis Paramètres → Serveur → Rigs |
Après le premier démarrage de chaque type de microVM, le serveur met en cache
une copie préextraite sous le répertoire de données et démarre toutes les
machines suivantes à partir de celle-ci — y compris les images préchauffées avec
les paquets déjà installés. Le terminal préchauffe un socle d’outils CLI de type
exécuteur hébergé par GitHub (git, gcc, python3, jq, rsync, les outils
d’archivage et le reste de la base apt; ni Docker ni les caches d’outils de
langage). Le qcow2 Ordinateur intègre ces mêmes noms d’outils CLI au moment de
la construction de l’image, aux côtés de XFCE et des trois navigateurs. Chaque
navigateur préchauffe son moteur. Les trois moteurs partagent une base Debian
mais ne partagent jamais un pack : le cache est indexé sur l’image, le moteur
et une révision audio (audio-v1-<engine>), parce qu’une machine préchauffée
pour un moteur — ou avant que PulseAudio et ffmpeg fassent partie de la charge de
travail — ne contient rien de l’autre. Le pack du terminal est indexé sur une
révision d’outillage (tools-v1) pour la même raison : un pack préchauffé avant
que le compilateur fasse partie de l’image ne doit pas servir une machine censée
en avoir un.
Aucune image d’automatisation préintégrée ne vaut la peine d’être reprise — le
chromedp/headless-shell de Chromium exclut à la compilation ALSA et PulseAudio,
de sorte qu’il ne peut jamais émettre de son; la seule image Firefox maintenue
fait 33× la taille de la base Debian et n’embarque toujours pas socat; il
n’existe aucune image WebKit maintenue. Chaque moteur s’installe donc au premier
démarrage (chromium, firefox-esr ou webkit2gtk-driver) et atteint les
archives Debian (deb.debian.org, security.debian.org, cloudfront.debian.net)
pour ce faire. Chromium est le binaire de la distribution lancé sous la forme
chromium --headless=new.
Images personnalisées par espace de travail
Section intitulée “Images personnalisées par espace de travail”| Clé de paramètre | Remplace |
|---|---|
rigs.smolvm.execImage |
L’image Terminal (VM) |
rigs.smolvm.browserImage |
L’image Navigateur (VM) Chromium |
Défini par le magasin de paramètres d’espace de travail réservé aux administrateurs (Paramètres → Serveur → Rigs → Images personnalisées (cet espace de travail)). La valeur doit être une référence de registre — les chemins locaux, les archives et les chaînes ressemblant à des indicateurs sont refusés, tant à la saisie qu’à nouveau au démarrage. Une valeur stockée invalide est ignorée bruyamment et c’est la valeur par défaut qui démarre. Le registre propre à l’image (ainsi que les CDN de blobs connus pour Docker Hub, GHCR, Quay, GitLab et GCR) est admis par la barrière de sortie réseau pour le tirage.
Contrat d’image Terminal — bash présent; git, curl, socat
préinstallés ou une base apt Debian/Ubuntu (l’enceinte installe ces trois
outils plus un socle d’outils CLI de type exécuteur hébergé par GitHub au premier
démarrage : compilateurs, Python 3, jq, outils d’archivage, rsync. Les caches
d’outils de langage et Docker ne sont pas installés).
Contrat d’image Navigateur — une base apt Debian/Ubuntu (ou les paquets déjà
installés) avec bash et socat, plus un binaire chromium que le serveur
lance lui-même sous la forme chromium --headless=new, avec DevTools sur la
boucle locale de l’invité 9223, relayé vers le port invité 9222. PulseAudio
et ffmpeg sont installés au premier démarrage pour la voie audio. Ne construisez
pas FROM chromedp/headless-shell : en amont, headless.gn exclut à la
compilation ALSA et PulseAudio, de sorte que ce binaire ne peut pas émettre de
son. La substitution s’applique aux rigs Chromium seulement — la commande de
charge de travail qu’elle démarre est celle de Chromium, et la transmettre à
Firefox ou WebKit lancerait un binaire absent. Un rig Firefox ou WebKit l’ignore
bruyamment et démarre son image épinglée.
Ports d’automatisation — chaque machine de navigateur transfère exactement un
port de boucle locale de l’hôte vers le port invité 9222. Derrière celui-ci :
les DevTools de Chromium et l’agent distant de Firefox se trouvent sur la boucle
locale de l’invité 9223, avec un relais socat devant (les deux se lient à la
boucle locale sans condition); le pilote de WebKit accepte un --host et se lie
lui-même à la carte réseau de l’invité. Firefox valide en outre l’en-tête Host
par rapport à son propre port, de sorte que le client envoie l’autorité côté
invité plutôt que celle qu’il a contactée.
Verbes d’action
Section intitulée “Verbes d’action”Chaque action est analysée de façon exhaustive : une charge utile malformée renvoie un message nommant le champ, jamais une exception. Les verbes d’observation (marqués ○) restent autorisés pendant qu’une personne détient le contrôle; les verbes de modification sont refusés.
computer_use
Section intitulée “computer_use”screenshot○, cursor_position○, mouse_move, left_click,
right_click, middle_click, double_click, triple_click,
left_mouse_down, left_mouse_up, left_click_drag, scroll, key,
hold_key (0–60 s), type, wait○ (0–60 s), set_display,
clipboard_read○, clipboard_write.
Les coordonnées sont des pixels de l’invité dans le mode courant de celui-ci;
chaque capture d’écran indique la taille de l’affichage. Les combinaisons de
touches utilisent l’orthographe X11 (ctrl+s, alt+Tab, Return).
clipboard_read accepte une selection : clipboard (ce que remplit ctrl+C, la
valeur par défaut), primary (sélection pour copie X11) ou xdnd (un glisser en
cours). Un résultat vide est une réponse normale pour les trois. clipboard_write
n’accepte que text — les images et les fichiers passent par la voie des
fichiers, parce que les arguments d’une action sont conservés dans le journal
d’audit et que les octets d’image n’y ont rien à faire. Le contenu du
presse-papiers revient encadré comme donnée non fiable.
browser_use
Section intitulée “browser_use”navigate (http/https seulement), reload (hard facultatif), stop_loading,
click (sélecteur ou coordonnée), fill, type, key (noms de touches DOM),
scroll, mouse_move, drag, left_mouse_down, left_mouse_up,
extract○ (a11y | dom | console), screenshot○ (full_page
facultatif), set_viewport (min 320×240), history, wait_for○ (sélecteur,
0,1–30 s), clipboard_read○, clipboard_write.
Le contenu de page extrait revient encadré comme donnée non fiable.
Le navigateur n’a qu’un seul presse-papiers, de sorte que clipboard_read
n’accepte pas de selection. Les deux verbes de presse-papiers exigent un
contexte sécurisé : une page servie en http:// simple n’a aucune API de
presse-papiers, et le verbe le dit plutôt que de signaler un presse-papiers vide
— utilisez type dans ce cas, qui insère au point d’insertion sans passer par un
presse-papiers.
mobile_use
Section intitulée “mobile_use”tap, swipe (50–5000 ms), type, key (alias back, home,
recents, enter, delete, backspace, tab, escape, search,
menu, volume_up, volume_down, power, ou tout KEYCODE_*),
screenshot○, ui_dump○, install_apk
(limité à l’arbre de travail du rig et au répertoire de données du serveur), start_app,
stop_app, clear_app_data, uninstall_app, open_url, et shell.
shell accepte une liste argv et s’exécute à l’intérieur d’Android, jamais par
un interpréteur de commandes de l’hôte; il couvre les diagnostics de
développement tels que logcat, dumpsys et pm grant.
mobile_use n’a pas de verbes de presse-papiers. Depuis Android 10, seule
l’application au premier plan peut lire le presse-papiers.
ios_use
Section intitulée “ios_use”tap, swipe (50–5000 ms), type, key (enter, backspace, tab,
escape, touches fléchées ou un caractère imprimable; modificateurs command,
control, option et shift facultatifs), home, lock, unlock,
screenshot○, ui_dump○, install_app (un répertoire .app de simulateur
limité à l’arbre de travail du rig ou au répertoire de données du serveur),
start_app, stop_app, uninstall_app, open_url, et spawn. spawn
accepte argv et s’exécute dans le simulateur par simctl; il n’invoque jamais un
interpréteur de commandes de l’hôte.
Les coordonnées sont des points d’écran iOS, et non des pixels de capture d’écran. Le flux en direct conserve la taille fixe du simulateur et l’affiche en boîte aux lettres au lieu de redimensionner l’appareil. Le transfert de texte par presse-papiers de l’hôte vers le simulateur et du simulateur vers l’hôte suit la même politique d’autorisation par utilisateur et par sens que les autres rigs; les fichiers et les images ne sont pas acceptés par la voie du presse-papiers iOS.
Chaque rig crée un appareil CoreSimulator et une session WebDriverAgent qui lui appartiennent. Le fermer arrête WebDriverAgent, éteint et supprime cet appareil, puis retire son entrée du registre. Les rigs iOS ne tournent que sur un serveur macOS avec Xcode, un environnement d’exécution iOS installé et la passerelle d’automatisation épinglée. Ils n’offrent ni audio, ni microphone, ni dépôt de fichier, ni interpréteur de commandes de l’hôte, ni garantie de réseau en enceinte.
Outils de gestion
Section intitulée “Outils de gestion”| Outil | Description |
|---|---|
rig_list |
Liste les rigs d’un espace de travail avec leur surface, leur état, leur affichage et leur contrôleur |
rig_close |
Détruit un rig et jette son disque |
Cycle de vie
Section intitulée “Cycle de vie”| Phase | Signification |
|---|---|
provisioning |
Démarrage; le détail d’état reprend l’étape courante textuellement |
ready |
Joignable et acceptant des actions |
parked |
Mis en veille faute d’activité : vCPU arrêtés, mémoire RAM toujours résidente; l’action suivante le réveille |
closing |
En cours d’arrêt |
closed |
Disparu; la ligne subsiste pour la piste d’audit |
failed |
Mort ou jamais démarré; distinguable pour que l’interface puisse proposer de réessayer |
| Motif de fermeture | Déclenché quand |
|---|---|
requested |
Une personne ou un agent l’a demandé |
idleTimeout |
Inactif au-delà du double de la fenêtre d’inactivité, ou évincé pour libérer de la mémoire |
ttlExpired |
La durée de vie stricte est épuisée |
conversationEnded |
La conversation propriétaire a pris fin |
workspaceGone |
L’espace de travail a été supprimé ou l’appartenance a été perdue |
serverShutdown |
Le serveur s’arrête |
backendFailure |
L’hyperviseur est mort en dessous |
Valeurs par défaut et plafonds
Section intitulée “Valeurs par défaut et plafonds”| Valeur | Terminal | Navigateur | Ordinateur | Mobile |
|---|---|---|---|---|
| Mémoire | 512 MB | 2048 MB (Chromium); 2560 MB (Firefox, WebKit) | 4096 MB | 4096 MB |
| vCPU | 2 | 2 | 4 | 4 |
| TTL strict | 8 h | 2 h | 2 h | 2 h |
| Fenêtre d’inactivité | 45 min | 15 min | 15 min | 15 min |
| Affichage au démarrage | — | 1280×800 | 1280×800 | 1080×1920 |
- Les images fixes de la voie de l’agent sont plafonnées à 1280×800; la voie humaine négocie jusqu’à 2560×1600.
- Le budget de mémoire résidente de l’hôte pour l’ensemble des rigs est de 12 GB par défaut, compté en mégaoctets résidents (une VM en veille conserve sa mémoire RAM). L’éviction se fait selon la moins récemment utilisée et ne prend jamais une machine que quelqu’un pilote, regarde ou dans laquelle il a un terminal ouvert.
- Un terminal ouvert ou une voie d’observation empêche le rig d’être mis en veille ou récupéré faute d’activité; le TTL strict s’applique tout de même.
Ports et domaines de développement
Section intitulée “Ports et domaines de développement”| Port | Emplacement | Réservé à |
|---|---|---|
7911 |
Invité du terminal | Le multiplexeur de ports sur lequel passe chaque transfert |
9222, 9223 |
Invité du navigateur | Le relais et le point de terminaison d’automatisation (WebKit se lie directement à 9222 et n’utilise aucun relais) |
80, 443 |
Boucle locale de l’invité du navigateur | Les voies HTTP/HTTPS des domaines de développement |
- La découverte interroge les ports TCP en écoute de l’invité du terminal toutes les ~4 s, côté serveur.
- Au plus 16 ports sont transférés automatiquement par rig; les autres sont listés dans le journal, sans être transférés.
- Le transfert côté hôte se lie à la boucle locale, en préférant le numéro de port de l’invité; Partager sur le réseau local ajoute un port LAN attribué par le système.
- Les domaines de développement doivent correspondre à
name.testouname.localhost(en minuscules, étiquette d’au plus 63 caractères). Un domaine correspond à un port. - Le HTTPS des domaines de développement utilise une autorité de certification
locale au serveur (EC P-256, sous
<dataDir>/rigs/tls/, clés en 0600 et jamais dans un invité) avec un seul certificat feuille générique pour*.test/*.localhost. Sansopensslsur l’hôte, pas de voie HTTPS; le HTTP simple achemine quand même.
Valeurs par défaut de sortie réseau
Section intitulée “Valeurs par défaut de sortie réseau”| Surface | Liste d’hôtes autorisés par défaut |
|---|---|
| Terminal | La base de référence du développeur en bac à sable (forges, registres de paquets, fournisseurs de modèles) + les miroirs apt Ubuntu + l’hôte de forge propre à l’arbre de travail |
| Navigateur | usectrl.dev (le site du produit) — plus les archives Debian au premier démarrage de chaque moteur, pendant l’installation de ses paquets. La page d’accueil est un document file:// local et n’a besoin d’aucune sortie réseau |
| Ordinateur | Vide — tout est refusé — jusqu’à ce qu’un appelant accorde des hôtes |
| Mobile | Non appliquée (réseau géré par l’émulateur) |
Chaque microVM obtient en outre les hôtes de registre de son image, pour le tirage uniquement. L’ensemble d’hôtes autorisés du courtier d’identifiants est dérivé de la même liste : aucun jeton n’est émis pour un hôte que l’invité ne peut pas atteindre.
Presse-papiers et transfert de fichiers
Section intitulée “Presse-papiers et transfert de fichiers”Les deux sens du copier-coller, et le glisser-déposer de fichiers vers l’intérieur et vers l’extérieur. À la disposition d’une personne qui pilote un rig; un agent obtient le presse-papiers par les verbes ci-dessus et aucun transfert de fichiers du tout (il dispose déjà d’un interpréteur de commandes à l’intérieur de l’enceinte).
Le franchissement du presse-papiers est propre à chaque utilisateur et à chaque sens. Le collage de l’hôte vers un rig est autorisé par défaut; la copie d’un rig vers l’hôte demande d’abord une autorisation (une autorisation de dix minutes, ou toujours autoriser sous Paramètres → Serveur → Rigs → Accès au presse-papiers). Les deux choix sont indépendants et ne constituent jamais un paramètre d’espace de travail.
| Voie | Route | Contenu |
|---|---|---|
| Presse-papiers | GET/POST /rig/clipboard/<rigId> |
Du texte, un PNG/JPEG (≤16 MB) et les chemins d’invité des fichiers présents dans le presse-papiers |
| Fichiers | POST /rig/files/<rigId> |
Jusqu’à 64 fichiers, ≤256 MB chacun et ≤512 MB par dépôt, avec un point de dépôt facultatif en pixels de l’invité |
| Fichiers | GET /rig/files/<rigId>?p=<base64url path> |
Les octets d’un fichier, en sens inverse |
- HTTP, pas RPC. La socket RPC ferme une connexion dès qu’une trame entrante dépasse 256 KB — une protection contre les attaques DoS qui convient aux commandes JSON et qui est fatale à une capture d’écran collée. Les octets empruntent le même type de route que celui déjà utilisé par les trames de rig et l’audio de réunion.
- L’authentification repose sur la cible signée
rig-files:<workspaceId>/<rigId>plus l’appartenance à l’espace de travail — une cible distincte, de sorte qu’une URL émise pour regarder une machine ne peut pas aussi y écrire des fichiers. - La prise de contrôle s’applique. Écrire dans le presse-papiers et déposer des fichiers sont des actions de modification, et elles sont refusées pendant que quelqu’un d’autre détient le contrôle; lire le presse-papiers et extraire un fichier sont des observations et ne le sont pas.
- Où arrivent les dépôts :
~/Drops(bureau),~/drops(terminal — à côté de l’arbre de travail, jamais dedans, de sorte qu’un dépôt n’apparaisse jamais comme une modification non suivie),/tmp/cc-drops(navigateur). C’est le serveur qui choisit le répertoire; un appelant ne peut pas le nommer. Les fichiers existants ne sont jamais écrasés — un nom en collision arrive sous la forme2-name.ext. - Ce qu’on annonce à l’invité : une page de navigateur reçoit un véritable
événement de dépôt à l’endroit demandé (
Input.dispatchDragEvent); un bureau reçoit les fichiers plus leurs URI dans son presse-papiers, car aucun hôte ne peut synthétiser un glisser XDND vers une boîte à outils arbitraire sans un démon privilégié dans l’invité. La réponse indique lequel des deux s’est produit. - Le glisser vers l’extérieur ne fonctionne que sur le bureau et lit la
XdndSelectionde l’invité pendant qu’un glisser est en cours. Une charge utile identique à ce que l’invité détenait déjà au début de l’appui est traitée comme une sélection périmée d’un glisser terminé, et non comme une nouvelle — X n’a pas d’étape « le glisser est terminé ». - Exigences relatives à l’image : l’image de bureau doit être de protocole 2 ou ultérieur (construite après l’arrivée de la prise en charge du presse-papiers). Une image plus ancienne répond 404 et l’application invite à la reconstruire plutôt que de signaler une machine défectueuse.
- Le journal d’audit consigne la forme, jamais le contenu : les lignes
clipboard_read,clipboard_write,drop_filesetread_fileportent des comptes, des tailles et des chemins. Un presse-papiers est l’endroit où vivent les identifiants pendant quelques secondes à la fois, et rien de tout cela n’est écrit.
Garde-fous, événements, stockage
Section intitulée “Garde-fous, événements, stockage”- Les outils de rig déclarent la classe d’action
enclosureControl(plusnetworkEgressetprocessSpawnsur les outils d’utilisation;mobile_useetios_usedéclarent aussipackageInstall).rig_closedéclareenclosureControl;rig_listn’en déclare aucune. Autorisée par défaut; les modes en lecture seule la refusent entièrement; le réglage d’autonomie par espace peut la ramener à une demande d’approbation. - Événements de domaine :
RigClosedEvent(avec son motif de fermeture),RigControlChanged(prise de contrôle / remise du contrôle),RigReaped(récupération pour inactivité, TTL ou éviction de mémoire, avec l’agent pilote). L’ouverture d’un rig n’est pas un événement. Voir les événements de domaine. - Stockage :
rig_sessionsetrig_action_logdans la base de données de chaque espace de travail. Le journal d’actions consigne chaque événement d’entrée avec son principal et une séquence monotone propre au rig; le texte saisi est réduit à une longueur et à un hachage avant d’être écrit. - Répertoire de données :
rigs/images/(images qcow2 importées),rigs/smolvm/(état d’exécution propre à chaque rig),rigs/smolvm-packs/(packs de machines préextraits),rigs/tls/(l’autorité de certification des domaines de développement),rigs/run/(surcouches et amorces QEMU). - Routes : la vue en direct est un onglet dans un espace ou une page de PR;
/settings/server/rigsest l’écran de paramètres Rigs.