application tier

application-engine

Forge framework runtime crate: ForgeApp composer, ModuleRouter<S>, migration runner, registry, TOML config. Consumes application-core's contract.

Forge framework runtime crate: ForgeApp composer, ModuleRouter<S>, migration runner, registry, TOML config. Consumes application-core's contract.

Tierapplication
Roleunclassified (baselined)
Pathcrates/application/engine
Edition2021
Targetsbuild-script-build, application_engine, migration_versions
Public items35 across 9 modules
Tests25

What it is for

application-engine — Forge framework runtime.

Sprint 55 (2026-05-28) extracted this from forge-control per the sprint 54 architectural restructure. Holds the runtime half of the contract/runtime split:

here, not in application-core, because per Sprint 55 Round 3 Gemini pattern: object-safe application_core::ModuleIdentity in application-core for Vec<Box<dyn ...>> ingestion, generic ModuleRouter<S> in application-engine called with concrete state during axum compose).

and orchestrates migration ordering + router merging at boot.

forge_migration_log ledger.

ModuleRegistry (new ModuleIdentity trait).

Re-exports application-core for consumer convenience: a single use application_engine::* brings in the engine + the contract types it composes.

Capabilities

crate root

application-engine — Forge framework runtime.

Item
async fn run_platform_migrations(pool : & sqlx::PgPool,) -> Result <(), sqlx::migrate::MigrateError>

app (other)

ForgeApp — the composer.

Item
pub const ADMIN_PREFIX: & str

ForgeApp

ForgeApp — the composer.

Item
pub struct ForgeApp<S>

ForgeApp<S>

ForgeApp — the composer.

Item
ForgeApp<S> :: fn new(pool : PgPool, state : S) -> Self
ForgeApp<S> :: fn register <M>(mut self, module : M) -> Self where M : ModuleIdentity + ModuleRouter <S> + 'static,
ForgeApp<S> :: fn with_admin_layer <F>(mut self, layer : F) -> Self where F : FnOnce(axum::Router <S>) -> axum::Router <S> + 'static,
ForgeApp<S> :: fn into_router(self) -> axum::Router
ForgeApp<S> :: async fn boot(self) -> Result <axum::Router, MigrationError>
ForgeApp<S> :: async fn boot_with <F>(self, transform : F) -> Result <axum::Router, MigrationError> where F : FnOnce(axum::Router) -> axum::Router,
ForgeApp<S> :: fn modules(& self) -> & Box <dyn ModuleIdentity>
ForgeApp<S> :: fn pool(& self) -> & PgPool

ApplicationSection

application.toml config parser.

Item
pub struct ApplicationSection

Config

application.toml config parser.

Item
pub const CONFIG_FILE: & str
pub const CONFIG_FILE_SUPERSEDED: & str
pub struct Config
Config :: fn load(path : & Path) -> Result <Self, ConfigError>
Config :: fn discover(dir : & Path) -> Option <std::path::PathBuf>
Config :: fn save(& self, path : & Path) -> Result <(), ConfigError>

ConfigError

application.toml config parser.

Item
pub enum ConfigError

I18nSection

application.toml config parser.

Item
pub struct I18nSection

ThemeSection

application.toml config parser.

Item
pub struct ThemeSection

middleware::staging (other)

Sprint 65: extracted from rust-cms-engine.

Item
async fn staging_layer(mut req : Request <Body>, next : Next) -> Response

IsStaging

Sprint 65: extracted from rust-cms-engine.

Item
pub struct IsStaging

migrate (other)

Migration orchestration runner.

Item
async fn ensure_ledger(pool : & PgPool) -> Result <(), MigrationError>
async fn migrate(registry : & EngineRegistry, pool : & PgPool) -> Result <u32, MigrationError>

preview (other)

Responsive preview shell — a reusable staff/dev tool for SSR consumers.

Item
fn router <S>() -> Router <S> where S : Clone + Send + Sync + 'static,

EngineRegistry

Registries — collect registered engines/modules.

Item
pub struct EngineRegistry
EngineRegistry :: fn new() -> Self
EngineRegistry :: fn register(mut self, engine : Box <dyn Engine>) -> Self
EngineRegistry :: fn engines(& self) -> & Box <dyn Engine>

ModuleRegistry

Registries — collect registered engines/modules.

Item
pub struct ModuleRegistry
ModuleRegistry :: fn new() -> Self
ModuleRegistry :: fn register(mut self, module : Box <dyn ModuleIdentity>) -> Self
ModuleRegistry :: fn modules(& self) -> & Box <dyn ModuleIdentity>

staff (other)

Sprint 65: extracted from rust-cms-engine.

Item
fn router <S>(dist_dir : impl Into <PathBuf>) -> Router <S> where S : Clone + Send + Sync + 'static,

How to use it

No examples/ target and no doctest in this crate's rustdoc. The tests listed under Verification are the closest executable usage.

Module structure

application_engine

