Sobre o projeto

Wappie é um servidor de API do WhatsApp multi-tenant com um arquivo selado, além de um cliente web que consome a mesma API. Ele conecta sistemas empresariais ao WhatsApp via HTTP e WebSocket, com espaços de trabalho compartilhados, permissões por número e um cliente de mensagens. O servidor, CLI, cliente web e administração básica são de código aberto Apache-2.0; a hospedagem gerenciada e o faturamento comercial são mantidos separadamente, o piloto hospedado é apenas para convidados e gratuito, e os pagamentos lá são simulados. Funcionalmente, o servidor pareia um dispositivo WhatsApp a partir do terminal usando um código de oito caracteres (digitado em Dispositivos conectados) ou um QR renderizado no terminal, e então sela o tráfego desse dispositivo na entrada. Ele ingere a sincronização de histórico, projeta edições, revogações e reações, registra recibos e rastreia qual revisão cada leitor tinha na tela. Mídias recebidas são armazenadas exatamente como servidas pelo CDN da Meta, e o upload e envio de mídias externas são suportados, assim como a função de visualização única. Conteúdo estruturado (localização, enquete, contato, evento), contatos, nomes e fotos de perfil, preenchimento sob demanda e uma camada de conversa com contagens de não lidos, ticks, presença, grupos e enquetes estão todos implementados. O acesso é feito através de uma ferramenta CLI (`wsctl`) e de uma API HTTP/WebSocket, com um endpoint hospedado e `/v1/ws` para WebSocket. O modelo de proteção de arquivo é a peça central do projeto. As mídias do WhatsApp chegam já criptografadas em AES-256-CBC com um HMAC encrypt-then-MAC sob uma chave de mídia de 32 bytes; o texto cifrado é armazenado verbatim e apenas a chave de mídia é selada a uma chave pública do dispositivo. Os corpos das mensagens são selados com HPKE (RFC 9180, X25519 + HKDF-SHA256 + AES-256-GCM) sob uma chave de conteúdo que cobre um lote, o que o README justifica por razões de custo, e não de throughput. O servidor detém apenas chaves públicas: ele pode selar, mas não pode abrir. Cada dispositivo possui um par de chaves de arquivo gerado por qualquer cliente que o tenha pareado; a metade privada é selada à chave pública de cada conta que pode ler aquele dispositivo (uma concessão de chave) e então descartada. As chaves privadas da conta são geradas no navegador no momento do cadastro, encapsuladas sob uma chave derivada de Argon2id vinculada ao endereço da conta e nunca transmitidas; um código de recuperação encapsula a mesma chave por uma segunda vez. O navegador realiza o HPKE, a manipulação de chaves de conteúdo, a descriptografia de corpos de mensagens, nomes de contatos, fotos de perfil e anexos dentro da página. As permissões são em camadas: chaves de API possuem escopos de `read`, `send` ou `full`; um membro acessa apenas dispositivos concedidos a ele; um proprietário ou administrador acessa o envelope de cada dispositivo e pode parear, conceder, emitir chaves e alternar um dispositivo entre discreto e barulhento; nenhum escopo acessa a configuração do tenant. A terceiros é concedida uma conta de serviço — um par de chaves sem senha, com dispositivos concedidos como a de uma pessoa e acessada através de uma chave de API que atua em seu nome. A retenção é desativada por padrão; um tenant pode definir uma janela que o servidor aplica hourly a mensagens, recibos, eventos de grupo e anexos, enquanto chats e contatos permanecem. Uma pessoa pode ser apagada do arquivo em todos os dispositivos, e a exclusão de um dispositivo ou a redefinição de um arquivo remove seus objetos de anexo do armazenamento. Os logs mascaram identificadores em todos os níveis. Executar localmente requer PostgreSQL 18 ou superior para `uuidv7()`, e uma função de não-superusuário porque superusuários ignoram a segurança em nível de linha (row-level security). O armazenamento de objetos é opcional: sem configuração, os anexos ficam em fila no banco de dados até que o armazenamento apareça. Um alvo `make dev-up` inicia o Postgres e o MinIO no Docker. Os alvos de teste cobrem formatação, triagem, layout, testes com race-enabled, typecheck e build do cliente de navegador, cobertura e fuzzing, e cada teste roda em seu próprio esquema Postgres. O cliente web é construído com Vite em `web/dist` e servido por `WS_WEB_DIR`; nada é incorporado no binário Go e, sem um build presente, o servidor serve apenas a API. Durante o desenvolvimento, o servidor Vite faz proxy de `/v1` para a porta do Go, pois o manipulador de websocket aceita apenas conexões de mesma origem. O README declara os limites claramente em vez de sugerir mais do que é entregue. Um invasor executando código em um servidor ativo vê texto simples em trânsito entre a descriptografia do Signal, o selamento e o armazenamento, portanto, o selamento em repouso protege um disco roubado, um backup vazado ou um dump de banco de dados, não um processo comprometido. O armazenamento de sessão do whatsmeow deve permanecer legível pelo processo; quem o roubar pode personificar o dispositivo e ler novas mensagens, mas não o arquivo. O texto de saída passa em texto claro, assim como a mídia de saída, porque o upload do WhatsApp aceita apenas texto claro; a mídia de entrada nunca é descriptografada no lado do servidor. Metadados de anexos (tipo, tamanho, dimensões, duração, hashes) e metadados de roteamento, incluindo recibos, são legíveis, portanto, um dump do banco de dados revela o grafo social e quem leu o quê e quando, mas não o conteúdo. Revogar uma concessão impede que a chave seja obtida novamente, mas não pode recuperar uma cópia já desbloqueada, já que a chave residia no navegador. Perder todos os caminhos de acesso resulta na perda permanente do arquivo para todos. O material de sessão do navegador reside no IndexedDB como texto cifrado sob chaves WebCrypto não extraíveis, e o cliente envia uma política de segurança de conteúdo (CSP) e não carrega JavaScript de terceiros. A tabela de status lista as fases concluídas, desde esqueleto, migrações e criptografia de mídia até pareamento, ingestão, projeção de edição/revogação/reação, mídia de entrada e saída, sincronização de histórico, tentativa de mídia, contatos, preenchimento sob demanda, o cliente web, chaves por dispositivo e contas, a camada de conversa, incognito e quotas, e uma passagem de auditoria de segurança; o console de administração está listado como o próximo passo. Vetores de teste entre implementações são gerados em Go e abertos por ambas as implementações, incluindo casos negativos, como um blob movido para outra linha ou apresentado sob outro tipo, para que o cliente de navegador não concorde silenciosamente apenas consigo mesmo. Uma ferramenta `seeddemo` escreve uma pequena conversa falsa através do pipeline de ingestão real para desenvolver o cliente sem a necessidade de parear um telefone.