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.
The functional-spec-contract v0 artifact set (frozen 2026-06-13)
Three modules form the keystone contract for the website → mobile
regeneration program (2026-06-13-functional-spec-contract.md):
- [
functional_spec] — Artifact 1, the backend-agnostic [functional_spec::FunctionalSpec] that comprehension writes and generation reads. Itsui_states/navigationreuse [ir]::{IrState, IrTransition}(a literal type-level superset of the IR). - [
completeness_verdict] — Artifact 2, the Completeness Rubric + [completeness_verdict::CompletenessVerdict]. Borrows theDriftVerdictfield vocabulary and embeds [spec_check::SpecCheckResult] for the UI dimension. - [
priorities_profile] — Artifact 3, the [priorities_profile::Profile] that parameterizes the generators.
v0 stability contract: the specVersion / profileVersion fields are "0".
Until they bump to "1", changes are additive-only — new optional fields and
new enum variants only, never a rename, removal, or type change of an existing
field. (deny_unknown_fields is deliberately omitted on these three so a reader
tolerates a forward document.) Downstream plans #1 (app-gen), #2 (backend-gen),
and #3 (comprehension) build against this frozen interface in parallel.