byteor_app_kit/
capabilities.rs

1use serde::Serialize;
2
3/// Current schema version for enterprise runtime capability documents.
4pub const CAPABILITY_SCHEMA_VERSION: u32 = 1;
5
6/// Execution targets a runtime can advertise support for.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
8#[serde(rename_all = "snake_case")]
9pub enum ExecutionTarget {
10    /// Canonical lowered SingleRing execution.
11    SingleRing,
12    /// Canonical lowered LaneGraph execution.
13    LaneGraph,
14}
15
16/// LaneGraph feature families that matter to authoring and deploy checks.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
18#[serde(rename_all = "snake_case")]
19pub enum LaneFeature {
20    /// Basic events lanes.
21    Events,
22    /// Sequenced slots lanes.
23    SequencedSlots,
24    /// Journal lanes.
25    Journal,
26    /// Fanout-broadcast lanes.
27    FanoutBroadcast,
28}
29
30/// How a stage key should be interpreted by Cloud and policy surfaces.
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
32#[serde(rename_all = "snake_case")]
33pub enum StageKeyKind {
34    /// A fully stable, literal stage key.
35    Stable,
36    /// A parameterized stage key prefix such as `http_post:*`.
37    Prefix,
38}
39
40/// Shared policy-class vocabulary for runtime stage entries.
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
42#[serde(rename_all = "snake_case")]
43pub enum PolicyClassId {
44    /// Pure or deterministic transforms without external side effects.
45    PureTransform,
46    /// Side-effecting execution that may require approval or replay restrictions.
47    SideEffecting,
48}
49
50/// Replay posture attached to a stage or document.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
52#[serde(rename_all = "snake_case")]
53pub enum ReplaySupport {
54    /// Replay execution is allowed.
55    Allowed,
56    /// Replay is supported only as dry-run.
57    DryRunOnly,
58    /// Replay is not supported.
59    Unsupported,
60}
61
62/// Runtime environment posture recognized by Enterprise policy.
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
64#[serde(rename_all = "snake_case")]
65pub enum RuntimeEnvironment {
66    /// Development posture.
67    Dev,
68    /// Staging posture.
69    Staging,
70    /// Production posture.
71    Prod,
72}
73
74/// Side-effect policy in a given environment posture.
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
76#[serde(rename_all = "snake_case")]
77pub enum EnvironmentSideEffects {
78    /// Side effects may execute without an approval token.
79    Allowed,
80    /// Side effects may execute only with approval.
81    ApprovalRequired,
82    /// Side effects are denied.
83    Denied,
84}
85
86/// Machine-readable lane feature availability.
87#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
88#[serde(rename_all = "camelCase")]
89pub struct LaneFeatureSupport {
90    /// Feature identifier.
91    pub feature: LaneFeature,
92    /// Targets on which the feature is available.
93    pub supported_targets: Vec<ExecutionTarget>,
94}
95
96/// Shared policy-class definitions published with a capability document.
97#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
98#[serde(rename_all = "camelCase")]
99pub struct PolicyClassDefinition {
100    /// Stable policy-class identifier.
101    pub id: PolicyClassId,
102    /// Human-readable meaning of the class.
103    pub description: String,
104}
105
106/// Replay defaults that matter for authoring and deployment checks.
107#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
108#[serde(rename_all = "camelCase")]
109pub struct ReplayConstraints {
110    /// Default replay posture for governed executions.
111    pub default_mode: ReplaySupport,
112    /// Default replay action quota.
113    pub max_actions: u64,
114    /// Default replay input-byte quota.
115    pub max_input_bytes: u64,
116}
117
118/// Environment-level restrictions relevant to approval and deployment.
119#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
120#[serde(rename_all = "camelCase")]
121pub struct EnvironmentRestriction {
122    /// Environment posture.
123    pub environment: RuntimeEnvironment,
124    /// Side-effect policy in that posture.
125    pub side_effects: EnvironmentSideEffects,
126    /// Approval capability ids that become relevant in that posture.
127    #[serde(default, skip_serializing_if = "Vec::is_empty")]
128    pub required_approval_capabilities: Vec<String>,
129}
130
131/// One catalog entry in the runtime capability document.
132#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
133#[serde(rename_all = "camelCase")]
134pub struct StageCatalogEntry {
135    /// Stable key or key family.
136    pub key: String,
137    /// Whether the key is literal or parameterized.
138    pub key_kind: StageKeyKind,
139    /// Short operator-facing description.
140    pub description: String,
141    /// Targets the stage may appear on.
142    pub supported_targets: Vec<ExecutionTarget>,
143    /// Policy-class identifier for the stage.
144    pub policy_class: PolicyClassId,
145    /// Approval capability ids required when this stage executes under governed postures.
146    #[serde(default, skip_serializing_if = "Vec::is_empty")]
147    pub approval_capabilities: Vec<String>,
148    /// Replay support for this stage family.
149    pub replay_support: ReplaySupport,
150    /// Environment postures where the stage may appear.
151    pub environments: Vec<RuntimeEnvironment>,
152}
153
154/// Machine-readable runtime capability contract published by Enterprise runtimes.
155#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
156#[serde(rename_all = "camelCase")]
157pub struct RuntimeCapabilityDocument {
158    /// Capability schema version.
159    pub schema_version: u32,
160    /// Product or binary publishing the document.
161    pub product: String,
162    /// Top-level target support.
163    pub supported_targets: Vec<ExecutionTarget>,
164    /// LaneGraph feature availability.
165    pub lane_features: Vec<LaneFeatureSupport>,
166    /// Stage catalog entries the runtime understands.
167    pub stage_catalog: Vec<StageCatalogEntry>,
168    /// Shared policy-class definitions.
169    pub policy_classes: Vec<PolicyClassDefinition>,
170    /// Replay defaults visible to Cloud and operators.
171    pub replay_constraints: ReplayConstraints,
172    /// Environment restrictions visible to Cloud and operators.
173    pub environment_restrictions: Vec<EnvironmentRestriction>,
174}
175
176/// Build a stable-key stage catalog entry.
177pub fn stable_stage_catalog_entry(
178    key: impl Into<String>,
179    description: impl Into<String>,
180    supported_targets: Vec<ExecutionTarget>,
181    policy_class: PolicyClassId,
182    replay_support: ReplaySupport,
183    environments: Vec<RuntimeEnvironment>,
184    approval_capabilities: Vec<String>,
185) -> StageCatalogEntry {
186    StageCatalogEntry {
187        key: key.into(),
188        key_kind: StageKeyKind::Stable,
189        description: description.into(),
190        supported_targets,
191        policy_class,
192        approval_capabilities,
193        replay_support,
194        environments,
195    }
196}
197
198/// Build a parameterized-key stage catalog entry.
199pub fn prefix_stage_catalog_entry(
200    key: impl Into<String>,
201    description: impl Into<String>,
202    supported_targets: Vec<ExecutionTarget>,
203    policy_class: PolicyClassId,
204    replay_support: ReplaySupport,
205    environments: Vec<RuntimeEnvironment>,
206    approval_capabilities: Vec<String>,
207) -> StageCatalogEntry {
208    StageCatalogEntry {
209        key: key.into(),
210        key_kind: StageKeyKind::Prefix,
211        description: description.into(),
212        supported_targets,
213        policy_class,
214        approval_capabilities,
215        replay_support,
216        environments,
217    }
218}
219
220/// Build a complete runtime capability document around a stage catalog.
221pub fn runtime_capability_document(
222    product: impl Into<String>,
223    stage_catalog: Vec<StageCatalogEntry>,
224) -> RuntimeCapabilityDocument {
225    let replay_limits = byteor_policy::ReplayLimits::default();
226    RuntimeCapabilityDocument {
227        schema_version: CAPABILITY_SCHEMA_VERSION,
228        product: product.into(),
229        supported_targets: default_supported_targets(),
230        lane_features: default_lane_feature_support(),
231        stage_catalog,
232        policy_classes: vec![
233            PolicyClassDefinition {
234                id: PolicyClassId::PureTransform,
235                description: "Deterministic or pure transforms with no external side effects"
236                    .to_string(),
237            },
238            PolicyClassDefinition {
239                id: PolicyClassId::SideEffecting,
240                description:
241                    "Side-effecting execution that may require approval and replay gating"
242                        .to_string(),
243            },
244        ],
245        replay_constraints: ReplayConstraints {
246            default_mode: ReplaySupport::DryRunOnly,
247            max_actions: replay_limits.max_actions,
248            max_input_bytes: replay_limits.max_input_bytes,
249        },
250        environment_restrictions: vec![
251            EnvironmentRestriction {
252                environment: RuntimeEnvironment::Dev,
253                side_effects: EnvironmentSideEffects::Allowed,
254                required_approval_capabilities: Vec::new(),
255            },
256            EnvironmentRestriction {
257                environment: RuntimeEnvironment::Staging,
258                side_effects: EnvironmentSideEffects::ApprovalRequired,
259                required_approval_capabilities: vec!["execute_side_effects".to_string()],
260            },
261            EnvironmentRestriction {
262                environment: RuntimeEnvironment::Prod,
263                side_effects: EnvironmentSideEffects::ApprovalRequired,
264                required_approval_capabilities: vec!["execute_side_effects".to_string()],
265            },
266        ],
267    }
268}
269
270fn default_supported_targets() -> Vec<ExecutionTarget> {
271    vec![ExecutionTarget::SingleRing, ExecutionTarget::LaneGraph]
272}
273
274fn default_lane_feature_support() -> Vec<LaneFeatureSupport> {
275    let lane_graph_only = vec![ExecutionTarget::LaneGraph];
276    vec![
277        LaneFeatureSupport {
278            feature: LaneFeature::Events,
279            supported_targets: lane_graph_only.clone(),
280        },
281        LaneFeatureSupport {
282            feature: LaneFeature::SequencedSlots,
283            supported_targets: lane_graph_only.clone(),
284        },
285        LaneFeatureSupport {
286            feature: LaneFeature::Journal,
287            supported_targets: lane_graph_only.clone(),
288        },
289        LaneFeatureSupport {
290            feature: LaneFeature::FanoutBroadcast,
291            supported_targets: lane_graph_only,
292        },
293    ]
294}