Todos os posts

FourA Digest, 12 a 19 de junho de 2026

Páginas não-UTF-8 retornam texto legível no Single em vez de mojibake, regras validate definem a classificação de sucesso e o hardening de segurança da Wave 0 foi implementado.

Highlights

Duas mudanças nesta semana afetam o que retorna de seus requests. Corpos de response deixam de chegar como mojibake em sites não-UTF-8 e responses não-200 aceitos via validate finalmente contam como sucesso em vez de falha. Também fechamos algumas brechas de segurança na API do cliente.

What's New

Páginas não-UTF-8 retornam texto legível no Single

Se você chama Single em fóruns búlgaros, e-commerce chinês, notícias japonesas ou qualquer coisa que envie windows-1251, GBK, Big5 ou Shift_JIS, o corpo do response costumava voltar como bytes quebrados. A camada HTTP subjacente tinha um decoder UTF-8 hardcoded, então uma página em cirílico chegava como промоции e não havia como recuperar o original do seu lado.

Isso está corrigido na camada de request. O Single agora detecta o charset de origem (via header Content-Type, depois <meta charset>, depois <meta http-equiv>) e faz o transcode para UTF-8 antes do corpo chegar ao seu envelope JSON. E páginas UTF-8 ou ASCII passam intactas. Conteúdo binário como imagens ou PDFs nunca é decodificado. Se você quiser os bytes brutos, returnBuffer: true ainda devolve o buffer original.

Padrão ativado. Nenhuma flag para alternar. Páginas que funcionavam antes ainda funcionam, páginas que retornavam lixo agora retornam texto legível. Usuários de navegadores também não precisam pensar nisso, o Chromium decodifica charsets nativamente.

Regras validate agora definem a classificação de sucesso

Quando você define validate em um request (por exemplo validate.status.accept = [200, 403]), a engine de request já honrava sua regra e resolvia o response sem um erro. Mas nosso classificador de resultado upstream ignorava sua regra e agrupava qualquer coisa que não fosse um 200 literal como application_fail. Duas consequências: seu 403 aceito aparecia como uma falha no Dashboard e, como apenas o sucesso é cobrado, esses responses entregues também não eram cobrados.

O classificador agora respeita o que validate declarou. Requests com validate contam como sucesso sempre que a engine os resolveu sem erro, seja qual for o status. Requests sem validate se comportam da mesma forma que antes (sucesso apenas em 200), então o caminho legado está intocado.

Correção apenas para frente: linhas históricas mantêm seu resultado armazenado, novos requests classificam corretamente. Então se você estava vendo App Fail em responses que você sabia que eram válidos, este é o motivo.

Hardening de segurança na API do cliente

Implementamos a Wave 0 de uma revisão de segurança em toda a API do cliente:

  • CORS agora é restrito a https://foura.ai. A configuração anterior refletia qualquer origem enquanto enviava credenciais, que é a configuração padrão de CSRF. Chamadas de browser de mesma origem e suas chamadas de API server-side não são afetadas.
  • A rota de métricas por trás de sua timeline de Activity costumava aceitar um filtro outcome de forma livre que fluía direto para a query. Agora ela possui allowlist para valores de resultado conhecidos. Não explorável por uma conta normal, mas vale a pena fechar.

Nenhum dos dois muda qualquer contrato da API. Você não notará nada durante o uso normal. Mas encontrar um problema e fechá-lo antes que alguém perceba ainda merece ser dito em voz alta.

Rótulos de Activity correspondem ao Overview

Uma pequena. A tabela de Activity em seu Dashboard costumava renderizar strings de resultado brutas como Application_fail enquanto os chips, gráfico de rosca e timeline do Overview mostravam rótulos amigáveis (App Fail) e codificavam com cores cada resultado. Mesmos dados, duas apresentações. Eles agora estão sincronizados, ambos lendo do mesmo rótulo e mapa de cores, para que o status de uma linha pareça o mesmo onde quer que você verifique.

Numbers

Esta semana não traz novos números de latência ou taxa de sucesso. A maior parte disso é trabalho de correção e segurança onde a métrica certa é "parar de estar errado" em vez de "ir mais rápido". O digest da próxima semana deve ter dados de throughput de algumas coisas em andamento.