<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Asllan Maciel</title>
    <description>The latest articles on DEV Community by Asllan Maciel (@asllanmaciel).</description>
    <link>https://dev.to/asllanmaciel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F684817%2Fde7e5b27-bf97-458f-8c20-8dc285107515.png</url>
      <title>DEV Community: Asllan Maciel</title>
      <link>https://dev.to/asllanmaciel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asllanmaciel"/>
    <language>en</language>
    <item>
      <title>Onde agentes de IA ajudam — e onde só adicionam complexidade</title>
      <dc:creator>Asllan Maciel</dc:creator>
      <pubDate>Tue, 01 Sep 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/asllanmaciel/onde-agentes-de-ia-ajudam-e-onde-so-adicionam-complexidade-36al</link>
      <guid>https://dev.to/asllanmaciel/onde-agentes-de-ia-ajudam-e-onde-so-adicionam-complexidade-36al</guid>
      <description>&lt;p&gt;Agentes de IA podem acelerar desenvolvimento, pesquisa, conteúdo e operação. Também podem adicionar custo, variabilidade e uma nova camada de falhas a um processo que funcionava bem com código determinístico.&lt;/p&gt;

&lt;p&gt;Depois de testar agentes, MCPs e workflows em projetos reais, passei a usar uma pergunta simples:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Este trabalho precisa de julgamento ou apenas de execução previsível?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa distinção evita colocar um modelo onde uma função, uma fila ou uma regra seria melhor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde agentes ajudam
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Trabalho com informação não estruturada
&lt;/h3&gt;

&lt;p&gt;Resumir documentos, classificar mensagens, extrair intenção e comparar textos são tarefas nas quais regras rígidas ficam caras rapidamente. O agente consegue lidar com variação e produzir uma primeira interpretação útil.&lt;/p&gt;

&lt;h3&gt;
  
  
  Investigação com várias ferramentas
&lt;/h3&gt;

&lt;p&gt;Quando uma tarefa exige consultar código, documentação, logs e APIs, um agente pode coordenar as etapas e apresentar hipóteses. O ganho vem da combinação das fontes, não apenas da geração de texto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Primeira versão de trabalho intelectual
&lt;/h3&gt;

&lt;p&gt;Rascunhos, planos, testes, documentação e revisão inicial podem ser acelerados. O agente reduz o custo da primeira versão, enquanto critérios de aceitação continuam humanos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interfaces para operações complexas
&lt;/h3&gt;

&lt;p&gt;Um bom agente pode transformar uma intenção em uma sequência segura de ferramentas: localizar dados, validar pré-condições, preparar uma mudança e pedir confirmação antes do efeito externo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde agentes costumam atrapalhar
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Processos totalmente determinísticos
&lt;/h3&gt;

&lt;p&gt;Se entrada, regra e saída são conhecidas, código convencional é mais barato, rápido e testável. Usar IA para aplicar uma fórmula fixa cria incerteza sem benefício.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caminhos críticos sem validação
&lt;/h3&gt;

&lt;p&gt;Pagamento, exclusão, permissões e mudanças irreversíveis não devem depender de uma resposta livre do modelo. A IA pode analisar ou recomendar, mas a execução precisa de políticas e verificações determinísticas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automação sem observabilidade
&lt;/h3&gt;

&lt;p&gt;Um agente que age sem registrar ferramentas usadas, entradas relevantes e resultado é difícil de operar. Quando algo falha, “o modelo decidiu” não é diagnóstico.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contexto ruim disfarçado de prompt ruim
&lt;/h3&gt;

&lt;p&gt;Muitas tentativas de melhorar o prompt não resolvem dados incompletos, ferramentas ambíguas ou critérios de sucesso ausentes. Antes de trocar o modelo, revise o sistema ao redor.&lt;/p&gt;

&lt;h2&gt;
  
  
  O padrão que prefiro
&lt;/h2&gt;

&lt;p&gt;Uso agentes dentro de limites claros:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;objetivo e critérios de aceitação explícitos;&lt;/li&gt;
&lt;li&gt;ferramentas pequenas e bem definidas;&lt;/li&gt;
&lt;li&gt;permissões mínimas;&lt;/li&gt;
&lt;li&gt;validação determinística antes de efeitos externos;&lt;/li&gt;
&lt;li&gt;confirmação humana para ações públicas ou irreversíveis;&lt;/li&gt;
&lt;li&gt;logs que permitam reconstruir o fluxo;&lt;/li&gt;
&lt;li&gt;timeout, orçamento e condição de parada.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Quando há revisão por outro agente, ele recebe o artefato, os riscos e os critérios — não o veredito do primeiro. Isso reduz concordância artificial.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP não substitui desenho de ferramenta
&lt;/h2&gt;

&lt;p&gt;O Model Context Protocol facilita conectar modelos a dados e ações, mas não corrige uma ferramenta mal projetada.&lt;/p&gt;

&lt;p&gt;Uma boa ferramenta MCP deve ter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nome e descrição inequívocos;&lt;/li&gt;
&lt;li&gt;parâmetros pequenos;&lt;/li&gt;
&lt;li&gt;retorno estruturado;&lt;/li&gt;
&lt;li&gt;erros acionáveis;&lt;/li&gt;
&lt;li&gt;escopo de autorização claro;&lt;/li&gt;
&lt;li&gt;idempotência quando aplicável.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expor uma API inteira como dezenas de ações sobrepostas transfere complexidade para o modelo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como decidir
&lt;/h2&gt;

