1use chrono::{DateTime, Utc};
2use platform_core::{ActorContext, TraceContext};
3use platform_module::{AdminPage, ModuleManifest};
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::BTreeMap;
7
8pub const PROVIDER_PROTOCOL: &str = "lenso.provider.v1";
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase", deny_unknown_fields)]
12pub struct ProviderDescriptor {
13 pub protocol: String,
14 pub protocol_contract_digest: String,
15 pub service_id: String,
16 pub service_release_version: String,
17 pub service_release_digest: String,
18 pub runtime_instance_id: String,
19 #[serde(default)]
20 pub features: Vec<String>,
21 pub transports: Vec<ProviderTransportBinding>,
22 pub exports: Vec<ProviderExport>,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26#[serde(rename_all = "snake_case")]
27pub enum ProviderTransportBinding {
28 HttpJson,
29 Grpc,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33#[serde(rename_all = "camelCase", deny_unknown_fields)]
34pub struct ProviderExport {
35 pub export_key: String,
36 pub module_id: String,
37 pub module_version: String,
38 pub module_release_digest: String,
39 pub manifest_digest: String,
40 pub manifest: ModuleManifest,
41 #[serde(default)]
42 pub contract_digests: BTreeMap<String, String>,
43 pub ready: bool,
44 #[serde(default)]
45 pub readiness_reasons: Vec<String>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(rename_all = "snake_case")]
50pub enum ProviderOperationKind {
51 HttpRoute,
52 AdminList,
53 AdminGet,
54 AdminQuery,
55 AdminAction,
56 RuntimeFunction,
57 EventHandler,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "snake_case")]
62pub enum ProviderInvocationMode {
63 ReadOnly,
64 Durable,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68#[serde(rename_all = "camelCase", deny_unknown_fields)]
69pub struct ProviderInvocation {
70 pub protocol: String,
71 pub invocation_id: String,
72 pub request_id: String,
73 pub attempt: u32,
74 pub deadline: String,
75 pub service_release_digest: String,
76 pub export_key: String,
77 pub module_release_digest: String,
78 pub manifest_digest: String,
79 pub operation_kind: ProviderOperationKind,
80 pub operation_name: String,
81 pub operation_version: String,
82 pub mode: ProviderInvocationMode,
83 pub input_contract_digest: String,
84 pub output_contract_digest: String,
85 #[serde(default)]
86 pub tenant_id: Option<String>,
87 pub actor: ActorContext,
88 #[serde(default)]
89 pub delegation: Option<Value>,
90 #[serde(default)]
91 pub locale: Option<String>,
92 #[serde(default)]
93 pub context: BTreeMap<String, Value>,
94 pub correlation_id: String,
95 #[serde(default)]
96 pub causation_id: Option<String>,
97 pub trace: TraceContext,
98 pub content_type: String,
99 pub payload: Value,
100}
101
102#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
103#[serde(rename_all = "snake_case")]
104pub enum ProviderOutcomeStatus {
105 Pending,
106 Succeeded,
107 Rejected,
108 Failed,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase", deny_unknown_fields)]
113pub struct ProviderOutcome {
114 pub protocol: String,
115 pub invocation_id: String,
116 pub status: ProviderOutcomeStatus,
117 #[serde(default)]
118 pub result: Option<Value>,
119 #[serde(default)]
120 pub error: Option<ProviderErrorBody>,
121 #[serde(default)]
122 pub effect_evidence: Vec<Value>,
123 #[serde(default)]
124 pub host_effects: ProviderHostEffectBatch,
125 pub outcome_digest: String,
126}
127
128#[derive(Debug, Clone, Default, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase", deny_unknown_fields)]
130pub struct ProviderHostEffectBatch {
131 #[serde(default)]
132 pub events: Vec<ProviderHostEventEffect>,
133 #[serde(default)]
134 pub runtime_function_requests: Vec<ProviderHostRuntimeFunctionRequest>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase", deny_unknown_fields)]
139pub struct ProviderHostEventEffect {
140 pub event_id: String,
141 pub event_name: String,
142 pub event_version: u16,
143 pub source_module: String,
144 pub aggregate_type: String,
145 pub aggregate_id: String,
146 pub correlation_id: String,
147 #[serde(default)]
148 pub causation_id: Option<String>,
149 pub occurred_at: DateTime<Utc>,
150 pub payload: Value,
151 #[serde(default)]
152 pub headers: Value,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
156#[serde(rename_all = "camelCase", deny_unknown_fields)]
157pub struct ProviderHostRuntimeFunctionRequest {
158 pub request_id: String,
159 pub function_name: String,
160 pub input: Value,
161 pub correlation_id: String,
162 pub actor: ActorContext,
163 #[serde(default)]
164 pub tenant_id: Option<String>,
165 #[serde(default)]
166 pub trace: TraceContext,
167 #[serde(default)]
168 pub causation_id: Option<String>,
169 #[serde(default)]
170 pub max_attempts: Option<i32>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174#[serde(rename_all = "camelCase", deny_unknown_fields)]
175pub struct ProviderHealth {
176 pub protocol: String,
177 pub service_id: String,
178 pub service_release_digest: String,
179 pub live: bool,
180 pub ready: bool,
181 pub observed_at: String,
182 #[serde(default)]
183 pub exports: BTreeMap<String, ProviderExportHealth>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(rename_all = "camelCase", deny_unknown_fields)]
188pub struct ProviderExportHealth {
189 pub ready: bool,
190 #[serde(default)]
191 pub reasons: Vec<String>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195#[serde(rename_all = "camelCase", deny_unknown_fields)]
196pub struct ProviderInvocationReference {
197 pub invocation_id: String,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
201#[serde(rename_all = "camelCase", deny_unknown_fields)]
202pub struct ProviderInvocationAcknowledgement {
203 pub invocation_id: String,
204 pub outcome_digest: String,
205}
206
207pub type ProviderManifestResponse = ModuleManifest;
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct ProviderErrorEnvelope {
212 pub error: ProviderErrorBody,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
216#[serde(rename_all = "camelCase")]
217pub struct ProviderErrorBody {
218 pub code: String,
219 pub message: String,
220 #[serde(default)]
221 pub retryable: bool,
222 #[serde(default, alias = "retry_after_ms")]
223 pub retry_after_ms: Option<u64>,
224 #[serde(default, alias = "provider_trace_reference")]
225 pub provider_trace_reference: Option<String>,
226 #[serde(default)]
227 pub details: Vec<ProviderErrorDetail>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
231#[serde(rename_all = "camelCase")]
232pub struct ProviderErrorDetail {
233 pub field: Option<String>,
234 pub reason: String,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct ProviderListResponse {
239 pub records: Vec<Value>,
240 pub next_cursor: Option<String>,
241}
242
243impl From<ProviderListResponse> for AdminPage {
244 fn from(value: ProviderListResponse) -> Self {
245 Self {
246 records: value.records,
247 next_cursor: value.next_cursor,
248 }
249 }
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct ProviderGetResponse {
254 pub record: Option<Value>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct ProviderActionInvokeResponse {
259 pub result: Value,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize)]
263pub struct ProviderQueryResponse {
264 pub data: Value,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct ProviderAdminListRequest {
269 pub entity: String,
270 pub limit: i64,
271 pub cursor: Option<String>,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize)]
275pub struct ProviderAdminGetRequest {
276 pub entity: String,
277 pub id: String,
278}
279
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct ProviderAdminActionInvokeRequest {
282 pub action: String,
283 pub input: Value,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct ProviderAdminQueryRequest {
288 pub query: String,
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct ProviderHttpProxyInvokeRequest {
293 pub request_id: String,
294 pub correlation_id: String,
295 pub module_name: String,
296 pub method: String,
297 pub declared_path: String,
298 pub provider_path: String,
299 pub path_params: BTreeMap<String, String>,
300 pub headers: BTreeMap<String, String>,
301 pub body: Option<Value>,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
305pub struct ProviderHttpProxyInvokeResponse {
306 pub status_code: u16,
307 pub body: Option<Value>,
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
311pub struct ProviderFunctionInvokeRequest {
312 pub request_id: String,
313 pub function_run_id: String,
314 pub function_name: String,
315 pub attempt: u32,
316 pub correlation_id: String,
317 pub causation_id: Option<String>,
318 pub actor: ActorContext,
319 pub trace: TraceContext,
320 pub input: Value,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct ProviderFunctionInvokeResponse {
325 pub output: Value,
326}
327
328#[derive(Debug, Clone, Serialize, Deserialize)]
329pub struct ProviderEventHandleRequest {
330 pub request_id: String,
331 pub outbox_event_id: String,
332 pub handler_name: String,
333 pub event_name: String,
334 pub event_version: u16,
335 pub source_module: String,
336 pub aggregate_type: String,
337 pub aggregate_id: String,
338 pub correlation_id: String,
339 pub causation_id: Option<String>,
340 pub occurred_at: String,
341 pub actor: ActorContext,
342 pub trace: TraceContext,
343 pub payload: Value,
344 pub headers: Value,
345}
346
347#[derive(Debug, Clone, Default, Serialize, Deserialize)]
348pub struct ProviderEventHandleResponse {
349 #[serde(default)]
350 pub actions: Vec<ProviderEventResultAction>,
351}
352
353#[derive(Debug, Clone, Serialize, Deserialize)]
354#[serde(tag = "type", rename_all = "snake_case")]
355pub enum ProviderEventResultAction {
356 EnqueueFunction { function_name: String, input: Value },
357}