Apache / release assurance / field notes

Why Apache Matters
The Infrastructure Beneath the Infrastructure.

I spent a concentrated stretch chasing one question through Apache release infrastructure: where should supply-chain evidence become true in the first place? The answer moved from a Go binary, to a Conan graph, to artifact-bound attestations, and finally to eighteen lines in the ASF parent POM.

August 27, 2026 Robert McConnell Release engineering ~13 min read

Apache projects in this post · official project links

Software supply-chain security has an unfortunate tendency to become a shopping list.

Add a scanner. Add a dashboard. Add another workflow. Add a JSON file nobody knows whether to trust.

What interested me this week was a different question: where should the evidence become true in the first place? I ended up chasing that question through a burst of Apache pull requests, and the code got smaller as the leverage got larger.

The path was not really about SBOM generation. It was about authority. A filename can claim one version while a binary embeds another. An SBOM can list packages without making clear which build graph it describes. A container tag can move. A signature can prove who signed some bytes without proving those are the bytes the consumer thinks they are.

Supply-chain evidence becomes useful when every claim has an authoritative subject.
The path up the assurance stackidentity → inheritance
01 / IDENTITY

Iceberg

Prove which release binary this actually is, without rebuilding after the vote.

02 / GRAPH

Celix

Prove which dependency resolution an SBOM actually represents.

03 / BINDING

Camel K

Bind source, binaries, images, SBOMs, digests and attestations together.

04 / POLICY

ASF Parent

Put the evidence primitive where downstream Maven releases already inherit behavior.

01 — Release identityFix the claim without changing the object.

The first useful seam showed up in the Apache Terraform Provider for Iceberg. The release-candidate binaries were promoted bit-for-bit after the Apache vote. That is exactly the trust boundary you want to preserve. But Go 1.24 and newer stamps module version information from the VCS state it sees during the build, so a final artifact named as the final release could still report the RC tag in its embedded build info.

The tempting fix would be to rebuild after the vote. That would make the metadata look prettier by changing the thing the vote covered. Wrong direction.

The patch instead changes only the local VCS view during the RC build: an ephemeral final-version tag exists at the same commit, Go sees the final semantic version, and the binary still records the exact voted source revision. Then every packaged binary is independently inspected with go version -m to verify the module version, the exact vcs.revision, and vcs.modified=false.

Release identity invariantsame SHA · same bytes
iceberg / release provenance
# The vote covers the RC commit and its built convenience binaries.
vX.Y.Z-rcN commitlocal-only vX.Y.Z tag at the SAME SHA
        ↓
build voted convenience binaries
        ↓
go version -m
  module version  = vX.Y.Z
  vcs.revision    = exact RC SHA
  vcs.modified    = false
        ↓
promote the same bytes after the vote

That became the discipline for everything that followed: identify the authoritative object first, then make the metadata describe it honestly.

02 — Dependency graphAn SBOM needs an honest boundary.

Apache Celix made the next problem explicit. Celix already had a real Conan dependency graph. The information existed before the SBOM did. The first proposal, #844, resolved one documented Linux / Release / full-feature graph, preserved the resolution as a conan.lock receipt, and generated CycloneDX from that same graph.

The important part was not pretending that one configuration represented every platform, debug mode, sanitizer build, test dependency, or system-package path. An inventory only becomes evidence when you can answer inventory of what?

An SBOM without a statement of which build graph it describes is inventory-shaped ambiguity.

Then the reviewer made the implementation better. #844 was closed without merge after feedback that Conan's native CycloneDX deployer could do the job with a much simpler conan install ... --deployer=cyclone_1.6 path. That is not a failure of the idea. It is almost a perfect demonstration of it.

Within minutes, #845 superseded it and took the smaller seam: the existing Conan CI now invokes the built-in cyclone_1.6 deployer directly, publishes sbom/sbom-cyclonedx-1.6.json as the celix-conan-sbom artifact, and carries no custom SBOM generator or lockfile handling.

Status note: Celix #845 is open and mergeable as of this update. It supersedes #844 and directly incorporates the review feedback rather than defending the larger implementation.

That change also sharpens the claim boundary. The lockfile in #844 was useful as a resolution receipt, but #845 deliberately removes it to keep this patch scoped to native SBOM generation. If exact dependency-resolution provenance is needed later, it can be added as a distinct evidence layer instead of being smuggled into the SBOM change. Reproducibility and provenance are related, but they are not the same claim.

03 — Artifact bindingPublishing an SBOM is not the same as binding one.

Apache Camel K #6777 pushed the question farther. The release already had SBOM machinery. The gap was whether the evidence described the actual independently published binaries and container images.

A module-level SBOM sitting beside several release artifacts is useful context. It is not yet a release contract. The stronger design binds every claim to an immutable subject: exact source SHA, embedded binary revision, archive digest, SBOM digest, immutable OCI manifest digest, image SBOM, attestation, and then a deterministic receipt tying the whole thing together.