&lt;p&gt;Antes de adicionar um agente, avalio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A tarefa aceita variabilidade?&lt;/li&gt;
&lt;li&gt;Existe uma forma objetiva de validar a saída?&lt;/li&gt;
&lt;li&gt;O ganho compensa latência e custo?&lt;/li&gt;
&lt;li&gt;Uma regra simples resolveria 90%?&lt;/li&gt;
&lt;li&gt;É possível limitar o impacto de uma decisão errada?&lt;/li&gt;
&lt;li&gt;Conseguiremos explicar o que aconteceu?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se várias respostas forem “não”, provavelmente não preciso de um agente.&lt;/p&gt;

&lt;p&gt;IA aplicada não é colocar um chat em todo produto. É escolher cuidadosamente onde julgamento probabilístico cria valor e cercá-lo de engenharia previsível.&lt;/p&gt;

&lt;p&gt;Em qual tarefa um agente trouxe resultado real para você — e em qual só adicionou complexidade?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>automation</category>
    </item>
    <item>
      <title>5 decisões importantes em um SaaS multi-tenant</title>
      <dc:creator>Asllan Maciel</dc:creator>
      <pubDate>Tue, 25 Aug 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/asllanmaciel/5-decisoes-importantes-em-um-saas-multi-tenant-4fj4</link>
      <guid>https://dev.to/asllanmaciel/5-decisoes-importantes-em-um-saas-multi-tenant-4fj4</guid>
      <description>&lt;p&gt;Um SaaS multi-tenant pode começar pequeno sem começar frágil.&lt;/p&gt;

&lt;p&gt;O erro mais comum não é escolher o framework errado. É tratar isolamento, billing, filas e observabilidade como detalhes que serão resolvidos “quando o produto crescer”. Quando esse momento chega, dados e responsabilidades já estão espalhados pela aplicação.&lt;/p&gt;

&lt;p&gt;Ao organizar o &lt;a href="https://github.com/asllanmaciel/laravel-saas-blueprint" rel="noopener noreferrer"&gt;Laravel SaaS Blueprint&lt;/a&gt;, reuni cinco decisões que considero importantes desde o primeiro release.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Resolver o tenant uma vez
&lt;/h2&gt;

&lt;p&gt;Espalhar &lt;code&gt;tenant_id&lt;/code&gt; manualmente por controllers e queries cria uma convenção frágil. Basta uma consulta esquecer o filtro para atravessar a fronteira entre clientes.&lt;/p&gt;

&lt;p&gt;O ideal é resolver o tenant na entrada da requisição e carregar um contexto explícito para o restante do fluxo. Esse contexto pode vir de domínio, subdomínio, token, organização selecionada ou outro mecanismo — mas deve ser validado antes de acessar recursos protegidos.&lt;/p&gt;

&lt;p&gt;Também não basta filtrar o banco. O tenant precisa participar das chaves de cache, caminhos de storage, jobs, logs, exports e métricas.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Escolher isolamento pelo risco
&lt;/h2&gt;

&lt;p&gt;Não existe uma estratégia universal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;banco compartilhado com &lt;code&gt;tenant_id&lt;/code&gt; é simples e econômico;&lt;/li&gt;
&lt;li&gt;schema por tenant aumenta separação e complexidade operacional;&lt;/li&gt;
&lt;li&gt;banco por tenant oferece isolamento forte, mas cobra em deploy, migração e observabilidade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A decisão depende de risco, escala, regulamentação e capacidade da equipe. Para muitos MVPs, banco compartilhado funciona — desde que o isolamento seja centralizado e testado.&lt;/p&gt;

&lt;p&gt;O teste que realmente importa tenta acessar dados de outro tenant e espera falhar.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Tratar billing como estado de negócio
&lt;/h2&gt;

&lt;p&gt;Billing não é apenas “adicionar Stripe”. Uma assinatura percorre estados: avaliação, ativa, vencida, cancelada, em recuperação e possivelmente pausada.&lt;/p&gt;

&lt;p&gt;Webhooks podem chegar repetidos ou fora de ordem. A aplicação precisa manter um estado interno coerente, registrar identificadores de entrega e processar eventos de forma idempotente.&lt;/p&gt;

&lt;p&gt;O provedor de pagamento deve ser um adaptador. As regras do produto — limites, recursos disponíveis e períodos de tolerância — pertencem ao domínio da aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Projetar jobs e webhooks para repetição
&lt;/h2&gt;

&lt;p&gt;Em sistemas distribuídos, “executar exatamente uma vez” raramente é uma garantia prática. A estratégia mais segura é aceitar que a mensagem pode reaparecer e tornar a operação idempotente.&lt;/p&gt;

&lt;p&gt;Algumas técnicas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;chave única por evento externo;&lt;/li&gt;
&lt;li&gt;registro de processamento;&lt;/li&gt;
&lt;li&gt;transação envolvendo efeito e marcação;&lt;/li&gt;
&lt;li&gt;estados explícitos;&lt;/li&gt;
&lt;li&gt;retry com backoff;&lt;/li&gt;
&lt;li&gt;dead-letter queue para falhas persistentes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E todo job precisa carregar o contexto do tenant. Um worker sem contexto pode produzir vazamento mesmo quando a camada HTTP está correta.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Definir observabilidade antes do incidente
&lt;/h2&gt;

