frame_host/dev/door.rs
1//! The authority gate in front of the bytecode-push door (ruling C3).
2//!
3//! AT THIS COMMIT THERE IS NO DOOR: no code path anywhere in frame-host
4//! can activate staged bytes. This gate and its test land FIRST — the
5//! red-first pin the tear ruled — so that when the door is built (behind
6//! this gate, dev-wiring only), the production refusal is already law,
7//! not a property the door happens to have.
8//!
9//! Production is not "dev minus a flag": a production host has no path
10//! from a stage request to an activation, and the test pins that shape by
11//! asserting the gate refuses BEFORE anything downstream could run.
12
13use super::{NodeMode, StageRefusal};
14
15/// Refuses staged activation on any host that was not started in dev
16/// mode. Every handler of `DevRequest::StageAndActivate` MUST pass this
17/// gate before touching anything — the refusal happens with zero node
18/// operations performed.
19///
20/// # Errors
21///
22/// [`StageRefusal::NotADevNode`] for a production host.
23pub fn require_dev_node(mode: NodeMode) -> Result<(), StageRefusal> {
24 match mode {
25 NodeMode::Dev => Ok(()),
26 NodeMode::Production => Err(StageRefusal::NotADevNode),
27 }
28}
29
30#[cfg(test)]
31mod tests {
32 use super::require_dev_node;
33 use crate::dev::{NodeMode, StageRefusal};
34
35 /// The C3 pin: a production host refuses staged activation, typed,
36 /// with nothing downstream ever reached. This test predates the door
37 /// itself — at the commit that introduces it, no activation code
38 /// exists in this crate — and it must stay green forever after the
39 /// door is built behind the gate.
40 #[test]
41 fn production_host_refuses_staged_activation() {
42 assert_eq!(
43 require_dev_node(NodeMode::Production),
44 Err(StageRefusal::NotADevNode)
45 );
46 }
47
48 /// The gate admits exactly the dev-started host.
49 #[test]
50 fn dev_host_passes_the_gate() {
51 assert_eq!(require_dev_node(NodeMode::Dev), Ok(()));
52 }
53}