<?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: Rabah Laouadi </title>
    <description>The latest articles on DEV Community by Rabah Laouadi  (@rabeh_arch).</description>
    <link>https://dev.to/rabeh_arch</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3922515%2F09e5ae9b-3a9a-497e-b64c-f0dd29a10cdd.jpg</url>
      <title>DEV Community: Rabah Laouadi </title>
      <link>https://dev.to/rabeh_arch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rabeh_arch"/>
    <language>en</language>
    <item>
      <title>Why Green Tests Are Not Enough for AI Coding Agents#</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Thu, 22 Oct 2026 06:33:33 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/why-green-tests-are-not-enough-for-ai-coding-agents-app</link>
      <guid>https://dev.to/rabeh_arch/why-green-tests-are-not-enough-for-ai-coding-agents-app</guid>
      <description>&lt;p&gt;Over the last few months, I’ve been spending more time working with AI coding agents. They are fast, useful, and in many cases they can fix small bugs or implement focused changes much faster than doing everything manually.&lt;/p&gt;

&lt;p&gt;But while using them, I kept coming back to the same problem: how do I know that the evidence around the fix is actually meaningful?&lt;/p&gt;

&lt;p&gt;It is easy to ask an agent to change some code, run a test, and return a green result. The problem is that a green test only tells me that the final version passed. It does not necessarily tell me whether the test was capable of detecting the original bug.&lt;/p&gt;

&lt;p&gt;That difference sounds small, but it matters a lot.&lt;/p&gt;

&lt;p&gt;Imagine an AI agent fixes a bug and adds a regression test. The final test run passes, so the change looks good. Now imagine that we take the exact same test and run it against the broken version of the code, and it passes there too.&lt;/p&gt;

&lt;p&gt;In that case, the test is green, but it did not really prove the bug was fixed.&lt;/p&gt;

&lt;p&gt;That is the kind of problem I wanted to handle more systematically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basic idea
&lt;/h2&gt;

&lt;p&gt;The principle is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broken baseline + regression probe = FAIL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed result + same regression probe = PASS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the same probe fails on the broken version and passes on the fixed version, the evidence is much stronger.&lt;/p&gt;

&lt;p&gt;If it passes on both, then the test may not actually be testing the bug we care about.&lt;/p&gt;

&lt;p&gt;This idea became the basis for a small tool I’ve been building called &lt;strong&gt;AI Coding Agent Reliability Kit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a Linux-first local workflow for reviewing AI-assisted bug fixes with stronger mechanical evidence.&lt;/p&gt;

&lt;p&gt;The goal is not to replace code review, security review, or engineering judgment. The goal is to make the evidence produced around an AI-generated fix easier to inspect and harder to misinterpret.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I wanted from the workflow
&lt;/h2&gt;

&lt;p&gt;When I started working on this, I did not want another wrapper that simply runs a command and prints success or failure.&lt;/p&gt;

&lt;p&gt;I wanted a workflow that would answer several questions around the change.&lt;/p&gt;

&lt;p&gt;What was the agent allowed to modify?&lt;/p&gt;

&lt;p&gt;Did it stay inside that scope?&lt;/p&gt;

&lt;p&gt;Did the final verification command really pass?&lt;/p&gt;

&lt;p&gt;Does the regression probe fail on the broken baseline?&lt;/p&gt;

&lt;p&gt;Can the result be reproduced in a clean replay?&lt;/p&gt;

&lt;p&gt;Can another person review the evidence without having to reconstruct everything manually?&lt;/p&gt;

&lt;p&gt;These are basic questions, but once coding agents start making larger or more frequent changes, they become important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bounding the change before the agent starts
&lt;/h2&gt;

&lt;p&gt;One of the things the kit does is define the task and the allowed paths before the coding work begins.&lt;/p&gt;

&lt;p&gt;This is useful because an agent can sometimes fix the requested problem while also changing unrelated files. The final result may still work, but the change surface becomes larger than necessary.&lt;/p&gt;

&lt;p&gt;For a focused bug fix, I usually want a clear boundary.&lt;/p&gt;

&lt;p&gt;For example, if a task only needs a change in one source file and one regression test, then a modification to an unrelated README, configuration file, or another package should be visible immediately.&lt;/p&gt;

&lt;p&gt;The kit tracks the declared scope and checks whether the final change stayed inside it.&lt;/p&gt;

&lt;p&gt;If something changed outside the allowed boundary, that is reported instead of silently accepting the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking the final result is not enough
&lt;/h2&gt;

&lt;p&gt;A normal workflow often ends after something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pytest tests/test_bug.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command exits successfully, so the task is considered done.&lt;/p&gt;

&lt;p&gt;That is useful, but for a regression fix I want one more piece of information.&lt;/p&gt;

&lt;p&gt;I want to know what happens when the same probe is run against the known broken baseline.&lt;/p&gt;

&lt;p&gt;A good regression probe should normally distinguish the two states.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Broken version: FAIL
Fixed version:  PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a much stronger signal than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Broken version: PASS
Fixed version:  PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second result does not necessarily mean the code is wrong. It means the evidence is weak.&lt;/p&gt;

&lt;p&gt;That distinction is important.&lt;/p&gt;

&lt;p&gt;The workflow should not pretend that a test proves something it does not prove.&lt;/p&gt;

&lt;h2&gt;
  
  
  Non-discriminating tests
&lt;/h2&gt;

&lt;p&gt;This was one of the main reasons I built the kit.&lt;/p&gt;

&lt;p&gt;A test can look perfectly valid and still fail to discriminate between the broken and fixed versions.&lt;/p&gt;

&lt;p&gt;For example, imagine a function that is supposed to multiply two numbers but currently adds them.&lt;/p&gt;

&lt;p&gt;The broken code might look like this:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix changes it to:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine the test only checks this:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_calculate_exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test is green after the fix, but it was also green before the fix.&lt;/p&gt;

&lt;p&gt;It proves that the function exists. It does not prove that the bug was fixed.&lt;/p&gt;

&lt;p&gt;This type of result should not be treated the same as a real regression test.&lt;/p&gt;

&lt;p&gt;The kit detects this condition and reports the evidence as non-discriminating instead of treating the final green result as sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scope violations
&lt;/h2&gt;

