Sovereign CI — Build Infrastructure

How ecoPrimals builds, checksums, and distributes 30 binary artifacts across 15 primals and 2 architectures — entirely self-hosted.

Overview

Every ecoPrimals binary is built from source on sovereign infrastructure. No GitHub Actions for production builds. No cloud CI. No third-party artifact registry. The build host (sporeGate) pulls from Forgejo (git.primals.eco), cross-compiles for two target triples, computes BLAKE3 checksums, and publishes to the depot.

Build Pipeline

Forgejo (git.primals.eco)

    │ golgi cascade timer (15-min quorum)

sporeGate — Sovereign CI

    ├── cargo build --release --target x86_64-unknown-linux-musl
    ├── cargo build --release --target aarch64-unknown-linux-musl

    ├── BLAKE3 checksums → checksums.toml

    └── rsync → depot (membrane.primals.eco/depot/{triple}/{binary})

        ├── Gates cascade + pull binaries
        └── depot-verify validates BLAKE3 integrity

Binary Inventory (Wave 133a)

? primals compiled to 30 ecobins — 15 per architecture.

Binaryx86_64-muslaarch64-muslRatio
petalTongue28 MB25 MB90%
Songbird23 MB20 MB90%
biomeOS20 MB18 MB92%
sweetGrass13 MB14 MB101%
ToadStool13 MB9.7 MB75%
BearDog11 MB8.8 MB80%
NestGate8.1 MB7.0 MB87%
coralReef7.7 MB6.8 MB84%
rhizoCrypt7.5 MB6.1 MB81%
barraCuda5.4 MB4.3 MB79%
loamSpine4.5 MB3.8 MB85%
Squirrel4.3 MB3.4 MB78%
nucleus_launcher4.2 MB3.4 MB81%
sourdough3.0 MB2.6 MB83%
skunkBat2.8 MB2.4 MB85%
Total153 MB130 MB85%

All binaries are statically linked against musl libc — no runtime dependencies. The aarch64 binaries run on grapheneGate (Pixel 8a, GrapheneOS) and future ARM nodes.

Build Convention

For a primal to be CI-buildable with zero manual intervention:

  1. Binary discoverable from workspace root: cargo build --release --target $TRIPLE --bin $slug
  2. No special linker requirements beyond the global .cargo/config.toml
  3. Toolchain declared in rust-toolchain.toml
  4. Binary name = primal name lowercase with no separators

Currently 11/14 primals meet this convention. Three require workarounds:

These are documented divergences being converged by upstream teams.

Verification

Any gate can verify its local depot against the published checksums:

spore-validate depot-verify \
  --checksums /path/to/checksums.toml \
  --depot /path/to/depot \
  --arch x86_64-unknown-linux-musl

--partial mode allows incremental verification — pass when all present binaries verify, even if the depot is incomplete. This supports staged rollouts where not all binaries have been pulled yet.

Cascade Flow

The cascade is the heartbeat of the ecosystem. Every 15 minutes:

golgi (VPS)
    → pulls all 17+ repos from Forgejo
    → writes heads/golgi.toml (its local HEADs)
    → runs unify_freshness() → regenerates freshness.toml
    → pushes wateringHole to GitHub (trailing mirror)

Each gate after cascade:
    → writes heads/<gate>.toml with its local repo HEADs
    → pushes wateringHole (FF-only pull first, no conflict)

The write model is conflict-free: wave.toml is sole-writer (overwatch), each gate writes only its own heads/<gate>.toml. No merge conflicts. Ever.