mesofact-dev 0.8.43

Dev-tier affordances for mesofact workloads — a rebuild-on-change watcher, a local S3 surface standing in for R2, and `mesofact_dev::serve_app`, the dev half of a library-tier project's two bin targets. The serving engine lives in the `mesofact` facade; this crate must never be in a prod binary's dependency closure (W225 §2).
[package]
name = "mesofact-dev"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
repository.workspace = true
# PUBLISHABLE as of R832-T1 (was `publish = false`). W225 §2's library tier
# prescribes a consumer manifest naming `mesofact` AND `mesofact-dev` as plain
# non-optional deps; that manifest cannot resolve for anyone outside this
# monorepo while this crate is unpublishable, which is why the tier was not
# scaffoldable. `publish = false` was never a deliberate policy call — it was
# present in the crate's first commit (0aa2077e, a bulk "fix oss links" commit
# on 2026-06-11) with no rationale anywhere, at a time when this crate was a
# static-file dev server nobody would depend on.
#
# `mesofact-dev` is unclaimed on crates.io (sparse index 404, checked
# 2026-09-01; `mesofact` and `mesofact-publisher` are both there at 0.8.29).
# Flipping this does not publish anything by itself — `scripts/oss-publish.sh`
# is run by hand from a release recipe and simply stops excluding this member.
#
# Being publishable is a maintenance commitment: from the first upload this
# crate's public API is a public API, and crates.io versions can only be
# yanked, never withdrawn. Publishing it is what W225 §2 asks for; revert this
# hunk before the next `oss-publish.sh` run if that answer changes.
description = "Dev-tier affordances for mesofact workloads — a rebuild-on-change watcher, a local S3 surface standing in for R2, and `mesofact_dev::serve_app`, the dev half of a library-tier project's two bin targets. The serving engine lives in the `mesofact` facade; this crate must never be in a prod binary's dependency closure (W225 §2)."

[lib]
path = "src/lib.rs"

# DESCRIPTIVE NAME WHERE YOU READ IT, SHORT NAME WHERE YOU TYPE IT (operator
# decision, 2026-09-01; landed by MFT-R822). Cargo decouples package name from
# bin name, and this workspace uses that ACROSS A PACKAGE BOUNDARY rather than
# within one:
#
# - The PACKAGE stays `mesofact-dev`, permanently — not as a legacy spelling of
#   `mes`. It is the meta crate: the entrypoint to the collection of dev-tier
#   tools `mes` needs that are NOT mesofact — the rebuild-on-change watcher,
#   the local S3 surface standing in for R2, and `serve_app`. It DEPENDS ON the
#   `mesofact` facade rather than being it, and that direction is the whole
#   prod/dev boundary (W225 §2). A dependency line reading `mes = "0.8"` would
#   say none of that.
# - The COMMAND is `mes`, and it lives in its own package (`../mes`), three
#   lines over `mesofact_dev::cli::run()`. `cargo install` takes a PACKAGE
#   name, so a binary named `mes` shipping from a package named `mesofact-dev`
#   makes `cargo install mes` fail outright — the command a user is told to run
#   would not name anything installable.
#
# THIS PACKAGE THEREFORE EMITS NO BINARIES. There is no `[[bin]]` below and
# there should not be one: adding one here re-creates the install-name problem,
# and a second package emitting `mes` would race `../mes` for
# `~/.cargo/bin/mes`. The CLI itself stays in `src/cli.rs` (a library module),
# which is what lets `../mes/src/main.rs` be three lines.
#
# NOTE: the prod `mesofact-serve` bin used to live here. It moved to the
# `mesofact` facade — its presence in this crate is exactly what forced the prod
# binary to link the watcher + dev S3 surface, breaking W225 §2's dev/prod
# boundary. Do not reintroduce a prod-serving bin in this crate.

# `ssr` (default on) carries the in-process V8 runtime (mesofact-ssr →
# deno_core → prebuilt librusty_v8), forwarded to the facade. Static/SPA-only
# consumers can build with `--no-default-features` and skip the V8 toolchain
# entirely — the same posture the bun era guaranteed, carried over to the V8
# era. Without `ssr`, `mode:"ssr"` routes are not dispatchable; static serving,
# the SPA hydrate path, the same-origin reverse proxy, the watcher, and the dev
# S3 surface are all unaffected.
[features]
default = ["ssr", "build"]
# Forwards to the facade's `ssr` tier (runtime + revalidate receiver). The
# publisher dep stays direct: the dev S3 smoke test drives S3Store itself.
# Pulls the `publish` feature below for the same reason the facade's `ssr`
# does — see that manifest: forwarding `mesofact/ssr` alone would enable the
# facade's `publish` cfg without setting one here, so `#[cfg(feature =
# "publish")]` on the `mes publish` subcommand would be false while
# `mesofact::cli::publish` was very much present. Keep the two in lockstep.
ssr = ["mesofact/ssr", "dep:mesofact-publisher", "publish"]
# Mirrors the facade's flag so the `mes publish` subcommand is gated on a
# feature this crate actually declares.
publish = ["mesofact/publish"]
# Links the build pipeline (rolldown + lightningcss) so the watcher can build
# IN-PROCESS instead of shelling out to a third executable (R759-T4). This is
# the feature that makes the documented dev loop true: the release ships only
# `mesofact` and `mesofact-dev`, so a `sh -c "bun run build"` default meant
# the loop silently required bun on PATH.
#
# Default-ON, and it belongs HERE rather than in the facade: `mesofact-build`
# is the one from-source compile monster and W225 §2/§3 forbid it in the prod
# binary's closure. Dev is the tier that is allowed to be fat. A consumer who
# wants a lean dev binary (their own bundler step, declared as `[build]
# command` in workload.toml) can still `--no-default-features`.
build = ["mesofact/build"]

[dependencies]
axum = { version = "0.8", default-features = false, features = ["http1", "tokio"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "fs", "process", "time", "sync", "io-util", "net"] }
tower = "0.5"
tower-http = { version = "0.6", features = ["trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
clap = { version = "4", features = ["derive", "env"] }
anyhow = "1"
notify = "8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"
# The serving engine. This crate is now a thin dev-affordance layer ON TOP of
# the facade rather than the crate that owned the engine (W225 §2a).
mesofact = { path = "../mesofact", version = "0.8.43", default-features = false }
# Direct publisher dep for the instance-store wiring in cli.rs (drives
# S3Store itself against the camp-injected dev S3 coordinates).
# `version` is required now that this crate publishes: cargo rejects a path dep
# without one, since a path means nothing to a downstream consumer.
mesofact-publisher = { path = "../mesofact-publisher", version = "0.8.43", optional = true }
# Embedded dev-tier S3 surface, restored 2026-09-17 after R584-T1 deleted it.
# R584-T1's premise was that a `yah camp` always injects S3_* coordinates; that
# is true inside a camp and false for every other way `mes` is run — a bare
# `mes .` on a scaffolded project, which is the invocation the scaffold's own
# README gives. `DevStore::resolve` prefers the camp's store and falls back to
# this one, so the standalone tier has a store again without a camp.
s3s = "0.13"
s3s-fs = "0.13"
# Impl of s3s::access::S3Access for the embedded surface (async-trait method).
async-trait = "0.1"
hyper-util = { version = "0.1", features = ["server", "tokio", "http1"] }

[dev-dependencies]
tempfile = "3"
tower = { version = "0.5", features = ["util"] }