<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Amanda O&apos;Brien</title><description>Writing about distributed systems, AI-driven applications, and the craft of building things.</description><link>https://cyberrhizome.ca/</link><language>en-ca</language><item><title>Closing the Loop: What We Actually Shipped from the Roadmap</title><link>https://cyberrhizome.ca/blog/10-closing-the-loop-what-we-shipped/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/10-closing-the-loop-what-we-shipped/</guid><description>Post #05 ended with a list of half-built features and a promise to ship them. This is the delivery receipt: compliance export, idempotency hardening, and the systems work that made them production-ready.</description><pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Triple-Defense Idempotency in a Crash-Prone Event Stream</title><link>https://cyberrhizome.ca/blog/09-triple-defense-idempotency/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/09-triple-defense-idempotency/</guid><description>At-least-once delivery guarantees every message is processed — not exactly once. This post traces the three idempotency layers in the Sentinel-L7 Axiom pipeline and the specific failure modes each one defends against.</description><pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Four Signals for Quality Scoring in LLM Pipelines</title><link>https://cyberrhizome.ca/blog/08-quality-scoring-and-domain-rag/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/08-quality-scoring-and-domain-rag/</guid><description>An LLM pipeline that produces no exceptions is not necessarily a pipeline that works. This post covers four signals for scoring the quality of compliance audit narratives produced by Sentinel-L7.</description><pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Closing the Gap: Persistent Tokens, Containers, and the Road to k3s</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-06-03-closing-the-production-gap/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-06-03-closing-the-production-gap/</guid><description>The previous post listed what EventHorizon needed before it could run in production. This one closes the list — persistent resume tokens, a multi-stage Dockerfile, a dependency-aware health check, and k3s manifests. Along the way, a silent data-loss bug that the test suite missed entirely.</description><pubDate>Fri, 29 May 2026 00:00:00 GMT</pubDate></item><item><title>Graduated Backpressure: Moving Beyond Binary Pauses</title><link>https://cyberrhizome.ca/blog/07-graduated-backpressure/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/07-graduated-backpressure/</guid><description>The first version of Sentinel-L7&apos;s producer guard was binary: above the threshold it stopped, below it ran full speed. This post covers why that fails under real load and what graduated backpressure looks like in practice.</description><pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate></item><item><title>Self-Healing Worker Pools: Embedding XAUTOCLAIM in Every Worker</title><link>https://cyberrhizome.ca/blog/06-self-healing-worker-pools-xautoclaim/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/06-self-healing-worker-pools-xautoclaim/</guid><description>Sentinel-L7 runs two long-lived worker processes on Redis Streams. When a worker crashes mid-message, that message stays stuck in the PEL indefinitely. This post covers why the dedicated reclaimer daemon was replaced with embedded XAUTOCLAIM recovery in every worker.</description><pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate></item><item><title>The Catalyst of the Flawed First Move; or, The Freedom of the Sacrificial Draft</title><link>https://cyberrhizome.ca/blog/catalyst-or-sacrificial-draft/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/catalyst-or-sacrificial-draft/</guid><description>Why providing a deliberately flawed starting point is the fastest way to kill ambiguity and surface requirements.</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate></item><item><title>What Comes Next: Multi-Server Deployments, Persistent Resume Tokens, and the Patterns That Transfer</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-05-05-what-comes-next/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-05-05-what-comes-next/</guid><description>EventHorizon is feature-complete as a learning vehicle. The interesting question is which of its patterns survive the move to a real production environment, and which need to be reworked entirely.</description><pubDate>Tue, 05 May 2026 00:00:00 GMT</pubDate></item><item><title>One AI, One Context File</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-05-02-one-ai-one-context-file/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-05-02-one-ai-one-context-file/</guid><description>I started this project with two AI assistants and a sync problem. I&apos;m finishing it with one assistant and three documents that act as the project&apos;s durable memory. Here&apos;s what changed.</description><pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate></item><item><title>What Comes Next: Multi-Tenancy, Compliance Exports, and Closing the Loop to EventHorizon</title><link>https://cyberrhizome.ca/blog/05-sentinel-l7-what-comes-next-multi-tenancy-exports-and-closing-the-loop/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/05-sentinel-l7-what-comes-next-multi-tenancy-exports-and-closing-the-loop/</guid><description>A speculative look at what Sentinel L7 is pointing toward — the features that are half-built, the decisions still open, and what building this thing has actually taught me.</description><pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Extracting the App Factory to Make Tests Stop Lying</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-29-app-factory-tests-stop-lying/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-29-app-factory-tests-stop-lying/</guid><description>Importing a server module should not bind a port. It should not connect to MongoDB. It should not start a metrics interval. Once your tests can&apos;t import your server without ten unrelated things happening, you&apos;ve already broken your own contract.</description><pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Zod Won. Here&apos;s What It Cost.</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-28-zod-won-heres-what-it-cost/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-28-zod-won-heres-what-it-cost/</guid><description>I evaluated Valibot. I picked Zod. I lost half a day to a UUID validator that was technically more correct than the previous version. Here is what I&apos;d tell my past self about validation libraries.</description><pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Tests, Rough Edges, and What&apos;s Still Ahead for RhizoBook</title><link>https://cyberrhizome.ca/blog/06-rhizobook-testing-polish-next-steps/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/06-rhizobook-testing-polish-next-steps/</guid><description>The backend Jest strategy, frontend Vitest setup, two bugs found while writing tests, and an honest account of what the app still can&apos;t do.</description><pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Resume Tokens and the Lie of &apos;Just Reconnect&apos;</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-10-resume-tokens-and-just-reconnect/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-10-resume-tokens-and-just-reconnect/</guid><description>The dashboard said everything was fine. Stats updated. Connection dot was green. Nineteen thousand events had moved through the pipeline and the live feed was a frozen screenshot.</description><pubDate>Fri, 10 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Testing What You Can, Naming What You Can&apos;t</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-05-testing-what-you-can/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-05-testing-what-you-can/</guid><description>There are parts of this system I have no automated tests for, and that is a deliberate design decision. The trick is being honest about which parts those are and why.</description><pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Backpressure Is Just a Number You Have To Pick</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-03-backpressure-is-just-a-number/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-03-backpressure-is-just-a-number/</guid><description>AMQP prefetch is one integer in one config file. It is also the difference between competing consumers and one worker eating the entire queue while the others sit idle.</description><pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Draining 657 Messages and Running Out of AI on the Way Down</title><link>https://cyberrhizome.ca/blog/04-sentinel-l7-draining-657-messages-and-running-out-of-ai-on-the-way-down/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/04-sentinel-l7-draining-657-messages-and-running-out-of-ai-on-the-way-down/</guid><description>Integrating a Python anomaly sidecar, hitting Gemini quota limits within minutes, and why a pluggable driver abstraction is not over-engineering.</description><pubDate>Thu, 02 Apr 2026 00:00:00 GMT</pubDate></item><item><title>At-Least-Once Is a Lie Without an Idempotent Receiver</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-02-at-least-once-idempotent-receiver/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-02-at-least-once-idempotent-receiver/</guid><description>How I almost shipped duplicate documents into MongoDB, and why I now think of unique indexes as load-bearing infrastructure rather than schema decoration.</description><pubDate>Thu, 02 Apr 2026 00:00:00 GMT</pubDate></item><item><title>RAG Is Easy. Getting It to Actually Retrieve Anything Is Hard.</title><link>https://cyberrhizome.ca/blog/03-sentinel-l7-rag-is-easy-getting-it-to-actually-retrieve-anything-is-hard/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/03-sentinel-l7-rag-is-easy-getting-it-to-actually-retrieve-anything-is-hard/</guid><description>On building a policy knowledge base for compliance analysis — and the silent failure that made it look like everything was working when nothing was.</description><pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate></item><item><title>Three Strikes and the Dead Letter</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-04-01-three-strikes-dead-letter/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-04-01-three-strikes-dead-letter/</guid><description>Why the worker republishes failed messages instead of nacking them with requeue=true, and how a single boolean flag is the difference between a healthy pipeline and a frozen one.</description><pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate></item><item><title>The Seven-Step Shutdown</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-03-31-seven-step-shutdown/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-03-31-seven-step-shutdown/</guid><description>There are exactly seven steps in EventHorizon&apos;s graceful shutdown, in exactly one order, and every reordering loses data in a specific way.</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate></item><item><title>Four Planes, One Direction: The Shape of EventHorizon</title><link>https://cyberrhizome.ca/blog/event-horizon-2026-03-30-four-planes-one-direction/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/event-horizon-2026-03-30-four-planes-one-direction/</guid><description>Why I named the four stages of the pipeline before I wrote any code, what naming bought me, and what backflow between them would have cost.</description><pubDate>Mon, 30 Mar 2026 00:00:00 GMT</pubDate></item><item><title>The Hard Part: Appointment Scheduling, Conflict Detection, and Role-Aware Queries</title><link>https://cyberrhizome.ca/blog/05-rhizobook-appointments-business-logic/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/05-rhizobook-appointments-business-logic/</guid><description>How conflict detection, a status state machine, and a single role-aware endpoint handle the core scheduling logic in RhizoBook.</description><pubDate>Sun, 29 Mar 2026 00:00:00 GMT</pubDate></item><item><title>What Strangers Shouldn&apos;t See: Securing the Public Provider API</title><link>https://cyberrhizome.ca/blog/04-rhizobook-securing-public-apis/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/04-rhizobook-securing-public-apis/</guid><description>How Prisma&apos;s include silently exposed sensitive fields on a public endpoint, and how explicit select fixed it at the query level.</description><pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate></item><item><title>Semantic Caching, or: Why I Spent Three Days Making a Cache Hit Work</title><link>https://cyberrhizome.ca/blog/02-sentinel-l7-semantic-caching-or-why-i-spent-three-days-making-a-cache-hit-work/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/02-sentinel-l7-semantic-caching-or-why-i-spent-three-days-making-a-cache-hit-work/</guid><description>Fingerprints, embeddings, and the exact-timestamp bug that gave me a 0% cache hit rate until I stopped being clever and started being dumb.</description><pubDate>Fri, 27 Feb 2026 00:00:00 GMT</pubDate></item><item><title>Wiring Up the Frontend: Next.js App Router, NextAuth, and a Rewrite Proxy That Saved Me</title><link>https://cyberrhizome.ca/blog/03-rhizobook-nextjs-auth-proxy/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/03-rhizobook-nextjs-auth-proxy/</guid><description>How I structured the Next.js frontend with two route groups, wired up NextAuth JWT sessions, and replaced a fragile build-time env var with a server-side rewrite proxy.</description><pubDate>Sun, 22 Feb 2026 00:00:00 GMT</pubDate></item><item><title>Building a Compliance Engine That Doesn&apos;t Block the Web Server</title><link>https://cyberrhizome.ca/blog/01-sentinel-l7-building-a-compliance-engine-that-doesnt-block-the-web-server/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/01-sentinel-l7-building-a-compliance-engine-that-doesnt-block-the-web-server/</guid><description>Why I designed Sentinel L7 around three separate processes, Redis Streams, and a rule-based fallback that fires more than I expected.</description><pubDate>Thu, 19 Feb 2026 00:00:00 GMT</pubDate></item><item><title>Building RhizoBook: Structuring a NestJS Backend from the Ground Up</title><link>https://cyberrhizome.ca/blog/02-rhizobook-backend-foundation/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/02-rhizobook-backend-foundation/</guid><description>Why I chose NestJS over plain Express, how I structured domains as modules, and the schema decisions that shaped the whole app.</description><pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate></item><item><title>Why I&apos;m Building an Appointment Scheduler</title><link>https://cyberrhizome.ca/blog/01-rhizobook-intro/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/01-rhizobook-intro/</guid><description>From identifying a recurring problem in healthcare SaaS to designing a solution I actually want to use.</description><pubDate>Fri, 30 Jan 2026 00:00:00 GMT</pubDate></item><item><title>The 72-Hour Christmas Miracle: My First Amigurumi</title><link>https://cyberrhizome.ca/blog/personal/mr-robot/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/personal/mr-robot/</guid><description>Crunch time in Santa&apos;s workshop</description><pubDate>Sun, 28 Dec 2025 00:00:00 GMT</pubDate></item><item><title>on building in public</title><link>https://cyberrhizome.ca/blog/on-building-in-public/</link><guid isPermaLink="true">https://cyberrhizome.ca/blog/on-building-in-public/</guid><description>Why I&apos;m starting to write more and consume less — and what this site is for.</description><pubDate>Mon, 15 Dec 2025 00:00:00 GMT</pubDate></item></channel></rss>