Skip to main content

Crate ironstate

Crate ironstate 

Source
Expand description

ironstate

Verified state machines for humans and AI agents.

A state machine is the set of states something can be in and the legal moves between them. ironstate lets you declare those states and one transition function in plain Rust, then enforces the structure at runtime and verifies it in your tests. The same definition does both jobs, so there is no separate model to keep in sync.

use ironstate::prelude::*;

#[derive(StateMachine, Clone, Debug, PartialEq)]
#[state_machine(initial = Draft, terminal = [Archived])]
enum Article { Draft, Review, Published, Archived }

#[derive(Event, Clone, Debug, PartialEq)]
enum Edit { Submit, Approve, Reject, Archive }

impl TransitionRules for Article {
    type Event = Edit;
    fn transition(&self, event: &Edit) -> Option<Article> {
        use Article::*;
        use Edit::*;
        match (self, event) {
            (Draft, Submit) => Some(Review),
            (Review, Approve) => Some(Published),
            (Review, Reject) => Some(Draft),
            (Published, Archive) => Some(Archived),
            _ => None,
        }
    }
}

let mut article = Machine::<Article>::new();      // starts in Draft
assert_eq!(article.apply(Edit::Submit).unwrap(), Article::Review);

// Look before you leap, cheapest first:
assert!(article.could_apply(&Edit::Approve));     // would it be accepted?
assert!(article.why_not(&Edit::Submit).is_some()); // the typed reason it would not, or None
assert_eq!(article.peek_transition(&Edit::Approve), Some(Article::Published));

// A rejected event is handed back inside the error, so you can retry or re-route it:
let err = Machine::<Article>::restore(Article::Archived).apply(Edit::Submit).unwrap_err();
assert!(matches!(err, TransitionError::TerminalState { .. }));
assert_eq!(err.into_event(), Edit::Submit);

Verification is part of the API. Drop these in a test module and the definition tests itself:

ironstate::analyze!(Article);              // graph analysis: dead ends, unreachable states, dead transitions
ironstate::test!(Article, cases = 1000);   // randomized property testing against your declared invariants

§Cargo features

All three are on by default.

FeatureAdds
derivethe StateMachine/Event derive macros
proptestthe test! property-testing macro (analyze! is always available)
restoreversioned restore: decode a stored {version, payload} envelope and migrate it forward (pulls in serde)

Building a plain in-memory machine with no serialization dependency? Set default-features = false and add back just derive.

§Learn more

New here? The guide is a step-by-step walkthrough from a first machine through aggregates and the event journal. For a complete runnable program, see the release-pipeline example (operator/external-gated states, declared invariants, a pure transition function); the full example set goes on through aggregates and the journal. For what each test layer proves, see docs/testing.md.

§The ironstate family

Licensed under Apache-2.0.

Modules§

analysis_report
Graph-analysis report types produced by analyze!.
prelude
The common imports for defining and running a machine.

Macros§

analyze
Generate a #[test] that runs structural graph analysis on a machine.
test
Generate a #[test] that runs randomized property testing on a machine.

Structs§

Invariant
A named property checked after each transition during test!.
Kind
A compile-time event-kind label.
Machine
A running state machine.
MachineMetadata
A static view of a machine’s structure, built from the derived metadata.
TransitionRecord
What a transition listener is handed after a successful apply.

Enums§

RestoreError
Why a versioned restore failed.
TransitionError
Why a transition was rejected.

Traits§

EventKind
Event metadata read by the runtime and the verification macros.
Invariants
Implemented by a machine that declares domain invariants.
MigrateFrom
A pure, testable upgrade from an older schema to a newer one.
StateMachine
A verified state machine: an enum with a declared initial state, terminal states, and optional per-state event-kind restrictions.
TransitionRules
The transition function — the developer’s decision logic.
Versioned
A machine whose persisted form carries a schema version.

Derive Macros§

Event
Derive Event for an enum of events.
StateMachine
Derive StateMachine for an enum of states.