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 Arcature production health endpoints (AP2.1-10).
//!
//! Two endpoints, two responsibilities (PROGRAM.md AP2.1-10: "One health
//! endpoint convention (`/up/live`, `/up/ready`)"):
//!
//! - **`/up/live`** — liveness, independent of any external dependency.
//!   `200` while the process is up; `503` once it has stopped.
//! - **`/up/ready`** — readiness, gated on the lifecycle state being `Ready`
//!   **and** every application-registered readiness check passing. `200`
//!   only then; `503` during `Starting`, `Draining`, `Stopped`, or when a
//!   readiness check fails.
//!
//! Health and readiness are deliberately separate endpoints (do not overload
//! one): a liveness probe must not kill a process that is live but unready,
//! and a readiness probe must not route traffic to a process that is live
//! but still starting or already draining.
//!
//! # Composition
//!
//! [`router`] returns a stateless [`axum::Router<()>`] — standalone-first
//! (AGENTS.md §16): an expert user mounts it on their own Axum app without a
//! runtime dependency on `arcature` beyond the
//! [`Lifecycle`](crate::application::lifecycle::Lifecycle) handle. The
//! handlers read the
//! [`Lifecycle`](crate::application::lifecycle::Lifecycle) from an Axum
//! [`axum::Extension`] layer (installed via [`lifecycle_layer`]), so the
//! health router composes with any application state type `S` — it does not
//! require the app state to carry the lifecycle, and merging it into a
//! stateful router does not change the app's state type.
//!
//! The orchestrated paths (`Application::serve_with_health` /
//! `Application::run_with_health`) merge this router into the
//! application's routes before serving, installing the
//! [`lifecycle_layer`] so the health handlers observe the
//! same [`Lifecycle`](crate::application::lifecycle::Lifecycle) the
//! orchestration drives.
//!
//! The endpoints do not run on the application proxy or any post-routing
//! layer (maintenance, Inertia): they are plain routes, short-circuited by
//! Axum route selection before the fallback or the application's
//! middleware. A maintenance-mode 503 therefore does not wall the health
//! endpoints — `/up/ready` still reports the real lifecycle state, which is
//! what an operator draining traffic wants (PROGRAM.md AP2.1-10).
//!
//! # No information leakage
//!
//! The bodies are public-safe status words (`"live"`, `"ready"`,
//! `"starting"`, `"draining"`, `"unready"`, `"stopped"`). No dependency
//! names, no error messages, no internal paths. The readiness checks
//! themselves never receive the request and never emit output — they are
//! `Fn() -> bool` predicates the handler evaluates silently.

mod live;
mod ready;
mod router;

/// The public liveness response, for an app wiring its own liveness route.
pub use live::live_response;
/// The public readiness response, for an app wiring its own readiness route.
pub use ready::ready_response;
/// The liveness path (`/up/live`).
pub use router::LIVE_PATH;
/// The readiness path (`/up/ready`).
pub use router::READY_PATH;
/// The Axum layer that installs the `Lifecycle` into every request's
/// extensions so the [`router`] handlers can read it.
pub use router::lifecycle_layer;
/// Build the health router: `/up/live` and `/up/ready`, stateless (`()`)
/// so it composes with any application state via a merge/nest.
pub use router::router;