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 `SystemCheck` trait (AP2.1-7).
//!
//! A system check is a Django-inspired self-diagnostic: a typed,
//! statically-registered unit that inspects one narrow aspect of the
//! application's configuration or runtime state and reports a stable ID, a
//! severity, a human-readable context, and a fix hint. The framework
//! aggregates contributed checks into a
//! [`SystemCheckReport`](crate::system_check::report::SystemCheckReport)
//! consumed by `arc doctor --checks` and, later, the MCP `system_checks`
//! tool (AP2.1-9).
//!
//! # Ownership
//!
//! The trait lives in `arcature` so that **the application** (which depends
//! on `arcature`) and **the framework itself** can contribute checks
//! without depending on the CLI. Subsystem crates (`arcature-db`,
//! `arcature-cache`, …) CANNOT depend on `arcature` (the dependency
//! direction is facade → subsystem, never the reverse — AGENTS.md §16), so
//! a subsystem contributes its checks through the application's bootstrap:
//! the app collects `&'static [SystemCheck]` slices from `arcature` and
//! from each subsystem it uses, then builds one report. This wave ships the
//! trait, the registry, the report shape, and a small set of framework
//! checks; the application-side aggregation and the app-binary subcommand
//! that the CLI shells out to are future work (AP2.1-10 production
//! lifecycle seam).
//!
//! # No business behavior by discovery (AP2.1 §6)
//!
//! A system check INSPECTS and REPORTS. It never invents a route,
//! authorization decision, transaction, or DB mutation (§7). A check that
//! finds a problem reports it; the operator decides what to do. A check
//! MUST NOT mutate state as a side effect of running.
//!
//! # No panic on hostile input (AGENTS.md §17)
//!
//! A check must be total. A check that reads configuration, an
//! environment-supplied path, or a manifest value must not panic on
//! malformed, missing, or oversized input; it reports a warning/error
//! result instead.

use crate::system_check::category::CheckCategory;
use crate::system_check::id::CheckId;
use crate::system_check::severity::CheckSeverity;

/// A single self-diagnostic check.
///
/// Implementations are `&'static`-registered (see `registry`): each
/// contributor exposes a `pub const CHECKS: &[&dyn SystemCheck] = &[...]`
/// (or a `&'static [SystemCheck]` slice of concrete check structs), and the
/// aggregator merges the slices into one report.
///
/// A check carries:
/// - a stable [`CheckId`] (e.g. `ARC0001`) — greppable, never renamed;
/// - a [`CheckSeverity`] (Error / Warning / Info);
/// - a [`CheckCategory`] (the area the check inspects);
/// - a short description of what it inspects;
/// - a [`SystemCheck::run`] that returns a [`CheckResult`](super::report::CheckResult).
///
/// The trait object is safe because every implementor must be `Send + Sync
/// 'static` — checks are read from `&'static` slices and may run on any
/// thread.
pub trait SystemCheck: Send + Sync + 'static {
    /// The stable, greppable check ID (e.g. `ARC0001`).
    fn id(&self) -> CheckId;

    /// The severity of a failing result.
    ///
    /// A check that passes returns `severity` irrelevant — the result's
    /// `status` is `Pass`. The severity is the severity assigned to a
    /// failing or warning result.
    fn severity(&self) -> CheckSeverity;

    /// The category / area this check inspects.
    fn category(&self) -> CheckCategory;

    /// A short, human-readable description of what the check inspects.
    fn description(&self) -> &'static str;

    /// Run the check and return a result. MUST NOT panic; MUST NOT mutate
    /// state. A check that cannot determine the answer returns a result
    /// with `status = Skipped` and a context explaining why.
    fn run(&self) -> super::report::CheckResult;
}