Runtime substrate trait — the interface (design)
korp_collectors::runtime (feature daemon) is the object-safe interface that decides WHERE a collector daemon (or, later, a knut pipeline) runs, decoupled from its logic. A collector's behaviour is substrate-agnostic (Collector against CollectorCtx); this trait is the seam that spawns it. See the workspace design runtime-aortas-design-2026-07-29.md.
Leaf discipline
This crate depends on neither korp nor jera nor kube, so the trait pulls no new deps — pure serde + anyhow (both already under daemon). The concrete implementations (JeraRuntime, KubeRuntime) live in korp, which owns jera / aegir / skidbladnir. Keeping the interface here lets both korp and facett-demo consume it without the facett ⇄ korp cycle.
The shapes
RuntimeKind—Jera(metal in-process jera DAEMON job — default) ·JeraDistributed(DESIGN-ONLY, a stubbedTODO) ·Kube(full Kubernetes via kube-rs SSA, zero-shell).UnitSpec— the backend-neutral description of a runnable:name,UnitKind(Daemon→ Deployment/StatefulSet ·Cron→ CronJob ·OneShot→ Job),Entry(InProcess{collector}= the Jera-metal path ·Image{image,argv}= the Kube/distributed path,korp collector run <name>),config(a ConfigMap on Kube / theCollectorCtxconfig on metal),StorageSpec(durable dir ⇒ PVC + StatefulSet; S3 bucket ⇒ the rustfs Service),Resources, env / secret_env, image, namespace. Builder + serde round-trip.Handle— opaque{runtime, name, id}(the jerajob_id/ the k8s<ns>/<kind>/<name>) forstop/status.RunStatus—{phase, healthy, logs}— the live phase label + a health flag.
The trait
pub trait Runtime: Send + Sync {
fn kind(&self) -> RuntimeKind;
fn start(&self, spec: &UnitSpec) -> Result<Handle>; // idempotent where the substrate allows
fn stop(&self, h: &Handle) -> Result<()>; // idempotent
fn status(&self, h: &Handle) -> Result<RunStatus>;
fn reconcile(&self, desired: &[UnitSpec]) -> Result<()>; // the Settings toggle / matrix ▶Run route
}
Object-safe (&self, no generics), so a Box<dyn Runtime> selects the substrate at runtime from the persisted per-collector choice. Proven by a mock in the crate tests (runtime_is_object_safe_via_a_mock) plus key/serde round-trips.