microvms_core/lib.rs
1// SPDX-License-Identifier: Apache-2.0
2//! The MicroVMs client: the control plane, the in-VM daemon, the cost engine, and
3//! every trap closure, in one library crate (ARCH-1).
4//!
5//! # What this crate is for
6//!
7//! `docs/PLATFORM.md` records seventeen measured findings about AWS Lambda MicroVMs,
8//! fifteen of which a client can act on. Most of them are traps in the specific sense
9//! that the platform's answer points away from the cause: an unsupported region
10//! answers `AccessDeniedException` with a null message, a `clientToken` replay wedges
11//! an image in `CREATING` for fifteen hours with no error at all, a
12//! `minimumMemoryInMiB` of 512 produces a guest reporting 2 GB. Each finding cost a
13//! measurement, and this crate is where that measurement is spent once so no caller
14//! has to make it again.
15//!
16//! The Python client closed the same traps and stayed in the tree as the conformance
17//! oracle and the API reference until this port had driven the live suite green; it is
18//! git history now. The reason to port was that Rust can make several of those closures
19//! *unavailable* rather than merely rejected — see the strength ladder below.
20//!
21//! # How strongly a trap is closed
22//!
23//! The spec ranks each closure, strongest first:
24//!
25//! * **S1, inexpressible** — the mistake cannot be written down. [`region::Region`] is
26//! an enum over the five regions that carry MicroVMs, so a typo'd region is a
27//! compile error rather than a runtime check; [`sizing::SizeClass`] is closed over
28//! the five documented baselines; [`hooks::RunHookTimeout`] and
29//! [`hooks::BuildHookTimeout`] are separate types with no conversion between them,
30//! so a 3600-second build timeout cannot reach a field that caps at 60.
31//! * **S2, expressible but rejected** — the mistake can be written and the client
32//! refuses it locally, before any control-plane call, with an error naming the
33//! `docs/PLATFORM.md` finding. Weaker because the guard is code that can regress,
34//! but it costs seconds rather than a build cycle. Every boundary where a bare
35//! integer or string still has to be judged lands here:
36//! [`sizing::SizeClass::from_baseline_mib`], `Region::from_str`.
37//! * **S3, correct by default and overridable** — weakest, because it protects the
38//! caller who does nothing and abandons the one who overrides. An S3 closure must
39//! say what the override costs: [`region::Region::unlisted`] says it costs you the
40//! diagnostic.
41//!
42//! # Every error message names its finding
43//!
44//! A local reject explains itself by naming the `docs/PLATFORM.md` section that
45//! measured the behaviour, because the codes and the guards exist precisely so a
46//! reader can go to the measurement rather than to a constraint. "region
47//! 'eu-central-1' is invalid" sends someone to check their spelling; the message
48//! [`region::Region`] actually raises sends them to the null-message finding.
49//!
50//! # A guard that cannot fail is worse than no guard
51//!
52//! Carried over from the Python era unchanged: every guard here has a falsification —
53//! a specific plausible edit that must turn a specific test red. "Delete the feature
54//! and the test fails" does not count. The clearest case is TRAP-13 in
55//! [`sizing`]: every documented peak is exactly four times its baseline, so a test
56//! against the shipped table cannot tell a table lookup from `baseline * 4`, and the
57//! guard has to drive the lookup over a table where the pattern does not hold.
58//!
59//! # Layout
60//!
61//! [`error`], [`region`], [`sizing`], [`hooks`], and [`constants`] are the foundation
62//! every other module builds on. [`cost`], [`control`], [`session`], and [`sandbox`]
63//! are the product surface. [`agents`] is the one layer above them: the coding-agent
64//! helpers `docs/AGENT-VMS.md` specifies, which compose the surface and which nothing
65//! below depends on. [`provision`] stands beside the surface rather than on it: it obtains
66//! the verified `agentd` binary an image is built from, and makes no AWS call.
67
68// CLI-7: a print macro panics when its stream's reader has gone (#216). Every write goes
69// through a checked writer instead.
70#![deny(clippy::print_stdout, clippy::print_stderr)]
71
72pub mod agents;
73pub mod constants;
74pub mod control;
75pub mod cost;
76pub mod error;
77pub mod hooks;
78pub mod identity;
79pub mod names;
80pub mod preflight;
81pub mod provision;
82#[cfg(test)]
83mod provision_fuzz;
84pub mod region;
85pub mod sandbox;
86pub mod session;
87pub mod sizing;
88
89#[cfg(test)]
90mod sizing_fuzz;
91
92// Re-exported so consumers name wire types through this crate rather than
93// depending on `protocol` directly — the CLI's thinness guard counts on that.
94pub use protocol;
95
96pub use error::{Error, ErrorKind, WireKind};
97pub use hooks::{BuildHookTimeout, RunHookTimeout};
98pub use region::Region;
99pub use sizing::SizeClass;
100
101/// The crate's own version, for a `doctor` or `manifest` command to report.
102pub const VERSION: &str = env!("CARGO_PKG_VERSION");