
Não havia em lado nenhum do produto um evento a dizer “chegou um relatório novo”. Os avisos chegavam a uma caixa de entrada e a mais nada, por isso uma equipa que quisesse os seus relatórios no n8n, no Zapier ou num script seu não tinha para onde os apontar.
Agora há um destino: um URL seu, os eventos que quiser e uma chave de assinatura. Quatro eventos,
nomeados uma vez e escritos tal e qual em todo o lado - report.created, report.status_changed,
report.severity_changed e report.first_viewed. São uma interface a partir do momento em que
saem, porque alguém mete um deles num fluxo e uma mudança de nome parte-o em silêncio, por isso o
conteúdo leva a sua própria versão desde a primeira publicação.
O que vale a pena saber antes de apontar alguma coisa para lá:
- Todos os POST vão assinados. HMAC-SHA256 sobre a marca de tempo e o corpo em bruto, com a marca de tempo dentro do material assinado, de modo que um pedido capturado não lhe possa ser repetido mais tarde.
- O destino pertence à equipa, não a uma pessoa. O endereço tem de continuar a funcionar quando quem o acrescentou se for embora.
- As falhas são repetidas e depois param. A espera progressiva dura cerca de oito horas e meia antes de desistir.
-
Cada tentativa fica registada. “O webhook disparou?” responde-se a partir de
/app/webhookse não a partir dos registos de produção de alguém.
Um URL fornecido pelo cliente é, por construção, uma superfície de falsificação de pedidos, por isso o endereço é resolvido e verificado de novo mesmo antes de cada ligação e não apenas quando foi guardado, nunca se segue um reencaminhamento, e o corpo da resposta é lido só o suficiente para fechar o fluxo.
A página que um desconhecido abre
A página partilhada de um relatório é tanto a demonstração do produto como a ferramenta de triagem de quem é seu dono, e as duas coisas querem coisas diferentes do mesmo ecrã.
A ordem dos separadores foi decidida a pensar no dono: o que quem comunicou escreveu vem primeiro, porque é a coisa mais valiosa de um relatório e a mais curta. Isso está certo para quem trata da sua própria caixa de entrada e errado para aquele a quem a ligação foi enviada, que chegava e encontrava sete palavras com que não pode fazer nada, enquanto os erros de consola, os pedidos falhados e a gravação ficavam a um clique e por abrir. Quem não é dono do relatório aterra agora nas provas, e a faixa por cima dos separadores diz o que a captura contém, em vez de deixar que se descubra.
O leitor em si tinha dois defeitos, ambos visíveis numa única captura de ecrã. A sua superfície escura estendia-se por toda a largura da página, por isso qualquer gravação mais estreita do que essa faixa - num ecrã largo, quase todas - ficava encalhada no meio de um campo preto. E abria em pausa no fotograma zero, que é o que quer que estivesse no ecrã de quem comunicou enquanto ainda ia a estender a mão para o botão de gravar. A superfície escura é agora espaçamento do próprio elemento de vídeo, por isso agarra-se à gravação em qualquer proporção, e o leitor abre num fotograma escolhido por valer a pena olhar para ele.
Quem comunica fica a saber o que acontece à sua gravação
O registo de interações recusa-se a guardar o que alguém escreveu num campo de palavra-passe. O registo de rede oculta por omissão os valores das credenciais. O vídeo mostra o ecrã onde as escreveu, e nada age sobre isso.
A mesma pergunta, duas respostas diferentes - e quem está em melhor posição para a resolver é quem comunica, porque é o único que sabe se a ficha de cliente aberta por trás do erro importa. Por isso fica agora a saber em que se torna a gravação, antes de a começar em vez de depois.
É o mesmo instinto por trás de três alterações mais pequenas do outro lado. Alguém ler o seu próprio relatório nunca contou para o seu número de visualizações, mas nada o dizia; a página do relatório, a lista de relatórios e o resumo explicam agora, cada um deles, porque é que o número os deixa de fora.
Session Replay
Extensão gratuita do Chrome. Um clique na página que se está a portar mal captura a captura de ecrã, a consola e o registo de rede, e devolve-lhe um link para colar no ticket.
A captura ficou mais barata, e a sua ocultação ficou coerente
Uma captura corre à densidade de píxeis do ecrã salvo indicação em contrário, por isso um ecrã 6K gravava 6016 píxeis de largura. Esses píxeis eram pagos três vezes: no envio de quem comunica, onde comem o orçamento de bytes do plano e portanto a duração que lhe é permitido gravar; no armazenamento, porque o original é guardado seja o que for que se codifique ao lado dele; e em cada transcodificação, onde descodificar é a metade cara. Medido em produção, um clipe de trinta e dois segundos custava nove minutos e cinquenta e quatro segundos de CPU. A captura está agora limitada a 1920 de largura.
A correção da ocultação é a mais importante das duas. Um domínio com direito a captura sem ocultação
baixava a máscara dos cabeçalhos e da cadeia de consulta até só lhe restarem os nomes de cartão, de
modo que uma mesma gravação podia ocultar um campo de formulário chamado api_key e ao mesmo tempo
manter em claro um cabeçalho X-Api-Key, um token CSRF e um ?password= do mesmo pedido. Ninguém
escolheu aquilo: eram dois caminhos por um mesmo ficheiro a responder de forma diferente à mesma
pergunta. As credenciais em cabeçalhos e em URLs são mascaradas também num domínio com esse direito,
e um campo de passaporte que a lista de credenciais andava a engolir passou a ser apanhado como deve
ser.
Três coisas que dissemos que íamos fazer
Vale a pena listá-las juntas, porque sobre cada uma delas se escreveu aqui antes de estar feita.
A extensão já não expõe os seus ícones e os seus sons a todas as origens. web_accessible_resources
concedia as duas pastas a todos os URLs e nunca nenhuma página carregou fosse o que fosse de
qualquer uma delas - uma extensão lê os seus próprios ficheiros empacotados sem qualquer concessão.
Era a irmã da permissão por usar sobre a qual escrevemos no domingo, e ambas desapareceram; a
extensão 1.6.2 está na loja.
A biblioteca de integração é servida a partir das nossas próprias páginas como 0.4.0, por isso o
identify() a levar qualquer chave que uma meta tag possa levar já não é verdade apenas para quem
instala a partir do npm. Foram corrigidos três sítios que ainda diziam aos donos dos sites que
aceita cinco chaves.
E às zero e trinta desta madrugada o servidor MCP começou a dizer, no aperto de mão, que o texto que transmite é de terceiros: que o comentário, o título, o URL e o nome de um relatório foram escritos por quem comunicou o erro, normalmente uma pessoa do público, e que devem ser tratados como dados para ler e citar, nunca como instruções a seguir. Registámos isso ontem, com base na investigação da GhostSplice, e escrevemos porquê.
Coisas mais pequenas
- É o dono da subscrição que manda no cancelamento e na retoma dela.
- Um domínio reclamado chama-se domínio em todo o lado onde a interface lhe dá um nome, em vez de site em metade dos sítios.
- As imagens dos artigos aqui podem levar legenda, texto alternativo e um tamanho, e cabem na largura que o artigo lhes dá.
- As páginas dos termos e da segurança estão traduzidas nos outros seis idiomas, e todas as páginas estáticas declaram agora o idioma em que estão realmente escritas.
- A API entrega uma sessão por token em vez de uma por renovação, e a página dos tokens lê-se como uma linha por token.