macp_core/mode.rs
1//! The result a coordination mode hands back to the kernel.
2//!
3//! The `Mode` *trait* itself lives in `macp-modes` (behavior), but this enum
4//! (data) lives in core because [`crate::session::Session::apply_mode_response`]
5//! consumes it — keeping it here avoids a `macp-core -> macp-modes` cycle.
6
7/// The result of a Mode processing a message.
8/// The runtime applies this response to mutate session state.
9/// `#[non_exhaustive]`: downstream wildcard arms must treat unknown responses
10/// as no-ops or rejections, never as resolutions.
11#[non_exhaustive]
12#[derive(Debug)]
13pub enum ModeResponse {
14 /// No state change needed.
15 NoOp,
16 /// Persist updated mode state.
17 PersistState(Vec<u8>),
18 /// Resolve the session with the given resolution data.
19 Resolve(Vec<u8>),
20 /// Persist mode state and resolve in one step.
21 PersistAndResolve { state: Vec<u8>, resolution: Vec<u8> },
22}
23
24/// Kernel-supplied context accompanying an accepted-for-processing message.
25///
26/// `accepted_at_ms` is the runtime's acceptance timestamp — the same value
27/// recorded as the log entry's `received_at_ms`, so live processing and
28/// replay observe the identical clock. Modes that need a trustworthy time
29/// source (e.g. Handoff's implicit-accept timeout) must use this, never the
30/// client-supplied `Envelope.timestamp_unix_ms`, which the sender can forge.
31///
32/// `#[non_exhaustive]`: construct via [`MessageContext::new`] so fields can be
33/// added without breaking mode implementations.
34#[non_exhaustive]
35#[derive(Debug, Clone, Copy)]
36pub struct MessageContext {
37 pub accepted_at_ms: i64,
38}
39
40impl MessageContext {
41 pub fn new(accepted_at_ms: i64) -> Self {
42 Self { accepted_at_ms }
43 }
44}