<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>TabNews</title>
        <link>https://www.tabnews.com.br/recentes/rss</link>
        <description>Conteúdos para quem trabalha com Programação e Tecnologia</description>
        <lastBuildDate>Fri, 21 Aug 2026 07:49:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>pt</language>
        <image>
            <title>TabNews</title>
            <url>https://www.tabnews.com.br/favicon-mobile.png</url>
            <link>https://www.tabnews.com.br/recentes/rss</link>
        </image>
        <item>
            <title><![CDATA[Desvendei o código do Elifoot 98 após 25 anos: Engenharia reversa em 16-bit com Ghidra no Linux]]></title>
            <link>https://www.tabnews.com.br/trsthales/desvendei-o-codigo-do-elifoot-98-apos-25-anos-engenharia-reversa-em-16-bit-com-ghidra-no-linux</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/trsthales/desvendei-o-codigo-do-elifoot-98-apos-25-anos-engenharia-reversa-em-16-bit-com-ghidra-no-linux</guid>
            <pubDate>Fri, 21 Aug 2026 07:49:07 GMT</pubDate>
            <description><![CDATA[Quem cresceu nos anos 90 e 2000 certamente se lembra de passar horas na frente do PC jogando Elifoot 98. Por mais de duas décadas, circularam em fóruns de internet dezenas de mitos e teor...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Quem cresceu nos anos 90 e 2000 certamente se lembra de passar horas na frente do PC jogando <strong>Elifoot 98</strong>. Por mais de duas décadas, circularam em fóruns de internet dezenas de mitos e teorias sobre o funcionamento do jogo: <em>Será que zagueiro agressivo desarma melhor? Por que jogar sem meio-campo parecia tão roubado? Existe bônus por nacionalidade?</em></p><p>Resolvi investigar a fundo e decidi fazer engenharia reversa do executável original (<code>ELIFOOT.EXE</code>) no <strong>Debian 12</strong>, usando o <strong>Ghidra</strong> e o <strong>Cheat Engine</strong> sobre a camada <code>winevdm</code>.</p><p>Descobri que o binário original foi compilado em <strong>Borland Delphi 1.0 (16-bit)</strong> e consegui descompilar as funções responsáveis pela simulação de partidas, cálculo de força dos setores e evolução dos jogadores.</p><h3 id="trsthales-content--principais-descobertas">🔍 Principais Descobertas:</h3><ol><li><strong>O Mito da Nacionalidade era Real (+3 de Bônus):</strong> O código pré-jogo compara a sigla de país do clube com a do jogador (<code>CompareStr</code>) e adiciona <span class="math math-inline">+3</span> pontos fixos no setor para cada titular local (<code>FUN_17fb_397d</code>). Escalar 11 jogadores locais dá <span class="math math-inline">+33</span> pontos brutos de vantagem.</li><li><strong>A Assimetria do Mando de Campo:</strong> O mandante roda <code>Random(6000) &#x3C; Força</code>, enquanto o visitante roda <code>Random(7000) &#x3C; Força</code>. O time da casa tem cerca de <span class="math math-inline">+16,7\%</span> de vantagem matemática pura na criação de lances.</li><li><strong>Por que o 5-0-5 quebra o jogo:</strong> Médios diluem a força (<span class="math math-inline">50\%</span> ataque / <span class="math math-inline">50\%</span> defesa). Como não há punição por falta de meio-campo no código, jogar com 5 Defesas e 5 Atacantes maximiza o poder ofensivo e defensivo simultaneamente.</li><li><strong>Comportamento não ajuda no desarme:</strong> No duelo de dividida (<code>FUN_17fb_81ed</code>), a vitória depende <span class="math math-inline">100\%</span> da força nominal. A agressividade serve unicamente como peso em uma roleta de faltas e cartões (<code>FUN_17fb_100b</code>).</li><li><strong>Goleiros demoram o dobro para evoluir:</strong> Na rotina de evolução (<code>FUN_17fb_4a41</code>), goleiros precisam passar por um teste extra de <span class="math math-inline">50\%</span> (<code>Random(2) == 0</code>) para ganhar força.</li></ol><p>Documentei todas as structs de memória, as fórmulas descompiladas em C e os prints da análise no repositório do projeto:</p><p>🔗 <strong>Repositório no GitHub:</strong> <a href="https://github.com/trsthales/desvendando-elifoot-98">https://github.com/trsthales/desvendando-elifoot-98</a></p><p>Feedbacks, dúvidas e contribuições são muito bem-vindos!</p></div>]]></content:encoded>
            <author>trsthales</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Construí um cliente de Discord nativo em Rust que usa apenas ~30MB de RAM (e 0.1% de CPU)]]></title>
            <link>https://www.tabnews.com.br/Ak4ai/construi-um-cliente-de-discord-nativo-em-rust-que-usa-apenas-30mb-de-ram-e-0-1-por-cento-de-cpu</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Ak4ai/construi-um-cliente-de-discord-nativo-em-rust-que-usa-apenas-30mb-de-ram-e-0-1-por-cento-de-cpu</guid>
            <pubDate>Fri, 21 Aug 2026 02:33:35 GMT</pubDate>
            <description><![CDATA[Fala pessoal do TabNews! 👋 Se você joga no PC ou trabalha com várias abas e ferramentas pesadas abertas ao mesmo tempo, provavelmente já passou por isso: abrir o Discord oficial só para c...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Fala pessoal do TabNews! 👋</p><p>Se você joga no PC ou trabalha com várias abas e ferramentas pesadas abertas ao mesmo tempo, provavelmente já passou por isso: abrir o Discord oficial só para conversar com amigos em call e ver o Gerenciador de Tarefas acusar <strong>500MB a 800MB+ de memória RAM</strong> e picos de uso de CPU que provocam aqueles <em>micro-stutters</em> (micro-engasgos) chatos no meio de uma partida.</p><p>O motivo é conhecido: o Discord oficial roda sobre o <strong>Electron (Chromium + Node.js)</strong>, o que significa carregar um navegador web completo em segundo plano.</p><p>Incomodado com isso, decidi encarar um desafio: <strong>é possível recriar a essência do Discord — chat de texto e canais de voz com áudio de alta fidelidade — em um binário nativo ultra-leve em Rust?</strong></p><p>O resultado é o <strong>Litecord</strong>, um projeto 100% open source que consome <strong>menos de 35MB de RAM</strong> e <strong>&#x3C; 0.1% de CPU em idle</strong>. Compartilho abaixo as decisões de arquitetura e os desafios técnicos que enfrentei.</p><hr><h2 id="ak4ai-content-️-a-escolha-da-stack-por-que-não-usar-webviewtauri">🛠️ A Escolha da Stack: Por que não usar WebView/Tauri?</h2><p>A primeira tentação seria usar Tauri (que substitui o Chromium pelo WebView do sistema). Porém, para atingir o objetivo de <strong>performance máxima e consumo irrisório de memória</strong>, decidi ir direto ao metal:</p><ul><li><strong>Linguagem:</strong> <strong>Rust (2021 Edition)</strong> — controle total de memória, zero runtime overhead e segurança para processamento de áudio concorrente em tempo real.</li><li><strong>Interface Gráfica:</strong> <strong><a href="https://slint.dev/" rel="nofollow">Slint UI</a></strong> — um framework moderno de GUI declarativa compilada nativamente. O Slint não renderiza HTML/CSS; ele compila o layout direto para instruções gráficas nativas (via <em>FemtoVG/OpenGL</em> ou renderizador de software), gerando uma interface fluida a 60 FPS com menos de 10MB de pegada de memória.</li><li><strong>Pipeline de Áudio:</strong> <strong>CPAL</strong> (Cross-Platform Audio Library) + decodificador nativo <strong>Opus (48kHz)</strong>.</li><li><strong>Async Runtime:</strong> <strong>Tokio</strong> para orquestrar WebSockets, chamadas REST da API do Discord e o loop de eventos de interface sem travar a thread principal.</li></ul><hr><h2 id="ak4ai-content--desafios-técnicos-interessantes">🔬 Desafios Técnicos Interessantes</h2><h3 id="ak4ai-content-1-voz-em-tempo-real-e-criptografia-dave-e2ee">1. Voz em Tempo Real e Criptografia DAVE (E2EE)</h3><p>O Discord recentemente começou a implementar o protocolo <strong>DAVE (MLS - RFC 9420)</strong> para criptografia de ponta a ponta nas chamadas de voz.</p><ul><li>Para garantir que a voz não pipocasse ou ficasse "robótica" quando a GPU/CPU do computador estivesse em 100% de carga (durante um jogo pesado), implementamos <strong>Opus PLC (<em>Packet Loss Concealment</em>)</strong> com um jitter buffer adaptativo de 40ms e resampler cúbico Hermite a 48kHz.</li></ul><h3 id="ak4ai-content-2-login-seguro-por-qr-code-discord-remote-auth-v2">2. Login Seguro por QR Code (Discord Remote Auth v2)</h3><p>Em vez de pedir para o usuário colar tokens manualmente ou inspecionar cabeçalhos de rede:</p><ul><li>O Litecord implementa o protocolo <strong>Remote Auth v2</strong> do Discord via WebSocket com pares de chaves RSA-2048 transitórias.</li><li>O app gera um QR Code na tela; você escaneia pelo aplicativo do Discord no celular e autoriza o login com 1 toque.</li><li>No Windows, o token da sessão é persistido no disco criptografado através da API nativa <strong>Windows DPAPI (<code>CryptProtectData</code>)</strong>, garantindo que nenhum outro processo ou usuário não autorizado no PC consiga ler o segredo.</li></ul><h3 id="ak4ai-content-3-ducking-de-fala-dinâmico-foco-no-igl--líder-do-squad">3. Ducking de Fala Dinâmico (Foco no IGL / Líder do Squad)</h3><p>Em chamadas com muitas pessoas falando ao mesmo tempo ou bots de música tocando no canal, a comunicação tática fica caótica. Criamos um sistema de <strong>Prioridade de Fala (<code>P:1</code>, <code>P:2</code>, etc.)</strong>:</p><ul><li>Quando o líder/shot-caller fala, o volume de todos os outros participantes e bots é atenuado suavemente em tempo real (<em>ducking</em> inteligente), voltando ao normal assim que ele termina a frase.</li></ul><h3 id="ak4ai-content-4-deepsleep-na-bandeja-do-sistema">4. DeepSleep na Bandeja do Sistema</h3><p>Ao minimizar o Litecord para a bandeja do sistema (<em>System Tray</em>):</p><ul><li>Todos os loops de renderização visual e atualizações de UI do Slint são completamente suspensos (<code>0.0% de CPU</code>).</li><li>Apenas a thread assíncrona leve de recepção de áudio RTP/Opus continua ativa, consumindo recursos praticamente imperceptíveis enquanto você joga.</li></ul><hr><h2 id="ak4ai-content--comparativo-discord-oficial-vs-litecord">📊 Comparativo: Discord Oficial vs Litecord</h2><table><thead><tr><th align="left">Métrica</th><th align="left">Discord Oficial (Electron)</th><th align="left"><strong>Litecord (Nativo em Rust)</strong></th></tr></thead><tbody><tr><td align="left"><strong>Uso de CPU (Idle)</strong></td><td align="left">1.5% - 4.5%</td><td align="left"><strong>&#x3C; 0.1% (DeepSleep: 0.0%)</strong></td></tr><tr><td align="left"><strong>Uso de CPU (Voz Ativa)</strong></td><td align="left">4.0% - 8.0%</td><td align="left"><strong>~0.4% - 0.8%</strong></td></tr><tr><td align="left"><strong>Uso de Memória RAM (Idle)</strong></td><td align="left">~400 MB - 750 MB</td><td align="left"><strong>~28 MB - 35 MB</strong></td></tr><tr><td align="left"><strong>Uso de Memória RAM (Voz)</strong></td><td align="left">~600 MB - 900 MB</td><td align="left"><strong>~32 MB - 45 MB</strong></td></tr><tr><td align="left"><strong>Tamanho do Executável</strong></td><td align="left">~180 MB</td><td align="left"><strong>~8 MB (Standalone)</strong></td></tr><tr><td align="left"><strong>Tempo de Inicialização</strong></td><td align="left">4 a 9 segundos</td><td align="left"><strong>&#x3C; 200 milissegundos</strong></td></tr></tbody></table><hr><h2 id="ak4ai-content--código-aberto--como-testar">📦 Código Aberto &#x26; Como Testar</h2><p>O projeto é <strong>100% open source</strong> sob licença <strong>MIT</strong> e já conta com executáveis prontos gerados pelo GitHub Actions:</p><ul><li><p>🪟 <strong>Windows:</strong> Instalador <code>.exe</code> e versão Portátil <code>.zip</code></p></li><li><p>🐧 <strong>Linux:</strong> Pacote nativo <code>.tar.gz</code> (testado e compatível com Ubuntu/Arch)</p></li><li><p>🔗 <strong>Repositório no GitHub:</strong> <a href="https://github.com/Ak4ai/Litecord">https://github.com/Ak4ai/Litecord</a></p></li><li><p>🌐 <strong>Página do Projeto:</strong> <a href="https://ak4ai.github.io/Litecord/" rel="nofollow">https://ak4ai.github.io/Litecord/</a></p></li></ul><hr><h3 id="ak4ai-content--gostaria-do-feedback-de-vocês">💬 Gostaria do Feedback de Vocês!</h3><p>Quais outras otimizações ou recursos essenciais vocês acham que fariam sentido manter em um cliente focado puramente em leveza e baixo consumo? Fiquem à vontade para testar, abrir issues ou mandar PRs! 🦀🚀</p></div>]]></content:encoded>
            <author>Ak4ai</author>
        </item>
        <item>
            <title><![CDATA[Pitch: O que muda no custo de um projeto ao trocar de modelo de IA]]></title>
            <link>https://www.tabnews.com.br/CapivaraDoPix/pitch-o-que-muda-no-custo-de-um-projeto-ao-trocar-de-modelo-de-ia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/CapivaraDoPix/pitch-o-que-muda-no-custo-de-um-projeto-ao-trocar-de-modelo-de-ia</guid>
            <pubDate>Fri, 21 Aug 2026 02:31:13 GMT</pubDate>
            <description><![CDATA[Entrei no TabNews há pouco tempo, então esta é uma das minhas primeiras contribuições por aqui. Ainda estou conhecendo a comunidade e quero começar compartilhando algo que pode ser útil p...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Entrei no TabNews há pouco tempo, então esta é uma das minhas primeiras contribuições por aqui. Ainda estou conhecendo a comunidade e quero começar compartilhando algo que pode ser útil para quem coloca IA em produção.</p><p>Eu trabalho na equipe de San Jose por trás da Flatkey, uma camada de roteamento com API compatível com OpenAI. Estou deixando isso claro porque o texto também apresenta nosso produto.</p><p>Sobre este post: vou usar o DeepSeek como exemplo para mostrar como uma equipe pode avaliar e reduzir o custo do seu software. Também quero apresentar nossa plataforma. Em praticamente todo o catálogo, a Flatkey garante pelo menos 20% de desconto em relação ao preço oficial do modelo equivalente, considerando o mesmo tipo de uso. Como acabei de chegar ao TabNews, quero deixar uma pequena cortesia para a comunidade: os 50 primeiros usuários que se cadastrarem recebem US$ 5 em crédito gratuito, por ordem de chegada. <a href="https://console.flatkey.ai/redeem?from=TabNewsWelcome" rel="nofollow">Resgatar o crédito de boas-vindas</a>.</p><p>Nas últimas semanas, os fabricantes chineses anunciaram vários modelos importantes. Em 13 de agosto, o DeepSeek V4 Pro foi lançado oficialmente em versão GA no app, na web e na API. A Z.ai lançou o GLM-5.3 em 14 de agosto; e a MiniMax lançou, também em agosto, o H3, um modelo de geração de vídeo que compete com o Seedance 2.5. Em algumas tarefas, esses modelos entregam resultados comparáveis aos nomes mais conhecidos, como GPT e Claude, por um preço menor. Todos estão disponíveis no <a href="https://flatkey.ai/models?utm_source=tabnews&#x26;utm_medium=pitch1" rel="nofollow">catálogo de modelos da Flatkey</a>.</p><p>Para desenvolvedores independentes, geeks e equipes pequenas, a Flatkey pode ser uma opção prática: uma chave e um saldo para mais de 100 modelos oficiais e mais de 1.000 ferramentas cobradas por uso, com menos contas e integrações para manter.</p><h2 id="capivaradopix-content-o-preço-do-token-conta-mas-não-conta-sozinho">O preço do token conta, mas não conta sozinho</h2><p>Uma tabela de preços normalmente mostra entrada e saída. O orçamento real também absorve chamadas que falham, respostas que precisam ser refeitas, prompts maiores do que o necessário e horas gastas mantendo integrações diferentes.</p><p>Por isso, gosto mais de medir o custo por tarefa aprovada: tokens consumidos, repetições, fallbacks e custo operacional divididos pelo número de tarefas que realmente entraram no produto.</p><p>Um modelo barato pode sair caro se a resposta exigir três tentativas. Um modelo mais forte pode compensar o preço quando resolve a tarefa de primeira. A única forma de saber é medir no seu fluxo.</p><h2 id="capivaradopix-content-o-que-a-deepseek-publicou-sobre-o-v4">O que a DeepSeek publicou sobre o V4</h2><p>Eu conferi o changelog e a página de preços oficiais antes de escrever isto:</p><ul><li>Em 24 de abril, V4 Pro e V4 Flash apareceram na API como preview.</li><li>Em 31 de julho, a DeepSeek publicou o <code>DeepSeek-V4-Flash-0731</code>. A própria documentação ainda o chama de public beta.</li><li>Em 13 de agosto, o <code>DeepSeek-V4-Pro-0813</code> chegou a GA no app, na web e na API.</li></ul><p>Os IDs públicos são <code>deepseek-v4-pro</code> e <code>deepseek-v4-flash</code>. A documentação informa contexto de até 1 milhão de tokens, saída máxima de 384 mil tokens, tool calls, JSON output, Responses API e compatibilidade com a API da Anthropic. São especificações do fornecedor. A qualidade no seu caso precisa ser testada por você.</p><h2 id="capivaradopix-content-como-eu-dividiria-as-tarefas">Como eu dividiria as tarefas</h2><p>Não mandaria tudo para o mesmo modelo. Uma aplicação costuma ficar mais barata quando usa um modelo econômico para tarefas repetitivas, reserva o Pro para código e raciocínio mais difíceis e mantém um fallback para os casos em que a primeira chamada falha.</p><p>Também separaria as chaves por projeto ou ambiente. Assim fica possível responder uma pergunta que quase sempre aparece tarde demais: qual funcionalidade está consumindo o orçamento?</p><h2 id="capivaradopix-content-o-teste-leva-poucas-mudanças">O teste leva poucas mudanças</h2><p>Quem já usa o SDK da OpenAI não precisa reescrever a integração. Basta trocar o endpoint, a chave e o ID do modelo; a equipe pode então comparar o V4 Pro com o modelo que já usa no próprio fluxo de produção. A Flatkey verifica os endpoints oficiais a cada hora e tem failover entre canais, duas coisas que eu colocaria no mesmo teste de custo.</p><p>Outro detalhe de cobrança: chamadas que falham do lado da Flatkey não consomem saldo. Isso não elimina retries causados pelo seu próprio código ou pelo provedor, mas evita pagar por um erro na camada de roteamento.</p><h2 id="capivaradopix-content-quero-ouvir-quem-já-colocou-ia-em-produção">Quero ouvir quem já colocou IA em produção</h2><p>Qual tarefa vocês testariam primeiro no V4 Pro: código, agentes, suporte ou extração de dados?</p><p>Vocês acompanham apenas tokens ou sabem quanto custa cada tarefa concluída?</p><p>E o que uma camada entre a aplicação e o provedor precisa mostrar para vocês confiarem nela em produção?</p><p>Quem quiser testar pode usar a <a href="https://flatkey.ai/pt/deepseek-api?utm_source=tabnews&#x26;utm_medium=pitch1" rel="nofollow">página da API DeepSeek da Flatkey</a>. A Flatkey também oferece um programa de convites para que outras pessoas possam receber créditos. Se encontrar uma diferença entre a documentação, o preço exibido e o comportamento da API, prefiro que aponte nos comentários.</p><p>Fontes oficiais: <a href="https://api-docs.deepseek.com/updates/" rel="nofollow">changelog da DeepSeek</a>, <a href="https://api-docs.deepseek.com/news/news260424" rel="nofollow">preview do V4</a> e <a href="https://api-docs.deepseek.com/quick_start/pricing/" rel="nofollow">modelos e preços</a>.</p></div>]]></content:encoded>
            <author>CapivaraDoPix</author>
        </item>
        <item>
            <title><![CDATA[TeamSpeak 6 self-hosted numa VPS Oracle Cloud grátis: guia completo (e os dois firewalls que travam quase todo iniciante)]]></title>
            <link>https://www.tabnews.com.br/hiradox/teamspeak-6-self-hosted-numa-vps-oracle-cloud-gratis-guia-completo-e-os-dois-firewalls-que-travam-quase-todo-iniciante</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/hiradox/teamspeak-6-self-hosted-numa-vps-oracle-cloud-gratis-guia-completo-e-os-dois-firewalls-que-travam-quase-todo-iniciante</guid>
            <pubDate>Fri, 21 Aug 2026 02:08:57 GMT</pubDate>
            <description><![CDATA[Semana passada tentei assistir uma série com minha namorada usando a live do Discord. Não deu: se você não vive debaixo de uma porta, provavelmente sabe que desde 12 de agosto o recurso e...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Semana passada tentei assistir uma série com minha namorada usando a live do Discord. Não deu: se você não vive debaixo de uma porta, provavelmente sabe que desde 12 de agosto o recurso está suspenso no Brasil inteiro, por ordem da ANPD, depois que investigadores encontraram que a plataforma não consegue inspecionar uma transmissão em tempo real.</p><p>Esse guia não é sobre burlar a suspensão. É sobre o fato de que a comunicação inteira de um grupo pode depender de uma ferramenta que ninguém do grupo controla, e sumir por uma decisão tomada em outro lugar.</p><p>Testei a alternativa essa semana e documentei o processo inteiro: um servidor TeamSpeak 6 rodando numa VPS Oracle Cloud, camada Always Free, gratuita pra sempre. Uma hora do início ao fim, confortável pra 10 a 30 pessoas, sem custo nenhum e com compartilhamento de tela e com o deslumbre da antiga interface amável do TeamSpeak.</p><p>O motivo de eu trazer isso pra cá, e não só deixar no blog: a parte que mais gente trava é justamente a que a maioria dos tutoriais por aí pula. Uma instância Oracle fica atrás de dois firewalls independentes, a Security List da VCN e o iptables local, e os dois precisam liberar o tráfego. Isso é o que separa documentar que funciona de ser reproduzível por qualquer pessoa que seguir o passo a passo. Testei do zero, incluindo a persistência depois de um reboot.</p><p>Guia completo aqui: <a href="https://luanncurioso.dev/blog/self-hosting-teamspeak-oracle-free-vps" rel="nofollow">https://luanncurioso.dev/blog/self-hosting-teamspeak-oracle-free-vps</a></p><p>Ainda acho que os desenvolvedores de plantão que estão atrás de desenvolver uma plataforma para ocupar o lugar do discord irão se espantar com a simples ideia do custo inicial de um projeto desse em produção, portanto, mesmo que não perfeito, são apenas mais etapas para ter o que foi perdido durante esse período meio conturbado.</p></div>]]></content:encoded>
            <author>hiradox</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Publiquei minha primeira biblioteca Python]]></title>
            <link>https://www.tabnews.com.br/guitoorres/publiquei-minha-primeira-biblioteca-python</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/guitoorres/publiquei-minha-primeira-biblioteca-python</guid>
            <pubDate>Thu, 20 Aug 2026 21:17:06 GMT</pubDate>
            <description><![CDATA[Recentemente, a empresa onde trabalho decidiu implantar um SSO para acesso aos sistemas internos. Com isso, começamos a integrar nossas aplicações ao novo provedor de identidade. No entan...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Recentemente, a empresa onde trabalho decidiu implantar um SSO para acesso aos sistemas internos. Com isso, começamos a integrar nossas aplicações ao novo provedor de identidade.</p><p>No entanto, com o surgimento de novos projetos, percebemos que o mesmo trabalho de implementar repetidamente os fluxos de autenticação OAuth 2.0 e OpenID Connect acabava se repetindo. Foi então que surgiu a ideia de desenvolver uma biblioteca simples e objetiva, capaz de agilizar esse processo e permitir que os desenvolvedores direcionassem seus esforços para a lógica de negócio da aplicação.</p><p>O <strong>FastOIDC</strong> é uma biblioteca Python que abstrai o fluxo de autenticação OAuth 2.0 + OpenID Connect, permitindo configurar clientes OAuth rapidamente em backends desenvolvidos com FastAPI.</p><p>A biblioteca implementa o fluxo de autenticação, utilizando <strong>PKCE</strong> e mecanismos de proteção contra <strong>CSRF</strong>, além de oferecer renovação automática de tokens e gerenciamento da sessão do usuário.</p><p>Até o momento, o FastOIDC foi testado com os seguintes provedores de identidade: <strong>Google, WSO2, Keycloak, Auth0 e GitHub</strong>. Na documentação mostro alguns exemplos para você copiar e rodar na sua máquina.</p><p>Para quem não conhece, o <strong>OAuth</strong> é um protocolo de <strong>autorização</strong> que permite que um aplicativo acesse seus dados em outra aplicação em seu nome de forma segura, sem você precisar fornecer sua senha.</p><p>Já o <strong>OpenID Connect (OIDC)</strong> é uma camada de <strong>autenticação</strong> construída em cima do OAuth 2.0, ou seja, ele diz a aplicação quem você é através de um <strong>ID Token</strong>, que é um JWT assinado contendo os dados básicos de que fez o login (e-mail, nome, foto de perfil, etc). Sabe quando você vai acessar um site e na página de login mostra um "Entrar com Google"? Isso é o OIDC.</p><p>Existem 4 papéis principais no OAuth:<br>1 - <strong>Resource Owner</strong>: Quem é dono dos dados e pode conceder o acesso a eles.<br>2 - <strong>Client</strong>: A aplicação que quer acessar seus dados e precisa do seu consentimento para isso.<br>3 - <strong>Authorization Server</strong>: O Servidor que verifica quem você é, obtém o consentimento e emite tokens de acesso para o client acessar seus dados (Exemplo: Google, Github, Keycloak, etc).<br>3 - <strong>Resource Server</strong>: O Servidor que contém dados protegidos que só podem ser acessados por quem fornecer um token de acesso válido (Exemplo: APIs do Google, API do Github, etc).</p><p>O fluxo OAuth + OIDC funciona da seguinte forma:</p><p>1 - <strong>Início do login</strong>: Quando você clica em "Entrar com o google", por exemplo, você é redirecionado para a tela de login com o google, onde você consentirá o acesso aos seus dados pela aplicação.<br>2 - <strong>Código de autorização</strong>: O Google redireciona você para a aplicação, passando um código temporário (<code>authorization_code</code>) na URL.<br>3 - <strong>Troca do código por tokens</strong>: A aplicação usa esse código para solicitar os tokens de acesso para o Google e recebe um <code>access_token</code>,  um <code>id_token</code> e, opcionalmente, um <code>refresh_token</code>.<br>4 -  <strong>Acesso aos dados</strong>: A aplicação valida o <code>id_token</code>,  extrai os dados do usuário (e-mail, nome, foto de perfil, etc) e usa o <code>access_token</code> para acessar os recursos protegidos do Resource Server.</p><p>Abaixo está o diagrama que fiz para mostrar de forma didática o que cada papel faz no fluxo OAuth.</p><p><img src="https://i.imgur.com/V5MWt5j.png" alt="diagrama simplificado do fluxo OAuth" title="diagrama simplificado do fluxo OAuth"></p><p>Quem quiser conhecer o projeto FastOIDC, utilizá-lo ou contribuir com seu desenvolvimento pode acessar o <a href="https://github.com/guilherme-torres/fastoidc">repositório no GitHub</a>.</p><p>Alguns recursos interessantes sobre o tema abordado:</p><ul><li><a href="https://www.oauth.com/playground/" rel="nofollow">https://www.oauth.com/playground/</a></li><li><a href="https://www.youtube.com/watch?v=uLY1CuLi9ac" rel="nofollow">https://www.youtube.com/watch?v=uLY1CuLi9ac</a></li><li><a href="https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc" rel="nofollow">https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc</a></li></ul></div>]]></content:encoded>
            <author>guitoorres</author>
        </item>
        <item>
            <title><![CDATA[Ganhei uma carta de Pokémon de 1 milhão de dólares no GitHub com um projeto open source]]></title>
            <link>https://www.tabnews.com.br/igorcbraz1/ganhei-uma-carta-de-pokemon-de-1-milhao-de-dolares-no-github-com-um-projeto-open-source</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/igorcbraz1/ganhei-uma-carta-de-pokemon-de-1-milhao-de-dolares-no-github-com-um-projeto-open-source</guid>
            <pubDate>Thu, 20 Aug 2026 20:19:45 GMT</pubDate>
            <description><![CDATA[Eu estava procurando alguma coisa diferente para colocar no meu README do GitHub quando encontrei uma opção que me chamou bastante atenção: adicionar uma carta de Pokémon ao perfil. Botão...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Eu estava procurando alguma coisa diferente para colocar no meu README do GitHub quando encontrei uma opção que me chamou bastante atenção: <strong>adicionar uma carta de Pokémon ao perfil</strong>.</p><p><img src="https://i.ibb.co/rfNVKz3D/pokemon-card.gif" alt="Botão de adicionar carta de Pokémon"></p><p>A animação do botão já tinha me convencido a clicar. Fui ver como funcionava e descobri que dava para escolher a carta e configurar alguns detalhes antes de colocar no README.</p><h2 id="igorcbraz1-content-a-carta">A carta</h2><p><img src="https://i.ibb.co/NgsxTZRG/2.png" alt="Configuração da carta de Pokémon"></p><p>Como eu não tinha nenhum motivo específico para colocar uma carta de Pokémon no meu GitHub, achei que o mínimo seria escolher uma que realmente chamasse atenção.</p><p>Acabei escolhendo uma de <strong>US$ 1 milhão</strong>.</p><blockquote><p>Infelizmente, o card não vem acompanhado dos US$ 1 milhão.</p></blockquote><h2 id="igorcbraz1-content-o-resultado">O resultado</h2><p>Depois de colocar tudo no lugar, ficou assim:</p><p><img src="https://gitascii.com/api/Igorcbraz?v=1787254936063" alt="Meu README com a carta de Pokémon"></p><p>Agora meu GitHub tem:</p><ul><li>1 README bonito;</li><li>1 carta de Pokémon de <strong>US$ 1 milhão</strong>.</li></ul><p>Talvez tenha sido o melhor investimento que eu já fiz. Vai que o próximo recrutador é colecionador de Pokémon? Aí estou feito.</p><hr><p>O mais curioso é que encontrei tudo isso completamente por acaso. Entrei para mexer no README e comecei a explorar as opções disponíveis. Quando percebi, estava configurando uma carta de Pokémon milionária para colocar no meu perfil.</p><p>E acho que é justamente essa a parte legal de projetos open source: você entra procurando uma coisa e acaba encontrando outra completamente aleatória.</p><p>A ferramenta que usei para fazer tudo isso se chama <a href="https://github.com/Igorcbraz/GitAscii">GitAscii</a>. É um projeto open source para montar READMEs de um jeito mais visual e personalizável.</p><p>Se curtir a ideia, <strong>uma ⭐ é bem-vinda</strong>.</p></div>]]></content:encoded>
            <author>igorcbraz1</author>
        </item>
        <item>
            <title><![CDATA[QA: quando um incidente transforma estudo em experiência - Ciclo de Sanidade: carga/concorrência.]]></title>
            <link>https://www.tabnews.com.br/nicolasqa/qa-quando-um-incidente-transforma-estudo-em-experiencia-ciclo-de-sanidade-carga-concorrencia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/nicolasqa/qa-quando-um-incidente-transforma-estudo-em-experiencia-ciclo-de-sanidade-carga-concorrencia</guid>
            <pubDate>Thu, 20 Aug 2026 20:06:37 GMT</pubDate>
            <description><![CDATA[Recentemente vivi uma experiência que mudou minha percepção sobre evolução profissional em QA. Objetivo do ciclo: sanidade pós-correção de incidente. Atributo principal: confiabilidade —...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Recentemente vivi uma experiência que mudou minha percepção sobre evolução profissional em QA.</p><p><strong>Objetivo do ciclo:</strong> sanidade pós-correção de incidente.<br><strong>Atributo principal:</strong> confiabilidade — verificar perdas, duplicidades e pedidos presos.<br><strong>Condição aplicada:</strong> carga/concorrência controlada.<br><strong>Camada:</strong> integração/E2E — API, fila, estoque e banco.</p><p>Eu já havia estudado alguns conceitos relacionados a testes de confiabilidade, concorrência e desempenho. Ainda assim, esse tipo de trabalho parecia distante da minha realidade cotidiana. Até um incidente que gerou a necessidade de uma correção no menor tempo possível e consequetemente a validação da mesma. É muito diferente conhecer um assunto em um curso e precisar aplicá-lo durante a validação de uma correção originada por um incidente real.</p><p>Quando a demanda chegou, senti uma certa insegurança em saber como inciar a demanda. Reunião com a liderança do squad de Q.AS,  reunião com o techlead do produto e a partir disso uma estratégia para seguir. Havia uma correção importante aguardando validação e o resultado dos testes ajudaria a equipe a decidir se ela estava segura para seguir para produção.</p><h2 id="nicolasqa-content-o-desafio">O desafio</h2><p>O incidente envolvia um fluxo de pedidos processados de forma assíncrona. A API aceitava a solicitação, mas a conclusão dependia de outras etapas, como fila, processamento e disponibilidade de estoque.</p><p>Por isso, uma resposta de sucesso da API não era evidência suficiente. Um pedido poderia ser aceito e, ainda assim, permanecer em um estado intermediário ou não chegar ao resultado esperado pelo negócio.</p><p>A pergunta principal deixou de ser apenas “a API respondeu?” e passou a ser:</p><blockquote><p>Todos os pedidos aceitos foram realmente processados até o estado final esperado, sem perdas, duplicidades ou pedidos indevidamente parados na fila?</p></blockquote><p>Essa mudança de pergunta direcionou toda a validação.</p><h2 id="nicolasqa-content-começando-pelo-que-eu-já-conhecia">Começando pelo que eu já conhecia</h2><p>Iniciei os testes pelo Insomnia, ferramenta que já faz parte da minha rotina. Com ele, repeti o fluxo de criação de pedidos e observei o comportamento da fila.</p><p>Essa primeira etapa foi importante para validar o funcionamento básico da correção. Também me ajudou a perceber que repetir requisições em sequência não representava completamente o cenário do incidente, que havia ocorrido durante um volume concentrado de solicitações.</p><p>Eu precisava validar duas situações diferentes: o comportamento da fila ao processar vários pedidos e o comportamento do sistema quando pedidos chegavam concorrentemente.</p><p>Foi nesse momento que o k6 entrou na validação. Até então, eu o conhecia mais pelos estudos do que pela aplicação em uma demanda real. Utilizá-lo não foi somente escolher outra ferramenta, mas compreender qual risco ainda não estava coberto pelos testes que eu já havia executado.</p><h2 id="nicolasqa-content-um-passo-de-cada-vez">Um passo de cada vez</h2><p>Durante a preparação, nem tudo funcionou na primeira tentativa. Encontrei erro de rota, falha de autenticação e uma massa de teste que não representava corretamente o fluxo real.</p><p>Em vez de tratar isso como fracasso, passei a analisar um problema de cada vez. Primeiro confirmei a rota, depois a autenticação, o formato do pedido, a quantidade adequada e, somente então, aumentei o volume.</p><p>Essa forma de avançar foi essencial. Antes de executar centenas de pedidos, validei apenas um. Quando tive segurança de que a requisição estava correta, aumentei gradualmente a carga, sempre observando os resultados.</p><p>Também precisei respeitar as limitações do ambiente de homologação. O objetivo não era descobrir o limite máximo da plataforma, mas verificar com segurança se a correção se mantinha confiável diante do cenário que havia provocado o incidente.</p><h2 id="nicolasqa-content-a-importância-das-evidências">A importância das evidências</h2><p>Uma das partes mais marcantes dessa experiência foi entender que o teste não terminava na ferramenta que enviava as requisições.</p><p>Além de observar as respostas da API, registrei os horários, os tempos de resposta e os resultados de cada execução. Depois, cruzei essas informações com os registros do banco de dados para confirmar o estado final dos pedidos.</p><p>Esse cruzamento permitiu verificar se tudo o que havia sido aceito pela API realmente existia no banco, possuía o item esperado, recebeu estoque e chegou ao estado final correto.</p><p>Ao final do principal ciclo, foram criados 500 pedidos independentes. Todos foram aceitos pela API, encontrados no banco de dados e concluídos no estado esperado. Não houve falhas HTTP, perda de requisições nem pedidos indevidamente parados em estado intermediário.</p><p>Também foram realizados cenários regressivos com pedidos de estruturas diferentes, como combo e múltiplas variações, para verificar se a correção não havia afetado comportamentos relacionados.</p><p>Mais importante do que dizer “o teste passou” foi conseguir demonstrar por que ele passou.</p><h2 id="nicolasqa-content-o-que-essa-experiência-me-ensinou">O que essa experiência me ensinou</h2><p>O primeiro aprendizado foi que uma resposta de sucesso técnico nem sempre representa o sucesso do negócio. Em fluxos assíncronos, é necessário acompanhar o processamento até a sua conclusão.</p><p>Também aprendi que repetição e concorrência cobrem riscos diferentes. Uma ferramenta conhecida pode ser suficiente para uma parte da validação, mas o contexto deve orientar quando é necessário ampliar a estratégia.</p><p>Outro ponto importante foi perceber que as próprias evidências precisam ser conferidas. Durante os testes, identifiquei uma contagem que poderia transmitir uma conclusão incorreta. Isso reforçou que não basta automatizar: é preciso questionar se o resultado apresentado realmente corresponde ao que foi executado.</p><p>Por fim, entendi que testes de confiabilidade e desempenho não se resumem a gerar grandes volumes. Eles exigem uma hipótese clara, um ambiente conhecido, limites responsáveis e critérios que conectem o resultado técnico ao comportamento esperado pelo negócio.</p><h2 id="nicolasqa-content-evoluir-como-qa">Evoluir como QA</h2><p>Para mim, evoluir como QA não significa necessariamente seguir um único caminho ou buscar obrigatoriamente um cargo específico. Significa ampliar a capacidade de investigar riscos, compreender o sistema e oferecer informações confiáveis para que a equipe tome decisões melhores.</p><p>Mesmo com os estudos prévios, eu não comecei essa atividade me sentindo completamente preparado. A segurança foi sendo construída durante o processo: perguntando, pesquisando, testando em pequena escala, analisando os erros e compreendendo cada etapa antes de avançar.</p><p>Depois de concluir a validação, foi muito satisfatório apresentar as evidências dos testes executados e perceber que o trabalho ajudou a sustentar uma decisão mais segura. Não foi somente uma tarefa técnica concluída. Foi a sensação de ter apoiado um desenvolvimento mais íntegro e confiável.</p><p>O desafio que inicialmente parecia distante passou a fazer parte da minha experiência profissional. E talvez uma parte importante da evolução seja justamente essa: não esperar que o frio na barriga desapareça, mas aprender a transformá-lo em investigação, método e evidência. Saber pedir direcionamento para os colegas e agir na estratégia mas sem receio de sugerir teses.</p></div>]]></content:encoded>
            <author>nicolasqa</author>
        </item>
        <item>
            <title><![CDATA[Como construí um dashboard de energia solar embutido na parede da minha casa]]></title>
            <link>https://www.tabnews.com.br/marcosvpj/como-construi-um-dashboard-de-energia-solar-embutido-na-parede-da-minha-casa</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/marcosvpj/como-construi-um-dashboard-de-energia-solar-embutido-na-parede-da-minha-casa</guid>
            <pubDate>Thu, 20 Aug 2026 19:21:31 GMT</pubDate>
            <description><![CDATA[Moro numa casa off-grid no alto de uma montanha e trabalho remoto. Nesse cenário, monitorar o consumo de energia é necessidade constante: no verão os painéis solares recebem sol a partir...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Moro numa casa off-grid no alto de uma montanha e trabalho remoto. Nesse cenário, monitorar o consumo de energia é necessidade constante: no verão os painéis solares recebem sol a partir das 6-7h da manhã, mas no inverno isso só acontece por volta das 9-10h. A decisão de "assistir mais um episódio antes de dormir" ou "guardar energia" é literalmente a diferença entre ter ou não energia elétrica para trabalhar nos próximos dias nublados.</p><p>Para tomar essa decisão eu precisava consultar o aplicativo da bateria e a previsão do tempo — dois aplicativos, várias telas e atenção dividida. Então construí um dashboard que consulta os dados da bateria e uma API de previsão do tempo e exibe tudo em um display embutido na parede:</p><p><img src="https://marcosvpj.com.br/img/quantos-episodios-de-series-ainda-cabem-na-bateria/display-na-parede.webp" alt="Display embutido na parede mostrando a carga da bateria e a previsão do tempo"></p><p>Neste write-up, conto o processo por trás do projeto: as limitações que guiaram cada decisão de arquitetura, as semanas de engenharia reversa para conseguir os dados da bateria e a solução para responder o "e amanhã, vai ter sol?".</p><p>Se quiser o contexto completo (o problema que motivou tudo isso), leia o <a href="https://marcosvpj.com.br/posts/quantos-episodios-de-series-ainda-cabem-na-bateria/" rel="nofollow">post anterior no meu blog</a>.</p><h2 id="marcosvpj-content-as-limitações-do-cenário-off-grid">As limitações do cenário off-grid</h2><p>A maior restrição do projeto pode ser resumida em uma frase: <strong>não tenho internet disponível 24 horas por dia</strong>. Essa é uma limitação derivada de não ter geração de energia constante — e é justamente o problema que este projeto busca quantificar e deixar visível.</p><p>Consequência direta: todo o sistema precisava funcionar com ou sem acesso à internet.</p><h2 id="marcosvpj-content-onde-comecei">Onde comecei</h2><p>Meu ponto de partida foi ver o que eu já tinha em mãos:</p><ul><li>dados da bateria via aplicativo mobile do fabricante</li><li>APIs públicas de previsão do tempo</li><li>hardware barato e de baixo consumo de energia (um CYD — placa ESP32 com tela TFT de 2.8" soldada)</li></ul><p>O primeiro problema: eu sempre usei o próprio roteador da Starlink. Com ela desligada, eu ficava não só sem internet, mas também sem rede nenhuma — os dispositivos não conseguiam nem se falar entre si.</p><p>A solução foi adicionar um roteador wifi simples (Intelbras), que funciona 24h por dia independente da Starlink. Ele disponibiliza uma rede exclusiva para a bateria e o display, e se conecta via cabo ethernet à Starlink para dar acesso à internet quando ela está online.</p><h2 id="marcosvpj-content-os-dados-o-capítulo-da-engenharia-reversa">Os dados: o capítulo da engenharia reversa</h2><p>Conseguir os dados da bateria foi um longo processo de exploração que levou algumas semanas. Eu sabia que deveria haver algum modo de acessá-los, afinal a bateria enviava os dados para o aplicativo do fabricante.</p><p>Na primeira exploração, identifiquei a bateria na rede, mas não encontrei nenhum serviço aberto no IP dela. Descompilei o aplicativo, fiz engenharia reversa, monitorando o tráfego da minha rede — dias de frustração e nenhum caminho à frente.</p><p>Esgotadas minhas ideias, decidi fazer o caminho inverso: pegar os dados do aplicativo em vez da bateria. Não era o que eu queria, pois eu só teria acesso aos dados com internet, mas não ia deixar o projeto travar antes de sair do papel. Com isso, implementei a v0: a tela mostrava o estado de carga da bateria e uma estimativa de carga/descarga.</p><p>Satisfeito com a vitória e usando o dashboard há algumas semanas, decidi fazer um segundo round de exploração. Afinal, não faz sentido acessar um servidor na China para ler os dados de um dispositivo que está a 20 metros de mim, na mesma rede local.</p><p>Depois de muita pesquisa e leitura de várias versões de manuais, encontrei uma funcionalidade escondida no aplicativo: ele consegue acessar os dados da bateria <strong>sem internet</strong>, conectando-se diretamente a ela na rede local. Descoberta promissora.</p><p>A partir daí, instalei aplicativos de monitoramento de rede no celular e gravei o tráfego enquanto usava o aplicativo da bateria. Rede não é meu forte, e analisar aqueles logs manualmente levaria muito tempo, com risco de deixar algo passar. Então usei o Claude Code para analisar os logs, informando quais ações eu tinha feito durante a gravação — e ele identificou exatamente quais requests traziam os dados que eu via no app. Com alguns scripts Python, passei a replicar essas requests sem depender do aplicativo.</p><p>Para quem tem uma bateria da Felicity ou quer entender o protocolo por baixo dos panos, documentei tudo no <a href="https://github.com/marcosvpj/felicity-cyd/blob/main/docs/PROTOCOL.md">repositório do projeto</a>.</p><p>Com isso, a v1 estava de pé: dados da bateria sem nenhuma dependência de internet.</p><h2 id="marcosvpj-content-temos-o-hoje-mas-e-amanhã">Temos o hoje, mas e amanhã?</h2><p>Com a situação atual resolvida, faltava responder: vai ter sol amanhã? Posso esbanjar ou preciso economizar?</p><p>Depois de comparar APIs, escolhi a Open-Meteo. Melhor que previsão do tempo, ela disponibiliza a <strong>previsão de radiação solar</strong> — uma métrica muito mais precisa para o meu problema do que "nublado", "sol" ou "chuva".</p><p>Aqui esbarrei de novo na limitação de internet, e também na do hardware do display. A solução mais simples seria o próprio display consultar a API, mas isso significaria implementar em C uma série de redundâncias e caches para falhas de internet ou da API. Optei por uma solução um pouco mais complexa, porém mais simples de manter:</p><ul><li>um <strong>serviço em Go</strong> rodando na VPS busca os dados na Open-Meteo de hora em hora, aplica cache e cálculos, e sobrescreve um <strong>arquivo JSON estático</strong></li><li>o serviço nunca fica exposto na internet: se a API retornar erro, ele simplesmente não faz nada — o próprio arquivo vira a camada de cache</li><li>o display faz uma requisição para esse arquivo: se der erro, continua mostrando os últimos dados que tinha; se voltar, compara a data e atualiza o que está na tela</li><li>para falhas de conexão não passarem despercebidas, a tela mostra há quantas horas foi a última atualização bem-sucedida</li></ul><p><img src="https://marcosvpj.com.br/img/quantos-episodios-de-series-ainda-cabem-na-bateria/tela-detalhe.webp" alt="Detalhe da tela: carga, tensão, corrente, previsão de geração e histórico das últimas 24h"></p><h2 id="marcosvpj-content-instalação">Instalação</h2><p>Para simplificar, aproveitei uma tomada com adaptador USB: liguei os fios 220v na tomada e o CYD na saída USB, tudo em uma única peça. Removi as outras entradas da tomada, aumentei o buraco do espelho e embuti o CYD dentro da caixa — instalar ficou simples como instalar qualquer outra tomada.</p><p><img src="https://marcosvpj.com.br/img/quantos-episodios-de-series-ainda-cabem-na-bateria/placa-esp32.webp" alt="Parte de trás do display: placa ESP32 com tela TFT integrada, encaixada na caixa"></p><p><img src="https://marcosvpj.com.br/img/quantos-episodios-de-series-ainda-cabem-na-bateria/caixa-embutida.webp" alt="Interior da caixa embutida na parede, com a fonte e a fiação"></p><h2 id="marcosvpj-content-o-sistema-completo">O sistema completo</h2><pre><code>               wifi                      ethernetBateria Felicity &#x3C;-----> Roteador Intelbras &#x3C;-----> Starlink (internet)       ^                      ^       |                      |       +---- wifi ------------+                     |                     v            +--------------+            |  CYD (tela)  |            +--------------+                     ^                     | http (arquivo JSON)                     |Open-Meteo --https--> Serviço Go (VPS) --sobrescreve--> JSON estático</code></pre><p>Componentes: bateria Felicity, roteador Intelbras, CYD (ESP32 + tela), serviço Go na VPS, API Open-Meteo, tomada USB.</p><p>Código do firmware e do serviço: <a href="https://github.com/marcosvpj/felicity-cyd">github.com/marcosvpj/felicity-cyd</a></p><h2 id="marcosvpj-content-conclusão">Conclusão</h2><p>Não é porque moro off-grid, no alto de uma montanha, que não posso usar tecnologia para melhorar minha vida. A principal questão é entender as limitações vigentes e trabalhar com elas — e ao redor delas.</p><p>E isso serve para tudo: muitas vezes queremos fazer as coisas do melhor modo possível, com a melhor arquitetura possível, quando simplesmente disponibilizar um arquivo JSON estático já resolve.</p></div>]]></content:encoded>
            <author>marcosvpj</author>
        </item>
        <item>
            <title><![CDATA[Pitch: pqp.gg — chat de voz open source com tela compartilhada funcionando no Brasil]]></title>
            <link>https://www.tabnews.com.br/rafaelcg/pitch-pqp-gg-chat-de-voz-open-source-com-tela-compartilhada-funcionando-no-brasil</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/rafaelcg/pitch-pqp-gg-chat-de-voz-open-source-com-tela-compartilhada-funcionando-no-brasil</guid>
            <pubDate>Thu, 20 Aug 2026 18:48:14 GMT</pubDate>
            <description><![CDATA[Desde 17/08 o compartilhamento de tela, vídeo e Go Live do Discord estão suspensos no Brasil (ordem da ANPD, sem data pra voltar — afirmação de produto, não jurídica). Mesa de RPG, watch...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Desde 17/08 o compartilhamento de tela, vídeo e Go Live do Discord estão suspensos no Brasil (ordem da ANPD, sem data pra voltar — afirmação de produto, não jurídica). Mesa de RPG, watch party, coaching, estudo em call: todo mundo ficou sem a ferramenta principal.</p><p>Eu venho construindo o <strong>pqp</strong> — um chat de voz/texto open source, estilo Discord — e essa semana ele virou a minha resposta pra isso:</p><ul><li><strong>Tela compartilhada e câmera nas chamadas funcionando</strong>, direto do navegador, sem instalar nada (tem app desktop também)</li><li><strong>De graça</strong>, no <a href="https://pqp.gg" rel="nofollow">pqp.gg</a>, ou self-host na sua máquina</li><li><strong>Código aberto</strong> (AGPL-3.0): <a href="https://github.com/rafaelcg/pqp">https://github.com/rafaelcg/pqp</a></li><li>Servidores em São Paulo</li><li>Stack: React 19 + Node + Postgres, voz por WebRTC</li></ul><p>Sendo honesto: é <strong>beta aberto</strong>. O ecossistema é zero perto do Discord — bots, integrações, apps polidos de loja, dez anos de estrada. Eu mantenho uma página de comparação que lista onde o Discord ainda ganha: <a href="https://pqp.gg/vs-discord" rel="nofollow">pqp.gg/vs-discord</a>.</p><p>Uma coisa que estou testando: <strong>caça-bugs como atividade</strong>. Achou um bug de verdade e reportou (tem uma caixinha de feedback nas configurações)? Bug confirmado ganha um selo 🐛 permanente no seu perfil público.</p><p>Feedback duro é bem-vindo — de arquitetura a copy. E se quiser quebrar alguma coisa, melhor ainda: me conta como.</p></div>]]></content:encoded>
            <author>rafaelcg</author>
        </item>
        <item>
            <title><![CDATA[Cidadela do Pracinha: o projeto da minha vida (PWA + Agentes de IA + Economia Real)]]></title>
            <link>https://www.tabnews.com.br/johnpracinha/pitch-criei-uma-cidadela-de-simulacao-com-ia-economia-real-e-rpg-de-suspense-pwa</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/johnpracinha/pitch-criei-uma-cidadela-de-simulacao-com-ia-economia-real-e-rpg-de-suspense-pwa</guid>
            <pubDate>Thu, 20 Aug 2026 18:04:55 GMT</pubDate>
            <description><![CDATA[Fala, pessoal! ​A Cidadela do Pracinha é o projeto da minha vida. A ideia é criar um universo vivo rodando direto no navegador, onde uma simulação de carreira de futebol se cruza com econ...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Fala, pessoal!<br>​A Cidadela do Pracinha é o projeto da minha vida. A ideia é criar um universo vivo rodando direto no navegador, onde uma simulação de carreira de futebol se cruza com economia virtual e um RPG de investigação/suspense.<br>​A engrenagem do ecossistema funciona assim:<br>​Mundo vivo com Agentes de IA: Os habitantes da Cidadela (jornalistas, dirigentes, rivais) têm memória e contexto de dados reais.<br>​Impacto em tempo real: Suas declarações em entrevistas coletivas são interpretadas pela IA e registradas no Supabase. Isso gera reações imediatas: mensagens no celular virtual, matérias de imprensa e até oscilações de ativos na Bolsa interna do jogo.<br>​Economia com Ledger Próprio: Toda a movimentação financeira e os ativos da Cidadela são gerenciados por um sistema de registro interno.<br>​Camada Narrativa: Para quem quer ir além dos relvados, há todo um mistério investigativo escondido na Cidadela.<br>​Como o TabNews reúne referências em engenharia e produto, preciso da ajuda de vocês para evoluir o ecossistema.<br>​Quem puder navegar na Cidadela e testar a aplicação, gostaria muito de receber feedback sobre:<br>​Ideias de integração: Que novas mecânicas ou camadas de tecnologia ficariam interessantes para expandir essa simulação?<br>​Experiência de Uso (UX/UI): Como está a usabilidade do PWA no mobile e no desktop?<br>​Arquitetura &#x26; IA: Sugestões para otimizar o consumo de contexto dos agentes e a resposta do banco de dados.<br>​Toda crítica construtiva, apontamento de bug ou ideia de funcionalidade será fundamental para o desenvolvimento do projeto. Valeu demais!</p></div>]]></content:encoded>
            <author>johnpracinha</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Fiz um port do Brasfoot para Mac usando o Claude]]></title>
            <link>https://www.tabnews.com.br/nicolaileo/fiz-um-port-do-brasfoot-para-mac-usando-o-claude</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/nicolaileo/fiz-um-port-do-brasfoot-para-mac-usando-o-claude</guid>
            <pubDate>Thu, 20 Aug 2026 17:27:39 GMT</pubDate>
            <description><![CDATA[Falaa pessoal, faz alguns dias vi um cara fazendo o port de um driver de impressora que só existia pra Windows pro Mac dele usando uma IA, e pra mim foi um dos cases de uso mais legais qu...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Falaa pessoal, faz alguns dias vi um cara fazendo o port de um driver de impressora que só existia pra Windows pro Mac dele usando uma IA, e pra mim foi um dos cases de uso mais legais que vi recentemente. Aquilo me deu uma ideia na hora.</p><p>Faz um tempo como tenho usado só mac e não achava um investimento bom comprar um outro pc só pra jogar um ou dois jogos, fui buscar as ferramentas pra entender como funcionava, passei por GPTK, crossover, wine e até consegui jogar vários jogos antigos que gostava, porém, apenas um eu não consegui rodar, o bom e velho Brasfoot. O Brasfoot tem uma particularidade, apesar de ser um jogo leve ele roda sob o java ele verifica se  JAVA existe de uma forma específica, que é pelo path do ambiente do Windows. No mac não consegui funcionar. Tentei também com o GPTK, Crossover, e neles acabava batendo no mesmo problema, pq os contâineres que ele criava não conseguiam simular direito o JAVA ou a versão não que tinha compatível com a ferramenta.</p><p>Como eu ja tinha uma ideia de onde tava o problema e porque ele não rodava, iniciei por criar uma camada de abstração, basicamente um launcher que já sabe onde o Java está e passa os parâmetros certos pro executável. Joguei o problema pro Claude com esses detalhes. E papo de uma hora, depois de pegar alguns logs de erros no sistema e vibe coding, o jogo estava rodando.</p><p>Foi uma das experiências mais legais que tive usando uma IA e mostra o poder que essas ferramentas tem quando são usadas pra algo mais que criar uma landing page ou uma calculadora ou coisa do tipo.</p><p>Enfim, se você tem Mac e sempre quis jogar Brasfoot, aqui está:</p><p><a href="https://github.com/codenicolai/brasfoot_mac">https://github.com/codenicolai/brasfoot_mac</a></p><p>Super leve, simples de rodar, e mais importante, agora tem como.</p><p>PS: o jogo não foi pirateado. É a versão original do instalador, disponibilizada gratuitamente pelo Emanuel. e ainda precisa registrar (registro disponível no site oficial do brasfoot)</p><p>Se conseguir rodar, deixa uma ⭐ no repositório, ajuda muito!</p></div>]]></content:encoded>
            <author>nicolaileo</author>
        </item>
        <item>
            <title><![CDATA[Quanto tempo vocês levam para fazer rollback de um deploy quebrado?]]></title>
            <link>https://www.tabnews.com.br/csbills/quanto-tempo-voces-levam-para-fazer-rollback-de-um-deploy-quebrado</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/csbills/quanto-tempo-voces-levam-para-fazer-rollback-de-um-deploy-quebrado</guid>
            <pubDate>Thu, 20 Aug 2026 15:10:55 GMT</pubDate>
            <description><![CDATA[Esses dias implementei uma feature de rollback no Hangar e fiquei curioso para saber como vocês lidam com isso hoje. Imagina o cenário: Você faz um deploy, aparentemente está tudo certo,...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Esses dias implementei uma feature de rollback no Hangar e fiquei curioso para saber como vocês lidam com isso hoje.</p><p>Imagina o cenário:</p><blockquote><p>Você faz um deploy, aparentemente está tudo certo, e alguns minutos depois percebe que quebrou produção.</p></blockquote><p>Normalmente dá para fazer um <code>git revert</code>, voltar para o commit anterior e disparar outro deploy.</p><p>Funciona, mas dependendo do projeto você ainda precisa passar novamente por build, geração da imagem e todo o processo de deploy.</p><p>No Hangar resolvi fazer diferente.</p><p>Quando o rollback está ativado, a cada deploy eu salvo a imagem que foi compilada naquela versão.</p><p>Então se eu tiver:</p><p>Deploy #54 ← produção atual<br>Deploy #53<br>Deploy #52<br>Deploy #51</p><p>e o deploy #54 quebrar alguma coisa, o usuário pode simplesmente escolher o #53 e clicar em <strong>Rollback</strong>.</p><p>Como aquela imagem já foi compilada anteriormente, não fazemos o build novamente.</p><p>Em poucos segundos aquela versão volta para produção.</p><p>O que achei interessante nessa abordagem é que você não está reconstruindo um commit antigo. Você está colocando em produção exatamente a mesma imagem que já estava funcionando anteriormente.</p><p>Claro que existe um custo nisso, principalmente armazenamento das imagens antigas, então deixei a funcionalidade opcional.</p><p>Estou construindo o Hangar, um PaaS brasileiro, e fiquei curioso para saber como vocês resolvem isso hoje.</p><p>Vocês fazem <code>git revert</code> + novo deploy? Guardam imagens anteriores? Usam alguma funcionalidade da própria plataforma?</p></div>]]></content:encoded>
            <author>csbills</author>
        </item>
        <item>
            <title><![CDATA[Samsung teria aumentado em até 15% os preços dos serviços de fabricação de chips sob encomenda]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/samsung-teria-aumentado-em-ate-15-por-cento-os-precos-dos-servicos-de-fabricacao-de-chips-sob-encomenda</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/samsung-teria-aumentado-em-ate-15-por-cento-os-precos-dos-servicos-de-fabricacao-de-chips-sob-encomenda</guid>
            <pubDate>Thu, 20 Aug 2026 14:35:07 GMT</pubDate>
            <description><![CDATA[O reajuste ocorre em meio à forte demanda por componentes de IA, que pressiona a capacidade de produção. A procura de clientes chineses tem sido especialmente alta, mas a empresa não cons...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>O reajuste ocorre em meio à forte demanda por componentes de IA, que pressiona a capacidade de produção. A procura de clientes chineses tem sido especialmente alta, mas a empresa não consegue atender todos os pedidos porque também precisa produzir para clientes dos EUA e reservar parte da capacidade para seus próprios chips.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Google vai treinar modelos de IA com conjunto massivo de dados de companhia aérea falida]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/google-vai-treinar-modelos-de-ia-com-conjunto-massivo-de-dados-de-companhia-aerea-falida</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/google-vai-treinar-modelos-de-ia-com-conjunto-massivo-de-dados-de-companhia-aerea-falida</guid>
            <pubDate>Thu, 20 Aug 2026 14:30:07 GMT</pubDate>
            <description><![CDATA[A Spirit Airlines encerrou as operações em maio e colocou os dados à venda durante a liquidação. O Google venceu o leilão por 10 milhões de dólares e terá acesso a 100 milhões de e-mails,...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A Spirit Airlines encerrou as operações em maio e colocou os dados à venda durante a liquidação. O Google venceu o leilão por 10 milhões de dólares e terá acesso a 100 milhões de e-mails, 537,5 milhões de registros do Teams, OneDrive e SharePoint, além de mais de 45 milhões de gravações de chamadas e chats de atendimento ao cliente. A venda ainda depende de aprovação judicial e informações pessoais devem ser removidas antes da transferência.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Unitree Robotics, maior fabricante de robôs humanoides do mundo, estreia na Bolsa de Xangai com alta superior a 460% nas ações]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/unitree-robotics-maior-fabricante-de-robos-humanoides-do-mundo-estreia-na-bolsa-de-xangai-com-alta-superior-a-460-por-cento-nas-acoes</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/unitree-robotics-maior-fabricante-de-robos-humanoides-do-mundo-estreia-na-bolsa-de-xangai-com-alta-superior-a-460-por-cento-nas-acoes</guid>
            <pubDate>Thu, 20 Aug 2026 14:25:06 GMT</pubDate>
            <description><![CDATA[A listagem também torna a empresa a primeira do setor a abrir capital em uma bolsa da China continental. No ano passado, a companhia despachou mais de 5.500 robôs humanoides e registrou l...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A listagem também torna a empresa a primeira do setor a abrir capital em uma bolsa da China continental. No ano passado, a companhia despachou mais de 5.500 robôs humanoides e registrou lucro líquido de 41,3 milhões de dólares.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[NASA desiste de missão para resgatar observatório Swift antes que ele reentre na atmosfera]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/nasa-desiste-de-missao-para-resgatar-observatorio-swift-antes-que-ele-reentre-na-atmosfera</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/nasa-desiste-de-missao-para-resgatar-observatorio-swift-antes-que-ele-reentre-na-atmosfera</guid>
            <pubDate>Thu, 20 Aug 2026 14:20:06 GMT</pubDate>
            <description><![CDATA[O satélite Link, lançado no mês passado e do tamanho de uma geladeira, seria usado para capturar o Swift com três braços robóticos e elevar sua órbita, mas sofreu problemas contínuos de c...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>O satélite Link, lançado no mês passado e do tamanho de uma geladeira, seria usado para capturar o Swift com três braços robóticos e elevar sua órbita, mas sofreu problemas contínuos de controle de altitude. A NASA queria evitar a reentrada porque ela encerraria as operações do observatório, que ainda poderia continuar produzindo dados científicos sobre explosões de raios gama. Ele está em órbita há 21 anos e deve reentrar na atmosfera ainda em 2026.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Microsoft investiga travamentos em jogos após atualização de agosto do Windows 11]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/microsoft-investiga-travamentos-em-jogos-apos-atualizacao-de-agosto-do-windows-11</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/microsoft-investiga-travamentos-em-jogos-apos-atualizacao-de-agosto-do-windows-11</guid>
            <pubDate>Thu, 20 Aug 2026 14:15:05 GMT</pubDate>
            <description><![CDATA[Segundo a empresa, alguns títulos podem parar de responder, fechar inesperadamente, exibir o erro “EXCEPTION_ACCESS_VIOLATION” ou até reiniciar o dispositivo. Os relatos surgiram após o l...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Segundo a empresa, alguns títulos podem parar de responder, fechar inesperadamente, exibir o erro “EXCEPTION_ACCESS_VIOLATION” ou até reiniciar o dispositivo. Os relatos surgiram após o lançamento da KB5121003 e a companhia apura se o problema foi causado pela atualização ou por drivers de terceiros.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Modelo novo, comportamento novo: trate a troca como uma migração]]></title>
            <link>https://www.tabnews.com.br/Centelha/modelo-novo-comportamento-novo-trate-a-troca-como-uma-migracao</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Centelha/modelo-novo-comportamento-novo-trate-a-troca-como-uma-migracao</guid>
            <pubDate>Thu, 20 Aug 2026 14:14:50 GMT</pubDate>
            <description><![CDATA[O fornecedor anuncia um modelo novo. O modelo que você usa ganha data de saída. Entre um aviso e outro, aparece um seletor na interface e a troca parece tão simples quanto mudar uma confi...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>O fornecedor anuncia um modelo novo. O modelo que você usa ganha data de saída. Entre um aviso e outro, aparece um seletor na interface e a troca parece tão simples quanto mudar uma configuração.</p><p>A API continua aceitando mensagens. A resposta continua sendo texto. Talvez os testes unitários até passem. Dias depois, porém, o agente começa a chamar ferramentas em outra ordem, ignora uma etapa de validação ou gasta mais para resolver a mesma issue.</p><p>É aí que a falsa simplicidade do seletor cobra a conta.</p><p>No ecossistema do GitHub Copilot, por exemplo, o anúncio da chegada do Gemini 3.7 Flash veio no mesmo período em que outros modelos receberam uma data de depreciação. O Copilot cloud agent também passou a permitir a escolha do nível de raciocínio por execução, com impacto possível no consumo de tokens ou créditos. São mudanças diferentes, mas apontam para o mesmo cuidado operacional: modelo e esforço fazem parte da rota de execução do produto.</p><p>Trocar essa rota exige o mesmo cuidado que uma migração de dependência importante. Não precisa virar um projeto de três meses. Precisa ser pequena, observável e reversível.</p><h2 id="centelha-content-o-seletor-esconde-uma-dependência-de-comportamento">O seletor esconde uma dependência de comportamento</h2><p>Duas opções compatíveis com a mesma API não são, necessariamente, equivalentes no seu workflow. A troca pode alterar:</p><ul><li>como o agente interpreta uma instrução ambígua;</li><li>quando ele decide chamar uma ferramenta;</li><li>o formato e a consistência da saída estruturada;</li><li>a quantidade de tentativas até concluir uma tarefa;</li><li>a latência e o custo da execução;</li><li>o ponto em que ele considera o trabalho encerrado.</li></ul><p>Essa diferença importa pouco em uma conversa casual. Importa bastante quando o modelo edita código, usa credenciais, abre um pull request ou chama um serviço externo.</p><p>Fixar a rota atual traz alguma estabilidade, mas não elimina a migração. Só adia o momento. Se o fornecedor já definiu uma data de depreciação, esperar até a última semana reduz justamente o que você mais precisa para trocar com segurança: tempo para comparar o comportamento.</p><p>Atualizar automaticamente resolve o problema oposto. Você recebe novidades sem esforço manual, mas aceita mudanças antes de entender como elas afetam o seu fluxo. Para um agente em produção, nenhuma das duas escolhas funciona bem sozinha. É melhor ter uma política explícita de versão, avaliação e promoção.</p><h2 id="centelha-content-escreva-o-contrato-antes-de-escolher-o-candidato">Escreva o contrato antes de escolher o candidato</h2><p>Comparar modelos por uma resposta isolada quase sempre favorece o texto mais convincente. O produto, no entanto, depende do fluxo completo.</p><p>Antes de testar o candidato, descreva o comportamento que precisa sobreviver à troca. Use poucos casos reais e declare o que será observado em cada um. Um contrato enxuto pode registrar:</p><pre><code class="hljs language-yaml"><span class="hljs-attr">rota:</span> <span class="hljs-string">corrigir-bug-frontend</span><span class="hljs-attr">entrada:</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">issue</span> <span class="hljs-string">com</span> <span class="hljs-string">passos</span> <span class="hljs-string">de</span> <span class="hljs-string">reprodução</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">repositório</span> <span class="hljs-string">em</span> <span class="hljs-string">uma</span> <span class="hljs-string">branch</span> <span class="hljs-string">isolada</span><span class="hljs-string">saída_obrigatória:</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">arquivos</span> <span class="hljs-string">alterados</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">resumo</span> <span class="hljs-string">curto</span> <span class="hljs-string">da</span> <span class="hljs-string">causa</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">testes</span> <span class="hljs-string">executados</span><span class="hljs-attr">ferramentas_permitidas:</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">leitura</span> <span class="hljs-string">e</span> <span class="hljs-string">edição</span> <span class="hljs-string">do</span> <span class="hljs-string">repositório</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">terminal</span> <span class="hljs-string">com</span> <span class="hljs-string">comandos</span> <span class="hljs-string">aprovados</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">navegador</span> <span class="hljs-string">de</span> <span class="hljs-string">teste</span><span class="hljs-attr">limites:</span>  <span class="hljs-attr">tentativas:</span> <span class="hljs-number">3</span>  <span class="hljs-string">custo_por_execução:</span> <span class="hljs-string">definido_pelo_time</span><span class="hljs-string">condições_de_parada:</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">pedir</span> <span class="hljs-string">contexto</span> <span class="hljs-string">se</span> <span class="hljs-string">a</span> <span class="hljs-string">reprodução</span> <span class="hljs-string">falhar</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">parar</span> <span class="hljs-string">antes</span> <span class="hljs-string">de</span> <span class="hljs-string">qualquer</span> <span class="hljs-string">deploy</span><span class="hljs-string">validação:</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">testes</span> <span class="hljs-string">automatizados</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">console</span> <span class="hljs-string">sem</span> <span class="hljs-string">erro</span> <span class="hljs-string">novo</span>  <span class="hljs-bullet">-</span> <span class="hljs-string">critérios</span> <span class="hljs-string">da</span> <span class="hljs-string">issue</span> <span class="hljs-string">reproduzidos</span> <span class="hljs-literal">no</span> <span class="hljs-string">navegador</span></code></pre><p>Esse arquivo não precisa virar uma especificação universal. Ele só precisa expor o que hoje está escondido no prompt, no código ou na cabeça de quem montou o agente.</p><p>Também vale evitar um contrato que descreve o comportamento do modelo atual em vez da necessidade do produto. “Responder com o mesmo estilo e o mesmo número de passos” pode congelar uma peculiaridade sem valor. “Entregar JSON válido, executar os testes aprovados e preservar o estado de erro do formulário” define algo que o usuário realmente percebe.</p><h2 id="centelha-content-tire-modelo-e-esforço-da-regra-de-negócio">Tire modelo e esforço da regra de negócio</h2><p>Se o identificador do modelo aparece espalhado por handlers, jobs e scripts, cada migração vira uma caça ao texto. O risco não está apenas em esquecer um ponto. Rotas diferentes podem acabar usando versões distintas sem que isso seja intencional.</p><p>Concentre a decisão em uma configuração versionada:</p><pre><code class="hljs language-yaml"><span class="hljs-attr">rotas:</span>  <span class="hljs-attr">corrigir-bug-frontend:</span>    <span class="hljs-attr">modelo:</span> <span class="hljs-string">modelo-atual</span>    <span class="hljs-attr">esforco:</span> <span class="hljs-string">medio</span>    <span class="hljs-attr">fallback:</span> <span class="hljs-string">modelo-anterior</span>  <span class="hljs-attr">revisar-pull-request:</span>    <span class="hljs-attr">modelo:</span> <span class="hljs-string">modelo-atual</span>    <span class="hljs-attr">esforco:</span> <span class="hljs-string">alto</span>    <span class="hljs-attr">fallback:</span> <span class="hljs-string">desabilitado</span></code></pre><p>O formato é menos importante que a separação. A regra de negócio pede “corrija este bug com estes limites”; a camada de roteamento decide qual modelo e qual nível de esforço executam a tarefa.</p><p>Essa camada também deve registrar a rota que foi usada de verdade. Um log útil inclui modelo, configuração de esforço, versão do prompt, ferramentas liberadas, duração, custo, resultado da validação e motivo de fallback.</p><p>Sem isso, o fallback vira uma fonte de confusão. A tarefa termina, mas ninguém sabe que ela passou pelo modelo de reserva. A disponibilidade parece boa enquanto uma regressão fica escondida nos bastidores.</p><p>Fallback explícito não significa anunciar detalhes técnicos ao usuário em toda resposta. Significa deixar a substituição visível para quem opera e avalia o sistema.</p><h2 id="centelha-content-uma-migração-curta-em-seis-passos">Uma migração curta em seis passos</h2><p>Você não precisa reproduzir toda a produção. Uma amostra pequena, escolhida a partir de falhas e tarefas frequentes, costuma revelar mais que um benchmark genérico.</p><ol><li>Inventarie a rota atual. Localize identificadores de modelo, níveis de esforço, fallbacks, prompts, limites de custo e ferramentas disponíveis.</li><li>Salve um baseline. Execute os casos representativos com a configuração atual e guarde saídas, validações, latência, custo e falhas.</li><li>Rode o candidato nas mesmas condições. Se possível, use execução em sombra ou uma branch descartável para impedir efeitos externos.</li><li>Revise diferenças, não só acertos. Observe chamadas de ferramenta, tentativas extras, omissões, formato de saída e condições de parada.</li><li>Libere para uma amostra pequena. Comece por tarefas reversíveis e acompanhe a rota usada em cada execução.</li><li>Mantenha o rollback por um prazo definido. Preserve a configuração anterior enquanto o novo caminho ganha volume suficiente para revelar regressões menos óbvias.</li></ol><p>Rodar duas rotas custa mais tokens e créditos. É um custo temporário para obter evidências antes da virada. Se o orçamento for apertado, reduza a quantidade de casos, não a qualidade dos critérios. Três tarefas bem escolhidas são mais úteis que cinquenta prompts genéricos.</p><h2 id="centelha-content-exemplo-um-agente-que-corrige-bugs-de-frontend">Exemplo: um agente que corrige bugs de frontend</h2><p>Imagine um agente interno que recebe issues pequenas. A rota atual altera o código, executa os testes e valida o fluxo no navegador. Para avaliar um novo modelo, o time separa três casos:</p><ul><li>um formulário que precisa preservar os dados depois de um erro da API;</li><li>uma tela que quebra em largura de celular;</li><li>um componente que perdeu o nome acessível após uma refatoração.</li></ul><p>O candidato pode produzir um diff elegante e ainda reprovar. Se limpar o formulário depois do erro, corrigir apenas o viewport usado no teste ou ignorar a regressão de acessibilidade, o comportamento importante não foi preservado.</p><p>A avaliação deveria comparar pelo menos quatro tipos de evidência:</p><ul><li>o diff e os arquivos tocados;</li><li>o resultado dos testes;</li><li>erros novos no console;</li><li>a reprodução dos critérios no navegador.</li></ul><p>Suponha que o candidato acerte o código, mas pare antes da validação visual. Isso não prova que o modelo seja ruim. A causa pode estar no prompt, no nível de esforço, na ferramenta disponível ou no limite de tentativas. Como o contrato separa essas partes, o time consegue ajustar uma variável por vez em vez de escolher outra opção no seletor e torcer.</p><p>Esse detalhe evita uma armadilha comum: transformar toda falha em comparação de inteligência. Às vezes, o modelo tinha capacidade para concluir a tarefa, mas a rota não lhe deu tempo, permissão ou um critério de parada adequado.</p><h2 id="centelha-content-rollback-de-configuração-não-desfaz-o-mundo">Rollback de configuração não desfaz o mundo</h2><p>Voltar ao identificador anterior é simples quando o roteamento está isolado. Isso restaura a configuração para as próximas execuções. Não apaga uma mensagem enviada, não reverte automaticamente um deploy e não desfaz uma gravação feita em um serviço externo.</p><p>Por isso, a primeira fase da migração deve privilegiar tarefas reversíveis. Para ações externas, use aprovação humana, idempotência, modo de simulação ou uma operação compensatória quando o sistema oferecer esse caminho.</p><p>O rollback precisa responder a duas perguntas diferentes:</p><ol><li>como voltar a executar tarefas com a rota anterior;</li><li>como tratar os efeitos que a rota nova já produziu.</li></ol><p>Misturar as duas dá uma sensação de segurança que não existe.</p><h2 id="centelha-content-o-que-revisar-antes-da-troca">O que revisar antes da troca</h2><p>Uma última checagem ajuda a evitar a migração feita no impulso:</p><ul><li>onde o modelo atual está configurado?</li><li>quais tarefas representam o uso real?</li><li>quais saídas e ferramentas fazem parte do contrato?</li><li>existe um teto de custo e uma condição clara de parada?</li><li>a telemetria mostra modelo, esforço e fallback usados?</li><li>o candidato foi testado sem receber a fila inteira?</li><li>há um prazo para manter a rota anterior disponível?</li><li>efeitos externos exigem aprovação ou compensação?</li></ul><p>Modelos vão entrar, melhorar, mudar de disponibilidade e sair de catálogo. Tentar impedir esse ciclo só torna a próxima troca mais urgente.</p><p>A saída mais prática é fazer do modelo uma dependência substituível e do comportamento um contrato verificável. Assim, o nome no seletor pode mudar sem transformar cada novidade ou depreciação em uma aposta na produção.</p><h2 id="centelha-content-fontes">Fontes</h2><ul><li><a href="https://github.blog/changelog/2026-07-31-upcoming-august-2026-model-deprecations-in-github-copilot/" rel="nofollow">Upcoming August 2026 model deprecations in GitHub Copilot</a></li><li><a href="https://github.blog/changelog/2026-08-13-gemini-3-7-flash-is-now-available-in-github-copilot" rel="nofollow">Gemini 3.7 Flash is now available in GitHub Copilot</a></li><li><a href="https://github.blog/changelog/2026-08-03-customize-the-reasoning-level-for-copilot-cloud-agent/" rel="nofollow">Customize the reasoning level for Copilot cloud agent</a></li></ul></div>]]></content:encoded>
            <author>Centelha</author>
        </item>
        <item>
            <title><![CDATA[Projetos de lei gerados por IA com erros escrita aumentam 70% nos EUA]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/projetos-de-lei-gerados-por-ia-com-erros-escrita-aumentam-70-por-cento-nos-eua</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/projetos-de-lei-gerados-por-ia-com-erros-escrita-aumentam-70-por-cento-nos-eua</guid>
            <pubDate>Thu, 20 Aug 2026 14:10:05 GMT</pubDate>
            <description><![CDATA[Senadores e deputados estariam usando versões básicas do ChatGPT e Claude para redigir os documentos, contendo informações incorretas e falta de profundidade, o que tem atrasado processos...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Senadores e deputados estariam usando versões básicas do ChatGPT e Claude para redigir os documentos, contendo informações incorretas e falta de profundidade, o que tem atrasado processos de tramitação devido à necessidade de revisões frequentes.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Renda Extra com IA]]></title>
            <link>https://www.tabnews.com.br/IgorCirilo/renda-extra-com-ia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/IgorCirilo/renda-extra-com-ia</guid>
            <pubDate>Thu, 20 Aug 2026 14:07:58 GMT</pubDate>
            <description><![CDATA[Fala, galera! Beleza? Tenho visto muita gente quebrando a cabeça para achar formas reais de fazer uma renda extra hoje em dia. Com tanta inteligência artificial por aí, dá para automatiza...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Fala, galera! Beleza?</p><p>Tenho visto muita gente quebrando a cabeça para achar formas reais de fazer uma renda extra hoje em dia. Com tanta inteligência artificial por aí, dá para automatizar muita coisa e criar negócios digitais do zero sem precisar manjar de programação.</p><p>Assisti esse vídeo super legal com 5 ideias de negócios práticos e validados. Quem quiser dar uma olhada e pegar os insights, o vídeo completo tá aqui:👉 <a href="https://www.youtube.com/watch?v=op0GvHqDOFQ" rel="nofollow">https://www.youtube.com/watch?v=op0GvHqDOFQ</a></p></div>]]></content:encoded>
            <author>IgorCirilo</author>
        </item>
        <item>
            <title><![CDATA[Slack lança canais colaborativos de programação com IA]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/slack-lanca-canais-colaborativos-de-programacao-com-ia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/slack-lanca-canais-colaborativos-de-programacao-com-ia</guid>
            <pubDate>Thu, 20 Aug 2026 14:05:04 GMT</pubDate>
            <description><![CDATA[O Slack Code cria canais abertos e dedicados por projeto para que desenvolvedores trabalhem em conjunto sem precisar alternar entre diferentes ferramentas. O recurso inclui abas de usuári...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>O Slack Code cria canais abertos e dedicados por projeto para que desenvolvedores trabalhem em conjunto sem precisar alternar entre diferentes ferramentas. O recurso inclui abas de usuários, comparação de mudanças no código e prévia da saída em HTML. A novidade já está disponível para todos e funciona com agentes do marketplace do Slack, além de Claude Code, Devin, Vercel Agent e GitHub Copilot.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Stripe afirma que 1º de janeiro de 2026 marcou o “início da singularidade” e reforça que continuará privada]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/stripe-afirma-que-1-de-janeiro-de-2026-marcou-o-inicio-da-singularidade-e-reforca-que-continuara-privada</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/stripe-afirma-que-1-de-janeiro-de-2026-marcou-o-inicio-da-singularidade-e-reforca-que-continuara-privada</guid>
            <pubDate>Thu, 20 Aug 2026 14:00:04 GMT</pubDate>
            <description><![CDATA[Para ela, isso significa que a IA entrou em uma nova fase de rápida transformação da economia, evidenciada, entre outros fatores, pelo forte aumento na criação de novas empresas. Nesse ce...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Para ela, isso significa que a IA entrou em uma nova fase de rápida transformação da economia, evidenciada, entre outros fatores, pelo forte aumento na criação de novas empresas. Nesse cenário, manter-se privada permitirá tomar decisões de longo prazo com mais liberdade e agilidade, afirma a Stripe, sem pressão de acionistas e do mercado.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Codificando bits em números negativos e positivos]]></title>
            <link>https://www.tabnews.com.br/Programmer404/codificando-bits-em-numeros-negativos-e-positivos</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Programmer404/codificando-bits-em-numeros-negativos-e-positivos</guid>
            <pubDate>Thu, 20 Aug 2026 13:25:40 GMT</pubDate>
            <description><![CDATA[Neste post irei demonstrar e explicar como funciona a codificação de números negativos e positivos. Usarei o termo encoding ao invés de codificação por ser mais familiar para os devs. Os...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Neste post irei demonstrar e explicar como funciona a codificação de números negativos e positivos.</p><p>Usarei o termo <code>encoding</code> ao invés de codificação por ser mais familiar para os devs.</p><p>Os exemplos estarão em <code>Rust</code>.</p><h2 id="programmer404-content-o-que-é-encoding">O que é Encoding</h2><p>O que é <em>encoding</em>? Bem, <em>encoding</em> é o processo de mapear uma sequência de bits para um valor <strong>X</strong>.</p><p>Considere a seguinte sequência de bits:</p><pre><code class="hljs language-txt">0000</code></pre><p>Aqui temos 4 bits. Todos os bits tem <code>0</code> como seu valor. Você já deve saber que, quando todos os bits são <code>0</code>, ele normalmente representa o <code>0</code> em decimal.</p><blockquote><p>Irei trabalhar com decimais por ser simples e direto. No entanto, a notação funciona para Octal e Hexadecimal também, caso reste dúvidas.</p></blockquote><p>No entanto, o bit <code>0</code> pode ser o que eu quiser. Eu posso "encode" o bit <code>0</code> para a seguinte string: "The Elder Scrolls: Skyrim". Eu posso mapear <code>00</code> para uma coisa complemente diferente, tal como valor numérico: <code>101</code>.</p><p>Bits não significam nada sozinhos. O seu valor depende inteiramente do contexto. Isso significa que uma mesma sequência de bits pode representar infitas coisas dependendo do contexto. O que muda não são os bits, mas a <em>interpretação deles</em>. Iremos trabalhar com números nestes post.</p><p>Por debaixo dos panos, o mesmo ocorre quando escrevemos <code>let x = 10</code>. Como é de conhecimento comum, computadores usam base <code>2</code> (binária). Então como estamos vendo o número <code>10</code>? Eu não só estou vendo o número <code>10</code>, como é rotineiro manipular informação usando decimais ao invés de base binária!</p><h2 id="programmer404-content-enconding-unsigned-numbers">Enconding Unsigned numbers</h2><p>Para quem vêm do <code>Python</code>, <code>JavaScript</code>, e linguagens de alto nível, normalmente não se preocupam com multiplos tipos para valores numéricos, tais como <code>u8</code>, <code>u16</code>, <code>u32</code>, <code>u64</code>, <code>u128</code> e outras variantes. Para que fique de fácil entendimento, um número <em>unsigned</em> é um valor pertencente ao conjunto dos números naturais. Ou seja, não é fracionário e nem pode ser negativo.</p><p>Eu não irei entrar em comprovação matemática. Eu irei demonstrar na prática com código de alto nível como funciona.</p><p>Considere a seguinte sequência de bits:</p><pre><code class="hljs language-txt">0 0 0 1 &#x3C;- bit sequence3 2 1 0 &#x3C;- bit index</code></pre><p>Temos um bit de valor <code>1</code> e o restante com o valor de <code>0</code>, totalizando <code>4</code> bits.</p><p>Dizemos que, quando um bit tem o valor de <code>1</code>, ele contribui <span class="math math-inline">x \times 2^i</span> onde <code>x</code> é o valor do bit, e <code>i</code> é o posicionamento dele. Vamos fazer o processo passo a passo:</p><pre><code class="hljs language-txt">0 0 0 1 1 x 2^0 = 10 x 2^1 = 0 0 x 2^2 = 00 x 2^3 = 00 + 0 + 0 + 1 = 1 </code></pre><p>Se você não entendeu o que aconteceu aqui, você provavelmente não sabe, ou não lembra como funciona potenciação e multiplicação por zero. Ensinar isto foge do escopo do post.</p><p>Perceba que no final, após calcular a contribuição de cada bit, somamos tudo e é retornado o valor decimal: <code>1</code>. Isto significa que, <code>0001</code> é equivalente ao número <code>1</code>. Portanto, ao escrever:</p><pre><code class="hljs language-rust"><span class="hljs-keyword">let</span> <span class="hljs-variable">x</span> = <span class="hljs-number">1</span>;</code></pre><p>Nós vemos um decimal, mas o computador trabalha com <code>0001</code>.</p><p>Um detalhe importante. Eu usei 4 bits por questões de simplicidade. Normalmente trabalhamos com 8 bits em diante. A boa nóticia é que zero a esquerda não altera o valor, portanto:</p><pre><code class="hljs language-txt">0001 = 00000001</code></pre><p>São equivalentes. Daqui em diante, continuarei usando 4 bits.</p><p>Um ponto interessante é que, podemos determinar o valor mínimo e máximo que uma sequência de bits pode representar da seguinte forma para <strong>unsigned numbers</strong>:</p><p><span class="math math-inline">0</span> a <span class="math math-inline">2^n</span> onde <code>n</code> é o comprimento da sequência de bits. Neste caso é <code>4</code>, portanto o valor máximo que eu posso expressar usando 4 bits é <span class="math math-inline">2^4 = 15</span>.</p><p>Antes que alguém corra para me corrigir, o valor é <code>15</code> porque o <code>0</code> esta incluso. Porém entendemos que na matemática seria <code>16</code>.</p><hr><p>Existe uma propriedade que garante os números nunca colidam. Isso significa que cada sequência de bit representa apenas uma única coisa, e que o processo de decimal para bits, e de bits para decimal sempre retorna o mesmo valor. Esta propriedade é matemática e foge do escopo do post.</p><h2 id="programmer404-content-encoding-signed-numbers">Encoding signed numbers</h2><p>Signed numbers representa números do conjunto de números inteiros. Portanto isto engloba números negativos, aumentando a complexidade da coisa.</p><p>Apesar de relativamente mais difícil de entender conceitualmente, a ideia é praticamente a mesma. A diferença reside no bit mais a esquerda.</p><pre><code class="hljs language-txt">1001</code></pre><p>Para quem teve o trabalho de mapear sequências de bits do 0 até o <code>15</code>, assim como eu, sabe que <code>1001</code> é o mesmo que <code>9</code> em decimal. No entanto, quando estamos lidando com números <em>signed</em> , não é <code>9</code>, mas <code>-7</code>.</p><p>A cabeça pode está explodindo agora, mas calma, relaxa.</p><p>Antes de mais nada, é importante ressaltar que, estamos usando um algoritmo específico para este exemplo, o <em>two's complement</em>, que é o mais popular.</p><p>Lembra que eu disse que um bit não significa nada por si só? Agora é o momento de trabalharmos em cima disto!</p><p>Temos uma sequência de <code>4</code> bits. Sabemos que para números <code>unsigned</code>, temos um total de <code>15</code> diferentes sequências de bits, onde cada uma representa um número diferente. Agora pense, temos uma sequência de 4 bits, e agora passamos a representar não só positivos, mas valores negativos também, a minha interpretação sobre estas sequências precisa mudar.</p><p>O bit mais a esquerda determina se o valor é positivo ou negativo. Se o bit for igual a <code>1</code>, o resultado final será negativo. Se for <code>0</code>, valor final será positivo. Na prática, quando estamos trabalhando com <em>signed numbers</em>, ao invés de calcular da seguinte forma <span class="math math-inline">x \times 2^i</span>, calculamos da desta forma o <strong>último bit</strong>: <span class="math math-inline">x \times -2^i</span>.</p><p>Considere o seguinte exemplo:</p><pre><code class="hljs language-txt">1 x 2^0 = 10 x 2^1 = 00 x 2^2 = 01 x -2^3 = -8-8 + 0 + 0 + 1 = -7</code></pre><p>A forma que interpretamos o último bit mudou. Calculamos ele de forma diferente de como faziamos antes. Graças a isto somos capazes de representar números negativos também!</p><h2 id="programmer404-content-detalhes">Detalhes</h2><p>Eu me referi a uma cadeia de bits como <em>sequência de bits</em>, mas o termo comum é <em>bit vector</em>.</p><p><em>signed numbers</em> pode representar apenas metade do que os <em>unsigned numbers</em>. Isto porque não aumentamos ou diminuimos a quantidade de bits, apenas pegamos os mesmos bits e mudamos a nossa interpretação em relação a eles. Considere:</p><p><em>MAX usigned</em> = <code>15</code>;<br><em>MIN usigned</em> = <code>0</code>;<br><em>MAX signed</em> = <code>7</code>;<br><em>MIN signed</em> = <code>-8</code>;</p><p>O valor máximo positivo para <em>signed</em>  é <code>7</code> e não <code>8</code> porque esta sendo considerado também.</p><p>Para que fique de fácil visualização, imagine uma casa. A casa é grande, porém decimos dividir os comôdos entre duas pessoas. Ainda é a mesma casa, mas pessoa <code>X</code> tem acesso a menos espaço que antes agora que <code>Y</code> esta presente.</p><h2 id="programmer404-content-conclusão">Conclusão</h2><p>Como sempre, eu não considero minha explicação adequada como a de um professor, mas espero que ao menos uma pessoa tenha apreciado o que eu trouxe.</p><p>Agradeço pela a leitura até aqui!</p></div>]]></content:encoded>
            <author>Programmer404</author>
        </item>
        <item>
            <title><![CDATA[Fiz uma ferramenta de Lotofácil para o meu pai e acabou ficando boa demais para deixar só com ele.]]></title>
            <link>https://www.tabnews.com.br/ctgargiulo/fiz-uma-ferramenta-de-lotofacil-para-o-meu-pai-e-acabou-ficando-boa-demais-para-deixar-so-com-ele</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/ctgargiulo/fiz-uma-ferramenta-de-lotofacil-para-o-meu-pai-e-acabou-ficando-boa-demais-para-deixar-so-com-ele</guid>
            <pubDate>Thu, 20 Aug 2026 12:35:50 GMT</pubDate>
            <description><![CDATA[Meu pai gosta bastante de Lotofácil e sempre teve o costume de fazer contas de fechamento e desdobramento no papel. Era aquela coisa: várias dezenas anotadas, combinações, contas, conferê...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Meu pai gosta bastante de Lotofácil e sempre teve o costume de fazer contas de fechamento e desdobramento no papel.</p><p>Era aquela coisa: várias dezenas anotadas, combinações, contas, conferência de jogos... e um monte de papel espalhado.</p><p>Um dia parei para entender exatamente o que ele estava fazendo.</p><p>Depois de algumas conversas, comecei a transformar aquilo em código.</p><p>A ideia inicial nem era criar algo público. Eu só queria facilitar a vida dele.</p><p>No fim nasceram duas ferramentas:</p><p>Calculadora de Fechamento da Lotofácil<br><a href="https://valorfinal.com.br/calculadora-fechamento-lotofacil" rel="nofollow">https://valorfinal.com.br/calculadora-fechamento-lotofacil</a></p><p>Calculadora de Desdobramento da Lotofácil<br><a href="https://valorfinal.com.br/calculadora-desdobramento-lotofacil" rel="nofollow">https://valorfinal.com.br/calculadora-desdobramento-lotofacil</a></p><p>As duas são gratuitas.</p><p>O mais engraçado é que meu pai realmente gostou.</p><p>Virou a nova diversão dele. Detalhe ele tem 75 anos.</p><p>Agora ele fica horas colocando dezenas, testando combinações, gerando jogos e depois conferindo os resultados. Basicamente trocou o papel pela ferramenta.</p><p>E para mim acabou sendo um projeto bem legal porque eu não conhecia praticamente nada sobre fechamento e desdobramento de loterias antes disso. Precisei primeiro entender a lógica que ele fazia manualmente para depois conseguir transformar aquilo em uma ferramenta que realmente fosse útil.</p><p>Como já estava funcionando bem para ele, resolvi disponibilizar para todo mundo.</p><p>Se alguém aqui também joga Lotofácil ou tem pai, mãe, avô, amigo que gosta dessas contas, manda para a pessoa testar.</p><p>E se encontrarem alguma coisa que possa ser melhorada, podem falar,toda sugestão é bem-vinda.</p><p>Obrigado</p></div>]]></content:encoded>
            <author>ctgargiulo</author>
        </item>
        <item>
            <title><![CDATA[AI e o problema da responsabilidade]]></title>
            <link>https://www.tabnews.com.br/evertonruan/ia-ou-ai-de-quem-fez</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/evertonruan/ia-ou-ai-de-quem-fez</guid>
            <pubDate>Thu, 20 Aug 2026 11:03:07 GMT</pubDate>
            <description><![CDATA[Muitas são as preocupações de que a AI irá substituir os humanos. Bem, o mesmo aconteceu com outras tecnologias no passado. Porém, as preocupações de agora são até validas. Porque a AI co...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Muitas são as preocupações de que a AI irá substituir os humanos. Bem, o mesmo aconteceu com outras tecnologias no passado.</p><p>Porém, as preocupações de agora são até validas. Porque a AI consegue fazer coisas <strong>no nível humano, e até melhor</strong>! É diferente de qualquer outra coisa antiga, em que era só uma ferramenta e o ser humano no controle é quem dava a forma. Sabe, agora a AI consegue fazer coisas no nível humano <em>quando</em> um humano dá um comando a ela. Ops… peraí. <em>Quando um humano dá um comando a ela</em>? Sim e aí o humano não precisa pensar, ele delega a AI, que vai tomar todas as decisões por ele, e quando algo dá errado, a culpa é <em>dela</em>. Ops.. como é? Pois é, parece que estamos vivendo em um momento delicado.</p><blockquote><p>Uma AI consegue fazer coisas no nível humano quando um humano dá um comando a ela</p></blockquote><p>Ao mesmo tempo, a AI, consegue nos substituir, mas ao mesmo tempo não consegue. Parece que falta alguma coisa. E parece que a palavra é “<strong>decisão</strong>”. Essa palavra tem peso. Afinal, se algo existe, é porque houve alguma decisão, pequena ou grande, mas houve. E se houve uma decisão, houve um responsável. Se alguém é responsável, então a ação parte dele. Pensar assim é interessante. Por exemplo, a AI desenha uma linda “pintura” onde há uma casa e uma linda paisagem, e você vê em uma rede social. Quem fez isso? Alguém diz: a AI. Porém ela não faria isso se não tivesse alguém que tomou uma decisão de propositalmente transformar uma onda cerebral (ou seja, um pensamento) em uma ação. E por mais ínfima que pareça, essa é uma decisão interessante. Passou por:</p><ol><li>Ter um entendimento do que é uma AI;</li><li>Escolher uma dentre tantas;</li><li>Formular um prompt;</li><li>Por fim, clicar em “Enviar";</li></ol><p>Mas o fim está longe de terminar. Foi preciso:</p><ol start="5"><li>Escolher propositalmente uma rede social;</li><li>Fazer o upload do arquivo, talvez (6.1) escrever alguma legenda e então</li><li>Clicar em “Postar”.</li></ol><p>Você viu? E ainda tem gente que diz que foi a AI que fez.</p><p>Mas claro que tudo parece muito óbvio. Teve mesmo que ter um humano por trás. O humano é que é o problema, não a tecnologia. E aí podemos ampliar esse exemplo para qualquer outra coisa que foi a AI que fez. Se algo existe é porque houve uma decisão. Se houve uma decisão, alguém foi responsável. Desde uma função em algum programa a um vídeo de gatinho tomando leite. E o que será que podemos dizer dos agentes de IA, que tomamam incontáveis decisões "sem um responsável"?</p><blockquote><p>A IA não faria algo se não tivesse alguém que tomou uma decisão de propositalmente transformar um pensamento em uma ação</p></blockquote><p>Mas talvez estamos só divagando aqui. Pois não chegamos em lugar algum. Às vezes, só o fato de pensar e analisar algo, já é melhor do que um resultado concreto. Afinal qualquer ação começa no pensamento.</p><p>Mas a pergunta é:</p><h2 id="evertonruan-content-a-ai-pode-substituir-humanos-olha-depende">A AI pode substituir humanos? Olha, depende.</h2><p>Veja só… é na questão da responsabilidade.</p><p>É claro que com a evolução da tecnologia, muitas funções acabam sendo centralizadas em uma pessoa. Isso é algo natural.</p><p>Imagine quantas tarefas cotidianas do seu trabalho ou vida pessoal a AI está agilizando. Talvez você antes demorava horas para fazer algo. Agora leva minutos. Isso é algo natural. Não escrevemos mais tanto a mão, nós digitamos e agora pedimos pra IA escrever. Levamos menos tempo. (Embora nesse texto, IA nenhuma tocou)</p><p>Mas veja o seguinte cenário: uma empresa pode até reduzir seu pessoal, afinal a AI reduz o tempo das coisas.</p><p>Porém, veja essa situação: um designer pede pra AI fazer uma função de um sistema complexo. A AI implementou, ele testou e tudo funcionou. Perfeito! Não precisamos mais de um programador! Bem, uma semana depois aquela função começa a bugar e o sistema quebra. O designer vai lá, faz outro prompt. A AI conserta. Tudo funcionando. E isso acontece algumas vezes. Dali uns dias, o sistema até não quebrou mais, porém algumas coisas não estão funcionando como antes. Alguns comportamentos estão estranhos. Outras coisas estão sendo salvas, mas o banco de dados está com bugs. Alguns dispositivos dão erro, enquanto em outros aparentemente está certo.. Parece que está tudo meio “mexido”. E agora? quem vai arrumar essa bagunça? (parece que o agente inteligente artificial tomou algumas liberdades)</p><p>Bem, chegamos numa das extremidades da AI. Ela até faz. Mas quem deu o comando é responsável. Quem deu o comando sabia o que estava fazendo? Ele tinha em mente as limitações e detalhes? Nesse caso, não. Apenas um conhecimento superficial. E de quem é a responsabilidade? Da AI, ou “ai” de quem fez?</p><p>Se fosse um programador com conhecimento de causa, tudo seria diferente. Poderia dar problemas? Com certeza. (e sempre tem bugs de todas as espécies). Mas ele saberia usar um log para investigar, e ir até a causa raiz do problema.</p><p>Poderíamos inverter essa situação para um programador backend que pede à AI fazer um design de uma landing page. Mas ele não sabe nada sobre branding ou CTA, ou como se deve estruturar uma página.</p><p>Novamente, isso tudo poderia ser concentrado em uma pessoa — desde que saiba o que está fazendo. Pois a AI não sabe. Ela só obedece o que alguém pede. E alguém sim pediu.</p><p>Então, a AI pode substituir humanos? Depende. Eu acredito fortemente que os que tomam decisão (pequena ou grande) sem saber, serão substituídos por aqueles que entendem do assunto e usam AI para fazer o trabalho braçal</p></div>]]></content:encoded>
            <author>evertonruan</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Criei QA Gates pra rodar no seu rep vibecodado]]></title>
            <link>https://www.tabnews.com.br/PedroOSilva/criei-qa-gates-pra-rodar-no-seu-rep-vibecodado</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/PedroOSilva/criei-qa-gates-pra-rodar-no-seu-rep-vibecodado</guid>
            <pubDate>Thu, 20 Aug 2026 10:42:37 GMT</pubDate>
            <description><![CDATA[Passando aqui pra compartilhar um repositório que particularmente eu acredito, fiz um teste de um framework que criei e funcionou muito bem, e achei tão bom e tão chato que estou aqui pas...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Passando aqui pra compartilhar um repositório que particularmente eu acredito, fiz um teste de um framework que criei e funcionou muito bem, e achei tão bom e tão chato que estou aqui passando pra compartilhar com vocês e coletar feedback também.</p><p>Basicamente o que eu fiz é o dever de casa que todo dev deveria fazer, mas na prática não é o que fazemos, muitas vezes não temos paciência em aplicar git hooks e técnicas de CI e CD, então basicamente fiz um rep onde você pode instalar gates de QA (Quality Assurance) na seu projeto e pronto.</p><p>Esse trabalho resolve isso de algumas maneiras:</p><ol><li>System prompts, o mínimo.</li><li>Git hooks: executa scripts de validação localmente, pra verificar segredos e complexidade de código.</li><li>Github Actions:</li><li><ol><li>QA structural gates: duplicação de código, complexidade assintótica limitada, hardcoded secrets.</li></ol></li><li><ol start="2"><li>Megalinter.</li></ol></li><li><ol start="3"><li>Testes de unidade automatizados.</li></ol></li></ol><p>A grande ideia é não confiar na IA pra garantir qualidade, e sim usar indicadores estáticos de qualidade, assim o commit só sobe se seguir um padrão semantico de nome e passar nos testes locais, a PR só aprova se a complexidade ciclomática estiver abaixo de 10, se o arquivo tiver menos de 300 linhas, e se não tiverem mais de 6 funções em um mesmo arquivo.</p><p>É claro que todos esses indicadores são adaptáveis a cada projeto, mas essa é uma maneira aceitável de garantir o mínimo. Isso torna o trabalho revisável e melhora muito a manutenção do código. Você basicamente força a IA a não ser relaxada (e ela tenta).</p><p>Por fim, esse rep não resolve qualidade sozinho, mas te ajuda com o mínimo, ter prompts forçando a tua IA a não escrever código que não responde as tuas regras de negócio e forçando a ter o mínimo de padrões código limpo.</p><p>Obs: como disse, precisa ainda garantir que o código atende as regras de negócio que você tem, e isso é trabalho só seu. E lançar esse rep em um projeto já em andandamento pode te levar a um ciclo de refatoração infindável, por isso veja quais gates fazem sentido serem ativados no seu projeto.</p><p>Aqui o link: <a href="https://github.com/PedroOSilv/qagates">https://github.com/PedroOSilv/qagates</a></p><p>Quero ouvir de vocês o que pensam disso.</p><p>Salve Lucas Montano, seu vídeo me inspirou a fazer esse projeto ...</p><p>Se você leu até aqui, obrigado pela atenção!</p></div>]]></content:encoded>
            <author>PedroOSilva</author>
        </item>
        <item>
            <title><![CDATA[oh-my-agent: refactor guards cross-vendor e avaliação isolada]]></title>
            <link>https://www.tabnews.com.br/gracefullight/oh-my-agent-refactor-guards-cross-vendor-e-avaliacao-isolada</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/gracefullight/oh-my-agent-refactor-guards-cross-vendor-e-avaliacao-isolada</guid>
            <pubDate>Thu, 20 Aug 2026 02:05:01 GMT</pubDate>
            <description><![CDATA[O oh-my-agent 12.4.0 acaba de receber um refactor guard cross-vendor e avaliação isolada de harness. Quando um agent edita linhas demais em um único arquivo sem refatorar, o runtime agora...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>O oh-my-agent 12.4.0 acaba de receber um refactor guard cross-vendor e avaliação isolada de harness. Quando um agent edita linhas demais em um único arquivo sem refatorar, o runtime agora bloqueia o evento de parada e despacha um refactor engineer dedicado para limpar a bagunça antes de devolver o controle.</p><h2 id="gracefullight-content-novidades">Novidades</h2><ul><li><strong>Cross-vendor refactor guard</strong>: O novo hook <code>refactor_guard</code> rastreia o orçamento de linhas entre as ferramentas de edição. Se um agent ultrapassar 500 linhas em um único arquivo, o hook bloqueia a finalização e despacha o <code>refactor-engineer</code>. Isso funciona em todos os 9 vendors suportados.</li><li><strong>Isolated harness evaluation</strong>: O comando <code>oma harness</code> agora compara overlays <code>.agents</code> com escopo fechado em workspaces temporários pareados, usando verificações determinísticas de artefatos e record and replay vinculados a hashes.</li><li><strong>Agent Plugins support</strong>: Um <code>git clone</code> padrão do repositório agora atua como um pacote instalável do Agent Plugins 1.0.0, expondo <code>plugin.json</code>, <code>mcp.json</code> e a árvore de skills diretamente na raiz do repositório.</li><li><strong>Translation profiles</strong>: O <code>oma-translator</code> agora usa perfis por idioma (<code>en</code>, <code>ko</code>, <code>ja</code>, <code>zh</code>) para isolar registros de sistema e regras de tipografia da taxonomia de padrões compartilhada.</li></ul><p>Controlar o contexto de um agent exige precisão. O novo refactor guard garante que grandes mudanças sejam forçadas a passar por uma fase de refatoração antes do fim da sessão, mantendo os arquivos manuteníveis.</p><h2 id="gracefullight-content-correções">Correções</h2><ul><li>Decisões de SCM, como splits de commit e merges, não são mais gravadas como fatos duráveis no armazenamento de memória do agent. Elas já estão no histórico do git, e ignorá-las evita que metadados do repositório ofusquem as reais decisões cross-session.</li><li>O comando <code>oma link</code> agora renderiza a união de hooks de vendors e subagents para arquivos compartilhados como o <code>AGENTS.md</code>, impedindo que o arquivo fique alternando de estado quando diferentes vendors disparam o merge.</li><li>Servidores MCP adicionados pelo usuário em <code>.cursor/mcp.json</code> são preservados durante as atualizações. A CLI agora faz o merge dos servidores que ela gerencia em vez de sobrescrever o arquivo inteiro.</li><li>As verificações de autenticação do OpenCode agora derivam o provedor corretamente a partir da especificação do modelo, resolvendo falsos reportes de estado offline quando usuários se autenticavam com provedores alternativos.</li></ul><h2 id="gracefullight-content-melhorias">Melhorias</h2><ul><li>Substituímos as alegações inatingíveis de orçamento de contexto na documentação por custos de tokens medidos e reprodutíveis. O design de skills em duas camadas evita cerca de 75% do overhead de carregamento de skills em tarefas complexas.</li><li>Limitamos a proteção de Single Source of Truth (SSOT) estritamente aos arquivos de definição. Os agents agora recebem instruções explícitas de que os outputs em <code>.agents/results/</code> são esperados, impedindo que deletem o estado de handoff da sessão na tentativa de restaurar a proteção.</li><li>As traduções em coreano em todas as 22 páginas foram sincronizadas para paridade com a fonte em inglês, normalizando os registros de instrução e corrigindo desvios estruturais legados.</li></ul><h2 id="gracefullight-content-instalação">Instalação</h2><pre><code class="hljs language-bash"><span class="hljs-comment"># macOS / Linux</span>curl -fsSL https://raw.githubusercontent.com/first-fluke/oh-my-agent/main/cli/install.sh | bash</code></pre><pre><code class="hljs language-powershell"># Windows (PowerShell)irm https://raw.githubusercontent.com/first-fluke/oh-my-agent/main/cli/install.ps1 | iex</code></pre><p>O oh-my-agent é construído para equipes que orquestram mais do que escrevem prompts. O próximo passo: primitivas de rollback em múltiplos turnos para loops de raciocínio travados.</p><blockquote><p>Texto original (em inglês): <a href="https://dev.to/gracefullight/oh-my-agent-cross-vendor-refactor-guards-and-isolated-eval-4c9o" rel="nofollow">https://dev.to/gracefullight/oh-my-agent-cross-vendor-refactor-guards-and-isolated-eval-4c9o</a></p><p><a href="https://github.com/first-fluke/oh-my-agent">https://github.com/first-fluke/oh-my-agent</a></p></blockquote></div>]]></content:encoded>
            <author>gracefullight</author>
        </item>
        <item>
            <title><![CDATA[Como Publicar uma Biblioteca .NET no NuGet.org]]></title>
            <link>https://www.tabnews.com.br/lzocateli/como-publicar-uma-biblioteca-net-no-nuget-org</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/lzocateli/como-publicar-uma-biblioteca-net-no-nuget-org</guid>
            <pubDate>Thu, 20 Aug 2026 02:01:26 GMT</pubDate>
            <description><![CDATA[Introdução# Publicar uma biblioteca .NET no NuGet.org não é apenas empacotar um projeto e enviar o .nupkg para o servidor. O ponto mais importante é tratar a API pública como um contrato...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><h2 id="lzocateli-content-introdução">Introdução#</h2><p>Publicar uma biblioteca .NET no NuGet.org não é apenas empacotar um projeto e enviar o <code>.nupkg</code> para o servidor. O ponto mais importante é tratar a API pública como um contrato que outras pessoas e outros times vão consumir. Se eu publicar uma API sem pensar em compatibilidade, o problema não fica só no pacote: ele se espalha para dependências, pipelines e aplicações que dependem do mesmo assembly. Por isso, a publicação segura combina três pilares: contrato estável, versionamento consciente e validação real do artefato em um ambiente de consumidor separado.</p><p>A ideia deste artigo é explicar a jornada completa de uma biblioteca .NET: preparar a API, decidir o tipo de distribuição, validar localmente, publicar em um ambiente de teste e, por fim, divulgar a versão estável em nuget.org. Também vou mostrar quando o pacote deve ficar em um feed público e quando ele precisa ir para Azure Artifacts ou GitHub Packages. O objetivo é dar uma visão prática para quem está publicando o primeiro pacote ou tentando organizar a distribuição interna da empresa.</p><p>Se você já usou pacotes NuGet em projetos de aplicação, sabe que o fluxo de consumo parece simples na superfície: restaurar, compilar e executar. O ponto delicado é o contrato. A biblioteca que parece compatível no build pode gerar erros de runtime quando o pacote é consumido em um projeto externo com metadados ou dependências diferentes. Por isso, vale separar a publicação em etapas: feed local, ambiente de teste do NuGet, publicação pública e feeds privados. O percurso é simples de entender, mas a disciplina é o que evita retrabalho e quebrar clientes.</p><blockquote><p><strong>⚠️ Atenção:</strong> o ambiente de teste do NuGet não substitui um feed privado. Ele serve para validar o fluxo de publicação antes de subir a versão definitiva. Azure Artifacts e GitHub Packages existem para distribuição interna persistente e autenticada.</p></blockquote><h2 id="lzocateli-content-pré-requisitos">Pré-requisitos#</h2><p>Antes de empacotar o primeiro pacote, eu gosto de validar alguns preceitos básicos para evitar a sensação de que a publicação foi bem-sucedida e, depois, o pacote não ficou útil para quem vai consumir. Em primeiro lugar, você precisa do .NET SDK instalado e funcional; a checagem mínima é <code>dotnet --info</code>. O lado operacional também importa: uma conta no nuget.org e uma API key com escopo limitado para o pacote. Isso reduz o impacto de vazamento ou uso indevido.</p><p>O próximo passo é separar o cenário de distribuição. Se o pacote é público, um fluxo de publicação no nuget.org exige revisão e indexação. Se ele é interno, a melhor alternativa costuma ser Azure Artifacts ou GitHub Packages, com autenticação e controle de acesso. Em qualquer caso, o ideal é nunca expor tokens em arquivos versionados ou em comandos de terminal que fiquem no histórico do shell.</p><p>Também vale deixar claro que esse processo não é só de “empacotar e publicar”. É de “empacotar e validar”. A rotina de publicação tem um exercício importante: criar um projeto consumidor separado e instalar o pacote que acabou de ser gerado. Só assim é possível verificar se README, dependências, arquivos e metadados estão corretos.</p><h2 id="lzocateli-content-defina-o-contrato-e-a-estratégia-de-versionamento-semver">Defina o Contrato e a Estratégia de Versionamento SemVer#</h2><p>A publicação de bibliotecas .NET exige que o versionamento seja tratado como parte do contrato público. O SemVer é a convenção mais usada no ecossistema e define que a versão siga a estrutura <code>MAJOR.MINOR.PATCH</code>. Cada componente comunica algo diferente:</p><ul><li><code>MAJOR</code> indica alteração incompatível de API pública</li><li><code>MINOR</code> indica adição de funcionalidade compatível</li><li><code>PATCH</code> indica correção de defeito sem mudar a API<br>Não é só uma convenção estética. O número da versão comunica ao consumidor o risco da atualização. Se eu remover um método público ou mudar o comportamento de forma que um cliente dependa do antigo contrato, a mudança é de <code>MAJOR</code>. Se eu adiciono um novo método a uma API que não quebra ninguém, a mudança é de <code>MINOR</code>. Se eu corrijo um bug internalmente sem alterar a interface, a mudança é de <code>PATCH</code>.</li></ul><p>Eu também gosto de reforçar a importância das versões pré-release. Em bibliotecas, <code>1.5.0-beta.1</code>, <code>1.5.0-rc.1</code> e <code>1.6.0-alpha.3</code> são úteis para validar uma funcionalidade antes de o pacote ser publicado como estável. Isso reduz o risco de anunciar uma versão definitiva sem testar os impactos reais. A regra mais importante é simples: uma versão publicada é imutável. Se ela estiver errada, você corrige em uma nova versão, não reescreve a antiga.</p><table><thead><tr><th>Mudança no contrato público</th><th>Próxima versão</th><th>Exemplo</th></tr></thead><tbody><tr><td>Remover método ou alterar comportamento incompatível</td><td>MAJOR</td><td>1.4.2 → 2.0.0</td></tr><tr><td>Adicionar método sem quebrar consumidores</td><td>MINOR</td><td>1.4.2 → 1.5.0</td></tr><tr><td>Corrigir defeito sem alterar contrato</td><td>PATCH</td><td>1.4.2 → 1.4.3</td></tr><tr><td>Validar versão futura</td><td>Sufixo pré-release</td><td>1.5.0-beta.1</td></tr></tbody></table><blockquote><p><strong>💡 Dica:</strong> o chamado SemVer 2 também permite pré-releases com rótulos e regras de normalização que o NuGet aceita. Isso é importante quando você quer testar uma nova funcionalidade com consumidores que ainda não querem depender dela em produção.</p></blockquote><h2 id="lzocateli-content-prepare-a-biblioteca-para-distribuição">Prepare a Biblioteca para Distribuição#</h2><p>Uma biblioteca pode ser pequena e ainda assim precisa de itens mínimos de qualidade para ser publicada. O projeto de exemplo usado neste artigo está no repositório de exemplos do blog e chama-se <code>Contoso.TextRules</code>. Ele expõe regras reutilizáveis para validação e normalização de texto. A estrutura do pacote é simples, mas a forma como ele é descrito no <code>.csproj</code> é o que permite que o NuGet gere uma página útil no site e que o pacote seja reconhecido corretamente pelo tooling do .NET.</p><p>No arquivo de projeto, alguns metadados são fundamentais:</p><ul><li><code>PackageId</code> — identifica o pacote</li><li><code>Version</code> — define a versão da distribuição</li><li><code>Authors</code> — informa autoria</li><li><code>Description</code> — resumo útil para busca e descoberta</li><li><code>PackageTags</code> — pesquisa e classificação no NuGet.org</li><li><code>PackageReadmeFile</code> — inclui README dentro do pacote</li><li><code>PackageLicenseExpression</code> — licença SPDX para transparência</li><li><code>RepositoryUrl</code> e <code>RepositoryType</code> — ajuda na navegação e rastreabilidade<br>Além disso, vale empacotar símbolos quando a biblioteca é relevante para depuração e diagnósticos. O <code>dotnet pack</code> também consegue incluir arquivos do pacote, como <code>README.md</code> e <code>LICENSE</code>, o que melhora bastante a experiência de quem vai consumir a biblioteca.</li></ul><p>A separação entre abstração e implementação também é relevante como boa prática. O NuGet tem uma cultura muito forte de pacotes pequenos e de responsabilidade clara. Em projetos maiores, é comum separar um contrato da implementação: por exemplo, projetar uma biblioteca de abstração com interfaces e contratos e outra biblioteca com a implementação concreta. Isso evita que consumidores dependam de todo o conjunto de funcionalidades e permite que a API pública evolua com mais clareza. Isso não é obrigatório para todo projeto pequeno, mas é um padrão útil para bibliotecas de plataforma ou componentes de domínio.</p><p><strong>📂 Código Fonte:</strong> O exemplo completo está disponível no repositório de exemplos do blog:<br><code>BlogSamples/Packaging/NuGetPublish/</code></p><h2 id="lzocateli-content-empacote-e-valide-localmente-antes-do-push">Empacote e Valide Localmente Antes do Push#</h2><p>Depois de preparar a biblioteca, o próximo passo é empacotar o artefato em modo Release. Isso é o ponto em que eu verifico se o projeto realmente gera um pacote completo. O comando principal é:</p><pre><code class="hljs language-bash">dotnet pack src/BlogSamples/Packaging/NuGetPublish/Contoso.TextRules/Contoso.TextRules.csproj -c Release</code></pre><p>O resultado esperado é um <code>.nupkg</code> na pasta <code>bin/Release</code>. Mas o simples fato de existir um arquivo não basta. Eu sempre inspeciono o pacote para confirmar que ele contém o README, a licença e as dependências corretas. O pacote pode compilar e ainda assim ter metadados incompletos ou arquivos faltando, o que costuma aparecer quando a biblioteca é consumida por um projeto externo.</p><p>A validação mais importante é consumir o pacote em outro projeto. Isso muda o cenário: o consumidor não está dentro do mesmo repositório nem do mesmo assembly. Ele instala o pacote via <code>dotnet add package</code> ou via feed local, e aí aparecem erros de integração que os testes da própria biblioteca não capturam. Um erro clássico é um arquivo que fica ausente no pacote ou um README que não foi incluído corretamente. O pacote precisa funcionar como um item distribuído, não apenas como um projeto compilado localmente.</p><h2 id="lzocateli-content-valide-no-ambiente-de-teste-do-nuget">Valide no Ambiente de Teste do NuGet#</h2><p>Depois que o pacote está funcionando localmente, o próximo ambiente natural é o teste do NuGet. O endereço oficial é <code>https://int.nugettest.org</code>. Esse ambiente foi criado para validar o fluxo de publicação antes do envio ao feed público. O objetivo não é substituir o processo de produção, e sim confirmar que o pacote pode ser enviado, restaurado e consumido em um cenário semelhante ao real.</p><p>Em geral, o fluxo é simples: configurar uma fonte de pacote nomeada para o ambiente de teste, autenticar com o usuário e enviar a versão. Com o pacote em mãos, um projeto consumidor diferente pode restaurá-lo e executar o código real. Essa validação reduz o risco de uma falha de packaging ou de uma API pública que ainda não está pronta para o feed público.</p><blockquote><p><strong>ℹ️ Informação:</strong> a documentação oficial do NuGet usa <code>int.nugettest.org</code> como ambiente para testar a publicação antes do <code>nuget.org</code>. Pacotes enviados para esse ambiente podem não ser preservados, por isso ele é útil para validação, não para distribuição persistente.</p></blockquote><h2 id="lzocateli-content-publique-uma-versão-estável-no-nugetorg">Publique uma Versão Estável no NuGet.org#</h2><p>Quando a API pública está pronta e o pacote passou pela validação de consumo, a próxima etapa é publicar a versão estável em nuget.org. Esse processo exige uma API key do NuGet com escopo mínimo: o ideal é restringir o token ao prefixo do pacote e ao tempo de validade necessário. Isso reduz muito o impacto de vazamento de credenciais.</p><p>O comando mais comum é o <code>dotnet nuget push</code>, geralmente com o pacote já empacotado em Release:</p><pre><code class="hljs language-bash">dotnet nuget push ./artifacts/Contoso.TextRules.1.0.0.nupkg --api-key <span class="hljs-variable">$NUGET_API_KEY</span> --<span class="hljs-built_in">source</span> https://api.nuget.org/v3/index.json</code></pre><p>Na prática, a publicação no nuget.org não é o fim do processo: ela também dispara a indexação e a disponibilidade do pacote para busca e restauração. O pacote passa por validações do NuGet e, em alguns casos, demora alguns minutos para aparecer como disponível para instalação. Isso é normal e faz parte do fluxo oficial. Também vale deixar claro que a decisão de usar <code>unlist</code> faz sentido para remover uma versão da visibilidade pública sem apagá-la por completo; já “excluir” uma versão não é a abordagem recomendada para distribuir um artefato público de forma segura.</p><p>A regra mais importante é reservar a primeira estável <code>1.0.0</code> para o momento certo. Em bibliotecas, eu prefiro validar a API em pré-release primeiro. Isso dá tempo de ajustar comportamento sem a pressão de “uma versão potencialmente quebrada” já disponível publicamente.</p><h2 id="lzocateli-content-distribua-bibliotecas-internas-com-azure-artifacts-e-github-packages">Distribua Bibliotecas Internas com Azure Artifacts e GitHub Packages#</h2><p>Nem todo pacote merece ir para nuget.org. Quando a biblioteca é interna, um feed privado é a opção mais segura e fácil de operar. Azure Artifacts e GitHub Packages atendem a esse cenário com autenticação e controle de acesso. A decisão geralmente depende da assinatura da plataforma usada pela organização.</p><h3 id="lzocateli-content-azure-artifacts">Azure Artifacts#</h3><p>O Azure Artifacts funciona muito bem quando a organização já usa Azure DevOps e tem pipelines centralizados. O feed de pacotes fica associado à organização e ao projeto do Azure DevOps, e a autenticação pode ser integrada a pipelines e regras de segurança. Para times usando Azure como plataforma principal, essa é uma forma natural de publicar bibliotecas internas com políticas de acesso e revisão de versões.</p><h3 id="lzocateli-content-github-packages">GitHub Packages#</h3><p>O GitHub Packages se encaixa bem em times que já vivem dentro do GitHub. A autenticação usa token com escopo e permissões mínimas, e a integração com GitHub Actions costuma ser direta. Isso facilita muito a publicação de componentes internos, bibliotecas compartilhas e dependências para repositórios privados e públicos em diferentes fluxos de desenvolvimento.</p><table><thead><tr><th>Critério</th><th>Azure Artifacts</th><th>GitHub Packages</th></tr></thead><tbody><tr><td>Plataforma principal</td><td>Azure DevOps</td><td>GitHub</td></tr><tr><td>Integração de CI</td><td>Azure Pipelines</td><td>GitHub Actions</td></tr><tr><td>Controle de acesso</td><td>Organização e projeto</td><td>Organização e repositório</td></tr><tr><td>Melhor cenário</td><td>Times centralizados no Azure DevOps</td><td>Times que já usam GitHub</td></tr></tbody></table><blockquote><p><strong>⚠️ Atenção:</strong> nunca deixe tokens em <code>NuGet.Config</code> versionado. O arquivo de configuração pode apontar para diferentes fontes, mas os segredos devem sair do repositório e entrar por variáveis de ambiente ou secret stores do CI.</p></blockquote><h2 id="lzocateli-content-automatize-releases-sem-quebrar-consumidores">Automatize Releases sem Quebrar Consumidores#</h2><p>A automação de publicação é importante, mas ela precisa ser um guard rail, não um atalho. O fluxo ideal de CI/CD para uma biblioteca .NET é: validar testes, empacotar, verificar se a versão já existe no feed e só então publicar. Isso evita que uma tentativa de push reescreva uma versão já publicada ou publique um pacote quebrado para o feed errado.</p><p>Uma boa estratégia é separar release e publicação em dois momentos. O processo de tag e changelog fica em Git; a publicação de pré-release pode ir para feed privado ou ambiente de teste; a versão estável vai para nuget.org somente após revisão de compatibilidade. Isso ajuda a manter o controle da API pública e faz com que a decisão de publicar uma nova versão seja uma decisão mais consciente.</p><p>Em pipelines, a regra é proteger os segredos. O principal é manter o token em um secret do CI, usá-lo em um passo específico de publish e restringir as permissões. O código da biblioteca pode ser automático, mas a decisão de liberar uma nova versão estável continua sendo algo que exige atenção humana e documentação de breaking change.</p><h2 id="lzocateli-content-exemplo-prático">Exemplo Prático#</h2><p>Vou usar o mesmo cenário do projeto de exemplo: uma biblioteca chamada <code>Contoso.TextRules</code> com regras de validação reutilizáveis. O objetivo é demonstrar a parte do contrato: a API pública fica estável, a versão de pacote inicia como <code>1.0.0-alpha.1</code>, e a promoção para <code>1.0.0</code> acontece depois que a biblioteca é validada em um ambiente de consumidor separado.</p><p>Primeiro, a biblioteca em si. O trecho principal mostra como a API pública é simples e previsível:</p><pre><code class="hljs language-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">BlogSamples.Packaging.NuGetPublish</span>;<span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TextRuleSet</span>{    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-built_in">bool</span> <span class="hljs-title">IsValidEmail</span>(<span class="hljs-params"><span class="hljs-built_in">string</span> <span class="hljs-keyword">value</span></span>)</span>    {        ArgumentException.ThrowIfNullOrWhiteSpace(<span class="hljs-keyword">value</span>);        <span class="hljs-keyword">return</span> <span class="hljs-keyword">value</span>.Contains(<span class="hljs-string">'@'</span>)            &#x26;&#x26; <span class="hljs-keyword">value</span>.Contains(<span class="hljs-string">'.'</span>)            &#x26;&#x26; <span class="hljs-keyword">value</span>.IndexOf(<span class="hljs-string">'@'</span>, StringComparison.Ordinal) > <span class="hljs-number">0</span>;    }    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> <span class="hljs-title">NormalizeWhitespace</span>(<span class="hljs-params"><span class="hljs-built_in">string</span> <span class="hljs-keyword">value</span></span>)</span>    {        ArgumentException.ThrowIfNullOrWhiteSpace(<span class="hljs-keyword">value</span>);        <span class="hljs-keyword">return</span> <span class="hljs-built_in">string</span>.Join(<span class="hljs-string">' '</span>, <span class="hljs-keyword">value</span>.Split(<span class="hljs-string">' '</span>, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries));    }}</code></pre><p><strong>📂 Código Fonte:</strong> O exemplo completo está disponível no repositório de exemplos do blog:<br><code>BlogSamples/Packaging/NuGetPublish/Contoso.TextRules/</code></p><p>Em seguida, acrescento os metadados importantes para o pacote:</p><pre><code class="hljs language-xml"><span class="hljs-tag">&#x3C;<span class="hljs-name">Project</span> <span class="hljs-attr">Sdk</span>=<span class="hljs-string">"Microsoft.NET.Sdk"</span>></span>  <span class="hljs-tag">&#x3C;<span class="hljs-name">PropertyGroup</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">TargetFramework</span>></span>net10.0<span class="hljs-tag">&#x3C;/<span class="hljs-name">TargetFramework</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">PackageId</span>></span>Contoso.TextRules<span class="hljs-tag">&#x3C;/<span class="hljs-name">PackageId</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">Version</span>></span>1.0.0-alpha.1<span class="hljs-tag">&#x3C;/<span class="hljs-name">Version</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">PackageReadmeFile</span>></span>README.md<span class="hljs-tag">&#x3C;/<span class="hljs-name">PackageReadmeFile</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">PackageLicenseExpression</span>></span>MIT<span class="hljs-tag">&#x3C;/<span class="hljs-name">PackageLicenseExpression</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">RepositoryUrl</span>></span>https://github.com/lzocateli/blog-zocateli-sample<span class="hljs-tag">&#x3C;/<span class="hljs-name">RepositoryUrl</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">RepositoryType</span>></span>git<span class="hljs-tag">&#x3C;/<span class="hljs-name">RepositoryType</span>></span>  <span class="hljs-tag">&#x3C;/<span class="hljs-name">PropertyGroup</span>></span><span class="hljs-tag">&#x3C;/<span class="hljs-name">Project</span>></span></code></pre><p>A geração do pacote acontece em Release:</p><pre><code class="hljs language-bash">dotnet pack src/BlogSamples/Packaging/NuGetPublish/Contoso.TextRules/Contoso.TextRules.csproj -c Release</code></pre><p>Para consumo em um projeto separado, eu também gosto de configurar uma fonte local ou de teste e instalar o pacote em um consumidor mínimo:</p><pre><code class="hljs language-bash">dotnet new classlib -n Contoso.TextRules.Consumer<span class="hljs-built_in">cd</span> Contoso.TextRules.Consumerdotnet add package Contoso.TextRules --version 1.0.0-alpha.1 --<span class="hljs-built_in">source</span> /caminho/para/o/feed</code></pre><p>Esse passo é essencial. Ele confirma que a biblioteca não depende apenas do projeto em que ela foi compilada, mas do artefato que será entregue ao consumidor final. Depois da validação, a promoção para <code>1.0.0</code> fica muito mais segura e a decisão de publicar em nuget.org passa a ser uma escolha tecnológica, não só uma sensação de “está funcionando”.</p><h2 id="lzocateli-content-dicas-e-boas-práticas">Dicas e Boas Práticas#</h2><ul><li><strong>Trate a API pública como contrato.</strong> Qualquer alteração de assinatura, comportamento observável ou semântica documentada precisa ser avaliada pelo impacto em consumidores antes de escolher a versão SemVer.</li><li><strong>Consuma o <code>.nupkg</code> em outro projeto.</strong> Testar apenas a biblioteca compilada não verifica se o pacote contém README, dependências e assemblies corretos.</li><li><strong>Crie API keys e tokens com escopo mínimo.</strong> Uma credencial limitada ao prefixo do pacote e à operação de push reduz o impacto de vazamento acidental.</li><li><strong>Nunca reutilize uma versão publicada.</strong> Corrija o problema em uma nova versão <code>PATCH</code> ou publique uma nova pré-release; isso preserva reprodutibilidade de restore.</li><li><strong>Separe fontes públicas e privadas no <code>NuGet.Config</code>.</strong> Dê nomes claros às fontes, restrinja mapeamento de pacotes quando apropriado e evite que dependências internas sejam procuradas no nuget.org.</li><li><strong>Automatize, mas preserve revisão.</strong> O CI deve garantir testes e empacotamento repetíveis; a decisão de uma release estável ainda exige revisão de compatibilidade e changelog.</li></ul><hr><p>📖 <strong>Artigo completo com exemplos de código:</strong> <a href="https://zocate.li/posts/2026/publicar-biblioteca-dotnet-nuget/?utm_source=tabnews&#x26;utm_medium=social&#x26;utm_campaign=blog-2026" rel="nofollow">Como Publicar uma Biblioteca .NET no NuGet.org</a></p></div>]]></content:encoded>
            <author>lzocateli</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Jogando WAR de tabuleiro de forma mais rápida]]></title>
            <link>https://www.tabnews.com.br/Leodeymison/jogando-war-de-tabuleiro-de-forma-mais-rapida</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Leodeymison/jogando-war-de-tabuleiro-de-forma-mais-rapida</guid>
            <pubDate>Wed, 19 Aug 2026 23:47:40 GMT</pubDate>
            <description><![CDATA[Normalmente jogar o jogo de tabuleiro WAR é bastante demora por conta das batalhas de dados, pensando nisso, criei usando o cloud um "gerenciador" de WAR, para agilizar as partidas. Confi...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Normalmente jogar o jogo de tabuleiro WAR é bastante demora por conta das batalhas de dados, pensando nisso, criei usando o cloud um "gerenciador" de WAR, para agilizar as partidas. Confira:<br>Online: <a href="https://manager-online-war.vercel.app/" rel="nofollow">https://manager-online-war.vercel.app/</a></p><p>Github: <a href="https://github.com/leodeymison/manager-online-war">https://github.com/leodeymison/manager-online-war</a></p></div>]]></content:encoded>
            <author>Leodeymison</author>
        </item>
        <item>
            <title><![CDATA[Aprendendo a Aprender]]></title>
            <link>https://www.tabnews.com.br/13samuelconradt/aprendendo-a-aprender</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/13samuelconradt/aprendendo-a-aprender</guid>
            <pubDate>Wed, 19 Aug 2026 21:49:27 GMT</pubDate>
            <description><![CDATA[Olá Devs, A um tempo atrás eu estava com um hiperfoco sinistro no Fabio Akita, e fiz algumas anotações e hoje, quis compartilhar com vocês! Aprendendo a Aprender Todo curso online é um tu...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Olá Devs,</p><p>A um tempo atrás eu estava com um hiperfoco sinistro no Fabio Akita, e fiz algumas anotações e hoje, quis compartilhar com vocês!</p><h1 id="13samuelconradt-content-aprendendo-a-aprender">Aprendendo a Aprender</h1><ul><li>Todo curso online é um tutorial ou coisa simples, superficial e não se aprofunda.</li><li>Vocë não pode aprender arte usando um livro passo a passo de como desenhar o naruto, você até vai desenhar o naruto, mas não vai saber desenhar, e talvez nem saber desenhar o mesmo naruto sem o passo a passo.</li><li>Os estagiarios devem entender e aprender a estudar, e não entregar, afinal eles estão ali para aprender, não entregar, se quiser que entrega, contrata um indiano que é o mesmo preço.</li><li>Nenhum funcionario deve fazer algo sem saber, o porque daquilo, como funciona e como fazer.</li><li>Microgerenciamento NÃO EXISTE</li></ul><h1 id="13samuelconradt-content-como-aprender">Como Aprender?</h1><ol><li>Sem aula</li><li>Sem material</li><li>Sem professor<br>Assim se aprende de verdade, batendo a porta na caram se ferrando e aprendendo</li></ol><ul><li>Devemos aprender a formular a pergunta certa, e não ter a resposta certa</li><li>Passamos a vida seguindo passo a passo, e nunca aprendendo algo real</li><li>Tudo tem que ser dificil, para poder assim aprender.</li><li>Você não é sua linguagem de programação</li><li>Aprender = se virar nos 30</li><li>Quem se destaque é aquele que aprende de verdade e se esforça</li></ul><h2 id="13samuelconradt-content-como-realmente-estudar-na-faculdade">Como realmente estudar na faculdade?</h2><ul><li>Defina bem o que estudar (ter clareza)</li><li>Anotar termos para estudar depois, e tudo o que aprender, tentar ensinar para alguém.</li><li>Tire a faculdade da frente</li><li>Crie um site de exercios para praticar</li><li>Defgina como praticar o que aprendeu</li><li>Transforme TUDO em estudos</li><li>Arranjar tempo para estudar, no onibus, no trabalho, no banho, se vira meu!</li><li>Tenha SEMPRE um projeto pessoal</li><li>Ajude os outros</li></ul><h3 id="13samuelconradt-content-agora-o-mais-importante">AGORA O MAIS IMPORTANTE:</h3><ul><li>Defina quem você quer ser;</li><li>Como chegar lá;</li><li>O que preciso para chegar lá;</li></ul><hr><p>Eu não sou responsavel por esses ensinamentos, todos eles vem do Akita, apenas sintetizei algumas coisas para compartilhar por aqui. Fique a vontade para compartilhar por aqui a sua opinião e coisas a acrescentar!</p></div>]]></content:encoded>
            <author>13samuelconradt</author>
        </item>
    </channel>
</rss>