&lt;p&gt;Logs sem &lt;code&gt;tenant_id&lt;/code&gt;, &lt;code&gt;request_id&lt;/code&gt;, &lt;code&gt;job_id&lt;/code&gt; ou &lt;code&gt;delivery_id&lt;/code&gt; têm pouco valor durante uma investigação.&lt;/p&gt;

&lt;p&gt;No mínimo, eu quero conseguir responder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;qual tenant foi afetado;&lt;/li&gt;
&lt;li&gt;qual operação falhou;&lt;/li&gt;
&lt;li&gt;qual evento iniciou o fluxo;&lt;/li&gt;
&lt;li&gt;quantas tentativas ocorreram;&lt;/li&gt;
&lt;li&gt;onde o tempo foi gasto;&lt;/li&gt;
&lt;li&gt;se houve impacto em outros tenants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso não exige uma plataforma enorme no MVP. Exige campos consistentes, erros acionáveis e métricas básicas desde o início.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simples não é o mesmo que improvisado
&lt;/h2&gt;

&lt;p&gt;Você não precisa começar com Kubernetes, microserviços ou um banco por cliente. Precisa preservar fronteiras que serão caras de reconstruir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;contexto de tenant;&lt;/li&gt;
&lt;li&gt;isolamento verificável;&lt;/li&gt;
&lt;li&gt;estados de billing;&lt;/li&gt;
&lt;li&gt;idempotência;&lt;/li&gt;
&lt;li&gt;observabilidade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todo o resto pode crescer de forma incremental.&lt;/p&gt;

&lt;p&gt;O blueprint é documentação comunitária e independente de fornecedor. Se você está desenhando ou migrando um SaaS em Laravel, contribuições e contrapontos são bem-vindos.&lt;/p&gt;

&lt;p&gt;Qual dessas decisões mais causou retrabalho em um produto seu?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>saas</category>
      <category>laravel</category>
      <category>architecture</category>
      <category>security</category>
    </item>
    <item>
      <title>O que estou construindo com o GitHub DevLog AI</title>
      <dc:creator>Asllan Maciel</dc:creator>
      <pubDate>Tue, 18 Aug 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/asllanmaciel/o-que-estou-construindo-com-o-github-devlog-ai-38ge</link>
      <guid>https://dev.to/asllanmaciel/o-que-estou-construindo-com-o-github-devlog-ai-38ge</guid>
      <description>&lt;p&gt;Construir um produto em público não significa expor código privado, dados de clientes ou decisões que ainda precisam amadurecer. Significa compartilhar o problema, os limites e os aprendizados que podem ajudar outras pessoas.&lt;/p&gt;

&lt;p&gt;É isso que pretendo fazer com o &lt;a href="https://ghdevlog.com/" rel="noopener noreferrer"&gt;GitHub DevLog AI&lt;/a&gt;: uma central privada para receber, validar e investigar webhooks do GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  O problema não era receber o POST
&lt;/h2&gt;

&lt;p&gt;Criar uma rota que receba um webhook é fácil. A dificuldade aparece quando algo falha e precisamos responder perguntas simples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O GitHub realmente enviou o evento?&lt;/li&gt;
&lt;li&gt;Qual repositório e tipo de evento estavam envolvidos?&lt;/li&gt;
&lt;li&gt;A assinatura &lt;code&gt;X-Hub-Signature-256&lt;/code&gt; foi validada?&lt;/li&gt;
&lt;li&gt;O payload chegou completo?&lt;/li&gt;
&lt;li&gt;A entrega foi duplicada?&lt;/li&gt;
&lt;li&gt;Quem pode consultar esses dados?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em desenvolvimento, normalmente olhamos o terminal, adicionamos logs temporários ou usamos um RequestBin público. Isso ajuda no primeiro teste, mas perde valor quando a integração precisa de histórico, privacidade e contexto compartilhado.&lt;/p&gt;

&lt;p&gt;O produto nasceu dessa diferença entre &lt;strong&gt;receber um webhook&lt;/strong&gt; e &lt;strong&gt;conseguir explicar o que aconteceu com ele&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A proposta do GHDevLog
&lt;/h2&gt;

&lt;p&gt;Cada conta recebe um workspace privado com endpoint e secret próprios. O GitHub envia eventos como &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pull_request&lt;/code&gt;, &lt;code&gt;issues&lt;/code&gt; e &lt;code&gt;workflow_run&lt;/code&gt;; o sistema valida a assinatura, associa a entrega ao workspace correto e apresenta o evento em um painel de investigação.&lt;/p&gt;

&lt;p&gt;O núcleo atual inclui:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cadastro e autenticação;&lt;/li&gt;
&lt;li&gt;workspace isolado por conta;&lt;/li&gt;
&lt;li&gt;endpoint exclusivo;&lt;/li&gt;
&lt;li&gt;secret com possibilidade de rotação;&lt;/li&gt;
&lt;li&gt;validação HMAC SHA-256;&lt;/li&gt;
&lt;li&gt;histórico de eventos;&lt;/li&gt;
&lt;li&gt;visualização do payload e dos headers relevantes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Não é apenas uma caixa de entrada. É uma fronteira de confiança entre uma origem externa e o restante da aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisão 1: privado por padrão
&lt;/h2&gt;

