Artigo publicado
Em uma malha dos seus próprios dispositivos, a confiança precisa ser conquistada em ambos os lados
No momento em que um dos seus dispositivos pode pedir a outro para executar um LLM ou ler seus dados, você tem uma superfície de ataque dentro da sua própria casa. Como a malha do Aurora conquista confiança em ambos os lados: transporte WebRTC, emparelhamento no estilo Bluetooth e RBAC de interseção.

- aurora
- distributed
- mesh
- security
- networking
O momento em que você permite que um de seus dispositivos peça a outro para executar um LLM, transcrever áudio ou ler do seu banco de dados, você cria uma superfície de ataque dentro da sua própria casa. Um Raspberry Pi comprometido não deve entrar diretamente nos dados do seu desktop. Portanto, a pergunta interessante para uma malha privada de IA não é como os dispositivos se comunicam. É como um dispositivo prova que tem permissão para isso.
Este é o terceiro artigo da minha série sobre a malha distribuída do Aurora. O primeiro abordou por que um único dispositivo é um limite. O segundo cobriu a arquitetura que permite que uma solicitação seja executada em outra máquina como uma alteração de configuração. Este cobre a parte que torna qualquer coisa segura para ser ativada: o transporte, o emparelhamento e o controle de acesso.
O transporte: WebRTC, e por que não as alternativas óbvias
Para comunicação ponto a ponto, o Aurora usa os DataChannels do WebRTC. Optei por eles em vez de WebSockets, soquetes brutos, uma VPN e pilhas P2P mais pesadas como libp2p, ZeroMQ ou gRPC. Quatro motivos guiaram essa escolha:
- Criptografia de ponta a ponta por padrão. Os DataChannels funcionam sobre DTLS-SRTP. Mesmo o servidor de sinalização usado para o handshake inicial não pode ler o que flui entre os pares. A criptografia é o único modo, não uma configuração que você precisa lembrar de ativar.
- Traversal de NAT integrado. O ICE com STUN/TURN trata da parte que a maioria subestima: fazer dois dispositivos em redes diferentes se encontrarem, sem encaminhamento de portas, IPs públicos ou uma VPN para vigiar.
- Battle-tested. O WebRTC transporta chamadas de vídeo para bilhões de pessoas. A criptografia e a maquinaria de NAT são maduras e bem compreendidas, o que é exatamente o que você quer sob uma fronteira de segurança.
- Baixa latência. SCTP sobre DTLS é ajustado para tempo real, o que importa quando alguém aguarda do outro lado do "Hey Aurora."
A única dependência externa no projeto é um servidor de sinalização STUN/TURN, que vê o mínimo: um endereço IP por par tentando se conectar. Ele não armazena nada e nunca vê o tráfego criptografado em trânsito. Você pode hospedá-lo por quase nada ou usar uma rede de sinalização pública. De qualquer forma, ele não pode ler seus dados. A sinalização leve do MQTT lida com a geração automática de salas e a presença criptografada (AEAD) de pares, de modo que os dispositivos se anunciem sem vazar quem está online para quem estiver observando.
Os dados que atravessam esses canais são JSON-RPC carregando os mesmos contratos tipados que os serviços usam internamente, de modo que uma chamada remota tenha o mesmo formato de uma local.
O portão de autenticação: culpado até ser emparelhado
Quando um par se conecta pela primeira vez por um DataChannel, o Aurora não confia nele. O RTCClient aplica um portão de autenticação: para um par não autenticado, apenas mensagens relacionadas à autenticação passam, e o portão descarta tudo o mais. Um par anônimo pode chamar exatamente quatro métodos: PairingStart, PairingConnect, PairingExchange e Login, a superfície mínima necessária para se tornar confiável, e nenhum método além disso.
Esconde-se aqui um problema de tempo. O emparelhamento precisa de um humano para aprovar o novo dispositivo, e humanos são lentos. Um timeout de conexão ingênuo mataria o handshake enquanto você caminha até aprová-lo. Então o portão executa um timeout inteligente. Um loop de batimento cardíaco, a cada aproximadamente 5 segundos, estende o prazo enquanto um fluxo de emparelhamento está realmente em andamento, e então deixa expirar quando nada está acontecendo. A conexão permanece aberta exatamente pelo tempo necessário.
Emparelhamento: o modelo Bluetooth
Entrar em uma malha deve parecer o emparelhamento de fones de ouvido, não a configuração de um firewall. Então é assim:
- O novo dispositivo solicita emparelhamento e mostra um código de 6 dígitos.
- Você verifica esse código em um dispositivo já confiável.
- Como administrador, você o aprova e, nesse momento, define suas permissões conforme o necessário.
- O Aurora emite um token de portador com escopo nas permissões que você concedeu.
Nenhuma senha atravessa a rede. Nenhuma chave pré-compartilhada para girar e perder. Apenas um código curto que você confirma pessoalmente, de modo que um humano estabeleça confiança intencionalmente, uma vez.
Confiança bilateral: A aprovando B não é B confiando em A
Esta é a escolha de design que mantenho com mais firmeza. A maioria dos sistemas trata a confiança como unilateral, onde um lado abre uma porta e o outro atravessa. Em uma malha onde qualquer dispositivo "confiável" pode ser comprometido posteriormente, isso é uma responsabilidade. Então o emparelhamento do Aurora é bilateral e em duas fases.
Na fase 1, o iniciador alcança o respondente. O PairingStart traz o ID do par remoto, o lado do respondente aprova e o PairingExchange emite um token. Na fase 2, o respondente faz o emparelhamento de volta automaticamente. Um passo _reverse_pairing() é executado pelo mesmo __PTBR_PROTECT_34_, de modo que a relação se torne mútua em vez de unidirecional.
Cada lado estabelece confiança em seus próprios termos. A Instância A decidindo confiar na Instância B não inscreve A no círculo de confiança de B. Ambos os lados executam o fluxo e ambos definem suas próprias permissões. Por baixo do capô, isso se consolida nas tabelas de autenticação. O Aurora mantém usuários, dispositivos e tokens sincronizados com mesh_peers por meio de sincronização de chaves estrangeiras de saída e emite um JWT durante a troca.
RBAC: o tópico do barramento é a permissão
O Aurora controla cada ação, e o modelo permanece uniforme: um tópico do barramento e uma permissão são a mesma string. Há 195+ strings de permissão validadas, e elas se aninham por granularidade, de um Auth.* amplo até Auth.use versus Auth.manage, até uma única operação como Auth.PairingApprove. Essa divisão entre uso e gerenciamento é o method_type do contrato do artigo anterior em ação real, pois ler de um serviço pertence a uma classe de permissão diferente da administração dele.
Na prática, você distribui a quantidade correta de acesso:
- Um alto-falante de sala de estar recebe TTS.* e STT.*, podendo ouvir e falar, mas não acessar DB.*. Ele nunca toca nos seus dados.
- Seu telefone recebe Orchestrator.*, chat.send e Scheduler.*, podendo fazer perguntas e definir lembretes.
- O dispositivo de um amigo que você emparelhou apenas para compartilhar computação recebe TTS.Request e nada mais. Ele pode usar seu mecanismo de TTS e permanece cego a tudo mais.
A regra que une tudo: as permissões efetivas são a interseção do que o usuário é permitido e do que o token está escopoado. Mesmo um token vazado não pode ultrapassar o usuário por trás dele, e um usuário com escopo generoso ainda não pode agir por meio de um token com escopo estreito.
A administração roda como seu próprio conjunto de métodos controlados: ApproveMeshPeer, DenyMeshPeer, ListMeshPeers e RemoveMeshPeer. Uma alteração de permissão (UpdateMeshPeerPermissions) se propaga por essas mesmas chaves estrangeiras de saída para as tabelas de auth, de modo que revogar um dispositivo o revogue em todos os locais, em vez de deixar uma concessão obsoleta para trás. A aplicação reside em uma camada de ACL dedicada na frente do gateway, no mesmo modelo de tópico como permissão.
Como você verificaria isso
Um modelo de segurança é tão bom quanto os testes que tentam quebrá-lo, portanto, a avaliação mira diretamente nos limites. Confirme que o portão de autenticação rejeita tentativas de RPC não autorizadas. Confirme que o timeout de emparelhamento e o loop de batimento cardíaco se comportam sob uma aprovação humana deliberadamente lenta. Coloque o DataChannel sob Wireshark ou tcpdump e confirme a criptografia DTLS no fio. Verifique o RBAC concedendo e negando por method_type para provar que uso e gerenciamento realmente são portas separadas.
A forma da confiança em um sistema que você possui
Junte as peças e uma filosofia emerge. A criptografia é o padrão. Novos dispositivos permanecem não confiáveis até que um humano confirme um código pessoalmente. A confiança é mútua e com escopo, nunca unilateral e nunca geral. As permissões são a interseção de identidade e token, então o sistema falha fechado. E a única parte externa, o servidor de sinalização, não pode ler nada que importe.
Nada disso é específico para assistentes de voz. Serviços baseados em contrato, um portão de autenticação no transporte, emparelhamento bilateral e RBAC baseado em interseção lhe dão um modelo para qualquer carga de trabalho de IA distribuída que você queira manter privada enquanto ainda a espalha por mais de uma máquina.
Isso encerra esta série sobre a malha distribuída do Aurora: o porquê, a arquitetura e o modelo de confiança. A malha funciona hoje, com emparelhamento e RBAC granular, compartilhamento seletivo de serviços com limites de capacidade, roteamento transparente com fallback e um sistema que roda em qualquer topologia, de um único processo a uma malha P2P. Em seguida vem o alcance: clientes móveis, uma interface web UI, LLMs on-device melhores e OAuth para MCP.
O Aurora é gratuito e de código aberto. Se você trabalha com segurança de sistemas distribuídos e teria traçado esses limites de forma diferente, essa é exatamente a conversa que espero ter.
Publicado originalmente no LinkedIn.
Projetos relacionados: escrita pública