flowchart TD
  n_application_engine["application_engine"]
  n_application_engine --> n_app["app"]
  n_application_engine --> n_config["config"]
  n_application_engine --> n_middleware["middleware"]
  n_middleware --> n_middleware__staging["staging"]
  n_application_engine --> n_migrate["migrate"]
  n_application_engine --> n_module_router["module_router"]
  n_application_engine --> n_preview["preview"]
  n_application_engine --> n_registry["registry"]
  n_application_engine --> n_staff["staff"]

Public surface

`crate root`

ItemWhat it is
async fn run_platform_migrations(pool : & sqlx::PgPool,) -> Result <(), sqlx::migrate::MigrateError>Apply the canonical Forge platform schema migrations

`app`

ItemWhat it is
pub const ADMIN_PREFIX: & strPrefix under which every module's admin surface is mounted.
pub struct ForgeApp<S>Composer that holds the pool, state, registered modules, and the accumulated public/admin routers
ForgeApp<S> :: fn new(pool : PgPool, state : S) -> SelfCreate a new empty app with the given pool and state.
ForgeApp<S> :: fn register <M>(mut self, module : M) -> Self where M : ModuleIdentity + ModuleRouter <S> + 'static,Register a module
ForgeApp<S> :: fn with_admin_layer <F>(mut self, layer : F) -> Self where F : FnOnce(axum::Router <S>) -> axum::Router <S> + 'static,Provide the layer that wraps the admin subtree (typically the RBAC stack)
ForgeApp<S> :: fn into_router(self) -> axum::RouterAssemble the final router: public surfaces at root, the (optionally layer-wrapped) admin subtree nested under ADMIN_PREFIX, state applied once
ForgeApp<S> :: async fn boot(self) -> Result <axum::Router, MigrationError>Run all registered modules' migrations in registration order, then return the assembled router (state applied) ready for axum::serve
ForgeApp<S> :: async fn boot_with <F>(self, transform : F) -> Result <axum::Router, MigrationError> where F : FnOnce(axum::Router) -> axum::Router,Boot, then apply a router transform — e.g
ForgeApp<S> :: fn modules(& self) -> & Box <dyn ModuleIdentity>Borrow the registered module list (useful for tests + admin introspection).
ForgeApp<S> :: fn pool(& self) -> & PgPoolBorrow the pool — useful when sharing it with non-module workers.

`config`

ItemWhat it is
pub enum ConfigErrorErrors raised when reading/parsing/writing the app config.
pub const CONFIG_FILE: & strThe config file a consumer app carries, in preference order
pub const CONFIG_FILE_SUPERSEDED: & str
pub struct ConfigTop-level config container.
pub struct ApplicationSectionapplication section.
pub struct ThemeSectionforge.theme subsection.
pub struct I18nSectionforge.i18n subsection.
Config :: fn load(path : & Path) -> Result <Self, ConfigError>
Config :: fn discover(dir : & Path) -> Option <std::path::PathBuf>The config file in dir, preferring the current name over the superseded one
Config :: fn save(& self, path : & Path) -> Result <(), ConfigError>

`middleware::staging`

ItemWhat it is
pub struct IsStagingRequest extension flag — true when the request arrived on a staging host
async fn staging_layer(mut req : Request <Body>, next : Next) -> Response

`migrate`

ItemWhat it is
async fn ensure_ledger(pool : & PgPool) -> Result <(), MigrationError>Bootstrap the forge_migration_log ledger table
async fn migrate(registry : & EngineRegistry, pool : & PgPool) -> Result <u32, MigrationError>Run pending migrations across all registered engines in registration order: 1

`preview`

ItemWhat it is
fn router <S>() -> Router <S> where S : Clone + Send + Sync + 'static,The /responsive-preview router

`registry`

ItemWhat it is
pub struct EngineRegistryLegacy engine registry — Box<dyn Engine> collection
EngineRegistry :: fn new() -> Self
EngineRegistry :: fn register(mut self, engine : Box <dyn Engine>) -> Self
EngineRegistry :: fn engines(& self) -> & Box <dyn Engine>
pub struct ModuleRegistryModule registry — Box<dyn ModuleIdentity> collection consumed by crate::ForgeApp
ModuleRegistry :: fn new() -> Self
ModuleRegistry :: fn register(mut self, module : Box <dyn ModuleIdentity>) -> Self
ModuleRegistry :: fn modules(& self) -> & Box <dyn ModuleIdentity>

`staff`

ItemWhat it is
fn router <S>(dist_dir : impl Into <PathBuf>) -> Router <S> where S : Clone + Send + Sync + 'static,Returns an axum sub-router that serves a staff-ui SPA bundle out of dist_dir with correct caching headers and deep-link fallback

Re-exports. Exported here, defined elsewhere.

