<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>BXM.net</title>
    <link>https://bxm.net/</link>
    <description>Recent content 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/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>Why CI Pipelines Redo Work Nobody Changed and How a Command Memoizer Stops It</title>
      <link>https://bxm.net/why-ci-pipelines-redo-work-nobody-changed-and-how-a-command-memoizer-stops-it/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/why-ci-pipelines-redo-work-nobody-changed-and-how-a-command-memoizer-stops-it/</guid>
      <description>&lt;p&gt;Watch a CI log for a week and count the steps that produced exactly the same output as last time. Code generation from schemas that didn&amp;rsquo;t change. Image resizing for assets nobody touched. Test fixtures rebuilt from the same seed data. A documentation site rendered from the same pages. Each step is a few seconds or a few minutes. On every push, on every branch, on every laptop, it adds up to hours a week of machines doing work they&amp;rsquo;ve already done.&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>Memo in GitHub Actions Skipped a Rust Release Build and Caught Runners With Different Compilers</title>
      <link>https://bxm.net/memo-in-github-actions-skipped-a-rust-release-build-and-caught-runners-with-different-compilers/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/memo-in-github-actions-skipped-a-rust-release-build-and-caught-runners-with-different-compilers/</guid>
      <description>&lt;p&gt;Most CI jobs build the same thing again and again. A docs fix or a typo in a README triggers the whole pipeline, and the release build runs as if the code had changed. This case study puts BXM Memo in front of one such step, a release build of the &lt;code&gt;bxm-canon&lt;/code&gt; binary, and keeps Memo&amp;rsquo;s cache between jobs with &lt;code&gt;actions/cache&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The workflow is in the &lt;a href=&#34;https://github.com/softdevstudio/bxm&#34;&gt;repository&lt;/a&gt; as &lt;code&gt;.github/workflows/case-study-memo.yml&lt;/code&gt;. Five jobs run one after another, each on a fresh GitHub-hosted runner. &lt;code&gt;plain&lt;/code&gt; builds without Memo for the baseline. &lt;code&gt;cold&lt;/code&gt; builds through Memo with an empty cache, &lt;code&gt;warm&lt;/code&gt; changes nothing, &lt;code&gt;docs&lt;/code&gt; edits the README, and &lt;code&gt;source&lt;/code&gt; edits a Rust source file. The inputs are &lt;code&gt;canon/src/**&lt;/code&gt;, &lt;code&gt;Cargo.toml&lt;/code&gt; and &lt;code&gt;Cargo.lock&lt;/code&gt;, and the salt is &lt;code&gt;rustc --version&lt;/code&gt;, so a different compiler means a different result. We ran the whole workflow twice.&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>
    <item>
      <title>Replaying 13 Commits Through Memo Cut Test Time From 228 to 79 Seconds and Turned Up Two Flaky Tests</title>
      <link>https://bxm.net/replaying-13-commits-through-memo-cut-test-time-from-228-to-79-seconds-and-turned-up-two-flaky-tests/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/replaying-13-commits-through-memo-cut-test-time-from-228-to-79-seconds-and-turned-up-two-flaky-tests/</guid>
      <description>&lt;p&gt;BXM&amp;rsquo;s repository has two packages with their own test suites: Canon, tested with &lt;code&gt;cargo test&lt;/code&gt;, and Memo, tested with &lt;code&gt;go test&lt;/code&gt;. Most commits touch one of them, or neither. A docs change or a new JavaScript build script doesn&amp;rsquo;t change either suite&amp;rsquo;s result, yet a plain CI job runs both every time.&lt;/p&gt;&#xA;&lt;p&gt;So we replayed the repository&amp;rsquo;s own history. All 13 commits from 0.1.0 to the end of 0.3.0 were checked out one after another, and both suites ran at each one. That happened twice: once plain, and once with each suite behind Memo. Canon&amp;rsquo;s suite takes &lt;code&gt;canon/**&lt;/code&gt; and the spec&amp;rsquo;s test vectors as inputs. Memo&amp;rsquo;s takes &lt;code&gt;memo/**&lt;/code&gt;. Memo needs a declared output, so each suite writes its log to a file and that file is the output.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Did My Build Step Run Again, Six Cache Misses and What Memo Said About Each</title>
      <link>https://bxm.net/why-did-my-build-step-run-again-six-cache-misses-and-what-memo-said-about-each/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/why-did-my-build-step-run-again-six-cache-misses-and-what-memo-said-about-each/</guid>
      <description>&lt;p&gt;A cache that misses without saying why is almost as annoying as no cache. Someone notices the step ran again, nobody knows why, and the cache key gets a random suffix &amp;ldquo;to be safe&amp;rdquo;. After that the cache never hits.&lt;/p&gt;&#xA;&lt;p&gt;BXM Memo keeps the manifest of the last run of each named job. On a miss it compares the two and says what changed. We put that to work on a small report step: a Python script that totals sales per region from monthly CSV files into &lt;code&gt;out/report.txt&lt;/code&gt;. The step runs through Memo with the script and &lt;code&gt;data/*.csv&lt;/code&gt; as inputs, &lt;code&gt;REPORT_CURRENCY&lt;/code&gt; as an environment variable that changes the result, and the Python version as the salt.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why the Project Is Called BXM</title>
      <link>https://bxm.net/why-the-project-is-called-bxm/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/why-the-project-is-called-bxm/</guid>
      <description>&lt;p&gt;BXM started as a three-letter name looking for a project, and ended up with two projects that each claim it.&lt;/p&gt;&#xA;&lt;p&gt;Read one way, it&amp;rsquo;s &lt;strong&gt;Binary eXchange Messages&lt;/strong&gt;: values written as bytes, passed between programs and languages, and agreed on byte for byte at both ends. That&amp;rsquo;s Canon.&lt;/p&gt;&#xA;&lt;p&gt;Read the other way, it&amp;rsquo;s &lt;strong&gt;Build eXecution Memo&lt;/strong&gt;: a note of what a build step did, kept so the step never has to do it again with the same inputs. That&amp;rsquo;s Memo.&lt;/p&gt;</description>
    </item>
    <item>
      <title>About</title>
      <link>https://bxm.net/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/about/</guid>
      <description>&lt;p&gt;BXM is two small tools that share one idea: same input, same bytes, same result. They live in one repository and on one site because they solve the same kind of problem from two ends.&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. When two programs encode the same data, they get the same bytes, so a hash or a signature taken on one machine holds on every other. &lt;a href=&#34;https://bxm.net/canon/&#34;&gt;More about Canon&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>BXM Canon</title>
      <link>https://bxm.net/canon/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/canon/</guid>
      <description>&lt;p&gt;BXM Canon is a binary encoding with exactly one valid encoding for every value. Same data in, same bytes out, on any machine. The decoder refuses everything else, so &amp;ldquo;are these two the same?&amp;rdquo; becomes &amp;ldquo;are these bytes equal?&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem-it-solves&#34;&gt;The Problem It Solves&lt;/h2&gt;&#xA;&lt;p&gt;Sign a JSON object on one machine and check the signature on another, and it can fail even though nothing changed. One side wrote the keys in another order. Or &lt;code&gt;1.0&lt;/code&gt; came out as &lt;code&gt;1&lt;/code&gt;. Or a string used an escape the other side didn&amp;rsquo;t. Same data, different bytes, broken hash.&lt;/p&gt;</description>
    </item>
    <item>
      <title>BXM Memo</title>
      <link>https://bxm.net/memo/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/memo/</guid>
      <description>&lt;p&gt;BXM Memo skips a command when its inputs haven&amp;rsquo;t changed. Put &lt;code&gt;bxm-memo run&lt;/code&gt; in front of a slow step, say what it reads and writes, and the next time the inputs match it restores the outputs instead of running the step. When the inputs don&amp;rsquo;t match, it says which one changed.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bxm-memo run -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;proto/**/*.proto&amp;#39;&lt;/span&gt; -i gen.sh -o gen/ -- ./gen.sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-problem-it-solves&#34;&gt;The Problem It Solves&lt;/h2&gt;&#xA;&lt;p&gt;Build and CI pipelines redo work whose inputs didn&amp;rsquo;t change: code generation, asset processing, test fixtures, site builds, data preparation. Each step is a few seconds or minutes, and it adds up on every push and every laptop.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Contact</title>
      <link>https://bxm.net/contact/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/contact/</guid>
      <description>&lt;p&gt;Bug reports, feature requests and pull requests are welcome on &lt;a href=&#34;https://github.com/softdevstudio/bxm/issues&#34;&gt;GitHub&lt;/a&gt;. That&amp;rsquo;s the fastest way to get something fixed, and other people can see the answer.&lt;/p&gt;&#xA;&lt;p&gt;For anything else, write to &lt;strong&gt;&lt;a href=&#34;mailto:info@bxm.net&#34;&gt;info@bxm.net&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The project would especially like to hear from:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;People writing another Canon implementation&lt;/strong&gt;, in any language, who find a corner of the &lt;a href=&#34;https://bxm.net/reference/&#34;&gt;spec&lt;/a&gt; that could be read two ways.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Teams trying Memo in CI&lt;/strong&gt;, about what they wrapped, how much time it saved and what got in the way.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Anyone who signs or hashes structured data&lt;/strong&gt; and has been bitten by two systems writing the same thing differently.&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Download BXM</title>
      <link>https://bxm.net/download/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/download/</guid>
      <description>&lt;p&gt;Each archive holds both tools, &lt;code&gt;bxm-canon&lt;/code&gt; and &lt;code&gt;bxm-memo&lt;/code&gt;, plus the Canon library and C header, the format spec with its test vectors, and the license files. The links always point to the latest release.&lt;/p&gt;&#xA;&lt;div style=&#34;overflow-x:auto&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;System&lt;/th&gt;&#xA;          &lt;th&gt;Download&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Linux, x86-64&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://github.com/softdevstudio/bxm/releases/latest/download/bxm-linux-amd64.tar.gz&#34;&gt;bxm-linux-amd64.tar.gz&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Linux, ARM64&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://github.com/softdevstudio/bxm/releases/latest/download/bxm-linux-arm64.tar.gz&#34;&gt;bxm-linux-arm64.tar.gz&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;macOS, Apple silicon&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://github.com/softdevstudio/bxm/releases/latest/download/bxm-darwin-arm64.tar.gz&#34;&gt;bxm-darwin-arm64.tar.gz&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;macOS, Intel&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://github.com/softdevstudio/bxm/releases/latest/download/bxm-darwin-amd64.tar.gz&#34;&gt;bxm-darwin-amd64.tar.gz&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Windows, x86-64&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://github.com/softdevstudio/bxm/releases/latest/download/bxm-windows-amd64.zip&#34;&gt;bxm-windows-amd64.zip&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;To check a download, compare it with &lt;a href=&#34;https://github.com/softdevstudio/bxm/releases/latest/download/SHA256SUMS&#34;&gt;SHA256SUMS&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;canon-for-javascript&#34;&gt;Canon for JavaScript&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;code&gt;bxm-canon&lt;/code&gt; package for Node 18+ and browsers is attached to every release:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Quick Start</title>
      <link>https://bxm.net/quick-start/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/quick-start/</guid>
      <description>&lt;p&gt;Five minutes with each tool. First &lt;a href=&#34;https://bxm.net/download/&#34;&gt;download&lt;/a&gt; the archive for your system and put &lt;code&gt;bxm-canon&lt;/code&gt; and &lt;code&gt;bxm-memo&lt;/code&gt; on your &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bxm-canon&#34;&gt;BXM Canon&lt;/h2&gt;&#xA;&lt;p&gt;Write the same data two ways and hash both:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;name&amp;#34;:&amp;#34;bxm&amp;#34;,&amp;#34;tags&amp;#34;:[&amp;#34;a&amp;#34;,&amp;#34;b&amp;#34;],&amp;#34;n&amp;#34;:3}&amp;#39;&lt;/span&gt; &amp;gt; a.json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{ &amp;#34;n&amp;#34;: 3, &amp;#34;tags&amp;#34;: [&amp;#34;a&amp;#34;, &amp;#34;b&amp;#34;], &amp;#34;name&amp;#34;: &amp;#34;bxm&amp;#34; }&amp;#39;&lt;/span&gt; &amp;gt; b.json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bxm-canon hash --text a.json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bxm-canon hash --text b.json&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The two hashes are the same, because both files hold the same value and Canon has one encoding for it.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Reference</title>
      <link>https://bxm.net/reference/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/reference/</guid>
      <description>&lt;p&gt;Every command and flag of both tools, and the Canon format in brief. The full format is in &lt;a href=&#34;https://github.com/softdevstudio/bxm/blob/main/spec/CANON.md&#34;&gt;spec/CANON.md&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bxm-canon&#34;&gt;bxm-canon&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bxm-canon encode [FILE] [-o OUT]     Canon text (JSON) in, canonical bytes out&#xA;bxm-canon decode [FILE] [--pretty]   canonical bytes in, Canon text out&#xA;bxm-canon fmt [FILE] [--pretty]      text in, the one normal text form out&#xA;bxm-canon check FILE...              exit 0 only if every file is canonical bytes&#xA;bxm-canon hash [FILE] [--text]       SHA-256 of the canonical bytes&#xA;bxm-canon diff A B [--text]          paths that differ between two values&#xA;bxm-canon version&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;FILE&lt;/code&gt; defaults to standard input, and &lt;code&gt;-&lt;/code&gt; also means standard input. &lt;code&gt;--text&lt;/code&gt; tells &lt;code&gt;hash&lt;/code&gt; and &lt;code&gt;diff&lt;/code&gt; that the inputs are Canon text rather than canonical bytes. &lt;code&gt;-o&lt;/code&gt; writes to a file instead of standard output.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Use Cases</title>
      <link>https://bxm.net/use-cases/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/use-cases/</guid>
      <description>&lt;p&gt;Where BXM earns its place, with a worked case study for each. Every case study is a script in the &lt;a href=&#34;https://github.com/softdevstudio/bxm&#34;&gt;repository&lt;/a&gt; under &lt;code&gt;examples/case-studies&lt;/code&gt;. Its recorded output is in &lt;code&gt;test/results/case-studies&lt;/code&gt;, and you can run it again yourself.&lt;/p&gt;&#xA;&lt;h2 id=&#34;bxm-canon&#34;&gt;BXM Canon&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Signatures and hashes across languages.&lt;/strong&gt; One service signs data and another checks it, each in its own language. With Canon both sides sign the same bytes, so the check only fails when the data changed. &lt;a href=&#34;https://bxm.net/one-order-built-in-python-javascript-and-by-hand-gives-three-json-hashes-and-one-canon-hash/&#34;&gt;One order built in Python, JavaScript and by hand&lt;/a&gt; gave three JSON hashes and one Canon hash. Python&amp;rsquo;s signature over its JSON failed in JavaScript, and the one over the Canon bytes passed.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
