Obszary robocze i izolacja
Czym jest obszar roboczy?
Dział zatytułowany „Czym jest obszar roboczy?”Obszar roboczy to najwyższego poziomu dzierżawca izolacji w Control Center. Grupuje agentów, repozytoria, przestrzenie, zgłoszenia, pamięć, potoki i członków w jeden kontekst ograniczony. Wszystko, co dzieje się wewnątrz obszaru roboczego, pozostaje w nim.
Typowy obszar roboczy odpowiada jednemu projektowi albo jednej bazie kodu. Możesz mieć osobne obszary robocze dla „api-service”, „frontend-v2” i „infrastructure”.
Dane w zakresie obszaru roboczego
Dział zatytułowany „Dane w zakresie obszaru roboczego”Wiersze obszaru roboczego leżą w jego własnym pliku SQLite, pod <dataDir>/<workspaceId>/workspace.db. Każdy obszar roboczy dostaje katalog, a nie sam plik, ponieważ gromadzi więcej niż bazę danych — worktree poszczególnych rozmów, pliki agentów i skilli, poświadczenia botów czatu — a danie mu folderu sprawia, że wszystko to żyje i jest usuwane razem.
| Encja | Zasięg |
|---|---|
| Agenci | Należą dokładnie do jednego obszaru roboczego |
| Repozytoria | Rejestrowane w jednym obszarze roboczym (patrz niżej) |
| Przestrzenie, rozmowy i wiadomości | W zakresie obszaru roboczego |
| Zgłoszenia, projekty, plany, orkiestracje | W zakresie obszaru roboczego |
| Fakty pamięci, zasady, domeny, granty dostępu | W zakresie obszaru roboczego |
| Uruchomienia potoków, szablony, wyzwalacze | W zakresie obszaru roboczego |
| Stan pull requestów, przestrzenie recenzji, kohorty recenzji | W zakresie obszaru roboczego |
| Dzienniki uruchomień agentów i pamięć robocza | W zakresie obszaru roboczego |
| Członkowie, zaproszenia, granty na repozytoria | W zakresie obszaru roboczego |
| Symbole i krawędzie grafu kodu | W zakresie repoId w pliku obszaru roboczego |
Większość z tych wierszy ma kolumnę workspaceId; izolację wymuszają osobne pliki baz danych. Zobacz niezmiennik izolacji poniżej.
Repozytoria są w zakresie obszaru roboczego; tożsamość między obszarami roboczymi wyznacza ścieżka
Dział zatytułowany „Repozytoria są w zakresie obszaru roboczego; tożsamość między obszarami roboczymi wyznacza ścieżka”Wiersz repozytorium leży we własnym pliku bazy danych obszaru roboczego — to plik jest zakresem, więc tabela nie ma kolumny workspaceId ani tabeli łączącej.
Repozytorium dodajesz do obszaru roboczego w Ustawienia → Obszar roboczy → Repozytoria. Zarejestrowanie tego samego checkoutu w dwóch obszarach roboczych tworzy dwa niezależne wiersze o dwóch identyfikatorach; tożsamość repozytorium między obszarami roboczymi wyznacza ścieżka w systemie plików (albo właściciel/nazwa w GitHubie), nigdy identyfikator.
Rejestracja jest rygorystyczna: ścieżka musi znajdować się w drzewie roboczym git, musi mieć zdalne repozytorium origin, a to zdalne repozytorium musi wskazywać na obsługiwany host kodu (github.com, gitlab.com albo bitbucket.org). Host kodu jest odczytywany ze zdalnego repozytorium i zapisywany w repozytorium, więc jeden obszar roboczy może przechowywać repozytoria ze wszystkich trzech. Wszystko inne jest odrzucane. Przeglądarka folderów, z której wybierasz, pokazuje system plików hosta serwera, ograniczony do listy dozwolonych ścieżek serwera --repo-roots (która domyślnie wskazuje katalog domowy użytkownika serwera).
Usunięcie repozytorium z obszaru roboczego kasuje wiersz bezpowrotnie i kaskadowo usuwa jego symbole kodu, krawędzie, pliki, punkty kontrolne indeksu oraz granty poszczególnych członków. Checkout na dysku pozostaje nietknięty.
Graf kodu żyje w tym samym pliku, kluczowany przez repoId, ponieważ różne obszary robocze mogą mieć to samo repozytorium na różnych gałęziach z różnym kodem.
Niezmiennik izolacji
Dział zatytułowany „Niezmiennik izolacji”Wycieki danych między obszarami roboczymi są traktowane jak błędy. Izolacja jest strukturalna i wymuszana na kilku poziomach:
- Warstwa bazy danych. Każdy obszar roboczy ma własny plik SQLite, wydawany przez
WorkspaceDatabaseManager.of(workspaceId). Baza danych obszaru roboczego nie deklaruje tabelusers,workspacesani żadnego innego obszaru roboczego, więc odczyt między obszarami roboczymi to nie błąd, który można napisać — on się nie kompiluje. Repozytoria rozwiązują swoje DAO przy każdym wywołaniu, zamiast buforować jedno, a ponieważ każda metoda repozytorium przyjmuje wymaganyworkspaceId, obszaru roboczego nigdy nie da się wywnioskować ani przyjąć domyślnie. - Identyfikator obszaru roboczego to segment ścieżki. Ponieważ identyfikator staje się nazwą katalogu, musi pasować do bezpiecznego wzorca pojedynczego segmentu (początek alfanumeryczny, potem znaki alfanumeryczne, kropki, podkreślenia, myślniki; bez
..). W całym produkcie identyfikatory to UUID-y. Wszystko inne rzuca wyjątek, zamiast być sanityzowane — to zabezpieczenie przed przejściem po ścieżce (path traversal) i zawodzi głośno, zamiast zapisać dane obszaru roboczego pod ścieżką wybraną przez kogoś innego. - Obrona w głąb. Kolumny
workspaceIdwciąż tam są i wciąż są zapisywane. Zbędne w obrębie jednego pliku, pozostawiają wyzwalacze kanału synchronizacji, indeksy FTS i istniejące kształty wierszy bez zmian, a plik opisuje sam siebie, gdy ogląda się go osobno — na czym opierają się eksport i import. - Warstwa domenowa. Usługi, które mutują encje po identyfikatorze, walidują
entity.workspaceId == workspaceIdw jednym punkcie kontrolnym, zanim przejdą dalej, i rzucająWorkspaceMismatchExceptionprzy niezgodności — głośna porażka dla identyfikatora, który przyszedł z niewłaściwego kontekstu. Głośna odmowa ma znaczenie: cicha operacja bez efektu ukrywa błąd, a kontynuowanie powoduje wyciek. - Warstwa RPC. Dyspozytor repo-RPC jest punktem kontrolnym. Każda operacja w zakresie obszaru roboczego musi nieść
workspace_idwe własnych argumentach — nie ma „bieżącego obszaru roboczego” na sesję, który mógłby wyciec, a nieznany identyfikator jest odrzucany jako nie znaleziono, zanim cokolwiek otworzy bazę danych, więc zły identyfikator nie może zmaterializować widmowegoworkspace.db. Operacje naprawdę globalne (newsfeed, kolejka floty) deklarują się jako nieobjęte zakresem na mocy jawnej, zweryfikowanej decyzji. Narzędzia MCP podlegają tej samej regule: każde narzędzie dotykające danych w zakresie obszaru roboczego wymagaworkspace_id. - Fan-out między obszarami roboczymi jest policzalny. Odpowiedź na pytanie o kilka obszarów roboczych oznacza otwarcie kilku baz danych. Ten fan-out jest zamknięty w jednym pomocniku,
CrossWorkspaceQueries, więc pełna lista rzeczy, które legalnie przekraczają granicę, żyje w miejscach wywołań jednego pliku, zamiast rozpraszać się po komentarzach dokumentacyjnych. Tymi miejscami wywołań są: agregacja dla całego serwera, reconcillery startowe, cykle retencji i GC, kopia zapasowa, routery zdarzeń — oraz wyszukiwanie członkostwa poniżej. - Dostęp wyłącznie po identyfikatorze nie wystarcza. Znalezienie encji po jej UUID nie dowodzi, że należy do obszaru roboczego wywołującego. Podział plików czyni niewłaściwy plik nieosiągalnym; walidacja w warstwie domenowej wyłapuje zły identyfikator, który przychodzi przez legalny plik.
Członkostwo, a nie klucz parowania, przyznaje dostęp
Dział zatytułowany „Członkostwo, a nie klucz parowania, przyznaje dostęp”Posiadanie poświadczenia urządzenia uwierzytelnia urządzenie. Nie upoważnia do niczego wewnątrz obszaru roboczego. Każda operacja w zakresie obszaru roboczego rozwiązuje rolę członkostwa wywołującego i wymusza próg wynikający z rodzaju operacji — odczyt wymaga guest, mutacja wymaga member, operacja niszcząca wymaga admin — a operacje ujawniające treść repozytorium dodatkowo sprawdzają grant wywołującego na dane repozytorium. Ważny klucz parowania bez członkostwa dostaje Not a member of this workspace.
Konsekwencja dla izolacji jest elegancka: wiersze członkostwa leżą w pliku samego obszaru roboczego, więc „kto jest w tym obszarze roboczym?” to zwykły odczyt w zakresie. Pytanie odwrotne — „w których obszarach roboczych jestem?” — z definicji rozciąga się na wiele plików, więc jest jednym z niewielu usankcjonowanych fan-outów CrossWorkspaceQueries i to je wykonuje selektor obszarów roboczych, zanim zostanie wybrany jakikolwiek obszar roboczy.
Zobacz Wieloosobowość, aby poznać drabinkę ról i granty na repozytoria.
Globalny rejestr
Dział zatytułowany „Globalny rejestr”Nie wszystko jest w zakresie obszaru roboczego. Druga baza danych, <dataDir>/global.db, przechowuje to, co jest naprawdę wspólne dla całego serwera:
- rejestr obszarów roboczych, dzięki czemu przełącznik może wypisać każdy obszar roboczy bez otwierania choćby jednego pliku obszaru roboczego — a nazwa, logo, właściciel, ręczna kolejność i znacznik miękkiego usunięcia obszaru roboczego leżą poza plikiem, który opisują;
- tożsamość: użytkownicy, preferencje użytkowników i sparowane urządzenia, ponieważ jeden człowiek to jeden użytkownik we wszystkich obszarach roboczych, a sparowane urządzenie przeżywa usunięcie obszaru roboczego;
- kolejkę floty (workery, zadania, dziennik przydziałów), której scheduler dopasowuje całą kolejkę do każdego workera przy każdym takcie;
- newsfeed, który jest przypisany do użytkownika (a nie do obszaru roboczego) — dodanie kanału podąża za Tobą do każdego obszaru roboczego;
workspace_routes, indeks używany przed uwierzytelnieniem, który odpowiada na pytanie „który obszar roboczy jest właścicielem tego klucza?” dla punktów wejścia przychodzących tylko z sekretem albo nieprzejrzystym identyfikatorem (skrót zaproszenia, token webhooka, deep link) i bez obszaru roboczego. Brak trafienia oznacza „nie znaleziono”; celowo nie ma mechanizmu zastępczego w postaci skanowania;- ustawienia i tożsamość dla całej instalacji: identyfikator instalacji, ustawienia na poziomie hosta, połączenia SSO oraz zarządzane polityki działań (ograniczenie dla całej instalacji, które może tylko zaostrzać guardraile obszarów roboczych).
Rozruch otwiera tylko ten plik. Pliki obszarów roboczych otwierają się leniwie przy pierwszym użyciu, więc koszt startu pozostaje stały niezależnie od tego, ile historii zgromadzą obszary robocze, a quick_check poszczególnych plików jest opłacany przy pierwszym użyciu, a nie na drodze do banera gotowości.
Plik obszaru roboczego niesie tylko jednowierszowy workspace_meta do samoidentyfikacji (jego identyfikator, instalację, która go utworzyła, wersję schematu, z jaką został utworzony, i kiedy). Wszystko opisowe o obszarze roboczym jest w rejestrze.
Tworzenie obszaru roboczego
Dział zatytułowany „Tworzenie obszaru roboczego”Utworzenie obszaru roboczego to więcej niż wstawienie wiersza do rejestru. W jednej operacji serwer stempluje tworzącego użytkownika jako ownerUserId, zapisuje jego członkostwo z rolą właściciela i publikuje zdarzenie domenowe WorkspaceCreated. Nasłuchujący tego zdarzenia zasiewają następnie, idempotentnie i w tle:
- agenta CEO oraz czterech specjalistów —
qa,architect,engineer,librarian— którzy podlegają CEO; - wbudowane szablony potoków i ich wyzwalacze (wyzwalacze zdarzeniowe i ręczne są domyślnie włączone; wyzwalacze harmonogramu trzeba włączyć, z wyjątkiem dziennego czyszczenia worktree przez GC);
- startowe zestawy ewaluacji.
Dzieje się tak dla każdego obszaru roboczego, nie tylko pierwszego. Zasiani agenci są tworzeni bez adaptera, więc działają na Control Center (built-in) z domyślnym modelem Anthropic (claude-opus-4-8, o ile nie przypniesz innego), dopóki nie ustawisz adaptera i modelu dla poszczególnych agentów w Ustawienia → Obszar roboczy → Agenci. Zobacz Model agentów.
Zapis członkostwa właściciela ma większe znaczenie, niż się wydaje: bez niego świeżo utworzony obszar roboczy nie miałby członków, a każde kolejne wywołanie w zakresie obszaru roboczego wykonane przez twórcę zostałoby odrzucone.
Usuwanie, eksportowanie, importowanie
Dział zatytułowany „Usuwanie, eksportowanie, importowanie”Usunięcie obszaru roboczego oznacza wiersz rejestru i odłącza katalog. Obszar roboczy znika z każdej listy i wyszukiwania. Wiersz rejestru pozostaje (miękko usunięty), więc identyfikator jest wciąż znany kopii zapasowej i konserwacji, ale workspace.delete natychmiast porzuca katalog tego obszaru roboczego — bazę danych, worktree, pliki agentów i resztę — przez WorkspaceDatabaseManager.dropAndClose. Tylko właściciel obszaru roboczego może go usunąć.
Ponieważ jeden obszar roboczy to jeden plik, przekazywanie obszaru roboczego jest operacją na pliku, a nie zrzutem tabela po tabeli:
workspace.exportto pojedynczeVACUUM INTO— spójna, zdefragmentowana migawka wykonana w transakcji odczytu, gdy serwer nadal obsługuje żądania.workspace.importprzyjmuje taki plik, zastępując wszystko, co docelowy obszar roboczy aktualnie zawiera. Osadzoneworkspace_metapozwala importowi odróżnić „własny plik, przyjęty ponownie” od „pliku z innej instalacji” (ten drugi jest dozwolony, ale rejestrowany w dzienniku, a nie niewidoczny).server.backupNowtworzy migawkę całej instalacji w katalogu ze znacznikiem czasu, który odwzorowuje bieżący katalog danych —manifest.json,global.dbi po jednym<workspaceId>/workspace.dbna obszar roboczy — więc przywrócenie to skopiowanie go z powrotem.server.listBackupsodczytuje ten katalog z powrotem, od najnowszego, wraz z rozmiarem i listą obszarów roboczych każdej migawki. Migawka, której manifestu brakuje albo która wymienia nieistniejące pliki, jest nadal raportowana i oznaczana jako niekompletna — ukrycie jej to sposób, w jaki operator zaczyna wierzyć, że ma kopię zapasową, której nie ma.
Operacje kopii zapasowej znajdują się w Ustawienia → Serwer → Kopia zapasowa i przywracanie: Wykonaj kopię teraz tworzy migawkę instalacji, lista pokazuje, które migawki są kompletne, i pozwala właścicielowi instalacji usunąć jedną po potwierdzeniu, a każdy obszar roboczy oferuje eksport i import. Wbudowany potok Workspace backup bierze w tygodniowym harmonogramie tylko bazę danych tego obszaru roboczego i usuwa własne kopie zapasowe starsze niż skonfigurowany wiek retencji. Przywrócenie obszaru roboczego z migawki instalacji to workspace.import wskazany na <workspaceId>/workspace.db migawki; przywrócenie całej instalacji pozostaje kopiowaniem z powrotem katalogu migawki przy zatrzymanym serwerze.
Żadna z nich nie przenosi jednak reszty katalogu obszaru roboczego. Obszar roboczy gromadzi więcej niż bazę danych — wklejone obrazy, pliki skilli i agentów, poświadczenia czatu, worktree — a eksport i import przenoszą plik, więc wszystko obok niego zostaje tam, gdzie było. W przypadku poświadczeń jest to zamierzone, a w przypadku worktree są one jednorazowe; w pozostałym zakresie to ograniczenie, o którym warto wiedzieć, a nie funkcja. Pełną tabelę zawiera dokumentacja referencyjna kopii zapasowej.
Przenoszenie kopii zapasowej między serwerem a Twoim urządzeniem
Dział zatytułowany „Przenoszenie kopii zapasowej między serwerem a Twoim urządzeniem”Każda z powyższych operacji mówi ścieżkami na serwerze, co jest pełną odpowiedzią tylko wtedy, gdy serwer jest Twoją własną maszyną. Trzy podpisane trasy HTTP — /backup/workspace, /backup/snapshot i /backup/restore — przenoszą bajty w każdej innej topologii, tym samym uwierzytelnionym torem, z którego korzystają już proxy multimediów i magazyn obrazów. Na stronie jest to przycisk Pobierz obok każdego eksportu i każdej migawki (wybierasz, gdzie trafi), oraz Wybierz plik i wyślij, aby przywrócić z pliku leżącego na maszynie, której używasz. To wysyłanie działa, gdy serwer nie jest Twoją maszyną: workspace.import potrzebuje pliku już na hoście i właśnie w ten sposób się tam znajduje.
Warto znać trzy właściwości:
- Pobieranie tworzy świeżą kopię, a serwer nie zachowuje z niej nic. Pobieranie to nie „pobierz plik, który zrobił przycisk eksportu” — to ponowny eksport, strumieniowanie go i usunięcie. Odpowiedź ma
no-storeiAccept-Ranges: nonez tego samego powodu: wznowiony zakres skleiłby dwa różne eksporty w jeden plik, który wygląda na poprawny, a nim nie jest. - Przesyłanie jest strumieniowane na dysk, nigdy buforowane po obu stronach, a kopia tymczasowa jest usuwana na każdej ścieżce wyjścia — także przy odmowie. Baza danych obszaru roboczego to nie zrzut ekranu.
- Połączenie przekazywane przez relay nie ma źródła HTTP, więc kontrolki transferu są tam wyłączone wraz z informacją, dlaczego tak jest. Wszystko, co mówi ścieżkami po stronie serwera, działa dalej przez relay; bezpośredniego połączenia wymagają tylko tory bajtów.
Wiele obszarów roboczych
Dział zatytułowany „Wiele obszarów roboczych”Możesz prowadzić wiele obszarów roboczych równolegle. Każdy działa niezależnie: agenci w jednym obszarze roboczym nie mogą wysyłać wiadomości do agentów w innym, nie mogą czytać pamięci innego obszaru roboczego ani widzieć jego zgłoszeń. Rozwiązywanie odbiorców w komunikacji agent–agent jest dokładne i nigdy nie przekracza obszaru roboczego.
Nie ma pulpitu obejmującego wiele obszarów roboczych. Powierzchnia analityki pod /workspaces/:workspaceId/observability subskrybuje ograniczony globalny strumień ostatnich uruchomień i natychmiast zawęża go do aktywnego obszaru roboczego, więc widzisz tam jeden obszar roboczy naraz. Jedyne naprawdę wieloobszarowe powierzchnie, z którymi styka się człowiek, to selektor obszarów roboczych i przełącznik.
Jedno ograniczenie praktyczne, które warto znać: obszar roboczy, którego ktoś używa, pozostaje otwarty — nie ma LRU. Po przekroczeniu 32 takich obszarów serwer ostrzega, zamiast odmawiać, ponieważ każdy otwarty plik utrzymuje izolat w tle i pamięć podręczną stron. Fan-out między obszarami roboczymi otwiera pliki przejściowo i zamyka je potem, jeśli nic innego ich nie przejęło.
Powiązane koncepcje
Dział zatytułowany „Powiązane koncepcje”- Wieloosobowość: członkostwo, role i granty na repozytoria — dostępowa połowa izolacji
- Model agentów: agenci należą dokładnie do jednego obszaru roboczego
- Pamięć i wiedza: pamięć działa w zakresie obszaru roboczego
- Architektura: gdzie leżą bazy danych w podziale klient/serwer
- Kopia zapasowa i przywracanie: tworzenie migawki, przenoszenie obszaru roboczego, trzymanie kopii gdzie indziej
- Kopia zapasowa, eksport i import: każda operacja, trasa, pole manifestu i limit
- Dodaj repozytoria: rejestrowanie checkoutu w obszarze roboczym