The issue was titled “fix(release): add license compliance artifacts.” That sounds small. It was not.
FireCrab is a self-hosted microVM cloud built around AWS Firecracker. Its release process ships host binaries, a frontend, installer helpers, Firecracker tooling, and M2Image guest operating systems. Once you look at that as a distribution event instead of merely a build event, the compliance surface gets big very quickly.
#176 called out missing host notices, a GPL-covered helper, incomplete transitive attribution, Firecracker notice preservation, per-image SBOMs, real kernel/package versions, and matching source for GPL-covered guest software. The first mistake would have been treating that list as a pile of files to copy.
The patch needed a release contract
A weak fix would have copied LICENSE into a tarball, generated a notice file, and stopped there.
That would have addressed the visible symptom while leaving the real problem intact: nothing connected the thing
being distributed to the evidence required to distribute it responsibly.
So the host side became a release-time inventory. Cargo and frontend runtime dependencies were classified, build/test-only packages were separated, notices were generated mechanically, and missing or clearly incompatible runtime declarations became a hard failure instead of documentation debt.
The host bundle itself changed meaning. It now had a defined compliance payload: FireCrab’s license, generated third-party notices, a machine-readable inventory, the GPL text required by the release tooling, and preserved upstream Firecracker notices.
Observe
Read real lockfiles, package databases, and built guest images.
Describe
Produce transitive attribution, SPDX, and package→source identity.
Package
Put legal evidence and a frozen source plan inside the artifact.
Materialize
Retrieve exact corresponding source and hash the bytes.
Publish
Upload source first; make the catalog visible last.
The guest images made it a supply-chain problem
FireCrab’s M2Images contain complete operating-system package sets: Alpine, Ubuntu, and Rocky. Kernels, BusyBox, libc, networking tools, package-manager components, and a long tail of libraries all become part of the shipped artifact. A repository-root notice cannot tell you what a particular image actually contains.
The build therefore started producing SPDX 2.3 from the package database inside the built image itself. Every installed binary package gets a source identity or an explicit narrow non-source disposition. The source plan is frozen into the artifact so later publication cannot silently reinterpret what was built.
That immediately found real gaps. The first Alpine proof had zero guest legal files. The answer was not to weaken the check; the image gained Alpine’s packaged SPDX license-text corpus. Rocky found a different weakness: an early validator encoded package counts as constants. When the repository moved, the validator failed even though the implementation was correct. The magic numbers were replaced with structural invariants.
The unit of work was no longer the patch. It was the proof.
Phase Blaster: make the validator hostile
I did not want the project’s own CI to be the only place where the logic was invented, exercised, and declared correct. I wanted an external validation plane whose job was to attack the assumptions from outside the normal release path.
I called that harness the Phase Blaster. It ran the policy tests in a disposable Python container and treated the release contract adversarially. Complete bundles had to pass. Zero legal evidence, missing source identity, malformed package metadata, the wrong SPDX version, and tampered indexed license bytes had to fail. Deterministic rebuilds had to remain deterministic.
The useful thing about the Phase Blaster was that it kept finding work. Alpine source recipes needed a writable scratch workspace while the pristine recipe remained evidence. Ubuntu retrieval had to preserve exact source versions. Rocky needed bounded concurrent SRPM fetching instead of a snapshot-specific count. Each failure made the release contract stronger.
“Source available somewhere” was not enough
Provenance can tell you where a package came from. That is useful, but it is not the same thing as publishing the matching source next to the binary artifact. So the M2Image bundle freezes a package→source publication plan at build time.
A source materializer consumes that plan and retrieves the exact units required by the built image: Alpine recipe state and
distfiles, exact-version Ubuntu source packages, and Rocky source RPMs. The resulting .sources.tar.zst is indexed
and hashed. The release catalog binds binary and source objects independently by SHA-256 and size.
Publication ordering is fail-closed: source is uploaded first, the binary follows, and catalog.json becomes visible
last. A consumer cannot discover a new M2Image through the catalog while its source sibling is missing.
No discoverable M2Image release without the exact source artifact required by the frozen build plan.
Then the proof moved into FireCrab’s own release path
An external validator is useful, but a compliance subsystem that works only in a special harness is still optional. The final pass wired the SBOM, legal-bundle, source-package, tamper, and publication contracts into FireCrab’s native Release Build compliance job.
ef0002b: normal CI and the complete Release Build both passed, including the release-compliance contracts and host archive checks.The submitted SHA passed formatting, Clippy, tests and coverage, rustdoc, frontend, installer integration, distro dependency smoke, x86_64 and aarch64 builds across GNU and musl, all four host bundles, archive-member verification, and runtime smoke. Only then did I open the upstream pull request.
Then upstream answered
PR #190 merged into FireCrab on August 27. Before merging it, the maintainer created follow-up issues #199, #200, and #207 rather than treating the compliance work as finished. That is the part I care about most: the patch did not land as a one-off pile of legal artifacts. It became a seam the project could keep extending.
There was another small signal I want to preserve exactly because it belongs to the project’s own voice. After the Clippy warning gate landed in #189, the maintainer wrote: “Happy Crab! 🦀” I am leaving the phrase as-is. Open source has enough flattened corporate language already.
Merged
Release compliance became upstream behavior, not an external proposal.
Baseline
The Clippy warning baseline refresh merged cleanly after warnings fell from 53 to 45.
OCI evidence
Arbitrary OCI imports now have an open path toward SPDX 2.3 generated from apk, dpkg, or RPM state.
Boot proof
The open M2Image CI fix drives the real MicroRegistry install path and has passed six of six guest boots.
Local trust
Host-local MicroRegistry packages are being wired into the same checksum-before-trust model.
#210 is the clearest continuation of the original idea. Instead of limiting evidence generation to curated M2Images, it moves the boundary to arbitrary OCI imports: inspect the merged root filesystem before FireCrab mutates it, detect apk/dpkg/RPM package databases as data, generate SPDX 2.3, and persist the result under a stable compliance path. It also refuses to follow symlinked package-database paths outside the imported rootfs and keeps unknown or distroless images usable by making unsupported package managers warning-only rather than turning evidence collection into a false compatibility gate.
#209 attacks a different class of drift. CI had stopped exercising the actual M2Image distribution path and could report success around alias collisions. The proposed fix drives the canonical two-phase MicroRegistry package/install flow and verifies that the requested image really became installed. Its forced validation passed six of six boots across two Ubuntu hosts and Alpine, Ubuntu, and Rocky guests.
#197 takes the same instinct into host-local images: verify the staged package SHA-256 before trusting embedded metadata, then require the template identity to agree with the local catalog row before handing the image to the existing installer. Different feature, same underlying rule: do not trust a name when you can bind the thing to evidence.
The release ticket did not end at merge. It taught the project where to put the next proof.
The interesting part is not who typed 4,367 lines
Implementation leverage changes what one person can attempt, but it does not remove the judgment problem. It makes the judgment problem more important. What is the invariant? Which failure is meaningful? Which green check is ceremonial? When is a test protecting a policy, and when is it merely memorizing yesterday’s package count?
The Phase Blaster made that separation useful. Implementation could move quickly while the validator stayed hostile. The result was not merely more code. It was a chain of evidence that kept forcing the implementation to become more precise.
One issue became an operating model
The release model is simple to say even though it took a lot of machinery to make real: observe the actual distribution → generate evidence → freeze source identity → materialize exact source → hash it → publish source first → expose the catalog last.
What changed after merge is that this stopped being only the story of #176 and #190. The same pattern is now showing up in OCI import, MicroRegistry installation, CI boot verification, and local package trust. That is a much stronger outcome than getting one large PR accepted. The architecture is reproducing itself.
A boring-looking release ticket hid a real architecture problem. The useful move was to define the proof before declaring the patch done — and then leave enough structure behind that the next proof had somewhere obvious to go.
This is a technical field note, not legal advice. The mechanical gates and source-publication machinery are engineering controls; license sufficiency ultimately depends on the applicable licenses and distribution facts.