Skip to main content

platform_module_remote/
protocol.rs

1use platform_core::{ActorContext, TraceContext};
2use platform_module::{AdminPage, ModuleManifest};
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7pub type RemoteManifestResponse = ModuleManifest;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct RemoteServiceManifestResponse {
12    pub name: String,
13    #[serde(default)]
14    pub version: Option<String>,
15    #[serde(default)]
16    pub provider: Option<RemoteServiceProviderMetadata>,
17    #[serde(default)]
18    pub compatibility: Option<RemoteServiceCompatibility>,
19    #[serde(default)]
20    pub config: Vec<RemoteServiceConfigField>,
21    #[serde(default)]
22    pub env: Vec<RemoteServiceEnvField>,
23    #[serde(default)]
24    pub health: Option<RemoteServiceHealth>,
25    #[serde(default)]
26    pub local_process: Option<RemoteServiceLocalProcess>,
27    pub modules: Vec<ModuleManifest>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(rename_all = "camelCase")]
32pub struct RemoteServiceProviderMetadata {
33    pub name: String,
34    #[serde(default)]
35    pub vendor: Option<String>,
36    #[serde(default)]
37    pub summary: Option<String>,
38    #[serde(default)]
39    pub homepage: Option<String>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct RemoteServiceCompatibility {
45    #[serde(default)]
46    pub remote_protocol_version: Option<String>,
47    #[serde(default)]
48    pub required_host_features: Vec<String>,
49    #[serde(default)]
50    pub sdk_language: Option<String>,
51    #[serde(default)]
52    pub sdk_version: Option<String>,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56#[serde(rename_all = "camelCase")]
57pub struct RemoteServiceConfigField {
58    pub key: String,
59    #[serde(default)]
60    pub required: bool,
61    #[serde(default)]
62    pub default_value: Option<serde_json::Value>,
63    #[serde(default)]
64    pub secret: bool,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct RemoteServiceEnvField {
70    pub name: String,
71    #[serde(default)]
72    pub required: bool,
73    #[serde(default)]
74    pub example: Option<String>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct RemoteServiceHealth {
80    #[serde(default)]
81    pub manifest_url: Option<String>,
82    #[serde(default)]
83    pub ready_url: Option<String>,
84    #[serde(default)]
85    pub liveness_url: Option<String>,
86    #[serde(default)]
87    pub status_url: Option<String>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91#[serde(rename_all = "camelCase")]
92pub struct RemoteServiceLocalProcess {
93    pub command: String,
94    #[serde(default)]
95    pub cwd: Option<String>,
96    #[serde(default)]
97    pub env: BTreeMap<String, String>,
98    #[serde(default = "default_service_auto_start")]
99    pub auto_start: bool,
100    #[serde(default = "default_service_ready_timeout_ms")]
101    pub ready_timeout_ms: u64,
102}
103
104fn default_service_auto_start() -> bool {
105    true
106}
107
108fn default_service_ready_timeout_ms() -> u64 {
109    30_000
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113#[serde(untagged)]
114pub enum RemoteManifestEnvelope {
115    Service(RemoteServiceManifestResponse),
116    Module(ModuleManifest),
117}
118
119/// Standard error response shape for the remote module protocol.
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct RemoteErrorEnvelope {
122    pub error: RemoteErrorBody,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct RemoteErrorBody {
127    pub code: String,
128    pub message: String,
129    #[serde(default)]
130    pub retryable: bool,
131    #[serde(default)]
132    pub details: Vec<RemoteErrorDetail>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct RemoteErrorDetail {
137    pub field: Option<String>,
138    pub reason: String,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct RemoteListResponse {
143    pub records: Vec<Value>,
144    pub next_cursor: Option<String>,
145}
146
147impl From<RemoteListResponse> for AdminPage {
148    fn from(value: RemoteListResponse) -> Self {
149        Self {
150            records: value.records,
151            next_cursor: value.next_cursor,
152        }
153    }
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct RemoteGetResponse {
158    pub record: Option<Value>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct RemoteActionInvokeResponse {
163    pub result: Value,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct RemoteQueryResponse {
168    pub data: Value,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct RemoteAdminListRequest {
173    pub entity: String,
174    pub limit: i64,
175    pub cursor: Option<String>,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct RemoteAdminGetRequest {
180    pub entity: String,
181    pub id: String,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct RemoteAdminActionInvokeRequest {
186    pub action: String,
187    pub input: Value,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct RemoteAdminQueryRequest {
192    pub query: String,
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct RemoteHttpProxyInvokeRequest {
197    pub request_id: String,
198    pub correlation_id: String,
199    pub module_name: String,
200    pub method: String,
201    pub declared_path: String,
202    pub remote_path: String,
203    pub path_params: BTreeMap<String, String>,
204    pub headers: BTreeMap<String, String>,
205    pub body: Option<Value>,
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct RemoteHttpProxyInvokeResponse {
210    pub status_code: u16,
211    pub body: Option<Value>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct RemoteFunctionInvokeRequest {
216    pub request_id: String,
217    pub function_run_id: String,
218    pub function_name: String,
219    pub attempt: u32,
220    pub correlation_id: String,
221    pub causation_id: Option<String>,
222    pub actor: ActorContext,
223    pub trace: TraceContext,
224    pub input: Value,
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct RemoteFunctionInvokeResponse {
229    pub output: Value,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct RemoteEventHandleRequest {
234    pub request_id: String,
235    pub outbox_event_id: String,
236    pub handler_name: String,
237    pub event_name: String,
238    pub event_version: u16,
239    pub source_module: String,
240    pub aggregate_type: String,
241    pub aggregate_id: String,
242    pub correlation_id: String,
243    pub causation_id: Option<String>,
244    pub occurred_at: String,
245    pub actor: ActorContext,
246    pub trace: TraceContext,
247    pub payload: Value,
248    pub headers: Value,
249}
250
251#[derive(Debug, Clone, Default, Serialize, Deserialize)]
252pub struct RemoteEventHandleResponse {
253    #[serde(default)]
254    pub actions: Vec<RemoteEventResultAction>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
258#[serde(tag = "type", rename_all = "snake_case")]
259pub enum RemoteEventResultAction {
260    EnqueueFunction { function_name: String, input: Value },
261}