&lt;p&gt;Payloads de webhook podem conter nomes de repositórios, usuários, branches, mensagens de commit e outros dados operacionais. Por isso, um endpoint sem isolamento adequado transforma uma ferramenta de debugging em risco de vazamento.&lt;/p&gt;

&lt;p&gt;O workspace não é apenas uma organização visual. Ele participa das consultas, da autorização e da resolução do endpoint. Um usuário não deve conseguir consultar eventos de outro, mesmo que descubra um identificador interno.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisão 2: preservar o evento antes de interpretá-lo demais
&lt;/h2&gt;

&lt;p&gt;Durante uma investigação, o dado mais valioso é o que realmente chegou. Se o sistema transforma ou descarta informações cedo demais, perdemos a capacidade de explicar uma falha.&lt;/p&gt;

&lt;p&gt;Ao mesmo tempo, guardar tudo indefinidamente também é uma má decisão. O produto precisa equilibrar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fidelidade do evento;&lt;/li&gt;
&lt;li&gt;minimização de dados;&lt;/li&gt;
&lt;li&gt;política de retenção;&lt;/li&gt;
&lt;li&gt;proteção de informações sensíveis;&lt;/li&gt;
&lt;li&gt;custo de armazenamento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Decisão 3: segurança precisa aparecer no produto
&lt;/h2&gt;

&lt;p&gt;Validar a assinatura no backend é obrigatório, mas o usuário também precisa entender o resultado. Mostrar que uma entrega foi validada — ou por que foi rejeitada — transforma segurança invisível em informação operacional.&lt;/p&gt;

&lt;p&gt;O mesmo vale para rotação de secret. Não basta aceitar um segredo; é preciso permitir substituí-lo quando houver suspeita de exposição, sem reconstruir toda a integração.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisão 4: responder rápido e processar depois
&lt;/h2&gt;

&lt;p&gt;O endpoint não deve executar todo o trabalho de forma síncrona. O fluxo mais seguro é validar, registrar um envelope mínimo, enfileirar o processamento e responder ao GitHub rapidamente.&lt;/p&gt;

&lt;p&gt;Isso abre espaço para idempotência, reprocessamento e análise sem manter a entrega original esperando.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que estou aprendendo
&lt;/h2&gt;

&lt;p&gt;Construir o GHDevLog reforçou algumas ideias:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Observabilidade é parte do produto, não um painel adicionado no fim.&lt;/li&gt;
&lt;li&gt;Multi-tenancy precisa alcançar banco, logs, filas, cache e exports.&lt;/li&gt;
&lt;li&gt;Segurança útil é aquela que também ajuda a diagnosticar.&lt;/li&gt;
&lt;li&gt;Um bom produto para desenvolvedores reduz tempo de investigação, não apenas número de cliques.&lt;/li&gt;
&lt;li&gt;A primeira versão deve resolver o fluxo principal antes de acumular integrações.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;O produto ainda está evoluindo. Entre os temas em estudo estão busca, filtros, reprocessamento controlado, métricas por origem e uso de IA para resumir eventos sem substituir os dados brutos.&lt;/p&gt;

&lt;p&gt;Vou compartilhar aqui decisões e erros desse processo sem transformar cada texto em anúncio. O objetivo é documentar o que aprendo ao construir um SaaS real.&lt;/p&gt;

&lt;p&gt;Se você trabalha com webhooks: qual informação costuma faltar justamente quando uma integração falha?&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>github</category>
      <category>saas</category>
      <category>webhooks</category>
    </item>
    <item>
      <title>Como validar webhooks do GitHub com HMAC em PHP e Node.js</title>
      <dc:creator>Asllan Maciel</dc:creator>
      <pubDate>Mon, 10 Aug 2026 16:56:57 +0000</pubDate>
      <link>https://dev.to/asllanmaciel/como-validar-webhooks-do-github-com-hmac-em-php-e-nodejs-a5n</link>
      <guid>https://dev.to/asllanmaciel/como-validar-webhooks-do-github-com-hmac-em-php-e-nodejs-a5n</guid>
      <description>&lt;p&gt;Receber um webhook é simples: você expõe um endpoint, recebe um POST e interpreta o JSON.&lt;/p&gt;

&lt;p&gt;O problema começa quando esse endpoint confia em qualquer payload que chega.&lt;/p&gt;

&lt;p&gt;Se uma aplicação executa ações a partir de webhooks — atualiza dados, inicia deploys, envia notificações ou dispara automações — ela precisa confirmar duas coisas antes de processar o evento:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;o payload foi assinado com o secret compartilhado com o GitHub;&lt;/li&gt;
&lt;li&gt;o conteúdo recebido não foi modificado no caminho.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neste artigo, vamos implementar essa verificação com HMAC SHA-256 em PHP e Node.js.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Os exemplos completos e testados estão no repositório &lt;a href="https://github.com/asllanmaciel/github-webhook-security-guide" rel="noopener noreferrer"&gt;github-webhook-security-guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Como a assinatura funciona
&lt;/h2&gt;

&lt;p&gt;Ao enviar uma entrega, o GitHub calcula um HMAC usando o corpo original da requisição, o secret configurado no webhook e o algoritmo SHA-256.&lt;/p&gt;

&lt;p&gt;O resultado é enviado no header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Hub-Signature-256: sha256=&amp;lt;assinatura hexadecimal&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seu endpoint precisa calcular a assinatura esperada a partir do &lt;strong&gt;corpo bruto&lt;/strong&gt; recebido e compará-la com o valor do header.&lt;/p&gt;

