Espaços de trabalho e isolamento
O que é um espaço de trabalho?
Secção intitulada “O que é um espaço de trabalho?”Um espaço de trabalho é o inquilino de isolamento de nível superior no Control Center. Agrupa agentes, repositórios, espaços, tickets, memória, pipelines e membros num contexto delimitado. Tudo o que acontece dentro de um espaço de trabalho fica dentro dele.
Um espaço de trabalho típico corresponde a um projeto ou a uma base de código. Pode ter espaços de trabalho separados para “api-service”, “frontend-v2” e “infrastructure”.
Dados com âmbito de espaço de trabalho
Secção intitulada “Dados com âmbito de espaço de trabalho”As linhas de um espaço de trabalho vivem no ficheiro SQLite do próprio espaço de trabalho, em <dataDir>/<workspaceId>/workspace.db. Cada espaço de trabalho recebe um diretório em vez de um ficheiro simples, porque um espaço de trabalho acumula mais do que uma base de dados — worktrees por conversa, os ficheiros de agentes e de skills, credenciais de bots de chat — e dar-lhe uma pasta faz com que tudo isso viva e seja eliminado, em conjunto.
| Entidade | Âmbito |
|---|---|
| Agentes | Pertencem a exatamente um espaço de trabalho |
| Repositórios | Registados num espaço de trabalho (ver abaixo) |
| Espaços, conversas e mensagens | Com âmbito de espaço de trabalho |
| Tickets, projetos, planos, orquestrações | Com âmbito de espaço de trabalho |
| Factos de memória, políticas, domínios, concessões de acesso | Com âmbito de espaço de trabalho |
| Execuções de pipeline, modelos, disparadores | Com âmbito de espaço de trabalho |
| Estado de pull requests, espaços de revisão, coortes de revisão | Com âmbito de espaço de trabalho |
| Registos de execução de agentes e memória de trabalho | Com âmbito de espaço de trabalho |
| Membros, convites, concessões por repo | Com âmbito de espaço de trabalho |
| Símbolos e arestas do grafo de código | Com âmbito definido por repoId dentro do ficheiro do espaço de trabalho |
A maioria destas linhas transporta uma coluna workspaceId; ficheiros de base de dados separados impõem o isolamento. Ver o invariante de isolamento abaixo.
Os repos têm âmbito de espaço de trabalho; a identidade entre espaços de trabalho é feita pelo caminho
Secção intitulada “Os repos têm âmbito de espaço de trabalho; a identidade entre espaços de trabalho é feita pelo caminho”Uma linha de repo vive no ficheiro de base de dados do próprio espaço de trabalho — o ficheiro é o âmbito, pelo que a tabela não tem coluna workspaceId nem tabela de associação.
Adicione um repo a um espaço de trabalho em Definições → Espaço de trabalho → Repositórios. Registar o mesmo checkout em dois espaços de trabalho cria duas linhas independentes com dois ids; a identidade de um repo entre espaços de trabalho é feita pelo caminho no sistema de ficheiros (ou pelo proprietário/nome no GitHub), nunca pelo id.
O registo é estrito: o caminho tem de estar dentro de uma árvore de trabalho git, tem de ter um remoto origin e esse remoto tem de apontar para um host de código suportado (github.com, gitlab.com ou bitbucket.org). O host de código é lido a partir do remoto e guardado no repo, pelo que um espaço de trabalho pode conter repos dos três. Tudo o resto é rejeitado. O navegador de pastas onde escolhe lista o sistema de ficheiros do host do servidor, confinado à lista de autorizações do servidor definida por --repo-roots (que, por predefinição, é o diretório pessoal do utilizador do servidor).
Remover um repositório de um espaço de trabalho elimina a linha de imediato e propaga a eliminação aos seus símbolos de código, arestas, ficheiros, pontos de verificação de indexação e concessões por membro. O checkout no disco não é tocado.
O grafo de código vive no mesmo ficheiro, indexado por repoId, porque espaços de trabalho diferentes podem ter o mesmo repositório em branches diferentes com código diferente.
O invariante de isolamento
Secção intitulada “O invariante de isolamento”As fugas de dados entre espaços de trabalho são tratadas como erros. O isolamento é estrutural e é imposto a vários níveis:
- Camada de base de dados. Cada espaço de trabalho tem o seu próprio ficheiro SQLite, fornecido por
WorkspaceDatabaseManager.of(workspaceId). Uma base de dados de espaço de trabalho não declarausers,workspaces, nem tabelas de qualquer outro espaço de trabalho, pelo que uma leitura cruzada entre espaços de trabalho não é um erro que se possa escrever — não compila. Os repositórios resolvem o seu DAO a cada chamada em vez de o colocarem em cache e, como todos os métodos de repositório recebem umworkspaceIdobrigatório, o espaço de trabalho nunca pode ser inferido nem assumido por predefinição. - O id do espaço de trabalho é um segmento de caminho. Como o id se torna um nome de diretório, tem de corresponder a um padrão seguro de segmento único (começa com um caráter alfanumérico e segue-se de carateres alfanuméricos, pontos, underscores e hífenes; sem
..). Em todo o produto, os ids são UUID. Qualquer outra coisa lança uma exceção em vez de ser saneada — essa é a proteção contra travessia de caminhos e falha de forma ruidosa em vez de escrever os dados de um espaço de trabalho para um caminho que outra pessoa escolheu. - Defesa em profundidade. As colunas
workspaceIdcontinuam a existir e continuam a ser preenchidas. Redundantes dentro de um ficheiro, mantêm inalterados os disparadores do feed de sincronização, os índices FTS e as formas de linha existentes, e tornam um ficheiro autodescritivo quando é inspecionado isoladamente — que é aquilo em que a exportação e a importação se baseiam. - Camada de domínio. Os serviços que modificam entidades por id validam
entity.workspaceId == workspaceIdnum único ponto de estrangulamento antes de prosseguir e lançamWorkspaceMismatchExceptionquando não coincidem — a falha ruidosa para um id que chegou do contexto errado. Recusar de forma ruidosa é importante: um no-op silencioso esconde o erro e prosseguir deixa escapar dados. - Camada RPC. O despachante de RPC de repos é o ponto de estrangulamento. Todas as operações com âmbito de espaço de trabalho têm de transportar
workspace_idnos seus próprios argumentos — não existe nenhum “espaço de trabalho atual” por sessão que possa escapar-se, e um id desconhecido é recusado como não encontrado antes de algo abrir uma base de dados, pelo que um id errado não pode materializar umworkspace.dbfantasma. As operações genuinamente globais (o feed de notícias, a fila da frota) declaram-se a si próprias sem âmbito, como decisão explícita e revista. As ferramentas MCP seguem a mesma regra: qualquer ferramenta que toque em dados com âmbito de espaço de trabalho exigeworkspace_id. - O fan-out entre espaços de trabalho é enumerável. Responder a uma pergunta sobre vários espaços de trabalho implica abrir várias bases de dados. Esse fan-out está confinado a um único auxiliar,
CrossWorkspaceQueries, pelo que a lista completa das coisas que atravessam legitimamente a fronteira vive nos locais de chamada de um só ficheiro em vez de se difundir por trás de comentários de documentação. Esses locais de chamada são: a agregação de todo o servidor, os reconciliadores de arranque, as varreduras de retenção e de GC, a cópia de segurança, os encaminhadores de eventos — e a consulta de pertença abaixo. - O acesso apenas por ID não é suficiente. Procurar uma entidade pelo seu UUID não prova que ela pertence ao espaço de trabalho de quem chama. A divisão em ficheiros torna inalcançável o ficheiro errado; a validação da camada de domínio apanha um id errado que chegue através de um ficheiro legítimo.
É a pertença, e não a chave de emparelhamento, que concede o acesso
Secção intitulada “É a pertença, e não a chave de emparelhamento, que concede o acesso”Possuir uma credencial de dispositivo autentica um dispositivo. Não autoriza nada dentro de um espaço de trabalho. Todas as operações com âmbito de espaço de trabalho resolvem a função de pertença de quem chama e aplicam um limite mínimo derivado do tipo de operação — uma leitura precisa de guest, uma mutação precisa de member, uma operação destrutiva precisa de admin — e as operações que expõem conteúdo de repos verificam ainda a concessão por repo de quem chama. Uma chave de emparelhamento válida sem pertença recebe Not a member of this workspace.
A consequência para o isolamento é elegante: as linhas de pertença vivem no ficheiro do próprio espaço de trabalho, pelo que “quem está neste espaço de trabalho?” é uma leitura corrente com âmbito. A pergunta inversa — “em que espaços de trabalho estou?” — está, por definição, espalhada por ficheiros, pelo que é um dos poucos fan-outs permitidos de CrossWorkspaceQueries e é o que o seletor de espaços de trabalho executa antes de qualquer espaço de trabalho ter sido escolhido.
Ver Multijogador e presença para a escala de funções e as concessões por repo.
O registo global
Secção intitulada “O registo global”Nem tudo tem âmbito de espaço de trabalho. Uma segunda base de dados, <dataDir>/global.db, contém o que é genuinamente de todo o servidor:
- o registo de espaços de trabalho, para que o comutador possa listar todos os espaços de trabalho sem abrir um único ficheiro de espaço de trabalho — e para que o nome, o logótipo, o proprietário, a ordem manual e o marcador de eliminação reversível de um espaço de trabalho vivam fora do ficheiro que descrevem;
- a identidade: utilizadores, preferências de utilizador e dispositivos emparelhados, porque um ser humano é um único utilizador em todos os espaços de trabalho e um dispositivo emparelhado sobrevive à eliminação de um espaço de trabalho;
- a fila da frota (workers, trabalhos, registo de colocação), cujo agendador compara a fila inteira com todos os workers a cada ciclo;
- o feed de notícias, que é por utilizador (não por espaço de trabalho) — acrescentar um feed acompanha-o em todos os espaços de trabalho;
workspace_routes, o índice de pré-autenticação que responde a “que espaço de trabalho é dono desta chave?” para pontos de entrada que chegam sem nada além de um segredo ou de um id opaco (um hash de convite, um token de webhook, uma ligação direta) e sem espaço de trabalho. Uma falha aí é um não encontrado; deliberadamente, não existe nenhuma alternativa que faça uma pesquisa exaustiva;- definições e identidade de toda a instalação: o id da instalação, as definições ao nível do host, as ligações SSO e as políticas de ações geridas (um limite de toda a instalação que só pode apertar as barreiras do espaço de trabalho).
O arranque abre apenas este ficheiro. Os ficheiros de espaço de trabalho abrem de forma preguiçosa, no primeiro acesso, pelo que o custo de arranque se mantém constante independentemente do histórico que os espaços de trabalho acumulam e o quick_check por ficheiro é pago na primeira utilização em vez de no caminho até ao banner de prontidão.
Um ficheiro de espaço de trabalho transporta apenas um workspace_meta de linha única para autoidentificação (o seu id, a instalação que o criou, a versão do esquema com que foi criado e quando). Tudo o que descreve um espaço de trabalho está no registo.
Criar um espaço de trabalho
Secção intitulada “Criar um espaço de trabalho”Criar um espaço de trabalho faz mais do que inserir uma linha no registo. Numa única operação, o servidor marca o utilizador criador como ownerUserId, regista a pertença desse utilizador com a função de proprietário e publica um evento de domínio WorkspaceCreated. Os ouvintes desse evento semeiam então, de forma idempotente e em segundo plano:
- um agente CEO e mais quatro especialistas —
qa,architect,engineer,librarian— com os especialistas a reportar ao CEO; - os modelos de pipeline integrados e os respetivos disparadores (os disparadores de evento e manuais vêm ativados; os agendados são opcionais, exceto a varredura diária de GC de worktrees);
- as suites de avaliação iniciais.
Isto acontece em todos os espaços de trabalho, não apenas no primeiro. Os agentes semeados são criados sem adaptador, pelo que são executados em Control Center (built-in) com o modelo predefinido da Anthropic (claude-opus-4-8, a menos que fixe outro) até definir um adaptador e um modelo por agente em Definições → Espaço de trabalho → Agentes. Ver O modelo de agentes.
A escrita da pertença do proprietário importa mais do que parece: sem ela, o espaço de trabalho acabado de criar não teria membros e todas as chamadas com âmbito de espaço de trabalho que o criador fizesse a seguir seriam recusadas.
Eliminar, exportar e importar
Secção intitulada “Eliminar, exportar e importar”Eliminar um espaço de trabalho marca a linha do registo e desvincula o diretório. O espaço de trabalho desaparece de todas as listas e consultas. A linha do registo mantém-se (eliminada de forma reversível) para que o id continue a ser conhecido da cópia de segurança e da manutenção, mas workspace.delete descarta de imediato o diretório desse espaço de trabalho — base de dados, worktrees, ficheiros de agentes e o resto — através de WorkspaceDatabaseManager.dropAndClose. Só o proprietário do espaço de trabalho o pode eliminar.
Como um espaço de trabalho é um único ficheiro, passar um espaço de trabalho de mão em mão é uma operação sobre ficheiros e não um despejo tabela a tabela:
workspace.exporté um únicoVACUUM INTO— um instantâneo consistente e desfragmentado, tirado no âmbito de uma transação de leitura enquanto o servidor continua a servir.workspace.importadota um ficheiro desses, substituindo tudo o que o espaço de trabalho de destino contém atualmente. Oworkspace_metaincorporado permite que uma importação distinga “o meu próprio ficheiro, adotado de novo” de “um ficheiro de outra instalação” (este último é permitido, mas registado em vez de invisível).server.backupNowcria um instantâneo de toda a instalação numa pasta com data e hora que espelha o diretório de dados em funcionamento —manifest.json,global.dbe um<workspaceId>/workspace.dbpor espaço de trabalho — pelo que restaurar é copiá-la de volta.server.listBackupsvolta a ler esse diretório, do mais recente para o mais antigo, com o tamanho e a lista de espaços de trabalho de cada instantâneo. Um instantâneo cujo manifesto esteja em falta ou que refira ficheiros que não existem continua a ser comunicado, sinalizado como incompleto — escondê-lo é a forma de um operador passar a acreditar que tem uma cópia de segurança que não tem.
As operações de cópia de segurança encontram-se em Definições → Servidor → Backup e restauração:
Fazer backup agora cria um instantâneo da instalação, a lista mostra que
instantâneos estão completos e permite ao proprietário da instalação eliminar um após
confirmação, e cada espaço de trabalho oferece exportação e importação. O pipeline
integrado Workspace backup recolhe apenas a base de dados desse espaço de trabalho
numa agenda semanal e elimina as suas próprias cópias de segurança com idade superior à
retenção configurada. Restaurar um espaço de trabalho a partir de um instantâneo da
instalação é apontar workspace.import ao <workspaceId>/workspace.db do instantâneo;
restaurar uma instalação completa continua a ser uma cópia de volta do diretório do
instantâneo com o servidor parado.
O que nenhuma delas transporta é o resto do diretório do espaço de trabalho. Um espaço de trabalho acumula mais do que uma base de dados — imagens coladas, ficheiros de skills e de agentes, credenciais de chat, worktrees — e a exportação e a importação movem o ficheiro, pelo que tudo o que está ao seu lado fica onde está. Isso é deliberado para as credenciais e descartável para as worktrees; quanto ao resto, é um limite que convém conhecer e não uma funcionalidade. A referência da cópia de segurança tem a tabela completa.
Mover uma cópia de segurança entre o servidor e o seu dispositivo
Secção intitulada “Mover uma cópia de segurança entre o servidor e o seu dispositivo”Todas as operações acima falam em caminhos no servidor, o que só é uma resposta completa quando o servidor é a sua própria máquina. Três rotas HTTP assinadas — /backup/workspace, /backup/snapshot e /backup/restore — transportam os bytes em qualquer outra topologia, na mesma via autenticada que o proxy de multimédia e o armazenamento de imagens já utilizam. Na página, isto traduz-se num botão Descarregar junto a cada exportação e a cada instantâneo (escolhe onde fica) e em Escolher um ficheiro e enviar para restaurar a partir de um ficheiro que esteja na máquina que está a utilizar. O envio é o que funciona quando o servidor não é a sua máquina: workspace.import precisa que o ficheiro já esteja no host, e é assim que ele lá chega.
Vale a pena conhecer três propriedades:
- Um descarregamento gera uma cópia nova e o servidor não guarda nada dela. Descarregar não é “ir buscar o ficheiro que o botão de exportação criou” — exporta outra vez, transmite esse resultado em fluxo e elimina-o. A resposta é
no-storecomAccept-Ranges: nonepela mesma razão: um intervalo retomado iria juntar duas exportações diferentes num único ficheiro que parece válido e não é. - Um envio é transmitido em fluxo para o disco, nunca colocado em buffer, em ambas as extremidades, e a cópia preparada é eliminada em todas as saídas — incluindo numa recusa. Uma base de dados de espaço de trabalho não é uma captura de ecrã.
- Uma ligação retransmitida por relay não tem origem HTTP, pelo que os controlos de transferência ficam aí desativados, com uma nota a explicar porquê. Tudo o que fala em caminhos do lado do servidor continua a funcionar através do relay; só as vias de bytes precisam de uma ligação direta.
Vários espaços de trabalho
Secção intitulada “Vários espaços de trabalho”Pode executar vários espaços de trabalho em paralelo. Cada um funciona de forma independente: os agentes de um espaço de trabalho não podem enviar mensagens a agentes de outro, não podem ler a memória de outro espaço de trabalho e não podem ver os seus tickets. A resolução de destinatários para mensagens entre agentes é exata e nunca atravessa um espaço de trabalho.
Não existe nenhum painel que abranja vários espaços de trabalho. A superfície de análise em /workspaces/:workspaceId/observability subscreve um feed global limitado de execuções recentes e restringe-o de imediato ao espaço de trabalho ativo, pelo que o que aí vê é um espaço de trabalho de cada vez. As únicas superfícies que uma pessoa toca e que envolvem genuinamente vários espaços de trabalho são o seletor de espaços de trabalho e o comutador.
Há um limite prático que vale a pena conhecer: um espaço de trabalho que alguém está a utilizar permanece aberto — não há LRU. A partir de 32 desses, o servidor avisa em vez de recusar, porque cada ficheiro aberto mantém um isolate em segundo plano e uma cache de páginas. O fan-out entre espaços de trabalho abre ficheiros de forma transitória e fecha-os depois, se nada mais os tiver reclamado.
Conceitos relacionados
Secção intitulada “Conceitos relacionados”- Multijogador e presença: pertença, funções e concessões por repo — a metade do isolamento relativa ao acesso
- O modelo de agentes: os agentes pertencem a exatamente um espaço de trabalho
- Memória e conhecimento: a memória tem âmbito de espaço de trabalho
- Arquitetura: onde se situam as bases de dados na divisão cliente/servidor
- Fazer cópia de segurança e restaurar: tirar um instantâneo, mover um espaço de trabalho, manter cópias noutro sítio
- Cópia de segurança, exportação e importação: todas as operações, rotas, campos do manifesto e limites
- Adicionar repos a um espaço de trabalho: registar um checkout num espaço de trabalho