mesofact — the Rust-native web framework facade.
This is the one crate consumers depend on. Subsystems are selected by feature rather than by picking crate names out of a 7-crate workspace (bevy-style). Two distribution strategies, one crate:
- Prebuilt binary / container — we build the
mesofactbin with thedeploypreset, arch-native per libc, and kamaji fetches it. The consumer's project compiles zero Rust, only their TypeScript — the Node.js model. - Crate dependency — the same crate from crates.io, where a consumer picks features and builds a bespoke binary. What Node can't offer, because it's Rust-native all the way down instead of C++ addons.
They are the same crate at two lifecycle stages; the shared deploy feature
preset is what keeps them honest. See W225 §2a.
Feature tiers
default— the lean, V8-free Rust-handler harness: [serve_app] / [wrap] + the standard stack ([HEALTH_PATH],TraceLayer, graceful shutdown). For services whose handlers are Rust functions; the dogfood is yah's cloud-admin dashboard. Continues the "replacing bun with Rust-native SSR" arc (R448 rolldown → R449 deno_core → R450 default-flip).ssr— the SSR serving tier: the [Server] engine's V8 dispatch plus the revalidate receiver. Links the prebuiltlibrusty_v8.a(a CDN download, not a from-source compile).build— adds the bundler (rolldown + lightningcss), the one genuinely uncached from-source compile. Its own crate so a stray feature flip can't drag it into a lean consumer.
What lives here vs. mesofact-dev
The prod serving engine ([server], [proxy], and under ssr the ssr,
revalidate and tenants modules) lives here. mesofact-dev holds only
the dev affordances — the file watcher and the local S3 surface — and depends
on this crate. That direction is load-bearing: it is what keeps a prod binary
from linking dev code (W225 §2), and it is enforced by the dependency graph
rather than by dead-stripping. Do not add a dev affordance to this crate, and
do not add a prod-serving bin to mesofact-dev.
Cache / session / resilience layers live in mesofact_core::proxy today and are
bundle-shaped; lifting them here as caller-composable tower::Layers is a
follow-up once a second Rust-handler service needs them.
@yah:relay(R445, "mesofact-app: lean Rust-native app harness for Rust-handler services (continues R448/R449/R450 'replacing bun with rust-native SSR' arc; dogfooded by yah parent R568-T4)") @yah:at(2026-06-30T07:22:46Z) @yah:status(review) @yah:assignee(agent:bundle-anthropic-ashguard) @arch:see(.yah/docs/working/W174-mesofact-rust-native-pipeline.md) @yah:next("yah parent camp R568-T4 consumes this via root [patch.crates-io] mesofact-app = { path = "oss/mesofact/crates/mesofact-app" } + a path-deferred version dep in crates/yah/cloud-admin.") @yah:next("Once a 2nd Rust-handler mesofact service exists, lift cache/session/resilience layers from mesofact::core::proxy::* into the mesofact facade as caller-composable tower::Layers (deferred per lib doc until 2nd consumer appears).") @yah:handoff("Landed mesofact-app crate (oss/mesofact/crates/mesofact-app, publish=false). Lean Rust-handler harness: pub HEALTH_PATH const + pub fn wrap(Router) -> Router (adds /__mesofact/health + tower-http TraceLayer) + pub async fn serve_app(Router, SocketAddr) -> Result<()> (binds, wraps, axum::serve with graceful Ctrl-C/SIGTERM) + pub async fn shutdown_signal. Companion to mesofact-dev: no mesofact-ssr/deno_core/V8 dep so pure-Rust services don't inherit the ~75MB V8 binary. Registered in oss/mesofact workspace members. 3 tests pass (health auto-add, serve_app round-trip, documented panic guard on duplicate health route). Continues R448/R449/R450 arc (replacing bun with Rust-native SSR) -- this is the next milestone after R449 swapped the engine, taking handlers from JS to Rust.") @yah:verify("cargo test -p mesofact-app # 3 passed") @yah:gotcha("Tier: Cleric -- discovery+replicate. Mirrored mesofact-dev's health/shutdown_signal shape so probes are drop-in compatible across JS-bundle and Rust-handler services.") @yah:gotcha("wrap() panics if the caller already registered HEALTH_PATH (axum::Router::merge rejects overlapping method routes regardless of order). Constraint is documented + pinned by a should_panic test; richer-probe services must bypass wrap.") @yah:gotcha("RESOLVED 2026-07-23 (W225 §2a) -- was: 'mesofact-dev refactor to delegate its bind/serve to mesofact-app is deferred'. The whole serving engine moved INTO this crate and mesofact-dev now depends on it, so the delegation is structural rather than deferred. Server's router now uses this crate's HEALTH_PATH + default_health + shutdown_signal instead of the byte-identical copies it carried in mesofact-dev.")