Nasazení a klienti
Control Center není jeden program. Je to architektura tenkého klienta: server bez rozhraní, který vlastní tvoje data, a sada klientů, kteří přes jedno spojení RPC kreslí rozhraní. Tohle rozdělení vysvětluje, proč některé věci běží tam, kde běží, a na co který klient dosáhne a na co ne.
Server vlastní data
Sekce “Server vlastní data”Proces jménem cc_server drží databáze — malý global.db pro stav celého
serveru plus jeden soubor SQLite na každý
pracovní prostor, otevřený až
ve chvíli, kdy je potřeba — a spouští dlouho žijící práci: enginy pipeline,
reconcilery, plochu nástrojů MCP a posluchače orchestrace. Všechno, co má
přežít okno, nebo co mají dva klienti vidět stejně, žije tam.
Žádný klient neotevírá databázový soubor sám. Každý místo toho drží jednoho
RemoteRpcClient a přes něj posílá operace nad repozitáři a odběry.
Server spojení ověří proti předem sdílenému klíči spárovaného zařízení a pak
už ho spojení nezajímá. Relace není vázaná na pracovní prostor. Dispečer
je bezstavový: každé volání vázané na pracovní prostor nese ve svých
argumentech vlastní workspace_id a volání, které ho vynechá, se odmítne.
Je to schválně. Díky tomu můžou dva klienti na jednom serveru sedět v různých pracovních prostorech a nemají serverem držený „aktuální pracovní prostor“, o kterém by se mohli rozejít. Izolace se místo toho vynucuje u každého volání, ve čtyřech krocích:
- Operace deklaruje, jestli je vázaná na pracovní prostor; když je a
nedorazilo
workspace_id, volání se odmítne. - Uvedené id musí být registrovaný pracovní prostor a kontrola proběhne
dřív, než cokoli otevře databázi. Jinak by neznámé id při každém požadavku
vytvořilo prázdný přízrak
workspace.db. Chybějící id je nenalezeno. WorkspaceRolevolajícího musí splnit spodní hranici operace, odvozenou od jejího druhu: čtení vyžaduje roli Host, změna roli Člen, destruktivní operace roli Admin.- Operace, která odhaluje obsah repozitáře, navíc vyžaduje oprávnění k danému
repozitáři na úrovni, kterou deklaruje —
none/read/review/write— aby členství v pracovním prostoru nikdy tiše nepřekonalo oprávnění forge.
Věta, na které záleží: držet párovací klíč není hranice přístupu; tou je členství.
Proč to tak rozdělit
Sekce “Proč to tak rozdělit”K serveru vedly tři tlaky:
- Jeden zdroj pravdy. Desktop a telefon, nebo notebook a desktop, mají vidět stejný stav flotily. Kdyby každý vlastnil vlastní databázi, rozešly by se. Jeden server znamená, že každý klient čte tatáž živá data.
- Web se neobslouží sám. Prohlížeč neumí spustit podproces ani otevřít místní soubor, takže webové sestavení nikdy nemůže vlastnit databázi ani spustit agenta. Musí mluvit se serverem, který to umí. Místo druhé, čistě webové datové cesty se na stejnou cestu dostal i desktop.
- Provoz bez rozhraní. Server, který spustíš na malém stroji a dosáhneš na něj z telefonu ve vlaku nebo z prohlížeče kdekoli, je užitečnější než grafické rozhraní, které musíš nechat otevřené.
Daní za to je, že server je teď závislost: když neběží, nefunguje nic. Výchozí odpověď desktopu je spustit ho sám.
Klienti
Sekce “Klienti”Na server dosáhne pět klientů, každý s jiným tvarem a profilem důvěry.
Aplikace pro počítač
Sekce “Aplikace pro počítač”Desktopová aplikace ve Flutteru (macOS, Windows, Linux) je plný klient. Při prvním spuštění se zeptá, jak má běžet, a volbu si pak pamatuje:
- Místní: spustí a hlídá
cc_serverna tomhle stroji. Výchozí, samostatné nastavení pro jednoho uživatele. Desktop server spustí, ten vlastní databázi pod kořenem podpory aplikace a mluví s ním přes loopback. - Vzdálené: připojí se k
cc_server, který běží jinde, přes zabezpečený WebSocket. Data žijí na tom serveru; tenhle desktop jen vykresluje.
V obou případech výsledný klient RPC přepíše poskytovatele dat aplikace, takže celé rozhraní — každá obrazovka, každá funkce — čte a zapisuje přes server. Desktop se databázového souboru přímo nikdy nedotkne.
Webový klient
Sekce “Webový klient”Webové sestavení je ta samá aplikace ve Flutteru, přeložená pro prohlížeč a
hostovaná na app.usectrl.dev, takže není co
instalovat. Prohlížeč neumí spustit podproces, takže webový klient je
vždy vzdálený: naváže cc_server přes wss:// a vykreslí plné desktopové
rozhraní. Po připojení ukazuje tytéž obrazovky nad toutéž flotilou, protože je
to tentýž kód nad týmž RPC. Mezery jsou ta hrstka míst, která potřebují
nativní schopnost, kterou prohlížeč nemá. Hlavní je vrstva kvality záznamu
schůzky níže, další jsou oznámení operačního systému.
Proto jsou „bez stahování“ a „bez serveru“ různá tvrzení. Webový klient
odstraňuje instalaci, server ne. Kam se připojuje, může být cc_server na
tom samém notebooku — ws://localhost:9030, který nepotřebuje certifikát,
protože prohlížeče berou loopback jako důvěryhodný — nebo server na jiném
stroji, který musí být dostupný přes wss:// s certifikátem, jemuž prohlížeč
důvěřuje. cc_server odmítne naslouchat na adrese mimo loopback bez TLS, takže
vzdálený server znamená vlastní certifikát, proxy, která TLS ukončuje, nebo
tunel či VPN, která ho dodá.
Samotný balík je hostovaný odděleně od serveru, se kterým mluví. Samostatný
cc_server obsluhuje koncový bod RPC, plochu MCP a své proxy, ale ne
webový balík. Cesta ke statickým souborům na serveru existuje, ale na
samostatném binárním souboru není nastavený webový kořen, takže na / nemá co
servírovat. Publikovaný obraz kontejneru cc-webapp balík hostuje a
scripts/build_web.sh ho sestavuje. Server přijímá originy prohlížeče jen ze
seznamu --allowed-origins, který má výchozí hodnotu
https://app.usectrl.dev, takže vlastní hostování balíku znamená přidat jeho
origin.
Média (avatary, obrázky kanálu, snímky PR) jdou přes proxy koncový bod serveru, ne přímo na upstream hostitele, takže prohlížeč nikdy nenačítá libovolný origin. Nasazený klient nastaví pro každý požadavek Content-Security Policy z necitlivé cookie, takže je povolený jen origin připojeného serveru.
Telefonní společník (cc_remote)
Sekce “Telefonní společník (cc_remote)”Aplikace Remote je samostatný, lehčí klient — webová PWA ve Flutteru na remote.usectrl.dev. Schválně to není plná aplikace. Páruje se přes zprostředkované WebSocket relé zapečetěné od konce ke konci a mluví převážně čtecím výřezem plochy nástrojů: čte tickety, zprávy a kanál novinek; pošle odpověď nebo aktualizuje ticket.
Telefon je subjekt s nižšími oprávněními než místní agent. Politika nástrojů s výchozím zákazem, předem sdílený klíč, který zapečeťuje každý rámec, schopnost relace, která zamkne privilegované operace (třeba párování) mimo doprovodného klienta, kontroly role a oprávnění k repozitáři u každého volání výše a omezování četnosti brání tomu, aby schválené (nebo uniklé) párování znamenalo plné vzdálené ovládání. Viz Vzdálené ovládání a mobil pro celý model zabezpečení.
Klienti MCP
Sekce “Klienti MCP”Externí nástroje — editory, jiní agenti, CLI — které mluví Model Context Protocol, se připojí k ploše MCP serveru a berou typovaný registr nástrojů. Tohle je programová integrační cesta; není to grafické rozhraní. Viz Používejte MCP server a Nástroje MCP.
Workeři flotily (cc_worker)
Sekce “Workeři flotily (cc_worker)”cc_worker je binární soubor v čistém Dartu bez rozhraní, který se spáruje
s cc_server, ohlásí schopnosti hostitele a stahuje zapůjčené úlohy
k provedení. Události procesu streamuje zpátky po tom samém RPC a nedrží
trvalý stav: žádnou databázi, žádnou autentizaci, žádná schválení, žádné
rozpočty. To všechno zůstává v cc_server. Worker je končetina, ne druhý
mozek. Jeden autoritativní server, N hloupých končetin; žádný konsenzus,
žádný provoz mezi workery.
Zapůjčené provádění je pořád jen rozvod zapůjčení. agentRun je jediný druh,
který spustí skutečný příkaz (CC_JOB_COMMAND, nebo ozvěnu promptu, když
žádný nebyl dodaný). pipelineStep, codeIndex, goldenRender, benchmark
a evalBatch teď sondí přes git --version / rev-parse HEAD, aby se
procvičila streamovací cesta a nepředstíralo se, že ty úlohy opravdu běžely.
Co ohlašuje, je operační systém, architektura CPU, počet jader, RAM, jestli je
dosažitelný Flutter SDK a které backendy sandboxu hostitel má (na Windows
žádný). Vyhrazený worker navíc vždy ohlašuje alwaysOn a acceptsParallel,
a právě podle toho plánovač připnout → upřednostnit → přelít umisťuje úlohy.
Sonda GPU ani ML tu není.
Samotný desktop si toho nevšimne, protože běžné odeslání flotilou vůbec
neprochází. Implicitní worker v procesu pro hostitele serveru existuje, ale
je to jen registrační spoj bez napojených vykonavatelů. Úloha, která se na
místního workera opravdu umístí, selže, místo aby se provedla. Dnes zapůjčené
úlohy provádí jen skutečný cc_worker.
Co kde běží
Sekce “Co kde běží”| Oblast | Server (cc_server) |
Worker flotily (cc_worker) |
Desktopový klient | Webový / telefonní klient |
|---|---|---|---|---|
| Databáze (Drift/SQLite) | vlastní je | — | — | — |
| Autentizace, schválení, rozpočty, identita | vlastní je | — | — | — |
| Pipeline, reconcilery, posluchač orchestrace | spouští je | — | — | — |
| Plocha nástrojů MCP | obsluhuje ji | — | — | — |
| Provádění agentů | spouští ho (nebo ho zapůjčí) | provádí zapůjčené úlohy | — | — |
| Vykreslování rozhraní | — | — | plné | plné (web) / převážně čtení (telefon) |
| Záznam schůzky (mikrofon + zvuk schůzky) | — | — | nativní záznam | jen web, přes zvuk sdílení obrazovky |
| OAuth kalendáře (Google) | ukládá tokeny | — | — | — |
Obě vrstvy sandbox nepoužívají stejně. cc_server obalí běhy, které provádí
sám, sandboxem operačního systému hostitele, kde backend existuje — Seatbelt
na macOS, bubblewrap na Linuxu a WSL2 — a na Windows nebo bez bwrap a
socat spadne na ostatní hranice. cc_worker sandbox nepoužívá vůbec.
Ohlašuje schopnost sandbox, aby server uměl umisťovat úlohy podle platformy,
ale ve workeru se žádný neaplikuje: zapůjčená úloha se spustí přímo,
ohraničená prostředím zapůjčení a worktree, který dostala. Zapůjčit práci ven
tedy přesune provádění mimo sandbox i na hostiteli, který ho má. Viz
Sandbox a zabezpečení
pro to, co běh v každém případě ohraničuje.
Záznam schůzky probíhá na klientovi, protože potřebuje mikrofon a zvuk schůzky. Server ve skříni ti hovor nenahraje. Nahrávku pak shrne pipeline serveru a poznámky se uloží tam, kde je přečte každý klient.
Nahrává i webový klient, což tvar tabulky může zakrýt: v prohlížeči bere mikrofon plus zvukovou stopu sdílení obrazovky a streamuje 16 kHz PCM na server. Tu zvukovou stopu vyžaduje, takže tam, kde ji prohlížeč nedá, selže explicitně. Co je opravdu jen na desktopu, je vrstva kvality kolem záznamu: potlačení ozvěny na úrovni signálu nativním procesorem, měřič úrovně vstupu a upozornění na mrtvý mikrofon, opětovné spuštění souhrnu, zrušení zpracování a akce kalendáře nahrát a propojit.
Párování a důvěra
Sekce “Párování a důvěra”Každý klient prokáže, kdo je, předem sdíleným klíčem zřízeným jednou:
- Desktop v místním režimu vygeneruje při každém startu čerstvý klíč a předá ho spuštěnému serveru přes prostředí, takže na desktopu nezůstane nic tajného.
- Vzdálení klienti (desktop na dálku, web, telefon) použijí klíč, který vydá
příkaz
pairna serveru, a uloží ho do systémové klíčenky (na telefonu místně).
Odvolání je okamžité, ne odložené. Server sleduje tabulku spárovaných zařízení a do několika sekund shodí každou otevřenou relaci, jejíž zařízení opustilo aktivní množinu, na přímé cestě WebSocket i na cestě relé. Nemusíš čekat, až se zařízení znovu připojí, abys ho odřízl.
Klíč nikdy neputuje URL, kterou statický hostitel uvidí. Když přijde odkazem,
na telefonu nebo v prohlížeči, veze se ve fragmentu URL, v části za #,
kterou prohlížeč nikdy nepošle serveru hostujícímu stránku. To je invariant,
který stojí za zapamatování, a platí pro obojí. Webový klient má dva další
vstupy: formulář připojení, kam vložíš server a klíč přímo, a kód pozvánky,
který vymění za pověření vydané jen pro ten prohlížeč.
Související koncepty
Sekce “Související koncepty”- Pracovní prostory a izolace: proč každé volání RPC nese vlastní id pracovního prostoru a jak rozdělení databází dělá izolaci strukturální
- Architektura: jak je kódová báze uspořádaná kolem serveru a jeho klientů
- Vzdálené ovládání a mobil: párování telefonu a model zabezpečení
Související návody
Sekce “Související návody”- Spusťte headless server: spusť
cc_servera spáruj klienta - Připojte se ke vzdálenému serveru: namiř desktop nebo webového klienta na server jinde
- Spárujte zařízení: přidej telefon, druhý prohlížeč nebo další desktop
- Spusťte worker flotily: přidej
cc_worker, který stahuje zapůjčené úlohy