qontinui-types
Canonical DTO types shared across the Qontinui stack.
Rust is the single source of truth. TypeScript and Python bindings are
generated from the JSON Schemas emitted by schemars on these types; see
qontinui-schemas/scripts/ and the just generate-types task.
Conventions
- Every field that is optional on the wire uses
#[serde(default, skip_serializing_if = "Option::is_none")]so absence andnullare distinguishable and round-trip faithfully. - Dates and times are ISO 8601
Strings. Do not introducechrono::DateTime<Utc>here — it complicates JSON Schema output and couples the DTO layer to a particular chrono version. The types crate is a wire-format layer, not a domain model. - UUIDs are
Strings (wire-format), notuuid::Uuid. Same reason. - Polymorphic step arrays use
Vec<serde_json::Value>. JSON Schema emits{ "type": "array", "items": {} }→unknown[]in TS,list[Any]in Python. Typed step discriminated unions are a future migration (Wave 4).
Drift between these Rust sources and the checked-in TS/Python bindings is
caught in CI by .github/workflows/schema-drift.yml, which regenerates
the bindings on every PR touching rust/src/** and fails if git diff
reports any non-timestamp change. The codegen toolchain (Tauri Linux deps,
datamodel-code-generator version) is pinned in that workflow — bump the
pins deliberately when upstream output changes.