<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Doby Baxter Computing</title>
    <link>https://dobybaxter127.gitlab.io/</link>
    <description>Recent content on Doby Baxter Computing</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 13 Sep 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://dobybaxter127.gitlab.io/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>A Rule It Cannot Quietly Break: Building an Assistant That Checks Its Own Answers</title>
      <link>https://dobybaxter127.gitlab.io/articles/nexa-checking-its-own-answers/</link>
      <pubDate>Sun, 13 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/nexa-checking-its-own-answers/</guid>
      <description>&lt;p&gt;An answer should not have to be taken on trust. I&#39;m building &lt;a href=&#34;https://gitlab.com/dobybaxter127/nexa&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Nexa&lt;/a&gt; because I believe a coding assistant should be able to show you what it checked — which rule, from which source, and whether the code it just wrote actually obeys it — grounded in a corpus you can read rather than in a confident paragraph. The first version is now finished, and this is why it exists and how it&#39;s built. The deeper technical walkthrough lives in the &lt;a href=&#34;https://dev.to/dobybaxter127/ai-as-a-fluency-machine-what-software-engineering-taught-me-about-checking-a-models-answer-mgj&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;companion article on dev.to&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-012: Check Generated Code Against Its Cited Rules, Not Just Its Citations</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-012-check-generated-code-against-its-cited-rules-not-just-its-citations/</link>
      <pubDate>Sun, 13 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-012-check-generated-code-against-its-cited-rules-not-just-its-citations/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;A system that answers from a rule corpus can cite the rules it used, and citation is commonly treated as sufficient evidence that an answer is grounded. It is not. A citation proves a rule was retrieved and named. It proves nothing about whether the code beneath it obeys that rule.&lt;/p&gt;&#xA;&lt;p&gt;Nexa is a local, offline assistant that answers Odoo, TypeScript and JavaScript validation questions from a schema-validated rule corpus, running entirely on the user&#39;s own hardware. The first version is finished, and this record captures the verification decision that gives it its shape.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-010: Enforcing Data Invariants at the Persistence Boundary for Consistent Data Integrity</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-010-enforcing-data-invariants-at-the-persistence-boundary-for-consistent-data-integrity/</link>
      <pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-010-enforcing-data-invariants-at-the-persistence-boundary-for-consistent-data-integrity/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;A framework like Odoo exposes one stored model through many write paths: the form UI, ORM &lt;code&gt;create()&lt;/code&gt; and &lt;code&gt;write()&lt;/code&gt;, CSV and Excel import, and remote calls over XML-RPC, the API, and DCI. Each of these paths reaches the same database rows, but they do not share the same guards.&lt;/p&gt;&#xA;&lt;p&gt;A validation hook attached to the form (&lt;code&gt;@api.onchange&lt;/code&gt;) runs only while a user edits in the UI. Every other path (import, RPC, direct ORM) sails past it. This means a rule that feels enforced, because it works when you click through the form, can be silently absent everywhere else.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-011: Fitness for Purpose: Essential Properties for System Evaluation and User Outcomes</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-011-fitness-for-purpose-essential-properties-for-system-evaluation-and-user-outcomes/</link>
      <pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-011-fitness-for-purpose-essential-properties-for-system-evaluation-and-user-outcomes/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;The earlier decisions in this series each answer a narrow question: where a validation belongs, which layer owns an invariant, what a component is allowed to assume about the data reaching it. Each one is a local judgment about correctness at a boundary.&lt;/p&gt;&#xA;&lt;p&gt;Sitting above them is a question those decisions do not answer on their own. A system can satisfy every local rule, run every component as designed, and still fail the person it exists for. A service can have a portal, a workflow, a set of criteria, a budget, and staff, and process a high volume of cases through all of it. None of that establishes that it is doing what it was built to do. A system existing is not the same thing as a system working.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Enforcing Data Invariants in Odoo: Model Constraints, Migrations, and Tests That Actually Cover the Fix</title>
      <link>https://dobybaxter127.gitlab.io/articles/enforcing-data-invariants-in-odoo/</link>
      <pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/enforcing-data-invariants-in-odoo/</guid>
      <description>&lt;p&gt;This post collects a few things I ran into while contributing fixes to &lt;a href=&#34;https://openspp.org/en/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenSPP&lt;/a&gt;, a social-protection platform built on Odoo. They are all variations on one question: when a value has to satisfy a rule, where does that rule need to live so it holds on every path the value can arrive through.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This article is also published &lt;a href=&#34;https://dev.to/dobybaxter127/enforcing-data-invariants-in-odoo-model-constraints-migrations-and-tests-that-actually-cover-the-1le0&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;on dev.to&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Write paths in Odoo&lt;/h2&gt;&#xA;&lt;p&gt;A stored model field can be written through several paths:&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-001: Validate Configuration Before Execution</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-001-validate-configuration-before-execution/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-001-validate-configuration-before-execution/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;Configuration is an input to software systems, but configuration errors are often discovered only after execution has already begun. This can lead to confusing failures, partial execution, difficult-to-diagnose behavior, or invalid system state.&lt;/p&gt;&#xA;&lt;p&gt;For systems where configuration controls execution behavior, configuration should therefore be treated as an input that requires explicit validation rather than something that can be assumed to be correct.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;problem&#34;&gt;Problem&lt;/h2&gt;&#xA;&lt;p&gt;If invalid configuration is allowed to reach the execution layer, the resulting failure may occur far away from the original mistake.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-002: Validate LLM Workflow Topology Before Execution</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-002-validate-llm-workflow-topology-before-execution/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-002-validate-llm-workflow-topology-before-execution/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;An LLM workflow is a directed graph: steps are nodes, and the transitions each step permits are edges. Structural mistakes in that graph, such as a transition to a step that no longer exists, a step with no way out, or a cycle that can never terminate, are present the moment the workflow is written. They do not depend on model output or user content.&lt;/p&gt;&#xA;&lt;p&gt;Despite that, these errors usually surface only at runtime, in production, minutes into a real conversation, when a step hands off to a target that was renamed or loops until something times out.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-003: Gate Irreversible Actions on Provable Eligibility, Not Navigation</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-003-gate-irreversible-actions-on-provable-eligibility-not-navigation/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-003-gate-irreversible-actions-on-provable-eligibility-not-navigation/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;Many workflows collect answers across many steps and end in an action that cannot be undone: a non-refundable payment, a submission, a provisioning call. A real-world post-mortem motivates this record. A &lt;a href=&#34;http://GOV.UK&#34; class=&#34;adr-evidence-link&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;http://GOV.UK&lt;/a&gt;  passport application asked, early on, whether the applicant held a required certificate. The applicant answered &amp;quot;No&amp;quot;, which quietly made the whole application invalid, yet the form behaved exactly as it did for every other question and walked the applicant all the way to a non-refundable payment, without ever acting on the answer it had held since near the start.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-004: Test External Source-of-Truth Invariants at the Seam</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-004-test-external-source-of-truth-invariants-at-the-seam/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-004-test-external-source-of-truth-invariants-at-the-seam/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;Most testing advice quietly assumes you own the definition of correct: your code, your tests, your rules, and a failing test means something in your repository changed. Configuration tooling breaks that assumption. Pyxel Config Lab exists to help scientists write YAML that ESA Pyxel, a large and actively-developed framework on its own release cadence, will accept. Pyxel is the source of truth for what a valid config is. The tool only holds a copy of that truth: a bundled JSON schema, a set of tutorial examples, and a mapping of detector types to parameter bounds.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-005: Treat Error Messages as First-Class Outputs</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-005-treat-error-messages-as-first-class-outputs/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-005-treat-error-messages-as-first-class-outputs/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;A safety net has two jobs: it has to catch the user, and it has to talk to them when it does. The validation boundaries established in ADR-001, ADR-002, and ADR-004 handle the catching. This ADR concerns the speaking half, which is the part that usually goes unbudgeted.&lt;/p&gt;&#xA;&lt;p&gt;The speaking half turns out to be the better-researched of the two, and the research is firm. People do read error messages: an eye-tracking study of developers (Barik et al.) found they allocate roughly a quarter of their visual attention to error text, and that reading a message is comparable in difficulty to reading source code. The message is not a footnote to the work, it is work imposed on the reader. Rewriting cryptic errors into enhanced ones (Becker et al.) reduced errors overall and, notably, reduced repeated errors, the signature of someone stuck in a loop, though the literature also shows that prettier wording alone is not the mechanism. Traver&#39;s HCI analysis frames the message as the primary interface between the system&#39;s internal state and the user&#39;s mental model. Later work shows readability is relative to the reader&#39;s experience. Nielsen&#39;s ninth heuristic (help users recognize, diagnose, and recover) and fifth heuristic (prevent the error in the first place) have held since the 1990s.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-006: Own the Telemetry Namespace for Non-Model GenAI Systems</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-006-own-the-telemetry-namespace-for-non-model-genai-systems/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-006-own-the-telemetry-namespace-for-non-model-genai-systems/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;The LLM Workflow Router is a topology-enforcement layer, not a model-selection router. Given structured metadata about an interaction, it answers one question, &amp;quot;is this workflow transition permitted&amp;quot;, independently of model choice or content. It validates workflow topology at load time, enforces invocation limits, and returns one of three terminal decisions: PROCEED, REFUSE, or PAUSE. Its defining property for instrumentation is that it is content-blind: it never sees a prompt, never calls a provider, and never generates a token.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-007: Reconstruct Ranked Attack Paths With Explicit Confidence, Not Binary Detection</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-007-reconstruct-ranked-attack-paths-with-explicit-confidence-not-binary-detection/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-007-reconstruct-ranked-attack-paths-with-explicit-confidence-not-binary-detection/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;In modern cloud incident response there is often nothing to detect in the old sense. Attackers increasingly log in rather than break in: a large share of recent detections are malware-free, with valid-account abuse behind a significant fraction of cloud incidents. Detection tells you that something happened, but rarely how: which account was really patient zero, which token was replayed, which consent grant opened the door, and in what order.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-008: Design API Endpoints That Degrade Without Breaking the Frontend</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-008-design-api-endpoints-that-degrade-without-breaking-the-frontend/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-008-design-api-endpoints-that-degrade-without-breaking-the-frontend/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;A full-stack app shows one place, the Sheffield Cholera Monument, at two scales at once: a satellite vegetation view from orbit and a centimeter-scale ground model. The backend is a FastAPI service that authenticates against the Copernicus Sentinel Hub, pulls the newest real Sentinel-2 scene over a bounding box, computes NDVI, and pins a satellite marker to the point in orbit where the satellite passed closest to the monument for that scene. It depends on external systems it does not control: the Copernicus APIs and a live Celestrak orbital-elements feed.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ADR-009: Social Resource Floor as a Contracts-First Coordination Layer Owned by No One</title>
      <link>https://dobybaxter127.gitlab.io/adr/adr-009-social-resource-floor-as-a-contracts-first-coordination-layer-owned-by-no-one/</link>
      <pubDate>Sun, 23 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/adr/adr-009-social-resource-floor-as-a-contracts-first-coordination-layer-owned-by-no-one/</guid>
      <description>&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&lt;p&gt;Delivery systems for social protection already exist and are strong: OpenSPP orchestrates programs and registries, OpenG2P provides delivery rails, and OpenCRVS handles civil registration. What is missing is an open, shared layer above them that coordinates one person&#39;s whole survival floor across many providers and many resource types at once, so help can find a person regardless of which organizations happen to serve them.&lt;/p&gt;&#xA;&lt;p&gt;The Social Resource Floor is a blueprint for that missing layer. The first version is finished, and this record captures the architectural decisions that give it its shape.&lt;/p&gt;</description>
    </item>
    <item>
      <title>If GOV.UK Knows the Application Is Invalid, Why Did It Take My Payment?</title>
      <link>https://dobybaxter127.gitlab.io/articles/if-govuk-knows-the-application-is-invalid/</link>
      <pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/if-govuk-knows-the-application-is-invalid/</guid>
      <description>&lt;p&gt;TL;DR — I applied for a British passport on GOV.UK, answered &amp;quot;No&amp;quot; to a question that quietly made the whole application invalid, and the system still walked me all the way to a non-refundable payment — without ever acting on the answer it had held since question three. This isn&amp;#x27;t really a politics post, it&amp;#x27;s a post-mortem. The real failure wasn&amp;#x27;t input validation; it was workflow validation: an invalid state was allowed to propagate all the way to an irreversible action. Below I separate the layers of validation that actually matter, argue that irreversible actions must be gated on provable eligibility rather than mere navigation, show why real-world dependencies are asynchronous, and make the case that accessibility is a property of the workflow, not just the UI.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Floor Beneath Every Person: Building Toward Survival as a Right</title>
      <link>https://dobybaxter127.gitlab.io/articles/a-floor-beneath-every-person/</link>
      <pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/a-floor-beneath-every-person/</guid>
      <description>&lt;p&gt;Human survival should not depend on financial access. I&#39;m building the &lt;a href=&#34;https://gitlab.com/dobybaxter127/social-resource-floor&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Social Resource Floor&lt;/a&gt; because I believe there should be an open, shared way for a person to reach the resources they need to stay alive — food, housing, energy, healthcare — grounded in being human rather than in what they can pay. The first version of the blueprint is now finished, and this is why it exists and how it&#39;s built. The deeper technical walkthrough lives in the &lt;a href=&#34;https://dev.to/dobybaxter127/a-floor-beneath-every-person-design-choices-in-the-first-social-resource-floor-blueprint-2hb5&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;companion article on dev.to&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Floor Beneath Which No One Falls: Why I Started the Social Resource Floor</title>
      <link>https://dobybaxter127.gitlab.io/articles/social-resource-floor-essay/</link>
      <pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/social-resource-floor-essay/</guid>
      <description>&lt;p&gt;Survival should be grounded in being human, not in financial access. I started the &lt;a href=&#34;https://social-resource-floor-5a9cc0.gitlab.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Social Resource Floor&lt;/a&gt; because I could not stop noticing the gate that stands between people and the resources they need to live — and because I believe the structure that coordinates access to those resources should be owned by no one and open to everyone.&lt;/p&gt;&#xA;&lt;h2&gt;The gate we stopped noticing&lt;/h2&gt;&#xA;&lt;p&gt;For most people, most of the time, survival routes through money. To reach food, housing, energy, or healthcare, you generally need purchasing power — and to hold or move purchasing power you need banking, employment, or standing of some kind. We have lived with this arrangement so long that it feels like the natural order rather than a design decision. But it is a design decision, and like any design decision it decides who is left out.&lt;/p&gt;</description>
    </item>
    <item>
      <title>OpenSPP And Why This Work Matters to Me: Infrastructure, Openness, and Survival as a Right</title>
      <link>https://dobybaxter127.gitlab.io/articles/why-this-work-matters/</link>
      <pubDate>Sun, 09 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/why-this-work-matters/</guid>
      <description>&lt;p&gt;Where a government cannot reach its people, software sometimes can. I contribute to &lt;a href=&#34;https://openspp.org/en/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;OpenSPP&lt;/a&gt; because I believe the infrastructure that carries survival to a human being should belong to everyone — and I hope that one day it reaches everyone.&lt;/p&gt;&#xA;&lt;h2&gt;The gap infrastructure is meant to close&lt;/h2&gt;&#xA;&lt;p&gt;OpenSPP&#39;s homepage states it plainly: more than four billion people worldwide still have no access to social protection. That number is easy to read past, but it isn&#39;t abstract. It is the measure of how many people are one bad harvest, one illness, or one disaster away from having nothing to fall back on.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Teleporter Problem Was Never About Teleporters</title>
      <link>https://dobybaxter127.gitlab.io/articles/teleporter-problem/</link>
      <pubDate>Sun, 09 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/teleporter-problem/</guid>
      <description>&lt;p&gt;TL;DR — I usually write about tools and tests. This one starts with a teleporter and ends somewhere much stranger. The setup is the science-fiction one: scan a person completely, turn them into information, transmit it, and rebuild them atom-for-atom at the other end. The interesting question isn&#39;t whether we can build the machine. It&#39;s the one the engineering never touches — how do we know the person who steps out is actually alive, and actually &lt;em&gt;them&lt;/em&gt;, and not a sophisticated enough copy that behaves exactly like the original? Following that question honestly, teleportation quietly stops being the mystery. Underneath the copy sits a stack of much older problems — why there are separate perspectives at all, why there is any experience at all, and why, even if reality prefers nothing whatsoever, no perspective inside it can ever share that neutrality.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Paving the wrong Path: What a Broken Government System Taught Me About Feedback Loops</title>
      <link>https://dobybaxter127.gitlab.io/articles/paving-the-wrong-path/</link>
      <pubDate>Mon, 27 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/paving-the-wrong-path/</guid>
      <description>&lt;p&gt;Last year I was made redundant from an NHS role. Around the same time, the team I worked in got a &amp;quot;new system.&amp;quot; Everything that used to live on paper — or, honestly, in something that behaved like a shared Excel sheet — was going digital.&lt;/p&gt;&#xA;&lt;p&gt;I was still employed during the first few weeks of rollout, so I watched it happen. And the thing I remember most clearly is that it didn&amp;#x27;t make anything better. The forms moved from paper to screen, and that was more or less the whole story. The same duplications, the same overlaps, the same unanswered questions. If anything, it felt more primitive than the retro spreadsheet it replaced.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Reconstructing cloud identity intrusions from O365 and CloudTrail logs</title>
      <link>https://dobybaxter127.gitlab.io/articles/reconstructing-cloud-identity-intrusions/</link>
      <pubDate>Mon, 20 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/reconstructing-cloud-identity-intrusions/</guid>
      <description>&lt;p&gt;The uncomfortable truth of modern cloud IR is that there is often nothing to &amp;quot;detect&amp;quot; in the old sense. Attackers don&amp;#x27;t break in anymore; they log in. CrowdStrike&amp;#x27;s 2026 Global Threat Report put 82% of last year&amp;#x27;s detections in the malware-free column, with valid-account abuse behind roughly a third of cloud incidents. No dropper, no exploit chain — just a legitimate identity doing legitimate-looking things across Entra, M365, and a dozen SaaS apps.&lt;/p&gt;</description>
    </item>
    <item>
      <title>AI as a Laundering Machine: What Software Engineering Taught Me About Accountability</title>
      <link>https://dobybaxter127.gitlab.io/articles/ai-laundering-machine/</link>
      <pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/ai-laundering-machine/</guid>
      <description>&lt;p&gt;If an employer uses AI to decide whether I&amp;#x27;m worth interviewing, we call it innovation. If I use the same technology to write more clearly or work around a disability, we call it cheating. The algorithms haven&amp;#x27;t changed — only who benefits.&lt;/p&gt;&#xA;&lt;h2&gt;The paradox&lt;/h2&gt;&#xA;&lt;p&gt;There&amp;#x27;s an asymmetry in how we talk about AI and work that I can&amp;#x27;t stop thinking about, because when an employer runs ten thousand applications through a ranking model, we call it efficiency. When an applicant uses that same technology to organize their thoughts or compensate for a cognitive barrier, the language suddenly turns to authenticity, fairness, and &amp;quot;unfair advantage.&amp;quot;&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Safety Net Is an Accessibility Feature: ADHD, AI, and How I Actually Build Software</title>
      <link>https://dobybaxter127.gitlab.io/articles/safety-net-accessibility-feature/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/safety-net-accessibility-feature/</guid>
      <description>&lt;p&gt;A while back I wrote that you don&amp;#x27;t need perfect code — you need a safety net that talks back. People read it as an engineering post, which it was. But I left something out. I don&amp;#x27;t build those systems only because they&amp;#x27;re good engineering. I build them because they&amp;#x27;re how I stay functional as a developer with ADHD and autism. The clear error messages, the validation that runs before anything else does, the tests that fail loudly and specifically — those aren&amp;#x27;t just reliability features to me. They&amp;#x27;re external memory. They&amp;#x27;re the structure my own brain doesn&amp;#x27;t reliably hold on its own.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Building a FastAPI Backend That Serves Live Satellite Imagery and Orbital Position</title>
      <link>https://dobybaxter127.gitlab.io/articles/fastapi-satellite-backend/</link>
      <pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/fastapi-satellite-backend/</guid>
      <description>&lt;p&gt;TL;DR — I built a full-stack app that shows one place — the Sheffield Cholera Monument — from two scales at once: a satellite&amp;#x27;s-eye vegetation view from space, and a centimeter-scale 3D model from the ground. This post is about the backend: a FastAPI service that authenticates against the Copernicus Sentinel Hub, pulls the newest real Sentinel-2 scene over a bounding box, computes NDVI, and then pins a satellite marker to the exact point in orbit where Sentinel-2A passed closest to the monument for that scene. The satellite-data pipeline is the heart of it, so that&amp;#x27;s where I&amp;#x27;ll spend most of the words.&lt;/p&gt;</description>
    </item>
    <item>
      <title>I Instrumented a System the OTel GenAI Conventions Weren&#39;t Built For - Here&#39;s Where They Broke</title>
      <link>https://dobybaxter127.gitlab.io/articles/otel-genai-frictions/</link>
      <pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/otel-genai-frictions/</guid>
      <description>&lt;p&gt;TL;DR — I instrumented a deterministic, content-blind AI workflow enforcer with the emerging OpenTelemetry GenAI semantic conventions. It technically worked, but pinched in six specific places — each one exposing the same hidden assumption: that a GenAI system is, by definition, a model invoker. This post catalogs the six frictions, shows the design I shipped instead, and follows one friction into a live semantic-conventions discussion.&lt;/p&gt;&#xA;&lt;h2&gt;What you&amp;#x27;ll get out of it&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A concrete map of where the GenAI conventions assume a model sits at the center of every span&lt;/li&gt;&#xA;&lt;li&gt;A reusable pattern for instrumenting orchestration / governance / policy layers that don&amp;#x27;t call models&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;ul&gt;&#xA;&lt;li&gt;Why &amp;quot;refused&amp;quot; must not be encoded as &amp;quot;errored,&amp;quot; and how to fix that in one line&lt;/li&gt;&#xA;&lt;li&gt;How a friction log — not a formal proposal — can still move a standard&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;h2&gt;Contents&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The system under instrumentation&lt;/li&gt;&#xA;&lt;li&gt;The six frictions (at a glance)&lt;/li&gt;&#xA;&lt;li&gt;The frictions in detail&lt;/li&gt;&#xA;&lt;li&gt;What I shipped instead: own the namespace&lt;/li&gt;&#xA;&lt;li&gt;The pattern underneath&lt;/li&gt;&#xA;&lt;li&gt;Where one friction ended up&lt;/li&gt;&#xA;&lt;li&gt;Takeaways&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;h2&gt;The system under instrumentation&lt;/h2&gt;&#xA;&lt;p&gt;First, a disambiguation, because &amp;quot;LLM router&amp;quot; is an overloaded term.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing Against State Drift: Guarding a Config Tool Whose Source of Truth Lives Somewhere Else</title>
      <link>https://dobybaxter127.gitlab.io/articles/testing-against-state-drift/</link>
      <pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/testing-against-state-drift/</guid>
      <description>&lt;p&gt;TL;DR — I maintain a browser-based configuration tool for ESA&amp;#x27;s Pyxel detector-simulation framework. Its whole job is to help people write configs that a separate, independently-versioned project will accept. That makes drift — my tool&amp;#x27;s idea of &amp;quot;valid&amp;quot; quietly falling out of sync with Pyxel&amp;#x27;s — the central failure mode. This post is about the testing and automation I built to catch drift at three different layers, and the one principle that ties them together: test each invariant at the seam where it actually lives.&lt;/p&gt;</description>
    </item>
    <item>
      <title>You Don&#39;t Need Perfect Code - You Need a Safety Net That Talks Back</title>
      <link>https://dobybaxter127.gitlab.io/articles/you-dont-need-perfect-code/</link>
      <pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/you-dont-need-perfect-code/</guid>
      <description>&lt;p&gt;TL;DR — My last post was about catching drift: the moment my config tool&amp;#x27;s idea of &amp;quot;valid&amp;quot; silently diverges from the real Pyxel framework. This post is about the other half of the same system — what happens the instant a human hits one of those checks. A safety net has two jobs: it has to catch you, and it has to talk to you when it does. Perfect code chases the first and forgets the second. I dug into ~60 years of error-message research to work out what a net that talks back should actually say, and mapped each finding onto a concrete rule I now hold my own diagnostics to.&lt;/p&gt;</description>
    </item>
    <item>
      <title>GitLab vs GitHub in 2026: Integrated Platform vs. Composable Ecosystem</title>
      <link>https://dobybaxter127.gitlab.io/articles/gitlab-vs-github-2026/</link>
      <pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/gitlab-vs-github-2026/</guid>
      <description>&lt;p&gt;Pick GitLab or GitHub in 2026 and you&amp;#x27;re not really choosing between two Git hosts — you&amp;#x27;re choosing between two philosophies about what a development platform should be. The old comparison (&amp;quot;GitLab has CI/CD built in, GitHub needs external tools&amp;quot;) is out of date. GitHub has native CI/CD, native security scanning, and a native container registry now. The real difference is architectural: GitLab bundles the whole DevSecOps lifecycle into one integrated application, while GitHub gives you a strong core and an enormous ecosystem to compose the rest yourself.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Validate Your LLM Workflow Before It Runs (Python &#43; YAML Topology Checks)</title>
      <link>https://dobybaxter127.gitlab.io/articles/validate-llm-workflow-topology/</link>
      <pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/validate-llm-workflow-topology/</guid>
      <description>&lt;p&gt;Your LLM app boots fine. It answers the first few messages fine. Then, ten minutes into a real conversation, it quietly walks from the support step into the billing step that doesn&amp;#x27;t exist anymore, or loops faq → support → faq → support until something times out. Nothing crashed at startup. The mistake was in the workflow&amp;#x27;s shape the whole time — you just didn&amp;#x27;t find out until runtime, in production, with a user watching.&lt;/p&gt;</description>
    </item>
    <item>
      <title>About</title>
      <link>https://dobybaxter127.gitlab.io/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/about/</guid>
      <description></description>
    </item>
    <item>
      <title>Contact</title>
      <link>https://dobybaxter127.gitlab.io/contact/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/contact/</guid>
      <description></description>
    </item>
    <item>
      <title>Learning to Build Without a Ladder</title>
      <link>https://dobybaxter127.gitlab.io/articles/learning-to-build-without-a-ladder-site/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/learning-to-build-without-a-ladder-site/</guid>
      <description>&lt;p&gt;I never got the junior job.&lt;/p&gt;&#xA;&lt;p&gt;Not for lack of trying. I spent well over a year applying, building, learning, and applying again. For long stretches I could not get past the first filter, let alone into a room with an engineer. And I am not unusual. I am one of a very large group of people who entered software and security over the past five years or so and found that the door marked &#34;start here&#34; had quietly been taken off its hinges.&lt;/p&gt;</description>
    </item>
    <item>
      <title>LLM Workflow Router</title>
      <link>https://dobybaxter127.gitlab.io/products/llm-workflow-router/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/products/llm-workflow-router/</guid>
      <description></description>
    </item>
    <item>
      <title>Nexa</title>
      <link>https://dobybaxter127.gitlab.io/products/nexa/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/products/nexa/</guid>
      <description></description>
    </item>
    <item>
      <title>Nimbus Vestige</title>
      <link>https://dobybaxter127.gitlab.io/products/nimbus-vestige/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/products/nimbus-vestige/</guid>
      <description></description>
    </item>
    <item>
      <title>Products</title>
      <link>https://dobybaxter127.gitlab.io/products/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/products/</guid>
      <description></description>
    </item>
    <item>
      <title>Projects</title>
      <link>https://dobybaxter127.gitlab.io/projects/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/projects/</guid>
      <description></description>
    </item>
    <item>
      <title>Services</title>
      <link>https://dobybaxter127.gitlab.io/services/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/services/</guid>
      <description></description>
    </item>
    <item>
      <title>When Is a System Not Fit for Purpose?</title>
      <link>https://dobybaxter127.gitlab.io/articles/when-is-a-system-not-fit-for-purpose/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://dobybaxter127.gitlab.io/articles/when-is-a-system-not-fit-for-purpose/</guid>
      <description>&lt;p&gt;In software engineering we have a fairly plain answer to the question of whether something is fit for purpose: a system is fit for purpose if it reliably does the thing it was designed to do. We seem to apply a much softer standard to the systems people actually have to live inside. A public service can have a department, an application portal, a helpline, a set of criteria, a budget, and hundreds of people working within it, and none of that tells us whether it is achieving its purpose. A system existing is not the same thing as a system working. The longer technical walkthrough lives in the &lt;a href=&#34;https://dev.to/dobybaxter127/when-is-a-system-not-fit-for-purpose-587d&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;companion article on dev.to&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
