pub struct Manifest {
pub trust: Trust,
pub state: State,
pub filters: Vec<FilterEntry>,
pub chain: Chain,
pub upstreams: Vec<Upstream>,
pub routes: Vec<Route>,
pub tls: Vec<TlsCert>,
pub resumption: Option<Resumption>,
pub observability: Observability,
pub listen: Listen,
}Expand description
A parsed manifest. Deserialised from TOML; no I/O happens here (key files and artifacts
are resolved by Control). Serialize exists only to derive the semantic content hash
(content_hash) — the canonical, representation-independent identity of the config.
Determinism invariant (f000004 #6): no map fields (HashMap). content_hash relies on
serde_json emitting fields and Vec elements in a fixed order; a HashMap would
serialise in nondeterministic order and silently break reload idempotency. If a manifest
ever needs a map, use BTreeMap (ordered) and keep this invariant.
Fields§
§trust: Trust§state: State[state]: the host state backend (ADR 000041). Rides the content hash like [trust],
and like [trust] it is fixed at construction — a reload rejects a change.
filters: Vec<FilterEntry>[[filter]] entries.
chain: ChainThe default [chain] — driven by the chain-only Control::on_request convenience and
used by a route that names no filters of its own. The fast-path server uses [[route]].
upstreams: Vec<Upstream>[[upstream]] entries: named backends the fast-path server forwards to (ADR 000013).
routes: Vec<Route>[[route]] entries: host + path-prefix → an (inline) chain and an upstream (ADR 000013).
Empty until the fast-path server is configured; matching is the server’s job, declared here.
tls: Vec<TlsCert>[[tls]] entries: server certificates for TLS termination (ADR 000014). Empty = plain
HTTP/1.1 (the fast path serves TLS only when at least one cert is declared).
resumption: Option<Resumption>[resumption]: opt-in shared session-ticket keys across replicas (ADR 000062). None
(the default) keeps the per-node, process-lifetime ticket key (ADR 000052). Rides the
content hash like [[tls]] and is rebuilt on reload — the keys derive deterministically
from (file, cert set), so a rebuild with unchanged inputs keeps outstanding tickets valid.
observability: Observability[observability]: operational metrics / access-log / admin-endpoint config (ADR 000009),
captured at construction. skip_serializing keeps it OUT of the semantic content_hash, so
toggling observability never counts as a config-version change (it is not part of the
filter/route identity, and the admin listener binds once at startup — like [trust]).
listen: Listen[listen]: the data-plane bind address + h3 advertisement (moka-1 field report §3.2/§3.4).
Mostly captured at construction like [observability] (the listener binds once at
startup, so a reload does not re-bind — restart to move the listener), and those fields
stay out of the semantic content_hash via field-level skip_serializing in Listen.
The exception is listen.client_auth, which build_active consumes on every reload and
therefore rides the hash (see Listen’s serialization note) — the section as a whole is
only skipped when it hashes to nothing anyway (no client_auth), preserving existing
config versions.
Implementations§
Source§impl Manifest
impl Manifest
Sourcepub fn content_hash(&self) -> Result<String, ControlError>
pub fn content_hash(&self) -> Result<String, ControlError>
The semantic content hash of this manifest — sha256:<hex> over a canonical
serialisation, not over the raw TOML. Two manifests that mean the same thing (differing
only in comments, whitespace, key order, or an explicit default written vs. omitted)
hash identically; any meaningful change flips the hash.
This is the manifest’s config version: the unit the reload gate compares for
idempotency (via [content_hash_at]), the value an operator audits, and the value a
future opt-in consensus layer (ADR 000008 openraft) would agree on. Canonical form is
serde_json over the derived Serialize — deterministic because the struct field order
is fixed and the manifest holds no maps (only ordered Vecs).
Does not read referenced files. The load/reload path uses [content_hash_at] /
[content_hash_with_ca] so an in-place client-auth CA renewal flips the version.
Sourcepub fn content_hash_at(
&self,
base_dir: Option<&Path>,
) -> Result<String, ControlError>
pub fn content_hash_at( &self, base_dir: Option<&Path>, ) -> Result<String, ControlError>
[content_hash] with referenced files resolved against base_dir (when Some): reads
[listen.client_auth].ca_path and mixes its digest in. Same path + different bytes must
flip the config version; otherwise SIGHUP reports Unchanged and the new trust roots
never load (fail-closed: an unreadable CA is an error, not a silently CA-less hash).
Sourcepub fn read_client_auth_ca(
&self,
base_dir: &Path,
) -> Result<Option<Vec<u8>>, ControlError>
pub fn read_client_auth_ca( &self, base_dir: &Path, ) -> Result<Option<Vec<u8>>, ControlError>
Read [listen.client_auth].ca_path, or None when no client auth is configured. The
ONE read a build shares between the config version and the client verifier
([content_hash_with_ca] + tls::build_server_configs), so the recorded version always
describes the trust roots the verifier was actually built from.
Sourcepub fn content_hash_with_ca(
&self,
client_auth_ca: Option<&[u8]>,
) -> Result<String, ControlError>
pub fn content_hash_with_ca( &self, client_auth_ca: Option<&[u8]>, ) -> Result<String, ControlError>
The semantic hash, with the client-auth CA bundle’s digest mixed in when supplied
(callers obtain the bytes from [read_client_auth_ca]).
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Manifest
impl<'de> Deserialize<'de> for Manifest
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonSchema for Manifest
impl JsonSchema for Manifest
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreAuto Trait Implementations§
impl Freeze for Manifest
impl RefUnwindSafe for Manifest
impl Send for Manifest
impl Sync for Manifest
impl Unpin for Manifest
impl UnsafeUnpin for Manifest
impl UnwindSafe for Manifest
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more