Mapa da trilha
Conteúdo detalhado
🔌 RPC e event bus
Como o core expõe funcionalidades via controller registry, fala com o renderer sem CORS e coordena módulos internos por broadcast tipado.
Cada domínio em src/openhuman/<dom>/ declara handlers em rpc.rs e expõe schemas em schemas.rs — registrados num registry central.
É a regra única para adicionar um método. Sem isso você não consegue chamar nada do TypeScript nem do CLI.
ControllerSchema, RegisteredController, all_*_registered_controllers, wiring em src/core/all.rs.
Tipo de retorno padrão dos controllers que carrega valor de sucesso OU erro estruturado — sempre serializável para JSON-RPC.
Sem ele cada handler inventa formato próprio e o frontend explode. RpcOutcome é o "Result" do core.
Variantes Ok/Err, erro tipado, propagação até o renderer, mapeamento em coreRpcClient.
Metadados sobre cada método (campos, tipos, descrição) declarados no schemas.rs e consumidos por CLI e JSON-RPC genéricos.
Permite que adapters não cresçam ramos por domínio — toda exposição é dirigida por dados.
all_controller_schemas(), all_registered_controllers(), ControllerFuture, handle_* fns delegando para rpc.rs.
Comando Tauri que roteia chamadas RPC do renderer para http://127.0.0.1:<port>/rpc com bearer auth, evitando preflight CORS.
fetch() direto força OPTIONS preflight — quebra silenciosamente em produção. invoke contorna isso e ainda autentica.
OPENHUMAN_CORE_TOKEN, core_rpc_token, coreRpcClient, IPC nativo vs HTTP do renderer.
Pub/sub tipado em cima de tokio::broadcast. Muitos subscribers, sem retorno, eventos descritos por DomainEvent.
Desacopla domínios. Cron publica, webhook escuta, memory observa — sem ninguém importar ninguém.
DomainEvent #[non_exhaustive], EventHandler trait, SubscriptionHandle RAII, domain() filter.
Dispatch 1-para-1 por método string, zero serialização. Tipos Send + 'static, mas não Serialize — trafega trait objects, Senders, Arcs.
Quando dois módulos precisam conversar in-process com handles vivos (mpsc, oneshot), JSON quebra. Native registry resolve.
register_native_global, request_native_global, NativeRequestError, override em testes.
🖼️ CEF e webview accounts
Por que o app embute Chromium, o que CDP destrava, e a regra de ouro que mantém os webviews de terceiros seguros: zero JS injection.
Chromium Embedded Framework — runtime de browser empacotado no app, em vez do webview nativo do SO.
WKWebView, WebView2 e WebKitGTK não expõem Chrome DevTools Protocol. Sem CDP, nada de "saber o que tá rolando no Slack/Whatsapp".
Target.getTargets, IndexedDB.requestData, DOMSnapshot, Page.addScriptToEvaluateOnNewDocument, --remote-debugging-port=19222.
CLI customizada em app/src-tauri/vendor/tauri-cef/crates/tauri-cli que empacota Chromium em Contents/Frameworks/.
Stock @tauri-apps/cli produz bundle quebrado: panic em LibraryLoader::new. Diagnóstico desse erro custa horas.
scripts/ensure-tauri-cli.sh, pnpm tauri:ensure, [patch.crates-io], fork em tinyhumansai/tauri-cef.
Um módulo Rust por provider (whatsapp, telegram, slack, discord, meet, imessage) com WebSocket para CDP em cadência fixa.
Toda a inteligência de "ler o que está acontecendo lá dentro" mora aqui — não no renderer, não no servidor.
Tick 2s DOM + 30s IDB walk, openhuman.memory_doc_ingest, webview:event payloads.
Webviews acct_* (Slack, WhatsApp, Telegram, Discord, browserscan) carregam com ZERO JS injetado por design.
Qualquer script que roda dentro de origem terceira é superfície de ataque e contamina o estado da página.
CEF handlers nativos, CDP a partir do scanner, providers grandfathered (gmail, linkedin, meet), audit obrigatório.
Domínios do Chrome DevTools Protocol usados para observar e dirigir os webviews sem rodar JS na página.
É a interface oficial. Se você quer interceptar request, mudar user-agent, simular clique — tudo aqui.
Network.* fetch, Emulation.setUserAgentOverride, Input.dispatchMouseEvent, Page.navigate, CefRequestHandler.
Plugins Tauri podem injetar init scripts globais por padrão. tauri-plugin-opener instala click listener via init-iife.js.
É vetor silencioso: adiciona JS em TODOS os webviews, incluindo os de terceiros. Quebra a regra zero-injection sem aviso.
js_init_script, .open_js_links_on_click(false), audit ao adicionar plugin em app/src-tauri/src/lib.rs.
📱 Cliente iOS (experimental)
Como o iOS conversa com o core desktop por três transportes diferentes, com criptografia E2E, PTT nativo e pareamento via QR.
Target iOS coexiste no repo mas não é produto entregável. Não roda core Rust on-device — conecta ao desktop.
Saber o que existe e o que NÃO existe evita expectativas erradas e PRs que tentam shipar o que não está pronto.
app/src/pages/ios/, components/ios/, dependência do backend #709, sem core local.
Quando iPhone e desktop estão na mesma rede, vai direto: HTTP ao core na porta dele.
Latência mínima, zero dependência de backend. É o caminho feliz quando a rede coopera.
ConnectionProfile, descoberta de IP, fallback automático quando LAN falha.
Relay socket.io no backend, mas o conteúdo é criptografado E2E com XChaCha20-Poly1305 sobre key agreement X25519.
Resolve NAT/CGNAT sem servidor ver mensagem. Backend é só carteiro cego.
app/src/lib/tunnel/, channelId, pairingToken, sessionToken, ephemeral keypair, nonce.
Último recurso: HTTP ao backend cloud quando LAN falha E tunnel está fora do ar.
Garante que o app não fica preto. Cobertura de cenário, mesmo que com features reduzidas.
Backend API endpoints, autenticação por sessionToken, ordem de fallback LAN → Tunnel → Cloud.
Plugin Tauri iOS-only em packages/tauri-plugin-ptt/ que usa APIs Apple de PushToTalk para áudio com tela bloqueada.
PTT no iOS exige entitlement especial e ciclo de vida diferente. Não dá pra hackear com microfone genérico.
Swift bridge, AVAudioSession, Push to Talk framework, entitlement com.apple.developer.push-to-talk.
Desktop gera QR com cid + pairingToken + chave pública. iOS escaneia e abre tunnel ao backend assumindo role:client.
É o único momento em que as duas pontas trocam chaves. Errar aqui = sessão sem E2E.
channelId, NSCameraUsageDescription, devices RPC domain, dependência backend tinyhumansai/backend#709.