Skip to main content

microvms_protocol/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2//! The `microvms-agentd` wire contract as types, shared by the daemon and every
3//! Rust client of it.
4//!
5//! # Why this is a crate rather than a copy on each side
6//!
7//! The daemon serializes these shapes and a client deserializes them, and for as
8//! long as each side owned its own definitions the only thing keeping them in step
9//! was review. That is the failure mode `docs/schema.json` was built to catch after
10//! the fact; this crate makes the class of error unavailable in the first place. A
11//! field renamed here breaks compilation on whichever side has not caught up, which
12//! is the earliest and cheapest place a protocol change can fail.
13//!
14//! # What lives here and what does not
15//!
16//! Pure data only: serde plus schemars, no tokio, no axum, no base64. The rule is
17//! whether the type is *what travels* or *machinery for making it travel*. So the
18//! SSE event payloads are here and the stream that emits them is not; the base64
19//! field is here as a `String` and the encoding is in the daemon's handler; the
20//! error body is here and the `fail(status, slug, detail)` helper that pairs it with
21//! an axum `StatusCode` is not.
22//!
23//! Every type derives both `Serialize` and `Deserialize` even where one side needs
24//! only one of them, because the missing half is exactly what a client would have to
25//! hand-write. `docs/schema.json` is generated from these attributes under both
26//! contracts and byte-compared in CI, so a shape that reads differently than it
27//! writes is a test failure rather than a consumer's problem.
28
29pub mod discovery;
30pub mod exec;
31pub mod fs;
32pub mod health;
33pub mod hook;
34pub mod identity;
35pub mod tunnel;
36
37/// The daemon listener port when `AGENTD_PORT` is unset.
38///
39/// Shared by the daemon, image builders, and clients so their defaults agree.
40pub const DEFAULT_AGENT_PORT: u16 = 9000;
41
42/// Protocol version, distinct from the daemon version.
43///
44/// It tracks the wire contract, including verified tunnel framing, rather than the crate version: a patch to
45/// the daemon does not change the wire format, and a client that pinned a daemon
46/// version would refuse an upgrade it is compatible with.
47///
48/// What a client should do on a mismatch, stated here because it is the question a
49/// version number exists to answer:
50///
51/// * **Same `protocol_version`, different `daemon_version`** — proceed. The path
52///   namespace, framing, and shapes in `$defs` are compatible; only the implementation
53///   moved. This is the normal case and must not be treated as an error.
54/// * **Different `protocol_version`** — do not proceed against `/v1/`. A new
55///   protocol version means a shape or a status code changed meaning, and a client
56///   built for `1` cannot tell a changed meaning from a bug. Fetch `/v1/schema`,
57///   which stays unauthenticated precisely so this is diagnosable, and fail with
58///   the two versions named.
59/// * **The `microvms-agentd-version` response header disagrees with the schema
60///   document's `daemon_version`** — you are talking to two daemons through one
61///   endpoint, or to a proxy that rewrote a response. Treat it as a transport
62///   fault, not a version negotiation.
63///
64/// There is deliberately no negotiation *request*: the daemon serves exactly one
65/// protocol version, and a client that has read this document already knows which.
66pub const PROTOCOL_VERSION: &str = "2";
67
68/// The response header carrying the daemon version, on every response including
69/// errors.
70///
71/// Lowercase because HTTP/2 requires it and hyper normalizes anyway; naming it
72/// once here keeps the layer, the schema document, and any test asserting on it
73/// from drifting into three spellings of the same header.
74pub const VERSION_HEADER: &str = "microvms-agentd-version";