skip to content
A logo Linell asked a nice AI to create. Linell Bonnette

March & April 2026: DURP, MTG roaster, AI that sucks

Updates from March and April 2026

Work

March and April were the Durable Endpoint streaming era. With v4 out the door at the end of February, most of the next two months went into building out streaming for durable endpoints (affectionately referred to as DURP) on the TypeScript SDK — frame handling, SSE parsing, redirect following, the DX for consuming streams, and the docs to back all of it up. April closed out with a flurry of security fixes that I wrapped up just before sitting down to write this.

I also got to ship a personal project I’m happy with: the MTG Deck Analyzer, an Inngest-powered tool that ingests a Moxfield decklist and streams back card data, salt scores, a bracket classification, and a Claude-written roast. It’s at mtg.thelinell.com.

Durable Endpoint Streaming

The bulk of March was a pretty deep tour through SSE — parsing it, framing it, following redirects through it, and figuring out the right shape for the consumer-facing API. The hard part wasn’t any one of those individually; it was making a stream feel seamless to the user across retries and potentially many redirects, which is what pushed us into our own framing on top of SSE. A lot of small refactors that, looking back, do add up to a real feature. I also wrote the docs for it.

Security Fixes

The back half of April was about CVE-2026-42047 — a high-severity bug where the TypeScript SDK’s serve() handler, on unsupported HTTP methods (PATCH, OPTIONS, DELETE), fell through to a diagnostic response that included process.env. If your serve() endpoint was reachable via one of those methods, an unauthenticated request could pull whatever secrets happened to live in your environment. The bug shipped in 3.22.0, was patched in 3.54.0, and the 4.x line was thankfully never affected.

This was also the first real CVE process I’ve ever been a part of — the private fork, coordinated disclosure timing, writing the advisory copy, scoping the affected versions, figuring out how much to say in the changelog before the patch is widely available. A lot of new muscle to build, and I’m glad to have it in my repertoire!

Pull Requests

Durable Endpoint Streaming

Security

OTel & Observability

Other Work

Personal

I absolutely cannot seem to get myself back into the swing of exercising consistently. I’ve gone for a few great runs, maybe ridden my bike twice, and have gained ten-ish pounds. I’ve been prioritizing trying to be more present and thoughtful, and I’ve really enjoyed the San Diego sun.

I did make a trip back to Mississippi, but it was quick and not exactly a vacation. We checked in our on house there, visited with family, and ate good ole down home food. For better or for worse, my father decided that he won’t be continuing the radiation treatment his doctor suggested to help assuage the return of his tongue cancer. I can’t fault the decision but I’m not very fond of any version of facing my father’s mortailty.

On the upside, my partner and I booked a small weekend trip to Joshua Tree! We’ve been once before, but this time we know more about what we actually want to do. It’s one of the most beautiful places I’ve ever been and we’re both super excited to get the chance to unwind soon.

My AI Utopia Dystopia Projects

Most of my non-Inngest hours over the past several months have funneled into a project I’ve been calling ecosystem — a Bun-workspace monorepo that’s the culmination of a lot of thinking I’ve been doing about what I actually want from an AI assistant. It’s split into three pieces:

  • Cleo, an agentic assistant I talk to via Telegram. The interesting bit is that an agent turn can pause for up to ten minutes waiting on a human reply without holding a process open — Inngest’s step.waitForEvent does the suspending. Claude Haiku 4.5 drives a small Zod-typed tool registry on top of that.
  • Bronte, a local-first markdown PWA. Notes live in OPFS via Turso’s sync-wasm, which buys offline-first persistence at the cost of single-tab access — open it in a second tab and the first one breaks. Custom CodeMirror extensions handle heading folding, emoji autocomplete, wiki-links, and backlinks.
  • Citadel, the Cloudflare Worker backend — per-user database provisioning, a 5-minute schedule tick that fires user-defined check-ins, and semantic indexing, all driven by Inngest.

March and April were largely about hardening Cleo (photos from Telegram, MLB tools, better semantic search, scheduled check-ins, emoji reactions for perceived progress) and pushing Bronte forward with markdown polish, drag-and-drop, daily notes, and backlinks.

Honest assessment: Cleo is still pretty far from the assistant I actually want, and Bronte is stuck at “mediocre” instead of “great.” I have been able to use them as my daily driver for note taking and really don’t have a reason to switch other than yak shaving in the name of perfection.

In mid-April I started reimagining the backend half of all this as a pair of new projects — barad-dur, a Go server with per-user SQLite that would replace Turso, and palantir, a TanStack Start UI on top of it. Both got about three and a half days of attention before I paused them.

There’s a lot of work there needed to really bring to life the idea I’ve got noodling around. Before I go much further down this path, I’m going to try and write up my actual lessons learned.

Personal Projects

The big shipped one was the MTG Deck Analyzer, which is a Commander deck analysis tool built with Inngest, TanStack Start, and Cloudflare Workers, with Claude doing a roast at the end. It started as a “fish for a Go project, end up writing TypeScript” pivot after my friend Michael Roush pitched me the idea. You can try it at mtg.thelinell.com.

I built mario-kart-analyzer, a Mario Kart 8 Deluxe build optimizer that lets you assemble driver/body/tire/glider combinations and see real-time stats across the four terrain types, with a “pin one part” mechanic for ranking alternatives. TanStack Start on Cloudflare Workers, no AI involved. Underneath it, a Cheerio-based MarioWiki scraper (scripts/scrape.ts) generates the part registry as idempotent TypeScript, and builds are URL-encoded for sharing. Sometimes you just want to ship a thing. Check it out at mario-kart.thelinell.com.

Plus the usual pile of small tweaks to this site - better project tags, more accurate wording, smarter AI agent setup.