Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Synth

A zndx-constellation project: a federated gRPC engine with thin CLI, TUI, and MCP clients, a keiretsu-themed web UI with ghostty terminal control, and an airgap-ready Zarf deployment path.

Scope decisions (2026-08-03):

  • Federation happens only via the signals-protocol (zndx.engine.v1.Engine); Apache Kudu, Atlas, and Ranger integration is deliberately deferred to the signals project.
  • Submodules live under components/ (ratified over the external/ naming used by gaius/atelier): oss-deluge, kvasir, signals-protocol.
  • Secrets are declared with secretspec and stored via SOPS/age.
  • SBOM presence is asserted by the Zarf closure gate — a deliberate raise over the older repos.

Engine-First

The doctrine, inherited from gaius: the engine is the nervous system; CLI, TUI, and MCP are thin clients. A client does exactly three things:

  1. parse input,
  2. await client.call(service, action, params),
  3. format output.

No business logic in clients, no local algorithms, no engine-bypassing fallbacks, no heavy dependencies (models, embedders). The CLI doubles as the verification harness: every engine feature must be reachable and verified through synth-cli.

The client layer (src/synth/client/) is the only import path clients take: a generic GrpcEngineClient.call() plus typed proxies.

Federation

Synth federates via the signals-protocol (components/signals-protocol), never via direct integration with peer engines’ native surfaces.

The core law (learned 2026-07-03, first live cross-engine call): gRPC method paths embed package+service, so a wire-identical peer still returns UNIMPLEMENTED if only the native service is registered. Therefore serve() registers both servicers on one port:

  • synth.engine.SynthEngine — the native, project-internal surface (src/synth/engine/proto/synth_engine.proto);
  • zndx.engine.v1.Engine — the shared federation face (Complete / Status / Remediate).

Shared-host lattice

EnginegRPC portvLLM range
gaius500518080+
aegir501518100+
atelier502518200+
synth503518300–8399

Ratifying synth’s row in the signals-protocol adopters table is a pending follow-up (additive change to the submodule’s spec, PR’d upstream).

GPU co-tenancy uses the advisory lease directory /tmp/zndx-gpu-leases; capability requests are forwarded to peers in preference to moving GPUs.

Development Environment

devenv (Nix) is the substrate; devenv.nix stays a pure service declaration (operational logic lives in the justfile).

Service/processPort(s)Notes
postgres 165566pgvector; DB synth; lattice: cyberphy 5438 · gaius 5444 · signals 5455 · atelier 5533 · aegir 5555
qdrant (process)6365 http / 6366 grpcreadiness probe on /healthz; house norm is a process, not a service
rustfs9000/9001 (allocated)MinIO replacement; always read RUSTFS_ADDRESS etc. at runtime — devenv allocates the real ports

First devenv shell builds RustFS from source (flake input github:rustfs/rustfs) — a one-time cost unless the store already has it.

Secrets: declared in secretspec.toml, provided per environment (devenv.yaml defaults to the dotenv provider; SOPS/age for committed encrypted files under config/secrets/).

Configuration

HOCON config/base.conf is the single source of truth. Env vars enter only via ${?VAR} capture; application code reads synth.config.load_config() and never os.environ.

The ritual:

just resolve-config   # materialize -> build/config/synth.{env,json}
just preflight        # deny/warn validation (bin/preflight.py)
just policy           # conftest gate (policy/environment/synth.rego)

Preflight and the rego policy express the same deny/warn taxonomy, so the gates hold both in-process and in CI. Every deny message names its remediation.

Deployment (Zarf)

Airgap-ready packaging per the cyberphy laws — CLOSURE, CONSERVATION, RECONCILIATION, PARTIAL ROLLOUT:

  • Everything the deploy needs is declared once in zarf/artifacts.manifest.json and verified at build time by zarf/scripts/check-closure.py (just zarf-build) — nothing is discovered missing inside the air gap.
  • SBOMs are required. Never pass --skip-sbom; the closure gate asserts the SBOM entry in the built package. This is a deliberate raise over the older repos (aegir skips SBOMs; cyberphy generates but never asserts).
  • Realized *.closure.json files are committed per release as provenance.
  • Size budget: 2 GiB hard (GitHub release asset limit), warn at 1.75 GiB.

Deployment modalities follow the house taxonomy — laptop (k3d + Tilt) → workstation (RKE2) → airgap — with policy/k8s/<modality>/ gating each as it lands.

Open item: cosign/GPG signing (the whole constellation is SHA256SUMS-only today).