<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Canon on BXM.net</title>
    <link>https://bxm.net/tags/canon/</link>
    <description>Recent content in Canon on BXM.net</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 22 Oct 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://bxm.net/tags/canon/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>BXM 0.1.0 Launches With Canon and Memo, Two Open Source Tools for Repeatable Results</title>
      <link>https://bxm.net/bxm-0.1.0-launches-with-canon-and-memo-two-open-source-tools-for-repeatable-results/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/bxm-0.1.0-launches-with-canon-and-memo-two-open-source-tools-for-repeatable-results/</guid>
      <description>&lt;p&gt;BXM 0.1.0 is out. It&amp;rsquo;s two small command-line tools in one repository, open source under the Apache License 2.0, with builds for Linux, macOS and Windows.&lt;/p&gt;&#xA;&lt;p&gt;They share one idea. Same input, same bytes, same result. Canon applies it to data and Memo applies it to work.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;BXM Canon&lt;/strong&gt; is a binary encoding with exactly one valid form for every value. Two programs that encode the same data get the same bytes, whatever order they wrote the keys in and however they spelled the numbers. A hash or a signature taken on one machine holds on every other. The decoder refuses any byte string that isn&amp;rsquo;t the one encoding of its value, so a second spelling can&amp;rsquo;t sneak in through the back door.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Signed JSON Breaks and How a Canonical Encoding Fixes It</title>
      <link>https://bxm.net/why-signed-json-breaks-and-how-a-canonical-encoding-fixes-it/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/why-signed-json-breaks-and-how-a-canonical-encoding-fixes-it/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a bug that shows up in almost every system that signs or hashes structured data. Service A builds a record, serializes it as JSON, hashes it and signs the hash. Service B receives the record, parses it, does some work, serializes it again and checks the signature. It fails. Nobody changed a single field.&lt;/p&gt;&#xA;&lt;p&gt;What changed was the bytes. Service B&amp;rsquo;s JSON library wrote the keys in a different order. Or it wrote &lt;code&gt;1.0&lt;/code&gt; as &lt;code&gt;1&lt;/code&gt;. Or it escaped &lt;code&gt;é&lt;/code&gt; as &lt;code&gt;é&lt;/code&gt; where A wrote the character itself. All three are valid JSON for the same data. A hash doesn&amp;rsquo;t care about data, though. It cares about bytes, and there are many ways to write the same JSON.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Config Diff of 128 Lines Hid Two Real Changes, and Canon Named Both in Two Lines</title>
      <link>https://bxm.net/a-config-diff-of-128-lines-hid-two-real-changes-and-canon-named-both-in-two-lines/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/a-config-diff-of-128-lines-hid-two-real-changes-and-canon-named-both-in-two-lines/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a familiar review. The config for a checkout service comes back from someone&amp;rsquo;s editor and the diff is a wall of red and green. The editor saved with four spaces instead of two, sorted the keys, and escaped the &amp;ldquo;ü&amp;rdquo; in the description. Somewhere in there, maybe, a value changed.&lt;/p&gt;&#xA;&lt;p&gt;We built that situation on purpose. One service config of 66 lines covers the server, database, cache, limits, features, logging and deploy settings. The deploy tool writes it one way. An editor saves it another way and changes two values on the way: the database pool timeout drops from 30000 ms to 3000 ms, and the replica count turns from the integer &lt;code&gt;3&lt;/code&gt; into the float &lt;code&gt;3.0&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>BXM Canon 0.2.0 Brings the Same Bytes to JavaScript With One Rust Core Compiled to WebAssembly</title>
      <link>https://bxm.net/bxm-canon-0.2.0-brings-the-same-bytes-to-javascript-with-one-rust-core-compiled-to-webassembly/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/bxm-canon-0.2.0-brings-the-same-bytes-to-javascript-with-one-rust-core-compiled-to-webassembly/</guid>
      <description>&lt;p&gt;BXM Canon 0.2.0 adds a JavaScript package. It runs in Node 18 and later and in browsers, and it gives exactly the bytes and hashes the &lt;code&gt;bxm-canon&lt;/code&gt; command gives, because it is the same Rust code compiled to WebAssembly.&lt;/p&gt;&#xA;&lt;p&gt;That matters more for Canon than for most libraries. A canonical encoding is only as good as the agreement between the programs that use it. If the Node service and the Go service each carry their own implementation, a single corner case they read differently, a float spelled one way or a key compared another, brings back the problem Canon exists to remove.&lt;/p&gt;</description>
    </item>
    <item>
      <title>BXM Canon 0.3.0 Adds Python, With Ints, Floats and Bytes Kept Apart and the Same Hash as Every Other Build</title>
      <link>https://bxm.net/bxm-canon-0.3.0-adds-python-with-ints-floats-and-bytes-kept-apart-and-the-same-hash-as-every-other-build/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/bxm-canon-0.3.0-adds-python-with-ints-floats-and-bytes-kept-apart-and-the-same-hash-as-every-other-build/</guid>
      <description>&lt;p&gt;BXM Canon 0.3.0 adds a Python package. It&amp;rsquo;s the same Rust core again, this time called through PyO3, with wheels for Linux, macOS and Windows and any Python from 3.9 up. A value hashed in Python gives the hash the command line, the C library and the JavaScript package give, because all of them run the same code.&lt;/p&gt;&#xA;&lt;p&gt;Python turned out to be the most natural fit so far. JavaScript has one number type, so a JavaScript caller has to think about whether &lt;code&gt;1&lt;/code&gt; should be an integer or a float. Python already keeps &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;float&lt;/code&gt; apart, and it has a real &lt;code&gt;bytes&lt;/code&gt; type, which is exactly what Canon distinguishes. So the Python package can take a value straight from your program, no text step in between.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hashing 100,000 JSON Lines Found No Duplicates, Hashing Them With Canon Found 9,900</title>
      <link>https://bxm.net/hashing-100000-json-lines-found-no-duplicates-hashing-them-with-canon-found-9900/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/hashing-100000-json-lines-found-no-duplicates-hashing-them-with-canon-found-9900/</guid>
      <description>&lt;p&gt;Event pipelines get the same event twice. A producer times out, retries, and the retry goes through a different service that writes JSON its own way. The usual dedupe is a hash of each line, and it quietly misses all of these.&lt;/p&gt;&#xA;&lt;p&gt;We generated a stream of 100,000 JSON lines from a fixed seed, 13.1 MB in all. 90,000 are distinct purchase events. The other 10,000 are resends of earlier events, written by two other producers. One sorts the keys and escapes non-ASCII, so &amp;ldquo;Zürich&amp;rdquo; arrives as &lt;code&gt;Z\u00fcrich&lt;/code&gt;. The other reverses the key order and adds spaces. For a twist, 100 of the resends come from a producer that writes the quantity as a float: &lt;code&gt;2.0&lt;/code&gt; where the original said &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How BXM Was Tested With Two Million Damaged Inputs, Sixteen Processes and a Killed Run</title>
      <link>https://bxm.net/how-bxm-was-tested-with-two-million-damaged-inputs-sixteen-processes-and-a-killed-run/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/how-bxm-was-tested-with-two-million-damaged-inputs-sixteen-processes-and-a-killed-run/</guid>
      <description>&lt;p&gt;Each BXM tool makes one main promise. Canon promises that every value has exactly one encoding. Memo promises that it never hands you a wrong or half-restored output. Most of the testing went into trying to break those two promises, and the results are recorded in the repository&amp;rsquo;s &lt;code&gt;test/results&lt;/code&gt; folder by a script anyone can run again.&lt;/p&gt;&#xA;&lt;h2 id=&#34;canon&#34;&gt;Canon&lt;/h2&gt;&#xA;&lt;p&gt;The property behind Canon is short to state: if the decoder accepts a byte string, encoding the decoded value gives back exactly the same bytes. If that holds, no value can have a second accepted spelling.&lt;/p&gt;</description>
    </item>
    <item>
      <title>One Order Built in Python, JavaScript and by Hand Gives Three JSON Hashes and One Canon Hash</title>
      <link>https://bxm.net/one-order-built-in-python-javascript-and-by-hand-gives-three-json-hashes-and-one-canon-hash/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/one-order-built-in-python-javascript-and-by-hand-gives-three-json-hashes-and-one-canon-hash/</guid>
      <description>&lt;p&gt;A checkout service written in Python signs each order before it hands it on. A fulfilment service written in JavaScript checks the signature before it ships anything. Both have the same order in memory. The question is whether they agree on its bytes.&lt;/p&gt;&#xA;&lt;p&gt;We built one order three ways. Python filled a dict in the order its code reads, and &lt;code&gt;json.dumps&lt;/code&gt; wrote it with its defaults: a space after every comma and colon, and &amp;ldquo;Zürich&amp;rdquo; escaped as &lt;code&gt;Z\u00fcrich&lt;/code&gt;. JavaScript built the same object with its keys in another order, and &lt;code&gt;JSON.stringify&lt;/code&gt; wrote it compactly with the ü left as it is. The third copy is a file written by hand, pretty-printed, with yet another key order, hashed with the &lt;code&gt;bxm-canon&lt;/code&gt; command.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
