Skip to main content

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}