&lt;p&gt;Another case I wanted to handle is when the actual code change is correct, but something outside the allowed scope is modified.&lt;/p&gt;

&lt;p&gt;This can happen accidentally, or because an automated workflow touches another file during execution.&lt;/p&gt;

&lt;p&gt;Suppose the agent is allowed to modify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/formatter.py
tests/test_formatter.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source fix and test may both be correct, but if the final change also modifies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then the workflow should report that separately.&lt;/p&gt;

&lt;p&gt;The important point here is that correctness and scope are different things.&lt;/p&gt;

&lt;p&gt;A correct source fix does not automatically make an unrelated change acceptable.&lt;/p&gt;

&lt;p&gt;The kit keeps those concerns separate so the reviewer can see exactly what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean replay
&lt;/h2&gt;

&lt;p&gt;Another feature I wanted was the ability to reproduce a result from a clean state when needed.&lt;/p&gt;

&lt;p&gt;Sometimes a change passes because of something left behind in the working environment: generated files, caches, local state, or another uncommitted change.&lt;/p&gt;

&lt;p&gt;A clean replay helps answer a simple question:&lt;/p&gt;

&lt;p&gt;Can the same result be reproduced without depending on the current working directory state?&lt;/p&gt;

&lt;p&gt;Not every task needs a full clean replay, but for changes where reproducibility matters, it gives the reviewer another useful piece of evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review summaries
&lt;/h2&gt;

&lt;p&gt;One problem with automation is that it can generate too much output.&lt;/p&gt;

&lt;p&gt;Raw logs are useful when investigating something, but they are not always the best way to review a change.&lt;/p&gt;

&lt;p&gt;The kit produces a structured review summary that makes the main results easier to inspect.&lt;/p&gt;

&lt;p&gt;A reviewer can see things such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scope: PASS
Final verification: PASS
Broken baseline probe: FAIL
Fixed probe: PASS
Differential evidence: PASS
Replay: REPRODUCIBLE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If something fails, the summary should show that clearly instead of hiding it behind a successful final command.&lt;/p&gt;

&lt;p&gt;The idea is to reduce the amount of reconstruction the reviewer needs to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof bundles and integrity
&lt;/h2&gt;

&lt;p&gt;The workflow can also export proof material and verify its integrity.&lt;/p&gt;

&lt;p&gt;This is useful when the evidence needs to be moved, archived, or reviewed later.&lt;/p&gt;

&lt;p&gt;Instead of only saying that a command passed at some point, the workflow can preserve the relevant result records and verify that the expected material has not changed.&lt;/p&gt;

&lt;p&gt;This is not meant to turn the tool into a security certification system. It is simply a way to make the evidence around a run more inspectable and reproducible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What READY_FOR_REVIEW means
&lt;/h2&gt;

&lt;p&gt;One thing I wanted to keep very clear is the meaning of the final status.&lt;/p&gt;

&lt;p&gt;When the kit reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;READY_FOR_REVIEW
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it does not mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The code is definitely correct.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The code is secure.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also does not mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This is automatically production-ready.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means that the configured mechanical evidence gates passed and the result is ready for a human reviewer to inspect.&lt;/p&gt;

&lt;p&gt;That distinction is intentional.&lt;/p&gt;

&lt;p&gt;I do not think an automated workflow should silently upgrade mechanical evidence into a semantic engineering judgment.&lt;/p&gt;

&lt;p&gt;A human reviewer still needs to look at the actual change and decide whether it is correct for the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more with coding agents
&lt;/h2&gt;

&lt;p&gt;A human developer usually has some context in their head while making a change. They know what they touched, what they were trying to fix, and what assumptions they made.&lt;/p&gt;

&lt;p&gt;With an AI coding agent, more of that work can happen automatically and quickly.&lt;/p&gt;

&lt;p&gt;That speed is useful, but it also means it becomes easier to accept a result simply because the agent says the task is complete and the final test is green.&lt;/p&gt;

&lt;p&gt;The faster the implementation becomes, the more useful it is to make the verification process explicit.&lt;/p&gt;

&lt;p&gt;I do not see this as an argument against coding agents. I use them.&lt;/p&gt;

&lt;p&gt;The point is that if agents are going to make more changes for us, then the evidence around those changes should become better as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux-first and local
&lt;/h2&gt;

&lt;p&gt;The first version of the kit is intentionally simple in its environment assumptions.&lt;/p&gt;

&lt;p&gt;It is designed for Linux and uses a local workflow with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;a local project repository&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted the first version to stay focused instead of claiming support for platforms I had not properly validated.&lt;/p&gt;

&lt;p&gt;Windows and macOS are not part of the validated V1 environment.&lt;/p&gt;

&lt;p&gt;That may change later, but I prefer to be explicit about what has actually been tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the kit is not
&lt;/h2&gt;

&lt;p&gt;This tool does not try to prove that a program is correct.&lt;/p&gt;

&lt;p&gt;It does not replace unit tests, integration tests, static analysis, security review, or a good human code review.&lt;/p&gt;

&lt;p&gt;It also does not make a weak test strong automatically.&lt;/p&gt;

&lt;p&gt;If the regression probe is poorly designed, the workflow can detect some types of weak evidence, such as a probe that passes on both the broken and fixed versions, but it cannot understand every semantic requirement of every project.&lt;/p&gt;

&lt;p&gt;What it does is provide a stricter process around the evidence that already exists.&lt;/p&gt;

&lt;p&gt;For me, that is the useful part.&lt;/p&gt;

&lt;h2&gt;
  
  
  The workflow in practice
&lt;/h2&gt;

&lt;p&gt;A typical flow looks roughly like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define the task and allowed paths.&lt;/li&gt;
&lt;li&gt;Generate a bounded brief for the coding agent.&lt;/li&gt;
&lt;li&gt;Let the agent implement the fix.&lt;/li&gt;
&lt;li&gt;Run the declared final verification.&lt;/li&gt;
&lt;li&gt;Check the resulting changes against the allowed scope.&lt;/li&gt;
&lt;li&gt;Run the same regression probe against the broken baseline.&lt;/li&gt;
&lt;li&gt;Reject the evidence if the probe does not distinguish broken from fixed.&lt;/li&gt;
&lt;li&gt;Perform a clean replay when required.&lt;/li&gt;
&lt;li&gt;Generate a review summary.&lt;/li&gt;
&lt;li&gt;Export and verify the proof material if needed.&lt;/li&gt;
&lt;li&gt;Hand the result to a human reviewer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is intentionally not a fully autonomous approval system.&lt;/p&gt;

