Quickstart
Run a Sovereign Engine node, write through the SDK, and read it back. This guide mirrors the operator + developer getting-started paths from the engine source.
1. Provision a mesh CA (dev)
Use pkg/crypto's dev-mesh CA to mint a CA and per-node leaves (or supply your own PKI and point --tls-cert --tls-key --tls-ca at it):
ca, err := crypto.NewMeshCA()
leaf, err := ca.IssueLeaf(nodeID, "localhost")
crypto.WriteCAPEM(ca, "ca.crt")
leaf.WritePEM("leaf.crt", "leaf.key")Dev mesh only
This is a DEV mesh CA, not production PKI — offline root, intermediate CAs, HSM-backed key custody, OCSP/CRL revocation, and automated rotation are named as post-launch work (ADR-0006).
2. Derive node identity
Pass --identity-seed (an Ed25519 seed); the nodeID is the first 16 bytes of the derived pubkey and must equal engine.localNodeID.
3. Start a node
cmd/sovereign-node \
--bind :443 \
--peers peer1:443,peer2:443 \
--tls-cert leaf.crt --tls-key leaf.key --tls-ca ca.crt \
--metrics-addr :9100 \
--control-addr :4433 \
--arena-mib 4096 \
--wal-path /var/lib/sovereign/wal \
--lsm-root /var/lib/sovereign/lsm \
--gossip-tick 1s \
--batch-size 100Defaults are byte-identical-Day-15 conservative: pruning OFF, reaper OFF.
4. Opt into durability & compaction
Once you trust the T_gc floor:
--wal-checkpoint-interval N \
--compaction-prune-enable \
--compaction-prune-horizon-ns <T_gc> \
--compaction-prune-backoff-ns <backoff>Add --compaction-reap-enable once you trust your storage layer's existence-probe — the reaper never auto-ONs.
5. Observe
Scrape /metrics for sovereign_* (labelled) and supremum_* (cumulative) series; hit /livecheck for liveness; arm --otel for OTel export to the operator log.
6. Write & read via the SDK
client, _ := sovereign.DialWithCerts(":4433", "leaf.crt", "leaf.key", "ca.crt", "node-1")
// Originator path: routes through Gossiper.InsertLocalEvents → bridge.PutLocal (WAL fsync)
err := client.InsertLocal("entity-1", `{"v":42}`)
// Get — Payload only on the originator; peers return the digest, not a value
res, _ := client.Get("entity-1")
// res.PayloadDigest is always set; res.Payload is non-empty only on the originator
root, _ := client.MerkleRoot()Honest boundary (Ruling 3)
GetResult.Payload is non-empty only on the originator (cache hit); peers return Payload=="" + PayloadDigest!="" because the engine stores only the PayloadDigest on a joined CRDTEntry (TestClientGetOnPeerReturnsDigestNotValue). The SDK does not claim linearizability — InsertLocal returns at LOCAL-apply; peer convergence is eventual (next gossip sweep).
Direct engine use
For direct engine use, the pkg/sync public surface is:
eng, err := sync.NewDeltaCRDTEngine(nodeID, initialCounter, arenaSize)
dot := eng.InsertLocal(entityID, entry) // 0 allocs/op hot path
eng.Join(delta) // FROZEN merge-union
remoteDigest := eng.GenerateDigest() // IBLT
delta := eng.GenerateDelta(remoteDigest) // minimal missing set; defer delta.Release()
eng.ApplyCRDTDeltaEvent(wire) // wire-integrity + Join
wire, _ := sync.BuildCRDTDeltaEvent(entityID, payload, entry)Next
- Integration & Usage → — the full flag reference, control surface, and honest readiness assessment.
- Primary Use Cases → — where the engine excels.