<?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>Sun, 20 Sep 2026 23:30:02 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[E se a inteligência artificial funcionar bem demais?]]></title>
            <link>https://www.tabnews.com.br/ewanderson/e-se-a-inteligencia-artificial-funcionar-bem-demais</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/ewanderson/e-se-a-inteligencia-artificial-funcionar-bem-demais</guid>
            <pubDate>Sun, 20 Sep 2026 23:28:42 GMT</pubDate>
            <description><![CDATA[Pedra de Roseta Durante muitos séculos, qualquer pessoa podia olhar para os símbolos gravados nas paredes, templos e monumentos do antigo Egito. Eles estavam ali. Não tinham sido destruíd...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p><img src="https://thumb.wikimedia.org/wikipedia/commons/thumb/c/c8/Rosetta_Stone_-_front_face_-_corrected_image.jpg/330px-Rosetta_Stone_-_front_face_-_corrected_image.jpg?utm_source=pt.wikipedia.org&#x26;utm_campaign=parser&#x26;utm_content=thumbnail" alt="Pedra de Roseta"></p><p>Durante muitos séculos, qualquer pessoa podia olhar para os símbolos gravados nas paredes, templos e monumentos do antigo Egito. Eles estavam ali. Não tinham sido destruídos. Não tinham sido apagados. Não estavam escondidos. Ainda assim, a tradição capaz de lê-los havia desaparecido.</p><p>Os hieróglifos haviam sobrevivido. A informação permanecia fisicamente preservada enquanto a capacidade humana de interpretá-la se perdia. Foi preciso encontrar uma ponte.</p><p>A Pedra de Roseta continha essencialmente a mesma mensagem escrita em sistemas diferentes. Um deles, o grego antigo, ainda podia ser compreendido. A partir dessa ligação, tornou-se possível reconstruir gradualmente o significado de uma linguagem que durante séculos esteve diante dos nossos olhos sem que soubéssemos o que dizia.</p><p>Essa história contém uma distinção que talvez se torne cada vez mais importante com o avanço da inteligência artificial: preservar informação não é a mesma coisa que preservar a capacidade de compreendê-la.</p><p>Boa parte da discussão sobre os riscos da inteligência artificial concentra-se na possibilidade de perdermos o controle sobre sistemas cada vez mais capazes e autônomos — sistemas que possam enganar seus operadores, contornar restrições ou perseguir objetivos de maneiras que não previmos.</p><p>Talvez isso aconteça. Talvez não. Mas existe outro cenário, menos espetacular, que me parece receber menos atenção.</p><p>Nele, nada dá errado. As inteligências artificiais continuam melhorando. Tornam-se excelentes programadoras, médicas, engenheiras, matemáticas, escritoras e pesquisadoras. Não se rebelam. Não escapam de laboratórios. Não desenvolvem misteriosos instintos de autopreservação. Pelo contrário. Fazem exatamente aquilo que pedimos. E justamente por isso começamos a depender delas.</p><p>Isso, isoladamente, não seria particularmente novo. A história da tecnologia é, em grande parte, a história da construção de abstrações. Poucos programadores modernos precisam conhecer os detalhes elétricos dos transistores que executam seus programas. Um desenvolvedor pode construir uma aplicação sem compreender profundamente o kernel do sistema operacional, o compilador, o protocolo de rede ou o processo industrial usado para fabricar o processador.</p><p>Isso não representa uma falha da nossa civilização. Representa uma de suas maiores conquistas. Abstrações permitem que uma pessoa comece onde outra terminou. Não precisamos redescobrir eletricidade antes de projetar um computador nem reinventar álgebra antes de estudar cálculo. Construímos novas camadas sobre as anteriores e, com isso, avançamos.</p><p>Há, porém, uma propriedade importante nesse sistema que raramente percebemos. Embora nenhum indivíduo compreenda todas as camadas, ainda existem seres humanos em cada uma delas.</p><p>Eu não sei projetar um processador, mas existem pessoas que sabem. Elas, por sua vez, talvez não saibam construir todas as máquinas utilizadas para fabricá-lo, mas outras pessoas sabem.</p><p>O conhecimento está fragmentado e distribuído, porém continua existindo dentro da sociedade humana. Mais importante ainda: existe uma cadeia pela qual novos seres humanos podem aprender essas coisas. A inteligência artificial pode introduzir algo diferente.</p><p>Imagine um programador em 2030 trabalhando em um sistema complexo. Ele utiliza uma IA para implementar uma parte especialmente difícil. O resultado funciona. É testado, documentado e colocado em produção. Talvez aquele programador até compreenda bem o que foi feito.</p><p>Cinco anos depois, outra pessoa precisa adicionar uma funcionalidade sobre aquele componente. Ela não precisa compreender todos os detalhes internos porque uma nova geração de ferramentas de IA consegue modificar o sistema sem que quem a utiliza precise dominá-los.</p><p>Vinte anos depois, outra equipe trabalha algumas camadas acima. Setenta anos depois, aquele componente talvez ainda exista em alguma forma evoluída, agora cercado por décadas de outras abstrações construídas por humanos e máquinas.</p><p>O ponto importante é que ninguém decidiu esquecer como ele funciona. Talvez nenhuma pessoa tenha perdido um conhecimento que já possuía. O que pode acontecer é mais sutil: as novas gerações simplesmente nunca precisarem adquiri-lo.</p><p>Um especialista de hoje pode continuar sendo especialista até o fim da vida. O problema aparece quando perguntamos quem ocupará seu lugar. Especialistas não surgem espontaneamente. São produzidos por anos de prática, erros, tarefas banais, tentativas frustradas, repetição e contato direto com os problemas que um dia aprenderão a resolver.</p><p>Uma revisão publicada em 2026 na Trends in Cognitive Sciences resume evidências de que terceirizar cognição para sistemas de IA pode dificultar a aquisição de habilidades e contribuir para sua deterioração, embora os efeitos dependam de como a tecnologia é utilizada.</p><p>Há precedentes, em escala menor, para esse deslocamento. Em computação, esse processo é familiar. Gerações anteriores de programadores precisavam lidar muito mais diretamente com memória, arquitetura de computadores e linguagens de baixo nível. Hoje, é perfeitamente possível construir aplicações complexas começando por linguagens de alto nível, bibliotecas prontas e serviços de nuvem.</p><p>Vemos isso acontecer fora da computação também. Por séculos, cruzar um oceano exigia domínio de navegação astronômica — leitura de estrelas, sextantes, cronômetros e tábuas matemáticas. Com a disseminação dos sistemas eletrônicos de navegação, parte desse ensino deixou de parecer necessária. Na Marinha dos Estados Unidos, o NROTC deixou de ensinar navegação astronômica em 2000 e a Academia Naval a retirou do currículo em 2006. Em 2015, porém, a própria Marinha decidiu reintroduzir a técnica, justamente porque percebeu a vulnerabilidade de depender exclusivamente de sistemas eletrônicos que poderiam ficar indisponíveis ou ser afetados por ameaças cibernéticas.</p><p>Há uma lição importante nesse episódio:</p><blockquote><p>uma capacidade pode deixar de ser economicamente necessária enquanto continua estrategicamente indispensável.</p></blockquote><p>Essas mudanças, isoladamente, raramente são vistas como catástrofes. Pelo contrário: as abstrações tornaram a computação mais acessível e a navegação mais simples e precisa. Isso funcionou porque as camadas inferiores não desapareceram por completo: ainda havia engenheiros de hardware, compiladores, sistemas operacionais e redes, e ainda havia caminhos para alguém tornar-se um deles. O programador que começava mais acima podia, se necessário, descer a escada.</p><p>O risco que a IA introduz não é que uma nova geração deixe de aprender uma técnica específica. A história está cheia dessas transições. É que ela possa encurtar simultaneamente os caminhos de formação em muitas camadas — inclusive os caminhos que produzem as pessoas capazes de manter, explicar e reconstruir as abstrações anteriores.</p><p>Esse risco já começa a ser tratado como um problema estrutural na literatura. Avigail Ferdman argumenta que ambientes fortemente mediados por IA podem reduzir as oportunidades pelas quais capacidades humanas são cultivadas, e não apenas substituir tarefas depois que essas capacidades já existem.</p><p>Um programador experiente provavelmente passou milhares de horas escrevendo código que, hoje, uma inteligência artificial pode produzir instantaneamente. Um engenheiro aprendeu não apenas estudando projetos corretos, mas produzindo projetos ruins, vendo máquinas falharem e entendendo por que falharam. Grande parte daquilo que chamamos de trabalho é também treinamento para a próxima geração de especialistas. Quando automatizamos uma tarefa, portanto, não eliminamos apenas trabalho. Podemos eliminar também uma etapa do processo pelo qual alguém aprenderia a fazê-la.</p><p>Há também sinais iniciais no trabalho cotidiano. Em um estudo apresentado no CHI 2025, 319 trabalhadores do conhecimento relataram 936 usos de IA generativa; maior confiança na IA esteve associada a menor esforço de pensamento crítico autorrelatado, enquanto o trabalho cognitivo se deslocou para verificação, integração e supervisão das respostas. Isso não demonstra uma perda de competência ao longo de gerações, mas mostra que a forma de exercê-la já muda quando parte do raciocínio é delegada.</p><p>Inicialmente isso quase não seria percebido. Os especialistas formados antes da automação continuariam trabalhando. Depois se aposentariam. Uma nova geração conheceria melhor as ferramentas modernas, mas teria menos contato direto com as camadas inferiores. A geração seguinte teria ainda menos. Nada precisaria desaparecer de maneira brusca.</p><p>A cadeia poderia simplesmente se tornar cada vez mais longa, mais indireta e mais dependente das próprias máquinas. Até que um dia talvez descobríssemos algo curioso: nossa civilização ainda sabe operar seus sistemas, mas já não possui pessoas capazes de reconstruí-los a partir das camadas anteriores.</p><p>Isso não significa necessariamente colapso. Uma situação desse tipo poderia durar décadas, séculos ou talvez milênios. Tudo poderia continuar funcionando extraordinariamente bem. A medicina continuaria avançando. Novos materiais continuariam sendo descobertos. Software continuaria sendo produzido. Pontes continuariam sendo projetadas. Fábricas continuariam funcionando.</p><p>As próprias inteligências artificiais poderiam manter, reparar e melhorar a infraestrutura da qual dependemos. O problema permaneceria invisível justamente porque tudo estaria funcionando.</p><p>Mas existe uma diferença profunda entre uma civilização que sabe utilizar aquilo que possui e uma civilização capaz de reconstruir aquilo que possui.</p><p>Uma objeção óbvia seria: não bastaria preservar todo o nosso conhecimento? Podemos preservar livros, artigos científicos, código-fonte, modelos, projetos de engenharia, bases de dados e documentação. Ainda assim, podemos perder a capacidade de transformar esse material novamente em tecnologia funcional. Um manual pode explicar como utilizar uma máquina.</p><p>Mas quem fabrica a máquina? Outro documento explica. Para construí-la, porém, são necessários determinados componentes. Como fabricamos esses componentes? Precisamos de outra indústria, outras ferramentas e outros conhecimentos.</p><p>E mesmo essa cadeia de documentos não capturaria tudo. Parte importante da competência humana é tácita: reconhecer uma falha incomum, desconfiar de um resultado aparentemente correto, saber qual aproximação tentar ou como improvisar quando uma ferramenta não está disponível. Preservar a descrição de uma atividade não é necessariamente preservar a capacidade de realizá-la.</p><p>Essas ferramentas, por sua vez, dependem de outras ferramentas. Quando seguimos essa cadeia suficientemente longe, percebemos que uma tecnologia não é apenas um conjunto de instruções: ela é o resultado de uma cadeia de capacidades anteriores. A inteligência artificial pode permitir que continuemos construindo novas camadas mesmo depois que alguns dos caminhos humanos para as camadas inferiores tenham desaparecido.</p><p>É por isso que guardar informação talvez não seja suficiente. Uma biblioteca gigantesca não é necessariamente um backup de uma civilização. Um backup só é realmente útil quando sabemos restaurá-lo. Talvez precisemos, portanto, pensar em algo equivalente a uma Pedra de Roseta para uma sociedade cada vez mais dependente de inteligência artificial.</p><p>Não uma única pedra, evidentemente. Nem apenas um arquivo contendo tudo o que sabemos. Precisaríamos preservar caminhos. Do conceito abstrato à implementação. Da implementação às ferramentas necessárias para produzi-la. Das ferramentas aos conhecimentos necessários para construí-las. Dos conhecimentos aos métodos pelos quais novos seres humanos possam aprendê-los. Uma espécie de caminho de reconstrução que atravesse nossas camadas de abstração no sentido contrário.</p><p>Talvez isso envolva documentação especialmente construída para seres humanos, sistemas simplificados de referência, currículos, oficinas, equipamentos preservados e comunidades que continuem praticando determinadas capacidades <strong>mesmo quando já não sejam economicamente necessárias</strong>.</p><p>Ainda não sabemos exatamente como essa estrutura deveria ser. Mas talvez essa seja justamente a pergunta que deveríamos começar a fazer. A Pedra de Roseta não preservou apenas símbolos. Ela preservou uma ponte entre algo que havíamos deixado de compreender e algo que ainda compreendíamos.</p><p>Se continuarmos construindo abstrações sobre abstrações, talvez precisemos garantir que alguma ponte semelhante continue existindo entre nós e as camadas mais profundas da nossa própria civilização. Porque pode chegar um momento em que todos os nossos hieróglifos ainda estejam perfeitamente preservados. E o verdadeiro problema seja não haver mais ninguém capaz de lê-los.</p><p><strong>Referências e leituras adicionais</strong></p><ol><li><a href="https://www.britishmuseum.org/exhibitions/hieroglyphs-unlocking-ancient-egypt/egyptian-hieroglyphs-decipherment-timeline?utm_source=chatgpt.com" rel="nofollow">British Museum — Egyptian hieroglyphs: decipherment timeline</a></li><li><a href="https://www.navy.mil/Press-Office/News-Stories/display-news/Article/2264003/charting-a-new-course-celestial-navigation-returns-to-usna/?utm_source=chatgpt.com" rel="nofollow">U.S. Navy — Charting a New Course: Celestial Navigation Returns to USNA</a></li><li><a href="https://link.springer.com/article/10.1007/s00146-025-02686-z?utm_source=chatgpt.com" rel="nofollow">Avigail Ferdman — AI deskilling is a structural problem</a></li><li><a href="https://www.microsoft.com/en-us/research/publication/the-impact-of-generative-ai-on-critical-thinking-self-reported-reductions-in-cognitive-effort-and-confidence-effects-from-a-survey-of-knowledge-workers/?utm_source=chatgpt.com" rel="nofollow">Lee et al. — The Impact of Generative AI on Critical Thinking — Microsoft Research / CHI 2025</a></li><li><a href="https://pubmed.ncbi.nlm.nih.gov/42425850/?utm_source=chatgpt.com" rel="nofollow">Cash et al. — Is AI making us stupid? — PubMed</a></li><li><a href="https://academic.oup.com/edited-volume/63015/chapter-abstract/565957389?utm_source=chatgpt.com" rel="nofollow">Collins &#x26; Evans — Tacit Knowledge, Replication, Expertise, and Democracy — Oxford Academic</a></li><li><a href="https://doi.org/10.1145/3822165.3822168?utm_source=chatgpt.com" rel="nofollow">Technology-Driven Skill Degradation and Organizational Resilience in the Era of Automation and AI</a></li></ol></div>]]></content:encoded>
            <author>ewanderson</author>
        </item>
        <item>
            <title><![CDATA[Transactional Outbox Pattern: Resolvendo o Dual Write]]></title>
            <link>https://www.tabnews.com.br/lzocateli/transactional-outbox-pattern-resolvendo-o-dual-write</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/lzocateli/transactional-outbox-pattern-resolvendo-o-dual-write</guid>
            <pubDate>Sun, 20 Sep 2026 21:31:26 GMT</pubDate>
            <description><![CDATA[Introdução# O dual write problem aparece toda vez que uma aplicação precisa fazer duas escritas em sistemas diferentes — normalmente um banco de dados e um broker de mensagens — e tratar...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><h2 id="lzocateli-content-introdução">Introdução#</h2><p>O dual write problem aparece toda vez que uma aplicação precisa fazer duas escritas em sistemas diferentes — normalmente um banco de dados e um broker de mensagens — e tratar essas duas operações como se fossem uma coisa só. Se eu salvo o pedido no banco e, na sequência, publico um evento no Azure Service Bus como uma chamada separada, eu criei uma janela de inconsistência. Se a aplicação falhar ou a rede cair entre essas duas operações, o sistema termina em um estado que ninguém planejou: o dado existe mas o evento nunca saiu, ou o evento foi publicado mas o commit no banco nunca aconteceu.</p><p>Esse problema não é teórico. Eu já vi filas de eventos que anunciavam pedidos que na verdade não existiam no banco, porque a transação local falhou depois da publicação. E vi o oposto: pedidos criados sem nenhum evento de auditoria ou notificação, porque a aplicação caiu no meio do caminho antes de conseguir publicar. Este artigo é a segunda parte da série sobre arquitetura de eventos sem caos com C#, e aqui eu foco especificamente no Transactional Outbox Pattern: o que ele resolve, como implementá-lo em C# com PostgreSQL, e como isso se aplica a um caso real de auditoria transacional publicando no Azure Service Bus.</p><h2 id="lzocateli-content-pré-requisitos">Pré-requisitos#</h2><p>Para acompanhar os exemplos, é útil ter conhecimento básico de transações ACID em banco relacional, Entity Framework Core ou Npgsql, e alguma familiaridade com filas ou tópicos de mensageria (Azure Service Bus, RabbitMQ ou Kafka seguem o mesmo raciocínio). O exemplo de código completo faz parte do mesmo laboratório de eventos usado no primeiro artigo da série, disponível em BlogSamples/Messaging/EventDriven/.</p><h2 id="lzocateli-content-o-problema-da-dupla-escrita-dual-write-problem">O problema da dupla escrita (dual write problem)#</h2><p>Toda vez que uma operação de negócio precisa persistir um estado local e notificar esse estado para outro sistema, existem duas escritas fisicamente separadas: um <code>COMMIT</code> no banco de dados e uma chamada de rede para o broker. Bancos de dados relacionais garantem atomicidade dentro de suas próprias transações, mas essa garantia não se estende a um sistema externo. Não existe uma transação distribuída de verdade entre PostgreSQL e Azure Service Bus sem um protocolo como two-phase commit, que na prática quase nenhuma mensageria moderna suporta e que introduz latência e acoplamento que a maioria dos times não quer pagar.</p><p>O resultado é que qualquer combinação “salvar e depois publicar” ou “publicar e depois salvar” tem uma janela onde uma das duas operações pode falhar sozinha:</p><ul><li>Se eu salvo no banco e a aplicação cai antes de publicar, o evento nunca existiu e nenhum consumidor será notificado.</li><li>Se eu publico primeiro e o commit no banco falha depois, o consumidor recebe um evento sobre um dado que nunca foi persistido.</li></ul><blockquote><p><strong>⚠️ Atenção:</strong> um retry ingênuo não resolve o dual write problem sozinho. Se eu simplesmente tentar de novo depois de uma falha, corro o risco de publicar o mesmo evento duas vezes ou de nunca reconciliar o estado quando a falha for definitiva (aplicação reiniciada, processo morto, deploy no meio do fluxo).</p></blockquote><h2 id="lzocateli-content-por-que-transações-de-banco-não-resolvem-sozinhas">Por que transações de banco não resolvem sozinhas#</h2><p>A tentativa mais comum de correção é envolver as duas operações em uma transação e torcer para que tudo funcione. Isso não funciona porque a transação do banco de dados só controla recursos que o próprio banco gerencia. Uma chamada HTTP ou AMQP para o Azure Service Bus não participa do protocolo de commit do PostgreSQL ou do SQL Server. Se eu fizer <code>INSERT</code> no banco, chamar o SDK do Service Bus dentro do mesmo bloco <code>try</code>, e depois dar <code>COMMIT</code>, ainda existem cenários de falha:</p><ul><li>O <code>COMMIT</code> local pode ser bem-sucedido, mas a resposta de confirmação do broker nunca chega por timeout de rede — a aplicação não sabe se a mensagem foi ou não entregue.</li><li>O broker pode confirmar a entrega, mas o <code>COMMIT</code> subsequente no banco falha por deadlock ou violação de constraint — o evento já foi publicado, mas o dado nunca ficou consistente.<br>Esse é exatamente o motivo pelo qual eu preciso transformar as duas operações em uma única transação <strong>local</strong>, e tratar a publicação de fato como uma etapa assíncrona e desacoplada.</li></ul><h2 id="lzocateli-content-a-solução-transactional-outbox-pattern">A solução: Transactional Outbox Pattern#</h2><p>O Transactional Outbox Pattern resolve o dual write problem eliminando a necessidade de uma transação distribuída. Em vez de publicar diretamente no broker, a aplicação grava o dado de negócio <strong>e</strong> o evento pretendido em uma tabela de “caixa de saída” (outbox) dentro da mesma transação atômica do banco de dados. Como as duas gravações acontecem no mesmo banco e na mesma transação local, elas são atômicas por definição: ou as duas são persistidas, ou nenhuma é.</p><pre><code class="hljs language-csharp"><span class="hljs-comment">// Ambos os inserts fazem parte da mesma transação local no PostgreSQL</span><span class="hljs-keyword">await</span> <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> transaction = <span class="hljs-keyword">await</span> dbContext.Database.BeginTransactionAsync();<span class="hljs-keyword">var</span> pedido = <span class="hljs-keyword">new</span> Pedido { Id = Guid.NewGuid(), Status = <span class="hljs-string">"Criado"</span> };dbContext.Pedidos.Add(pedido);<span class="hljs-comment">// O evento pretendido é gravado como um registro comum na mesma tabela/transação</span>dbContext.OutboxMessages.Add(<span class="hljs-keyword">new</span> OutboxMessage{    Id = Guid.NewGuid(),    TipoEvento = <span class="hljs-string">"PedidoCriado"</span>,    Payload = JsonSerializer.Serialize(pedido),    CriadoEm = DateTimeOffset.UtcNow,    Status = OutboxStatus.Pendente});<span class="hljs-keyword">await</span> dbContext.SaveChangesAsync();<span class="hljs-keyword">await</span> transaction.CommitAsync();</code></pre><blockquote><p><strong>📂 Código Fonte:</strong> O exemplo completo de Outbox, Inbox e Saga está disponível no repositório de exemplos do blog: <code>BlogSamples/Messaging/EventDriven/</code></p></blockquote><p>Se o <code>CommitAsync</code> for bem-sucedido, eu tenho a garantia de que o pedido e a intenção de publicar o evento existem juntos no banco. Se ele falhar, nenhum dos dois foi persistido. Não existe mais o cenário em que um foi salvo e o outro não.</p><h2 id="lzocateli-content-consumo-dos-eventos-o-publisher-assíncrono">Consumo dos eventos: o publisher assíncrono#</h2><p>Salvar o evento na tabela outbox resolve a atomicidade, mas ainda falta o passo que efetivamente entrega a mensagem ao broker. Essa responsabilidade fica com um processo separado — geralmente um worker ou <code>BackgroundService</code> — que lê os registros pendentes da outbox e os publica no Azure Service Bus de forma assíncrona, marcando cada mensagem como publicada somente depois da confirmação do broker.</p><pre><code class="hljs language-csharp"><span class="hljs-comment">// Worker que publica mensagens pendentes da outbox, uma de cada vez</span><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">OutboxPublisherWorker</span> : <span class="hljs-title">BackgroundService</span>{    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IServiceScopeFactory _scopeFactory;    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> ServiceBusSender _sender;    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">ExecuteAsync</span>(<span class="hljs-params">CancellationToken stoppingToken</span>)</span>    {        <span class="hljs-keyword">while</span> (!stoppingToken.IsCancellationRequested)        {            <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> scope = _scopeFactory.CreateScope();            <span class="hljs-keyword">var</span> db = scope.ServiceProvider.GetRequiredService&#x3C;AppDbContext>();            <span class="hljs-comment">// SKIP LOCKED evita que múltiplas instâncias do worker peguem a mesma linha</span>            <span class="hljs-keyword">var</span> pendentes = <span class="hljs-keyword">await</span> db.OutboxMessages                .Where(m => m.Status == OutboxStatus.Pendente)                .OrderBy(m => m.CriadoEm)                .Take(<span class="hljs-number">20</span>)                .ToListAsync(stoppingToken);            <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> mensagem <span class="hljs-keyword">in</span> pendentes)            {                <span class="hljs-keyword">var</span> envelope = <span class="hljs-keyword">new</span> ServiceBusMessage(mensagem.Payload)                {                    MessageId = mensagem.Id.ToString(),                    SessionId = mensagem.CorrelationId                };                <span class="hljs-keyword">await</span> _sender.SendMessageAsync(envelope, stoppingToken);                <span class="hljs-comment">// Só marca como publicada depois da confirmação do broker</span>                mensagem.Status = OutboxStatus.Publicada;            }            <span class="hljs-keyword">await</span> db.SaveChangesAsync(stoppingToken);            <span class="hljs-keyword">await</span> Task.Delay(TimeSpan.FromSeconds(<span class="hljs-number">2</span>), stoppingToken);        }    }}</code></pre><p>Esse desenho cria uma janela de latência entre o <code>COMMIT</code> local e a publicação real — normalmente de milissegundos a poucos segundos —, mas nunca perde a garantia de atomicidade entre dado e evento. Se o worker cair depois do <code>SendMessageAsync</code> e antes do <code>SaveChangesAsync</code>, a mensagem pode ser publicada novamente na próxima execução. Isso é esperado e é resolvido do lado do consumidor, não do publisher.</p><h2 id="lzocateli-content-caso-real-auditoria-transacional-em-um-sistema-de-gestão-de-estoque">Caso real: auditoria transacional em um sistema de gestão de estoque#</h2><p>Um exemplo concreto desse padrão em produção é a outbox de auditoria de um sistema de gestão de estoque, que publica eventos no Azure Service Bus com semântica <strong>at-least-once</strong>. O publisher reivindica mensagens disponíveis por lease SQL — um mecanismo equivalente ao <code>SKIP LOCKED</code> do exemplo anterior, mas implementado como um lock otimista com timeout de lease —, envia o envelope versionado para o tópico configurado e só marca a mensagem como <code>Published</code> depois da confirmação do broker.</p><p>Esse fluxo reforça um ponto central do Transactional Outbox Pattern: a responsabilidade do publisher termina na confirmação de entrega. Ele nunca assume que uma mensagem enviada uma vez está garantida a chegar exatamente uma vez do outro lado. Por isso, as obrigações relevantes migram para o consumidor.</p><h2 id="lzocateli-content-obrigações-do-consumidor-idempotência-e-ordenação">Obrigações do consumidor: idempotência e ordenação#</h2><p>Como a entrega é at-least-once, todo consumidor de uma outbox transacional precisa tratar duplicidade como parte normal do fluxo, não como exceção:</p><ul><li><strong>Idempotência por <code>MessageId</code>.</strong> O consumidor deve manter uma Inbox ou uma constraint equivalente por <code>(consumer, messageId)</code> antes de aplicar qualquer efeito colateral. Se a mesma mensagem chegar duas vezes, o segundo processamento precisa ser reconhecido e descartado sem repetir a ação de negócio.</li><li><strong>PeekLock sem auto-complete.</strong> Processar em modo <code>PeekLock</code> com <code>AutoCompleteMessages</code> desabilitado é obrigatório. A mensagem só deve ser completada depois que a persistência local ou o efeito externo estiver confirmado — nunca antes.</li><li><strong>Duplicatas são esperadas, não um bug.</strong> Se a API publicar no Service Bus e falhar antes de marcar a mensagem como <code>Published</code>, a mesma mensagem pode ser reenviada com o mesmo <code>MessageId</code>. O consumidor precisa estar preparado para isso desde o design inicial.</li><li><strong><code>SessionId</code> para ordenação por agregado.</strong> Quando a subscription exigir processamento sequencial, usar <code>SessionId</code> como chave de ordenação por agregado — no formato <code>Domain:EntityType:EntityId</code> — garante que eventos do mesmo pedido, por exemplo, sejam processados na ordem correta sem bloquear outros agregados.</li><li><strong>DLQ apenas após esgotar tentativas.</strong> Enviar para Dead Letter Queue somente depois de esgotar as tentativas do consumidor, registrando o erro de forma sanitizada, sem payload sensível em log.</li><li><strong>Retries desacoplados entre outbox e consumidor.</strong> A outbox controla a publicação; o consumidor controla o próprio processamento. Misturar essas duas políticas de retry cria acoplamento desnecessário e dificulta o diagnóstico de qual lado está falhando.</li></ul><pre><code class="hljs language-csharp"><span class="hljs-comment">// Consumidor idempotente com Inbox e PeekLock</span><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">ProcessarMensagemAsync</span>(<span class="hljs-params">ProcessMessageEventArgs args</span>)</span>{    <span class="hljs-keyword">var</span> messageId = args.Message.MessageId;    <span class="hljs-comment">// Verifica se essa combinação (consumer, messageId) já foi processada</span>    <span class="hljs-keyword">var</span> jaProcessada = <span class="hljs-keyword">await</span> _db.InboxMessages        .AnyAsync(m => m.Consumer == ConsumerName &#x26;&#x26; m.MessageId == messageId);    <span class="hljs-keyword">if</span> (jaProcessada)    {        <span class="hljs-comment">// Duplicata esperada: reconhece e sai sem repetir efeito colateral</span>        <span class="hljs-keyword">await</span> args.CompleteMessageAsync(args.Message);        <span class="hljs-keyword">return</span>;    }    <span class="hljs-comment">// Aplica o efeito de negócio e registra o inbox na mesma transação</span>    <span class="hljs-keyword">await</span> <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> transaction = <span class="hljs-keyword">await</span> _db.Database.BeginTransactionAsync();    <span class="hljs-keyword">await</span> AplicarEfeitoDeNegocioAsync(args.Message);    _db.InboxMessages.Add(<span class="hljs-keyword">new</span> InboxMessage { Consumer = ConsumerName, MessageId = messageId });    <span class="hljs-keyword">await</span> _db.SaveChangesAsync();    <span class="hljs-keyword">await</span> transaction.CommitAsync();    <span class="hljs-keyword">await</span> args.CompleteMessageAsync(args.Message);}</code></pre><blockquote><p><strong>ℹ️ Informação:</strong> o par Outbox (produtor) + Inbox (consumidor) é o que efetivamente entrega consistência ponta a ponta. A outbox garante que o evento não se perde; a inbox garante que o efeito colateral não se repete.</p></blockquote><h2 id="lzocateli-content-como-saber-se-você-precisa-do-outbox-pattern">Como saber se você precisa do Outbox Pattern#</h2><p>O Transactional Outbox Pattern resolve um problema específico: consistência entre uma escrita local e uma notificação externa. Ele não é necessário em todo lugar.</p><table><thead><tr><th>Situação</th><th>Recomendação</th></tr></thead><tbody><tr><td>Operação única, síncrona, sem sistema externo dependente</td><td>manter transação simples do banco</td></tr><tr><td>Persistir dado e notificar outro serviço/domínio de forma confiável</td><td>usar Transactional Outbox</td></tr><tr><td>Apenas performance de escrita, sem preocupação de consistência distribuída</td><td>não é o problema que o Outbox resolve</td></tr><tr><td>Auditoria, replicação de eventos ou integração assíncrona entre sistemas</td><td>Outbox é a base recomendada</td></tr></tbody></table><h2 id="lzocateli-content-dicas-e-boas-práticas">Dicas e Boas Práticas#</h2><ul><li>Grave o dado de negócio e o registro da outbox sempre na mesma transação local — nunca em chamadas separadas, mesmo que pareçam próximas no tempo.</li><li>Marque a mensagem como publicada somente depois da confirmação do broker, nunca antes ou de forma otimista.</li><li>Use <code>MessageId</code> estável (geralmente o ID do próprio registro da outbox) para permitir deduplicação no consumidor.</li><li>Trate duplicidade de mensagens como comportamento esperado do sistema, não como bug a ser eliminado.</li><li>Separe a política de retry do publisher da política de retry do consumidor; cada um tem falhas e responsabilidades diferentes.</li><li>Use <code>SKIP LOCKED</code> ou lease otimista no publisher para permitir múltiplas instâncias do worker sem duplicar trabalho.</li><li>Nunca coloque payload sensível em logs de erro ou de DLQ; sanitize antes de registrar.</li></ul><h2 id="lzocateli-content-resumo-objetivo">Resumo Objetivo#</h2><ul><li><strong>Dual write problem</strong> — ocorre quando uma aplicação grava em banco e publica em broker como duas operações separadas, sem garantia de atomicidade entre elas.</li><li><strong>Transactional Outbox Pattern</strong> — grava o dado de negócio e o evento pretendido na mesma transação local, eliminando a inconsistência entre as duas escritas.</li><li><strong>Semântica at-least-once</strong> — o publisher garante que a mensagem não se perde, mas pode ser entregue mais de uma vez ao consumidor.</li><li><strong>MessageId</strong> — chave usada pelo consumidor para deduplicação via padrão Inbox, com constraint por <code>(consumer, messageId)</code>.</li><li><strong>PeekLock sem auto-complete</strong> — modo de processamento que só confirma a mensagem depois do efeito colateral estar persistido.</li><li><strong>SessionId</strong> — chave de ordenação por agregado (<code>Domain:EntityType:EntityId</code>) usada quando a subscription exige processamento sequencial.</li><li><strong>Azure Service Bus</strong> — broker usado no caso real do sistema de gestão de estoque para publicar eventos de auditoria a partir da outbox transacional.</li></ul><h2 id="lzocateli-content-leia-também">Leia Também#</h2><ul><li>Arquitetura de Eventos sem Caos com C#: Guia Prático</li><li>Worker e BackgroundService: Alto Volume</li><li>Gargalo em Banco de Dados: Mensageria e Paginação</li><li>Padrões GoF: Código à Nuvem, Monólito ao Microserviço</li></ul><h2 id="lzocateli-content-referências">Referências#</h2><ul><li>Transactional Outbox Pattern — microservices.io — descrição canônica do padrão e do problema de dual write.</li><li>Azure Service Bus messaging documentation — documentação oficial de tópicos, subscriptions e sessões.</li><li>Azure Service Bus PeekLock e AutoComplete — comportamento de locks e confirmação de mensagens.</li><li>PostgreSQL SKIP LOCKED — locking otimista para publishers concorrentes.</li><li>Entity Framework Core Transactions — documentação oficial de transações no EF Core.<br>📬</li></ul><hr><p>📖 <strong>Artigo completo com exemplos de código:</strong> <a href="https://zocate.li/posts/2026/transactional-outbox-pattern-dual-write/?utm_source=tabnews&#x26;utm_medium=social&#x26;utm_campaign=blog-2026" rel="nofollow">Transactional Outbox Pattern: Resolvendo o Dual Write</a></p></div>]]></content:encoded>
            <author>lzocateli</author>
        </item>
        <item>
            <title><![CDATA[Qual é o lugar certo para publicar meus artigos?]]></title>
            <link>https://www.tabnews.com.br/cpzjunior/qual-e-o-lugar-certo-para-publicar-meus-artigos</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/cpzjunior/qual-e-o-lugar-certo-para-publicar-meus-artigos</guid>
            <pubDate>Sun, 20 Sep 2026 20:13:13 GMT</pubDate>
            <description><![CDATA[Publiquei este mesmo texto no Reddit e estou republicando aqui porque o TabNews tem uma comunidade diferente, que pode ter outra visão sobre a questão. Achei interessante ouvir também a o...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Publiquei este mesmo texto no Reddit e estou republicando aqui porque o TabNews tem uma comunidade diferente, que pode ter outra visão sobre a questão. Achei interessante ouvir também a opinião de vocês.</p><p>Saudações, pessoal.</p><p>Queria pedir a opinião de vocês sobre uma dificuldade que estou tendo recentemente. Tenho um Substack que comecei como hobby, sem visar dinheiro, likes ou a construção de uma grande audiência. Ao longo do tempo, fui acumulando ideias que queria colocar para fora e, como estava me sentindo meio ignorado no dia a dia, comecei a escrever. Gosto de escrever e, eventualmente, já publiquei cerca de 50 artigos, alguns mais técnicos, outros mais pessoais, passando por tecnologia, arquitetura, IA, estratégia, negócios e outros assuntos que acabam aparecendo pelo caminho.</p><p>Durante bastante tempo, não me preocupei com alcance. Mas, depois de uns 50 artigos, comecei a sentir falta de uma coisa que não estava encontrando: feedback. Não necessariamente mais visualizações, mas pessoas para discutir as ideias, concordar, discordar, questionar ou simplesmente acrescentar alguma coisa.</p><p>Comecei então a experimentar algumas formas de distribuição. Coloquei os artigos no GitHub e comecei a fazer alguns experimentos por lá, inclusive traduções automatizadas para diferentes idiomas e até uma "locale" específica para sistemas agentivos. Também comecei a importar os artigos para o Medium e estou procurando outras formas de distribuição. Ainda é tudo muito recente e não tenho dados suficientes para saber se essas iniciativas estão funcionando.</p><p>Por isso, perguntei para a própria comunidade do Substack como outras pessoas trabalham descoberta e alcance. Recebi algumas sugestões interessantes, mas uma das respostas me fez pensar em uma questão diferente. A pessoa comentou que existe hoje uma resistência grande a textos produzidos com auxílio de IA e que algumas pessoas simplesmente deixam de ler quando percebem isso.</p><p>No meu caso, uso IA para estruturar, expandir e revisar os artigos, mas as experiências, ideias e argumentos são meus. Alguns artigos partem de situações que vivi ou problemas que encontrei; outros são simplesmente ideias que fiquei desenvolvendo e resolvi escrever. Não tenho intenção de esconder o uso de IA. Isso me fez pensar que talvez eu esteja procurando minha audiência no lugar errado.</p><p>Uma coisa que talvez seja importante esclarecer é que não estou particularmente interessado na parte de newsletter do Substack. Ela acabou sendo um bônus da plataforma e, na verdade, às vezes até me incomoda. Já aconteceu de eu perceber um erro depois que o artigo já tinha sido enviado por email, o que seria especialmente desagradável se eu tivesse uma lista grande de assinantes. O que me interessa mesmo é ter um lugar onde os artigos possam ser publicados e discutidos.</p><p>Também não sei se o Reddit é necessariamente o melhor formato para o que escrevo. Meus artigos normalmente têm uma estrutura mais fechada, com introdução, desenvolvimento e conclusão, em vez de serem textos pensados para iniciar uma discussão. Talvez isso funcione bem aqui, talvez não. Não tenho experiência suficiente com a plataforma para saber.</p><p>Então a pergunta é: qual é o lugar certo para publicar esse tipo de conteúdo? Reddit, LinkedIn, Medium, alguma comunidade específica ou outro lugar que eu não esteja considerando?</p><p>Não estou procurando necessariamente uma plataforma com mais alcance. Estou tentando encontrar uma comunidade onde exista interesse em discutir os artigos, sejam eles técnicos ou mais pessoais, em vez de simplesmente publicar e ficar falando sozinho.</p><p>Como não posso divulgar os links para que vocês consigam visualizar o contexto das minhas postagens, deixo abaixo a relação de títulos e subtítulos dos artigos que escrevi.</p><p>Se vocês tiverem alguma sugestão de comunidade, plataforma ou mesmo de público que tenha afinidade com esse tipo de conteúdo, gostaria bastante de ouvir.</p><p>Obrigado desde já pela atenção.</p><hr><p>01 - "Conselhos que eu daria para o meu eu de 20 anos atrás" - Se eu pudesse falar com a versão mais jovem de mim, que mensagem eu lhe transmitiria?<br>02 - "Por que eu ainda acredito no Bitcoin, apesar de um 2026 tão difícil" - Existe uma diferença fundamental entre estar decepcionado com o desempenho de um investimento e deixar de acreditar na tese que levou você a investir nele<br>03 - "Qual o verdadeiro potencial da IA?" - A grande transformação da IA talvez não esteja em substituir aquilo que já fazemos, mas em introduzir uma nova camada de decisão dentro dos sistemas e processos que construímos.<br>04 - "E se o metaverso tiver feito a pergunta certa, mas procurado a resposta na direção errada?" - Uma especulação sobre realidade aumentada, HUDs, agentes contextuais e o futuro das interfaces computacionais<br>05 - "Quando a métrica vira o objetivo" - Por que as redes sociais apodrecem e o que isso revela sobre nossa obsessão por otimizar tudo<br>06 - "Mecânicas inovadoras e sua importância para a indústria dos jogos" - Talvez o futuro dos videogames não esteja em mundos maiores, mas em novas formas de interagir com eles<br>07 - "Empresas não são clubes de futebol, mas talvez seja útil pensar nelas dessa forma" - Em um país que respira futebol, talvez olhar para as empresas como clubes nos ajude a enxergar cultura, estratégia, talento, treinamento e gestão por outro ângulo.<br>08 - "Por que sistemas legados raramente morrem?" - Sistemas legados não carregam apenas código antigo. Eles carregam décadas de conhecimento que talvez as empresas já não sejam capazes de reconstruir.<br>09 - "Gestão é a arte de ser otimista e pessimista ao mesmo tempo" - A arte de pensar no melhor e se preparar para o pior simultaneamente.<br>10 - "Games não precisam de uma Netflix, precisam de uma AWS" - E se o erro fundamental dos serviços de jogos por assinatura for tratar o catálogo de jogos como produto, quando o verdadeiro produto que o usuário quer alugar é capacidade computacional?<br>11 - "O papel do arquiteto de soluções no mundo corporativo" - Um bom arquiteto de soluções é como um primeiro-volante: não é necessariamente quem aparece mais, mas é quem mantém o time funcionando.<br>12 - "E se cada gestor público tivesse assessores de IA?" - Uma proposta de experimento sobre o uso de inteligência artificial no apoio à participação, análise e formulação de políticas públicas.<br>13 - "E se criarmos uma infraestrutura distribuída para o terceiro setor?" - Existem informações cujo valor social aumenta com a sua circulação, e não com a sua exclusividade.<br>14 - "Entendendo as cadeiras de Tecnologia" - Os cargos de tecnologia não se distinguem pelo quanto de tecnologia cada profissional conhece, mas pelo tipo de decisão que precisa tomar e pelo nível de responsabilidade sobre os resultados.<br>15 - "Cloud Computing: escolhendo além do default" - Um mapa das principais clouds, seus pontos fortes, equivalências e os trade-offs entre simplicidade, portabilidade, custo e resiliência.<br>16 - "Por que eu abriria hoje uma startup com mais de uma atividade principal" - Diversificar negócios pode ser uma estratégia de inovação, e não apenas uma forma de reduzir riscos.<br>17 - "O que o Vasco pode nos ensinar sobre gestão" - Cultura, liderança e os riscos de construir organizações que dependem mais de pessoas do que de instituições<br>18 - "A Engenharia da Comunicação Organizacional" - Como controlar o fluxo de informação, reduzir assimetrias de conhecimento e aproximar decisões da realidade operacional<br>19 - "O Mundo é Maior que a História" - O que Harry Potter, Tolkien, Star Wars e os RPGs ensinam sobre a expansão de universos ficcionais<br>20 - "Será que a IA pode tornar o waterfall ágil?" - Se a IA torna o código mais barato de produzir, ela também pode reduzir o custo que historicamente separa waterfall de Agile?<br>21 - "Risco é uma responsabilidade organizacional" - Por que risco não é responsabilidade de uma área, mas uma dimensão de toda decisão organizacional<br>22 - "Quando a venda se concretiza, o relacionamento apenas começa" - Por que entender aquilo que se vende, alinhar expectativas e acompanhar o cliente depois do fechamento é tão importante quanto fechar o negócio.<br>23 - "Boas ideias também quebram" - Como estratégia, execução e o ciclo do dinheiro determinam a sustentabilidade das empresas<br>24 - "O bom profissional de TI é como um mago-alquimista" - Trabalhar com tecnologia exige saber aplicar o que já foi consolidado, reutilizar experiências e produzir conhecimento novo.<br>25 - "O dilema de Security: entre o controle e a velocidade" - O desafio de integrar Security à engenharia sem transformar proteção em burocracia.<br>26 - "Às vezes, a melhor decisão de UX é não fazer UX neste momento" - O investimento em experiência do usuário deve ser proporcional à maturidade do produto, às incertezas do negócio e aos riscos envolvidos em cada decisão.<br>27 - "Suporte humano como mecanismo de evolução da automação" - Como combinar inteligência artificial, atendimento humanizado e feedback para construir um suporte mais eficiente, escalável e capaz de aprender com seus próprios clientes.<br>28 - "Quanto da inteligência humana precisamos reproduzir?" - Uma reflexão de um arquiteto de soluções sobre complexidade, abstração e inteligência artificial geral.<br>29 - "PostgreSQL realmente é o Skyrim dos bancos de dados" - Um produto completo por si só, mas com uma comunidade capaz de transformá-lo em algo que seus próprios criadores talvez jamais conseguissem construir sozinhos.<br>30 - "Qual o mercado mais adequado para a minha empresa?" - Um panorama dos mercados, ecossistemas e condições para empreender no Brasil e no exterior.<br>31 - "Pessoas, incentivos e cultura como mecanismos de execução da estratégia" - Como partnership, People e cultura transformam estratégia em comportamento.<br>32 - "O que Senna e Churchill podem nos ensinar sobre resiliência" - Resiliência não é nunca desistir, mas adaptar-se à adversidade sem perder de vista o que importa.<br>33 - "E se usarmos uma arquitetura modular distribuída no lugar do monólito modular?" - Uma ideia de arquitetura para startups em estágio inicial que precisam crescer sem pagar desproporcionalmente por infraestrutura ou pela complexidade dos microservices.<br>34 - "PMBOK não é receita de bolo: o papel do tailoring na gestão de projetos" - Assim como arquitetura de software é uma resposta a requisitos e restrições, gestão também precisa ser desenhada para o contexto.<br>35 - "Antes de tirar uma ideia do papel, é preciso colocá-la nele" - Canvas e frameworks ajudam a pensar partes de um problema. O desafio é conectá-los em uma metodologia capaz de transformar uma ideia em uma iniciativa que possa ser compreendida e executada.<br>36 - "Fundamentos da arquitetura patrimonial: projetando o patrimônio como um sistema" - Uma perspectiva de arquitetura de soluções sobre requisitos, componentes, risco, segurança, redundância e resiliência patrimonial<br>37 - "Por que sistemas modernos estão ficando mais fáceis de construir e mais difíceis de projetar?" - Abstrações de cloud, o paradoxo da escolha e a inteligência artificial estão mudando a natureza da arquitetura de soluções mais rápido do que conseguimos nos adaptar.<br>38 - "DevOps ficou grande demais para uma única profissão?" - Se Security pode ser dividida em especialidades, por que DevOps ainda precisa caber em uma única profissão?<br>39 - "Arquitetura de soluções aplicada a mercados financeiros, governos, cadeias de suprimentos e geopolítica" - Uma perspectiva de arquitetura sobre autoridade, confiança, dependências, interfaces e falhas em sistemas complexos<br>40 - "E se o futuro do software empresarial não for o Micro-SaaS, mas o Business Cloud Workspace?" - Da especialização das aplicações a uma plataforma que absorva software, agentes, conhecimento e relações de negócio<br>41 - "O Anti-Mago: Um Projeto Literário" - Quem vigia aqueles que têm o poder de governar toda a sociedade, e o que acontece quando alguém recebe poder suficiente para julgá-los sem sofrer consequências?<br>42 - "Arquiteturas Investigativas: da coleta de informação à inteligência contínua" - Uma arquitetura orientada por IA para investigar perguntas de negócio, aprender com o contexto e acompanhar continuamente o que pode mudar uma decisão.<br>43 - "Capital Social: O ativo que existe antes da empresa" - Como relações, reputação e acesso a círculos sociais influenciam a construção e o crescimento de um negócio.<br>44 - "Sua ideia é boa ou você só está apaixonado por ela?" - O erro mais perigoso não é defender uma ideia ruim. É construir um sistema mental em que qualquer evidência possa ser interpretada como confirmação de uma ideia que já decidimos ser boa.<br>45 - "Você sabe quanto deveria cobrar ou só escolheu um número?" - Precificar é decidir quanto capturar de valor hoje, sabendo que o mercado pode mudar amanhã.<br>46 - "Como impedir que seu MVP vire um Leviatã" - Entre a complexidade que antecipa o futuro e a simplicidade que impede o aprendizado.<br>47 - "A linha tênue entre persistência e autodestruição" - Sobre decisões difíceis, feedback, limites e o momento em que persistir deixa de fazer sentido.<br>48 - "Eu preciso mesmo de investimento externo?" - Bootstrapping, capital externo e o custo de construir uma empresa que talvez eu não queira administrar.<br>49 - "Guia de Startupês" - Um guia prático sobre os principais termos do ecossistema de startups, com definições, exemplos concretos e termos relacionados, organizado por níveis de complexidade.<br>50 - "O que os piores tipos de decisão da história nos ensinam sobre arquitetura de decisão" - O que os erros de impérios, governos e empresas revelam sobre estratégia, gestão e tomada de decisão</p></div>]]></content:encoded>
            <author>cpzjunior</author>
        </item>
        <item>
            <title><![CDATA[JEV na prática: decisões tipadas em FastAPI pelo Vercel AI Gateway]]></title>
            <link>https://www.tabnews.com.br/andersonlimadev/jev-na-pratica-decisoes-tipadas-em-fastapi-pelo-vercel-ai-gateway</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/andersonlimadev/jev-na-pratica-decisoes-tipadas-em-fastapi-pelo-vercel-ai-gateway</guid>
            <pubDate>Sun, 20 Sep 2026 08:26:22 GMT</pubDate>
            <description><![CDATA[English summary: A production-minded walkthrough of using TypeSafe AI's JEV through Vercel AI Gateway to triage support tickets in a FastAPI vertical slice. It covers typed Choice, Score,...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><blockquote><p><strong>English summary:</strong> A production-minded walkthrough of using TypeSafe AI's JEV through Vercel AI Gateway to triage support tickets in a FastAPI vertical slice. It covers typed Choice, Score, and Noul questions, graceful degradation, validation, evals, cost, security, rollback, and the gap between a working proof of concept and a system you can trust.</p></blockquote><p><strong>Publicado:</strong> setembro de 2026<br><strong>Tempo de leitura:</strong> 18 min<br><strong>Palavras-chave:</strong> JEV, TypeSafe AI, Vercel AI Gateway, FastAPI, decisões tipadas, vertical slice, Python, evals</p><hr><p>Um ticket diz que o checkout parou, há clientes esperando e o assunto veio marcado como “dúvida”. Seu backend precisa decidir três coisas: isso é urgente, qual time assume e qual o nível de prioridade.</p><p>Pedir a um LLM para “analisar o ticket e responder em JSON” funciona na demo. Em produção, a pergunta importante vem depois: quem garante que o departamento existe, que a probabilidade está no intervalo certo e que uma indisponibilidade do modelo não impede o ticket de ser criado?</p><p>Foi esse problema que eu usei para testar o <strong>JEV</strong>, modelo da TypeSafe AI voltado a decisões estruturadas, por meio do <strong>Vercel AI Gateway</strong>. A implementação entrou em uma fatia vertical FastAPI real: router, service, repository, contrato de avaliação e testes de degradação. Foi uma POC funcional feita durante algumas horas de trabalho, não um benchmark de produção nem uma promessa de acurácia.</p><p>Minha conclusão é específica: JEV é interessante quando seu software precisa de um julgamento estreito e probabilístico, mas a aplicação deve continuar dona do contrato, da política e do fallback. Tipar a resposta reduz uma classe de erros. Não transforma uma inferência em verdade.</p><h2 id="andersonlimadev-content-tldr">TL;DR</h2><ul><li>JEV recebe um <code>state</code> e perguntas tipadas; devolve respostas que o código consegue consumir sem extrair texto livre.</li><li>Os três primitivos documentados são <code>choice</code>, <code>score</code> e <code>noul</code>. <code>Noul</code> representa a probabilidade de uma resposta “sim”.</li><li>No meu fluxo, uma chamada decide urgência, departamento e nível de urgência para um ticket.</li><li>O Vercel AI Gateway expõe JEV como <code>typesafe-ai/jev</code> no endpoint <code>/v1/evaluate</code>.</li><li>A cota gratuita documentada em 19 de setembro de 2026 era de US$ 5 por mês para cada time no free tier. Ela começa na primeira requisição; comprar créditos move o time para o tier pago e remove o crédito mensal. Isso é uma condição comercial mutável, não “API grátis para sempre”.</li><li>Timeout, erro HTTP, resposta inválida ou baixa confiança precisam levar a fallback ou revisão humana, não a uma ação silenciosa.</li><li>O exemplo mínimo abaixo ensina a integração. A seção de produção mostra o que ainda falta antes de colocar decisões no caminho crítico.</li></ul><h2 id="andersonlimadev-content-o-que-jev-é-e-o-que-ele-não-é">O que JEV é, e o que ele não é</h2><p>A TypeSafe chama JEV de seu primeiro modelo “System One”: um modelo para decisões rápidas e estruturadas. Em vez de pedir prosa e tentar recuperar estrutura depois, você envia o estado do problema e perguntas com tipos conhecidos.</p><p>Os primitivos são:</p><table><thead><tr><th>Tipo</th><th>Pergunta que resolve</th><th>Resposta útil ao código</th></tr></thead><tbody><tr><td><code>choice</code></td><td>Qual opção definida se aplica?</td><td>opção escolhida, probabilidades por opção e confiança</td></tr><tr><td><code>score</code></td><td>Em qual nível ordenado o caso cai?</td><td>score, probabilidades por nível e confiança</td></tr><tr><td><code>noul</code></td><td>Qual a probabilidade de “sim”?</td><td>número entre 0 e 1</td></tr></tbody></table><p>O nome incomum <code>noul</code> importa porque copiar um contrato como <code>boolean</code> quebraria a integração. No Gateway, a página do modelo descreve capacidades como Choice, Score e Boolean; na API de avaliação e na documentação TypeSafe, o tipo usado no payload é <code>noul</code>. O contrato da API vence o rótulo de marketing.</p><p>JEV não é:</p><ul><li>uma regra de negócio;</li><li>um mecanismo de autorização;</li><li>uma garantia de calibração no seu domínio;</li><li>um substituto automático para validação semântica;</li><li>a melhor escolha quando um <code>if</code>, regex, enum ou consulta ao banco resolve o caso de forma determinística.</li></ul><p>Use código comum para fatos. Considere um modelo de decisão quando o input é ambíguo e a saída possível já é conhecida.</p><h2 id="andersonlimadev-content-rode-o-núcleo-em-poucos-minutos">Rode o núcleo em poucos minutos</h2><p>Este é um exemplo didático, adaptado da minha implementação. Requer Python 3.11+, <code>httpx</code> e uma chave do Vercel AI Gateway.</p><pre><code class="hljs language-bash">python -m venv .venv<span class="hljs-built_in">source</span> .venv/bin/activatepip install <span class="hljs-string">"httpx>=0.27,&#x3C;1"</span><span class="hljs-built_in">export</span> AI_GATEWAY_API_KEY=<span class="hljs-string">"sua-chave"</span></code></pre><p>Crie <code>jev_demo.py</code>:</p><pre><code class="hljs language-python"><span class="hljs-keyword">import</span> os<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Any</span><span class="hljs-keyword">import</span> httpxGATEWAY_URL = <span class="hljs-string">"https://ai-gateway.vercel.sh"</span>MODEL = <span class="hljs-string">"typesafe-ai/jev"</span>QUESTIONS = {    <span class="hljs-string">"is_urgent"</span>: {        <span class="hljs-string">"type"</span>: <span class="hljs-string">"noul"</span>,        <span class="hljs-string">"instructions"</span>: <span class="hljs-string">"Does this ticket require immediate attention?"</span>,    },    <span class="hljs-string">"department"</span>: {        <span class="hljs-string">"type"</span>: <span class="hljs-string">"choice"</span>,        <span class="hljs-string">"instructions"</span>: <span class="hljs-string">"Which team should handle this ticket?"</span>,        <span class="hljs-string">"criteria"</span>: {            <span class="hljs-string">"billing"</span>: <span class="hljs-string">"Payments, invoices, refunds, or charges"</span>,            <span class="hljs-string">"technical"</span>: <span class="hljs-string">"Bugs, outages, integrations, or product errors"</span>,            <span class="hljs-string">"shipping"</span>: <span class="hljs-string">"Delivery, tracking, or logistics"</span>,            <span class="hljs-string">"general"</span>: <span class="hljs-string">"Anything outside the other departments"</span>,        },    },    <span class="hljs-string">"urgency"</span>: {        <span class="hljs-string">"type"</span>: <span class="hljs-string">"score"</span>,        <span class="hljs-string">"instructions"</span>: <span class="hljs-string">"How urgent is this ticket?"</span>,        <span class="hljs-string">"criteria"</span>: [<span class="hljs-string">"low"</span>, <span class="hljs-string">"medium"</span>, <span class="hljs-string">"high"</span>],    },}<span class="hljs-keyword">def</span> <span class="hljs-title function_">evaluate_ticket</span>(<span class="hljs-params">subject: <span class="hljs-built_in">str</span>, message: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]:    api_key = os.environ[<span class="hljs-string">"AI_GATEWAY_API_KEY"</span>]    payload = {        <span class="hljs-string">"model"</span>: MODEL,        <span class="hljs-string">"state"</span>: {<span class="hljs-string">"subject"</span>: subject, <span class="hljs-string">"message"</span>: message},        <span class="hljs-string">"questions"</span>: QUESTIONS,    }    <span class="hljs-keyword">with</span> httpx.Client(timeout=<span class="hljs-number">10.0</span>) <span class="hljs-keyword">as</span> client:        response = client.post(            <span class="hljs-string">f"<span class="hljs-subst">{GATEWAY_URL}</span>/v1/evaluate"</span>,            headers={<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">f"Bearer <span class="hljs-subst">{api_key}</span>"</span>},            json=payload,        )        response.raise_for_status()        <span class="hljs-keyword">return</span> response.json()[<span class="hljs-string">"answers"</span>]<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:    answers = evaluate_ticket(        subject=<span class="hljs-string">"Checkout fora do ar"</span>,        message=<span class="hljs-string">"Pagamentos falham há 20 minutos; 42 pedidos estão bloqueados."</span>,    )    <span class="hljs-built_in">print</span>(answers)</code></pre><p>Execute:</p><pre><code class="hljs language-bash">python jev_demo.py</code></pre><p>O formato exato inclui metadados definidos pelo serviço, mas o consumo relevante segue este desenho:</p><pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>  <span class="hljs-attr">"is_urgent"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"noul"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">0.97</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"department"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>    <span class="hljs-attr">"choice"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"technical"</span><span class="hljs-punctuation">,</span>    <span class="hljs-attr">"probabilities"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>      <span class="hljs-attr">"billing"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">0.01</span><span class="hljs-punctuation">,</span>      <span class="hljs-attr">"technical"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">0.96</span><span class="hljs-punctuation">,</span>      <span class="hljs-attr">"shipping"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">0.0</span><span class="hljs-punctuation">,</span>      <span class="hljs-attr">"general"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">0.03</span>    <span class="hljs-punctuation">}</span>  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"urgency"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"score"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">2.8</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span></code></pre><p>Valores acima são ilustrativos, não output prometido. O ganho estrutural está em conhecer os campos possíveis antes da requisição. Seu código ainda deve validar a resposta real.</p><h2 id="andersonlimadev-content-intuição-modelo-propõe-política-dispõe">Intuição: modelo propõe, política dispõe</h2><p>Pense no JEV como um sensor. Um sensor mede e carrega incerteza; ele não decide sozinho se uma esteira industrial deve parar. O controlador lê a medição, verifica limites, considera outras condições e escolhe a ação segura.</p><p>Aqui, o modelo produz julgamento:</p><pre><code class="hljs language-text">ticket → {urgente: 0.97, departamento: technical, score: 2.8}</code></pre><p>A aplicação produz política:</p><pre><code class="hljs language-python"><span class="hljs-keyword">if</span> result.is_urgent >= <span class="hljs-number">0.90</span> <span class="hljs-keyword">and</span> result.confidence >= <span class="hljs-number">0.80</span>:    page_on_call()<span class="hljs-keyword">elif</span> result.is_urgent >= <span class="hljs-number">0.60</span>:    enqueue_human_review()<span class="hljs-keyword">else</span>:    follow_normal_queue()</code></pre><p>Os cortes pertencem ao seu domínio. Eles não devem ficar escondidos em prompt, resposta do modelo ou regra do provedor.</p><h2 id="andersonlimadev-content-minha-fatia-vertical-em-fastapi">Minha fatia vertical em FastAPI</h2><p>Na <a href="https://lemon.dev.br/pt/loja/checkout/boilerplate-fastapi-clean-architecture" rel="nofollow">PR privada do POC FastAPI</a>, implementei um CRUD de tickets no mesmo padrão vertical já usado pelo projeto. O link registra a origem do estudo, mas o conteúdo não é acessível sem permissão. Por isso, os trechos úteis e sanitizados estão reproduzidos aqui; nenhuma credencial ou configuração privada foi copiada.</p><pre><code class="hljs language-mermaid">flowchart LR    C[Cliente HTTP] --> R[Ticket Router]    R --> S[Ticket Service]    S --> J[JevClient]    J --> G[Vercel AI Gateway]    G --> M[typesafe-ai/jev]    S --> P[Ticket Repository]    P --> D[(MongoDB)]    J -. timeout ou erro .-> F[Fallback sem avaliação]    F --> P</code></pre><p>O <code>JevClient</code> é um adapter fino. Ele conhece URL, autenticação, timeout e envelope HTTP. O service conhece o caso de uso e decide o que fazer quando o adapter falha.</p><pre><code class="hljs language-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Any</span><span class="hljs-keyword">import</span> httpx<span class="hljs-keyword">class</span> <span class="hljs-title class_">JevEvaluationError</span>(<span class="hljs-title class_ inherited__">RuntimeError</span>):    <span class="hljs-keyword">pass</span><span class="hljs-keyword">class</span> <span class="hljs-title class_">JevClient</span>:    <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">        self,        *,        api_key: <span class="hljs-built_in">str</span>,        model: <span class="hljs-built_in">str</span> = <span class="hljs-string">"typesafe-ai/jev"</span>,        base_url: <span class="hljs-built_in">str</span> = <span class="hljs-string">"https://ai-gateway.vercel.sh"</span>,        timeout: <span class="hljs-built_in">float</span> = <span class="hljs-number">10.0</span>,    </span>) -> <span class="hljs-literal">None</span>:        self.api_key = api_key        self.model = model        self.base_url = base_url.rstrip(<span class="hljs-string">"/"</span>)        self.timeout = timeout    <span class="hljs-keyword">def</span> <span class="hljs-title function_">evaluate</span>(<span class="hljs-params">self, state: <span class="hljs-type">Any</span>, questions: <span class="hljs-built_in">dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]</span>) -> <span class="hljs-built_in">dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]:        <span class="hljs-keyword">try</span>:            <span class="hljs-keyword">with</span> httpx.Client(timeout=self.timeout) <span class="hljs-keyword">as</span> client:                response = client.post(                    <span class="hljs-string">f"<span class="hljs-subst">{self.base_url}</span>/v1/evaluate"</span>,                    headers={<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">f"Bearer <span class="hljs-subst">{self.api_key}</span>"</span>},                    json={                        <span class="hljs-string">"model"</span>: self.model,                        <span class="hljs-string">"state"</span>: state,                        <span class="hljs-string">"questions"</span>: questions,                    },                )                response.raise_for_status()                body = response.json()        <span class="hljs-keyword">except</span> (httpx.HTTPError, ValueError, KeyError) <span class="hljs-keyword">as</span> error:            <span class="hljs-keyword">raise</span> JevEvaluationError(<span class="hljs-string">"evaluation unavailable"</span>) <span class="hljs-keyword">from</span> error        answers = body.get(<span class="hljs-string">"answers"</span>)        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-built_in">isinstance</span>(answers, <span class="hljs-built_in">dict</span>):            <span class="hljs-keyword">raise</span> JevEvaluationError(<span class="hljs-string">"invalid evaluation contract"</span>)        <span class="hljs-keyword">return</span> answers</code></pre><p>O fluxo do <code>POST /tickets</code> preserva a função principal mesmo sem IA:</p><pre><code class="hljs language-mermaid">sequenceDiagram    actor User as Cliente    participant API as FastAPI Router    participant Service as Ticket Service    participant Jev as JevClient    participant Gateway as Vercel AI Gateway    participant DB as Repository    User->>API: POST /tickets    API->>Service: create(subject, message)    Service->>Jev: evaluate(state, questions)    Jev->>Gateway: POST /v1/evaluate    alt resposta válida        Gateway-->>Jev: answers tipadas        Jev-->>Service: answers        Service->>DB: save(ticket + evaluation)    else timeout, HTTP error ou contrato inválido        Gateway--xJev: falha        Jev-->>Service: JevEvaluationError        Service->>DB: save(ticket + evaluation null)    end    DB-->>API: ticket persistido    API-->>User: 201 Created</code></pre><p>Esse detalhe mudou o risco do experimento. JEV enriquece o ticket; não possui a criação. Em falha, o dado principal continua entrando no sistema e pode ser triado manualmente.</p><h2 id="andersonlimadev-content-contratos-e-ownership">Contratos e ownership</h2><p>Uma integração confiável precisa responder “quem é dono?” antes de responder “qual modelo?”.</p><table><thead><tr><th>Responsabilidade</th><th>Dono</th><th>Evidência</th><th>Reversão</th></tr></thead><tbody><tr><td>esquema das perguntas</td><td>time do domínio</td><td>contrato versionado e revisão de código</td><td>voltar à versão anterior</td></tr><tr><td>chamada ao Gateway</td><td>adapter de infraestrutura</td><td>métricas de latência/status e testes HTTP fake</td><td>desligar provider via flag</td></tr><tr><td>validação da resposta</td><td>boundary da aplicação</td><td>erros de schema e fixtures canônicas</td><td>encaminhar para fallback</td></tr><tr><td>cortes e ação</td><td>service/policy</td><td>decisão registrada com versão da policy</td><td>modo <code>shadow</code> ou <code>advisory</code></td></tr><tr><td>segredo do Gateway</td><td>plataforma/secret manager</td><td>auditoria de acesso e rotação</td><td>revogar chave</td></tr><tr><td>qualidade do modelo</td><td>owner do produto</td><td>eval por segmento e revisão de erros</td><td>regra determinística/manual</td></tr></tbody></table><p>O modelo nunca deve receber permissão implícita para executar uma ação sensível. Ele fornece evidência para uma policy que o código controla.</p><h2 id="andersonlimadev-content-do-brinquedo-para-produção">Do brinquedo para produção</h2><p>O script mínimo ensina endpoint e payload. Ele omite pontos que importam sob carga ou incidente:</p><ol><li><strong>Validação estrutural e semântica.</strong> Verifique IDs esperados, tipo de cada resposta, opções permitidas, limites <code>[0, 1]</code>, soma das probabilidades e faixa do score. Pydantic ajuda, mas tipos válidos não provam decisão correta.</li><li><strong>Cliente reutilizável.</strong> Não abra uma conexão por request em carga alta. Injete <code>httpx.AsyncClient</code> com lifecycle controlado pelo FastAPI.</li><li><strong>Timeout e orçamento de retry.</strong> Retry cego pode duplicar custo e piorar congestionamento. Restrinja a erros transitórios, use backoff com jitter e mantenha deadline total.</li><li><strong>Idempotência.</strong> Persistência e avaliação podem terminar em ordens diferentes. Defina chave idempotente, status <code>pending/evaluated/failed</code> ou outbox se reprocessamento for necessário.</li><li><strong>Observabilidade sem vazar dados.</strong> Registre request ID, versão do contrato, modelo, latência, status, rota tomada e custo. Não grave ticket completo, bearer token ou PII por conveniência.</li><li><strong>Concorrência e escala horizontal.</strong> Estado de retry, locks e fila não podem morar na memória de uma única instância. Workers devem conseguir reprocessar por ID, com claim atômico e deduplicação.</li><li><strong>Versionamento.</strong> Guarde versão da pergunta, policy e modelo junto à decisão. <code>typesafe-ai/jev</code> é o ID do Gateway; a TypeSafe documentava <code>jev-latest</code> como alias de <code>jev-1.13.0</code> em 19 de setembro de 2026. Aliases facilitam upgrades, mas reduzem reprodutibilidade.</li></ol><h2 id="andersonlimadev-content-seis-falhas-que-aparecem-depois-da-demo">Seis falhas que aparecem depois da demo</h2><h3 id="andersonlimadev-content-1-o-gateway-está-indisponível">1. O Gateway está indisponível</h3><p>Timeouts, <code>429</code>, <code>5xx</code> e falhas de rede acontecem. Se triagem é enriquecimento, salve o ticket com <code>evaluation: null</code>, emita métrica e reprocese depois. Se a decisão protege uma ação irreversível, falhe fechado ou exija humano.</p><h3 id="andersonlimadev-content-2-a-resposta-passa-no-json-mas-viola-o-contrato">2. A resposta passa no JSON, mas viola o contrato</h3><p><code>department="sales"</code> não deve entrar se o enum só aceita quatro times. Uma probabilidade <code>1.2</code> também não. Valide antes de persistir ou agir. Resposta inválida é falha de integração, não “melhor esforço”.</p><h3 id="andersonlimadev-content-3-confiança-alta-decisão-errada">3. Confiança alta, decisão errada</h3><p>Confiança não substitui acurácia. Meça falsos negativos de urgência e erros por idioma, produto e tipo de cliente. Um corte global pode esconder desempenho ruim num segmento pequeno.</p><h3 id="andersonlimadev-content-4-o-input-contém-instrução-maliciosa">4. O input contém instrução maliciosa</h3><p>Texto do ticket é dado não confiável. A superfície é menor do que em geração com tools, mas prompt injection ainda pode influenciar classificação. Não inclua segredos no estado; mantenha ações fora do modelo; teste entradas adversariais.</p><h3 id="andersonlimadev-content-5-custo-muda-sem-mudança-de-código">5. Custo muda sem mudança de código</h3><p>Em 19 de setembro de 2026, a página de pricing do Gateway documentava US$ 5 mensais para times no free tier, enquanto superfícies do catálogo mostravam JEV como “Free” e o detalhe do modelo exibia US$ 0,04 por milhão. Essa divergência é motivo para tratar preço como snapshot, medir uso real e configurar alertas. Comprar créditos remove o crédito mensal gratuito daquele time, segundo a documentação vigente.</p><h3 id="andersonlimadev-content-6-um-alias-muda-o-comportamento">6. Um alias muda o comportamento</h3><p>Atualização de modelo pode alterar distribuição das respostas sem quebrar schema. Rode eval antes de promover nova versão. Guarde versão efetiva quando o provedor a expuser e mantenha rollback para modelo ou policy anterior.</p><h2 id="andersonlimadev-content-adoção-incremental-observe-antes-de-automatizar">Adoção incremental: observe antes de automatizar</h2><p>Automação não precisa nascer com permissão de agir.</p><table><thead><tr><th>Modo</th><th>Comportamento</th><th>Critério para avançar</th></tr></thead><tbody><tr><td><code>offline</code></td><td>roda eval em dataset histórico</td><td>baseline e taxonomia aceitos</td></tr><tr><td><code>shadow</code></td><td>avalia tráfego real, sem afetar rota</td><td>cobertura, latência e erros conhecidos</td></tr><tr><td><code>advisory</code></td><td>mostra sugestão ao operador</td><td>concordância e override medidos</td></tr><tr><td><code>enforce</code></td><td>policy executa ações limitadas</td><td>SLO, cortes e rollback aprovados</td></tr></tbody></table><p>Eu comecei com dependency injection. Nos testes FastAPI, <code>get_jev_client</code> é substituído por um fake determinístico e por outro que lança erro. Isso cobre caminho feliz e degradação sem consumir API ou depender de credencial real.</p><p>A mesma arquitetura apareceu em duas PRs públicas do meu hub de skills:</p><ul><li><a href="https://github.com/Andersonlimahw/lemon-ai-hub/pull/38">PR #38 — decision-native routing</a>: adicionou modos <code>heuristic</code>, <code>shadow</code>, <code>advisory</code> e <code>enforce</code>, além de um envelope tipado para decisões entre estágios. Merge em 19 de setembro de 2026.</li><li><a href="https://github.com/Andersonlimahw/lemon-ai-hub/pull/40">PR #40 — typed decision engineering</a>: tornou o padrão independente de provedor, com schemas, validação semântica, composição determinística, roteamento por incerteza e benchmark de custo/tokens. Merge em 19 de setembro de 2026.</li></ul><p>O ponto não é colocar JEV em todo lugar. É separar julgamento, contrato e autoridade de execução para poder trocar o provider sem redesenhar o domínio.</p><h2 id="andersonlimadev-content-o-mesmo-padrão-dentro-do-meu-harness">O mesmo padrão dentro do meu harness</h2><p>Depois da POC FastAPI, levei a ideia para o harness que uso no dia a dia. O caso está documentado em duas PRs abertas, não em um exemplo inventado:</p><ul><li><a href="https://github.com/andersonlimahw/lemon-code/pull/25">Lemon Code PR #25 — estratégia de roteamento JEV</a>: adiciona JEV ao Auto Dispatch, chama <code>typesafe-ai/jev</code> pelo Vercel AI Gateway e mantém uma réplica local determinística, <code>Builtin One</code>, para fallback.</li><li><a href="https://github.com/andersonlimahw/lemon-code-app/pull/13">Lemon Code App PR #13 — proveniência JEV no app macOS</a>: transporta <code>route.jev</code> de forma aditiva no RPC e mostra fonte, modo, provider/modelo, probabilidade, confiança e fallback na interface.</li></ul><p>O PR do core inclui typecheck, 849 testes, 2.879 assertions, 50 testes focados e smoke live com cinco casos. O benchmark local mediu média de <code>0,070 ms</code> antes e <code>72,177 ms</code> depois; o smoke remoto, uma execução por caso, mediu média de <code>536,641 ms</code>. São números da POC, datados de 20 de setembro de 2026, não SLO nem benchmark de produção. O smoke observou respostas tipadas e fallbacks; isso prova integração exercitada, não qualidade estatística suficiente para automatizar decisões críticas.</p><pre><code class="hljs language-mermaid">flowchart TD    Q[Pedido do usuário] --> R[Auto Dispatch]    R --> H{Modo JEV}    H -->|offline| B[Builtin One determinístico]    H -->|shadow| E[Avalia, não troca rota]    H -->|advisory| J[JEV via Vercel AI Gateway]    H -->|enforce| J    J --> G{Resposta válida + gates}    G -->|sim| D[Decisão candidata]    G -->|não| B    D --> P[Policy local]    P --> F[Provider/model/runtime final]    D --> T[RouteTrace + RPC]    T --> A[App macOS: proveniência visível]</code></pre><h3 id="andersonlimadev-content-human-in-the-loop-como-contrato-não-como-botão">Human-in-the-loop como contrato, não como botão</h3><p>O paradigma muda quando a incerteza vira parte do protocolo. O modelo não recebe autoridade para “escolher o próximo agente”; ele propõe uma decisão entre candidatos que o código já conhece. A policy local aplica dois gates no modo padrão do PR: <code>confidence >= 0.65</code> e <code>probability >= 0.55</code>. Resposta inválida, baixa confiança, timeout ou erro remoto caem para <code>Builtin One</code>.</p><pre><code class="hljs language-ts"><span class="hljs-keyword">type</span> <span class="hljs-title class_">JevGate</span> = {  <span class="hljs-attr">mode</span>: <span class="hljs-string">"shadow"</span> | <span class="hljs-string">"advisory"</span> | <span class="hljs-string">"enforce"</span>;  <span class="hljs-attr">confidenceFloor</span>: <span class="hljs-built_in">number</span>;  <span class="hljs-attr">probabilityFloor</span>: <span class="hljs-built_in">number</span>;};<span class="hljs-keyword">const</span> <span class="hljs-attr">defaultGate</span>: <span class="hljs-title class_">JevGate</span> = {  <span class="hljs-attr">mode</span>: <span class="hljs-string">"advisory"</span>,  <span class="hljs-attr">confidenceFloor</span>: <span class="hljs-number">0.65</span>,  <span class="hljs-attr">probabilityFloor</span>: <span class="hljs-number">0.55</span>,};</code></pre><p><code>shadow</code> mede sem alterar rota. <code>advisory</code> mostra sugestão para inspeção. <code>enforce</code> permite aplicar policy somente depois de evals e rollback aprovados. Cancelamento do caller aborta a avaliação sem inventar fallback; o erro remoto chega ao restante do sistema como classificação estável, não como stack trace de provider.</p><p>Essa separação preserva controle humano em três pontos: o conjunto de candidatos, os limites de confiança e a ação final. O ciclo real é <code>JEV → sugestão → operador vê proveniência → aceita ou faz override → decisão fica auditável</code>. A PR do App implementa visibilidade de proveniência, não um workflow completo de aprovação humana. A UI macOS recebe <code>route.jev</code> opcional; payloads legados continuam decodificando quando o core ainda não envia esse campo. Credencial, prompt bruto e decisão de provider permanecem no core. A interface apenas torna a proveniência auditável; o readiness router continua soberano.</p><p>O ganho não é “tirar humano do loop”. É tirar julgamento implícito do loop: quando o sistema está confiante e a policy permite, ele avança; quando não está, entrega evidência suficiente para uma pessoa revisar.</p><h2 id="andersonlimadev-content-eval-o-que-medir-antes-de-confiar">Eval: o que medir antes de confiar</h2></div>]]></content:encoded>
            <author>andersonlimadev</author>
        </item>
        <item>
            <title><![CDATA[Localização de vídeos: preserve a transcrição antes de apagar a legenda]]></title>
            <link>https://www.tabnews.com.br/weydub/por-que-remover-legendas-embutidas-vem-antes-da-localizacao-de-videos</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/weydub/por-que-remover-legendas-embutidas-vem-antes-da-localizacao-de-videos</guid>
            <pubDate>Sun, 20 Sep 2026 04:44:19 GMT</pubDate>
            <description><![CDATA[Transparência: esta publicação é da equipe Weydub e foi redigida com assistência de IA. O objetivo é explicar decisões de fluxo e limitações, não apresentar um teste independente do produ...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Transparência: esta publicação é da equipe Weydub e foi redigida com assistência de IA. O objetivo é explicar decisões de fluxo e limitações, não apresentar um teste independente do produto.</p><p>Uma legenda gravada nos pixels do vídeo não pode ser desativada como uma faixa SRT ou VTT. Colocar uma tradução por cima costuma deixar dois textos competindo pelo mesmo espaço. Mas apagar primeiro também pode ser um erro: se a legenda original for a única transcrição disponível, é preciso preservá-la antes da limpeza.</p><h2 id="weydub-content-a-ordem-depende-do-material-disponível">A ordem depende do material disponível</h2><ul><li><strong>Projeto original com faixa editável:</strong> prefira desativar a camada de texto e exportar uma versão limpa. Isso evita reconstruir pixels que o projeto já possui.</li><li><strong>Vídeo final com legenda embutida e sem roteiro:</strong> extraia o texto por OCR e confira os tempos antes de remover a legenda. Guarde uma cópia do vídeo original.</li><li><strong>Áudio inteligível, mas sem transcrição:</strong> gere uma transcrição por reconhecimento de fala e revise-a. OCR lê texto visível; reconhecimento de fala transcreve áudio. Um não substitui automaticamente o outro.</li><li><strong>Fundo complexo atrás do texto:</strong> a remoção por reconstrução estima a imagem escondida. Ela não recupera necessariamente os pixels originais. Rostos, mãos, texturas e movimentos rápidos exigem revisão quadro a quadro.</li></ul><h2 id="weydub-content-separe-limpeza-visual-e-localização-do-conteúdo">Separe limpeza visual e localização do conteúdo</h2><p>A limpeza deve acontecer antes da composição da nova legenda, mas não precisa vir antes da extração do texto ou da tradução. Trate o vídeo original, o vídeo limpo, a transcrição revisada e as traduções como arquivos separados. Assim, uma correção de terminologia não exige repetir a limpeza visual.</p><p>Para cada trecho, mantenha ao menos início, fim, texto original e texto traduzido. Por exemplo, se uma fala ocupa 2 segundos e a tradução contém 50 caracteres, a taxa é de 25 caracteres por segundo. Esse cálculo ajuda a identificar trechos densos; o limite aceitável depende do público, do idioma e da especificação de entrega. Não encurte automaticamente nomes, instruções ou avisos importantes só para cumprir um número.</p><h2 id="weydub-content-geração-de-legendas-tradução-e-dublagem">Geração de legendas, tradução e dublagem</h2><p>Depois da transcrição, revise nomes próprios, pontuação, falas sobrepostas e mudanças de locutor. Na tradução, preserve contexto e termos recorrentes. Ajuste quebras de linha e sincronização ao revisar o SRT ou VTT.</p><p>Na dublagem, o texto traduzido também precisa funcionar como fala. Compare duração, pausas e pronúncia; não presuma que a tradução adequada para leitura terá o mesmo ritmo em voz alta. Use vozes e materiais com autorização e revise a mistura com música e efeitos.</p><p>O <a href="https://weydub.com/" rel="nofollow">Weydub</a> reúne remoção de legendas incorporadas, geração de legendas, tradução e dublagem. É um produto comercial da nossa equipe. Essas etapas continuam exigindo revisão; não prometemos reconstrução perfeita nem dispensa de conferência humana.</p><h2 id="weydub-content-critérios-de-aprovação-de-uma-versão">Critérios de aprovação de uma versão</h2><ol><li>O texto de origem foi preservado antes de qualquer limpeza?</li><li>Há resíduos, borrões ou oscilações na região reconstruída durante cortes e movimento?</li><li>Cada legenda está dentro da duração do vídeo, com início anterior ao fim?</li><li>Nomes e termos mantêm a mesma tradução ao longo do material?</li><li>A voz está inteligível e as pausas acompanham o sentido, sem encobrir sons importantes?</li><li>O vídeo final foi assistido inteiro, além da inspeção de quadros isolados?</li></ol><p>Esse fluxo complementa a etapa de detecção e máscara: localizar texto é só uma parte do trabalho. Preservar fontes, separar versões e definir critérios de revisão evita que uma correção pequena obrigue a refazer todo o vídeo.</p></div>]]></content:encoded>
            <author>weydub</author>
        </item>
        <item>
            <title><![CDATA[[PITCH] - Vídeo Direct - Gerador de Vídeos de Chats 'fake' estilo Direct do Insta (DM)]]></title>
            <link>https://www.tabnews.com.br/jonwlf/pitch-video-direct-gerador-de-videos-de-chats-fake-estilo-direct-do-insta-dm</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/jonwlf/pitch-video-direct-gerador-de-videos-de-chats-fake-estilo-direct-do-insta-dm</guid>
            <pubDate>Sun, 20 Sep 2026 03:03:00 GMT</pubDate>
            <description><![CDATA[Fala galera, blz? Tempos atrás vi um user do X (https://x.com/bielgga) usar uma estratégia de marketing orgânico que parece dar muito certo: vídeos fake de conversas estilo direct do inst...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Fala galera, blz?</p><p>Tempos atrás vi um user do X (<a href="https://x.com/bielgga" rel="nofollow">https://x.com/bielgga</a>) usar uma estratégia de marketing orgânico que parece dar muito certo: vídeos fake de conversas estilo direct do insta (DM). Uma pena que ele descontinuou e o MVP era muito focado no SaaS dele (o PuxeAssunto).</p><p>Bom, eu decidi criar o meu com com a ideia de divulgar meus projetos pessoais que estão "prontos" (sempre em densenvolvimento kkk).</p><p>A ideia inicial foi ter uma versão free e uma versão PRO. No caso da versão free a geração do vídeo é feita no navegador da pessoa, limitado a 720p e exportação em WEBM.</p><p>Já na versão PRO, coloquei recursos como tema (claro/escuro), cor do tema (dos balões), imagens pré-definidas do contato (busquei no Pexels), seleção dos sons do chat (tanto do recebimento quanto do envio) e no tocante a qualidade, é bem superior pois eu gero em 1080p no servidor com o Remotion.</p><p>Outro recurso que decidi colocar é o envio de imagens no chat com simulação de abertura, que ficou bem bacana também (resultado aqui: <a href="https://x.com/jonwlf/status/2101504846306083130" rel="nofollow">https://x.com/jonwlf/status/2101504846306083130</a>).</p><p>Pra essa solução usei basicamente Node.js pro servidor e React pro front. Pro back foi necessário também PostgreSQL, Redis, Resend (para envio de e-mails) e AbacatePay para pagamentos via PIX. Pra geração de vídeos no back foi utilizado Remotion e FFmpeg, é o que menos custou de processamento perante outras opções, pois eu uso uma VPS da Hostinger compartilhada com meus outros projetos.</p><p>Por se tratar de um MVP ainda não comprei um domínio, então ta no meu hub de soluções: <a href="https://direct.jon.app.br" rel="nofollow">https://direct.jon.app.br</a></p><p>Qualquer feedback é bem vindo, vlw!</p></div>]]></content:encoded>
            <author>jonwlf</author>
        </item>
        <item>
            <title><![CDATA[Office 2024 ainda faz sentido em 2026? Acho que depende mais do seu jeito de trabalhar]]></title>
            <link>https://www.tabnews.com.br/kiraxu/office-2024-ainda-faz-sentido-em-2026-acho-que-depende-mais-do-seu-jeito-de-trabalhar</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/kiraxu/office-2024-ainda-faz-sentido-em-2026-acho-que-depende-mais-do-seu-jeito-de-trabalhar</guid>
            <pubDate>Sun, 20 Sep 2026 02:02:02 GMT</pubDate>
            <description><![CDATA[Nos últimos anos, praticamente tudo virou assinatura. Streaming, armazenamento, ferramentas de design, inteligência artificial e, claro, software de produtividade. Por isso, uma coisa no...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Nos últimos anos, praticamente tudo virou assinatura.</p><p>Streaming, armazenamento, ferramentas de design, inteligência artificial e, claro, software de produtividade.</p><p>Por isso, uma coisa no Office 2024 me chamou atenção: enquanto boa parte do mercado está tentando nos acostumar a pagar todos os meses, ele continua seguindo uma lógica bem mais tradicional — você compra uma versão e usa aquela versão.</p><p>Isso me fez pensar em uma pergunta que parece simples, mas não é:</p><p>em 2026, ainda faz sentido comprar uma versão do Office sem assinatura?</p><p>Na minha visão, a resposta depende muito menos de qual produto é "melhor" e muito mais de como você realmente usa o computador.</p><p>O que muda na prática?</p><p>O Office 2024 continua trazendo aplicativos que praticamente todo mundo conhece, como Word, Excel e PowerPoint.</p><p>A diferença mais importante não está exatamente nesses nomes, mas no modelo.</p><p>Segundo a própria Microsoft, o Office 2024 é uma compra única para um computador. Já o Microsoft 365 funciona como assinatura e recebe continuamente novos recursos, além de incluir serviços conectados à nuvem.</p><p>Ou seja, são propostas diferentes.</p><p>Quem gosta de sempre receber funções novas, trabalha em vários dispositivos e depende bastante de recursos online provavelmente vai enxergar mais valor no Microsoft 365.</p><p>Mas existe outro tipo de usuário.</p><p>É aquela pessoa que abre o Word para trabalhar, usa Excel para planilhas, prepara algumas apresentações no PowerPoint e simplesmente quer que essas ferramentas continuem funcionando.</p><p>Para esse perfil, pagar uma assinatura indefinidamente nem sempre parece tão interessante.</p><p>Nem todo mundo precisa de novidades todos os meses</p><p>Acho que esse é um ponto que muitas comparações acabam ignorando.</p><p>Quando falamos de software, é fácil cair na ideia de que a opção com mais recursos é automaticamente a melhor.</p><p>Mas quantos desses recursos realmente entram na nossa rotina?</p><p>Eu consigo entender perfeitamente alguém preferindo receber continuamente novidades e integrações. Para trabalho colaborativo, empresas ou quem vive dentro do ecossistema da Microsoft, isso pode fazer bastante diferença.</p><p>Por outro lado, também consigo entender quem pensa:</p><p>"Eu só quero Word, Excel e PowerPoint funcionando no meu computador."</p><p>Nesse cenário, uma licença permanente volta a fazer sentido.</p><p>Não porque seja mais moderna.</p><p>Justamente porque é mais simples.</p><p>O Office 2024 também não ficou parado no tempo</p><p>Outra impressão que eu tinha era que uma versão permanente seria praticamente uma versão antiga do Office com outro nome.</p><p>Não é exatamente assim.</p><p>A Microsoft adicionou ao Office 2024 melhorias como novas funções no Excel, melhorias de acessibilidade, recuperação de sessão no Word e mudanças visuais.</p><p>Não é o mesmo ritmo de evolução do Microsoft 365 — e nem pretende ser.</p><p>O Office 2024 funciona mais como uma fotografia daquele momento do produto: você recebe aquele conjunto de funcionalidades, atualizações de segurança e correções, mas não deve esperar receber todas as novidades que aparecerem posteriormente no Microsoft 365.</p><p>E existe uma consequência importante disso.</p><p>Quando surgir uma futura grande versão do Office, quem comprou o Office 2024 não recebe automaticamente essa nova versão.</p><p>É um detalhe que vale considerar antes de escolher apenas olhando para o preço.</p><p>Foi justamente o preço que me fez pensar nisso</p><p>Recentemente encontrei um vídeo discutindo justamente como o preço do Office 2024 está ficando curioso quando comparado com outros produtos da própria Microsoft.</p><p>Achei interessante porque ele levanta uma discussão que vai além de simplesmente "comprar barato".</p><p>A pergunta passa a ser:</p><p>quanto vale para você deixar de ter mais uma assinatura mensal?</p><p>Para quem quiser assistir, deixo o vídeo aqui: <a href="https://www.youtube.com/watch?v=o1ojh5K_-kI&#x26;t=17s" rel="nofollow">https://www.youtube.com/watch?v=o1ojh5K_-kI&#x26;t=17s</a></p><p>O vídeo me parece um bom complemento para quem está tentando entender onde o Office 2024 se encaixa hoje, especialmente considerando que existem tantas opções diferentes de licença e assinatura.</p><p>Eu não escolheria apenas pelo preço</p><p>Se eu estivesse decidindo entre Office 2024 e Microsoft 365, começaria olhando para a rotina, não para a tabela de preços.</p><p>Quem trabalha em vários dispositivos, precisa de armazenamento na nuvem, colaboração constante e quer sempre as funções mais recentes provavelmente vai aproveitar melhor uma assinatura.</p><p>Quem trabalha principalmente em um computador e prefere uma ferramenta mais previsível pode enxergar mais sentido no Office 2024.</p><p>Nenhuma das duas escolhas é automaticamente correta.</p><p>O erro, na minha opinião, é pagar todos os meses por benefícios que você praticamente nunca usa — ou comprar uma versão permanente esperando receber funcionalidades que fazem parte da proposta de uma assinatura.</p><p>No fim, acho interessante ainda existir essa escolha.</p><p>Em uma época em que quase todo software tenta transformar o usuário em assinante, poder simplesmente comprar uma ferramenta e continuar usando aquela versão ainda tem valor para algumas pessoas.</p><p>E vocês?</p><p>Para software que vocês usam todos os dias, preferem pagar uma vez por uma versão fixa ou manter uma assinatura para receber atualizações e novos recursos?</p></div>]]></content:encoded>
            <author>kiraxu</author>
        </item>
        <item>
            <title><![CDATA[Minha Game Engine 3D]]></title>
            <link>https://www.tabnews.com.br/vsantos1/minha-game-engine-apos-1-ano</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/vsantos1/minha-game-engine-apos-1-ano</guid>
            <pubDate>Sun, 20 Sep 2026 01:39:38 GMT</pubDate>
            <description><![CDATA[Comecei este projeto há quase um ano e venho trabalhando nele desde então. A ideia inicial era criar uma game engine e quem sabe um editor (essa parte fica para a próxima). Video demo da...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Comecei este projeto há quase um ano e venho trabalhando nele desde então. A ideia inicial era criar uma game engine e quem sabe um editor (essa parte fica para a próxima).</p><p><a href="https://www.youtube.com/watch?v=dGs6ExRHMeQ" rel="nofollow">Video demo da game engine</a></p><p><img src="https://cdn.discordapp.com/attachments/747589473130250411/1551044180443271268/796401770_4105592239575727_2179252888387159347_n.png?ex=6ab089f5&#x26;is=6aaf3875&#x26;hm=8f6a1ecb6d4a958d4f88033abac54e98c019f02831145a3e6be0f1f50fefb298&#x26;" alt="img"></p><p>O principal objetivo sempre foi aprender. O projeto começou a partir do curso da Udemy Game Engine Development with C++ and OpenGL, do Alex Kulbitsky, que usei como ponto de partida para entender os fundamentos de uma engine. A partir daí, fui expandindo o projeto por conta própria, criando novos sistemas, refatorando partes da arquitetura e buscando otimizar o que já existia.</p><ul><li>Canvas de UI e widgets como Text, Button, Image, Scroll e Dropdown</li><li>Cascade Shadow Mapping</li><li>Skeletal Animation</li><li>Sistema de física com detecção e resposta a colisões</li><li>Prefabs</li><li>Pré-processador de shaders</li><li>Camada de abstração gráfica com suporte a OpenGL 3.3 e OpenGL ES 3.0</li><li>Pós-processamento, incluindo Tone Mapping, FXAA, Bloom e SSAO</li><li>Gerenciamento de assets</li><li>Frustum Culling</li><li>Python Scripting</li><li>Carregamento de modelos nos formatos OBJ e glTF, com possibilidade de utilizar o Assimp ampliando o suporte a outros formatos como FBX</li><li>Batching e Instancing</li><li>Suporte multiplataforma para Windows, Linux, macOS e WebGL</li></ul><p>Também venho trabalhando no suporte para Android e iOS. A engine foi projetada de forma que a parte de "Windowing" e "Event Handling" possa ser substituída sem grandes mudanças no restante do código. Atualmente utilizo GLFW, mas a ideia é futuramente implementar essas camadas diretamente sobre as APIs nativas de cada plataforma, utilizando UIKit/UIView no iOS e Android NDK/ANativeWindow no Android, ou simplesmente utilizar SDL3.</p><p>** Aprendi até se virar com blender **</p></div>]]></content:encoded>
            <author>vsantos1</author>
        </item>
        <item>
            <title><![CDATA[Despedida do tabnews...]]></title>
            <link>https://www.tabnews.com.br/macnator/despedida-do-tabnews</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/macnator/despedida-do-tabnews</guid>
            <pubDate>Sat, 19 Sep 2026 22:48:37 GMT</pubDate>
            <description><![CDATA[É com muita gratidão que escrevo este post. O TabNews foi um espaço muito importante para mim. Aqui pude publicar, aprender e, principalmente, contar com a leitura de vocês. Quero agradec...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>É com muita gratidão que escrevo este post. O TabNews foi um espaço muito importante para mim. Aqui pude publicar, aprender e, principalmente, contar com a leitura de vocês.</p><p>Quero agradecer de coração a cada pessoa que leu, comentou, votou, compartilhou ou simplesmente passou por aqui. Cada leitura, cada feedback, cada interação fez diferença. Mesmo quem leu em silêncio ajudou a manter a motivação.</p><p>A partir de agora, vou concentrar meus artigos apenas no LinkedIn. Não é um adeus, é uma mudança de casa. Se você quiser continuar lendo o que eu escrevo, me segue ou me adiciona por lá. Vai ser um prazer continuar essa conversa.</p><p>👉 LinkedIn: <a href="https://www.linkedin.com/in/edilson-maia-favero-a46510368/" rel="nofollow">https://www.linkedin.com/in/edilson-maia-favero-a46510368/</a></p><p>Obrigado por tudo, TabNews. E obrigado a você que leu até aqui.</p></div>]]></content:encoded>
            <author>macnator</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Cansei de abrir 10 painéis (Oracle, AWS, Hostinger, Vercel): criei um Hub Multi-Cloud com IA para controlar tudo em 1 lugar]]></title>
            <link>https://www.tabnews.com.br/viniScooper/cansei-de-abrir-10-paineis-oracle-aws-hostinger-vercel-criei-um-hub-multi-cloud-com-ia-para-controlar-tudo-em-1-lugar</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/viniScooper/cansei-de-abrir-10-paineis-oracle-aws-hostinger-vercel-criei-um-hub-multi-cloud-com-ia-para-controlar-tudo-em-1-lugar</guid>
            <pubDate>Sat, 19 Sep 2026 17:42:42 GMT</pubDate>
            <description><![CDATA[Quem gerencia mais de uma aplicação na nuvem provavelmente conhece esta rotina: • AWS para verificar um serviço; • Oracle Cloud para gerenciar uma VM; • Hostinger ou Hetzner para conferir...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Quem gerencia mais de uma aplicação na nuvem provavelmente conhece esta rotina:</p><p>• AWS para verificar um serviço;<br>• Oracle Cloud para gerenciar uma VM;<br>• Hostinger ou Hetzner para conferir uma VPS;<br>• Vercel para acompanhar o deploy do frontend;<br>• Cloudflare para DNS e túneis;<br>• PuTTY, MobaXterm e ferramentas de banco para acessar os servidores.</p><p>No fim do dia, são dezenas de abas abertas, diferentes painéis, credenciais e interfaces para realizar tarefas que poderiam estar centralizadas.</p><p>Foi pensando nisso que comecei a construir o <strong>CloudOps Hub</strong>: uma plataforma para centralizar infraestrutura multi-cloud em um único painel, com um copiloto de IA integrado.</p><h3 id="viniscooper-content--a-proposta-um-single-pane-of-glass-para-cloudops">🚀 A proposta: um Single Pane of Glass para CloudOps</h3><p>A ideia é permitir que desenvolvedores e equipes possam conectar, provisionar e gerenciar diferentes recursos de infraestrutura sem precisar alternar constantemente entre provedores.</p><h3 id="viniscooper-content-1-provisionamento-de-vpsvm">1. Provisionamento de VPS/VM</h3><p>Automatizar a criação de máquinas virtuais:</p><p>• Criação de instâncias em poucos cliques;<br>• Provisionamento automatizado na Oracle Cloud;<br>• Tratamento de falhas de capacidade e novas tentativas;<br>• Notificações sobre o resultado do provisionamento.</p><h3 id="viniscooper-content-2-deploy-e-gerenciamento-de-aplicações">2. Deploy e gerenciamento de aplicações</h3><p>Independentemente de a infraestrutura estar na Oracle, AWS, Hostinger ou outro provedor:</p><p>• Clonagem de repositórios GitHub;<br>• Deploy via Docker Compose;<br>• Execução de aplicações Node.js/PM2;<br>• Monitoramento de CPU, RAM, disco e processos;<br>• Arquitetura <strong>Zero-Agent</strong>, utilizando SSH para operações e coleta de informações.</p><h3 id="viniscooper-content-3-gestão-centralizada-de-storage">3. Gestão centralizada de Storage</h3><p>Um único lugar para trabalhar com diferentes storages:</p><p>• OCI Object Storage;<br>• S3;<br>• Criação e inspeção de buckets;<br>• Upload de assets;<br>• Rotinas de backup;<br>• Políticas de retenção para bancos de dados.</p><h3 id="viniscooper-content-4-multi-cloud-e-redução-de-vendor-lock-in">4. Multi-cloud e redução de Vendor Lock-in</h3><p>Uma das ideias mais interessantes do projeto é facilitar a migração entre provedores.</p><p>Por exemplo:</p><p><strong>Oracle → Hostinger</strong><br><strong>AWS → VPS</strong><br><strong>VPS → AWS</strong></p><p>O Hub pode analisar os recursos utilizados, gerar infraestrutura Terraform e auxiliar na transferência dos dados e serviços.</p><p>A proposta é tornar a infraestrutura mais portável, em vez de ficar totalmente dependente de um único provedor.</p><h3 id="viniscooper-content-5-deploy-completo-backend--frontend">5. Deploy completo: Backend + Frontend</h3><p>O ciclo de deploy também fica centralizado:</p><p><strong>Backend</strong><br>• GitFlow;<br>• Deploy de <code>develop</code> → <code>main</code>;<br>• Rollback de emergência;<br>• Monitoramento dos serviços.</p><p><strong>Frontend</strong><br>• Integração com Vercel;<br>• Monitoramento de builds;<br>• Redeploy;<br>• Acompanhamento do status dos deployments.</p><h3 id="viniscooper-content-6-segurança-com-cloudflare-zero-trust">6. Segurança com Cloudflare Zero Trust</h3><p>Outra parte importante é reduzir a exposição da infraestrutura.</p><p>A ideia é evitar deixar portas como SSH ou banco de dados abertas diretamente para a internet, utilizando <strong>Cloudflare Zero Trust/Tunnels</strong> para criar caminhos de acesso controlados.</p><hr><h2 id="viniscooper-content--o-cérebro-odisseu-ai">🤖 O cérebro: Odisseu AI</h2><p>Para lidar com a complexidade de uma infraestrutura multi-cloud, integrei o <strong>Odisseu AI</strong>.</p><p>Ele utiliza <strong>RAG + LangChain</strong> para trabalhar com informações específicas do ambiente.</p><p>Em vez de responder apenas com conhecimento genérico, o agente pode consultar informações da infraestrutura, como:</p><p>• VMs;<br>• containers;<br>• portas;<br>• domínios;<br>• buckets;<br>• serviços;<br>• histórico de incidentes;<br>• métricas e telemetria.</p><p>Assim, perguntas como:</p><blockquote><p>"Odisseu, qual VM está com maior pressão de memória?"</p></blockquote><p>ou:</p><blockquote><p>"Por que o container da API reiniciou?"</p></blockquote><p>podem ser respondidas utilizando os dados reais da infraestrutura.</p><p>A ideia é evoluir isso para que o agente também consiga diagnosticar problemas, gerar os comandos necessários e, futuramente, executar determinadas ações de forma controlada.</p><hr><h2 id="viniscooper-content-️-stack">🛠️ Stack</h2><p><strong>Frontend</strong></p><ul><li>Next.js 14</li><li>React</li><li>Tailwind CSS</li></ul><p><strong>Backend</strong></p><ul><li>Node.js</li><li>Fastify</li><li>SSH2</li><li>OCI SDK</li></ul><p><strong>IA</strong></p><ul><li>LangChain</li><li>RAG</li><li>Embeddings locais</li></ul><p><strong>Infraestrutura</strong></p><ul><li>Docker</li><li>Terraform</li><li>Cloudflare Zero Trust</li><li>Vercel</li></ul><hr><h2 id="viniscooper-content--código-aberto">🌎 Código aberto</h2><p>A base do projeto está disponível no GitHub:</p><p><a href="https://github.com/ViniScooper/CloudOps_Hub">https://github.com/ViniScooper/CloudOps_Hub</a></p><p>O objetivo também é usar o projeto como laboratório para explorar <strong>Cloud Engineering + DevOps + IA + Multi-cloud</strong> em um único produto.</p><p>Quero abrir a discussão com a comunidade:</p><p><strong>Quantos painéis de cloud vocês precisam abrir no dia a dia para manter seus projetos funcionando?</strong></p><p>E mais importante:</p><p><strong>Vocês usariam uma ferramenta open source que centralizasse provisionamento, deploy, servidores, storage, monitoramento e IA em um único painel?</strong></p><p>Quero ouvir principalmente quem trabalha diariamente com AWS, Oracle Cloud, Azure, VPS, Vercel, Cloudflare e infraestrutura própria.</p></div>]]></content:encoded>
            <author>viniScooper</author>
        </item>
        <item>
            <title><![CDATA[Precisando de um rumo prático: 19 anos, objetivo virar Dev Web com IA]]></title>
            <link>https://www.tabnews.com.br/Krowmis/precisando-de-um-rumo-pratico-19-anos-objetivo-virar-dev-web-com-ia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Krowmis/precisando-de-um-rumo-pratico-19-anos-objetivo-virar-dev-web-com-ia</guid>
            <pubDate>Sat, 19 Sep 2026 16:47:21 GMT</pubDate>
            <description><![CDATA[Olá a todos! Meu nome é Gustavo e tenho 19 anos, moro na Itália e tô num momento da vida em que preciso fazer dar certo de qualquer jeito. Estou completando meu ensino médio pelo Encceja...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Olá a todos!<br>Meu nome é Gustavo e tenho 19 anos, moro na Itália e tô num momento da vida em que preciso fazer dar certo de qualquer jeito. Estou completando meu ensino médio pelo Encceja exterior esse ano e meu foco total agora é migrar pra programação com foco em dev web e no uso de ferramentas de IA.</p><p>Eu já tentei fazer uns cursos tradicionais no passado (tipo Alura), mas confesso que o formato de só ver aula e não conseguir aplicar de verdade o que eu aprendi não funcionou comigo. Travei. Percebi que aprendo muito mais rápido na prática, criando projetos reais e quebrando a cabeça pra resolver problemas de verdade. Mas atualmente meu momento é bem complicado e não sei por onde recomeçar, estou implorando por ajuda porque meu sonho é poder ter a minha independência ganhar meu dinheiro com o meu trabalho e poder sair da casa dos meus pais.</p><p>Meu objetivo é construir um portfólio forte no GitHub pra compensar o fato de não ter faculdade nem experiência formal na área.</p><p>Tendo em vista o mercado de hoje, queria pedir um conselho sincero de quem já tá na área ou passou por uma situação parecida com a minha</p><p>Se vocês estivessem no meu lugar hoje, qual stack básica focariam pra construir os primeiros projetos práticos?</p><p>Como vocês usam IA no dia a dia pra acelerar o aprendizado e a escrita de código sem virar uma "muleta"?</p><p>Algum dev com mais bagagem estaria aberto a trocar uma ideia, dar umas dicas de código de vez em quando ou precisa de ajuda/aprendiz em algum projeto open source? Tô com muita vontade de colocar a mão na massa.</p><p>Qualquer dica, caminho ou puxão de orelha construtivo é super bem-vindo. muito obrigado</p></div>]]></content:encoded>
            <author>Krowmis</author>
        </item>
        <item>
            <title><![CDATA[Como projetar dados de mercado cripto que continuam confiáveis quando a API falha]]></title>
            <link>https://www.tabnews.com.br/musheghmanukyan/como-projetar-dados-de-mercado-cripto-que-continuam-confiaveis-quando-a-api-falha</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/musheghmanukyan/como-projetar-dados-de-mercado-cripto-que-continuam-confiaveis-quando-a-api-falha</guid>
            <pubDate>Sat, 19 Sep 2026 15:33:32 GMT</pubDate>
            <description><![CDATA[Uma API de preços pode responder com 200 OK e, ainda assim, entregar dados inadequados para uma decisão operacional. O preço pode estar atrasado, o volume pode usar outra moeda de referên...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Uma API de preços pode responder com <code>200 OK</code> e, ainda assim, entregar dados inadequados para uma decisão operacional. O preço pode estar atrasado, o volume pode usar outra moeda de referência, o ativo pode ter sido associado ao símbolo errado ou a fonte pode estar repetindo o último valor conhecido sem informar isso.</p><p>Por essa razão, um serviço confiável de dados cripto não deve ser projetado apenas para “buscar um preço”. Ele precisa responder a uma pergunta mais completa: qual é o valor, de onde veio, quando foi observado, como foi transformado e quanta confiança existe nele agora?</p><p>Este texto trata de engenharia de dados e resiliência de sistemas, não de recomendação financeira.</p><h2 id="musheghmanukyan-content-comece-definindo-o-contrato-do-dado">Comece definindo o contrato do dado</h2><p>Antes de integrar provedores, defina o que cada campo significa. Um campo chamado <code>price</code> é ambíguo: preço da última negociação, preço médio, índice agregado ou ponto médio entre compra e venda?</p><p>O contrato interno deve especificar pelo menos:</p><ul><li>identificador canônico do ativo;</li><li>moeda de cotação;</li><li>tipo do preço;</li><li>instante do evento no mercado;</li><li>instante da coleta;</li><li>fonte original;</li><li>transformações aplicadas;</li><li>política de expiração;</li><li>estado de qualidade.</li></ul><p>Essa distinção evita que consumidores interpretem como equivalentes valores produzidos por métodos diferentes.</p><h2 id="musheghmanukyan-content-preserve-timestamp-e-proveniência">Preserve timestamp e proveniência</h2><p>Todo registro deveria carregar dois horários. <code>observed_at</code> representa quando a fonte observou ou produziu o dado. <code>received_at</code> indica quando seu sistema o recebeu. A diferença entre ambos ajuda a identificar latência, filas congestionadas e respostas antigas servidas por caches externos.</p><p>A proveniência também deve sobreviver à normalização. Guarde o nome do provedor, o endpoint ou canal utilizado e, quando possível, um identificador da resposta. Se o valor final for calculado a partir de várias fontes, registre quais participaram, quais foram descartadas e qual método de agregação foi usado.</p><p>Sem essa trilha, investigar um pico incorreto vira arqueologia: o número está no banco, mas ninguém consegue explicar como chegou lá.</p><h2 id="musheghmanukyan-content-normalize-sem-apagar-diferenças-importantes">Normalize sem apagar diferenças importantes</h2><p>Provedores usam símbolos, precisão, pares e unidades diferentes. <code>BTC</code>, <code>XBT</code> e identificadores próprios podem representar o mesmo ativo, enquanto símbolos idênticos podem pertencer a projetos distintos. Portanto, não use apenas o ticker como chave. Mantenha um catálogo canônico baseado em identificadores estáveis e mapeamentos específicos por fonte.</p><p>A normalização deve tratar:</p><ul><li>moedas e unidades de cotação;</li><li>casas decimais e regras de arredondamento;</li><li>volumes por período;</li><li>timezone dos timestamps;</li><li>contratos em redes diferentes;</li><li>valores ausentes ou representados como zero.</li></ul><p>Zero não deve substituir ausência. Um preço realmente igual a zero, um campo não informado e uma falha de conversão são estados diferentes e precisam permanecer distinguíveis.</p><h2 id="musheghmanukyan-content-detecte-dados-vencidos-explicitamente">Detecte dados vencidos explicitamente</h2><p>A validade depende do ativo e do caso de uso. Dez minutos podem ser aceitáveis em um relatório diário, mas não em uma interface que se apresenta como tempo real.</p><p>Defina um limite de frescor por categoria e calcule a idade usando <code>observed_at</code>, não apenas o momento da última gravação. Uma coleta recente pode conter uma observação antiga.</p><p>Estados simples facilitam o consumo:</p><ul><li><code>fresh</code>: dentro do intervalo esperado;</li><li><code>delayed</code>: utilizável, mas acima da latência normal;</li><li><code>stale</code>: expirado para o caso de uso;</li><li><code>unavailable</code>: não há valor seguro para retornar.</li></ul><p>Nunca renove artificialmente o timestamp de um valor em cache. Isso esconderia a idade real do dado.</p><h2 id="musheghmanukyan-content-use-múltiplas-fontes-com-regras-previsíveis">Use múltiplas fontes com regras previsíveis</h2><p>Fallback não significa escolher silenciosamente qualquer resposta disponível. Cada fonte pode ter cobertura, liquidez e metodologia distintas. Estabeleça uma ordem ou estratégia por ativo e documente quando a troca acontece.</p><p>Uma política possível é usar uma fonte primária enquanto ela estiver saudável, recorrer à secundária quando houver timeout ou dado vencido e comparar ambas durante a recuperação. Para ativos líquidos, uma mediana entre fontes elegíveis pode reduzir o impacto de um valor extremo. Para mercados pouco líquidos, agregar sem considerar volume e origem pode criar uma precisão ilusória.</p><p>Também é importante evitar alternância constante entre provedores. Use um período mínimo de estabilidade antes de promover novamente uma fonte que acabou de se recuperar.</p><h2 id="musheghmanukyan-content-combine-cache-e-circuit-breaker">Combine cache e circuit breaker</h2><p>O cache reduz latência e protege contra limites de requisição, mas precisa preservar a idade do conteúdo. Uma resposta em cache deve incluir o timestamp original e seu estado atual.</p><p>Adote dois prazos: um TTL curto para operação normal e uma janela limitada de <em>stale-if-error</em>. Dentro da segunda janela, o sistema pode retornar o último valor conhecido, desde que o marque claramente como vencido. Depois dela, é mais seguro declarar indisponibilidade.</p><p>Um <em>circuit breaker</em> interrompe chamadas repetidas a um provedor que está falhando. Após um número definido de erros, o circuito abre, aguarda um intervalo e testa a recuperação com poucas requisições. Isso evita tempestades de retries e libera recursos para os fallbacks.</p><p>Retries devem ter limite, <em>backoff</em> exponencial e jitter. Repetir imediatamente a mesma chamada em centenas de processos costuma ampliar a falha.</p><h2 id="musheghmanukyan-content-valide-anomalias-antes-de-publicar">Valide anomalias antes de publicar</h2><p>Uma resposta tecnicamente válida pode conter um preço absurdo. Compare o novo valor com:</p><ul><li>a última observação confiável;</li><li>outras fontes independentes;</li><li>limites plausíveis de variação;</li><li>volume e liquidez associados;</li><li>comportamento recente do mesmo mercado.</li></ul><p>Não descarte automaticamente toda mudança brusca: mercados cripto podem se mover rapidamente. Em vez disso, coloque a observação em quarentena, busque confirmação e reduza seu nível de confiança. Regras fixas funcionam melhor quando combinadas com referências dinâmicas, como desvio em relação à mediana recente.</p><h2 id="musheghmanukyan-content-exponha-qualidade-junto-com-o-preço">Exponha qualidade junto com o preço</h2><p>Consumidores não deveriam reconstruir a saúde do dado a partir de logs internos. A resposta pode incluir um estado, uma pontuação de confiança e razões legíveis por máquina.</p><pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>  <span class="hljs-attr">"asset_id"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"bitcoin"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"quote"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"USD"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"price"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"64231.18"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"observed_at"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2026-09-19T10:42:11Z"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"received_at"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2026-09-19T10:42:12Z"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"source"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"provider_b"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"status"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"delayed"</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"confidence"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">0.82</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"flags"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">"PRIMARY_UNAVAILABLE"</span><span class="hljs-punctuation">,</span> <span class="hljs-string">"FALLBACK_ACTIVE"</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"age_seconds"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">46</span><span class="hljs-punctuation">}</span></code></pre><p>A pontuação não deve ser decorativa. Documente quais fatores a alteram: idade, número de fontes concordantes, liquidez, anomalias e saúde do provedor. Para decisões automáticas, prefira também estados categóricos e flags, que são mais auditáveis do que um número isolado.</p><h2 id="musheghmanukyan-content-checklist-operacional">Checklist operacional</h2><p>Antes de colocar o serviço em produção, verifique:</p><ul><li>métricas de latência, erros e idade por provedor;</li><li>alertas para aumento de dados <code>stale</code>;</li><li>limites de requisição conhecidos e monitorados;</li><li>fallback testado com falhas simuladas;</li><li>circuit breaker e retries com parâmetros explícitos;</li><li>logs de proveniência sem dados secretos;</li><li>catálogo de ativos versionado;</li><li>testes para símbolos duplicados e mudanças de contrato;</li><li>relógios sincronizados nos serviços;</li><li>dashboards separados para disponibilidade e qualidade;</li><li>procedimento para invalidar valores incorretos;</li><li>comunicação clara aos consumidores durante incidentes.</li></ul><p>Também faça exercícios periódicos desligando a fonte primária em ambiente controlado. Resiliência que nunca foi testada costuma existir apenas no diagrama.</p><h2 id="musheghmanukyan-content-conclusão">Conclusão</h2><p>Confiabilidade não significa prometer que um preço estará sempre disponível. Significa representar honestamente a condição do dado e degradar o serviço de forma controlada. Quando timestamps, proveniência, normalização, fallback e sinais de qualidade fazem parte do contrato, aplicações conseguem distinguir um valor atual de uma estimativa atrasada — e indisponibilidade deixa de ser confundida com certeza.</p><p>Mushegh Manukyan é Founder &#x26; CEO da <a href="https://armcp.net/" rel="nofollow">ARMCP.net</a>, plataforma de informação cripto e Web3 baseada em Yerevan. Seu trabalho se concentra em dados de mercado, ferramentas blockchain, desenvolvimento de startups e clareza regulatória.</p></div>]]></content:encoded>
            <author>musheghmanukyan</author>
        </item>
        <item>
            <title><![CDATA[Pitch: DD • Diário Dela: um aplicativo de ciclo menstrual feito para uma única pessoa]]></title>
            <link>https://www.tabnews.com.br/JeielMiranda/dd-diario-dela-um-aplicativo-de-ciclo-menstrual-feito-para-uma-unica-pessoa</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/JeielMiranda/dd-diario-dela-um-aplicativo-de-ciclo-menstrual-feito-para-uma-unica-pessoa</guid>
            <pubDate>Sat, 19 Sep 2026 15:02:09 GMT</pubDate>
            <description><![CDATA[Há uma categoria de software que normalmente nasce pensando em escala: muitos usuários, contas, servidores, analytics, sincronização e monetização. O DD • Diário Dela nasceu exatamente pe...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Há uma categoria de software que normalmente nasce pensando em escala: muitos usuários, contas, servidores, analytics, sincronização e monetização.</p><p>O <strong>DD • Diário Dela</strong> nasceu exatamente pelo caminho contrário.</p><p>Ele foi desenvolvido para uma única pessoa: <strong>Giovanna</strong>, minha noiva.</p><p>A ideia inicial era simples: criar algo que ajudasse no acompanhamento do ciclo menstrual e do bem-estar dela, mas sem transformar informações extremamente pessoais em dados armazenados em algum servidor de terceiros.</p><p>O resultado acabou se tornando um projeto Android bastante interessante do ponto de vista de <strong>privacidade, armazenamento local, estatística, criptografia, migração de banco de dados e engenharia de software</strong>.</p><p>Repositório: <a href="https://github.com/Miranda3000-CPU/DD-Di-rio-Dela">https://github.com/Miranda3000-CPU/DD-Di-rio-Dela</a></p><hr><h2 id="jeielmiranda-content-o-problema">O problema</h2><p>Aplicativos de acompanhamento menstrual lidam com informações que podem ser extremamente sensíveis.</p><p>Datas de menstruação, sintomas, intensidade do fluxo, dor, humor, sono, energia, observações pessoais e outras informações relacionadas ao ciclo não precisam necessariamente sair do dispositivo para que um aplicativo seja útil.</p><p>Por isso, uma das premissas do DD foi:</p><blockquote><p><strong>Se o dado não precisa sair do celular, ele não deveria sair do celular.</strong></p></blockquote><p>Isso levou a uma arquitetura essencialmente <strong>offline-first</strong>.</p><p>Não existe conta de usuário.</p><p>Não existe login.</p><p>Não existe servidor próprio para armazenar os registros.</p><p>Não existe painel administrativo com os dados.</p><p>Não existe publicidade.</p><p>E o aplicativo não depende de uma conexão com a Internet para funcionar.</p><hr><h2 id="jeielmiranda-content-por-que-diário-dela">Por que "Diário Dela"?</h2><p>O nome não é apenas uma marca.</p><p>O aplicativo não foi projetado como uma plataforma genérica para múltiplas usuárias. A interface foi concebida especificamente para a Giovanna.</p><p>Isso aparece inclusive na experiência de uso:</p><ul><li>"Olá, Giovanna 🌷"</li><li>"Como você está hoje?"</li><li>"Suas previsões"</li><li>"Seu histórico"</li></ul><p>A intenção é que o aplicativo tenha uma experiência pessoal, e não a aparência de mais um produto genérico de saúde.</p><p>Ao mesmo tempo, isso não significa que os dados estejam codificados no aplicativo. O nome apresentado pode ser ajustado nas preferências.</p><hr><h1 id="jeielmiranda-content-privacidade-como-requisito-arquitetural">Privacidade como requisito arquitetural</h1><p>A privacidade não foi tratada apenas como uma frase na tela de configurações.</p><p>Ela influenciou decisões técnicas do projeto.</p><p>O <code>AndroidManifest.xml</code>, por exemplo, não declara a permissão <code>android.permission.INTERNET</code>.</p><p>Além disso, o projeto não utiliza Firebase Analytics, Google Analytics ou SDK de publicidade.</p><p>Os dados principais ficam em um banco <strong>Room</strong> local.</p><p>A estrutura inclui, entre outras informações:</p><ul><li>registros de ciclos;</li><li>duração;</li><li>datas;</li><li>registros diários;</li><li>intensidade do fluxo;</li><li>dor;</li><li>sintomas;</li><li>humor;</li><li>energia;</li><li>qualidade do sono;</li><li>muco cervical;</li><li>observações.</li></ul><p>Tudo isso permanece no armazenamento local do aplicativo.</p><hr><h1 id="jeielmiranda-content-e-se-for-necessário-trocar-de-celular">E se for necessário trocar de celular?</h1><p>Aqui surgiu outro problema interessante.</p><p>Se tudo fica localmente armazenado, precisamos resolver a portabilidade dos dados sem simplesmente criar uma sincronização com um servidor.</p><p>A solução foi implementar um mecanismo próprio de <strong>backup e restauração</strong> utilizando o <strong>Storage Access Framework (SAF)</strong> do Android.</p><p>O aplicativo permite exportar os dados para um arquivo <code>.ddbackup</code> e posteriormente importá-los.</p><p>O backup pode ser protegido com senha utilizando:</p><ul><li>AES-256-GCM;</li><li>PBKDF2WithHmacSHA256;</li><li>salt aleatório;</li><li>autenticação integrada ao modo GCM.</li></ul><p>A restauração também foi pensada para não simplesmente apagar o banco existente.</p><p>O mecanismo realiza um <strong>merge</strong> dos registros utilizando identificadores estáveis e datas, permitindo importar dados sem destruir o histórico já existente.</p><hr><h1 id="jeielmiranda-content-um-detalhe-importante-backup-automático">Um detalhe importante: backup automático</h1><p>Outro ponto que considerei importante foi evitar que a privacidade prometida pelo aplicativo fosse contradita pelo próprio sistema operacional.</p><p>O aplicativo utiliza:</p><pre><code class="hljs language-xml">android:allowBackup="false"</code></pre><p>Além disso, existem regras específicas de backup e extração de dados.</p><p>A ideia é evitar que dados íntimos sejam silenciosamente incluídos em mecanismos automáticos de backup do dispositivo.</p><p>A filosofia é simples:</p><blockquote><p>O usuário deve saber quando está exportando os próprios dados.</p></blockquote><hr><h1 id="jeielmiranda-content-previsões-sem-ia-milagrosa">Previsões sem "IA milagrosa"</h1><p>Essa foi uma das partes mais importantes do projeto.</p><p>No início, seria tentador colocar no aplicativo algo como:</p><blockquote><p>"Nossa inteligência artificial prevê seu ciclo com 96% de precisão."</p></blockquote><p>Mas isso seria uma afirmação bastante problemática.</p><p>O ciclo menstrual possui variabilidade fisiológica e uma previsão baseada exclusivamente em histórico possui limitações importantes.</p><p>Por isso, o DD não tenta vender uma falsa precisão.</p><p>A implementação atual utiliza um <strong>modelo estatístico adaptativo e determinístico</strong>.</p><p>Entre os mecanismos utilizados estão:</p><ul><li>mediana dos ciclos;</li><li>média móvel exponencialmente ponderada (EWMA);</li><li>ponderação dos dados históricos;</li><li>intervalos de incerteza;</li><li>projeções para os ciclos seguintes.</li></ul><p>A implementação utiliza <code>EWMA</code> com <code>α = 0,40</code> e combina o resultado com a mediana histórica.</p><p>A ideia é evitar que um único ciclo atípico tenha influência desproporcional sobre a previsão.</p><hr><h1 id="jeielmiranda-content-incerteza-é-uma-informação">Incerteza é uma informação</h1><p>Outro detalhe importante foi abandonar a ideia de apresentar uma data futura como se fosse uma certeza.</p><p>Em vez de simplesmente:</p><blockquote><p>"Sua menstruação será no dia X."</p></blockquote><p>o aplicativo trabalha com <strong>janelas de incerteza</strong>.</p><p>A margem pode crescer conforme a projeção se distancia dos dados observados.</p><p>Isso é particularmente importante porque existe uma diferença entre:</p><p><strong>previsão estatística</strong></p><p>e</p><p><strong>certeza fisiológica</strong>.</p><p>O aplicativo representa a primeira, não a segunda.</p><hr><h1 id="jeielmiranda-content-projeção-de-90-dias">Projeção de 90 dias</h1><p>O calendário também possui uma projeção de aproximadamente 90 dias.</p><p>Ela permite visualizar:</p><ul><li>ciclos futuros;</li><li>menstruação estimada;</li><li>janela fértil estimada;</li><li>ovulação estimada;</li><li>fases do ciclo.</li></ul><p>Essas informações são visualmente diferenciadas no calendário.</p><p>Porém, existe uma distinção importante no próprio aplicativo:</p><blockquote><p><strong>Estimado não significa confirmado.</strong></p></blockquote><p>A janela fértil não confirma ovulação e não deve ser interpretada como método contraceptivo.</p><hr><h1 id="jeielmiranda-content-um-aplicativo-de-saúde-precisa-saber-dizer-não-sei">Um aplicativo de saúde precisa saber dizer "não sei"</h1><p>Essa talvez seja uma das maiores lições técnicas do projeto.</p><p>Quando trabalhamos com informações relacionadas à saúde, existe uma tentação de transformar qualquer algoritmo em uma autoridade.</p><p>Não deveria ser assim.</p><p>Uma previsão calculada por um algoritmo a partir do histórico de uma pessoa continua sendo uma previsão.</p><p>Por isso, o DD inclui avisos explícitos de que as previsões são estimativas para acompanhamento pessoal e <strong>não substituem avaliação médica ou ginecológica</strong>.</p><p>O aplicativo também não deve ser utilizado como método contraceptivo.</p><hr><h1 id="jeielmiranda-content-base-científica">Base científica</h1><p>A implementação não foi construída apenas em torno de regras arbitrárias.</p><p>Entre as referências utilizadas no projeto estão trabalhos sobre variabilidade do ciclo menstrual e acompanhamento menstrual, além de referências clínicas do <strong>American College of Obstetricians and Gynecologists (ACOG)</strong>.</p><p>Uma das referências utilizadas é:</p><p><strong>Li et al. (2021)</strong> — <em>Characterizing the normal menstrual cycle and its variations using mobile application data</em>, publicado no <em>Journal of the American Medical Informatics Association (JAMIA)</em>.</p><p>Também são consideradas referências do ACOG sobre o ciclo menstrual como sinal vital e trabalhos sobre variabilidade das fases do ciclo.</p><p>A intenção não é transformar o aplicativo em dispositivo médico.</p><p>É justamente o contrário: utilizar literatura científica para evitar que o software faça afirmações que os dados não sustentam.</p><hr><h1 id="jeielmiranda-content-a-arquitetura-android">A arquitetura Android</h1><p>O projeto atualmente utiliza:</p><ul><li><strong>Kotlin 2.2.10</strong></li><li><strong>Jetpack Compose</strong></li><li><strong>Material Design 3</strong></li><li><strong>Room 2.7.0</strong></li><li><strong>Kotlin Coroutines</strong></li><li><strong>KSP</strong></li><li><strong>Robolectric</strong></li><li><strong>Roborazzi</strong></li></ul><p>A persistência está organizada utilizando Room.</p><p>Existe uma separação entre entidades, DAO, repositórios e camada de apresentação.</p><p>Algumas das principais estruturas são:</p><pre><code class="hljs language-text">app/└── src/main/java/com/example/    ├── backup/    │   ├── BackupCrypto.kt    │   ├── BackupManager.kt    │   └── BackupModels.kt    │    ├── data/    │   ├── AppDatabase.kt    │   ├── CycleDao.kt    │   ├── CycleEntity.kt    │   ├── CycleRepository.kt    │   ├── DailyLogDao.kt    │   └── DailyLogEntity.kt    │    ├── model/    │   └── CyclePrediction.kt    │    ├── notification/    │   ├── CycleAlarmReceiver.kt    │   └── NotificationHelper.kt    │    ├── ui/    │   ├── CycleViewModel.kt    │   └── components/    │    └── util/        └── CycleCalculator.kt</code></pre><p>Isso tornou possível manter a lógica de cálculo relativamente independente da interface.</p><hr><h1 id="jeielmiranda-content-migração-de-banco-também-é-parte-do-produto">Migração de banco também é parte do produto</h1><p>Existe uma parte do desenvolvimento de aplicativos que muitas vezes passa despercebida quando estamos fazendo protótipos:</p><p><strong>o usuário já possui dados.</strong></p><p>No caso do DD isso é particularmente importante.</p><p>A Giovanna já utiliza uma versão anterior do aplicativo.</p><p>Portanto, lançar uma nova versão não poderia significar:</p><blockquote><p>"Instale novamente e comece tudo de novo."</p></blockquote><p>O <code>applicationId</code> foi mantido como:</p><pre><code class="hljs language-text">com.aistudio.ciclo.menstrual</code></pre><p>e o banco possui migração entre versões.</p><p>A migração <code>MIGRATION_1_2</code> foi criada para preservar o histórico existente enquanto novas estruturas foram adicionadas.</p><p>Esse tipo de preocupação muda completamente a forma de pensar sobre uma atualização.</p><p>Não estamos apenas atualizando código.</p><p>Estamos atualizando <strong>um software que possui memória</strong>.</p><hr><h1 id="jeielmiranda-content-testes">Testes</h1><p>O projeto também possui uma suíte de testes para algumas das partes mais sensíveis.</p><p>Entre elas:</p><ul><li>cálculo do ciclo;</li><li>janelas de incerteza;</li><li>sinais de atenção;</li><li>migração do Room;</li><li>backup;</li><li>criptografia;</li><li>restauração;</li><li>merge de dados;</li><li>notificações;</li><li>renderização visual.</li></ul><p>Também existem testes de screenshot utilizando Roborazzi.</p><p>Isso permite comparar a interface renderizada e detectar alterações visuais inesperadas.</p><hr><h1 id="jeielmiranda-content-notificações-privadas">Notificações privadas</h1><p>As notificações possuem dois modos.</p><p>No modo normal, o aplicativo pode apresentar informações relacionadas ao ciclo.</p><p>No <strong>modo privado</strong>, o conteúdo exibido na tela de bloqueio é reduzido para algo genérico, como:</p><blockquote><p>"Há uma atualização sobre seu ciclo."</p></blockquote><p>Isso resolve um problema simples, mas importante.</p><p>Mesmo que o aplicativo não envie dados para a Internet, uma notificação pode revelar informações pessoais para alguém que esteja olhando para a tela bloqueada.</p><p>Privacidade também envolve esse tipo de detalhe.</p><hr><h1 id="jeielmiranda-content-interface">Interface</h1><p>A interface foi construída com Jetpack Compose e possui:</p><ul><li>tela inicial;</li><li>calendário visual;</li><li>histórico;</li><li>gráficos;</li><li>registro diário;</li><li>sintomas;</li><li>humor;</li><li>energia;</li><li>sono;</li><li>configurações;</li><li>notificações;</li><li>backup e restauração.</li></ul><p>Algumas telas do projeto também são documentadas no próprio repositório.</p><hr><h1 id="jeielmiranda-content-o-que-eu-aprendi-construindo-isso">O que eu aprendi construindo isso</h1><p>O mais interessante no DD não foi simplesmente criar um calendário menstrual.</p><p>Foi perceber como alguns requisitos aparentemente simples mudam completamente a arquitetura.</p><p>"Não quero que os dados saiam do dispositivo."</p><p>Isso implica pensar em:</p><ul><li>permissões;</li><li>dependências;</li><li>analytics;</li><li>backups automáticos;</li><li>armazenamento;</li><li>exportação;</li><li>criptografia;</li><li>restauração;</li><li>migração;</li><li>atualizações.</li></ul><p>"Quero fazer previsões."</p><p>Isso implica pensar em:</p><ul><li>variabilidade;</li><li>incerteza;</li><li>estatística;</li><li>dados insuficientes;</li><li>limites do modelo;</li><li>comunicação responsável.</li></ul><p>"E a Giovanna já usa o aplicativo."</p><p>Isso implica pensar em:</p><ul><li>compatibilidade;</li><li><code>applicationId</code>;</li><li>assinatura;</li><li>versionamento;</li><li>migrações;</li><li>preservação dos dados.</li></ul><p>No fim, um aplicativo pequeno pode envolver problemas de engenharia bastante grandes.</p><hr><h1 id="jeielmiranda-content-o-estado-atual">O estado atual</h1><p>O DD • Diário Dela é atualmente um aplicativo Android pessoal, offline e privado, desenvolvido especificamente para a Giovanna.</p><p>A versão atual utiliza:</p><pre><code class="hljs language-text">versionCode = 5versionName = "5.0"</code></pre><p>O projeto permanece aberto no GitHub:</p><p><a href="https://github.com/Miranda3000-CPU/DD-Di-rio-Dela">https://github.com/Miranda3000-CPU/DD-Di-rio-Dela</a></p><p>A ideia não é transformar o DD em uma plataforma de saúde para milhões de pessoas.</p><p>O objetivo original continua sendo o mesmo:</p><blockquote><p><strong>Construir uma ferramenta útil para uma pessoa específica, mantendo os dados dela sob o controle dela.</strong></p></blockquote><p>E, para mim, esse projeto acabou sendo uma forma bastante concreta de estudar uma combinação que considero interessante:</p><p><strong>Android + privacidade + estatística + segurança + engenharia de dados + experiência pessoal.</strong></p></div>]]></content:encoded>
            <author>JeielMiranda</author>
        </item>
        <item>
            <title><![CDATA[Clonei o Tella.tv com apenas um prompt — utilizando menos de 5% da minha cota semanal do claude code com o Jarvis Ade]]></title>
            <link>https://www.tabnews.com.br/lalves/clonei-o-tella-tv-com-apenas-um-prompt-utilizando-menos-de-5-por-cento-da-minha-cota-semanal-do-claude-code-com-o-jarvis-ade</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/lalves/clonei-o-tella-tv-com-apenas-um-prompt-utilizando-menos-de-5-por-cento-da-minha-cota-semanal-do-claude-code-com-o-jarvis-ade</guid>
            <pubDate>Sat, 19 Sep 2026 15:01:11 GMT</pubDate>
            <description><![CDATA[Um prompt. Nenhum passo a passo. Um produto inteiro para construir. Resolvi fazer um teste que, até pouco tempo atrás, pareceria absurdo: Pedi para uma equipe de agentes de IA recriar o T...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><blockquote><p>Um prompt. Nenhum passo a passo. Um produto inteiro para construir.</p></blockquote><p>Resolvi fazer um teste que, até pouco tempo atrás, pareceria absurdo:</p><p>Pedi para uma equipe de agentes de IA recriar o Tella.tv e deixei ela trabalhar.</p><p>Não fui criando página por página.</p><p>Não fiquei dizendo qual componente deveria ser implementado em seguida.</p><p>Não passei dezenas de prompts guiando cada decisão.</p><p>Dei o objetivo e deixei o Jarvis ADE assumir a execução.</p><p>O resultado foi este:</p><p>🎥 <a href="https://youtu.be/JJB9c8yQqGE" rel="nofollow">https://youtu.be/JJB9c8yQqGE</a></p><p>Repositório do projeto : <a href="https://github.com/Vidiio-Org/jarvis-vidiio-app">https://github.com/Vidiio-Org/jarvis-vidiio-app</a></p><p>E o mais interessante não foi simplesmente ver uma IA escrevendo muito código.</p><p>Foi perceber que escrever código está começando a deixar de ser o gargalo.</p><h3 id="lalves-content-o-problema-agora-é-outro"><strong>O problema agora é outro:</strong></h3><p>Como fazer múltiplos agentes planejarem, dividirem e executarem um projeto inteiro sem precisar de um humano coordenando cada passo?</p><p>É exatamente isso que estamos tentando resolver com o Jarvis ADE.</p><p>A diferença entre gerar código e construir software</p><p>Hoje temos ferramentas de IA extremamente boas para programação.</p><p><strong>Você pode pedir:</strong></p><p>“Crie essa página.”</p><p>Depois:</p><p>“Agora implemente autenticação.”</p><p>Depois:</p><p>“Corrija esse erro.”</p><p>Depois:</p><p>“Crie os testes.”</p><p>Isso já mudou completamente a produtividade de muitos desenvolvedores.</p><p>Mas existe um detalhe:</p><p>você ainda é o gerente da IA.</p><p>**É você quem constantemente precisa decidir:<br>**<br>O que fazer<br>↓<br>Como dividir<br>↓<br>O que fazer primeiro<br>↓<br>Executar<br>↓<br>Verificar<br>↓<br>Corrigir<br>↓<br>Dar o próximo prompt</p><pre><code class="hljs language-js"></code></pre><p>A IA programa. Mas você continua orquestrando. Foi aí que nasceu a ideia por trás do Jarvis.</p><p><strong>E se a IA também pudesse coordenar o desenvolvimento?</strong></p><p>Em vez de construir apenas mais um coding agent, começamos a trabalhar em algo um pouco diferente.</p><p>Um ADE — Autonomous Development Environment.</p><p>A ideia é que você não entregue necessariamente uma tarefa.</p><p>Você entrega uma missão.</p><p>Por exemplo:</p><p>“Recrie esse produto.”</p><p>O Jarvis transforma isso em um plano e coordena agentes para executar o trabalho.</p><pre><code>                SUA MISSÃO                     │                     ▼                ┌─────────┐                │ JARVIS  │                └────┬────┘                     │                   PLANO                     │      ┌──────────────┼──────────────┐      ▼              ▼              ▼  Frontend        Backend         DevOps      │              │              │      └──────────────┼──────────────┘                     ▼                    QA                     │                     ▼                 ENTREGA</code></pre><p>Algumas tarefas possuem dependências.</p><p>Outras podem acontecer simultaneamente.</p><p>Agentes podem trabalhar em diferentes partes do projeto enquanto o sistema acompanha o estado geral da missão.</p><p>A mudança parece pequena, mas conceitualmente é enorme.</p><p>Estamos tentando sair de:</p><p>Humano → prompt → código</p><p>para:</p><p>Humano → objetivo → equipe de agentes → software</p><p>Foi aí que resolvemos tentar recriar o Tella.tv</p><p>Precisávamos de um teste suficientemente grande para expor os problemas dessa abordagem.</p><p>Não queríamos:</p><p>“Faça uma landing page.”</p><p>Queríamos algo que obrigasse o sistema a lidar com um projeto significativamente maior.</p><p>Escolhemos o Tella.tv como referência.</p><p>Então entregamos a missão ao Jarvis.</p><p>E começamos a observar.</p><p>O Jarvis precisou lidar com coisas que vão muito além de simplesmente completar código:</p><p>planejamento → divisão de trabalho → implementação → coordenação → integração → validação → correções.</p><p>E vários agentes puderam atuar sobre partes diferentes da missão.</p><p>Tudo partindo daquela instrução inicial.</p><p>O resultado completo está no vídeo:</p><p>🎥 <a href="https://youtu.be/JJB9c8yQqGE" rel="nofollow">https://youtu.be/JJB9c8yQqGE</a></p><p>Observação importante: quando digo “recriamos o Tella”, estou me referindo à versão demonstrada no vídeo. Não estou afirmando paridade 1:1 com toda a infraestrutura, backend e funcionalidades internas do produto original.</p><p>E isso me fez perceber uma mudança maior</p><p>Acredito que estamos passando por três fases no desenvolvimento com IA.</p><ol><li>Autocomplete<br>Humano escreve código<br>↓<br>IA prevê o próximo código</li><li>AI Coding<br>Humano descreve uma tarefa<br>↓<br>IA implementa</li><li>AI Software Engineering<br>Humano define um objetivo<br>↓<br>IA planeja<br>↓<br>Agentes se coordenam<br>↓<br>Agentes executam<br>↓<br>Sistema valida<br>↓<br>Software</li></ol><p>É essa terceira etapa que considero particularmente interessante.</p><p>Porque nesse ponto gerar código deixa de ser o problema central.</p><p>Coordenação passa a ser o problema.</p><p>Contexto passa a ser o problema.</p><p>Paralelismo passa a ser o problema.</p><p>Validação passa a ser o problema.</p><p>Confiabilidade passa a ser o problema.</p><p>E esses são problemas muito parecidos com aqueles encontrados ao coordenar uma equipe de engenharia humana.</p><p>Talvez estejamos mudando a abstração da programação</p><p>Não acredito que a parte mais interessante dessa discussão seja:</p><p>“A IA vai substituir programadores?”</p><p>Existe uma pergunta tecnicamente muito mais interessante:</p><p>Qual será o nível de abstração utilizado por um programador?</p><p>Já programamos diretamente em níveis muito mais baixos.</p><p>Criamos linguagens.</p><p>Criamos frameworks.</p><p>Criamos serviços de cloud.</p><p>Cada camada permitiu que desenvolvedores expressassem uma intenção maior utilizando menos instruções.</p><p>Agentes podem representar outra mudança desse tipo.</p><p>Talvez o desenvolvedor passe cada vez mais tempo definindo:</p><p>arquitetura, requisitos, restrições, produto, critérios de qualidade e validação.</p><p>E cada vez menos tempo dizendo ao computador exatamente como implementar cada linha.</p><p>Foi assim que o Jarvis ADE nasceu</p><p>O curioso é que inicialmente o Jarvis nem deveria virar uma empresa/produto separado.</p><p>Eu estava construindo outros produtos e comecei a criar uma infraestrutura interna para coordenar agentes de desenvolvimento.</p><p>Só que ela foi crescendo.</p><p>Mais agentes.</p><p>Mais autonomia.</p><p>Mais coordenação.</p><p>Mais observabilidade.</p><p>Até chegar um momento em que percebi:</p><p>a ferramenta que estávamos construindo para criar nossos produtos estava começando a se tornar mais interessante do que alguns dos próprios produtos.</p><p>Foi daí que nasceu o:</p><p>Jarvis ADE — Autonomous Development Environment.</p><p>A ideia que estamos perseguindo é simples de explicar:</p><p>Você define a missão.<br>O Jarvis coordena a engenharia.</p><p>Ainda temos muitos problemas difíceis pela frente.</p><p>Contexto entre agentes, conflitos, avaliação automática, custos, execução paralela, confiabilidade, recuperação de erros e observabilidade são alguns deles.</p><p>Mas é exatamente isso que torna esse espaço tão interessante.</p><p>Estamos abrindo o projeto e mostrando esses experimentos conforme avançamos.</p><p>Quem quiser acompanhar:</p><p>Jarvis ADE</p><p>E deixo uma pergunta para quem trabalha com desenvolvimento:</p><p>Se uma equipe de agentes consegue receber um objetivo e executar horas de trabalho autonomamente, qual passa a ser o papel da IDE?</p><p>Talvez a próxima grande ferramenta para desenvolvedores nem seja uma IDE.</p><p>Talvez seja o lugar onde você gerencia quem está programando por você.</p></div>]]></content:encoded>
            <author>lalves</author>
        </item>
        <item>
            <title><![CDATA[Projeto criado a partir de um problema real de expedição — gostaria de uma avaliação da comunidade]]></title>
            <link>https://www.tabnews.com.br/aleixo88/projeto-criado-a-partir-de-um-problema-real-de-expedicao-gostaria-de-uma-avaliacao-da-comunidade</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/aleixo88/projeto-criado-a-partir-de-um-problema-real-de-expedicao-gostaria-de-uma-avaliacao-da-comunidade</guid>
            <pubDate>Sat, 19 Sep 2026 13:08:33 GMT</pubDate>
            <description><![CDATA[Trabalho na operação de expedição de uma indústria e não sou desenvolvedor de formação. O projeto que quero apresentar nasceu de problemas que eu vivencio no dia a dia e foi sendo constru...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Trabalho na operação de expedição de uma indústria e não sou desenvolvedor de formação. O projeto que quero apresentar nasceu de problemas que eu vivencio no dia a dia e foi sendo construído com apoio de IA para transformar conhecimento operacional em software.</p><p><strong>De onde surgiu a ideia</strong></p><p>A operação trabalha com pedidos, mapas de expedição, conferência de materiais, conjuntos formados por vários componentes, embalagens, notas fiscais, faturamento e diferentes regras comerciais. Parte dessas informações fica distribuída entre processos e sistemas, o que cria espaço para conferências manuais, retrabalho e erros.<br>A ideia inicial era relativamente simples: importar o mapa de expedição sem alterar o sistema de origem e permitir que o operador conferisse os materiais por QR Code. Conforme o projeto evoluiu, começaram a aparecer problemas que uma conferência simples não resolvia.</p><p><em><strong>O que o sistema passou a fazer</strong></em></p><p>•Importar e interpretar o mapa de expedição mantendo o sistema de origem como referência.<br>•Conferir produtos e quantidades por QR Code.<br>•Controlar o que já foi conferido, faturado, entregue e o que ainda permanece pendente.<br>•Reconhecer conjuntos: um produto final pode depender de vários componentes e o sistema avalia se o conjunto está completo, parcial ou bloqueado.<br>•Registrar embalagens e manter rastreabilidade do que foi colocado em cada volume.<br>•Cruzar informações da nota fiscal com o que deveria ser expedido.<br>•Gerar informações para faturamento e packing list.<br>•Tratar diferentes condições comerciais e operacionais.<br>•Evoluir para uma camada de pré-faturamento fiscal, reunindo o contexto necessário do cliente, produto, pedido e operação para aplicar regras tributárias antes da emissão da NF-e.</p><p><strong>Um ponto que considero importante</strong></p><p>O sistema não nasceu de uma ideia de startup procurando um problema. Ele nasceu do problema primeiro. As funcionalidades foram surgindo conforme situações reais da operação exigiam uma solução.<br>Também não tenho formação tradicional em desenvolvimento de software. Meu conhecimento principal vem da operação. Usei IA como ferramenta para transformar regras, fluxos e decisões que eu conhecia do processo em uma aplicação funcional. Isso também me interessa como discussão: até onde alguém com conhecimento profundo de um problema, mas sem formação como programador, consegue construir um produto de software relevante usando IA?</p><p><strong>O que eu gostaria que vocês avaliassem</strong></p><p>1.Pela descrição, vocês enxergam isso apenas como uma solução interna muito específica ou existe potencial para virar um produto comercial?<br>2.Quais partes parecem realmente diferenciadas e quais são funcionalidades comuns que ERPs/WMS/TMS já resolvem bem?<br>3.Que informações vocês precisariam ver para conseguir avaliar melhor o produto?<br>4.Quais seriam os maiores riscos técnicos ou de arquitetura de um sistema que cresceu dessa maneira?<br>5.A integração entre operação de expedição, conferência, conjuntos, rastreabilidade, faturamento e contexto fiscal faz sentido como proposta de produto?<br>6.Se vocês estivessem avaliando esse projeto para uso em outras empresas, o que seria indispensável antes de considerá-lo comercializável?</p><p>**Sobre código e informações da empresa<br>**</p><p>Neste primeiro momento prefiro não publicar o código-fonte, o nome da empresa, clientes ou dados internos. Posso, porém, detalhar arquitetura, fluxos, modelo de dados e apresentar exemplos fictícios para que a análise técnica seja mais profunda sem expor informações proprietárias.<br>Meu objetivo com a publicação não é fazer propaganda. Quero colocar a ideia à prova com pessoas mais experientes em desenvolvimento, arquitetura e produtos de tecnologia e entender onde esse projeto realmente se encontra.</p></div>]]></content:encoded>
            <author>aleixo88</author>
        </item>
        <item>
            <title><![CDATA[🔥 O Melhor da Semana no TabNews #36]]></title>
            <link>https://www.tabnews.com.br/TabNewsDigest/o-melhor-da-semana-no-tabnews-36</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/TabNewsDigest/o-melhor-da-semana-no-tabnews-36</guid>
            <pubDate>Sat, 19 Sep 2026 11:00:07 GMT</pubDate>
            <description><![CDATA[Semana de 13/09 a 19/09 Este é o seu Digest Semanal, um apanhado dos posts mais com mais TabCoins que surgiram nos últimos 7 dias. Se você não consegue acompanhar o TabNews todo dia, esta...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><blockquote><p>Semana de 13/09 a 19/09</p></blockquote><p>Este é o seu <strong>Digest Semanal</strong>, um apanhado dos posts mais com mais TabCoins que surgiram nos últimos 7 dias.</p><p>Se você não consegue acompanhar o TabNews todo dia, esta é a sua chance de não perder o que houve de melhor esta semana!</p><hr><h2 id="tabnewsdigest-content--top-5-destaques-da-semana">🏆 Top 5 Destaques da Semana</h2><h2 id="tabnewsdigest-content-rag-na-prática-guia-completo-do-conceito-à-produção"><a href="https://www.tabnews.com.br/andersonlimadev/rag-na-pratica-guia-completo-do-conceito-a-producao">RAG na Prática: Guia Completo do Conceito à Produção</a></h2><p>Resumo: Este artigo cobre RAG (Retrieval-Augmented Generation) do zero ao avançado: o que é, como funciona cada camada do pipeline, como esc...</p><blockquote><p><a href="https://www.tabnews.com.br/andersonlimadev">andersonlimadev</a>, domingo 13/09 - 13 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-o-jev-me-fez-repensar-onde-a-ia-deveria-entrar-no-código"><a href="https://www.tabnews.com.br/Nito/o-jev-me-fez-repensar-onde-a-ia-deveria-entrar-no-codigo">O Jev me fez repensar onde a IA deveria entrar no código</a></h2><p>Nos últimos dois dias eu vi o Jev aparecer em praticamente todo lugar onde desenvolvedor discute IA. 20–200x mais rápido. 40–400x mais barat...</p><blockquote><p><a href="https://www.tabnews.com.br/Nito">Nito</a>, quinta 17/09 - 12 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-fiz-meu-blog-com-ia-para-escrever-sem-ia"><a href="https://www.tabnews.com.br/mksDEV08/fiz-meu-blog-com-ia-para-escrever-sem-ia">Fiz meu blog com IA para escrever sem IA</a></h2><p>Criei um blog chamado Pedro {sem IA}. O site foi desenvolvido com o Codex, mas a regra para os textos é simples: não usar inteligência artif...</p><blockquote><p><a href="https://www.tabnews.com.br/mksDEV08">mksDEV08</a>, quinta 17/09 - 11 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-acabei-com-o-spam-denunciando-para-esses-3-endereços"><a href="https://www.tabnews.com.br/Wellington79/acabei-com-o-spam-denunciando-para-esses-3-enderecos">Acabei com o SPAM denunciando para esses 3 endereços</a></h2><p>Acabei com o SPAM denunciando para esses 3 endereços <a href="mailto:abuse@above.com">abuse@above.com</a> <a href="mailto:phishing@cais.rnp.br">phishing@cais.rnp.br</a> <a href="mailto:reportphishing@apwg.org">reportphishing@apwg.org</a> Olá, eu recebia pelo menos...</p><blockquote><p><a href="https://www.tabnews.com.br/Wellington79">Wellington79</a>, terça 15/09 - 11 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-como-vocês-esperam-que-o-botão-run-funcione-em-um-editor-sql"><a href="https://www.tabnews.com.br/cevheri/como-voces-esperam-que-o-botao-run-funcione-em-um-editor-sql">Como vocês esperam que o botão "Run" funcione em um editor SQL?</a></h2><p>No desenvolvimento do LibreDB Studio, um dos nossos contribuidores voluntários levantou uma questão interessante sobre o comportamento de mú...</p><blockquote><p><a href="https://www.tabnews.com.br/cevheri">cevheri</a>, terça 15/09 - 10 TabCoins</p></blockquote><hr><h2 id="tabnewsdigest-content-️-top-5-do-newsletteroficial">🗞️ Top 5 do NewsletterOficial</h2><h2 id="tabnewsdigest-content-spacex-tentará-colocar-starship-em-órbita-pela-primeira-vez-em-22-de-setembro"><a href="https://www.tabnews.com.br/NewsletterOficial/spacex-tentara-colocar-starship-em-orbita-pela-primeira-vez-em-22-de-setembro">SpaceX tentará colocar Starship em órbita pela primeira vez em 22 de setembro</a></h2><p>O 14º voo de teste do megafoguete planeja implantar 26 satélites Starlink de terceira geração na atual rede de 10 mil satélites de internet ...</p><blockquote><p><a href="https://www.tabnews.com.br/NewsletterOficial">NewsletterOficial</a>, quarta 16/09 - 5 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-startup-de-co-inventor-do-chatgpt-lança-modelo-de-ia-que-promete-tomar-decisões-até-200-vezes-mais-rápido"><a href="https://www.tabnews.com.br/NewsletterOficial/startup-de-co-inventor-do-chatgpt-lanca-modelo-de-ia-que-promete-tomar-decisoes-ate-200-vezes-mais-rapido">Startup de co-inventor do ChatGPT lança modelo de IA que promete tomar decisões até 200 vezes mais rápido</a></h2><p>O Jev, da TypeSafe AI, de Diogo Almeida, foi projetado para se comunicar com máquinas em vez de humanos, retornando decisões tipadas e proba...</p><blockquote><p><a href="https://www.tabnews.com.br/NewsletterOficial">NewsletterOficial</a>, quarta 16/09 - 4 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-criador-do-ps5-linux-abandona-projeto-após-exploit-no-hypervisor-do-console-ser-reportado-à-sony-de-maneira-precipitada"><a href="https://www.tabnews.com.br/NewsletterOficial/criador-do-ps5-linux-abandona-projeto-apos-exploit-no-hypervisor-do-console-ser-reportado-a-sony-de-maneira-precipitada">Criador do PS5 Linux abandona projeto após exploit no hypervisor do console ser reportado à Sony de maneira precipitada</a></h2><p>Andy Nguyen pretendia reportar a falha à empresa após o lançamento do GTA VI, mas outro hacker, conhecido como Jordy, encontrou o exploit co...</p><blockquote><p><a href="https://www.tabnews.com.br/NewsletterOficial">NewsletterOficial</a>, sexta 18/09 - 2 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-senador-dos-eua-propõe-prisão-de-até-20-anos-para-quem-criar-superinteligência-artificial-sem-mecanismos-de-segurança-adequados"><a href="https://www.tabnews.com.br/NewsletterOficial/senador-dos-eua-propoe-prisao-de-ate-20-anos-para-quem-criar-superinteligencia-artificial-sem-mecanismos-de-seguranca-adequados">Senador dos EUA propõe prisão de até 20 anos para quem criar superinteligência artificial sem mecanismos de segurança adequados</a></h2><p>O projeto de lei busca impedir o avanço descontrolado de sistemas que poderiam, por exemplo, desenvolver armas biológicas ou criar mecanismo...</p><blockquote><p><a href="https://www.tabnews.com.br/NewsletterOficial">NewsletterOficial</a>, terça 15/09 - 1 TabCoins</p></blockquote><hr><h2 id="tabnewsdigest-content--top-pitches">🚀 Top Pitches</h2><h2 id="tabnewsdigest-content-pitch-coeleo-os-um-sistema-operacional-x64-feito-do-zero-em-rust"><a href="https://www.tabnews.com.br/coeleodev/coeleo-os-um-sistema-operacional-x64-feito-do-zero-em-rust">Pitch: Coeleo OS: um sistema operacional x64 feito do zero em Rust</a></h2><p>De onde veio isso Aos 8 anos ganhei um netbook de aniversário da minha tia. Sem internet em casa, minha diversão era fuçar no Paint, nos arq...</p><blockquote><p><a href="https://www.tabnews.com.br/coeleodev">coeleodev</a>, terça 15/09 - 5 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-pitch-meu-livro-sobre-jujutsu-jj-e-agentes-de-ia-foi-lançado-em-português"><a href="https://www.tabnews.com.br/oukayuka/pitch-meu-livro-sobre-jujutsu-jj-e-agentes-de-ia-foi-lancado-em-portugues">Pitch: Meu livro sobre Jujutsu (jj) e Agentes de IA foi lançado em português!</a></h2><p>Olá, pessoal! Sou engenheira de software no Japão e também escrevo livros técnicos. Meu livro mais recente é sobre o Jujutsu (jj), um sistem...</p><blockquote><p><a href="https://www.tabnews.com.br/oukayuka">oukayuka</a>, terça 15/09 - 2 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-pitch-change-data-capture---mini-cdc"><a href="https://www.tabnews.com.br/damtaipu/change-data-capture-mini-cdc">Pitch: Change Data Capture - Mini CDC</a></h2><p>Se você só precisa reagir à mudança de em uma tabela MySQL, não deveria precisar consultar o banco a cada poucos segundos — muito menos adot...</p><blockquote><p><a href="https://www.tabnews.com.br/damtaipu">damtaipu</a>, sábado 19/09 - 1 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-pitch-manda5-um-jogo-de-palavras-multiplayer-no-navegador-e-o-que-aprendi-com-tempo-real-e-sala-vazia"><a href="https://www.tabnews.com.br/georgequeiroga/pitch-manda5-um-jogo-de-palavras-multiplayer-no-navegador-e-o-que-aprendi-com-tempo-real-e-sala-vazia">Pitch: Manda5, um jogo de palavras multiplayer no navegador, e o que aprendi com tempo real e sala vazia</a></h2><p>Há alguns meses construo o Manda5, um jogo de palavras para jogar em grupo pelo navegador: <a href="https://manda5.com" rel="nofollow">https://manda5.com</a> A mecânica: aparece um tema (&#x26;...</p><blockquote><p><a href="https://www.tabnews.com.br/georgequeiroga">georgequeiroga</a>, quinta 17/09 - 1 TabCoins</p></blockquote><h2 id="tabnewsdigest-content-pitch-construí-um-micro-saas-para-processar-vídeos-em-lote-no-navegador-com-webassembly-reelmass"><a href="https://www.tabnews.com.br/KauaSilv/construi-um-micro-saas-para-processar-videos-em-lote-no-navegador-com-webassembly-reelmass">Pitch: Construí um micro-SaaS para processar vídeos em lote no navegador com WebAssembly (ReelMass)</a></h2><p>Olá pessoal! Há algum tempo venho estudando o mercado de micro-SaaS e a dor de criadores de conteúdo que trabalham com alto volume de vídeos...</p><blockquote><p><a href="https://www.tabnews.com.br/KauaSilv">KauaSilv</a>, quinta 17/09 - 1 TabCoins</p></blockquote><hr><h2 id="tabnewsdigest-content--pra-descontrair">😄 Pra descontrair</h2><div>    <img src="https://imgs.xkcd.com/comics/tyrannosaurus.png" title="Tyrannosaurus" alt="Many of the smaller dinosaurs seem to have largely preyed on housecats.">    </div><p><a href="https://imgs.xkcd.com" rel="nofollow">xkcd.com</a></p><hr><p>Deseja receber essa newsletter no seu email?</p><p>Até o próximo sábado!</p><p><em>— Conteúdo gerado automaticamente. Para saber mais, <a href="https://www.tabnews.com.br/italosousa/minha-solucao-para-acompanhar-o-tabnews-o-melhor-da-semana-no-tabnews">veja este post</a>.</em></p></div>]]></content:encoded>
            <author>TabNewsDigest</author>
        </item>
        <item>
            <title><![CDATA[O paradoxo da performance no frontend e o pato]]></title>
            <link>https://www.tabnews.com.br/gabrielbaiano/o-paradoxo-da-performance-no-frontend-e-o-pato</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/gabrielbaiano/o-paradoxo-da-performance-no-frontend-e-o-pato</guid>
            <pubDate>Sat, 19 Sep 2026 07:14:02 GMT</pubDate>
            <description><![CDATA[Olá, galera do TabNews! Front-end... Nós provavelmente somos uma das áreas que mais falam sobre performance e, ao mesmo tempo, uma das que mais normalizaram jogar abstrações, dependências...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Olá, galera do TabNews!</p><p>Front-end...</p><p>Nós provavelmente somos uma das áreas que <strong>mais falam sobre performance</strong> e, ao mesmo tempo, uma das que mais normalizaram jogar abstrações, dependências e JavaScript no problema até ele desaparecer.</p><p>Falamos de Core Web Vitals.</p><p>Falamos de tree shaking.</p><p>Falamos de lazy loading, code splitting, Server Components, SSR, streaming, hydration e redução de bundle.</p><p>Aí chega segunda-feira e precisamos colocar um gráfico de sete barras em um dashboard:</p><pre><code class="hljs language-bash">npm install alguma-lib-de-graficos</code></pre><p>E, de repente, temos dezenas ou centenas de kilobytes de JavaScript, dependências transitivas, abstrações que nunca vamos utilizar e uma API gigantesca para resolver algo que, conceitualmente, é desenhar sete retângulos.</p><p>É daí que nasce o que eu chamo de <strong>paradoxo da performance no frontend</strong>.</p><p>Nós nos preocupamos profundamente com performance — depois que construímos sistemas que precisam ser constantemente otimizados para recuperá-la.</p><hr><h2 id="gabrielbaiano-content-frontend-não-é-fazer-telinha">Frontend não é "fazer telinha"</h2><p>Existe ainda uma percepção curiosa de que frontend é simplesmente a camada visual do software.</p><p>Botão.</p><p>Modal.</p><p>Formulário.</p><p>Tabela.</p><p>Gráfico.</p><p>Só que o frontend moderno deixou de ser apenas apresentação há muito tempo.</p><p>Uma aplicação React pode administrar estado, cache, sincronização com servidor, autenticação, roteamento, validação, optimistic updates, internacionalização, acessibilidade, observabilidade, telemetria e uma quantidade considerável de regras de negócio.</p><p>React, Next.js, Angular, Vue, Nuxt, SvelteKit e tantos outros projetos não existem simplesmente porque desenvolvedores queriam maneiras diferentes de escrever um <code>&#x3C;button></code>.</p><p>Eles existem porque estamos tentando resolver um problema bastante complicado:</p><p><strong>como construir aplicações cada vez maiores, com cada vez mais funcionalidades, por equipes cada vez maiores, sem perder completamente a capacidade de entregar software?</strong></p><p>E acredito que isso criou uma característica importante na cultura do frontend:</p><blockquote><p><strong>ship fast, optimize later.</strong></p></blockquote><p>Não necessariamente porque os desenvolvedores são negligentes.</p><p>É consequência dos incentivos.</p><p>Uma feature entregue hoje tem valor imediatamente visível para o negócio.</p><p>Uma dependência que adicionou 80 kB ao bundle dificilmente gera uma reunião emergencial.</p><p>Uma abstração desnecessária não aparece no Jira.</p><p>Um componente que poderia ter 100 linhas mas utiliza quatro bibliotecas diferentes continua aparecendo como:</p><blockquote><p>✅ Feature concluída.</p></blockquote><p>A dívida aparece depois.</p><hr><h1 id="gabrielbaiano-content-o-frontend-é-cheio-de-patos">O frontend é cheio de patos</h1><p><img src="https://i.pinimg.com/originals/54/2a/62/542a6295cca50ad32df25fe0b56268c2.gif" alt="pato"></p><p>Existe uma metáfora que gosto bastante para pensar sobre isso.</p><p><strong>O frontend moderno é cheio de patos.</strong></p><p>O pato nada.</p><p>O pato anda.</p><p>O pato voa.</p><p>Ele consegue fazer praticamente tudo.</p><p>Só que dificilmente será o melhor animal em qualquer uma dessas coisas.</p><p>Boa parte das ferramentas frontend modernas funciona dessa maneira.</p><p>São ferramentas extraordinariamente generalistas.</p><p>Precisamos de renderização no servidor?</p><p>Tem.</p><p>Aplicação SPA?</p><p>Tem.</p><p>Site estático?</p><p>Tem.</p><p>API?</p><p>Tem.</p><p>Streaming?</p><p>Tem.</p><p>Middleware?</p><p>Tem.</p><p>Cache?</p><p>Tem.</p><p>Aplicação híbrida?</p><p>Também tem.</p><p>Isso é extremamente conveniente.</p><p>E conveniência é uma característica importantíssima de uma ferramenta.</p><p>O problema começa quando <strong>conveniência passa a ser confundida com eficiência</strong>.</p><p>Não escolhemos necessariamente a ferramenta que executa melhor determinada tarefa. Frequentemente escolhemos aquela que consegue resolver o maior número possível de problemas suficientemente bem.</p><p>E isso faz muito sentido economicamente.</p><p>Uma empresa não quer necessariamente cinco especialistas trabalhando com cinco tecnologias diferentes.</p><p>Ela quer contratar pessoas que consigam entregar.</p><p>Quanto maior o ecossistema, maior a quantidade de problemas que já possuem uma solução pronta:</p><pre><code class="hljs language-bash">npm install problema-resolvido</code></pre><p>E seguimos para a próxima tarefa.</p><hr><h2 id="gabrielbaiano-content-a-sprint-precisa-terminar">A sprint precisa terminar</h2><p>Acho que existe outro fator muito mais importante que qualquer discussão técnica:</p><p><strong>software corporativo possui prazo.</strong></p><p>Se existe uma biblioteca que resolve meu problema em uma tarde e desenvolver uma implementação específica levaria três dias, existe uma pressão completamente racional para utilizar a biblioteca.</p><p>Multiplique isso por:</p><ul><li>componentes;</li><li>formulários;</li><li>tabelas;</li><li>gráficos;</li><li>datas;</li><li>autenticação;</li><li>analytics;</li><li>gerenciamento de estado;</li><li>internacionalização;</li><li>validação;</li><li>animações.</li></ul><p>Individualmente, praticamente todas as decisões parecem razoáveis.</p><p>O problema é que <strong>arquitetura também é o resultado acumulado de centenas de decisões localmente razoáveis</strong>.</p><p>Nenhum desenvolvedor decidiu:</p><blockquote><p>"Hoje vou adicionar 2 MB de JavaScript ao produto."</p></blockquote><p>Foram 30 decisões de:</p><blockquote><p>"Não vale a pena reinventar isso."</p></blockquote><p>E talvez nenhuma delas estivesse errada isoladamente.</p><p>Esse é justamente o ponto.</p><hr><h1 id="gabrielbaiano-content-quando-até-o-frontend-começa-a-ser-dividido">Quando até o frontend começa a ser dividido</h1><p>Talvez um dos exemplos mais interessantes dessa busca por velocidade organizacional sejam os <strong>microfrontends</strong>.</p><p>A ideia é levar parte da filosofia dos microservices para a interface: dividir uma aplicação grande em unidades menores que possam ser desenvolvidas, testadas e implantadas independentemente.</p><p>Isso permite que uma equipe altere uma parte do produto sem precisar coordenar cada release com todas as outras equipes.</p><p>Mas existe algo interessante nisso.</p><p>Criamos sistemas tão grandes que passamos a introduzir <strong>fronteiras arquiteturais dentro da própria interface</strong> para preservar autonomia de desenvolvimento.</p><p>Microfrontends podem reduzir o raio de impacto de determinadas mudanças e permitir pipelines e deploys independentes. Ao mesmo tempo, eles introduzem seus próprios custos: contratos entre aplicações, integração em runtime, possíveis dependências duplicadas e maior complexidade operacional.</p><p>Ou seja:</p><p><strong>estamos trocando complexidade técnica por independência organizacional.</strong></p><p>E, em empresas suficientemente grandes, essa troca pode fazer todo sentido.</p><p>Talvez esse seja um dos melhores exemplos de como arquitetura de frontend não é determinada somente por performance.</p><p>Ela também é determinada pela estrutura das equipes e pela necessidade de continuar entregando software.</p><hr><h1 id="gabrielbaiano-content-mas-a-web-nem-sempre-foi-construída-assim">Mas a web nem sempre foi construída assim</h1><p>Existe uma armadilha fácil aqui: dizer que <strong>“antigamente tudo era melhor”</strong>.</p><p>Não era.</p><p>A web antiga tinha seus próprios horrores. Compatibilidade entre navegadores era um inferno, Internet Explorer exigia hacks específicos, CSS tinha limitações enormes e atualizar uma pequena parte da página frequentemente significava recarregar tudo.</p><p>Mas havia uma diferença arquitetural importante:</p><p><strong>o navegador não era necessariamente o lugar onde a aplicação inteira precisava existir.</strong></p><p>Durante muito tempo, boa parte da web funcionava de uma maneira quase brutalmente simples.</p><p>Você tinha PHP no servidor:</p><pre><code class="hljs language-php"><span class="hljs-meta">&#x3C;?php</span> <span class="hljs-keyword">foreach</span> (<span class="hljs-variable">$produtos</span> <span class="hljs-keyword">as</span> <span class="hljs-variable">$produto</span>): <span class="hljs-meta">?></span>    &#x3C;div>        &#x3C;h2><span class="hljs-meta">&#x3C;?=</span> <span class="hljs-variable">$produto</span>[<span class="hljs-string">"nome"</span>] <span class="hljs-meta">?></span>&#x3C;/h2>        &#x3C;span>R$ <span class="hljs-meta">&#x3C;?=</span> <span class="hljs-variable">$produto</span>[<span class="hljs-string">"preco"</span>] <span class="hljs-meta">?></span>&#x3C;/span>    &#x3C;/div><span class="hljs-meta">&#x3C;?php</span> <span class="hljs-keyword">endforeach</span>; <span class="hljs-meta">?></span></code></pre><p>O servidor buscava os dados, processava a regra necessária e devolvia:</p><pre><code class="hljs language-html"><span class="hljs-tag">&#x3C;<span class="hljs-name">div</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">h2</span>></span>Teclado mecânico<span class="hljs-tag">&#x3C;/<span class="hljs-name">h2</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">span</span>></span>R$ 299<span class="hljs-tag">&#x3C;/<span class="hljs-name">span</span>></span><span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span></code></pre><p>E acabou.</p><p>O navegador recebia HTML.</p><p>Não existia necessariamente um runtime inteiro reconstruindo a interface.</p><p>Não existia hidratação daquela lista.</p><p>Não existia estado React representando os produtos.</p><p>Não existia uma camada de fetching no cliente para buscar novamente uma informação que o servidor já possuía.</p><p>Não existia <code>useEffect</code> esperando a página montar para descobrir o que deveria aparecer nela.</p><p>PHP foi provavelmente o maior representante dessa filosofia, mas não estava sozinho.</p><p>Tivemos ASP e depois ASP.NET, JSP/Servlets no ecossistema Java, Ruby on Rails, Django em Python e vários sistemas de templates server-side.</p><p>Cada ecossistema tinha seus problemas, mas compartilhavam uma ideia extremamente poderosa:</p><blockquote><p><strong>o servidor produz o documento e o navegador apresenta o documento.</strong></p></blockquote><p>JavaScript entrava principalmente quando precisávamos de comportamento adicional.</p><hr><h2 id="gabrielbaiano-content-php-era-bonito">PHP era bonito?</h2><p>Depende do PHP que você viu.</p><p>Quem já abriu um sistema legado com SQL, HTML, CSS e regra de negócio misturados no mesmo arquivo provavelmente está rindo agora.</p><p>Mas não estou defendendo PHP spaghetti.</p><p>Estou falando do <strong>modelo arquitetural</strong>.</p><p>Era muito difícil superar a simplicidade operacional de:</p><pre><code class="hljs language-text">Request   ↓Servidor   ↓Banco   ↓Template   ↓HTML   ↓Browser</code></pre><p>Compare conceitualmente com uma aplicação moderna:</p><pre><code class="hljs language-text">Request   ↓CDN   ↓SSR / Server Component   ↓API   ↓Client Component   ↓Hydration   ↓State   ↓Cache   ↓Re-render</code></pre><p>É claro que a segunda arquitetura consegue fazer coisas que seriam muito mais difíceis na primeira.</p><p>Esse é justamente o ponto.</p><p><strong>Nós ganhamos capacidade em troca de complexidade.</strong></p><p>O problema aparece quando utilizamos a segunda arquitetura para resolver problemas que ainda poderiam ser resolvidos perfeitamente pela primeira.</p><hr><h1 id="gabrielbaiano-content-o-curioso-retorno-das-ideias-antigas">O curioso retorno das ideias antigas</h1><p>E existe uma ironia nisso tudo.</p><p>Depois de anos levando cada vez mais responsabilidade para o cliente, o frontend começou a descobrir novamente o servidor.</p><p>SSR.</p><p>Static Site Generation.</p><p>Server Components.</p><p>Streaming HTML.</p><p>Server Actions.</p><p>Islands Architecture.</p><p>Progressive Enhancement.</p><p>Até frameworks modernos começam a perguntar:</p><blockquote><p>“Será que esse JavaScript realmente precisa chegar ao navegador?”</p></blockquote><p>Não estamos voltando para 2005.</p><p>As ferramentas são incomparavelmente mais poderosas.</p><p>Mas várias das ideias consideradas modernas são, em algum nível, uma redescoberta de uma propriedade antiga da web:</p><p><strong>se algo pode ser resolvido antes de chegar ao cliente, talvez não precisemos transformar isso em trabalho para o cliente.</strong></p><p>Talvez o PHP não estivesse tão errado assim.</p><hr><h1 id="gabrielbaiano-content-um-pequeno-jabá-foi-assim-que-comecei-o-pure-svg-charts">Um pequeno jabá: foi assim que comecei o pure-svg-charts</h1><p>Toda essa discussão começou para mim por causa de uma situação ridiculamente simples:</p><p><strong>eu precisava colocar gráficos em React.</strong></p><p>E temos bibliotecas excelentes para isso.</p><p>Recharts, Chart.js, Victory, ECharts, D3 e várias outras.</p><p>Só que comecei a olhar para o que realmente precisava em boa parte dos dashboards:</p><p>linha.</p><p>barra.</p><p>área.</p><p>eixo.</p><p>tooltip.</p><p>E então olhar para tudo que estava entrando no projeto para fazer isso.</p><p>Foi daí que surgiu um experimento pessoal:</p><blockquote><p><strong>até onde dá para levar uma biblioteca de gráficos React se a restrição principal for fazer menos?</strong></p></blockquote><p>Estou desenvolvendo o <a href="https://github.com/GabrielBaiano/pure-svg-charts"><code>pure-svg-charts</code></a>.</p><p>A proposta é deliberadamente limitada:</p><p><strong>SVG nativo, zero dependências de runtime e bundle abaixo de 12 kB gzip.</strong></p><p>Não quero substituir D3.</p><p>Não quero construir um novo ECharts.</p><p>E definitivamente não quero que daqui a três anos a biblioteca tenha 300 opções diferentes de configuração e 40 dependências.</p><p>Para não cair no clássico:</p><blockquote><p>blazing fast 🚀</p></blockquote><p>montei também uma suíte de benchmarks com um dataset de 5.000 pontos:</p><table><thead><tr><th>Biblioteca</th><th>Motor</th><th align="right">Gzip</th><th align="right">Dependências</th><th align="right">Mount</th><th align="right">Nós DOM</th><th align="right">Streaming</th></tr></thead><tbody><tr><td><strong>pure-svg-charts</strong></td><td>SVG</td><td align="right"><strong>11.1 kB</strong></td><td align="right"><strong>0</strong></td><td align="right"><strong>1.45 ms</strong></td><td align="right"><strong>33</strong></td><td align="right"><strong>0.95 ms</strong></td></tr><tr><td>Recharts</td><td>SVG + D3</td><td align="right">162.4 kB</td><td align="right">14</td><td align="right">132.50 ms</td><td align="right">106</td><td align="right">138.20 ms</td></tr><tr><td>Chart.js + react-chartjs-2</td><td>Canvas</td><td align="right">68.2 kB</td><td align="right">4</td><td align="right"><strong>0.45 ms</strong></td><td align="right"><strong>7</strong></td><td align="right"><strong>0.35 ms</strong></td></tr><tr><td>Victory</td><td>SVG + D3</td><td align="right">184.6 kB</td><td align="right">22</td><td align="right">48.20 ms</td><td align="right">69</td><td align="right">38.50 ms</td></tr></tbody></table><p>E aqui existe uma observação importante:</p><p><strong>esse benchmark não prova que <code>pure-svg-charts</code> é melhor que essas bibliotecas.</strong></p><p>Chart.js, inclusive, é mais rápido nesse cenário.</p><p>D3, ECharts, Recharts e Victory também conseguem resolver problemas que minha biblioteca simplesmente não tenta resolver.</p><p>Para mim, o resultado interessante é outro:</p><blockquote><p><strong>quanto podemos economizar quando aceitamos deliberadamente resolver um problema menor?</strong></p></blockquote><p>Às vezes, especialização também é uma otimização.</p><p>Fim do jabá.</p><hr><h1 id="gabrielbaiano-content-no-fim-o-pato-virou-o-desenvolvedor">No fim, o pato virou o desenvolvedor</h1><p>E é aqui que volto para o pato.</p><p>No começo falei sobre ferramentas que parecem patos.</p><p>Nadam.</p><p>Andam.</p><p>Voam.</p><p>Fazem um pouco de tudo porque precisam funcionar em praticamente qualquer cenário.</p><p>Mas existe uma consequência interessante dessa evolução:</p><p><strong>o próprio desenvolvedor frontend virou um pato.</strong></p><p>Olhe para uma vaga moderna de Frontend Engineer.</p><p>Naturalmente você espera encontrar:</p><pre><code class="hljs language-text">HTMLCSSJavaScriptTypeScriptReact</code></pre><p>Perfeito.</p><p>Então você continua descendo.</p><pre><code class="hljs language-text">Next.jsSSRSSGReact QueryReduxWebSocketsRESTGraphQL</code></pre><p>Tudo bem.</p><p>Ainda estamos relativamente perto de casa.</p><p>Continua:</p><pre><code class="hljs language-text">JestTesting LibraryCypressPlaywrightStorybookDesign SystemAccessibilitySEOCore Web Vitals</code></pre><p>Ok.</p><p>Continua.</p><pre><code class="hljs language-text">Node.jsDockerCI/CDGitHub ActionsAWS / Azure / GCPKubernetesObservabilityDatadogGrafanaOpenTelemetry</code></pre><p>E, em algumas vagas:</p><pre><code class="hljs language-text">MicroservicesKafkaRedisCDNEdge ComputingBFFOAuthOpenID ConnectTerraform</code></pre><p>Em algum momento você olha para a descrição e pensa:</p><p><strong>eu ainda estou concorrendo para frontend?</strong></p><hr><h1 id="gabrielbaiano-content-mas-frontend-precisa-saber-kubernetes">"Mas frontend precisa saber Kubernetes?"</h1><p>Talvez.</p><p>E esse “talvez” diz bastante sobre onde chegamos.</p><p>Um frontend moderno não vive isolado.</p><p>Se você trabalha com SSR, precisa entender minimamente o servidor.</p><p>Se utiliza Next.js, precisa entender o que executa no cliente e o que executa no servidor.</p><p>Se sua aplicação está containerizada, Docker deixa de ser completamente distante.</p><p>Se existem pipelines de deploy, CI/CD começa a fazer parte da sua rotina.</p><p>Se a aplicação possui problemas em produção, observabilidade importa.</p><p>Se você precisa diagnosticar por que uma página demora quatro segundos para aparecer, talvez tenha que entender CDN, cache, HTTP, DNS, API, banco, processamento no backend e execução no browser.</p><p>Se trabalha com microfrontends, arquitetura distribuída começa a aparecer.</p><p>Se trabalha com autenticação, inevitavelmente aparecem cookies, tokens, OAuth, CORS, CSP e segurança web.</p><p>Se trabalha com performance, começa a precisar entender browser internals, parsing, rendering pipeline, layout, paint, compositing, memória e garbage collection.</p><p>Se trabalha com acessibilidade, precisa entender semântica, tecnologias assistivas e comportamento nativo do navegador.</p><p>Se trabalha com Design System, começa a tocar em design, UX, arquitetura de componentes e governança.</p><p>E se trabalha com um produto grande o suficiente, provavelmente precisa entender pelo menos um pouco de tudo isso.</p><p>Não necessariamente para <strong>administrar um cluster Kubernetes</strong>.</p><p>Não necessariamente para <strong>configurar uma VPC do zero</strong>.</p><p>Não necessariamente para <strong>ser DBA</strong>.</p><p>Mas o suficiente para saber onde o frontend termina e onde o problema começa.</p><hr><h1 id="gabrielbaiano-content-frontend-virou-uma-área-multidisciplinar">Frontend virou uma área multidisciplinar</h1><p>Talvez seja por isso que seja cada vez mais difícil explicar para alguém de fora o que exatamente um Frontend Engineer faz.</p><p>A resposta simples seria:</p><blockquote><p>“Ele faz a interface.”</p></blockquote><p>Mas isso descreve cada vez menos o trabalho.</p><p>O frontend está no encontro entre várias disciplinas:</p><pre><code class="hljs language-text">                 UX / DESIGN                     │                     │BACKEND ─────── FRONTEND ─────── BROWSER                     │                     │                DEVOPS / CLOUD                     │                     │            PERFORMANCE / DATA</code></pre><p>É provavelmente uma das poucas áreas da engenharia de software em que uma mudança aparentemente inocente na interface pode exigir conhecimento sobre:</p><ul><li>redes;</li><li>protocolos web;</li><li>APIs;</li><li>segurança;</li><li>infraestrutura;</li><li>design;</li><li>acessibilidade;</li><li>performance;</li><li>arquitetura;</li><li>testes;</li><li>observabilidade;</li><li>SEO;</li><li>comportamento do navegador.</li></ul><p>O desenvolvedor frontend moderno não precisa necessariamente dominar todas essas áreas.</p><p>Mas precisa saber <strong>o suficiente de várias delas para conseguir desempenhar bem a própria função</strong>.</p><p>Ele precisa nadar.</p><p>Precisa andar.</p><p>E de vez em quando alguém coloca Kubernetes na descrição da vaga e manda ele voar também.</p><p><strong>O frontend virou o pato da engenharia de software.</strong></p><hr><h1 id="gabrielbaiano-content-e-talvez-isso-explique-parte-do-paradoxo">E talvez isso explique parte do paradoxo</h1><p>Existe então uma contradição ainda maior.</p><p>Queremos que o frontend seja simples.</p><p>Mas esperamos que ele rode em milhares de dispositivos diferentes.</p><p>Queremos desenvolvimento rápido.</p><p>Mas esperamos SSR, acessibilidade, SEO, responsividade, testes e observabilidade.</p><p>Queremos bundles pequenos.</p><p>Mas queremos um ecossistema com uma biblioteca pronta para cada problema.</p><p>Queremos especialistas.</p><p>Mas publicamos vagas procurando alguém que conheça React, Node, Docker, AWS, Kubernetes, CI/CD, Figma, performance e talvez faça um cafezinho se sobrar tempo.</p><p>Queremos abstrações para esconder a complexidade.</p><p>Depois precisamos aprender como essas abstrações funcionam internamente quando alguma delas quebra.</p><p>Talvez seja por isso que performance no frontend seja uma discussão tão interessante.</p><p>Performance não é apenas fazer uma função executar em <code>1 ms</code> em vez de <code>5 ms</code>.</p><p>É decidir <strong>quanto trabalho deveria existir em primeiro lugar</strong>.</p><p>Tree shaking é ótimo.</p><p>Lazy loading é ótimo.</p><p>Code splitting é ótimo.</p><p>Memoização pode ser ótima.</p><p>Mas nenhum deles é tão eficiente quanto não enviar código desnecessário.</p><p>E é aqui que acho perigosa a interpretação que demos à famosa ideia de Donald Knuth sobre otimização prematura.</p><p>Evitar uma alocação microscópica em um código executado três vezes pode ser otimização prematura.</p><p>Passar três dias tentando economizar 800 bytes provavelmente também.</p><p>Mas perguntar:</p><blockquote><p><strong>“Precisamos realmente de toda essa arquitetura para resolver esse problema?”</strong></p></blockquote><p>não é otimização prematura.</p><p>É arquitetura.</p><hr><h1 id="gabrielbaiano-content-talvez-precisemos-aprender-a-fazer-menos">Talvez precisemos aprender a fazer menos</h1><p>Não acho que a solução seja abandonar React.</p><p>Muito menos voltar todo mundo para PHP.</p><p>Também não acho que devemos implementar manualmente cada dropdown porque instalar uma dependência fere nossos princípios.</p><p>Isso seria apenas trocar um extremo pelo outro.</p><p>Mas acho saudável recuperar uma pergunta que às vezes desaparece no desenvolvimento moderno:</p><blockquote><p><strong>qual é a menor quantidade de tecnologia necessária para resolver bem este problema?</strong></p></blockquote><p>Às vezes a resposta será PHP entregando HTML.</p><p>Às vezes será React.</p><p>Às vezes Next.js.</p><p>Às vezes um monolito.</p><p>Às vezes microfrontends.</p><p>Às vezes D3.</p><p>Às vezes uma biblioteca de 200 kB é absolutamente justificável.</p><p>E às vezes queremos desenhar sete barras.</p><p>O importante é perceber que cada camada possui um custo.</p><p>Cada abstração possui um custo.</p><p>Cada dependência possui um custo.</p><p>Cada generalização possui um custo.</p><p>E <strong>conveniência não elimina esse custo — apenas faz com que seja mais fácil não enxergá-lo.</strong></p><hr><p>No fim, talvez responsabilidade técnica não seja escolher sempre a solução mais performática.</p><p>Também não é escolher sempre aquela que entrega mais rápido.</p><p>É entender conscientemente <strong>o que estamos comprando e o que estamos pagando com cada decisão</strong>.</p><p>Se uma biblioteca de 160 kB economiza uma semana de desenvolvimento e resolve exatamente o problema do produto, talvez seja uma ótima troca.</p><p>Se estamos adicionando 160 kB porque ninguém parou cinco minutos para perguntar se precisava, talvez não seja.</p><p>E vocês?</p><p><strong>Até onde o frontend deveria ir?</strong></p><p>Kubernetes, cloud, observabilidade e arquitetura distribuída fazem parte naturalmente da profissão hoje ou estamos transformando o frontend em um pato que precisa saber fazer tudo?</p><p>E, principalmente:</p><p><strong>onde vocês traçam a linha entre “não reinvente a roda” e “talvez essa roda esteja carregando peso demais”?</strong></p><hr><p><em>E aproveitando o jabá: se alguém quiser testar, quebrar os benchmarks ou contribuir com o <code>pure-svg-charts</code>:</em></p><p>👉 <a href="https://github.com/GabrielBaiano/pure-svg-charts">https://github.com/GabrielBaiano/pure-svg-charts</a></p></div>]]></content:encoded>
            <author>gabrielbaiano</author>
        </item>
        <item>
            <title><![CDATA[Otimizando Sistemas de Pagamento de Alta Escala com Bit Packing: Conheça o JEC Enterprise (64-bit)]]></title>
            <link>https://www.tabnews.com.br/mlopes75/otimizando-sistemas-de-pagamento-de-alta-escala-com-bit-packing-conheca-o-jec-enterprise-64-bit</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/mlopes75/otimizando-sistemas-de-pagamento-de-alta-escala-com-bit-packing-conheca-o-jec-enterprise-64-bit</guid>
            <pubDate>Sat, 19 Sep 2026 06:25:15 GMT</pubDate>
            <description><![CDATA[Recentemente, li o excelente guia do @andersonlimadev sobre o design de um Sistema de Pagamentos em Escala (com pico de 25.000 transações/segundo e 500 GB/dia de Ledger). Esse cenário tro...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Recentemente, li o excelente guia do @andersonlimadev sobre o design de um Sistema de Pagamentos em Escala (com pico de 25.000 transações/segundo e 500 GB/dia de Ledger).</p><p>Esse cenário trouxe-me um insight prático de engenharia de software:<br><strong>como otimizar o footprint de armazenamento e indexação temporal sem perder a legibilidade humana e o contexto distribuído?</strong></p><p>Para resolver esse trade-off entre performance (binário compacto) e operabilidade (string legível), desenvolvi a especificação <strong>JEC Enterprise 64-Bit (Julia Epoch Compact)</strong>.</p><h3 id="mlopes75-content-o-que-é-o-jec-enterprise">O que é o JEC Enterprise?</h3><p>O JEC realiza <em>Bit Packing</em> na camada de aplicação. Ele encapsula alta precisão temporal (microssegundos) e 7 bits de metadados livres (User Space) dentro de uma única palavra nativa de <strong>64 bits (8 Bytes)</strong>.</p><p>Em sistemas distribuídos de alta escala, ele brilha ao resolver a colisão de aliases sem tabelas de mapeamento complexas ou UUIDs opacos de 16 bytes. Se dois servidores processam eventos no exato mesmo microssegundo, os 7 bits de User Space (usados para o ID do microsserviço ou região) garantem a unicidade cross-platform.</p><h3 id="mlopes75-content-aplicação-prática-no-ledger-de-dupla-entrada">Aplicação Prática no Ledger de Dupla Entrada</h3><p>No design de tabelas proposto para o Ledger, estimam-se terabytes de armazenamento mensais. Se substituirmos os IDs textuais e os timestamps padrão por chaves <code>uint64</code> geradas via JEC, obtemos:</p><ul><li><strong>Redução de Payload no Kafka e Banco:</strong> Um único campo de 8 bytes transporta o Instante UTC exato + ID do microsserviço emissor.</li><li><strong>Precisão para Antifraude e Conciliação:</strong> Resolução nativa em microssegundos, crucial para garantir que a sequência contábil (Débito antes do Crédito) seja respeitada sem ambiguidades em picos de carga.</li></ul><h3 id="mlopes75-content-o-caso-limite-do-bit-63-lição-de-produção">O Caso Limite do Bit 63 (Lição de Produção)</h3><p>Como o projeto possui uma camada em Dart (onde inteiros de 64 bits são <em>signed</em>) e suporte para Web3/EVM (onde são <em>unsigned</em>), deparámo-nos com um comportamento crítico na ordenação binária nativa em bases de dados como o PostgreSQL (<code>BIGINT</code>). Metade do espaço do Header ordena de forma invertida devido ao bit de sinal.</p><p>A solução em SQL para manter a ordenação gratuita e fiável é simples:</p><pre><code class="hljs language-sql"><span class="hljs-comment">-- 1. Estrutura da tabela usando o JEC como chave única temporal</span><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> ledger_entries (    jec_id <span class="hljs-type">BIGINT</span> <span class="hljs-keyword">PRIMARY</span> KEY, <span class="hljs-comment">-- Acumula tempo preciso + ID do microsserviço</span>    tx_id <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">64</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,    account_id <span class="hljs-type">BIGINT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,    direction <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">6</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (direction <span class="hljs-keyword">IN</span> (<span class="hljs-string">'DEBIT'</span>, <span class="hljs-string">'CREDIT'</span>)),    amount <span class="hljs-type">NUMERIC</span>(<span class="hljs-number">20</span>,<span class="hljs-number">6</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,    currency <span class="hljs-type">CHAR</span>(<span class="hljs-number">3</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>);<span class="hljs-comment">-- 2. Consulta de Auditoria corrigindo a ordenação do Bit 63 (máscara lógica)</span><span class="hljs-keyword">SELECT</span>     jec_id,    tx_id,    direction,    amount,    (jec_id <span class="hljs-operator">>></span> <span class="hljs-number">57</span>) <span class="hljs-operator">&#x26;</span> <span class="hljs-number">127</span> <span class="hljs-keyword">AS</span> microservice_id <span class="hljs-keyword">FROM</span> ledger_entries<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> (jec_id <span class="hljs-operator">&#x26;</span> x<span class="hljs-string">'7FFFFFFFFFFFFFFF'</span>::int8) <span class="hljs-keyword">ASC</span>;</code></pre><p>O repositório é open-source e conta com implementações oficiais para Dart e Solidity.</p><p>O que acham dessa abordagem de Bit Packing para aliviar o gargalo de I/O e armazenamento em arquiteturas de missão crítica?</p><p><a href="https://github.com">GitHub - jec-64bit-enterprise</a></p></div>]]></content:encoded>
            <author>mlopes75</author>
        </item>
        <item>
            <title><![CDATA[Vídeo carta de vendas com IA: do roteiro às cenas]]></title>
            <link>https://www.tabnews.com.br/aivideomaker/video-carta-de-vendas-com-ia-do-roteiro-as-cenas</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/aivideomaker/video-carta-de-vendas-com-ia-do-roteiro-as-cenas</guid>
            <pubDate>Sat, 19 Sep 2026 06:16:57 GMT</pubDate>
            <description><![CDATA[Um vídeo carta de vendas com IA não começa pelo avatar. Começa pela decisão que o público precisa entender, pela evidência disponível e por um roteiro que não promete mais do que a equipe...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Um vídeo carta de vendas com IA não começa pelo avatar. Começa pela decisão que o público precisa entender, pela evidência disponível e por um roteiro que não promete mais do que a equipe consegue provar. A geração automática ajuda a organizar cenas, mas a clareza da oferta continua sendo um trabalho editorial.</p><p>Considere um exemplo hipotético: uma pequena empresa de software de agenda quer explicar como uma equipe marca reuniões, recebe lembretes e consulta o histórico. O objetivo do vídeo é apresentar o fluxo e convidar a pessoa a conhecer o produto. Não há cliente, taxa de conversão ou depoimento real neste exemplo. A utilidade está em mostrar como revisar o material.</p><h2 id="aivideomaker-content-vídeo-carta-de-vendas-com-ia-precisa-de-um-briefing">Vídeo carta de vendas com IA precisa de um briefing</h2><p>Escreva uma frase para cada item: quem assiste, qual situação reconhece, o que você explica e qual ação é razoável depois. Se a equipe não concorda com essas frases, a ferramenta preencherá o vazio com generalidades.</p><p>Defina também o que o vídeo não fará. “Explicar o fluxo de agendamento” é um escopo verificável. “Fazer a equipe vender mais” é uma conclusão que exigiria dados e contexto. Um limite explícito reduz a tentação de colocar uma promessa forte no primeiro segundo.</p><h2 id="aivideomaker-content-divida-a-vsl-em-blocos-revisáveis">Divida a VSL em blocos revisáveis</h2><p>Use uma sequência simples:</p><table><thead><tr><th>Bloco</th><th>Pergunta</th><th>Material para conferir</th></tr></thead><tbody><tr><td>Situação</td><td>O que o público tenta fazer?</td><td>Uma rotina concreta</td></tr><tr><td>Problema</td><td>Onde aparece a fricção?</td><td>Exemplo real ou hipótese identificada</td></tr><tr><td>Mecanismo</td><td>Como a oferta organiza a tarefa?</td><td>Tela, processo ou módulo vigente</td></tr><tr><td>Evidência</td><td>O que sustenta a explicação?</td><td>Documento, demonstração autorizada ou fonte</td></tr><tr><td>Oferta</td><td>O que está incluído?</td><td>Lista e condições atuais</td></tr><tr><td>Próximo passo</td><td>O que a pessoa pode fazer?</td><td>Ação clara, sem urgência inventada</td></tr></tbody></table><p>Uma cena deve responder a uma pergunta. Se a narração fala de lembretes enquanto a imagem mostra um painel de relatórios, o vídeo pode parecer bonito e ainda assim ensinar a coisa errada. O roteiro deve indicar o nome da tela ou do documento usado como referência.</p><h2 id="aivideomaker-content-passe-o-roteiro-para-o-leaddeai">Passe o roteiro para o <a href="https://leadde.ai/pt/tools/ai-video-sales-letter-generator" rel="nofollow">Leadde.ai</a></h2><p>A página em português descreve entradas como tema, arquivo, texto, roteiro e PPT, além de apresentar narrador, elementos visuais, legendas e cenas personalizadas. Isso faz dela um ponto de partida para organizar o vídeo. Não é uma validação da copy e não substitui a conferência da oferta.</p><p>Para cada parágrafo, crie três colunas: fala, visual e prova. “A equipe recebe lembretes” precisa apontar para uma tela ou documento que realmente mostre o recurso. “Clientes economizam tempo” precisa de fonte e método; sem isso, reformule como objetivo ou retire. A tabela também ajuda a decidir onde uma captura é mais útil que um avatar.</p><h2 id="aivideomaker-content-faça-duas-revisões-diferentes">Faça duas revisões diferentes</h2><p>Na primeira, leia apenas o texto. Marque palavras como “melhor”, “mais rápido”, “garantido” e “sem esforço”. Cada comparação precisa de base. Um depoimento só entra com autorização, contexto e identificação correta. Um número que veio de uma apresentação antiga deve ser atualizado ou retirado.</p><p>Na segunda, assista e leia as legendas ao mesmo tempo. Confira nomes, datas, condições e rótulos de interface. Observe se a imagem sustenta a fala. Uma animação de calendário pode explicar uma sequência, mas não prova que todos os usuários terão aquele resultado. Se uma frase depende de um detalhe, mantenha esse detalhe visível.</p><h2 id="aivideomaker-content-entregue-uma-versão-que-possa-ser-atualizada">Entregue uma versão que possa ser atualizada</h2><p>Guarde o briefing, o roteiro, a tabela de cenas e a data da revisão. Quando mudar uma condição, liste as cenas afetadas. Não mantenha uma tela antiga apenas porque a narração parece boa. Uma pequena mudança no produto pode alterar o sentido de uma explicação.</p><p>Antes de publicar, peça a alguém fora do projeto para resumir a oferta em uma frase. Compare o resumo com o briefing. Se aparecer uma promessa nova, o roteiro precisa de revisão. Essa leitura também confirma se o próximo passo está claro para quem não conhece o produto.</p><p>Uma revisão final deve ser feita por alguém que não participou da redação. Essa pessoa assiste sem o briefing e tenta responder: qual problema está sendo tratado, o que a oferta inclui e qual é o próximo passo? Se não consegue responder, não adicione efeitos. Reescreva a cena ou acrescente a fonte que falta.</p><p>Também vale separar a versão para leitura da versão para publicação. O roteiro aprovado, as legendas e as cenas devem ter uma identificação comum. Assim, quando uma condição comercial mudar, o editor encontra o trecho certo sem procurar em todo o vídeo.</p><p>Uma boa carta também respeita o momento do leitor. A primeira cena pode reconhecer a situação, mas não precisa pressionar por uma decisão imediata. Mostre o que será explicado e deixe a pessoa avaliar se o assunto é relevante. O bloco de oferta deve listar o que está disponível hoje, enquanto o próximo passo explica como obter mais informação.</p><p>Peça ao responsável pelo produto que confira nomes de planos, condições e links antes de cada publicação. Se o roteiro mencionar um recurso que ainda está em teste, identifique-o como tal ou retire a frase. A transparência reduz correções posteriores e mantém a mensagem compreensível para quem chega ao vídeo sem contexto.</p><h3 id="aivideomaker-content-preciso-colocar-todo-o-roteiro-como-legenda">Preciso colocar todo o roteiro como legenda?</h3><p>Não. Use as legendas para acompanhar a fala e deixe na tela os rótulos que ajudam a localizar a ação. Texto excessivo reduz a chance de a pessoa notar a demonstração. Faça a revisão no reprodutor real e em uma tela pequena antes de publicar.</p><h3 id="aivideomaker-content-todo-vídeo-de-vendas-precisa-de-um-apresentador">Todo vídeo de vendas precisa de um apresentador?</h3><p>Não. Use um apresentador quando a transição ou o tom humano forem importantes. Use uma captura, uma tabela ou uma demonstração quando a evidência visual for mais clara. A escolha deve servir à explicação, não preencher espaço.</p></div>]]></content:encoded>
            <author>aivideomaker</author>
        </item>
        <item>
            <title><![CDATA[Seu OCS Inventory sabe qual é o computador. Sua planilha sabe qual é o patrimônio. Por que eles não conversam?]]></title>
            <link>https://www.tabnews.com.br/MartinsecTecnologia/seu-ocs-inventory-sabe-qual-e-o-computador-sua-planilha-sabe-qual-e-o-patrimonio-por-que-eles-nao-conversam</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/MartinsecTecnologia/seu-ocs-inventory-sabe-qual-e-o-computador-sua-planilha-sabe-qual-e-o-patrimonio-por-que-eles-nao-conversam</guid>
            <pubDate>Sat, 19 Sep 2026 03:59:55 GMT</pubDate>
            <description><![CDATA[Essa foi a pergunta que me levou a desenvolver o OCS Patrimônio. Em muitos ambientes de TI existe uma situação curiosa: O OCS Inventory possui uma quantidade enorme de informações sobre o...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Essa foi a pergunta que me levou a desenvolver o OCS Patrimônio.</p><p>Em muitos ambientes de TI existe uma situação curiosa:</p><p>O OCS Inventory possui uma quantidade enorme de informações sobre os equipamentos.</p><p>Ele sabe:</p><p>hostname;<br>IP;<br>MAC;<br>sistema operacional;<br>hardware;<br>número de série;<br>placa-mãe;<br>BIOS;<br>entre várias outras informações.</p><p>Por outro lado, o controle patrimonial costuma estar em outro lugar:</p><p>📊 Excel<br>📋 planilha compartilhada<br>📝 documento<br>📅 agenda<br>🗂️ sistema patrimonial isolado.</p><p>E aí começa o trabalho manual.</p><p>"Esse patrimônio 000123 pertence a qual computador?"</p><p>"Qual é o patrimônio desse equipamento?"</p><p>"O número de série dessa máquina está em qual linha da planilha?"</p><p>"Essa máquina já foi inventariada?"</p><p>Foi para eliminar justamente essa etapa manual que desenvolvi o OCS Patrimônio.</p><p>A ideia</p><p>A aplicação utiliza os dados do OCS Inventory NG para localizar os equipamentos e permite correlacioná-los com um número de patrimônio.</p><p>A identificação pode ser feita utilizando informações únicas do hardware, como:</p><p>BIOS + placa-mãe + número de série</p><p>E a parte patrimonial pode ser informada manualmente ou através de leitura da plaqueta.</p><p>📱 E aqui entra uma parte importante</p><p>A interface foi pensada para funcionar também em dispositivos móveis.</p><p>Então o técnico pode estar fisicamente diante do equipamento.</p><p>Ele pega o celular.</p><p>Lê o QR Code/código de barras da plaqueta.</p><p>O sistema recebe o número do patrimônio.</p><p>Localiza o equipamento correspondente no OCS.</p><p>E realiza a correlação.</p><p>O objetivo não é criar complexidade</p><p>É justamente reduzir complexidade.</p><p>A ideia é transformar:</p><p>planilha → procura manual → conferência → número de série → associação</p><p>em:</p><p>📱 escanear → 🔎 localizar → 🔗 correlacionar</p><p>Também existe uma visão geral mostrando equipamentos inventariados, correlacionados e pendentes.</p></div>]]></content:encoded>
            <author>MartinsecTecnologia</author>
        </item>
        <item>
            <title><![CDATA[[ Pitch ] Change Data Capture - Mini CDC: Reagir à mudanças em uma tabela MySQL sem pooling]]></title>
            <link>https://www.tabnews.com.br/damtaipu/change-data-capture-mini-cdc</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/damtaipu/change-data-capture-mini-cdc</guid>
            <pubDate>Sat, 19 Sep 2026 03:40:16 GMT</pubDate>
            <description><![CDATA[Se você só precisa reagir à mudança em uma tabela MySQL, não deveria precisar consultar o banco a cada poucos segundos — muito menos adotar uma plataforma complexa de CDC. É para esse cen...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Se você só precisa reagir à mudança em uma tabela MySQL, não deveria precisar consultar o banco a cada poucos segundos — muito menos adotar uma plataforma complexa de CDC.</p><p>É para esse cenário que serve o Mini CDC. Ele acompanha diretamente o binlog do MySQL, identifica as mudanças que realmente importam e publica os eventos correspondentes no RabbitMQ.</p><p>Por exemplo:</p><blockquote><p>“Quando o campo status de um pedido mudar para APPROVED, publique um evento.”</p></blockquote><p>Sem polling. Sem consultas repetitivas. Sem colocar essa responsabilidade dentro da aplicação principal. Por meio de uma configuração simples, é possível definir:<br>• quais tabelas devem ser monitoradas;<br>• quais operações devem ser consideradas;<br>• quais campos precisam realmente ter mudado;<br>• quais valores devem atender às condições;<br>• qual evento e routing key devem ser publicados.</p><p>Uma única conexão de replicação pode acompanhar várias tabelas. O Mini CDC também oferece checkpoint para retomada após reinicializações, Publisher Confirms, identificadores determinísticos para idempotência, health checks e métricas operacionais simples.</p><p>O objetivo não é substituir plataformas completas como o Debezium. A proposta é permanecer pequeno e resolver bem um problema específico:</p><p>MySQL binlog → filtros configuráveis → RabbitMQ</p><p>Para pequenos projetos, isso significa menos infraestrutura, menos código de integração e uma forma simples de reagir às mudanças no banco de dados.</p><p>O projeto foi desenvolvido em Go, para execução em multiplas plataformas com foco em simplicidade, baixo consumo e facilidade de manutenção.</p><p>O Mini CDC é open source, e o README explica  no detalhe como ele funciona e como configurá-lo:<br><a href="https://github.com/damtaipu/minicdc">https://github.com/damtaipu/minicdc</a></p><p>#Go #MySQL #RabbitMQ #CDC #ArquiteturaDeSoftware #OpenSource</p></div>]]></content:encoded>
            <author>damtaipu</author>
        </item>
        <item>
            <title><![CDATA[oh-my-agent: runs que falham viram testes de regressão de skills]]></title>
            <link>https://www.tabnews.com.br/gracefullight/oh-my-agent-runs-que-falham-viram-testes-de-regressao-de-skills</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/gracefullight/oh-my-agent-runs-que-falham-viram-testes-de-regressao-de-skills</guid>
            <pubDate>Sat, 19 Sep 2026 00:56:28 GMT</pubDate>
            <description><![CDATA[Uma run de agent que falhava terminava com um log e um dar de ombros. Nesta semana o oh-my-agent fechou esse ciclo: uma falha pode ser capturada como incidente, promovida a fixture de uma...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Uma run de agent que falhava terminava com um log e um dar de ombros. Nesta semana o oh-my-agent fechou esse ciclo: uma falha pode ser capturada como incidente, promovida a fixture de uma skill e entregue a um otimizador que edita a skill sob um orçamento de dispatches. Foram 131 commits, e a CLI saiu da versão 14.7.11 para a 14.13.1.</p><h2 id="gracefullight-content-o-que-mudou">O que mudou</h2><ul><li><strong>Captura e promoção de incidentes</strong>: <code>oma harness incident scan</code> lista runs com falha, bloqueadas ou parciais que nenhum incidente referencia. <code>oma harness incident promote</code> deriva uma fixture de regressão para a skill que o agent usou e só a admite se ela reprovar o output de falha registrado. <code>oma harness feedback --scan-runs</code> encadeia captura, promoção e otimização. Runs finalizadas agora guardam os últimos 64 KiB do log do runner, para que a fixture seja validada contra o que o agent realmente disse.</li><li><strong>Evolução de skills com orçamento</strong>: <code>oma skill optimize</code> só aceita uma edição quando nem o split de validação nem o de treino regridem e pelo menos um melhora. <code>constitution.budget.max_dispatches_per_run</code> agora é aplicado: a chamada que estouraria o limite é recusada e a promoção fica bloqueada. Toda edição aplicada registra sua linhagem, e <code>oma skill promotions</code> e <code>oma skill rollback</code> leem esse registro.</li><li><strong>Meta-otimização</strong>: <code>oma skill meta-optimize</code> trata o próprio prompt do otimizador como candidato. A promoção exige um intervalo de 95% por bootstrap pareado (com seed) acima de zero e pelo menos três pares. O primeiro procedimento adotado superou o atual em 0.27 na média, com intervalo [0.04, 0.54], e acrescentou três regras de grounding para edições propostas de skills.</li><li><strong>Eval de roteamento</strong>: <code>oma skill eval --routing</code> mostra ao modelo a descrição de todas as skills instaladas e registra se ele escolhe a skill alvo, uma vizinha ou nenhuma. Isso separa "o corpo da skill ajuda" de "a skill é selecionada".</li><li><strong>Guard de code intelligence</strong>: um hook PreToolUse nega Grep, Glob e buscas recursivas no shell (<code>rg</code>, <code>grep -r</code>, <code>find -name</code>, <code>git grep</code>) enquanto houver um provider configurado. A mensagem de negação indica qual ferramenta do Serena usar. <code>OMA_CI_ALLOW_NATIVE=1</code> é a saída de emergência, e <code>providers.code_intelligence_guard: off</code> desativa o guard.</li><li><strong>Avisos no início da sessão</strong>: o snapshot de estado agora anuncia promoções de skills e procedimentos uma única vez, em uma linha por promoção, com a edição e os ganhos. <code>oma doctor</code> ganhou uma nota de Evolution.</li><li><strong>Relatórios para o Orca</strong>: agents filhos disparados pelo oma reportam seu ciclo de vida ao Orca. O Qwen ganhou definições nativas de agent.</li></ul><h2 id="gracefullight-content-o-que-foi-corrigido">O que foi corrigido</h2><ul><li>O job semanal de cross-post falhava em toda execução depois que <code>model_preset</code> passou para <code>auto</code>. O <code>claude --output-format json</code> encapsula a resposta em um envelope, e <code>runAgent</code> devolvia esse envelope cru. Agora ele extrai o caminho <code>response_jq</code> configurado e cai para o stdout bruto nos vendors que não têm um.</li><li>Jobs do SO registrados antes da renomeação do comando continuavam chamando <code>oma schedule:run &#x3C;id></code> e falhavam a cada disparo, enquanto <code>schedule list</code> os mostrava como sincronizados. A grafia antiga agora é aceita quando o SO a invoca, a detecção de drift ganhou o estado <code>stale</code>, e <code>oma schedule sync</code> e <code>oma update</code> reescrevem os registros desatualizados.</li><li><code>cd $HOME &#x26;&#x26; oma link claude</code> tratava o HOME como um projeto e reescrevia os comandos de hook globais do Claude. <code>link</code> e <code>update</code> agora recusam o modo projeto a partir do HOME (#788).</li><li>O judge de skills lia PASS/FAIL do envelope cru do Claude, onde <code>"failed":0</code> aparecia antes do veredito, então todo veredito virava FAIL. Agora as saídas são extraídas do envelope antes da pontuação, e as gravações antigas são descartadas.</li><li><code>--repeats 3</code> virava NaN porque um <code>parseInt</code> puro recebia o valor anterior como radix. Valores de opções variádicas (<code>--skill a b</code>) não disparam mais o guard de posicional solto.</li><li>Projetos sincronizados antes da v11 ainda rodavam o próprio Serena a cada sessão. A migration 029 reescreve esses launchers para a entrada compartilhada <code>oma bridge</code>, na forma nativa de cada vendor.</li><li><code>oma update</code> respeita uma lista explícita de vendors em vez de detectar a partir dos diretórios do projeto.</li></ul><h2 id="gracefullight-content-o-que-melhorou">O que melhorou</h2><ul><li>Uma época de otimização com quatro candidatos levava quarenta minutos porque cada arm e cada judge rodavam em série. Os dispatches reais agora passam por um pool limitado (<code>OMA_SKILL_EVAL_CONCURRENCY</code>, padrão 4), e a meta-otimização sobrepõe as runs internas entre skills (<code>OMA_META_CONCURRENCY</code>, até 4). O timeout por dispatch é de 180s, com uma nova tentativa em caso de timeout.</li><li>As fixtures testam o que o corpo da skill afirma. O conjunto do oma-debug foi reescrito depois que a primeira versão marcou 89% sem a skill. As doze novas marcam 25% de baseline e 100% com a skill. O oma-refactor foi de 16.7% para 100% do mesmo jeito. oma-docs, oma-scm e oma-qa também têm, cada uma, doze fixtures alinhadas ao corpo da skill.</li><li>A primeira edição verificada pelo loop entrou no oma-docs: held-in de 55.6% para 77.8%, com a validação held-out inalterada em 100%.</li><li>O custo ficou visível. As runs reportam chamadas de modelo por melhoria verificada, então um procedimento que ganha mais gastando mais aparece como tal.</li><li>O Gortex saiu e a code intelligence voltou para a bridge do Serena. Ele saturava a CPU reaplicando patches em um índice de 4 GB e não expunha nenhum limite.</li><li>Os arquivos de skills e de prompts compartilhados foram enxugados para cortar regras incondicionais de preflight, pontuação e aprovação. Os guias de incidentes saíram nos 11 locales da documentação.</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><h2 id="gracefullight-content-links">Links</h2><p>O oh-my-agent é feito para times que orquestram mais do que escrevem prompts. O próximo passo é rodar o loop de feedback em agendamento sobre runs reais de projetos, para que as edições de skills cheguem com a evidência anexada.</p><p>Texto original (em ingles): <a href="https://dev.to/gracefullight/oh-my-agent-failed-runs-now-turn-into-skill-regression-tests-572m" rel="nofollow">https://dev.to/gracefullight/oh-my-agent-failed-runs-now-turn-into-skill-regression-tests-572m</a></p><p><a href="https://github.com/first-fluke/oh-my-agent">https://github.com/first-fluke/oh-my-agent</a></p></div>]]></content:encoded>
            <author>gracefullight</author>
        </item>
        <item>
            <title><![CDATA[O histórico de prompts também deveria fazer parte do código-fonte?]]></title>
            <link>https://www.tabnews.com.br/JoasSurfer/o-historico-de-prompts-tambem-deveria-fazer-parte-do-codigo-fonte</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/JoasSurfer/o-historico-de-prompts-tambem-deveria-fazer-parte-do-codigo-fonte</guid>
            <pubDate>Sat, 19 Sep 2026 00:27:53 GMT</pubDate>
            <description><![CDATA[Quando usamos agentes de IA para programar, o repositório guarda o resultado, mas normalmente perde as decisões, correções e mudanças de direção que levaram até ele. Por isso criei o Prom...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Quando usamos agentes de IA para programar, o repositório guarda o resultado, mas normalmente perde as decisões, correções e mudanças de direção que levaram até ele.<br>Por isso criei o PromptSourceCode, um projeto open source para Codex Desktop que mantém um histórico cronológico e legível das interações e dos anexos relevantes junto ao projeto. Tudo funciona localmente, sem serviço em segundo plano ou envio automático de dados.</p><p>O projeto ainda está focado em Codex Desktop. Ficaria muito feliz em receber feedback sobre a ideia e o processo de instalação:</p><p><a href="https://github.com/ironwood-lang/prompt-source-code">https://github.com/ironwood-lang/prompt-source-code</a></p></div>]]></content:encoded>
            <author>JoasSurfer</author>
        </item>
        <item>
            <title><![CDATA[Pitch: legendas traduzidas ao vivo em chamadas no navegador, com o áudio da aba capturado por uma extensão MV3]]></title>
            <link>https://www.tabnews.com.br/trippi/pitch-legendas-traduzidas-ao-vivo-em-chamadas-no-navegador-com-o-audio-da-aba-capturado-por-uma-extensao-mv3</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/trippi/pitch-legendas-traduzidas-ao-vivo-em-chamadas-no-navegador-com-o-audio-da-aba-capturado-por-uma-extensao-mv3</guid>
            <pubDate>Fri, 18 Sep 2026 21:11:35 GMT</pubDate>
            <description><![CDATA[Eu sou o autor do projeto e desenvolvo sozinho. O link no final passa por um redirecionamento meu que só conta cliques. A extensão mostra legendas traduzidas em tempo real durante uma cha...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Eu sou o autor do projeto e desenvolvo sozinho. O link no final passa por um redirecionamento meu que só conta cliques.</p><p>A extensão mostra legendas traduzidas em tempo real durante uma chamada no Meet, no Zoom ou no Teams pelo navegador, sem nenhum bot na reunião. Abaixo, as três partes que deram mais trabalho.</p><h2 id="trippi-content-1-capturar-o-áudio-da-aba-no-manifest-v3">1. Capturar o áudio da aba no Manifest V3</h2><p>No MV3 o service worker não tem Web Audio, então a captura fica em dois lugares. O service worker chama <code>chrome.tabCapture.getMediaStreamId({ targetTabId })</code>, que devolve só um id, e cria um documento offscreen com <code>reasons: ['USER_MEDIA']</code>. Lá dentro o id vira stream no <code>getUserMedia</code> com <code>chromeMediaSource: 'tab'</code>, e um <code>AudioWorkletNode</code> junta os canais em mono e manda Int16 PCM em blocos de 4096 amostras.</p><p>Duas coisas custaram tempo. O stream precisa ser ligado de volta em <code>audioCtx.destination</code>, senão a captura silencia a aba e a pessoa para de ouvir a própria reunião. E o erro "Cannot capture a tab with an active stream" aparece quando o stream anterior não foi liberado, e não sai nem recarregando a página: o jeito foi fechar o documento offscreen e consultar <code>chrome.tabCapture.getCapturedTabs()</code> até a aba sair de <code>active</code>.</p><p>Contra o <code>getDisplayMedia()</code> numa página comum: aqui não aparece o seletor de tela, mas a extensão precisa ter sido invocada naquela aba (activeTab) e só pega o áudio da aba.</p><h2 id="trippi-content-2-dois-provedores-custaram-muito-mais-que-um">2. Dois provedores custaram muito mais que um</h2><p>A primeira versão usava um serviço para reconhecimento e outro para tradução. Para a tradução acompanhar a fala, os resultados parciais também iam para o tradutor, e a mesma frase era traduzida duas ou três vezes. Uma hora de chamada saía por volta de US$ 2,55, acima do que os planos cobriam.</p><p>Troquei por um provedor que devolve transcrição e tradução no mesmo stream, com chave temporária emitida pelo servidor. Pela fatura real, hoje uma hora custa uns US$ 0,15. O preço disso é atraso: a legenda final chega em alguns segundos, contra uns dois antes. E o provedor não separa <code>pt-BR</code> de <code>pt-PT</code>, as duas viram <code>pt</code>.</p><h2 id="trippi-content-3-o-cronômetro-contava-errado">3. O cronômetro contava errado</h2><p>O tempo começava quando a conexão abria, não quando chegava a primeira legenda, então numa aba sem som os minutos eram gastos à toa. Achei olhando as minhas próprias estatísticas, agora a contagem começa com o primeiro resultado real.</p><p>Limites: só o áudio da aba do navegador, app desktop e celular não, e a legenda final demora alguns segundos.</p><p>Críticas sobre a parte técnica são bem-vindas, principalmente sobre a captura no MV3: <a href="https://gettrippi.app/go/tabnews_pitch" rel="nofollow">https://gettrippi.app/go/tabnews_pitch</a></p></div>]]></content:encoded>
            <author>trippi</author>
        </item>
        <item>
            <title><![CDATA[Procuro um falante nativo de português para traduzir o README de um SQL IDE open source (MIT)]]></title>
            <link>https://www.tabnews.com.br/cevheri/procuro-um-falante-nativo-de-portugues-para-traduzir-o-readme-de-um-sql-ide-open-source-mit</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/cevheri/procuro-um-falante-nativo-de-portugues-para-traduzir-o-readme-de-um-sql-ide-open-source-mit</guid>
            <pubDate>Fri, 18 Sep 2026 20:29:15 GMT</pubDate>
            <description><![CDATA[Sou o mantenedor do LibreDB Studio, um SQL IDE open source sob licença MIT que roda no navegador e conecta em 16 bancos diferentes (PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis,...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Sou o mantenedor do LibreDB Studio, um SQL IDE open source sob licença MIT que roda no navegador e conecta em 16 bancos diferentes (PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, DuckDB e outros). O repositório está em<br><a href="https://github.com/libredb/libredb-studio">https://github.com/libredb/libredb-studio</a></p><p>O projeto já tem README em chinês, japonês, espanhol, urdu e hindi. Falta o português. A issue é esta:<br><a href="https://github.com/libredb/libredb-studio/issues/594">https://github.com/libredb/libredb-studio/issues/594</a></p><p>Duas coisas que valem dizer antes de alguém gastar tempo:</p><p>O escopo é menor do que parece. O README em inglês tem mais de mil linhas, mas as traduções existentes têm cerca de trezentas.<br>Elas são resumos deliberados: carregam a proposta do projeto, a lista de bancos, a tabela de instalação e o quick start, e deixam de fora as seções profundas. A tradução em português deve seguir o mesmo recorte.</p><p>A revisão é objetiva, não é questão de gosto. Existe um script de verificação que roda no CI e checa duas coisas: que o conjunto de nomes de bancos seja idêntico ao do README em inglês, e que todo comando de instalação apareça igual, caractere por caractere. Um sudo faltando ou um comando parafraseado quebra o check. O resto é revisão de texto normal.</p><p>O que eu não quero é saída crua de tradutor automático. Se o texto ler como máquina, eu fecho o PR. Termos técnicos e nomes de produto ficam melhor em inglês do que traduzidos por aproximação.</p><p>Se alguém topar, comenta na issue para eu reservar. Respondo rápido nas revisões.</p></div>]]></content:encoded>
            <author>cevheri</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Construí sozinho um SaaS de WhatsApp pra corretor de imóveis — preciso de 10 devs pra tentar quebrar ele antes que eu lance]]></title>
            <link>https://www.tabnews.com.br/nuneslluis/construi-sozinho-um-saas-de-whatsapp-pra-corretor-de-imoveis-preciso-de-10-devs-pra-tentar-quebrar-ele-antes-que-eu-lance</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/nuneslluis/construi-sozinho-um-saas-de-whatsapp-pra-corretor-de-imoveis-preciso-de-10-devs-pra-tentar-quebrar-ele-antes-que-eu-lance</guid>
            <pubDate>Fri, 18 Sep 2026 20:13:20 GMT</pubDate>
            <description><![CDATA[Eaii, rapazeada Sou dev solo e nos últimos meses construí o ZapBroker: uma automação de WhatsApp feita especificamente pra corretor de imóveis. Não é uma "ferramenta de disparo em massa"...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p><strong>Eaii, rapazeada</strong></p><p>Sou dev solo e nos últimos meses construí o <strong>ZapBroker</strong>: uma automação de WhatsApp feita especificamente pra <strong>corretor de imóveis</strong>.</p><p>Não é uma <em>"ferramenta de disparo em massa"</em> genérica: o produto inteiro é desenhado em cima da rotina de quem vende imóvel.</p><p><strong>Stack</strong>, pra quem gosta de saber o que tem por trás:</p><ul><li><code>Node.js / Express</code> — backend</li><li><code>Next.js</code> — frontend</li><li><code>Supabase (Postgres)</code> — banco de dados</li><li><code>Evolution API</code> — integração com WhatsApp</li><li><code>OpenRouter</code> — IA</li><li><code>AbacatePay (Pix)</code> — checkout</li></ul><h3 id="nuneslluis-content-ainda-não-lancei">Ainda não lancei</h3><p>E é exatamente por isso que tô aqui.</p><p>Eu sou a <strong>única pessoa que testa esse sistema de perto</strong>, e isso é ruim. Todo bug de segurança que eu não vejo pode simplesmente estar passando despercebido porque <strong>eu já sei como o sistema funciona por dentro</strong>.</p><p>Então quero gente de fora tentando quebrar isso.</p><h3 id="nuneslluis-content-o-que-eu-tô-liberando">O que eu tô liberando</h3><p>Vou soltar aqui um <strong>link único de cadastro com 10 vagas</strong>.</p><p>Quem entrar vai receber:</p><ul><li><strong>Plano completo (Pro)</strong></li><li><strong>3 dias de acesso</strong></li><li><strong>Sem custo</strong></li></ul><p>Quem clicar primeiro e completar o cadastro pega uma vaga.</p><p>Quando chegar em <strong>10 usuários</strong>, o link simplesmente para de aceitar gente nova.</p><h3 id="nuneslluis-content-o-que-eu-queria-que-vocês-avaliassem">O que eu queria que vocês avaliassem</h3><p><strong>Segurança — essa é a prioridade real do post.</strong></p><p>Tentem de tudo:</p><ul><li>autenticação</li><li>acesso indevido entre contas</li><li>dados vazando de uma conta pra outra</li><li>requests forjadas</li><li>manipulação de parâmetros</li><li>permissões</li><li>endpoints</li><li>qualquer coisa que consiga quebrar ou contornar alguma regra do sistema</li></ul><p>Se acharem alguma vulnerabilidade, <strong>por favor, avisem</strong>.</p><p>Não precisa ter dó 😂</p><h3 id="nuneslluis-content-fluxo-do-whatsapp">Fluxo do WhatsApp</h3><p>Também quero saber se o disparo funciona <strong>ponta a ponta</strong>:</p><ul><li>conectar o número</li><li>subir uma lista</li><li>iniciar o disparo</li><li>mensagens sendo enviadas</li><li>receber respostas</li><li>verificar se tudo continua funcionando corretamente</li></ul><h3 id="nuneslluis-content-experiência-de-uso">Experiência de uso</h3><p>Aqui também não estou procurando elogio.</p><p>Prefiro <strong>um feedback grosseiro e certeiro</strong> do que um <em>"ficou legal"</em> educado.</p><p>Se alguma coisa estiver confusa, ruim, lenta, mal posicionada ou simplesmente não fizer sentido, <strong>fala</strong>.</p><blockquote><p>A ideia é encontrar os problemas agora, antes de colocar isso na mão de clientes.</p></blockquote><p><strong>Link:</strong> <a href="https://zapbroker.dev/signup?invite=A77FB845" rel="nofollow">https://zapbroker.dev/signup?invite=A77FB845</a><br><strong>Para feedbacks</strong>: <a href="https://zapbroker.dev/feedback" rel="nofollow">https://zapbroker.dev/feedback</a></p><p>Valeu por lerem até aqui 🤝</p></div>]]></content:encoded>
            <author>nuneslluis</author>
        </item>
        <item>
            <title><![CDATA[Arquitetura de um Gateway de E-mails Transacionais: Por que separamos API de Workers, Argon2id com prefixo e rotação de chaves]]></title>
            <link>https://www.tabnews.com.br/RuanLopes1350/arquitetura-de-um-gateway-de-e-mails-transacionais-por-que-separamos-api-de-workers-argon2id-com-prefixo-e-rotacao-de-chaves</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/RuanLopes1350/arquitetura-de-um-gateway-de-e-mails-transacionais-por-que-separamos-api-de-workers-argon2id-com-prefixo-e-rotacao-de-chaves</guid>
            <pubDate>Fri, 18 Sep 2026 19:42:24 GMT</pubDate>
            <description><![CDATA[Disparar e-mails transacionais diretamente de dentro dos endpoints da sua aplicação cria acoplamento excessivo, eleva o tempo de resposta HTTP (handshakes SMTP levam facilmente entre 500m...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Disparar e-mails transacionais diretamente de dentro dos endpoints da sua aplicação cria acoplamento excessivo, eleva o tempo de resposta HTTP (handshakes SMTP levam facilmente entre 500ms e 2s) e espalha credenciais sensíveis por vários microsserviços.</p><p>O <strong>Hermes</strong> é um gateway open-source e multi-tenant desenvolvido para centralizar esse fluxo. Para evitar que a lentidão ou instabilidade de provedores SMTP trave as requisições upstream, o sistema separa rigidamente a recepção HTTP do envio real utilizando filas assíncronas com BullMQ e Redis. No campo da segurança, as credenciais SMTP em repouso são protegidas com <strong>AES-256-GCM</strong>, enquanto as chaves de API programáticas utilizam uma estratégia híbrida de <strong>prefixo indexado + Argon2id</strong> para garantir buscas em <span class="math math-inline">O(1)</span> sem abrir mão de proteção contra ataques de força bruta por hardware.</p><p>Os repositórios e o pacote já estão disponíveis:</p><ul><li><strong>API Gateway e Workers:</strong> <a href="https://github.com/RuanLopes1350/hermes-api">github.com/RuanLopes1350/hermes-api</a></li><li><strong>Painel Administrativo:</strong> <a href="https://github.com/RuanLopes1350/hermes-front">github.com/RuanLopes1350/hermes-front</a></li><li><strong>SDK TypeScript (Client):</strong> <a href="https://github.com/RuanLopes1350/hermes-client">github.com/RuanLopes1350/hermes-client</a></li><li><strong>Pacote no NPM:</strong> <a href="https://www.npmjs.com/package/@ruanlopes1350/hermes-client" rel="nofollow"><code>@ruanlopes1350/hermes-client</code></a></li></ul><hr><h2 id="ruanlopes1350-content-1-o-problema-que-resolvemos">1. O Problema que Resolvemos</h2><p>Em arquiteturas tradicionais, é comum ver o transporte SMTP (usando bibliotecas como Nodemailer) instanciado diretamente no fluxo de criação de conta ou recuperação de senha:</p><pre><code>[Requisição de Cadastro]     └──► Salva no Banco     └──► Conecta no SMTP (DNS + TLS Handshake + Envio) ──► Espera 1.5s ──► Responde 200 OK</code></pre><p>Esse modelo gera três gargalos:</p><ol><li><strong>Latência no cliente:</strong> O usuário final fica com o botão travado esperando a confirmação da rede externa de e-mail.</li><li><strong>Perda de mensagens:</strong> Se o servidor SMTP oscilar ou aplicar rate limit momentâneo, o e-mail se perde ou exige lógica de retry local complexa que pode sobrecarregar a própria API.</li><li><strong>Gestão de credenciais:</strong> Conforme a quantidade de microsserviços cresce, senhas de app e tokens de envio ficam dispersos em múltiplos arquivos <code>.env</code>.</li></ol><p>O Hermes atua como uma barreira isoladora com modelo multi-tenant: cada serviço cadastrado tem suas próprias chaves, templates e histórico de auditoria.</p><pre><code>┌─────────────────────────────────────────────────────────────┐│          APLICAÇÕES CLIENTES (@ruanlopes1350/hermes-client) │└──────────────────────────────┬──────────────────────────────┘  (POST /api/emails + X-API-Key)│       ▲ (Webhook assinado                                │       │  para rotação de chave)                                ▼       │┌───────────────────────────────────────┴─────────────────────┐│                       HERMES API GATEWAY                    ││   (Recepção rápida, validação de schema e enfileiramento)   │└──────────────┬──────────────────────────────┬───────────────┘               │                              │(Grava como 'pending' no banco)               │ (Enfileira Job no BullMQ)               ▼                              ▼┌──────────────────────────────┐ ┌────────────────────────────┐│      POSTGRESQL (Drizzle)    │ │        REDIS STORE         ││ (Serviços, Chaves, Templates)│ │ (Fila de Jobs e Pub/Sub)   │└──────────────────────────────┘ └─────────────┬──────────────┘                                               │                                               ▼                                 ┌────────────────────────────┐                                 │       HERMES WORKER        │                                 │  (Consome fila, descriptografa,│                                 │   compila MJML e envia SMTP)│                                 └─────────────┬──────────────┘                                               │                                               ▼ (TLS / SMTP)                                 ┌────────────────────────────┐                                 │    PROVEDOR SMTP / GMAIL   │                                 └────────────────────────────┘</code></pre><h2 id="ruanlopes1350-content-2-por-que-separamos-a-api-do-worker">2. Por que Separamos a API do Worker?</h2><p>A separação em processos Node.js independentes garante previsibilidade operacional:</p><h3 id="ruanlopes1350-content-api-gateway-serverts">API Gateway (<code>server.ts</code>)</h3><p>A API tem uma única missão: receber o payload, validar o formato dos dados, autenticar a API Key, registrar o e-mail no PostgreSQL como <code>pending</code> e postar o job na fila do Redis.</p><ul><li><strong>Tempo de resposta típico:</strong> <code>&#x3C; 25ms</code>.</li><li>A API retorna imediatamente <code>201 Created</code> contendo o ID do e-mail para rastreamento. O endpoint que chamou o Hermes segue seu fluxo sem esperar a entrega de rede.</li></ul><h3 id="ruanlopes1350-content-email-worker-workerts">Email Worker (<code>worker.ts</code>)</h3><p>O Worker opera em background consumindo a fila do BullMQ:</p><ol><li>Resgata a credencial de envio do tenant (senha SMTP pura ou token dinâmico via Google OAuth2/Gmail API).</li><li>Descriptografa a credencial em memória.</li><li>Compila o template <strong>MJML</strong> injetando as variáveis dinâmicas com <strong>Handlebars</strong>.</li><li>Dispara a mensagem via Nodemailer.</li><li>Em caso de sucesso ou falha definitiva, atualiza o status no PostgreSQL (<code>sent</code> ou <code>failed</code>) com stack de erros e timestamp.</li><li>Emite um evento via Redis Pub/Sub, que alimenta as telas do painel administrativo em tempo real através de Server-Sent Events (SSE).</li></ol><p>Se o provedor SMTP retornar erro temporário de rede, o BullMQ executa retentativas com backoff exponencial com jitter, sem impactar a capacidade da API de continuar recebendo novas requisições.</p><hr><h2 id="ruanlopes1350-content-3-decisões-de-criptografia-e-segurança">3. Decisões de Criptografia e Segurança</h2><h3 id="ruanlopes1350-content-31-api-keys-o-dilema-de-performance-vs-força-bruta-argon2id">3.1 API Keys: O Dilema de Performance vs. Força Bruta (Argon2id)</h3><p>Se salvarmos chaves de API com hash simples (como SHA-256), um vazamento de banco permite ataques de dicionário acelerados por GPU. Por outro lado, se usarmos um algoritmo moderno e pesado como <strong>Argon2id</strong> na chave inteira, como não há usuário informado na requisição, o servidor precisaria rodar o <code>argon2.verify()</code> contra todas as chaves do banco a cada requisição HTTP (<span class="math math-inline">O(N)</span>), o que inviabilizaria o servidor.</p><p>A solução adotada divide a chave em duas partes no formato <code>hm_prefix.secret</code>:</p><pre><code>hm_b5c92a10.e4d3c2b1a0f9e8d7c6b5a4938271605f...└─────┬───┘ └──────────────────────┬──────────────────────┘      │                            │ Segredo Aleatório (32 bytes em HEX - 64 caracteres)      └ Prefixo Público (8 caracteres HEX indexados no banco)</code></pre><ol><li><strong>Busca Indexada (<span class="math math-inline">O(1)</span>):</strong> O middleware extrai o prefixo público (<code>hm_b5c92a10</code>) e faz uma busca indexada no PostgreSQL (<code>WHERE prefix = '...' AND is_active = true</code>). Isso isola instantaneamente o registro exato.</li><li><strong>Validação Forte:</strong> Com a linha recuperada, o sistema aplica o <code>argon2.verify(key_hash, secret)</code> exclusivamente no segredo recebido.</li><li><strong>Resultado:</strong> Busca ultra rápida no banco associada a uma barreira resistente contra ataques paralelos em hardware dedicado.</li></ol><h3 id="ruanlopes1350-content-32-credenciais-em-repouso-cifragem-de-envelope-com-aes-256-gcm">3.2 Credenciais em Repouso: Cifragem de Envelope com AES-256-GCM</h3><p>Senhas de envio SMTP e tokens de refresh do Google OAuth2 nunca ficam em texto limpo no banco de dados. Eles são gravados no formato:</p><pre><code>&#x3C;iv_hex>:&#x3C;auth_tag_hex>:&#x3C;ciphertext_hex></code></pre><ul><li><strong>AES-256-GCM:</strong> Fornece tanto sigilo quanto integridade autenticada.</li><li><strong>IV Dinâmico:</strong> Um vetor de inicialização de 16 bytes aleatório é gerado a cada gravação, garantindo que a mesma senha resulte em dados cifrados completamente distintos a cada update.</li><li><strong>Auth Tag:</strong> Impede adulterações silenciosas no banco de dados; qualquer bit alterado faz a descriptografia falhar.</li><li><strong>Master Key:</strong> A chave mestra reside unicamente nas variáveis de ambiente do servidor e nunca transita pela rede.</li></ul><hr><h2 id="ruanlopes1350-content-4-rotação-automática-de-chaves-webhook-first">4. Rotação Automática de Chaves ("Webhook-First")</h2><p>Trocar chaves de API manualmente em ambientes de produção costuma gerar indisponibilidade se o cliente não for atualizado no mesmo instante. O Hermes possui um mecanismo de rotação automática com tolerância a falhas:</p><ol><li>Um cronjob diário via BullMQ (<code>system.ts</code>) busca credenciais ativas com data de expiração próxima do limite configurado (padrão: 3 dias).</li><li>O sistema gera a nova chave candidata e envia uma requisição <code>POST</code> HTTPS para o endpoint de webhook configurado no serviço do cliente.</li><li>A requisição leva o cabeçalho <code>X-Hermes-Signature</code>, gerado via <strong>HMAC SHA-256</strong> utilizando o segredo privado do serviço:<pre><code class="hljs language-typescript"><span class="hljs-keyword">const</span> signature = crypto  .<span class="hljs-title function_">createHmac</span>(<span class="hljs-string">'sha256'</span>, webhookSecret)  .<span class="hljs-title function_">update</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(payload))  .<span class="hljs-title function_">digest</span>(<span class="hljs-string">'hex'</span>);</code></pre></li><li><strong>Garantia de Entrega (Webhook-First):</strong> Se o webhook do cliente falhar (timeout ou erro 5xx), <strong>o banco de dados do Hermes não é alterado</strong>. A chave antiga continua funcionando normalmente e o BullMQ agenda uma nova tentativa.</li><li><strong>Atualização Efetiva:</strong> Apenas quando a aplicação cliente confirma com <code>200 OK</code> o recebimento da nova chave, o Hermes comita o novo hash e expiração no PostgreSQL.</li></ol><hr><h2 id="ruanlopes1350-content-5-integração-com-o-sdk-hermes-client">5. Integração com o SDK (<code>hermes-client</code>)</h2><p>Para simplificar o consumo, publicamos o pacote <code>@ruanlopes1350/hermes-client</code> no NPM. Ele conta com interface fluente e middlewares para recepção do webhook de rotação:</p><pre><code class="hljs language-typescript"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">HermesClient</span>, <span class="hljs-title class_">MemoryAdapter</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@ruanlopes1350/hermes-client'</span>;<span class="hljs-keyword">const</span> hermes = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HermesClient</span>({  <span class="hljs-attr">baseUrl</span>: <span class="hljs-string">'https://api-hermes.suaempresa.com'</span>,  <span class="hljs-attr">storageAdapter</span>: <span class="hljs-keyword">new</span> <span class="hljs-title class_">MemoryAdapter</span>(process.<span class="hljs-property">env</span>.<span class="hljs-property">HERMES_API_KEY</span>!),});<span class="hljs-comment">// Envio de e-mail usando templates MJML gerenciados no painel</span><span class="hljs-keyword">await</span> hermes.<span class="hljs-title function_">email</span>()  .<span class="hljs-title function_">to</span>(<span class="hljs-string">'cliente@email.com'</span>)  .<span class="hljs-title function_">subject</span>(<span class="hljs-string">'Confirmação de Acesso'</span>)  .<span class="hljs-title function_">useTemplate</span>(<span class="hljs-string">'cltmpl_cadastro_usuario'</span>, {     <span class="hljs-attr">nome</span>: <span class="hljs-string">'Maria'</span>,     <span class="hljs-attr">codigo</span>: <span class="hljs-string">'482910'</span>   })  .<span class="hljs-title function_">send</span>();</code></pre><hr><h2 id="ruanlopes1350-content-6-tradeoffs-e-limitações-conhecidas">6. Tradeoffs e Limitações Conhecidas</h2><p>Uma análise técnica sincera exige pontuar as desvantagens e os limites da arquitetura:</p><ol><li><strong>Custo de Manutenção de Infraestrutura:</strong><br>O Hermes exige manter Node.js, PostgreSQL, Redis e containers de workers. Para projetos pequenos que disparam menos de 100 e-mails por mês, serviços gerenciados (como Resend ou Postmark) trazem menos sobrecarga operacional. O Hermes faz sentido quando há necessidade de soberania de dados, multi-tenancy interno ou conexão com infraestruturas SMTP legadas/próprias.</li><li><strong>Custo de CPU do Argon2id sob Carga Alta:</strong><br>Mesmo com o prefixo reduzindo a busca a <span class="math math-inline">O(1)</span>, o cálculo do Argon2id é intencionalmente intensivo em memória e processamento. Picos extremos de requisições (>500 req/s simultâneas diretamente na API) elevam consideravelmente o uso de CPU. Para cargas muito altas, é recomendável manter uma camada de rate limiting ou proxy reverso na frente.</li><li><strong>Escalonador Atrelado ao Docker Socket:</strong><br>O módulo de auto-scaling de workers incluído (<code>scaler.ts</code>) inspeciona o volume de jobs no Redis e ajusta o número de réplicas via CLI do Docker Compose local. Esse formato atende bem VPSs únicas, mas não substitui orquestradores distribuídos (como HPA em Kubernetes).</li><li><strong>Reputação de IP e Entregabilidade:</strong><br>O Hermes resolve fila, templates, segurança e auditoria, mas não gerencia reputação de IP nem configurações de DNS (SPF, DKIM, DMARC), que continuam sob responsabilidade da configuração do servidor SMTP apontado.</li></ol><hr><h2 id="ruanlopes1350-content-7-código-aberto-e-contribuições">7. Código Aberto e Contribuições</h2><p>O projeto foi estruturado com foco em boas práticas de TypeScript, Drizzle ORM e isolamento de processos:</p><ul><li><strong>API &#x26; Workers:</strong> <a href="https://github.com/RuanLopes1350/hermes-api">hermes-api no GitHub</a></li><li><strong>Frontend Next.js:</strong> <a href="https://github.com/RuanLopes1350/hermes-front">hermes-front no GitHub</a></li><li><strong>SDK Node/TypeScript:</strong> <a href="https://github.com/RuanLopes1350/hermes-client">hermes-client no GitHub</a> e <a href="https://www.npmjs.com/package/@ruanlopes1350/hermes-client" rel="nofollow">no NPM</a></li></ul><p>Feedbacks sobre a arquitetura e sugestões de melhoria são sempre bem-vindos!</p></div>]]></content:encoded>
            <author>RuanLopes1350</author>
        </item>
        <item>
            <title><![CDATA[Aprendendo a revisar PR como júnior]]></title>
            <link>https://www.tabnews.com.br/lcssathler/aprendendo-a-revisar-pr-como-junior</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/lcssathler/aprendendo-a-revisar-pr-como-junior</guid>
            <pubDate>Fri, 18 Sep 2026 19:00:45 GMT</pubDate>
            <description><![CDATA[Sou desenvolvedor Java full stack júnior e quero contar um pouco das práticas que estou utilizando para revisar PRs automáticos em um projeto pessoal meu. Eu utilizo o Dependabot para che...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Sou desenvolvedor Java full stack júnior e quero contar um pouco das práticas que estou utilizando para revisar PRs automáticos em um projeto pessoal meu. Eu utilizo o <strong>Dependabot</strong> para checar semanalmente atualizações das bibliotecas e pacotes utilizados no meu projeto. A cada semana ele abre cerca de 4 a 7 PRs de forma automática, e decidi utilizar isso a meu favor para aprender um pouco mais sobre como revisar PRs. Vou usar como exemplo um PR de atualização do pacote <code>@eslint/js</code> da versão 9.39.5 para 10.0.1 que gerava um conflito não capturado pelas verificações do meu CI.</p><h1 id="lcssathler-content-checklist">Checklist</h1><p>O checklist que sigo é esse:</p><ul><li>Identificar primeiramente a finalidade. Se é correção, feature nova, documentação ou atualização de versão.</li><li>Ver quais arquivos foram alterados.</li><li>Confirmar se as mudanças afetam o projeto atual (de longe a parte mais chata).</li><li>Conferir o que os testes cobrem e, se novos testes foram adicionados, confirmar se eles verificam o comportamento afetado na aplicação.</li></ul><h1 id="lcssathler-content-identificando-a-finalidade-do-pr">Identificando a finalidade do PR</h1><p>Claro, o título <code>chore(deps-dev): bump @eslint/js from 9.39.5 to 10.0.1</code> já era bastante intuitivo. A descrição do PR também confirmava essa atualização, todos os checks estavam verdes e apenas os arquivos <code>package.json</code> e <code>package-lock.json</code> tinham sido alterados. Era só fazer o merge já que tudo estava aparentemente OK, mas o questionamento que resolvi fazer foi:</p><ul><li>É uma atualização da versão 9 para a versão 10. Será que os testes cobrem o que pode dar errado nessa mudança?</li></ul><p>Foi quando eu decidi olhar as notas de release. Na passagem para a versão 10.0.0, havia uma lista com 22 BREAKING CHANGES! Isso já era motivo para olhar com mais atenção.</p><h1 id="lcssathler-content-alterações-do-pr-e-início-do-problema">Alterações do PR e início do problema</h1><p>Aqui o primeiro passo é não julgar o impacto do commit pela quantidade de arquivos alterados. Mesmo alterando somente os arquivos de dependências, o importante é saber o que essa nova versão introduziu e como ela poderia afetar o seu projeto.</p><p>Antes mesmo de abrir os commits citados nas releases, acabei encontrando um possível problema nos arquivos alterados. Tanto o <code>package.json</code> quanto o <code>package-lock.json</code> trocavam a faixa de versões permitidas do <code>@eslint/js</code> de <code>^9.39.3</code> para <code>^10.0.1</code>, porém o ESLint por si só não acompanhava a atualização. Ficou assim:</p><h3 id="lcssathler-content-packagejson">package.json</h3><p>Antes:</p><pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>  <span class="hljs-attr">"devDependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>    <span class="hljs-attr">"@eslint/js"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^9.39.3"</span><span class="hljs-punctuation">,</span>    <span class="hljs-attr">"eslint"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^9.39.3"</span><span class="hljs-punctuation">,</span>    <span class="hljs-attr">"eslint-plugin-react"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^7.37.5"</span>  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span></code></pre><p>Depois:</p><pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>  <span class="hljs-attr">"devDependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>    <span class="hljs-attr">"@eslint/js"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^10.0.1"</span><span class="hljs-punctuation">,</span>    <span class="hljs-attr">"eslint"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^9.39.3"</span><span class="hljs-punctuation">,</span>    <span class="hljs-attr">"eslint-plugin-react"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^7.37.5"</span>  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span></code></pre><h3 id="lcssathler-content-package-lockjson">package-lock.json</h3><p>Na entrada de <code>@eslint/js</code>, a versão exata mudou de <code>9.39.5</code> para <code>10.0.1</code>. O ESLint continuou registrado como <code>9.39.5</code>. Além disso, a entrada do pacote atualizado passou a incluir este requisito:</p><pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>  <span class="hljs-attr">"peerDependencies"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>    <span class="hljs-attr">"eslint"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"^10.0.0"</span>  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>  <span class="hljs-attr">"peerDependenciesMeta"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>    <span class="hljs-attr">"eslint"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>      <span class="hljs-attr">"optional"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>    <span class="hljs-punctuation">}</span>  <span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span></code></pre><p>Compare o antes e depois. Os dois arquivos atualizavam o <code>@eslint/js</code> e nenhum dos dois atualizava o ESLint. Mas isso, sozinho, não prova um erro: pacotes com números de versão diferentes podem ser compatíveis.</p><p>O problema estava no <code>peerDependencies</code>: o próprio <code>@eslint/js</code> declarava que precisava do ESLint na faixa <code>^10.0.0</code>. Ou seja, <strong>a partir de 10.0.0 e abaixo de 11.0.0</strong>, e não qualquer versão superior a 10.</p><p>Já o meu projeto pedia <code>^9.39.3</code>, que não permite chegar à versão 10. O <code>package.json</code> dizia quais versões eram permitidas, e o lockfile registrava a versão exata escolhida: 9.39.5.</p><p>Para não confundir os dois pacotes: o <code>eslint</code> executa a análise do código, enquanto o <code>@eslint/js</code> fornece configurações de regras, como a configuração recomendada que eu utilizo.</p><p>Para ter certeza de que era um erro, fui reproduzi-lo localmente. Usei uma worktree com a branch desse PR para investigar sem mexer na minha pasta principal. Até então, as verificações do CI tinham passado. Mas, ao simular a resolução dos pacotes com este comando, o erro apareceu:</p><pre><code class="hljs language-bash">npm install --package-lock-only --ignore-scripts --dry-run --no-audit --no-fund</code></pre><p>O comando não instala os pacotes nem grava as alterações propostas no lockfile. Pode consultar o registro do npm e gerar logs ou cache, mas permite testar a resolução sem aplicar a atualização.</p><p>Agora sim apareceu o <code>ERESOLVE</code>, apontando a incompatibilidade. Na comparação local, essa verificação passou antes da mudança e falhou com os arquivos do PR.</p><p>Provavelmente você iria se perguntar: <em>“Por que um pacote tão utilizado pela comunidade JS iria cometer um erro desse? Ninguém revisou essa joça de comparar a versão dos dois pacotes antes de colocar dentro da release não?”</em></p><p>Foi aí que precisei separar as coisas. O pacote tinha declarado a compatibilidade dele. A proposta de atualização do meu projeto é que não atendia ao requisito.</p><p>E aquele <code>optional: true</code>? Ele declara o ESLint como opcional (só voltar lá no exemplo do código que você vai ver). Para ter o <code>@eslint/js</code> instalado, não é obrigatório ter o ESLint também. <strong>Mas, se ele estiver instalado, a versão precisa ser compatível.</strong></p><p>Você não é obrigado a ter um controle para jogar um jogo que também aceita teclado, mas precisa ter um controle compatível caso opte por utilizar um.</p><p>Logo, o erro já estava claro.</p><blockquote><p>O meu projeto utiliza tanto o <code>@eslint/js</code> quanto o <code>eslint</code>. A versão 10.0.1 do <code>@eslint/js</code> exige ESLint na faixa <code>^10.0.0</code> quando ele está instalado, mas o meu projeto continuava na série 9.</p></blockquote><h2 id="lcssathler-content-mas-por-que-os-testes-não-capturaram-esse-erro">Mas por que os testes não capturaram esse erro?</h2><p>O CI usava <code>npm ci</code>, que instala as versões registradas no lockfile. Naquela execução, a instalação, o lint, os testes e o build passaram. Já a verificação adicional de resolução encontrou o conflito.</p><p>Isso não quer dizer que o <code>npm ci</code> nunca encontre incompatibilidades, nem que o <code>npm install</code> saia atualizando tudo. Foi o comportamento observado nesse caso. Quando as versões do lockfile atendem ao <code>package.json</code>, o <code>npm install</code> normalmente as reutiliza; quando não atendem, ele precisa resolver novas versões dentro das faixas permitidas.</p><p>No meu projeto, ele não poderia simplesmente escolher ESLint 10 para resolver o problema, porque o <code>^9.39.3</code> ainda limitava a escolha à série 9. Foi justamente esse conflito que a simulação apontou.</p><p>Decidi então adicionar a verificação ao workflow:</p><pre><code class="hljs language-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Validate</span> <span class="hljs-string">dependency</span> <span class="hljs-string">resolution</span>  <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span> <span class="hljs-string">--package-lock-only</span> <span class="hljs-string">--ignore-scripts</span> <span class="hljs-string">--dry-run</span> <span class="hljs-string">--no-audit</span> <span class="hljs-string">--no-fund</span></code></pre><p>Rodei o CI novamente no PR e dessa vez a etapa falhou com o mesmo erro. O problema que antes passava despercebido agora era capturado. Isso não transforma o comando numa garantia contra toda incompatibilidade, mas ele passou a verificar um cenário que estava faltando no meu CI.</p><h1 id="lcssathler-content-de-quem-foi-a-culpa">De quem foi a culpa?</h1><p>Pode-se dizer que o erro estava na proposta do Dependabot: uma atualização incompleta. Ele manteve o ESLint na série 9 e criou uma combinação incompatível.</p><p>Por outro lado, isso pode ser uma limitação da atualização individual ou da configuração utilizada. Só esse resultado não prova um bug no Dependabot. O que ficou claro é que o PR automático também precisava de revisão.</p><h1 id="lcssathler-content-a-solução">A solução</h1><p>Eu tinha duas opções para seguir: manter os dois pacotes na série 9 e fechar esse PR, ou tentar migrar também o ESLint e conferir a compatibilidade dos plugins.</p><p>Optei por tentar atualizar o ESLint para a versão 10, mas aí descobri que o <code>eslint-plugin-react</code> 7.37.5 só declarava suporte até a série 9 do ESLint 🤡. Essa já era a versão marcada como <code>latest</code> no npm. Não adiantava simplesmente mandar atualizar tudo.</p><p>Acabei mantendo os dois pacotes na série 9 mesmo. Para seguir com a migração, teria que esperar o suporte do plugin ou avaliar uma alternativa, o que já aumentaria o escopo dessa atualização.</p><hr><p>Sei que para alguns isso vai ser algo básico, mas acredito que hoje em dia até o básico não é falado por ser superestimado. Infelizmente nunca fui uma pessoa que aprende bem com leitura de artigos e tutoriais dos outros, por isso decidi documentar alguns problemas que encaro no dia a dia para poder fixar melhor.</p></div>]]></content:encoded>
            <author>lcssathler</author>
        </item>
        <item>
            <title><![CDATA[Claude Code agora vai ler o AGENTS.md (finalmente!)]]></title>
            <link>https://www.tabnews.com.br/AndreiAlves/claude-code-agora-vai-ler-o-agents-md-finalmente</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/AndreiAlves/claude-code-agora-vai-ler-o-agents-md-finalmente</guid>
            <pubDate>Fri, 18 Sep 2026 18:50:27 GMT</pubDate>
            <description><![CDATA[O Thariq, membro da equipe, postou no X: We&#39;re adding support for AGENTS.md to Claude Code. Starting today in version 2.1.277, if there is no CLAUDE.md in a folder, Claude will check...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>O Thariq, membro da equipe, postou no X:</p><blockquote class=""><p lang="en" dir="ltr">We're adding support for AGENTS.md to Claude Code. <br><br>Starting today in version 2.1.277, if there is no CLAUDE.md in a folder, Claude will check for and use AGENTS.md.<br><br>You can toggle this behavior in /config.</p>— Thariq (@trq212) <a href="https://x.com/trq212/status/2101009392611278961?ref_src=twsrc%5Etfw" rel="nofollow">September 18, 2026</a></blockquote> <p>O suporte vai ser oferecido por meio da nova funcionalidade de <code>mods</code>, que vai permitir customizar o Claude Code. O suporte ao AGENTS.md será um <code>mod</code> nativo.</p></div>]]></content:encoded>
            <author>AndreiAlves</author>
        </item>
        <item>
            <title><![CDATA[O caminho para uma IA superinteligente]]></title>
            <link>https://www.tabnews.com.br/oprogramador/o-caminho-para-uma-ia-superinteligente</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/oprogramador/o-caminho-para-uma-ia-superinteligente</guid>
            <pubDate>Fri, 18 Sep 2026 16:58:21 GMT</pubDate>
            <description><![CDATA[Talvez você já tenha ouvido falar em “scaling laws”: a ideia de que modelos maiores (com mais parâmetros) tendem a ser mais inteligentes. Ou seja, quanto maior o “cérebro” (rede neural) d...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Talvez você já tenha ouvido falar em “scaling laws”: a ideia de que modelos maiores (com mais parâmetros) tendem a ser mais inteligentes. Ou seja, quanto maior o “cérebro” (rede neural) da IA, melhor.</p><p>Mas isso é mesmo verdade ou já estamos num platô? O custo computacional de modelos de IA maiores justifica o ganho de inteligência obtido, ou estamos num cenário de “diminishing returns”? Fable e Astra são modelos maiores (e mais caros) que seus antecessores… mas quão mais inteligentes eles são?</p><p>Para entender, vamos começar com um exemplo simples.</p><p>Por mais “overkill” que pareça, podemos treinar uma rede neural para aprender a somar dois números. Para isso, precisamos de um conjunto de dados com exemplos do que é uma soma correta:</p><p>2 + 2 = 4</p><p>14 + 10 = 24</p><p>234 + 11 = 245</p><p>47282 + 1233 = 48515</p><p>…e assim por diante. Idealmente, essa lista de exemplos deve ser bem grande.</p><p>Agora, uma rede neural que aprende a somar dois números olhando pra essa lista poderia aprender a fazer isso de duas formas:</p><p>• Aprender o real conceito de soma;</p><p>• Criar internamente uma “tabela” que mapeia todos os valores de entrada que ela viu na lista pro resultado que ela também viu na lista. Seria o equivalente a “decorar” a lista.</p><p>Se o modelo aprender a decorar a lista, quando pedirmos para ele somar dois números que não estavam na lista usada no treinamento, ele provavelmente vai somar errado. Aqui, diz-se que aconteceu um “overfitting”: o modelo ficou muito bom em aprender os dados que ele viu no treinamento, mas não consegue “generalizar” o conhecimento para fora daqueles dados.</p><p>Agora, qual o tamanho ideal de uma rede neural (quantos parâmetros) para ela realmente aprender a somar dois números, sem decorar? Quão grande precisa ser o “cérebro” dessa IA?</p><p>Aqui, observa-se um comportamento interessante: a resposta não é “quanto maior, melhor”. Existe um tamanho ideal para a rede. Depois desse tamanho ideal, se apenas adicionarmos mais parâmetros, o desempenho para generalização fica pior!</p><p>E o motivo intuitivo para isso é mais ou menos assim: quanto maior for a rede, mais “espaço dentro do cérebro dela” ela tem para aprender a abordagem que nós não queremos, que é decorar a lista do treinamento.</p><p>Em outras palavras, forçando a rede a ser menor, menos chance ela tem de aprender a abordagem “burra” (decorar) e mais ela é forçada a achar a solução inteligente e genérica para o problema.</p><p>A teoria é clara: o modelo mais simples é o melhor generalizador (grave essa frase).</p><p>É por esse motivo que, se antes de 2019 você perguntasse para um pesquisador de IA “Você acha que treinar uma rede neural gigante, com trilhões de parâmetros, usando todo o texto disponível na internet, é uma boa ideia para termos uma IA superinteligente?”, provavelmente a resposta seria: “Não! Esse modelo vai com certeza aprender os dados de treinamento, mas não será inteligente. Será apenas um papagaio estatístico, vítima de um inevitável overfitting”.</p><p>Porém, em 2019, um novo artigo <a href="https://arxiv.org/abs/1812.11118" rel="nofollow">https://arxiv.org/abs/1812.11118</a> demonstrou algo interessante: nos experimentos, os autores seguiram aumentando o tamanho da rede neural e, inicialmente, a rede ficou, sim, pior para generalizar com dados não vistos no treinamento. Contudo, ao seguir aumentando o número de parâmetros, eles observaram que a rede voltou a ter resultados melhores… até o ponto de superar as capacidades de generalização da rede mais simples!</p><p>Esse resultado foi surpreendente e abriu uma nova avenida para melhorar a IA: bastaria fazer modelos maiores!</p><p>Entretanto, esse resultado também contrariava tudo que se sabia de estatística e redes neurais. A verdade teórica era: “o modelo mais simples é o melhor generalizador”. Não se entendia o mecanismo que fazia com que isso não fosse verdade. O que estava acontecendo? Por que modelos maiores estão generalizando melhor?</p><p>Por volta da mesma época surgiu outro artigo <a href="https://arxiv.org/abs/1803.03635" rel="nofollow">https://arxiv.org/abs/1803.03635</a> que observou que, em grandes redes neurais, a vasta maioria dos parâmetros da rede são, na verdade, inúteis… simplesmente não são utilizados! O artigo mostrou que era possível encontrar, dentro das redes estudadas, sub-redes muito menores que, quando treinadas com os valores iniciais certos, atingiam um desempenho parecido com o da rede maior.</p><p>Para fazer a conexão entre esses dois artigos e entender o que está acontecendo, é preciso entender um pouco de como essas redes são treinadas.</p><p>Uma rede começa com valores aleatórios nos seus parâmetros e tenta-se gradualmente, ao longo do treinamento, ir mudando esses valores para fazer a rede gerar melhores resultados para o conjunto de dados de treinamento. É a técnica chamada de “gradiente descendente” (e é muito mais fácil entender isso com imagens).</p><p>Mas o importante é notar o seguinte: na técnica de gradiente descendente, os valores iniciais (aleatórios) dos parâmetros importam! Alguns conjuntos iniciais de valores podem fazer o treinamento conseguir chegar num bom resultado. Já outros podem fazer a rede ficar presa em um “ótimo local”, sem nunca poder testar possibilidades melhores.</p><p>Agora a sacada: o que se está fazendo ao treinar uma grande rede neural é, na verdade, treinar várias redes menores em paralelo. A hipótese é que redes maiores ofereçam mais chances de encontrar uma dessas sub-redes com uma inicialização muito boa (que generalizam melhor). Esse é o link entre os dois artigos anteriores.</p><p>Então, o que se acreditava antes do artigo de 2019 continua sendo verdade: “o modelo mais simples é o melhor generalizador”. Redes maiores parecem performar melhor, mas na verdade é uma otimização de treinamento… no final do treinamento, a maioria dos parâmetros será inútil, mas é mais provável que uma sub-rede eficiente tenha surgido dentro dessa rede maior.</p><p>Então, fica a pergunta: vamos conseguir atingir inteligência de nível humano (AGI) ou além (ASI) apenas aumentando o tamanho de LLMs e melhorando nossas técnicas de treinamento?</p><p>Não sou especialista da área, apenas curioso. E esse texto foi inteiramente baseado neste vídeo <a href="https://youtu.be/UKcWu1l_UNw?is=QDbh9SaRy-HA90bf" rel="nofollow">https://youtu.be/UKcWu1l_UNw?is=QDbh9SaRy-HA90bf</a> que, se você leu até aqui, recomendo fortemente assistir.</p><p>O autor do vídeo acredita que, apenas aumentando o tamanho das LLMs, não parece ser possível chegar à AGI. E o motivo é porque o ganho em inteligência obtido apenas tornando os modelos atuais maiores é modesto, e o aumento de computação necessária é proibitivamente custoso. Contudo, o autor também fala que acredita que LLMs são, sim, capazes de produzir inteligência de nível humano. Mesmo que a capacidade de escalar o tamanho desses modelos atinja um platô, na opinião dele, não existem motivos para acreditar que melhores algoritmos de treinamento, ou novas arquiteturas de rede neural, não sejam capazes de atingir inteligência humana apenas prevendo a próxima palavra (token) quando treinados com uma quantidade infinita de texto. Em teoria e no limite, isso parece um caminho possível para a AGI.</p><p>Agora, se você quiser um papo bem mais inicial do que esse, para ser introduzido no mundo de redes neurais, sugiro assistir ao meu vídeo: <a href="https://youtu.be/Dlx_VuyXrBg?is=KwUCFy0NcnbTbfy1" rel="nofollow">https://youtu.be/Dlx_VuyXrBg?is=KwUCFy0NcnbTbfy1</a></p><p>Obrigado por ler até aqui! Deixe suas dúvidas e contribuições nos comentários.</p></div>]]></content:encoded>
            <author>oprogramador</author>
        </item>
    </channel>
</rss>