&lt;p&gt;The last step is still review.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small example
&lt;/h2&gt;

&lt;p&gt;Suppose the bug is in a slug function.&lt;/p&gt;

&lt;p&gt;The broken implementation is:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slugify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lower&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the broken result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helloworld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The required result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix might be:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slugify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&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="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the regression probe:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_slugify&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;slugify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello-world&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;slugify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Two Words&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;two-words&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the useful part is not only that this test passes after the fix.&lt;/p&gt;

&lt;p&gt;The stronger evidence is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Broken baseline: FAIL
Fixed result:    PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells the reviewer that the probe actually detects the behavior being corrected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;The main reason is that I want to use coding agents more, not less.&lt;/p&gt;

&lt;p&gt;But if I am going to delegate more implementation work to them, I want a better boundary between “the agent says it is done” and “there is enough evidence for me to review the result seriously.”&lt;/p&gt;

&lt;p&gt;That is the gap this project is trying to cover.&lt;/p&gt;

&lt;p&gt;It is still a first version, and I expect the workflow to evolve as I use it on more projects and find more edge cases.&lt;/p&gt;

&lt;p&gt;For now, the focus is narrow: bounded changes, stronger regression evidence, reproducibility, and human review.&lt;/p&gt;

&lt;p&gt;If that sounds useful for the way you work with coding agents, I published the first version here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sovereign-system.itch.io/ai-coding-agent-reliability-kit" rel="noopener noreferrer"&gt;https://sovereign-system.itch.io/ai-coding-agent-reliability-kit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>python</category>
      <category>devtools</category>
    </item>
    <item>
      <title>When a Compile-Fail Test Fails for the Wrong Reason</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Wed, 02 Sep 2026 22:45:32 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/when-a-compile-fail-test-fails-for-the-wrong-reason-je2</link>
      <guid>https://dev.to/rabeh_arch/when-a-compile-fail-test-fails-for-the-wrong-reason-je2</guid>
      <description>&lt;p&gt;I found a test recently that was doing exactly what it was supposed to do: it failed to compile.&lt;/p&gt;

&lt;p&gt;The problem was that it failed &lt;strong&gt;before it reached the thing I thought I was testing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That was a useful reminder. With compile-fail tests, “the compiler rejected it” is not enough. The reason for the rejection matters.&lt;/p&gt;

&lt;p&gt;I had a few cases like this while hardening some small Rust types. The production code was mostly fine. The stale part was the verification around it.&lt;/p&gt;

&lt;p&gt;The examples below are simplified, and the type names are intentionally generic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The compiler never reached the privacy boundary
&lt;/h2&gt;

&lt;p&gt;Imagine a public type with a private field and const-generic bounds:&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;BoundedValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MIN&lt;/span&gt;&lt;span class="p"&gt;:&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;const&lt;/span&gt; &lt;span class="n"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&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;Code outside the defining module should not be able to construct it by writing the field directly. A compile-fail test for that boundary might start like 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="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;BoundedValue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&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;It certainly does not compile.&lt;/p&gt;

&lt;p&gt;But in the case I was reviewing, the omitted const parameters caused a type-inference error first. The compiler had rejected the program without actually proving that direct field construction was blocked.&lt;/p&gt;

&lt;p&gt;The test looked healthy because it failed. The diagnostic told a different story.&lt;/p&gt;

&lt;p&gt;Making the const parameters explicit removed the unrelated ambiguity:&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;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;BoundedValue&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&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;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&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 test can actually reach the privacy boundary.&lt;/p&gt;

&lt;p&gt;That is a much better negative test. Not because it fails “more strongly,” but because it fails for the property I meant to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stale syntax can hide the same problem
&lt;/h2&gt;

&lt;p&gt;I ran into another version of this with a named-field byte wrapper.&lt;/p&gt;

&lt;p&gt;Simplified:&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;ByteBlock&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;N&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;&amp;gt;&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="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;N&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;An old compile-fail case was trying to construct it using tuple-struct syntax:&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;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ByteBlock&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="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, the compiler rejected it.&lt;/p&gt;

&lt;p&gt;But that test was not checking field privacy. It was only demonstrating that &lt;code&gt;ByteBlock&lt;/code&gt; was not a tuple struct.&lt;/p&gt;

&lt;p&gt;The type had changed shape at some point, while the negative test had kept an older idea of the API.&lt;/p&gt;

&lt;p&gt;If privacy is the thing I want to verify, the misuse needs to match the real shape of the type:&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;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ByteBlock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;32&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;bytes&lt;/span&gt;&lt;span class="p"&gt;:&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="mi"&gt;32&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;From outside the defining module, that gives the compiler a chance to reject the actual private-field access.&lt;/p&gt;

&lt;p&gt;The old test contained a real compiler error. It was just evidence for the wrong claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is easy to miss with &lt;code&gt;trybuild&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I like &lt;code&gt;trybuild&lt;/code&gt; for this kind of testing. A compile-fail case is compiled separately, and the compiler output is compared with the expected &lt;code&gt;.stderr&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;That makes regressions in diagnostics visible, which is useful.&lt;/p&gt;

&lt;p&gt;It also means I need to be careful when accepting or updating those snapshots.&lt;/p&gt;

&lt;p&gt;If a stale test starts failing for an incidental reason and I simply bless the new &lt;code&gt;.stderr&lt;/code&gt;, I can preserve a broken test while making the suite green again.&lt;/p&gt;

&lt;p&gt;That is not a problem with &lt;code&gt;trybuild&lt;/code&gt;. It is a problem with what I am asking the test to establish.&lt;/p&gt;

&lt;p&gt;I used to look at a successful compile-fail suite and move on fairly quickly. Now I read the diagnostic and ask whether it actually reaches the boundary named by the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  A compile-fail test should make one clear claim
&lt;/h2&gt;

&lt;p&gt;The rule I use now is simple: I want each negative test to have one intended reason to fail.&lt;/p&gt;

