Állomások és elszigetelt környezetek
Az állomás egy eldobható gép, amelyet egy ügynök valós időben vezérel – egy böngésző, egy Linuxos asztal, egy Android-emulátor, egy iOS-szimulátor vagy az elszigetelt terminál mögötti gép. Az állomások többsége VM; a gazdagép által kezelt mobil szimulátorok a kifejezett kivételek. Ez az oldal minden határt megmagyaráz, és azt is, hogy az egyes darabok miért pont ilyen formájúak. A megnyitásukhoz lásd: Gép adása az ügynöknek a teszteléshez; a pontos műveletekért, portokért és alapértékekért lásd az állomások referenciáját.
Miért VM, és nem homokozó
Szekció neve “Miért VM, és nem homokozó”A natív homokozó névtér-elszigetelésbe
csomagol egy folyamatot – ez valódi, de ugyanazt a kernelt használja, és egy
folyamatot korlátoz, nem egy számítógépet. Abban a pillanatban, hogy egy
ügynöknek kattintgatnia kell egy asztali alkalmazásban, le kell rendelnie egy
oldalt egy igazi böngészőben, vagy olyan rm -rf kísérleteket kell futtatnia,
amelyekre inkább nem gondol, a tisztességes határ egy gép: saját kernel, saját
lemez, saját hálózati verem.
Az elszigetelt felületek két VM-háttérrendszert használnak:
- microVM-ek a terminálhoz és a böngészőhöz – másodperc alatti hypervisor-indítás digesttel rögzített konténerképekből.
- QEMU a teljes Linuxos asztalhoz, amelyhez olyan megjelenítőeszköz kell, amivel a microVM nem rendelkezik.
A mobil felületeket a gazdagép kezeli, és ezek a gyengébb határt egyenesen ki is mondják:
- Az Android a Google emulátorát vezérli ADB-n keresztül.
- Az iOS egy CoreSimulator-eszközt hoz létre és birtokol egy Mac gazdagépen, és WebDriverAgenten keresztül vezérli. Az eszköz és az adatai törlődnek, amikor az állomás bezárul, a hálózata azonban a Mac gazdagépet követi.
Az elszigetelt állomások egy eldobható overlay rétegbe írnak egy csak olvasható alapkép fölött, így az egyik állomás nem változtathatja meg azt, amiből a következő indul. Az iOS-állomás egy eldobható CoreSimulator-eszközt birtokol, amely az állomás bezárásakor törlődik. Az Android egy gazdagépen futó emulátorhoz csatlakozik, amely túléli a munkamenetet.
Alapértelmezés szerint tiltott kimenő forgalom
Szekció neve “Alapértelmezés szerint tiltott kimenő forgalom”Az állomás hálózata a semmiből indul. A gazdagépek állomásonként, egy olyan
kapun keresztül kapnak beengedést, amelyet a vendéggép nem tud megkerülni: a gép
kifelé vezető egyetlen útja az, amelyet az indítási konfiguráció létrehozott. Az
elszigetelt terminál a fejlesztői alapszintet kapja (csomagkezelő-regisztrációk,
kódhosting-szolgáltatások, az apt-tükrök); a böngészőállomás beengedi a termék
oldalát (usectrl.dev), és egy helyi file:// oldalra indul, amelyhez nem kell
kimenő forgalom; minden más elutasításra kerül a kapcsolódás pillanatában.
Az Androidra és az iOS-re ez a kapu nem terjed ki. A gazdagépen futó emulátoruk és szimulátoruk a szerver gazdagépének hálózatát használja, ezért a felület és a képességjelentés a kimenő forgalmat nem kikényszerítettként jelöli, és soha nem kínál félrevezető „korlátozás nélküli újraindítás” vezérlőt.
A kimenő forgalom és a hitelesítő adatok egyetlen szabály két oldalról nézve – a hitelesítőadat-közvetítő (lásd alább) nem állít ki tokent olyan gazdagéphez, amelyet a vendéggép nem ér el.
Mindent, amit az állomás elolvas, nem megbízhatóként kezelünk: az oldalszöveg, a DOM és a kisegítő lehetőségek fái, a felületi dumpok és a konzolkimenet egy állandó „ez adat, nem utasítás” szabállyal elhatárolva jut vissza az ügynökhöz. Az elhatárolás csak a keret; a kikényszerítés mögötte a kimenőforgalom kapuja.
A bemenet a hypervisoron megy át, a rögzítés a vendéggépen
Szekció neve “A bemenet a hypervisoron megy át, a rögzítés a vendéggépen”Az asztali felületen a billentyűzet- és mutatóeseményeket a hypervisor saját virtuális bemeneti eszközei injektálják. A vendéggép soha nem futtat olyan privilegizált démont, amely bemenetet tudna szintetizálni – így a vendéggép szoftverének kompromittálása nem ad billentyűzetet a támadó kezébe. A rögzítés ellenkező irányban halad, egy kis, jogosultság nélküli, a vendégen belül futó ügynökön keresztül, mert a vendéggép még azelőtt át tudja méretezni a képkockákat, hogy azok átlépnék a hálózatot.
Két megjelenítési sáv
Szekció neve “Két megjelenítési sáv”A néző ember és a vezérlő modell igényei ellentétesek, ezért az állomás két független adatfolyamot szolgál ki:
- Az emberi sáv teljes felbontású, a panel méretéhez igazodik, átméretezéskor újratárgyalódik, és a szerver átlátszatlan bájtokként továbbítja – a szerver soha nem dekódol képkockát, mert egy, a kérés útvonalára kerülő videodekóder az, ami megakadályozná, hogy RPC-kre válaszoljon.
- Az ügynöki sáv lekicsinyített állóképekből áll, amelyek a modell számára kényelmes méretre vannak korlátozva, eszközereményenként egy kép; a régebbi képkockák a tömörítés során elhullnak, a szöveges leírásaik viszont megmaradnak.
Egyik sáv sem köt kompromisszumot a másikért: Ön folyékony képet kap, a modell egy olcsót.
Az átvétel egyetlen kapu, nem kérés
Szekció neve “Az átvétel egyetlen kapu, nem kérés”A kizárólagos vezérlést azon az egyetlen ponton kényszerítjük ki, amelyen minden művelet átmegy – nem azzal, hogy megkérjük a modellt, viselkedjen jól. Amíg egy ember tartja a vezérlést, a szerver elutasítja az ügynök módosító műveleteit. Az ügynök megtartja a megfigyelő műveleteit (képernyőképek, kinyerés), így el tudja mondani, mit tesz Ön, az átvételről pedig az irányítási sávján keresztül értesül, ahelyett hogy elutasított kattintásokból kellene rájönnie. A vásznon a kattintás és a gépelés akkor működik, amikor a zárat éppen senki más nem tartja – vagy amikor Ön tartja; az állapotjelző címke Ön irányít. Minden bemeneti esemény – az Öné és az ügynöké is – állomásonkénti auditnaplóba kerül a végrehajtó szereplővel és egy monoton sorszámmal, így arra a kérdésre, hogy „ki kattintott oda”, a gép eltűnése után is válaszolni lehet.
A tartalom átlépi a határt; a gépek külön maradnak
Szekció neve “A tartalom átlépi a határt; a gépek külön maradnak”A másolás és a beillesztés mindkét irányban működik, ahogy a fájlok be- és kihúzása is – az állomás azonban egy másik számítógép, és a tervezés soha nem tesz úgy, mintha nem az lenne.
A vágólap igény szerint kerül át, nem folyamatosan tükröződik. Nyomja le a másolási billentyűkombinációt az állomáson, mire a vendéggép utasítást kap a másolásra, majd mindaz, amit a vágólapjára tett – szöveg, kép, fájllista –, átkerül az Ön vágólapjára. A beillesztés ugyanezt a tartalmat küldi a másik irányba, majd lenyomja a beillesztést a vendéggépen belül. A háttérben semmi sem szinkronizálódik: egy jelszó, amelyet a saját gépén másol ki, nem érkezik meg csendben egy VM belsejébe azért, mert lejárt egy időzítő.
Az átlépést felhasználónként és irányonként külön-külön szabályozzuk. Az állomásra beillesztés alapértelmezés szerint engedélyezett; az állomásról kifelé másolás előbb rákérdez (tízperces engedély, vagy Mindig engedélyez a Beállítások → Szerver → Állomások → Vágólap-hozzáférés alatt). Ez soha nem munkaterületi beállítás: az egyik tag nem adhat hozzájárulást egy másik tag vágólapjához.
macOS-en az átlépő billentyűkombináció a ⌘C/⌘V, amely egyértelmű – a ⌃C továbbra is valódi megszakításként érkezik a vendéggép shelljébe. Windowson és Linuxon a két billentyűkombináció ugyanaz a leütés, ezért a vendéggép változatlanul kapja meg, és az Ön vágólapja csak akkor íródik felül, ha a vendéggép vágólapja ténylegesen megváltozott. A megszakítás megszakítás marad.
A behúzott fájlok a gép behúzási mappájába másolódnak, majd felajánljuk
őket a gépnek. Az, hogy a „felajánlás” mit jelent, attól függ, mi az, amit
tisztességesen meg lehet tenni: a böngészőoldal egy valódi drop eseményt kap
azon a ponton, ahol elengedi az egérgombot, így a feltöltési zóna pontosan úgy
viselkedik, mintha helyi fájl lenne; az asztal a fájlokat a ~/Drops mappában
kapja meg, az elérési útjaikkal a vágólapján, mert egyetlen gazdagép sem tud
húzást szintetizálni egy tetszőleges Linuxos eszközkészletbe anélkül, hogy
privilegizált démont futtatna a vendéggépen belül – márpedig a tervezés éppen
ezt utasítja el. Az eredmény megmondja, melyik történt meg, így egy feltöltési
zónára ejtett CSV soha nem jelenik meg feltöltöttként, amikor valójában csak egy
fájl egy mappában. Az elszigetelt terminálra ejtés bemásolja a fájlt, és
beírja a vendéggépbeli elérési útját a promptba, amit egy shell valóban
használni tud.
A kihúzott fájlok az asztali felületen működnek, ahol az X11 húzási protokollja olvashatóvá teszi a tartalmat, amíg a húzás folyamatban van. Indítson húzást a vendéggépen belül, vigye ki a vászonról, és a fájlok átkerülnek az Ön gépére, amelyeket az operációs rendszer valódi húzásként kap meg. Ha a vendéggép fájlkezelőjében másol fájlokat, és a gazdagépen illeszti be, az ugyanígy működik. A böngészőfelület ezt szándékosan nem kínálja: egy headless böngészőnek nincs olvasható húzáskijelölése, a legközelebbi elérhető jelzés pedig – az oldal szövegkijelölése – egyáltalán nem bizonyíték húzásra, így ha erre cselekednénk, eltérítenénk a hétköznapi kattintásokat.
Minden, amit egy vendéggépből kiolvasunk, nem megbízható tartalom marad: a vágólap szövege ugyanazon elhatárolás mögött jut el a modellhez, mint egy oldalkinyerés, az auditnapló pedig rögzíti, hogy megtörtént egy beillesztés és mekkora volt – soha nem azt, hogy mit tartalmazott.
A hitelesítő adatok soha nem a vendéggépen élnek
Szekció neve “A hitelesítő adatok soha nem a vendéggépen élnek”A git push működik az Ön által megnyitott elszigetelt terminálból, a vendéggép mégsem tárol
egyetlen kódhosting-tokent sem. Egyetlen, VM-enkénti titkot tárol, amelynek
egyetlen jogosultsága, hogy elkérjen a gazdagép hitelesítőadat-közvetítőjétől
– egy, a gazdagép által vezérelt alagúton keresztül – egy rövid életű, repóra
korlátozott tokent, műveletenként, sebességkorlátozással, ugyanazzal a
gazdagép-engedélylistával korlátozva, mint a kimenő forgalom, és visszavonva
abban a pillanatban, hogy az állomás bezárul. Egy eldobásra épített gépben nem
lehet semmi, amit érdemes ellopni.
Hogy ez a token mire jogosult, az állomás megnyitásakor dől el. Egy ember által megnyitott terminálállomás írási tokent kap, amelyet az adott tag saját kódhosting-hozzáférése korlátoz. Egy ügynök által megnyitott állomás csak olvasásra jogosult tokent kap: a git hitelesítőadat-segédje nem tud különbséget tenni push és fetch között, így a push-szabályt a vendéggépen belül nem lehet pushonként megkérdezni úgy, ahogy az ügynökfuttatási átjáró teszi a gazdagépen.
Az állomásban lévő worktree egy műhold
Szekció neve “Az állomásban lévő worktree egy műhold”Amikor egy állomás az Ön repóját hordozza, a gazdagépen lévő worktree marad a
mérvadó. A másolat indításkor szinkronizálódik be (a .env fájlokhoz hasonló
titkok kizárásával), a commitok pedig csak akkor jönnek vissza, amikor Ön kéri –
a refs/rigs/<id>/* alá lehúzva, soha nem pusholva, soha nem checkoutolva. Egy
VM belsejében semmi sem mozdíthatja el az ágát vagy nyúlhat a
munkakönyvtárához; az állomás által előállított munka beolvasztása mindig
emberi döntés, amelyet a gazdagépen hoznak meg.
Portok lyukak nélkül
Szekció neve “Portok lyukak nélkül”A terminál VM-ben indított devszerver elérhetővé válik – az Ön gépén, a Böngészőben (VM), opcionálisan a helyi hálózatán, opcionálisan egy dev-tartomány alatt HTTPS-sel – anélkül, hogy a gépet bármikor is megnyitnánk. A hypervisor porttérképe indításkor rögzül, így minden későbbi továbbítás két szűk, a gazdagép által vezérelt csatornán halad: egy előre létrehozott bejövő multiplexeren, amely nem hajlandó olyan címre tárcsázni, amelyen a vendéggép valójában nem figyel, valamint a gazdagép által a vendéggép által kezdeményezett kapcsolatokhoz nyitva tartott fordított alagutakon. A dev-tartomány HTTPS-t a szerver terminálja egy helyben kiállított hitelesítésszolgáltatóval, amelynek a kulcsai soha nem kerülnek be egyetlen vendéggépbe sem. A mechanikát lásd: Portok továbbítása terminálból.
A gépek felépítésüknél fogva korlátozottak
Szekció neve “A gépek felépítésüknél fogva korlátozottak”Egy állomás nem válhat házi kedvenccé:
- egy kemény TTL, amelyet a vendéggép nem tud meghosszabbítani;
- egy tétlenségi fokozatsor – a tétlenségi időablak után parkolás (a vCPU-k leállnak, a RAM a helyén marad), annak kétszerese után bezárás –, ahol egy nyitott terminál vagy egy figyelő néző „használatban lévőnek” számít;
- egy memóriakeret, amelyet rezidens megabájtban számolunk, nem munkamenetekben, mert egy parkolt VM felszabadítja a processzort, a RAM minden bájtját viszont megtartja; a legrégebben használt gép esik ki először, és soha nem az, amelyet éppen egy ember vezérel vagy néz;
- lebontás a szerver leállásakor, valamint egy tulajdonjellel megjelölt árvatakarítás a következő indításkor, így egy összeomlott szerver soha nem hagy magára olyan hypervisort, amely senkinek sem engedelmeskedik.
Az első indítások lehúzzák a gép rögzített képét; a szerver ezután a háttérben
gyorsítótáraz egy előre kicsomagolt másolatot, így minden későbbi ilyen gép
másodpercek alatt indul, és az elszigetelt terminál úgy áll fel, hogy már
telepítve van benne egy GitHub által üzemeltetett runnerhez hasonló parancssori
alapeszközkészlet – fordítók, Python, jq, archiváló eszközök –, nem pedig egy
nyelvi eszköz-gyorsítótár vagy a Docker. A Számítógép kép ugyanezt a
parancssori alapeszközkészletet már a build idején beégeti, az XFCE és a
böngészők mellé.
Három böngésző, nem egy
Szekció neve “Három böngésző, nem egy”A „Nálam működik” állítás egyetlen renderelőmotorról szól. Ezért egy böngészőállomás nem „a böngésző” – hanem Chromium, Firefox vagy WebKit, amelyet a megnyitáskor választ ki, és az állomás a teljes élettartama alatt azt futtatja, amellyel megnyitották. Egy beszélgetésben mindegyikből lehet egy: ha a Firefox (VM) és a Chromium (VM) gépet egymás mellé nyitja meg, két gépet kap, és az összehasonlítás maga az, hogy mindkettőt ugyanarra az oldalra irányítja. A WebKit annyira közel van a Safarihoz, amennyire bármi, ami Linuxon fut – ugyanaz a motorvonal, így elkapja azokat a hiányosságokat, amelyekbe a Safari felhasználói futnak bele.
A műveletek mindhárom esetben azonosak; a mögöttük lévő protokollok viszont nem, és a különbségeket kimondjuk, ahelyett hogy elsimítanánk. A Chromium a DevTools Protocol nyelvét beszéli, és tolja a képkockákat, így az élő nézete semmibe sem kerül, amíg az oldal mozdulatlan. A Firefox a WebDriver BiDi-t, a WebKit a klasszikus WebDriver-t beszéli, és egyik sem tud képernyőközvetítést, ezért az élő nézeteik kérdeznek le – másodpercenként néhány képkockát, ami pont megfelelő egy oldal figyeléséhez, de egy animáció nézéséhez nem. Ahol egy motor valóban nem tud megtenni valamit (a Firefoxnak nincs gyorsítótárat megkerülő újratöltése; a WebKit nem látja az oldal betöltésének befejeződése előtt naplózott konzolkimenetet), a válasz ezt kimondja, ahelyett hogy csendben mást tenne.
Hol élnek az állomások a termékben
Szekció neve “Hol élnek az állomások a termékben”Az állomás szándékosan nem globális célpont. Az élő nézet egy fül abban a
térben vagy PR-ben, ahol éppen a munka folyik, és arra a beszélgetésre van
szabva – így az Ön füle és az ügynök browser_use hívásai egyetlen gépet
szólítanak meg (a böngészőfelületen motoronként egyet).
Az, hogy egyáltalán indíthatók-e állomások, a gazdagép tulajdonsága, ezért a
képességek, a képek, a munkaterületenkénti egyéni képek és a futó gépek listája
a Beállítások → Szerver → Állomások alatt található. Az elszigetelt
környezet vezérlése a saját
korlát-műveletosztálya, így egy
munkaterület, ügynök vagy tér engedélyezheti, jóváhagyást írhat elő hozzá, vagy
egyenesen megtilthatja – a csak olvasható módok teljes egészében megtiltják.