ExportDefined in
ForgeAppapp::ForgeApp
ModuleRouterapplication_core::ModuleRouter
ModuleRoutermodule_router::ModuleRouter
{ApplicationSection,Config,ConfigError,I18nSection,ThemeSection,CONFIG_FILE,CONFIG_FILE_SUPERSEDED,}config::{ApplicationSection,Config,ConfigError,I18nSection,ThemeSection,CONFIG_FILE,CONFIG_FILE_SUPERSEDED,}
{Engine,I18nBundle,MigrationError,MigrationSet,ModuleIdentity,SeedEntity,ThemeBundle,Vertical,VerticalError,}application_core::{Engine,I18nBundle,MigrationError,MigrationSet,ModuleIdentity,SeedEntity,ThemeBundle,Vertical,VerticalError,}
{EngineRegistry,ModuleRegistry}registry::{EngineRegistry,ModuleRegistry}
{ensure_ledger,migrate}migrate::{ensure_ledger,migrate}
{staging_layer,IsStaging}middleware::staging::{staging_layer,IsStaging}

Boundary

Depends on no other workspace tier.

Shares tier application with 120 other crates: application-agreements, application-ai, application-analytics, application-approvals, application-assessments, application-audit-log, application-auth, application-billing, … (120 total).

_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._

Where it sits

Tier (ontology)application
Architectural role (taxonomy)unclassified (baselined)
Locationcrates/application/engine
Vocabulary in force (lexicon)current

Dependencies

Runtime, in this workspace.

CrateTierOptionalOnly on
`application-core`applicationnoalways

Runtime, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
async-trait^0.1noalways
axum^0.7multipartnoalways
chrono^0.4serdenoalways
serde^1derivenoalways
serde_json^1noalways
sqlx^0.8runtime-tokio, postgres, chrono, uuid, jsonnoalways
thiserror^2noalways
tokio^1fullnoalways
toml^0.8noalways
tower-http^0.6fs, trace, cors, request-idnoalways
tracing^0.1noalways
uuid^1v4, v7, serde, jsnoalways

Development, from outside the workspace.

CrateRequirementFeaturesOptionalOnly on
tempfile^3noalways
tower^0.5utilnoalways

Build. None.

Depended on by. 14 workspace crates.

Signal flow — what reaches this crate, and what it reaches.

flowchart LR
  n_application_auth["application-auth"] -->|uses| SELF
  n_application_billing["application-billing"] -->|uses| SELF
  n_application_calendar["application-calendar"] -->|uses| SELF
  n_application_calendar_recurrence["application-calendar-recurrence"] -->|uses| SELF
  n_application_catalog["application-catalog"] -->|uses| SELF
  n_application_cli["application-cli"] -->|uses| SELF
  n_application_cms["application-cms"] -->|uses| SELF
  n_application_encounters["application-encounters"] -->|uses| SELF
  n_application_identifiers["application-identifiers"] -->|uses| SELF
  n_application_messaging["application-messaging"] -->|uses| SELF
  n_application_parties["application-parties"] -->|uses| SELF
  n_application_party_discovery["application-party-discovery"] -->|uses| SELF
  n_application_planning["application-planning"] -->|uses| SELF
  n_application_taxonomy["application-taxonomy"] -->|uses| SELF
  SELF["application-engine"]
  SELF -->|runtime| n_application_core["application-core"]
  classDef self fill:#1f883d,stroke:#1f883d,color:#fff;
  class SELF self;

Feature flags

No Cargo features are defined: every capability is unconditional, so no consumer can receive a half-wired crate.

Targets

KindNameSource
custom-buildbuild-script-build`build.rs`
libapplication_engine`src/lib.rs`
testmigration_versions`tests/migration_versions.rs`

Error model

Error typeNamed by
ConfigErrordeclared, no public signature returns it

Operational characteristics

PropertyEvidence
async public surfaceyes
async runtimeyes
database accessyes
network I/Oyes
unsafe codenone detected
environment variablesnone detected

No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.

Configuration

No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.

14 workspace crates depend on this one: application-auth, application-billing, application-calendar, application-calendar-recurrence, application-catalog, application-cli, application-cms, application-encounters, application-identifiers, application-messaging, application-parties, application-party-discovery, … (14 total).

Verification

KindCount
Unit tests23
Integration tests2
Examples0
Doctests0

Evidence by module. How often each public module is named by something executable.

ModuleTestsExamplesConsumers
crate root100
app201
config704
middleware::staging201
migrate204
preview107
registry201
staff107

What the tests establish, by name:

Documentation coverage

MeasureDocumentedTotal
Public items with rustdoc2535
Public modules with a //! block99
pie showData
    title Public items with rustdoc
    "Documented" : 25
    "No rustdoc detected" : 10

Metrics

MetricValue
Rust source files10
Source lines1223
Code lines770
Public API items35
Public modules9
Tests25
Examples0
Cargo features0
Direct runtime dependencies13
Workspace reverse dependencies14
pie showData
    title Public API by kind
    "constant" : 3
    "enum" : 1
    "function" : 6
    "method" : 17
    "struct" : 8
pie showData
    title Rust source composition
    "Code" : 770
    "Blank or comment" : 453

Generation

Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.

All application · Manual