
Transcrição ao Vivo Quando a Firewall Bloqueia os WebSockets
As redes empresariais adoram permitir HTTPS e matar em silêncio os upgrades de WebSocket. Isso quebra silenciosamente a transcrição em tempo real. O GeekBye v2.0.8 recorre automaticamente a um transporte só-HTTPS — e lançá-lo destapou um bug que teria tornado toda a funcionalidade inútil.
Há uma forma específica e exasperante de a transcrição em tempo real falhar numa rede empresarial. O seu Wi-Fi está bom. O HTTPS funciona — consegue carregar qualquer site. Mas a transcrição ao vivo simplesmente... não arranca, e nada lhe diz porquê.
O culpado é uma classe de proxy empresarial que permite o tráfego HTTPS normal mas bloqueia o upgrade de WebSocket — o handshake que transforma uma ligação HTTPS no canal persistente e bidirecional de que a transcrição em tempo real precisa. Para o proxy, um WebSocket parece um túnel não vigiado para fora da rede, por isso mata-o. Para si, a transcrição está quebrada em silêncio.
O GeekBye v2.0.8 adicionou uma alternativa automática para exatamente isto — e construí-la fez emergir um bug que teria feito com que toda a funcionalidade não fizesse nada.
Porquê uma alternativa, e não apenas uma nova tentativa
Já lidamos com redes instáveis. Se a sua ligação cair a meio da sessão, o GeekBye reconecta com backoff e guarda o seu áudio em buffer para que nada se perca — essa é uma funcionalidade separada, tratada em porque é que o seu notetaker com IA para com mau Wi-Fi.
Mas um WebSocket bloqueado não é uma ligação instável. Repetir o mesmo WebSocket contra um proxy que recusa WebSockets falha da mesma forma todas as vezes, para sempre. A única correção é um transporte diferente — um que pareça o HTTPS simples que o proxy já permite.
Por isso o v2.0.8 recorre a um transporte só-HTTPS sobre o mesmo endpoint autenticado:
- De descida (transcrições que lhe chegam): server-sent events — uma resposta HTTPS de longa duração que o proxy vê como um download em streaming corrente.
- De subida (o seu áudio a sair): pedidos POST em lote, cada um a transportar um fragmento de áudio com um número de sequência para que o servidor os possa reagrupar por ordem mesmo que a rede os reordene.
Sem socket persistente, nada que pareça um túnel — apenas pedidos e respostas HTTPS. Se um proxy o deixa usar um site, deixa passar isto.
O bug que teria lançado uma funcionalidade morta
Aqui está a parte que vale a leitura. Supõe-se que a alternativa é acionada quando a ligação WebSocket esgota as suas tentativas com uma assinatura de transporte bloqueado — cada tentativa a falhar no upgrade, sem problema de auth nem de quota, pelo menos uma rejeição com forma de proxy. Um proxy que bloqueia um WebSocket responde tipicamente ao upgrade com um HTTP 403 Forbidden ou 407.
O problema: o nosso código de ligação já tinha uma regra segundo a qual um 403 significa erro fatal de autenticação — para, mostra-o ao utilizador, não repitas. O que é correto quase em todo o lado. Mas significava que o 403 de um proxy bloqueante — o sinal exato que devia ter acionado a alternativa — era em vez disso lançado como erro fatal antes de a lógica da alternativa alguma vez poder correr. Só uma queda bruta de ligação (um fecho 1006) chegava à alternativa. Por isso a funcionalidade teria funcionado para o caso raro e falhado em silêncio para o seu verdadeiro alvo principal: o proxy empresarial.
Apanhámos isto enquanto endurecíamos o lançamento, não em produção. A correção: um 403/407 na etapa do upgrade do WebSocket é agora tratado como recuperável para que o ciclo de ligação se possa esgotar até à alternativa — enquanto uma falha genuína de autenticação (que chega de outra forma, depois de o upgrade ter sucesso) continua a falhar depressa, exatamente como antes. Um teste de regressão fixa agora a distinção: um 403 de proxy bloqueante deve recorrer à alternativa; um 403 de auth real não deve.
O resto do endurecimento seguiu a mesma linha paranoica: um timeout em cada POST de subida para que um proxy que aceita um pedido mas nunca responde não possa encravar o fluxo de áudio, e uma garantia de que um problema genuíno de início de sessão nunca possa ser mascarado em silêncio pela maquinaria da alternativa.
Testámo-lo contra um proxy hostil real
Uma funcionalidade cujo propósito inteiro é sobreviver a redes hostis não pode ser validada só por testes unitários — os testes unitários não têm proxies. Antes de a ativar, passámos a app real por um reverse proxy local configurado para fazer exatamente o que os proxies empresariais fazem: reencaminhar HTTPS, recusar os upgrades de WebSocket com um 403.
O rasto nos logs é o recibo: quatro tentativas de WebSocket bloqueadas, a assinatura de esgotamento reconhecida, a troca automática para o transporte HTTPS, e depois uma sessão de transcrição saudável de 96 segundos sobre HTTPS puro — 66 segmentos de transcrição, zero perdas. O failover funciona porque o vimos a fazer failover.
Três lições transferíveis
- "Funciona com Wi-Fi instável" e "funciona atrás de um proxy hostil" são garantias diferentes. Uma precisa de reconexão; a outra precisa de um transporte diferente. Confundi-las deixa uma população inteira de utilizadores empresariais quebrada em silêncio.
- A sua classificação de erros pode esconder a sua própria funcionalidade de si mesma. Uma regra correta 99% das vezes (403 = auth fatal) era exatamente errada para o 1% que esta funcionalidade existia para servir. Quando adiciona uma alternativa, audite se a condição que a dispara consegue sequer chegar à alternativa.
- Teste o adversário, não apenas o caminho feliz. O único teste honesto de "sobrevive a um proxy que bloqueia WebSockets" é um proxy que bloqueia WebSockets. Construímos um.
O GeekBye v2.0.8 lançou a alternativa HTTPS protegida por flag e validada. Sobre o trabalho de fiabilidade ao lado do qual assenta, veja porque é que o seu notetaker com IA para com mau Wi-Fi, e sobre os lançamentos vizinhos desta série, porque é que o seu notetaker com IA para de gravar a meio da reunião (v2.0.9) e porque a transcrição com IA ouve mal os termos técnicos (v2.0.11).