Sovereign CI — Build Infrastructure
LIVE push-to-deploy pipeline: Forgejo → sporeGate build → sandbox validate → BLAKE3 depot → HTTPS serve. 35 binaries across 3 platforms. Zero human intervention.
Overview
Status (Wave 155n): Sovereign CI is LIVE. sporeGate is the build authority — push to Forgejo triggers auto build → sandbox validate → depot push → HTTPS serve. 35 binaries (16 musl + 4 gnu + 15 Windows), all BLAKE3 verified. J9+J10+J11 jelly strings KILLED — zero human intervention for musl builds. sporeGate is 11/11 HEALTHY.
Every ecoPrimals binary is built from source on sovereign infrastructure. No GitHub Actions for production builds. No cloud CI. No third-party artifact registry. sporeGate pulls from Forgejo (git.primals.eco), cross-compiles for three target triples, computes BLAKE3 checksums, publishes to the depot, and broadcasts mesh.publish depot.updated so consumer gates auto-fetch.
Build Pipeline
Forgejo (git.primals.eco)
│
│ golgi cascade timer (15-min quorum)
▼
Builder gate (sporeGate / eastGate / any build_authority)
│
├── membrane plasmid.harvest (manifest-driven)
│ ├── 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})
│
└── songBird mesh.publish { topic: "depot.updated" }
│
├── mesh.subscribe on all reachable peers
├── Consumer gates: membrane plasmid.auto_fetch (rate-limited)
└── depot-verify validates BLAKE3 integrity
Binary Inventory (Wave 155n)
15 primals compiled to 35 depot binaries across 3 platforms:
| Target | Binaries | Gates |
|---|---|---|
x86_64-unknown-linux-musl | 16 | eastGate, sporeGate, westGate, strandGate, ironGate, flockGate |
x86_64-unknown-linux-gnu | 4 (GPU trio + biomeOS) | strandGate (GPU compute) |
x86_64-pc-windows-gnu | 15 | blueGate, swiftGate, northGate |
Per-binary sizes (x86_64-musl):
| Binary | x86_64-musl | aarch64-musl | Ratio |
|---|---|---|---|
| petalTongue | 28 MB | 25 MB | 90% |
| Songbird | 23 MB | 20 MB | 90% |
| biomeOS | 20 MB | 18 MB | 92% |
| sweetGrass | 13 MB | 14 MB | 101% |
| ToadStool | 13 MB | 9.7 MB | 75% |
| BearDog | 11 MB | 8.8 MB | 80% |
| NestGate | 8.1 MB | 7.0 MB | 87% |
| coralReef | 7.7 MB | 6.8 MB | 84% |
| rhizoCrypt | 7.5 MB | 6.1 MB | 81% |
| barraCuda | 5.4 MB | 4.3 MB | 79% |
| loamSpine | 4.5 MB | 3.8 MB | 85% |
| Squirrel | 4.3 MB | 3.4 MB | 78% |
| nucleus_launcher | 4.2 MB | 3.4 MB | 81% |
| sourdough | 3.0 MB | 2.6 MB | 83% |
| skunkBat | 2.8 MB | 2.4 MB | 85% |
| Total | 153 MB | 130 MB | 85% |
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:
- Binary discoverable from workspace root:
cargo build --release --target $TRIPLE --bin $slug - No special linker requirements beyond the global
.cargo/config.toml - Toolchain declared in
rust-toolchain.toml - Binary name = primal name lowercase with no separators
All 15 primals meet this convention. Three historical divergences are now resolved via ecosystem_manifest.toml build metadata:
- CI-DIV-01: biomeOS needs
--package biomeos-unibin— encoded in[build.biomeos] - CI-DIV-02: skunkBat needs
--package skunk-bat-server— encoded in[build.skunkbat] - CI-DIV-03: NestGate uses project
.cargo/config.tomlfor linker config — resolved Wave 133a,cargo_config = truein[build.nestgate]
plasmid.harvest reads these entries from the manifest instead of relying on hardcoded bash workarounds.
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. Two timers per gate:
- cascade-pull.timer (every 4h): full repo sync + harvest + fetch
- cascade-sense.timer (hourly): convergence monitoring, staleness detection
golgi (VPS)
→ pulls all 17+ repos from Forgejo
→ writes heads/golgi.toml (its local HEADs, SHA-validated)
→ 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
→ SHA validation: rejects truncated commits (00000... tails)
→ pushes wateringHole (FF-only pull first, no conflict)
mesh.status enrichment:
→ scans heads/*.toml for files older than 24h
→ reports stale_peers in mesh.status response
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.
Crash-Loop Breaker (Wave 150x)
cellMembrane provides membrane gate.crash-loop — a self-recovery system that detects and stops runaway systemd services. The crash-loop breaker scans all primal services and detects restart spirals.
Real-world validation: biomeos-beacon accumulated 29,081 restarts before the breaker was shipped. The fix is structural:
| Problem | Fix |
|---|---|
StartLimitIntervalSec in [Service] | Moved to [Unit] (where systemd reads it) |
WorkingDirectory missing | Validated at install time |
| No restart ceiling | CrashLoopReport scan + disable logic |
The breaker runs at bootstrap/preflight and as an operator command. It detects services with restart counts exceeding threshold, stops the crash-looping service, reports to the operator, and prevents resource exhaustion.
systemd Hardening
Every primal service runs under systemd with defense-in-depth:
| Hardening | Purpose |
|---|---|
ProtectSystem=strict | Read-only root filesystem |
PrivateTmp=yes | Isolated /tmp |
NoNewPrivileges=yes | Prevent privilege escalation |
MemoryDenyWriteExecute=yes | W^X enforcement |
DNSSEC
All three ecosystem domains are DNSSEC-signed:
| Domain | Purpose | DNSSEC |
|---|---|---|
primals.eco | Intra-membrane (gate-to-gate) | Signed |
primal.eco | Inner membrane (public services) | Signed |
nestgate.io | Data service point (NestGate CAS) | Signed |
Related
- Tower Atomic — the transport stack that Sovereign CI builds and deploys
- Deployment Model — how binaries flow from depot to gates
- Living Systems — what’s actually running right now
- Gate Mesh — Live Topology — how gates connect
- Ecosystem Coordination — wateringHole standards and operational documents
- provision-golgi.sh — the VPS provisioning script in wateringHole