&lt;p&gt;Esse detalhe é importante: não valide a assinatura depois de converter o JSON em objeto e serializá-lo novamente. Qualquer mudança nos bytes — espaços, quebras de linha, Unicode ou ordem de serialização — muda o HMAC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist mínimo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Leia o corpo bruto antes de interpretar o JSON.&lt;/li&gt;
&lt;li&gt;Rejeite secret vazio.&lt;/li&gt;
&lt;li&gt;Valide o formato de &lt;code&gt;X-Hub-Signature-256&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Calcule o HMAC com SHA-256.&lt;/li&gt;
&lt;li&gt;Compare em tempo constante.&lt;/li&gt;
&lt;li&gt;Rejeite assinaturas ausentes ou inválidas.&lt;/li&gt;
&lt;li&gt;Só então interprete e processe o evento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementação em PHP 8+
&lt;/h2&gt;

&lt;p&gt;Em PHP, podemos usar &lt;code&gt;hash_hmac()&lt;/code&gt; para gerar a assinatura e &lt;code&gt;hash_equals()&lt;/code&gt; para realizar a comparação segura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;verifyGitHubWebhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$signatureHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$secret&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;$secret&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;preg_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/^sha256=[a-f0-9]{64}$/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$signatureHeader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sha256='&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;hash_hmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'sha256'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$secret&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;hash_equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$signatureHeader&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O formato é verificado antes do cálculo. Isso elimina headers ausentes ou malformados e garante que a comparação receba valores com a estrutura esperada.&lt;/p&gt;

&lt;p&gt;Um endpoint genérico poderia usar a função assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'php://input'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'HTTP_X_HUB_SIGNATURE_256'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GITHUB_WEBHOOK_SECRET'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;verifyGitHubWebhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$secret&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;http_response_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Invalid signature'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;JSON_THROW_ON_ERROR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O secret vem do ambiente, nunca do repositório.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementação em Node.js 20+
&lt;/h2&gt;

