arcature 2026.2.1

Arcature application framework: a high-level Application facade over the certified Arcature subsystems, with the low-level Axum/Tower escape hatch preserved.
Documentation
//! The [`Operations`] trait — the shared internal operation layer an
//! Arcature application implements for binary-subcommand dispatch
//! (AP2.1-10).
//!
//! The application implements [`Operations`] once; [`super::dispatch`] reads
//! the subcommand from argv and calls the corresponding method. This is the
//! "one internal operation layer" the six subcommands share: instead of six
//! separate binaries or six hand-written `main` branches, the app has one
//! trait impl and one `main` that calls `arcature::cli::run(operations)`.
//!
//! # Design
//!
//! Each method is `async` and returns [`crate::Result`] (the engine's typed
//! result). The dispatch drives them on the certified Tokio runtime
//! (`macros` feature). An operation that needs no subsystem (e.g. `about`)
//! returns `Ok(())` after printing; one that serves (`serve`) runs until a
//! termination signal. The application owns the bodies — the engine does not
//! invent business behavior (AGENTS.md §7, ADR-0006 §7: "Auto-discover
//! wiring, never invent business behavior").
//!
//! `about` is the one operation the engine can help with: it prints the
//! framework version. The app's `about` includes its own name and version
//! alongside [`crate::FRAMEWORK_VERSION`]; the engine re-exports that
//! constant so the app does not hardcode the Arcature version.

/// The shared internal operation layer an Arcature application implements.
///
/// One impl per application; [`super::dispatch`] calls the method matching
/// the parsed subcommand. Each method receives the trailing argv (the
/// arguments after the subcommand selector) so an operation like `migrate`
/// can forward `up`/`down`/`--steps N` to the app's migrator.
///
/// The trait is `Send + Sync + 'static` so the dispatch can own it across
/// the async runtime; `async-trait` is not used (the engine avoids the
/// `async-trait` supply-chain surface on the hot path) — the methods return
/// `Pin<Box<dyn Future>>` directly, which is the same desugaring without the
/// macro.
pub trait Operations: Send + Sync + 'static {
    /// `serve` — the normal production path. Run the application with the
    /// health lifecycle until a termination signal. The app typically
    /// builds an [`crate::Application`] and calls `run_with_health`.
    fn serve(
        &self,
        args: &[String],
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<()>> + Send + '_>>;

    /// `migrate` — apply schema migrations. The app owns the migrator; this
    /// forwards `args` (e.g. `up`, `down`, `--steps N`) to it.
    fn migrate(
        &self,
        args: &[String],
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<()>> + Send + '_>>;

    /// `queue` — run the job worker until a termination signal.
    fn queue(
        &self,
        args: &[String],
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<()>> + Send + '_>>;

    /// `schedule` — run the recurring-job scheduler until a termination
    /// signal.
    fn schedule(
        &self,
        args: &[String],
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<()>> + Send + '_>>;

    /// `doctor` — run app-level runtime diagnostics (dependency health
    /// checks needing the app's configured services). Distinct from the
    /// CLI's `arc doctor` (local toolchain environment).
    fn doctor(
        &self,
        args: &[String],
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<()>> + Send + '_>>;

    /// `about` — print the application's identity (name, version, Arcature
    /// engine version) to stdout. Side-effect-free.
    fn about(
        &self,
        args: &[String],
    ) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::Result<()>> + Send + '_>>;
}