Arc OS — Arquitetura

Visão Geral

O Arc OS substitui 11.321 linhas de infraestrutura customizada em Python/JS pelas ferramentas nativas do Claude Code. O agente de IA É o backend.

Arquitetura do Sistema (Phase 52.1)

graph TB
    User[👤 User Browser :18888]
    TG[📱 Telegram]
    Local[💻 Local IDE]

    subgraph "Edge"
      Nginx[Nginx :18888<br/>basic-auth + deny-list]
      FE[React CRM + Phaser<br/>frontend container]
    end

    subgraph "Master Bot Bun :19210 — 127.0.0.1 only"
      ApiSrv[api-server.ts<br/>196 LOC]
      Routes[master-bot/routes/<br/>auth · internal · cli · websocket]
      Router[shared/routes/router.ts<br/>373 LOC dispatcher]

      subgraph "19 Domain Modules — Phase 48"
        D1[auth · projects · workers]
        D2[skills · sage · chat]
        D3[wiki · files · onboarding]
        D4[billing · invites · analytics]
        D5[+ 7 more]
      end
    end

    subgraph "Federated Bots"
      Master[Master Bot<br/>orchestrator]
      Child[Child Bots<br/>per-project]
      Claude[claude -p CLI]
    end

    subgraph "Intelligence Layer"
      Eval[Binary Evals]
      Ctx[Context Router top-5]
      Learn[Learnings inject]
      Karp[Karpathy nightly loop]
    end

    NB[NotebookLM Bridge<br/>FastAPI :19213 localhost]
    Google[(Google NotebookLM)]

    DB[(SQLite WAL<br/>30+ tables<br/>migrations 001-035)]
    Vault[(AES-256-GCM Vault<br/>config/vault.json)]
    Bridge[Local Bridge CLI<br/>WebSocket relay]

    User -->|HTTPS| Nginx
    Nginx --> FE
    Nginx -->|/api/crm/*| ApiSrv
    Nginx -->|/api/sse/*| ApiSrv
    Nginx -->|/ws/terminal| ApiSrv
    ApiSrv --> Routes
    Routes --> Router
    Router --> D1 & D2 & D3 & D4 & D5

    TG --> Master
    TG --> Child
    Master -.spawns via tmux.-> Child
    Child --> Claude
    Claude --> Eval & Ctx & Learn

    Router -.queries.-> NB
    Child -.auto-sync.-> NB
    NB --> Google

    Router --> DB
    Router --> Vault
    Child --> Vault

    Local --> Bridge
    Bridge -.ws relay.-> ApiSrv
    Karp -.nightly.-> DB

Principais características:

LEGADO (v1):
User → Telegram Bot (Python 111KB) → HybridEngine → command_queue.json
       → bridge_processor.sh → Claude → command_responses.json
       → FastAPI EventBus → WebSocket → Phaser UI

V2 (NATIVE-FIRST):
User → Official Telegram Channel → Claude Code Session
       ↓                                ↓
       reply/edit_message          Agent Teams (TaskCreate/SendMessage)
                                        ↓
                                   Write state → JSON files
                                        ↓
                                   Arc OS Bridge MCP → HTTP/SSE → Phaser UI

Redução: 11.321 linhas → ~3.700 linhas (67% menos código)

Componentes

1. Claude Code Session (O Cérebro)

A sessão Claude Code substitui:

Toda a orquestração acontece nativamente via Agent Teams.

2. Arc OS Bridge MCP Server (Adaptador de Estado)

Servidor MCP em TypeScript (Bun) que faz ponte entre o estado do Claude Code e o frontend.

MCP Tools (lado Claude Code):

Tool Direção Descrição
get_office_state leitura Lê state/office-state.json
update_agent_state escrita Atualiza posição, status e balão do agente
get_tasks leitura Lê arquivos de tarefas do Agent Teams
get_knowledge leitura Lê índice de conhecimento

HTTP API (lado Frontend):

Endpoint Método Descrição
/api/state GET Estado completo do escritório
/api/tasks GET Lista de tarefas
/api/knowledge GET Índice de conhecimento
/api/events GET Stream SSE

3. Phaser Frontend (Camada Visual)

Phaser 3.80 + Vite. Conecta-se ao servidor MCP via HTTP/SSE.

Diferença-chave em relação à v1: sem WebSocket — substituído por SSE do servidor MCP. Sem UI de entrada de comandos — o Telegram é a interface de comando.

4. Interface de Comando Telegram (Camada Tática de UI — Phase 21.0)

O Telegram é o painel de controle principal de todo o Arc OS. Duas camadas de bots:

Master Bot (@citadel_ceo_bot):

Child Bots (@cv2_pt_bot, etc.):

Integração CRM (desenvolvimento):

CRM_BASE_URL = http://62.171.128.248:18888  (dev)
               https://crm.citadel.v2       (future prod)

Todos os layouts de teclado definidos em shared/ui_templates.ts — fonte única para mudanças de UI.

Protocolo de dados de callback: action:target (máx. 64 bytes)

Fluxo de Dados

1. Usuário envia "/status" via Telegram
2. Sessão Claude Code recebe via Telegram Channel
3. Rick lê state/office-state.json + TaskList()
4. Rick responde via Telegram (edit_message para atualizações ao vivo)
5. Rick chama update_agent_state() via MCP
6. Servidor MCP escreve em state/office-state.json
7. File watcher detecta a mudança → envia evento SSE
8. Frontend recebe SSE → atualiza sprites dos agentes

Gerenciamento de Estado

Todo o estado reside em arquivos JSON sob state/:

Arquivo Schema Atualizado Por Lido Por
office-state.json Posições, status e balões dos agentes Claude (via MCP) Frontend (via HTTP)
knowledge.json Metadados de arquivos indexados Agente Squanchy Frontend, Beth
reports/*.json Saída de análise Beth, Summer Frontend

Tarefas do Agent Teams gerenciadas nativamente pelo Claude Code em ~/.claude/tasks/citadel-v2/.

Agentes (6)

Agente Função Modelo Ativação
Rick CEO/Orquestrador opus-4.6 Sempre ativo (líder do time)
Morty SRE/Monitoramento haiku-4.5 Health checks, cron
Summer Memória/Revisão sonnet-4.5 Code review, segurança
Jerry Manutenção haiku-4.5 Limpeza, docs
Squanchy Arquivista haiku-4.5 Indexação de arquivos
Beth Analista sonnet-4.5 Pesquisa, análise

Supply Chain

CEO → Rick (decompõe) → Agent Team (executa)
                       → Cross-Review (Summer valida)
                       → Rick (sintetiza)
                       → CEO (resultado final)

Garantida por meio de:

Stack Tecnológico

Camada v1 v2
Backend FastAPI + Python 3.12 Sessão Claude Code
Banco de Dados SQLite (8 tabelas) Arquivos JSON + Agent Teams
Mensageria WebSocket + EventBus Agent Teams SendMessage
Estado SQLite + JSON bridge Arquivos JSON (state/)
Frontend Phaser 3.86 + WebSocket Phaser 3.80 + SSE
Telegram Bot customizado (111KB) Plugin de Channel oficial
Bridge bash + jq (19,6KB) Eliminado
MCP Nenhum Arc OS Bridge (TypeScript)
Deploy Docker Compose Docker Compose

Lifecycle Hooks

Hooks do Claude Code (~/.claude/settings.json) sincronizam automaticamente o estado dos agentes:

SubagentStop event → subagent-stop.sh → office-state.json (agent=idle)
                                              ↓
                                   StateManager (fs.watch) → SSE → Phaser UI

Stop event → session-end.sh → latest_wrapup.txt + all agents=idle

Scripts: scripts/citadel-hooks/subagent-stop.sh, scripts/citadel-hooks/session-end.sh

Campos-chave: subagentName (SubagentStop), stopReason (Stop), cwd (ambos).

NotebookLM Bridge (Phase 36.3)

Busca semântica real via Google NotebookLM, substituindo uploads manuais de arquivos:

Cloud PM Chat → Bun Master Bot (:19210)
                    │
         executeAskNotebooklm()
                    │
         HTTP → FastAPI Bridge (:19213, localhost only)
                    │
              notebooklm-py async client
                    │
              Google NotebookLM (free semantic search)

         Fallback: local keyword search (existing code)

Exportação baseada em arquivos legada (/citadel-wrapup, /citadel-recall) ainda funcional como fallback.

Política de Roteamento de Dados e Tarefas

Sistema de três camadas. Cada camada tem um propósito estrito. Misturar camadas = caos.

┌─────────────────────────────────────────────────────────────────┐
│  TIER 1: Working Memory (Quente)                                │
│  office-state.json + state/tasks/                               │
│  CLI: /citadel-task, /citadel-status                            │
│                                                                 │
│  Tarefas diárias dos agentes. Vive durante a sessão. Morre ao  │
│  final. Tarefa concluída → /citadel-wrapup → Tier 3.           │
├─────────────────────────────────────────────────────────────────┤
│  TIER 2: Backlog Estratégico (Morno)                            │
│  GitHub Issues (repos Claude-CEO + citadel-v2)                  │
│                                                                 │
│  Apenas épicos: Phase 20, Phase 21, bugs globais.               │
│  Sem tarefas diárias. Sem issues "corrigir typo".               │
│  Um issue = uma iniciativa multissemanal ou defeito crítico.    │
├─────────────────────────────────────────────────────────────────┤
│  TIER 3: Memória de Longo Prazo (Frio)                          │
│  docs/library-export/ → Google Drive → NotebookLM              │
│  CLI: /citadel-wrapup, /citadel-recall                          │
│                                                                 │
│  Enciclopédia. Resultados de sessão, decisões arquiteturais,    │
│  RAG. Arquivo somente-leitura. Sem tarefas ativas.              │
└─────────────────────────────────────────────────────────────────┘

Regras de Roteamento

Tipo de Dado Camada Exemplo
"Fix deploy script" 1 — Working Memory /citadel-task "Fix deploy script"
"Phase 20: Multi-Tenant SaaS" 2 — GitHub Issues gh issue create --title "Phase 20: ..."
"Resumo de sessão: hooks implementados" 3 — Library /citadel-wrapup → NotebookLM
"Decisão arquitetural: escolhemos SSE em vez de WS" 3 — Library Arquivado no wrapup após a sessão
"Bug: SSE cai no VPS" 2 — GitHub Issues Apenas se for cross-session / bloqueante
"Rick está trabalhando nos hooks" 1 — Working Memory Status do agente em office-state.json

Ciclo de Vida

CEO dá tarefa → Tier 1 (agente trabalha nela)
                     ↓ concluída
                 /citadel-wrapup → Tier 3 (arquivada)
                     ↓ se estratégica
                 gh issue create → Tier 2 (rastreada a longo prazo)

Anti-padrões (NÃO FAÇA)

Infraestrutura (Phase 20.5)

Logging Estruturado (shared/logger.ts)

Formato JSONL, saída dupla (arquivo + console), divisão diária de arquivos por categoria.

/var/log/citadel/
├── master/
│   ├── system-2026-04-02.log   ← ciclo de vida, config, health
│   ├── dialog-2026-04-02.log   ← (não usado pelo master)
│   └── error-2026-04-02.log    ← erros (também em system)
├── citadel-v2/
│   ├── system-2026-04-02.log
│   ├── dialog-2026-04-02.log   ← mensagens usuário ↔ Claude
│   └── error-2026-04-02.log
└── <project-name>/             ← por projeto integrado

Rotação de logs: config/logrotate-citadel.conf/etc/logrotate.d/citadel (diária, retenção de 7 dias).

Vault de Secrets (shared/vault.ts)

Armazenamento criptografado com AES-256-GCM para tokens de bot.

Key source: SECRET_ENCRYPTION_KEY env → config/vault-key file → auto-generated
Storage:    config/vault.json (atomic writes: tmp + mv)
Cache:      In-memory after initVault() — no disk I/O per getSecret()
Fallback:   getSecret("FOO") → vault cache → process.env.FOO
Naming:     child:<project-name>:token

O próprio token do master permanece no .env (o vault carrega dentro do processo master).

Watchdog Auto-Recuperável (master-bot/watchdog.ts)

Monitor em segundo plano para child bots. Roda dentro do processo do master bot.

A cada 30s: HTTP health check → /api/child/health (timeout 5s)
  Saudável → zera falhas
  Não saudável → incrementa falhas
  3+ falhas + backoff expirado → auto-restart (mata tmux → inicia novo com token do vault)
  Backoff: 30s → 1m → 5m → 15m → 60m (cap)
  10 falhas consecutivas → desativa permanentemente + notifica o CEO

Estado persistido em config/watchdog-state.json (sobrevive ao restart do master). Notificações ao CEO via Telegram: primeiro restart, falha de restart, desativação permanente. Comando /watchdog: status em tempo real de todos os children.

Protocolo de Remoção de Projeto (Phase 20.4 + 21.0)

/remove_project <name> → tripla confirmação → limpeza completa:

1. Mata sessão tmux: child-<name>
2. Kill em massa de fantasmas: ps aux | grep child-<name> → kill -9 todos os PIDs
3. Verificação de porta: ss -tlnp | grep :<port> → libera à força se ocupada
4. Remove de bot_registry.json + recarga em memória
5. Exclui /opt/repos/<name>/ (segurança: path deve estar sob /opt/repos/, mín. 3 segmentos)
6. Exclui /var/log/citadel/<name>/

Nomes protegidos: citadel-v2, citadel, claude-ceo, claude-CEO — remoção bloqueada.

Problema de processo fantasma (lição aprendida): após o kill do tmux, processos órfãos bun podem segurar portas. Kill em massa + verificação de porta evita "bots fantasma" que respondem a health checks mas ignoram o Telegram.

Gerenciamento de Skills (Phase 21.0)

Os child bots carregam skills de duas fontes na inicialização, com deduplicação via Set:

Fonte 1: MANIFEST.md (JSON)
  → manifest.skills[]          (correspondidos durante o onboarding)
  → manifest.library_skills[]  (arquivos .md da library correspondidos)

Fonte 2: diretório skills/
  → arquivos *.md → nome do arquivo sem extensão

Merge: Set<string>(manifest.skills + manifest.library_skills + skills/*.md)

Exemplo (projeto PT): 5 do manifest + 7 de skills/ = 12 skills únicas.

Skills aparecem como:

Segurança (Phase 42 — Auditoria Sentinel 2026-04-23, 4 passagens, 13 patches)

Visão geral completa: SECURITY.md. Relatório de auditoria: security/audit-2026-04-23.md.

Secrets e armazenamento:

Autenticação:

Multi-tenancy (Phase 42):

Perímetro de rede:

Segurança de entrada / path:

Cobertura de regressão: scripts/vps-sync.sh executa 7+ smoke tests pós-deploy a cada deploy (bind no loopback, path traversal, validação chat/save, canário de proxy, SSE ?token=, validação fail-closed, bloqueio de SSRF se CEO_TOKEN definido).

Módulos do Master Bot (Phase 25 — Resolução DEBT-1)

O master bot é organizado em módulos focados:

master-bot/
├── bot.ts               ← Bootstrap: vault, registry, context, conecta tudo (106 linhas)
├── context.ts           ← Tipo MasterContext + interfaces de domínio
├── api-server.ts        ← Bun.serve() — HTTP, WebSocket, SSE, rotas CRM
├── tg-api.ts            ← Wrapper da Telegram Bot API (sendMessage, getUpdates, etc.)
├── child-state.ts       ← Lê estado do child bot, health, heartbeat, tmux, bridge
├── telegram-commands.ts ← Todos os handlers /command, handler de callback query, roteador de mensagens
├── telegram.ts          ← Loop de polling simplificado + re-exports para compat. com versões anteriores
├── watchdog.ts          ← Monitor auto-recuperável de child bot
└── onboarding.ts        ← Wizard interativo de criação de projeto

bot.ts importa apenas de telegram.ts e api-server.ts. Todos os outros módulos são detalhes de implementação interna.

Bridge CLI (Phase 25 — Local Gateway)

bridge/
├── bin/citadel-bridge.ts    ← Entrada CLI (commander.js): connect, pull, push, status, disconnect
├── src/
│   ├── auth.ts              ← Validação JWT contra CRM
│   ├── config.ts            ← Persistência em ~/.citadel/bridge.json
│   ├── inject.ts            ← Marcadores <!-- CITADEL:START/END --> no CLAUDE.md
│   ├── sync.ts              ← Pull de skills-bundle + learnings, push de learnings locais
│   └── heartbeat.ts         ← Repórter de atividade de sessão
├── package.json
└── tsconfig.json

Endpoints da API CRM (50+ no total)

CRM Principal (Phase 22)

Endpoint Método Propósito
/api/master/health GET Health do master bot (público)
/api/crm/projects GET Lista todos os projetos + health ao vivo
/api/crm/projects/:name GET Detalhes do projeto
/api/crm/projects/:name/logs GET Tail de logs JSONL
/api/crm/projects/:name/files GET Listagem segura de diretório
/api/crm/projects/:name/files/upload POST Upload de arquivos
/api/crm/projects/:name/files/mkdir POST Cria pasta
/api/crm/projects/:name/files/create POST Cria arquivo
/api/crm/projects/:name/files/delete DELETE Exclui arquivo/pasta
/api/crm/projects/:name/files/clone POST Clona repositório git
/api/crm/projects/:name/files/read GET Lê conteúdo de arquivo
/api/crm/projects/:name/wiki/tree GET Lista arquivos .md da wiki
/api/crm/projects/:name/wiki/file GET Lê conteúdo de arquivo da wiki
/api/crm/projects/:name/skills GET Skills instaladas
/api/crm/projects/:name/metrics GET Série temporal de qualidade
/api/crm/projects/:name/restart POST Reinicia child bot
/api/crm/projects/:name/specs GET Lista specs
/api/crm/projects/:name/specs/:id/approve POST Aprova spec
/api/crm/projects/:name/specs/:id/reject POST Rejeita spec
/api/crm/projects/:name/active-role GET/POST Papel do agente
/api/crm/projects/:name/message POST Enfileira mensagem para worker
/api/crm/projects/:name/workers GET/POST CRUD do registry de workers
/api/crm/projects/:name/workers/:id PUT/DELETE Atualiza/exclui worker
/api/crm/projects/:name/workers/generate-prompt POST Gera system prompt com IA
/api/crm/projects/:name/skills-bundle GET Skills + evals para bridge
/api/crm/projects/:name/learnings GET/POST Sync de learnings
/api/sse/logs/:name GET Stream SSE de logs (?category=)

Dashboard e Wiki (Phase 32)

Endpoint Método Propósito
/api/crm/projects/:name/wiki/save PUT Salva/cria página da wiki
/api/crm/projects/:name/skills/save PUT Salva arquivo de skill
/api/crm/projects/:name/skills/delete DELETE Exclui arquivo de skill

Multi-Tenant (Phase 33)

Endpoint Método Propósito
/api/crm/account/settings GET/PUT Chaves de API no nível da conta
/api/crm/projects/create POST Criação simplificada de projeto
/api/crm/onboarding/setup POST Wizard completo de onboarding

MCP e CLI (Phase 34)

Endpoint Método Propósito
/api/mcp/issues/:project POST/GET CRUD de issues
/api/mcp/issues/:project/:id PUT Atualiza issue
/api/mcp/wiki/:project PUT Sync da wiki via MCP
/api/mcp/roadmap/:project GET/PUT Leitura/sync do roadmap
/api/cli/init/:project/:mode GET Contexto cloud para CLI
/api/mcp/skills/:project/:skill GET Busca skill para MCP
/api/mcp/report/:project POST Relatório de missão
/api/mcp/learnings/:project GET Obtém learnings para MCP

Terminal ao Vivo (Phase 35)

Endpoint Método Propósito
/api/crm/projects/:name/terminal/log POST Recebe JSONL do terminal via ARC CLI

Cloud PM e Conhecimento (Phase 36)

Endpoint Método Propósito
/api/crm/projects/:name/chat POST Proxy de chat SSE para Anthropic API
/api/crm/projects/:name/skills/generate POST Neural Skill Generator (NotebookLM)
/api/crm/projects/:name/notebooks GET Notebooks NotebookLM vinculados

Auth e OAuth (Phase 37)

Endpoint Método Propósito
/api/auth/register POST Registro email/senha
/api/auth/login POST Login email/senha
/api/auth/google GET Redirect OAuth Google
/api/auth/callback/google GET Callback OAuth Google
/api/auth/github GET Redirect OAuth GitHub
/api/auth/callback/github GET Callback OAuth GitHub
/api/auth/providers GET Provedores OAuth disponíveis

Notas Fixadas (Phase 41.8)

Endpoint Método Propósito
/api/crm/projects/:name/pins GET Lista notas fixadas (mais recentes primeiro)
/api/crm/projects/:name/pins POST Fixa mensagem de worker no Context Rail (body: worker_id, body, title e author opcionais)
/api/crm/projects/:name/pins/:id DELETE Remove pin

Backend: migration 009 (tabela pinned_notes), pinnedNoteQueries em shared/db.ts. Frontend: ContextRail.jsx busca no mount, escuta CustomEvent crm-pin-created, DELETE otimista.

Camada de Proteção de Dados (Phase 45)

Criptografia híbrida em repouso — base de criptografia client-side + criptografia vault server-side.

Client-Side (Browser)

Server-Side (Bun + SQLite)

Security Headers

Sanitização de PII

Endpoints de Recovery Key

Endpoint Método Propósito
/api/crm/account/recovery POST Cria recovery key (armazena master key criptografada)
/api/crm/account/recovery GET Lista recovery keys ativas
/api/crm/account/recovery DELETE Revoga recovery key(s)
/api/crm/account/recovery/restore GET Recupera master key criptografada para restauração

Detalhes completos de segurança: docs/SECURITY.md, docs/architecture/PHASE_45_E2EE.md.