Artifact-bound release assuranceconsumer-verifiable
camel-k / release-assurance.json
source SHA
  ├─→ client binary → embedded VCS revision
  │                  ├─→ archive SHA-256
  │                  └─→ CycloneDX SBOM SHA-256
  │
  └─→ pushed image → immutable OCI digest
                     ├─→ image SBOM
                     └─→ CycloneDX attestation

all subjects
  └─→ deterministic release-assurance.json
       └─→ keyless signature / attestations
            └─→ consumer-side verifier
                 └─→ TRUST | REJECT

This is the distinction that matters: publishing an SBOM tells me what a tool saw. Binding the SBOM to an immutable artifact tells me what the SBOM is evidence about.

The assurance pipeline also has to obey the discipline it asks of the product. During review, the release tooling itself got tightened: unnecessary credentials were removed for public-image scanning, tool declarations were centralized, and assurance tools were pinned rather than floated. The verifier fails closed on missing, modified, mismatched, or differently attested evidence.

04 — InheritanceThen look one layer up.

Once the lower-level behavior is understood, the next question changes. It is no longer “can this project generate an SBOM correctly?” It becomes: where should correct release behavior live so projects stop repeating it?

That is what made ASF Maven Parent #597 interesting. Apache Maven's own parent already had the prior art: bind the CycloneDX Maven Plugin to the release profile, run makeAggregateBom during package, attach JSON and XML SBOM artifacts, and let normal Maven deployment publish them with the release.

The ASF parent issue asks to generalize that proven behavior one inheritance layer higher. The proposed change does not invent a scanner, a format, a service, or a separate publication channel. Ordinary developer builds do not change. It adds the native evidence generator to the existing apache-release profile.

Apache Maven Parent #5972 files · +18 / −0
18
additions · zero deletions

The smallest patch had the largest blast radius.

One project patch improves one project. A parent-POM patch can change release behavior for downstream projects that already inherit from it. The leverage is architectural, not volumetric.

The actual seamapache-release / package
maven-apache-parent / pom.xml
+ <version.cyclonedx-maven-plugin>2.9.3</version.cyclonedx-maven-plugin>

  <profile>
    <id>apache-release</id>
    <build>
      <plugins>
+       <plugin>
+         <groupId>org.cyclonedx</groupId>
+         <artifactId>cyclonedx-maven-plugin</artifactId>
+         <version>${version.cyclonedx-maven-plugin}</version>
+         <executions>
+           <execution>
+             <goals><goal>makeAggregateBom</goal></goals>
+             <phase>package</phase>
+           </execution>
+         </executions>
+       </plugin>

The hard part was not writing eighteen lines of XML. The hard part was proving those were the right eighteen lines: release-only, compatible with the ASF parent's baseline, aligned with behavior Apache Maven already uses, and attached to the normal release path instead of creating parallel compliance machinery.

That is the point where the whole run snapped into focus. Iceberg established source identity. Celix forced an honest dependency boundary—and then reviewer feedback produced a smaller native follow-up almost immediately. Camel K made the evidence-to-artifact binding explicit. Maven Parent asked where the successful primitive should live organizationally.

The highest-leverage compliance patch may be the one that disappears into inheritance.

05 — The design ruleNative evidence first. External assurance second.

Conan should know the Conan graph. Maven should know the Maven reactor and the artifacts it attaches. Go should know what source revision was compiled. OCI registries should provide immutable digests. CycloneDX should represent inventory. Cosign should bind signed claims to subjects.

An external assurance layer can verify, retain, compare, and reason over those receipts. It should not rebuild every package manager's semantics from scratch.

Reusable patternauthoritative systems → evidence
release substrate / pattern
Find the authoritative subject
  ↓
Find the native system that knows its graph / identity
  ↓
Emit evidence there
  ↓
Bind evidence to immutable artifacts
  ↓
Verify from the consumer side
  ↓
Move successful policy upward to the inheritance point

06 — What this does not proveKeep the claims smaller than the evidence.

None of this means “Apache now has SBOMs everywhere.” Maven Parent #597, Camel K #6777, Iceberg #105, and Celix #845 are open upstream proposals at this update. Celix #845 supersedes the closed, unmerged #844. A single SBOM never represents every possible build configuration unless the build model actually makes that true.

SBOM publication alone also does not prove release integrity. Signatures, provenance, immutable identities, vulnerability analysis, policy evaluation, and independent verification are separate layers. The point is to connect them without blurring their claims.

Open source is especially good at this kind of correction because the architecture is not just something you describe. A maintainer can look at a larger implementation and say, in effect, “the native tool already does this.” The right response is not to defend the lines. It is to take the smaller seam—and, in this case, send the smaller patch right back upstream.

Infrastructure leverage is funny that way. The better you understand the boundary, the less code you may need to own.


An SBOM is a file.
An SBOM bound to a release is evidence.

Evidence generation inherited from the release substrate is infrastructure.

Primary threads

Apache and the Apache project names and logos shown here are trademarks of The Apache Software Foundation. Project marks are shown unmodified solely to identify the referenced projects and link to their official Apache pages.