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, 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)]
216pub struct ProviderErrorBody {
217 pub code: String,
218 pub message: String,
219 #[serde(default)]
220 pub retryable: bool,
221 #[serde(default)]
222 pub retry_after_ms: Option<u64>,
223 #[serde(default)]
224 pub provider_trace_reference: Option<String>,
225 #[serde(default)]
226 pub details: Vec<ProviderErrorDetail>,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct ProviderErrorDetail {
231 pub field: Option<String>,
232 pub reason: String,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct ProviderListResponse {
237 pub records: Vec<Value>,
238 pub next_cursor: Option<String>,
239}
240
241impl From<ProviderListResponse> for AdminPage {
242 fn from(value: ProviderListResponse) -> Self {
243 Self {
244 records: value.records,
245 next_cursor: value.next_cursor,
246 }
247 }
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
251pub struct ProviderGetResponse {
252 pub record: Option<Value>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct ProviderActionInvokeResponse {
257 pub result: Value,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct ProviderQueryResponse {
262 pub data: Value,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct ProviderAdminListRequest {
267 pub entity: String,
268 pub limit: i64,
269 pub cursor: Option<String>,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct ProviderAdminGetRequest {
274 pub entity: String,
275 pub id: String,
276}
277
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct ProviderAdminActionInvokeRequest {
280 pub action: String,
281 pub input: Value,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
285pub struct ProviderAdminQueryRequest {
286 pub query: String,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct ProviderHttpProxyInvokeRequest {
291 pub request_id: String,
292 pub correlation_id: String,
293 pub module_name: String,
294 pub method: String,
295 pub declared_path: String,
296 pub provider_path: String,
297 pub path_params: BTreeMap<String, String>,
298 pub headers: BTreeMap<String, String>,
299 pub body: Option<Value>,
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct ProviderHttpProxyInvokeResponse {
304 pub status_code: u16,
305 pub body: Option<Value>,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
309pub struct ProviderFunctionInvokeRequest {
310 pub request_id: String,
311 pub function_run_id: String,
312 pub function_name: String,
313 pub attempt: u32,
314 pub correlation_id: String,
315 pub causation_id: Option<String>,
316 pub actor: ActorContext,
317 pub trace: TraceContext,
318 pub input: Value,
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct ProviderFunctionInvokeResponse {
323 pub output: Value,
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct ProviderEventHandleRequest {
328 pub request_id: String,
329 pub outbox_event_id: String,
330 pub handler_name: String,
331 pub event_name: String,
332 pub event_version: u16,
333 pub source_module: String,
334 pub aggregate_type: String,
335 pub aggregate_id: String,
336 pub correlation_id: String,
337 pub causation_id: Option<String>,
338 pub occurred_at: String,
339 pub actor: ActorContext,
340 pub trace: TraceContext,
341 pub payload: Value,
342 pub headers: Value,
343}
344
345#[derive(Debug, Clone, Default, Serialize, Deserialize)]
346pub struct ProviderEventHandleResponse {
347 #[serde(default)]
348 pub actions: Vec<ProviderEventResultAction>,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
352#[serde(tag = "type", rename_all = "snake_case")]
353pub enum ProviderEventResultAction {
354 EnqueueFunction { function_name: String, input: Value },
355}