Skip to main content

bcx_model/
event.rs

1use bcx_core::{CapabilityRef, EventId, PolicyEpoch, ValidationError};
2use bcx_wire::WireLimits;
3
4/// Relationship between a BCX event and one of its parents.
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub enum RelationshipKind {
7    /// The parent directly caused this event.
8    CausedBy,
9    /// The event was delegated by the parent.
10    DelegatedFrom,
11    /// The event retries the parent.
12    RetryOf,
13    /// The event was scheduled by the parent.
14    ScheduledBy,
15    /// The event was derived from the parent.
16    DerivedFrom,
17    /// The event joins several parent branches.
18    JoinedFrom,
19}
20
21/// Observable cause class for an operation.
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum CauseKind {
24    /// An external network request entered the local trust boundary.
25    ExternalRequest,
26    /// A runtime or client attested an explicit user action.
27    ExplicitUserAction,
28    /// Application code initiated the operation.
29    ApplicationAction,
30    /// A service call was delegated by another participant.
31    DelegatedServiceCall,
32    /// A timer or schedule initiated the operation.
33    Timer,
34    /// A queue message initiated the operation.
35    QueueMessage,
36    /// The operation is a retry.
37    Retry,
38    /// An administrator initiated the operation.
39    Administrator,
40    /// An autonomous agent initiated the operation.
41    AutonomousAgent,
42}
43
44/// High-level operation action.
45#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46pub enum OperationAction {
47    /// Read data without modifying authoritative state.
48    Read,
49    /// Create a new object or state transition.
50    Create,
51    /// Update existing state.
52    Update,
53    /// Delete or tombstone existing state.
54    Delete,
55    /// Derive an output from one or more inputs.
56    Derive,
57    /// Execute a component or tool.
58    Execute,
59    /// Transfer data or authority across a boundary.
60    Transfer,
61    /// Subscribe to future updates.
62    Subscribe,
63    /// Publish an event.
64    Publish,
65}
66
67/// Admission decision produced before execution.
68#[derive(Clone, Copy, Debug, Eq, PartialEq)]
69pub enum AdmissionResult {
70    /// The operation may continue as requested.
71    Allow,
72    /// The operation is denied.
73    Deny,
74    /// The operation may continue only with a narrower scope.
75    Narrow,
76    /// The operation requires stronger approval.
77    RequireApproval,
78    /// The operation is quarantined for later review.
79    Quarantine,
80}
81
82/// Execution result recorded after an operation attempt.
83#[derive(Clone, Copy, Debug, Eq, PartialEq)]
84pub enum EffectResult {
85    /// The operation completed.
86    Completed,
87    /// The operation partially completed.
88    Partial,
89    /// The executor rejected the operation.
90    Rejected,
91    /// Execution failed.
92    Failed,
93    /// Execution was cancelled.
94    Cancelled,
95    /// Execution timed out.
96    TimedOut,
97}
98
99/// Compact event capsule for causal parentage.
100#[derive(Clone, Copy, Debug, Eq, PartialEq)]
101pub struct CauseCapsuleParts<'a> {
102    /// Local event identifier.
103    pub event_id: EventId,
104    /// Parent event identifiers.
105    pub parents: &'a [EventId],
106    /// Relationship used for every parent in this compact capsule.
107    pub relationship: RelationshipKind,
108    /// Observable cause class.
109    pub cause_kind: CauseKind,
110    /// Requested action.
111    pub action: OperationAction,
112    /// Optional authority reference.
113    pub authority: Option<CapabilityRef>,
114    /// Optional policy epoch reference.
115    pub policy_epoch: Option<PolicyEpoch>,
116}
117
118/// Validated compact event capsule for causal parentage.
119#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120pub struct CauseCapsule<'a> {
121    event_id: EventId,
122    parents: &'a [EventId],
123    relationship: RelationshipKind,
124    cause_kind: CauseKind,
125    action: OperationAction,
126    authority: Option<CapabilityRef>,
127    policy_epoch: Option<PolicyEpoch>,
128}
129
130impl<'a> CauseCapsule<'a> {
131    /// Creates a validated compact cause capsule.
132    pub const fn new(
133        parts: CauseCapsuleParts<'a>,
134        limits: WireLimits,
135    ) -> Result<Self, ValidationError> {
136        let capsule = Self {
137            event_id: parts.event_id,
138            parents: parts.parents,
139            relationship: parts.relationship,
140            cause_kind: parts.cause_kind,
141            action: parts.action,
142            authority: parts.authority,
143            policy_epoch: parts.policy_epoch,
144        };
145        match capsule.validate(limits) {
146            Ok(()) => Ok(capsule),
147            Err(error) => Err(error),
148        }
149    }
150
151    /// Validates bounded capsule shape.
152    pub const fn validate(&self, limits: WireLimits) -> Result<(), ValidationError> {
153        if self.parents.is_empty() {
154            return Err(ValidationError::Empty);
155        }
156        if self.parents.len() > limits.maximum_parent_events() {
157            Err(ValidationError::TooLarge)
158        } else {
159            Ok(())
160        }
161    }
162
163    /// Returns the local event identifier.
164    #[must_use]
165    pub const fn event_id(&self) -> EventId {
166        self.event_id
167    }
168
169    /// Returns parent event identifiers.
170    #[must_use]
171    pub const fn parents(&self) -> &'a [EventId] {
172        self.parents
173    }
174
175    /// Returns the relationship used for each parent.
176    #[must_use]
177    pub const fn relationship(&self) -> RelationshipKind {
178        self.relationship
179    }
180
181    /// Returns the observable cause class.
182    #[must_use]
183    pub const fn cause_kind(&self) -> CauseKind {
184        self.cause_kind
185    }
186
187    /// Returns the requested action.
188    #[must_use]
189    pub const fn action(&self) -> OperationAction {
190        self.action
191    }
192
193    /// Returns the optional authority reference.
194    #[must_use]
195    pub const fn authority(&self) -> Option<CapabilityRef> {
196        self.authority
197    }
198
199    /// Returns the optional policy epoch reference.
200    #[must_use]
201    pub const fn policy_epoch(&self) -> Option<PolicyEpoch> {
202        self.policy_epoch
203    }
204}