Configuração

O serviço de contas pertence ao OHarness Cloud. O cliente conhece apenas a origem pública dele, e não o projeto do Supabase nem a chave de API do projeto no Composio.

LocalResponsabilidade
~/.oharness/config.jsonPreferências gerais de runtime: modelos, permissões, logs, sincronização
~/.oharness/cloud.jsonEndereço público opcional do Cloud: { "siteUrl": "https://oharness.ai" }
~/.oharness/plugins.json{ "runtimePlugins": [...] }; plugins opcional para pacotes declarativos
~/.oharness/mcp.json{ "mcpServers": { ... } }; alterações de conectores feitas na Web são gravadas aqui
Ambiente/segredos da implantação do CloudConfiguração do Supabase e chaves de serviço da plataforma
Armazenamento de credenciaisCredenciais de login do usuário; nenhum dos arquivos de configuração acima

OHARNESS_HOME redireciona os quatro arquivos do cliente. A origem oficial do Cloud é o padrão; substituições para auto-hospedagem ou desenvolvimento usam OHARNESS_SITE_URL, depois cloud.json e, por fim, a origem pública embutida no pacote. HTTP só é permitido para desenvolvimento em loopback. A configuração do repositório não pode escolher a origem do Cloud nem carregar código de plugins de runtime. O Harness.create({ config, runtimePlugins }) programático continua aceitando configurações fornecidas explicitamente.

Memória

As notas duráveis são configuradas em memory no config.json (ou no oharness.config.json de um projeto): limites, recall por mensagem e extração automática. As notas do projeto ficam em Markdown em <project>/MEMORY/; as notas do usuário, válidas para todos os projetos, ficam em ~/.oharness/memory/user/. O consentimento de sincronização e os índices locais da máquina continuam no diretório do usuário. A configuração de um projeto pode ajustar o recall ou desligar a extração, mas só a configuração do próprio usuário pode ligá-la, já que ela gasta o crédito de modelo do usuário. Memória lista todas as opções.

Artefatos

Uma sessão em um projeto registrado salva cada artefato em <project>/ARTIFACTS/: a revisão mais recente como um arquivo comum (ARTIFACTS/blue-field.html) e as revisões que ela substituiu em ARTIFACTS/.versions/<name>/v<N>.<ext>. Uma sessão pode criar vários artefatos, cada um em seu próprio arquivo; o mesmo nome vindo de outra sessão ganha um sufixo (blue-field-2.html). Editar o arquivo principal em um editor muda o que o painel mostra. ~/.oharness/storage/artifact/<session>.jsonl continua sendo o índice — qual sessão criou o quê, e os campos de versão e sincronização de cada revisão — sem o conteúdo. Excluir uma sessão remove o índice e mantém os arquivos no projeto. Sessões fora de um projeto registrado, e imagens raster, mantêm o conteúdo no índice como antes. O conteúdo gravado inline antes dessa mudança é movido para o projeto na próxima vez que a sessão for aberta.

Sincronização

O destino auto-hospedado e a credencial da sessão pertencem apenas ao config.json do usuário:

{
  "sync": {
    "url": "https://sync.example.com",
    "token": "opaque-session-token",
    "enabled": true
  }
}

A precedência atual é sync.url do usuário, depois OHARNESS_SYNC_URL e, por fim, o destino oficial embutido. A configuração do repositório não pode definir a URL, o token nem a equipe, porque isso permitiria que um repositório clonado redirecionasse transcrições; ela só pode desligar a sincronização ou adicionar exclusões. Reinicie o OHarness depois de mudar o destino. Veja Rodando seu próprio servidor de sincronização para implantar o serviço incluído e Protocolo de sincronização para implementar um compatível.

Migração compatível

As seções existentes do config.json só são lidas como fallback enquanto o arquivo separado correspondente não existe. Um arquivo separado existente é a fonte oficial, inclusive uma lista de plugins vazia ou um mapa MCP vazio. O antigo account.siteUrl é aceito; os antigos campos do Supabase não são mais usados pelo cliente.

npm run config:migrate             # Preview filenames only; no secrets printed
npm run config:migrate -- --apply  # Back up, split, then clean the old sections

A migração preserva as preferências não relacionadas e não sobrescreve arquivos separados já existentes. Ela salva um backup privado config.before-split.<id>.json e grava a configuração geral por último. Os arquivos são substituídos de forma atômica com modo 0600. Não edite a configuração enquanto a migração estiver rodando nem execute vários processos de migração ao mesmo tempo. O backup pode conter credenciais antigas: mantenha-o privado e remova-o você mesmo depois de verificar. A migração nunca altera credenciais de login nem autoriza apps.

Transporte da conta

O login pelo navegador continua usando /auth/desktop e /api/desktop/exchange do Cloud. A renovação e o fallback com OTP no terminal agora usam /api/desktop/auth/refresh, /otp e /verify. Atualize o Cloud antes de reiniciar um cliente atualizado. Um Cloud mais antigo retorna um erro explícito; o cliente não recorre a chamadas diretas ao Supabase.

O Cloud usa o projeto de autenticação configurado, valida as entradas, limita o volume de requisições e o tamanho das respostas, e retorna apenas campos da sessão. Tokens nunca são registrados em logs nem incluídos em erros. As requisições não são repetidas automaticamente; as respostas são no-store. As credenciais obtidas a partir de agora registram a origem do Cloud; mudá-la exige entrar de novo antes da renovação. As credenciais antigas adquirem essa origem na primeira renovação bem-sucedida contra o endereço confiável atual do Cloud.

O limite de requisições do endpoint do Cloud é por processo. Implantações em produção também devem aplicar um limite compartilhado na borda. As configurações do Supabase do site continuam no projeto do Cloud; nenhuma mudança de schema no banco de dados é necessária para esta migração.

O conector na nuvem hospedado mantém a chave do Composio e a lista de apps permitidos no Cloud. O plugin de runtime embutido dele, connector-cloud, mostra cartões de autorização no chat Web e retoma a ferramenta que estava esperando depois de um vínculo verificado. O plugins.json controla o interruptor do plugin; ele não contém credenciais da plataforma.