Skip to content

I0902 — The deployment object becomes typed Rust that refuses nonsense

Parse the canonical deployment object into strongly typed Rust — enums and newtypes rather than strings — and validate it so that a deployment that cannot work is refused before anything is built.

DONE wave 1 · p0 · implementation profile · parallel safe

Part of fly-deployment — The container image is a projection of the repository model, and its smoke is its evidence.

Objective

Parse the canonical deployment object into strongly typed Rust — enums and newtypes rather than strings — and validate it so that a deployment that cannot work is refused before anything is built.

Why

Generation from an unvalidated document produces a valid-looking Dockerfile pointing at a binary that does not exist. The validation is the point at which a deployment mistake costs a test failure instead of a failed production rollout.

Current state

apps/majordomus-cli/src/deploy/ exists and parses the deployment object into typed structures, and apps/majordomus-cli/src/capability/builtin/deploy.rs projects it through the registry. As with I0901 the work reached master without ever being recorded against the issue. Measured on master 6042f4286, 2026-09-10; not marked complete here because this issue's validation has not been rerun against that tree.

Desired state

A deploy module parses the object into typed structures, validates every invariant that can be decided locally, and reports a failure that names the file, the key, what was wrong and what to do.

Scope

  • apps/majordomus-cli/src/deploy

Out of scope

  • Provider projection; that is I0913
  • Any network call, any process spawn, any Fly API access
  • A generic multi-provider trait hierarchy for a single provider

Dependencies

What waits on this

Acceptance criteria

  • Ports, memory, CPU class, machine counts and routes are typed rather than strings, and an invalid value cannot be constructed
  • Validation refuses zero memory, an invalid port, a health or readiness route that no capability registers, a package or binary the workspace does not contain, a build input that does not resolve, and a minimum running count above the machine count
  • Every refusal names the source file, the key, the observed value and the correction
  • Property tests cover the invariants that must hold for any accepted object, not merely the examples in the repository
  • Unit tests cover each refusal

Validation

  • cargo test --workspace --all-features
  • cargo clippy --workspace --all-targets --all-features -- -D warnings

Evidence required

  • typed_parse
  • validation_refuses
  • property_invariants

Evidence

coverstypecommandresultat commit
typed_parsetestcargo test --locked --manifest-path apps/majordomus-cli/Cargo.toml --lib deploy::teststest result: ok. 30 passed; 0 failed (run 2026-10-14 between 07:40Z and 07:58Z on master ce5959db59)ce5959d
validation_refusestestcargo test --locked --manifest-path apps/majordomus-cli/Cargo.toml --lib deploy::teststest result: ok. 30 passed; 0 failed (run 2026-10-14 between 07:40Z and 07:58Z on master ce5959db59)ce5959d
property_invariantstestcargo test --locked --manifest-path apps/majordomus-cli/Cargo.toml --lib deploy::teststest result: ok. 30 passed; 0 failed (run 2026-10-14 between 07:40Z and 07:58Z on master ce5959db59)ce5959d

Risk

Route validation needs the capability registry, which makes the deployment model depend on the index. Reading the registry that already exists is correct; building a second route list to avoid the dependency is not.

Timeline

started
2026-10-14T08:00:59Z
verified
—
completed
2026-10-14T08:01:10Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I0902.yaml. Read it back with majordomus plan show I0902.

Searches the titles and descriptions of every page this site publishes.