&lt;p&gt;Before I accept one, I check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claim:&lt;/strong&gt; What exact misuse is this test supposed to reject?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reachability:&lt;/strong&gt; Can the compiler reach that boundary without an unrelated error firing first?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diagnostic:&lt;/strong&gt; Is the observed error actually about the property I care about?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Currentness:&lt;/strong&gt; Does the test still match the current API, type shape, imports, and trait surface?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This sounds obvious in hindsight. It becomes less obvious after a test suite has lived through a few rounds of refactoring.&lt;/p&gt;

&lt;p&gt;A stale import can fail.&lt;/p&gt;

&lt;p&gt;Old constructor syntax can fail.&lt;/p&gt;

&lt;p&gt;Missing generic information can fail.&lt;/p&gt;

&lt;p&gt;An operation that used to be forbidden may even become valid later.&lt;/p&gt;

&lt;p&gt;The word “fail” does not tell me which of those happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime failure is a different boundary
&lt;/h2&gt;

&lt;p&gt;One other case was a useful sanity check.&lt;/p&gt;

&lt;p&gt;Something like 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="nn"&gt;SomeType&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="mi"&gt;0&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;might panic at runtime if &lt;code&gt;new(0)&lt;/code&gt; returns an error or &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the program itself can still be perfectly valid Rust and compile successfully.&lt;/p&gt;

&lt;p&gt;So that is not compile-fail evidence. It belongs to runtime behavior.&lt;/p&gt;

&lt;p&gt;Again, obvious once you say it out loud. But mixing compile-time and runtime expectations is surprisingly easy when old tests and old comments have been copied forward for long enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bigger lesson was about verification code
&lt;/h2&gt;

&lt;p&gt;What stuck with me was not the individual Rust errors. It was the fact that verification code can drift while production code keeps moving.&lt;/p&gt;

&lt;p&gt;Tests encode assumptions too.&lt;/p&gt;

&lt;p&gt;They encode assumptions about type shape, visibility, crate paths, trait surfaces, invariants, and what the API is supposed to forbid.&lt;/p&gt;

&lt;p&gt;Those assumptions can go stale.&lt;/p&gt;

&lt;p&gt;A missing test is easy to notice. A test that still “works” can be more misleading because it gives you confidence without checking the contract you think it checks.&lt;/p&gt;

&lt;p&gt;That applies beyond compile-fail tests. Property tests can model an old semantic rule. Fuzz targets can exercise an obsolete API. Snapshot-based tests can preserve an error that no longer represents the intended boundary.&lt;/p&gt;

&lt;p&gt;So I have become a lot more suspicious of verification artifacts during hardening work.&lt;/p&gt;

&lt;p&gt;I do not just ask whether the test suite passes anymore.&lt;/p&gt;

&lt;p&gt;For negative tests, I also ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why did the compiler say no?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is not the boundary I meant to protect, the test is not done yet.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>testing</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Primitive Should Never Have an Opinion</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Thu, 02 Jul 2026 23:33:53 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/a-primitive-should-never-have-an-opinion-7ja</link>
      <guid>https://dev.to/rabeh_arch/a-primitive-should-never-have-an-opinion-7ja</guid>
      <description>&lt;p&gt;I wasn't looking for a bug,I was auditing one of the foundational primitives in my infrastructure. The implementation was compact, the test coverage was solid, and nothing immediately stood out.&lt;br&gt;
Then one small constraint caught my attention. It had nothing to do with Rust's type system or memory safety, The primitive was rejecting a mathematically valid value without violating a single structural invariant,The rejection existed for one reason only:&lt;br&gt;
I had decided the value wasn't meaningful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Assumption
&lt;/h2&gt;

&lt;p&gt;For a long time, I believed that low-level infrastructure should protect developers from making questionable modeling decisions. It felt like responsible engineering. If a value looked practically useless, why should a primitive allow it to exist? That assumption naturally led me to introduce another rule not because mathematics required it, not because memory safety depended on it, and not because Rust expected it, but simply because I believed it would prevent misuse. The idea seemed harmless. It survived code reviews, redesigns, and every test I threw at it. At the time, I was convinced I was making the primitive more disciplined. I wasn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Question That Changed Everything
&lt;/h2&gt;

&lt;p&gt;The more I examined the constraint, the less sense it made. It wasn't protecting memory safety, it wasn't preserving mathematical correctness, and it wasn't enforcing any structural invariant. Its only purpose was to police intent. That realization forced me to stop reading the implementation and start examining responsibilities instead. Somewhere along the way, I had quietly crossed an architectural boundary. One question immediately exposed it: Who gave this primitive the authority to decide what is meaningful? The answer was obvious. No one had. I had simply allowed a low-level primitive to take ownership of a decision that belonged entirely to the domain above it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Boundary
&lt;/h2&gt;

&lt;p&gt;At first, the distinction felt philosophical. It wasn't. The more I traced responsibilities through the system, the more obvious it became that I had mixed two fundamentally different concerns. Structure is objective; meaning is contextual. One belongs to mathematics, the other belongs to people. A primitive exists to answer one question: Is this value structurally valid? Nothing more. The moment I asked it to answer a second question is this range meaningful? it quietly crossed an architectural boundary. It stopped enforcing structure and started enforcing policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Redesign
&lt;/h2&gt;

&lt;p&gt;One specific range exposed the flaw in my thinking. When I looked at         &lt;/p&gt;

&lt;p&gt;&lt;code&gt;BoundedU64&amp;lt;0, u64::MAX&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I realized there was nothing structurally or mathematically invalid about it. The restriction existed for one reason only: I had unconsciously attached domain semantics to pure mathematics. The redesign itself was surprisingly small removing the restriction required only a few lines of code—but the architectural shift behind it was far more significant. The primitive didn't become weaker by accepting every structurally valid range; it became more honest about its own responsibility. Instead of trying to predict intent or enforce what I considered good modeling decisions, it returned to doing the one thing it was originally meant to do: guarantee structural integrity and leave every question of meaning to the layers built above it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Survived
&lt;/h2&gt;

