Skip to main content

aion_proto/
deploy.rs

1//! Operator deploy API serde/prost wire types.
2//!
3//! These shapes mirror `proto/deploy.proto` and double as the JSON bodies of
4//! the `/deploy/*` HTTP routes (the archive upload itself rides a raw
5//! `application/octet-stream` body, not JSON). Deploy is an operator
6//! surface: it is deliberately separate from the workflow wire types so the
7//! caller SDK contract never grows deploy operations, and it is
8//! engine-global — no namespace field exists anywhere here.
9
10/// Proto representation of `LoadPackageRequest`: one complete `.aion`
11/// archive uploaded in a single unary message.
12#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
13pub struct ProtoLoadPackageRequest {
14    /// Complete `.aion` archive bytes.
15    #[prost(bytes = "vec", tag = "1")]
16    pub archive: Vec<u8>,
17}
18
19/// Proto representation of `LoadPackageResponse`.
20///
21/// Idempotency is specified behavior: re-sending the same archive succeeds
22/// with `freshly_loaded = false`, and `route_changed` reports whether the
23/// call re-pointed routing. A deploy pipeline may retry blindly.
24#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
25pub struct ProtoLoadPackageResponse {
26    /// Logical workflow type the package registers.
27    #[prost(string, tag = "1")]
28    pub workflow_type: String,
29    /// Textual content hash — the version identifier everywhere on the wire.
30    #[prost(string, tag = "2")]
31    pub content_hash: String,
32    /// Namespaced module name spawned for this version.
33    #[prost(string, tag = "3")]
34    pub deployed_entry_module: String,
35    /// Exported entry function spawned for this version.
36    #[prost(string, tag = "4")]
37    pub entry_function: String,
38    /// False = idempotent re-load (the hash was already resident).
39    #[prost(bool, tag = "5")]
40    pub freshly_loaded: bool,
41    /// False = the hash was already route-active (full no-op).
42    #[prost(bool, tag = "6")]
43    pub route_changed: bool,
44}
45
46/// Proto representation of `ListVersionsRequest` (engine-global; no namespace).
47#[derive(Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
48pub struct ProtoListVersionsRequest {}
49
50/// Proto representation of one loaded `WorkflowVersion` listing row.
51#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
52pub struct ProtoWorkflowVersion {
53    /// Logical workflow type this version belongs to.
54    #[prost(string, tag = "1")]
55    pub workflow_type: String,
56    /// Textual content hash identifying the package version.
57    #[prost(string, tag = "2")]
58    pub content_hash: String,
59    /// Namespaced module name spawned for this version.
60    #[prost(string, tag = "3")]
61    pub deployed_entry_module: String,
62    /// Exported entry function spawned for this version.
63    #[prost(string, tag = "4")]
64    pub entry_function: String,
65    /// Author-declared manifest version label.
66    #[prost(string, tag = "5")]
67    pub manifest_version: String,
68    /// RFC 3339 engine-local load instant.
69    #[prost(string, tag = "6")]
70    pub loaded_at: String,
71    /// Whether new dispatches of this type currently route to this version.
72    #[prost(bool, tag = "7")]
73    pub route_active: bool,
74}
75
76/// Proto representation of `ListVersionsResponse`.
77#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
78pub struct ProtoListVersionsResponse {
79    /// Every loaded version with its routing flag, sorted `(type, loaded_at)`.
80    #[prost(message, repeated, tag = "1")]
81    pub versions: Vec<ProtoWorkflowVersion>,
82}
83
84/// Proto representation of `RouteVersionRequest` (rollback / roll-forward).
85#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
86pub struct ProtoRouteVersionRequest {
87    /// Logical workflow type whose route is re-pointed.
88    #[prost(string, tag = "1")]
89    pub workflow_type: String,
90    /// Textual content hash of the already-loaded target version.
91    #[prost(string, tag = "2")]
92    pub content_hash: String,
93}
94
95/// Proto representation of `RouteVersionResponse`.
96#[derive(Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
97pub struct ProtoRouteVersionResponse {}
98
99/// Proto representation of `UnloadVersionRequest`.
100#[derive(Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
101pub struct ProtoUnloadVersionRequest {
102    /// Logical workflow type whose version is unloaded.
103    #[prost(string, tag = "1")]
104    pub workflow_type: String,
105    /// Textual content hash of the non-routed version to unload.
106    #[prost(string, tag = "2")]
107    pub content_hash: String,
108}
109
110/// Proto representation of `UnloadVersionResponse`.
111#[derive(Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, prost::Message)]
112pub struct ProtoUnloadVersionResponse {}
113
114#[cfg(test)]
115mod tests {
116    use super::{ProtoLoadPackageResponse, ProtoRouteVersionRequest, ProtoWorkflowVersion};
117
118    #[test]
119    fn deploy_shapes_round_trip_through_json() -> Result<(), serde_json::Error> {
120        let response = ProtoLoadPackageResponse {
121            workflow_type: "order".to_owned(),
122            content_hash: "a".repeat(64),
123            deployed_entry_module: format!("order${}", "a".repeat(64)),
124            entry_function: "run".to_owned(),
125            freshly_loaded: true,
126            route_changed: true,
127        };
128        let decoded: ProtoLoadPackageResponse =
129            serde_json::from_str(&serde_json::to_string(&response)?)?;
130        assert_eq!(decoded, response);
131
132        let route = ProtoRouteVersionRequest {
133            workflow_type: "order".to_owned(),
134            content_hash: "b".repeat(64),
135        };
136        let decoded: ProtoRouteVersionRequest =
137            serde_json::from_str(&serde_json::to_string(&route)?)?;
138        assert_eq!(decoded, route);
139
140        let version = ProtoWorkflowVersion {
141            workflow_type: "order".to_owned(),
142            content_hash: "c".repeat(64),
143            deployed_entry_module: format!("order${}", "c".repeat(64)),
144            entry_function: "run".to_owned(),
145            manifest_version: "c".repeat(64),
146            loaded_at: "2026-06-12T00:00:00Z".to_owned(),
147            route_active: false,
148        };
149        let decoded: ProtoWorkflowVersion =
150            serde_json::from_str(&serde_json::to_string(&version)?)?;
151        assert_eq!(decoded, version);
152        Ok(())
153    }
154}