&lt;p&gt;No Node.js, usamos &lt;code&gt;createHmac()&lt;/code&gt; e &lt;code&gt;timingSafeEqual()&lt;/code&gt; do módulo nativo &lt;code&gt;node:crypto&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timingSafeEqual&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyGitHubWebhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signatureHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="sr"&gt;/^sha256=&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-f0-9&lt;/span&gt;&lt;span class="se"&gt;]{64}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signatureHeader&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`sha256=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receivedBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signatureHeader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expectedBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;receivedBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;expectedBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nf"&gt;timingSafeEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receivedBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expectedBuffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A verificação do tamanho antes de &lt;code&gt;timingSafeEqual()&lt;/code&gt; é obrigatória: a função lança uma exceção quando os buffers têm comprimentos diferentes.&lt;/p&gt;

&lt;p&gt;Em frameworks como Express, Fastify ou NestJS, preserve o corpo bruto. Se o middleware de JSON consumir ou transformar o body antes da validação, a assinatura calculada não será a mesma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que não usar uma comparação comum?
&lt;/h2&gt;

&lt;p&gt;Pode parecer suficiente escrever &lt;code&gt;expected === signatureHeader&lt;/code&gt;. Mas comparações comuns podem encerrar o trabalho assim que encontram o primeiro caractere diferente. Em determinados cenários, a variação no tempo de resposta pode revelar informações sobre a assinatura esperada.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hash_equals()&lt;/code&gt; e &lt;code&gt;timingSafeEqual()&lt;/code&gt; foram projetadas para reduzir esse risco por meio de comparação em tempo constante.&lt;/p&gt;

&lt;h2&gt;
  
  
  A assinatura é apenas a primeira camada
&lt;/h2&gt;

&lt;p&gt;Uma assinatura válida prova que o payload foi assinado com o secret compartilhado. Ela não transforma todo evento em uma ação autorizada para o seu negócio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idempotência
&lt;/h3&gt;

&lt;p&gt;Armazene o header &lt;code&gt;X-GitHub-Delivery&lt;/code&gt;. Se a mesma entrega chegar novamente, responda de maneira idempotente em vez de repetir efeitos colaterais.&lt;/p&gt;

&lt;h3&gt;
  
  
  Eventos permitidos
&lt;/h3&gt;

&lt;p&gt;Leia &lt;code&gt;X-GitHub-Event&lt;/code&gt; e aceite somente os eventos necessários. Um endpoint criado para &lt;code&gt;push&lt;/code&gt; não deve processar qualquer tipo de entrega.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limites e filas
&lt;/h3&gt;

&lt;p&gt;Limite o tamanho do body, responda rapidamente e envie trabalho pesado para uma fila. O endpoint do webhook não deve executar todo o processamento de forma síncrona.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logs e retenção
&lt;/h3&gt;

&lt;p&gt;Nunca registre o secret. Evite armazenar payloads completos sem necessidade e defina uma política de retenção para dados que possam conter informações sensíveis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Autorização de negócio
&lt;/h3&gt;

&lt;p&gt;Mesmo depois de validar o GitHub, confirme se aquele repositório, organização, instalação ou evento pode executar a operação solicitada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testando a implementação
&lt;/h2&gt;

&lt;p&gt;O GitHub fornece um vetor público de teste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;secret: It's a Secret to Everybody
payload: Hello, World!
assinatura esperada:
sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use esse valor em testes automatizados e acrescente casos para assinatura correta, assinatura ausente, prefixo inválido, tamanho incorreto, payload modificado e secret vazio.&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://github.com/asllanmaciel/github-webhook-security-guide" rel="noopener noreferrer"&gt;repositório do guia&lt;/a&gt; inclui exemplos independentes de framework e testes executáveis para PHP e Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fluxo recomendado em produção
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Receber o POST via HTTPS.&lt;/li&gt;
&lt;li&gt;Preservar o corpo bruto.&lt;/li&gt;
&lt;li&gt;Validar a assinatura.&lt;/li&gt;
&lt;li&gt;Verificar duplicidade por &lt;code&gt;X-GitHub-Delivery&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Filtrar o tipo em &lt;code&gt;X-GitHub-Event&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Persistir um envelope mínimo.&lt;/li&gt;
&lt;li&gt;Enviar o processamento para uma fila.&lt;/li&gt;
&lt;li&gt;Responder rapidamente ao GitHub.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A validação HMAC é pequena em quantidade de código, mas define a fronteira de confiança de todo o sistema.&lt;/p&gt;

&lt;p&gt;Se seu produto recebe webhooks, não trate o endpoint como uma simples rota de entrada. Trate-o como uma interface pública exposta a dados não confiáveis.&lt;/p&gt;




&lt;p&gt;Como você trata idempotência e reprocessamento de webhooks nos seus projetos?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>github</category>
      <category>security</category>
      <category>php</category>
      <category>node</category>
    </item>
    <item>
      <title>Voltei ao DEV: o que mudou depois de 25 anos programando</title>
      <dc:creator>Asllan Maciel</dc:creator>
      <pubDate>Mon, 10 Aug 2026 16:46:18 +0000</pubDate>
      <link>https://dev.to/asllanmaciel/voltei-ao-dev-o-que-mudou-depois-de-25-anos-programando-1ikl</link>
      <guid>https://dev.to/asllanmaciel/voltei-ao-dev-o-que-mudou-depois-de-25-anos-programando-1ikl</guid>
      <description>&lt;p&gt;Programo desde o início dos anos 2000. Nesse tempo, linguagens mudaram, frameworks nasceram e desapareceram, a web amadureceu e a inteligência artificial deixou os laboratórios para entrar no trabalho diário.&lt;/p&gt;

&lt;p&gt;Eu também mudei.&lt;/p&gt;

&lt;p&gt;Quando publiquei meu primeiro texto aqui no DEV, em 2024, meu perfil ainda mostrava apenas uma parte da minha trajetória. Depois disso, continuei construindo sistemas, empresas, produtos digitais, plataformas SaaS e automações. Mas compartilhei muito pouco desse processo.&lt;/p&gt;

&lt;p&gt;Estou voltando para mudar isso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Construir continua sendo meu jeito de aprender
&lt;/h2&gt;

&lt;p&gt;Ao longo de mais de 25 anos, aprendi que tecnologia só ganha valor quando resolve um problema concreto.&lt;/p&gt;

&lt;p&gt;Uma API não é interessante apenas por estar bem estruturada. Ela é interessante quando permite que outro produto exista.&lt;/p&gt;

&lt;p&gt;Uma automação não importa apenas porque economiza alguns cliques. Ela importa quando devolve tempo, reduz erros e torna uma operação mais previsível.&lt;/p&gt;

&lt;p&gt;Um SaaS não se sustenta apenas com uma boa stack. Ele precisa resolver uma dor real, funcionar em produção e encontrar pessoas dispostas a usá-lo.&lt;/p&gt;

&lt;p&gt;Essa ligação entre engenharia, produto e negócio é o que mais me interessa hoje.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que estou construindo
&lt;/h2&gt;

&lt;p&gt;Atualmente, trabalho em produtos e experimentos que combinam desenvolvimento, inteligência artificial, automação e negócios digitais.&lt;/p&gt;

&lt;p&gt;Entre eles estão:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GHDevLog&lt;/strong&gt; — uma central privada para receber, validar e investigar webhooks do GitHub em tempo real, com foco em segurança e rastreabilidade;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BibliaAPI&lt;/strong&gt; — uma infraestrutura bíblica para aplicações, com API REST, WordPress, aplicativo mobile e recursos SaaS;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ClariDados&lt;/strong&gt; — analytics simples para acompanhar visitas, origens, páginas e conversões sem a complexidade das plataformas tradicionais;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cresça na Fé&lt;/strong&gt; — uma plataforma de conteúdo, estudos e recursos voltados ao crescimento espiritual;&lt;/li&gt;
&lt;li&gt;ferramentas para desenvolvedores, plugins WordPress, APIs e novos SaaS ainda em validação.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Também venho estudando e aplicando agentes de IA, MCPs, workflows e automações em situações reais — não apenas como demonstrações, mas como partes de produtos e operações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que voltar a escrever
&lt;/h2&gt;

&lt;p&gt;Durante muito tempo, grande parte do meu trabalho permaneceu nos bastidores. Muitos sistemas pertencem a clientes ou fazem parte de produtos privados. Isso, porém, não impede que as decisões, os padrões e os aprendizados sejam compartilhados.&lt;/p&gt;

&lt;p&gt;Quero usar este espaço para documentar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;decisões de arquitetura e seus trade-offs;&lt;/li&gt;
&lt;li&gt;construção e validação de produtos SaaS;&lt;/li&gt;
&lt;li&gt;APIs, webhooks e integrações seguras;&lt;/li&gt;
&lt;li&gt;PHP, Laravel, WordPress e JavaScript em produção;&lt;/li&gt;
&lt;li&gt;agentes de IA, MCPs e automações aplicadas;&lt;/li&gt;
&lt;li&gt;Docker, CI/CD, observabilidade e operação;&lt;/li&gt;
&lt;li&gt;erros, mudanças de direção e aprendizados de produto;&lt;/li&gt;
&lt;li&gt;a relação entre código, monetização e crescimento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A intenção não é publicar teoria distante da prática. Quero escrever sobre problemas que encontrei, soluções que testei e coisas que ainda estou tentando entender.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que 25 anos de programação me ensinaram
&lt;/h2&gt;

&lt;p&gt;Alguns princípios sobreviveram a todas as mudanças de stack:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O problema vem antes da ferramenta.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Escolher tecnologia sem compreender a necessidade costuma produzir soluções sofisticadas para o problema errado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Colocar no ar ensina mais do que planejar indefinidamente.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Construir, observar, aprender e melhorar continua sendo um ciclo poderoso.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Código é apenas uma parte do produto.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Segurança, documentação, experiência, operação, aquisição e sustentabilidade também fazem parte da engenharia de algo útil.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicidade exige experiência.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
É fácil adicionar camadas. Difícil é remover o que não precisa existir.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compartilhar organiza o pensamento.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Explicar uma decisão obriga a separar convicção, hábito e evidência.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  O que vem a seguir
&lt;/h2&gt;

&lt;p&gt;Nos próximos textos, pretendo abrir os bastidores dos projetos que estou construindo e transformar experiências práticas em conteúdo que outras pessoas possam testar e adaptar.&lt;/p&gt;

&lt;p&gt;Alguns temas que já estão na fila:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;como validar assinaturas de webhooks do GitHub com HMAC;&lt;/li&gt;
&lt;li&gt;decisões de arquitetura para SaaS multi-tenant;&lt;/li&gt;
&lt;li&gt;o que aprendi construindo uma API que serve diferentes produtos;&lt;/li&gt;
&lt;li&gt;onde agentes de IA realmente ajudam — e onde apenas adicionam complexidade;&lt;/li&gt;
&lt;li&gt;automações e ferramentas para o ecossistema WordPress;&lt;/li&gt;
&lt;li&gt;como conectar engenharia, produto e crescimento sem perder o foco técnico.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se você trabalha com algum desses temas, está construindo um produto ou enfrentando um problema parecido, vamos conversar.&lt;/p&gt;

&lt;p&gt;Estou de volta ao DEV para compartilhar enquanto construo — não depois que tudo parecer perfeito.&lt;/p&gt;

&lt;p&gt;Porque, depois de 25 anos, uma coisa continua igual: &lt;strong&gt;construir ainda é meu jeito de aprender.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Você também voltou a escrever depois de algum tempo? O que fez você recomeçar?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>career</category>
      <category>buildinpublic</category>
      <category>discuss</category>
    </item>
    <item>
      <title>O que é PHP e por que aprender?</title>
      <dc:creator>Asllan Maciel</dc:creator>
      <pubDate>Wed, 14 Aug 2024 01:28:02 +0000</pubDate>
      <link>https://dev.to/asllanmaciel/o-que-e-php-e-por-que-aprender-3po9</link>
      <guid>https://dev.to/asllanmaciel/o-que-e-php-e-por-que-aprender-3po9</guid>
      <description>&lt;p&gt;Se você está começando no mundo do desenvolvimento web, é provável que já tenha ouvido falar de PHP. Mas o que exatamente é PHP e por que ele é tão amplamente utilizado? Neste post, vamos explorar o que torna o PHP uma escolha popular entre desenvolvedores, suas principais aplicações e por que você deve considerar aprender essa linguagem.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é PHP?
&lt;/h2&gt;

&lt;p&gt;PHP, que originalmente significava "Personal Home Page" e agora é conhecido como "Hypertext Preprocessor", é uma linguagem de programação de código aberto utilizada principalmente para o desenvolvimento de aplicações web. Ele foi criado por Rasmus Lerdorf em 1994 e, desde então, se tornou uma das linguagens mais populares para o desenvolvimento de sites dinâmicos.&lt;/p&gt;

&lt;p&gt;PHP é uma linguagem server-side, o que significa que seu código é executado no servidor antes de ser enviado ao navegador do usuário. Isso permite que os desenvolvedores criem páginas web dinâmicas, onde o conteúdo pode mudar com base em interações do usuário ou outros fatores, como consultas a bancos de dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que o PHP é tão popular?
&lt;/h2&gt;

&lt;p&gt;PHP conquistou seu espaço no mundo do desenvolvimento web por várias razões:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Facilidade de Aprendizado:&lt;/strong&gt; Comparado a outras linguagens de programação, PHP é relativamente fácil de aprender, especialmente para quem já tem experiência com HTML. Sua sintaxe é clara e intuitiva, permitindo que novos desenvolvedores comecem a construir projetos rapidamente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comunidade e Suporte:&lt;/strong&gt; PHP tem uma comunidade enorme e ativa, o que significa que há uma abundância de recursos, tutoriais, e fóruns onde você pode encontrar ajuda. Além disso, muitas bibliotecas e frameworks, como Laravel e Symfony, foram desenvolvidos para facilitar ainda mais o trabalho com PHP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integração com Bancos de Dados:&lt;/strong&gt; PHP se integra facilmente com uma variedade de bancos de dados, como MySQL, PostgreSQL, Oracle, e muitos outros. Isso torna simples a criação de sites e aplicações que dependem de grandes volumes de dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custo-Benefício:&lt;/strong&gt; Sendo uma linguagem de código aberto, PHP não requer nenhum custo de licença. Isso, aliado à grande quantidade de ferramentas e hospedagens compatíveis, faz do PHP uma opção econômica para desenvolvimento de websites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexibilidade:&lt;/strong&gt; PHP é uma linguagem extremamente flexível. Ele pode ser usado tanto para criar pequenos scripts quanto para desenvolver grandes aplicações corporativas. Além disso, PHP se integra facilmente com outras tecnologias, como JavaScript, tornando-o ideal para desenvolver aplicações web completas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principais Aplicações do PHP
&lt;/h2&gt;

&lt;p&gt;PHP é uma linguagem versátil e pode ser usada para uma ampla gama de projetos. Aqui estão algumas das principais aplicações do PHP:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desenvolvimento de Sites Dinâmicos:&lt;/strong&gt; A aplicação mais comum do PHP é no desenvolvimento de sites dinâmicos. Usando PHP, você pode criar páginas que exibem conteúdo diferente dependendo da interação do usuário, como blogs, portais de notícias, e-commerce, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sistemas de Gerenciamento de Conteúdo (CMS):&lt;/strong&gt; Muitos dos CMS mais populares, como WordPress, Joomla e Drupal, são construídos com PHP. Esses sistemas permitem que os usuários gerenciem o conteúdo de seus sites sem necessidade de conhecimento técnico avançado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aplicações Web Complexas:&lt;/strong&gt; PHP também é amplamente utilizado para criar aplicações web mais complexas, como plataformas de e-learning, redes sociais, e sistemas de gerenciamento de projetos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;APIs e Microserviços:&lt;/strong&gt; PHP pode ser usado para construir APIs RESTful, que são utilizadas para conectar diferentes partes de uma aplicação ou para integrar diferentes sistemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que aprender PHP?
&lt;/h2&gt;

&lt;p&gt;Agora que você sabe o que é PHP e onde ele é usado, vamos falar sobre por que você deve aprender essa linguagem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alta Demanda no Mercado:&lt;/strong&gt; PHP é uma das linguagens mais utilizadas no desenvolvimento web, e há uma alta demanda por desenvolvedores que dominem essa tecnologia. Empresas de todos os portes, desde startups até grandes corporações, buscam profissionais que possam desenvolver e manter suas aplicações PHP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grande Ecossistema de Ferramentas:&lt;/strong&gt; Ao aprender PHP, você terá acesso a um grande ecossistema de ferramentas, frameworks e bibliotecas que podem acelerar o desenvolvimento e ajudar você a criar soluções mais sofisticadas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Oportunidades de Trabalho como Freelancer:&lt;/strong&gt; Se você deseja trabalhar como freelancer, PHP oferece uma ampla gama de oportunidades. Muitos pequenos negócios e empreendedores procuram desenvolvedores PHP para criar e manter seus sites, o que pode ser uma excelente fonte de renda extra.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Facilidade de Hospedagem:&lt;/strong&gt; A maioria das hospedagens web oferece suporte nativo ao PHP, o que significa que você pode facilmente colocar seus projetos no ar sem complicações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aprendizado Contínuo:&lt;/strong&gt; PHP tem evoluído continuamente, com novas versões introduzindo melhorias significativas. Aprender PHP significa também estar sempre atualizado com as últimas tendências e práticas do desenvolvimento web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;PHP é uma linguagem poderosa, flexível e amplamente utilizada que pode abrir muitas portas no mundo do desenvolvimento web. Se você está começando agora ou se já tem experiência com outras linguagens, aprender PHP pode ser um passo estratégico para avançar na sua carreira.&lt;/p&gt;

&lt;p&gt;Então, o que está esperando? Pegue seu editor de código, instale o PHP e comece a explorar o vasto universo de possibilidades que essa linguagem oferece. Nos próximos posts, vamos mergulhar mais fundo em como configurar seu ambiente PHP e começar a escrever seus primeiros scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursos Adicionais
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.php.net/docs.php" rel="noopener noreferrer"&gt;Documentação Oficial do PHP&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.reddit.com/r/php/" rel="noopener noreferrer"&gt;Comunidade PHP no Reddit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você quer acelerar seu aprendizado em PHP ou precisa de um especialista para impulsionar o seu projeto, estou aqui para ajudar. Vamos transformar suas ideias em realidade com soluções robustas e eficientes. Entre em contato comigo através do &lt;a href="https://asllanmaciel.com.br/" rel="noopener noreferrer"&gt;asllanmaciel.com.br&lt;/a&gt;, explore mais conteúdos sobre WordPress no &lt;a href="https://wp24horas.com.br/" rel="noopener noreferrer"&gt;WP24Horas&lt;/a&gt; ou conheça os serviços da minha agência em &lt;a href="https://m3marketingdigital.com.br/" rel="noopener noreferrer"&gt;M3 Marketing Digital&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Vamos juntos criar algo extraordinário?&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