&lt;p&gt;Looking back, there was never a bug hiding inside the primitive. It behaved exactly as I had designed it to behave. The mistake was mine. I had asked infrastructure to answer a question that belonged entirely to the domain. That audit didn't change the implementation nearly as much as it changed my understanding of architectural responsibility. Since then, one principle has stayed with me whenever I design low-level systems: infrastructure owns structure, while meaning belongs to the domain. The boundary between the two is easy to blur, but once you recognize it, it becomes remarkably difficult to design foundational software any other way.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>architecture</category>
      <category>systems</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>When a Constructor Became a Security Boundary</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Mon, 22 Jun 2026 22:51:57 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/when-a-constructor-became-a-security-boundary-1caj</link>
      <guid>https://dev.to/rabeh_arch/when-a-constructor-became-a-security-boundary-1caj</guid>
      <description>&lt;h1&gt;
  
  
  When a Constructor Became a Security Boundary
&lt;/h1&gt;

&lt;p&gt;I was auditing the initialization layer of one of my Rust systems when I noticed something that looked completely harmless.&lt;/p&gt;

&lt;p&gt;A constructor accepted an object that wasn't fully valid yet and relied on a later validation step to reject it if something was wrong.&lt;/p&gt;

&lt;p&gt;At first, I didn't think much about it. The object would eventually be validated anyway.&lt;/p&gt;

&lt;p&gt;Then it hit me.&lt;/p&gt;

&lt;p&gt;For a brief moment, an impossible state existed inside the system.&lt;/p&gt;

&lt;p&gt;It didn't matter that the state lived for only a few instructions. It didn't matter that validation would eventually reject it.&lt;/p&gt;

&lt;p&gt;The invalid state had already been created.&lt;/p&gt;

&lt;p&gt;That was the vulnerability.&lt;/p&gt;

&lt;p&gt;The audit completely changed how I think about constructors. I no longer see them as functions that merely initialize data.&lt;/p&gt;

&lt;p&gt;I now think of them as security boundaries.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Pattern That Looked Correct
&lt;/h2&gt;

&lt;p&gt;The constructor looked innocent enough.&lt;/p&gt;

