Skip to main content

floopy/types/
decisions.rs

1use serde::Deserialize;
2use serde_json::Value;
3
4/// One row of the per-request decision audit trail. Nullable gateway fields
5/// are `Option` (`None` == JSON `null`).
6#[derive(Debug, Clone, Deserialize)]
7pub struct Decision {
8    /// The originating request id.
9    pub request_id: String,
10    /// Session the request belonged to, if any.
11    pub session_id: Option<String>,
12    /// RFC3339 timestamp of the originating request.
13    pub request_created_at: String,
14    /// Resolved upstream provider.
15    pub provider: Option<String>,
16    /// Resolved upstream model.
17    pub model: Option<String>,
18    /// Terminal status of the request.
19    pub status: String,
20    /// End-to-end latency in milliseconds.
21    pub latency_ms: Option<i64>,
22    /// Cost in micro-USD.
23    pub cost_micro_usd: Option<i64>,
24    /// Whether caching was enabled for the request.
25    pub cache_enabled: Option<bool>,
26    /// Detected threat label, if the firewall flagged the request.
27    pub threat: Option<String>,
28    /// Opaque routing/decision trace.
29    pub decision_trace: Option<Value>,
30    /// Routing confidence score.
31    pub confidence: Option<f64>,
32    /// Why that confidence was assigned.
33    pub confidence_reason: Option<String>,
34    /// Human-readable explanation of the decision.
35    pub explanation: Option<String>,
36}
37
38/// One page of [`crate::resources::Decisions::list`].
39#[derive(Debug, Clone, Deserialize)]
40pub struct DecisionListPage {
41    /// Decisions in this page.
42    pub items: Vec<Decision>,
43    /// Cursor for the next page, if any.
44    pub next_cursor: Option<String>,
45    /// Whether more pages follow.
46    pub has_more: bool,
47}
48
49/// Filters for [`crate::resources::Decisions::list`] / `pages` / `iter`.
50/// Default is "no filter".
51#[derive(Debug, Clone, Default)]
52pub struct DecisionListParams {
53    /// Restrict to one session.
54    pub session_id: Option<String>,
55    /// Inclusive lower bound (RFC3339).
56    pub from: Option<String>,
57    /// Inclusive upper bound (RFC3339).
58    pub to: Option<String>,
59    /// Page size.
60    pub limit: Option<u32>,
61    /// Opaque pagination cursor.
62    pub cursor: Option<String>,
63}
64
65impl DecisionListParams {
66    pub(crate) fn query(&self) -> Vec<(String, String)> {
67        let mut q = Vec::new();
68        if let Some(v) = &self.session_id {
69            q.push(("session_id".to_owned(), v.clone()));
70        }
71        if let Some(v) = &self.from {
72            q.push(("from".to_owned(), v.clone()));
73        }
74        if let Some(v) = &self.to {
75            q.push(("to".to_owned(), v.clone()));
76        }
77        if let Some(v) = self.limit {
78            q.push(("limit".to_owned(), v.to_string()));
79        }
80        if let Some(v) = &self.cursor {
81            q.push(("cursor".to_owned(), v.clone()));
82        }
83        q
84    }
85}