mesofact_dev/lib.rs
1//! `mesofact-dev` — the dev-tier affordances, and nothing else.
2//!
3//! **This crate is deliberately small.** The serving engine (`Server`, SSR
4//! dispatch, the revalidate receiver, tenants, the same-origin proxy) used to
5//! live here, which meant the *prod* `mesofact-serve` binary — which shipped
6//! from this crate — linked the file watcher and the dev S3 surface. That broke
7//! the dev/prod crate boundary W225 §2 relies on for its security claim
8//! ("prod is clean by construction … the crate boundary already keeps it out of
9//! prod"). It wasn't: cleanliness rested on linker dead-stripping.
10//!
11//! The engine now lives in the `mesofact` facade and this crate *depends on*
12//! it, holding only the pieces that must never reach a prod binary:
13//!
14//! - [`watcher`] — the rebuild-on-change file watcher.
15//! - [`s3`] — reads the camp-injected dev-tier S3 coordinates that stand in
16//! for R2 during `dev` (R584-T1; W225 §2 "local pond emulation").
17//! - [`app`] — the **library-tier** dev entry point, [`serve_app`]: the dev
18//! counterpart of [`mesofact::serve_app`] for a consumer whose routes are
19//! Rust handlers rather than a built `dist/` tree. Read its module doc for
20//! what the dev half of that tier is and, just as load-bearing, what it
21//! deliberately is not.
22//! - [`cli`] — the `mes` toolchain CLI, and the two bin targets over it.
23//!
24//! [`cli`] carries the prod verbs (`serve`, `publish`, `new`) as well as the
25//! dev ones, so consumers learn one CLI — but it gets them by *calling into*
26//! [`mesofact::cli`], which is the direction that costs the prod binary
27//! nothing. The boundary above is about what links into a binary, not about
28//! which verbs a binary spells.
29//!
30//! Engine types are re-exported below so existing `mesofact_dev::Server`-style
31//! callsites keep working; new code should prefer `mesofact::…` directly.
32//!
33//! @arch:see(.yah/docs/working/W225-mesofact-consumer-deployment-model.md)
34
35pub mod app;
36pub mod cli;
37pub mod s3;
38pub mod watcher;
39
40pub use app::{serve_app, DevServer, DEV_STATE_DIR};
41pub use s3::{DevStore, StoreProvenance, EMBEDDED_BUCKET};
42pub use watcher::{BuildDriver, WatchOptions, Watcher};
43
44// Engine re-exports — the serving path now lives in the `mesofact` facade.
45pub use mesofact::proxy;
46pub use mesofact::server;
47pub use mesofact::{DistPointer, Identity, ProxyMap, ProxyState, Server, DEFAULT_PORT};
48#[cfg(feature = "ssr")]
49pub use mesofact::{
50 revalidate, ssr, tenants, ResiliencePolicy, RetryPolicy, SsrChild, SsrSlot, SsrSpawnOptions,
51 DEFAULT_RESILIENCE_TIMEOUT_MS,
52};
53
54/// Shared across `s3::tests` and `app::tests` (R584-T1): both mutate the same
55/// process-wide `S3_*`/`R2_*` env vars, and a lock private to one module does
56/// nothing to stop the default parallel test runner racing it against the
57/// other. `tokio::sync::Mutex` rather than `std::sync::Mutex` because
58/// `app::tests` holds the guard across an `.await` (`DevServer::start`).
59#[cfg(test)]
60pub(crate) mod test_support {
61 pub static ENV_LOCK: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(());
62}