&lt;p&gt;pub fn try_new(header_length: u32, ...) -&amp;gt; Option {&lt;br&gt;
    if header_length &amp;lt; Header::SIZE as u32 {&lt;br&gt;
        return None;&lt;br&gt;
    }&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Some(Self {
    header_length,
    // ...
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;At first glance, this seems perfectly reasonable.&lt;/p&gt;

&lt;p&gt;Reject obviously malformed inputs and let a later validation step enforce the remaining invariants.&lt;/p&gt;

&lt;p&gt;For years, this was implicitly my mental model:&lt;/p&gt;

&lt;p&gt;Construct&lt;br&gt;
↓&lt;br&gt;
Validate&lt;br&gt;
↓&lt;br&gt;
Use&lt;/p&gt;

&lt;p&gt;Nothing looked broken.&lt;/p&gt;

&lt;p&gt;The problem is that this design allows an impossible object to exist, even if only temporarily.&lt;/p&gt;

&lt;p&gt;And once an invalid state exists, all bets are off.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Vulnerability
&lt;/h2&gt;

&lt;p&gt;At this point, I stopped looking at the constructor and started looking at the object's lifetime.&lt;/p&gt;

&lt;p&gt;The model was effectively this:&lt;/p&gt;

&lt;p&gt;Construct&lt;br&gt;
↓&lt;br&gt;
Impossible state exists&lt;br&gt;
↓&lt;br&gt;
Validate later&lt;br&gt;
↓&lt;br&gt;
Use&lt;/p&gt;

&lt;p&gt;The object may only live in an invalid state for a few instructions or a few microseconds.&lt;/p&gt;

&lt;p&gt;That sounds harmless.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;The problem with transient invalid states is not their duration.&lt;/p&gt;

&lt;p&gt;The problem is their existence.&lt;/p&gt;

&lt;p&gt;The moment an impossible state exists, every assumption built on top of your invariants becomes questionable.&lt;/p&gt;

&lt;p&gt;An invalid object can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;leak into another subsystem,&lt;/li&gt;
&lt;li&gt;trigger assumptions that later become bugs,&lt;/li&gt;
&lt;li&gt;cause panic propagation,&lt;/li&gt;
&lt;li&gt;violate invariants,&lt;/li&gt;
&lt;li&gt;or create Time-of-Check to Time-of-Use (TOCTOU) style hazards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these failures are guaranteed to happen.&lt;/p&gt;

&lt;p&gt;That's what makes them dangerous.&lt;/p&gt;

&lt;p&gt;They become architectural landmines waiting for future code to step on them.&lt;/p&gt;

&lt;p&gt;I realized I had been treating validation as a repair mechanism.&lt;/p&gt;

&lt;p&gt;It shouldn't be.&lt;/p&gt;

&lt;p&gt;Validation should be the gate that prevents impossible states from ever entering the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Different Mental Model
&lt;/h2&gt;

&lt;p&gt;I no longer think in terms of:&lt;/p&gt;

&lt;p&gt;Construct&lt;br&gt;
↓&lt;br&gt;
Validate&lt;br&gt;
↓&lt;br&gt;
Use&lt;/p&gt;

&lt;p&gt;I think in terms of:&lt;/p&gt;

&lt;p&gt;Validate&lt;br&gt;
↓&lt;br&gt;
Construct&lt;br&gt;
↓&lt;br&gt;
Use&lt;/p&gt;

&lt;p&gt;Or even more simply:&lt;/p&gt;

&lt;p&gt;Valid object&lt;br&gt;
or&lt;br&gt;
No object.&lt;/p&gt;

&lt;p&gt;There should never be an intermediate state.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Doctrine
&lt;/h2&gt;

&lt;p&gt;This audit reinforced a principle that now governs my Rust designs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Invalid states should not be repaired.&lt;/p&gt;

&lt;p&gt;Invalid states should not be rejected later.&lt;/p&gt;

&lt;p&gt;Invalid states should never exist.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I no longer design constructors to initialize data.&lt;/p&gt;

&lt;p&gt;I design them to defend invariants.&lt;/p&gt;

&lt;p&gt;Because the most dangerous bugs are often not memory corruptions.&lt;/p&gt;

&lt;p&gt;They are the impossible states we accidentally allow to exist.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>kernel</category>
    </item>
    <item>
      <title>Why I Open-Sourced Only Layer Zero</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Mon, 01 Jun 2026 05:02:57 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/why-i-open-sourced-only-layer-zero-4op7</link>
      <guid>https://dev.to/rabeh_arch/why-i-open-sourced-only-layer-zero-4op7</guid>
      <description>&lt;p&gt;Why I Open-Sourced Only Layer Zero&lt;/p&gt;

&lt;p&gt;For the past months I’ve been building a deterministic infrastructure foundation in Rust.&lt;/p&gt;

&lt;p&gt;Today I decided to publicly expose only the lowest layer of that system:&lt;/p&gt;

&lt;p&gt;"sovereign-kernel"&lt;/p&gt;

&lt;p&gt;This layer is intentionally minimal and highly constrained.&lt;/p&gt;

&lt;p&gt;Its purpose is not “features”.&lt;br&gt;
Its purpose is correctness.&lt;/p&gt;

&lt;p&gt;The kernel focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"no_std"&lt;/li&gt;
&lt;li&gt;zero allocation&lt;/li&gt;
&lt;li&gt;deterministic serialization&lt;/li&gt;
&lt;li&gt;ABI-stable primitives&lt;/li&gt;
&lt;li&gt;invariant-enforced types&lt;/li&gt;
&lt;li&gt;side-effect free behavior&lt;/li&gt;
&lt;li&gt;fuzz-tested binary contracts&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Why Layer Zero?&lt;/p&gt;

&lt;p&gt;In most systems, instability begins at the foundation.&lt;/p&gt;

&lt;p&gt;If primitive types become ambiguous:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;serialization breaks&lt;/li&gt;
&lt;li&gt;protocols drift&lt;/li&gt;
&lt;li&gt;invariants leak&lt;/li&gt;
&lt;li&gt;behavior diverges across platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So instead of starting from services or APIs,&lt;br&gt;
I started from the lowest deterministic layer possible.&lt;/p&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;«Build primitives that remain predictable years later.»&lt;/p&gt;




&lt;p&gt;Fuzzing the Kernel&lt;/p&gt;

&lt;p&gt;One of the recent fuzzing sessions exposed a failure in chained XOR behavior inside a binary primitive.&lt;/p&gt;

&lt;p&gt;The issue appeared during invariant stress validation.&lt;/p&gt;

&lt;p&gt;The failing sequence:&lt;/p&gt;

&lt;p&gt;let mut acc_even = h;&lt;/p&gt;

&lt;p&gt;for _ in 0..8 {&lt;br&gt;
    acc_even = acc_even ^ h;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;assert!(acc_even.ct_eq(&amp;amp;FixedHash::ZERO));&lt;/p&gt;

&lt;p&gt;The fuzz target successfully detected an invariant violation during repeated mutation cycles.&lt;/p&gt;

&lt;p&gt;After isolating the issue, the primitive behavior was corrected and the invariant contract stabilized.&lt;/p&gt;

&lt;p&gt;This is exactly why fuzzing exists:&lt;br&gt;
not just to crash software,&lt;br&gt;
but to pressure-test assumptions.&lt;/p&gt;




&lt;p&gt;Design Constraints&lt;/p&gt;

&lt;p&gt;The kernel intentionally avoids:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;heap allocation&lt;/li&gt;
&lt;li&gt;runtime randomness&lt;/li&gt;
&lt;li&gt;hidden state&lt;/li&gt;
&lt;li&gt;implicit normalization&lt;/li&gt;
&lt;li&gt;unsafe code&lt;/li&gt;
&lt;li&gt;platform-dependent behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every primitive is designed as a deterministic value object.&lt;/p&gt;




&lt;p&gt;Why Publicly Release This?&lt;/p&gt;

&lt;p&gt;Only Layer Zero is public for now.&lt;/p&gt;

&lt;p&gt;The higher layers remain isolated until they mature further.&lt;/p&gt;

&lt;p&gt;I wanted the public part to be the foundation:&lt;br&gt;
the contracts,&lt;br&gt;
the invariants,&lt;br&gt;
the deterministic core.&lt;/p&gt;

&lt;p&gt;Because infrastructure quality starts long before APIs.&lt;/p&gt;




&lt;p&gt;GitHub:&lt;br&gt;
&lt;a href="https://github.com/Rust-Codes-Hub/kernel_layer_zero" rel="noopener noreferrer"&gt;https://github.com/Rust-Codes-Hub/kernel_layer_zero&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>14.8 Billion Fuzz</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Mon, 01 Jun 2026 01:18:12 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/148-billion-fuzz-515p</link>
      <guid>https://dev.to/rabeh_arch/148-billion-fuzz-515p</guid>
      <description>&lt;p&gt;&lt;em&gt;How 14.8 Billion Fuzz&lt;/em&gt;&lt;br&gt;
Executions Exposed an XOR Invariant Trap in a Rust Kernel Primitive&lt;/p&gt;

&lt;p&gt;For the past weeks, I’ve been building and stress-testing a minimal kernel layer for a long-term Rust infrastructure project.&lt;/p&gt;

&lt;p&gt;The focus is intentionally narrow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deterministic primitives&lt;/li&gt;
&lt;li&gt;zero-allocation types&lt;/li&gt;
&lt;li&gt;stable binary representations&lt;/li&gt;
&lt;li&gt;no hidden runtime behavior&lt;/li&gt;
&lt;li&gt;strict invariant enforcement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recently, I ran a long adversarial fuzzing campaign against the kernel primitives.&lt;/p&gt;

&lt;p&gt;The campaign crossed roughly 14.8 billion executions.&lt;/p&gt;

&lt;p&gt;At first, the interesting part seemed to be the crashes themselves.&lt;/p&gt;

&lt;p&gt;But the second crash turned out to be far more interesting than a typical memory bug.&lt;/p&gt;




&lt;p&gt;The Crash&lt;/p&gt;

&lt;p&gt;The fuzzer eventually stopped on this assertion:&lt;/p&gt;

&lt;p&gt;assertion failed: acc_even.ct_eq(&amp;amp;FixedHash::ZERO)&lt;/p&gt;

&lt;p&gt;At first glance, this looked like a potential issue in the XOR implementation of the hash primitive.&lt;/p&gt;

&lt;p&gt;That would have been serious.&lt;/p&gt;

&lt;p&gt;Especially in low-level deterministic infrastructure where algebraic guarantees matter.&lt;/p&gt;




&lt;p&gt;The Investigation&lt;/p&gt;

&lt;p&gt;The fuzz target contained a chained XOR stress test:&lt;/p&gt;

&lt;p&gt;let mut acc_even = h;&lt;/p&gt;

&lt;p&gt;for _ in 0..8 {&lt;br&gt;
    acc_even = acc_even ^ h;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The invariant incorrectly assumed:&lt;/p&gt;

&lt;p&gt;«even XOR count ⇒ ZERO»&lt;/p&gt;

&lt;p&gt;But there was a subtle mistake.&lt;/p&gt;

&lt;p&gt;The accumulator was already initialized with "h".&lt;/p&gt;

&lt;p&gt;That means the expression actually evaluated to:&lt;/p&gt;

&lt;p&gt;h ^ h ^ h ^ h ^ h ^ h ^ h ^ h ^ h&lt;/p&gt;

&lt;p&gt;Not 8 occurrences.&lt;/p&gt;

&lt;p&gt;9 occurrences.&lt;/p&gt;

&lt;p&gt;And XOR parity rules are strict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;even occurrences ⇒ ZERO&lt;/li&gt;
&lt;li&gt;odd occurrences ⇒ ORIGINAL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the primitive was correct.&lt;/p&gt;

&lt;p&gt;The verification logic was wrong.&lt;/p&gt;




&lt;p&gt;Why This Matters&lt;/p&gt;

&lt;p&gt;This is exactly why long-running fuzzing campaigns are valuable even for “simple” primitives.&lt;/p&gt;

&lt;p&gt;The goal is not only to find crashes.&lt;/p&gt;

&lt;p&gt;The goal is to validate assumptions.&lt;/p&gt;

&lt;p&gt;In low-level systems engineering, incorrect assumptions inside verification layers can become just as dangerous as implementation bugs themselves.&lt;/p&gt;

&lt;p&gt;Especially when those primitives are intended to become foundational infrastructure components.&lt;/p&gt;




&lt;p&gt;The Fix&lt;/p&gt;

&lt;p&gt;The invariant was rewritten to start from ZERO instead:&lt;/p&gt;

&lt;p&gt;let mut acc_even = FixedHash::ZERO;&lt;/p&gt;

&lt;p&gt;for _ in 0..8 {&lt;br&gt;
    acc_even = acc_even ^ h;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Now the parity logic is mathematically correct.&lt;/p&gt;




&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;One thing I’ve learned while building infrastructure software:&lt;/p&gt;

&lt;p&gt;Most failures do not come from “complex” code.&lt;/p&gt;

&lt;p&gt;They come from small assumptions that quietly survive code review, testing, and intuition.&lt;/p&gt;

&lt;p&gt;Fuzzing is one of the few tools brutal enough to challenge those assumptions continuously.&lt;/p&gt;

&lt;p&gt;And sometimes, the most valuable bug is the one that proves the primitive was right all along.&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%2Fhogvx2038yzkfhajmsyl.jpg" 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%2Fhogvx2038yzkfhajmsyl.jpg" alt=" " width="800" height="354"&gt;&lt;/a&gt;&lt;br&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%2F90y36svn4emyqyhrtxdr.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%2F90y36svn4emyqyhrtxdr.png" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;br&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%2F1sncrlhcaua683yu6znh.jpg" 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%2F1sncrlhcaua683yu6znh.jpg" alt=" " width="512" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Even a Rust Progress Bar Can Become a Reliability Problem</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Wed, 13 May 2026 18:34:12 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/even-a-rust-progress-bar-can-become-a-reliability-problem-13oc</link>
      <guid>https://dev.to/rabeh_arch/even-a-rust-progress-bar-can-become-a-reliability-problem-13oc</guid>
      <description>&lt;p&gt;While building &lt;em&gt;CommitGuard&lt;/em&gt;, I realized something interesting:&lt;/p&gt;




&lt;p&gt;even a simple CLI progress percentage can become dangerous under very large workloads.&lt;/p&gt;

&lt;p&gt;At first I had the classic calculation:&lt;/p&gt;

&lt;p&gt;let percentage =&lt;br&gt;
    (current_items * 100) / total_items;&lt;/p&gt;

&lt;p&gt;Looks harmless.&lt;/p&gt;

&lt;p&gt;And for many projects, it probably is.&lt;/p&gt;

&lt;p&gt;But CommitGuard is designed for huge repositories, fuzzing workloads, and long-running scans. That forced me to think more carefully about integer arithmetic and long-term reliability.&lt;/p&gt;

&lt;p&gt;The Overflow Problem&lt;/p&gt;

&lt;p&gt;The dangerous part is this:&lt;/p&gt;

&lt;p&gt;current_items * 100&lt;/p&gt;

&lt;p&gt;If "current_items" becomes large enough, multiplication overflows before division even happens.&lt;/p&gt;

&lt;p&gt;In Rust:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debug builds panic.&lt;/li&gt;
&lt;li&gt;Release builds wrap around.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means your progress percentage may silently become incorrect while the program keeps running.&lt;/p&gt;

&lt;p&gt;The code compiles perfectly.&lt;br&gt;
But correctness is already gone.&lt;/p&gt;

&lt;p&gt;Checked Arithmetic&lt;/p&gt;

&lt;p&gt;In low-level and defensive systems, I strongly prefer explicit arithmetic checks.&lt;/p&gt;

&lt;p&gt;Something like this:&lt;/p&gt;

&lt;p&gt;let scaled =&lt;br&gt;
    current_items.checked_mul(100);&lt;/p&gt;

&lt;p&gt;match scaled {&lt;br&gt;
    Some(value) =&amp;gt; {&lt;br&gt;
        let percentage =&lt;br&gt;
            value / total_items;&lt;br&gt;
    }&lt;br&gt;
    None =&amp;gt; {&lt;br&gt;
        // overflow detected&lt;br&gt;
    }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because "checked_*" makes overflow visible instead of hiding it.&lt;/p&gt;

&lt;p&gt;For long-term systems, silent corruption is usually worse than explicit failure.&lt;/p&gt;

&lt;p&gt;Saturating Arithmetic&lt;/p&gt;

&lt;p&gt;Another possible approach is saturating arithmetic:&lt;/p&gt;

&lt;p&gt;let percentage =&lt;br&gt;
    current_items&lt;br&gt;
        .saturating_mul(100)&lt;br&gt;
        / total_items;&lt;/p&gt;

&lt;p&gt;This avoids crashes and prevents wraparound behavior.&lt;/p&gt;

&lt;p&gt;However, saturation may still produce incorrect logical results once values hit the numeric limit.&lt;/p&gt;

&lt;p&gt;So while it is safer than wrapping arithmetic, it is not always mathematically accurate.&lt;/p&gt;

&lt;p&gt;Widening Arithmetic&lt;/p&gt;

&lt;p&gt;For the progress calculation itself, I ended up widening the arithmetic:&lt;/p&gt;

&lt;p&gt;let percentage = if total_items == 0 {&lt;br&gt;
    100&lt;br&gt;
} else {&lt;br&gt;
    (&lt;br&gt;
        (current_items as u128 * 100)&lt;br&gt;
            / total_items as u128&lt;br&gt;
    ) as usize&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;Using "u128" here makes overflow practically impossible for realistic workloads while keeping the implementation allocation-free and extremely lightweight.&lt;/p&gt;

&lt;p&gt;This was a good balance between correctness, simplicity, and hot-path performance.&lt;/p&gt;

&lt;p&gt;Why I Avoided Heavy Progress Libraries&lt;/p&gt;

&lt;p&gt;While profiling CommitGuard, I noticed many progress implementations rely on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;background threads&lt;/li&gt;
&lt;li&gt;shared state&lt;/li&gt;
&lt;li&gt;"Arc&amp;gt;"&lt;/li&gt;
&lt;li&gt;heap allocations&lt;/li&gt;
&lt;li&gt;constant terminal writes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For normal CLI tools, this is usually fine.&lt;/p&gt;

&lt;p&gt;But for high-frequency scanning loops, tiny overheads accumulate very quickly.&lt;/p&gt;

&lt;p&gt;Especially when progress updates happen millions of times.&lt;/p&gt;

&lt;p&gt;So I kept the implementation intentionally simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no heap allocations&lt;/li&gt;
&lt;li&gt;no background workers&lt;/li&gt;
&lt;li&gt;no synchronization overhead&lt;/li&gt;
&lt;li&gt;no hidden allocations in the hot path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also throttle terminal updates to around every 250ms instead of constantly redrawing the screen.&lt;/p&gt;

&lt;p&gt;That alone significantly reduces terminal I/O overhead.&lt;/p&gt;

&lt;p&gt;Small Math Becomes Systems Engineering&lt;/p&gt;

&lt;p&gt;One thing Rust keeps teaching me is this:&lt;/p&gt;

&lt;p&gt;there is no such thing as “just simple code” in long-term systems.&lt;/p&gt;

&lt;p&gt;A tiny arithmetic assumption can eventually become:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a panic&lt;/li&gt;
&lt;li&gt;corrupted state&lt;/li&gt;
&lt;li&gt;invalid metrics&lt;/li&gt;
&lt;li&gt;undefined behavior&lt;/li&gt;
&lt;li&gt;performance degradation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially under fuzzing or massive workloads.&lt;/p&gt;

&lt;p&gt;The code may compile.&lt;br&gt;
The tests may pass.&lt;br&gt;
But systems programming starts where edge cases begin.&lt;br&gt;
And honestly, that is one of the reasons I enjoy Rust so much.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>architecture</category>
    </item>
    <item>
      <title>14.8 Billion Fuzz Layer Zero Kernel</title>
      <dc:creator>Rabah Laouadi </dc:creator>
      <pubDate>Sat, 09 May 2026 22:17:26 +0000</pubDate>
      <link>https://dev.to/rabeh_arch/148-billion-fuzz-layer-zero-kernel-32jk</link>
      <guid>https://dev.to/rabeh_arch/148-billion-fuzz-layer-zero-kernel-32jk</guid>
      <description>&lt;p&gt;What 14.8 Billion Fuzz&lt;br&gt;
 Executions Revealed About My Rust Kernel Layer&lt;br&gt;
Over the past few days, I ran a long adversarial fuzzing campaign against the minimal kernel layer of my Rust __infrastructure stack.&lt;br&gt;
The target was intentionally small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deterministic primitives&lt;/li&gt;
&lt;li&gt;zero-allocation design&lt;/li&gt;
&lt;li&gt;no_std compatibility&lt;/li&gt;
&lt;li&gt;stable binary serialization&lt;/li&gt;
&lt;li&gt;overflow-safe arithmetic&lt;/li&gt;
&lt;li&gt;&lt;p&gt;invariant-preserving types&lt;br&gt;
The fuzzing campaign executed approximately 14.8 billion iterations.&lt;br&gt;
Focus Areas&lt;br&gt;
The testing focused on validating:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ABI stability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;serialization roundtrips&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;algebraic correctness&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;normalization logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;overflow behavior&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ordering consistency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mutation resistance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Results&lt;br&gt;
The campaign successfully exposed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 crash cases&lt;/li&gt;
&lt;li&gt;several edge-condition inconsistencies&lt;/li&gt;
&lt;li&gt;&lt;p&gt;missing algebraic symmetry in temporal primitives&lt;br&gt;
All issues were discovered before public release.&lt;br&gt;
One particularly interesting result was identifying an incomplete temporal algebra implementation:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Timestamp + Duration"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Timestamp - Timestamp"&lt;br&gt;
were implemented, but:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Timestamp - Duration"&lt;br&gt;
was missing entirely.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fuzzing process exposed this architectural gap immediately.&lt;br&gt;
Why This Matters&lt;br&gt;
Infrastructure primitives are often treated like simple utility code.&lt;br&gt;
I believe this is a mistake.&lt;br&gt;
Low-level primitives become the foundation for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;distributed systems&lt;/li&gt;
&lt;li&gt;ledgers&lt;/li&gt;
&lt;li&gt;event sourcing&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;synchronization layers&lt;/li&gt;
&lt;li&gt;audit systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the primitive layer is weak, every dependent system inherits that weakness.&lt;br&gt;
Final Thoughts&lt;br&gt;
Fuzzing is not just about finding crashes.&lt;br&gt;
It is one of the best tools for validating architectural assumptions under hostile input conditions.&lt;br&gt;
Especially for foundational systems software.&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%2F8whrtw5580b7z9sw5c4v.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%2F8whrtw5580b7z9sw5c4v.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>systems</category>
      <category>cybersecurity</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
