Skip to main content

getmyid/
types.rs

1//! Identity types returned by the whoami daemon.
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Runner information containing both client-provided context and
7/// server-injected identity fields.
8///
9/// This object is designed to be passed directly to a config server,
10/// which can use it to route and customize configuration based on
11/// both the verified identity and client-provided context.
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
13pub struct Runner {
14    /// Application-level identity name (injected by whoami).
15    #[serde(default)]
16    pub identity: String,
17
18    /// Hostname where the process is running (injected by whoami).
19    #[serde(default)]
20    pub hostname: String,
21
22    /// Process name (injected by whoami).
23    #[serde(default)]
24    pub process: String,
25
26    /// Process ID (injected by whoami).
27    #[serde(default)]
28    pub pid: u32,
29
30    /// User ID (injected by whoami).
31    #[serde(default)]
32    pub uid: u32,
33
34    /// Group ID (injected by whoami).
35    #[serde(default)]
36    pub gid: u32,
37
38    /// Client-provided instance identifier (optional).
39    #[serde(default, skip_serializing_if = "Option::is_none")]
40    pub instance_id: Option<u64>,
41
42    /// Client-provided timestamp (optional).
43    #[serde(default, skip_serializing_if = "Option::is_none")]
44    pub timestamp: Option<u64>,
45
46    /// Additional client-provided fields.
47    #[serde(flatten, default)]
48    pub extra: HashMap<String, serde_json::Value>,
49}
50
51/// Client-provided runner context to send to whoami daemon.
52///
53/// These fields will be merged with server-injected identity fields
54/// in the response's `runner` object.
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
56pub struct RunnerRequest {
57    /// Instance identifier for dynamic configuration routing.
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub instance_id: Option<u64>,
60
61    /// Timestamp for request tracking.
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub timestamp: Option<u64>,
64
65    /// Additional custom fields.
66    #[serde(flatten)]
67    pub extra: HashMap<String, serde_json::Value>,
68}
69
70impl RunnerRequest {
71    /// Create a new empty runner request.
72    pub fn new() -> Self {
73        Self::default()
74    }
75
76    /// Set the instance ID.
77    pub fn with_instance_id(mut self, id: u64) -> Self {
78        self.instance_id = Some(id);
79        self
80    }
81
82    /// Set the timestamp.
83    pub fn with_timestamp(mut self, ts: u64) -> Self {
84        self.timestamp = Some(ts);
85        self
86    }
87
88    /// Set the timestamp to the current Unix timestamp.
89    pub fn with_current_timestamp(mut self) -> Self {
90        self.timestamp = Some(
91            std::time::SystemTime::now()
92                .duration_since(std::time::UNIX_EPOCH)
93                .map(|d| d.as_secs())
94                .unwrap_or(0),
95        );
96        self
97    }
98
99    /// Add a custom field.
100    pub fn with_field(mut self, key: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
101        self.extra.insert(key.into(), value.into());
102        self
103    }
104}
105
106/// Identity information returned by the whoami daemon.
107///
108/// This struct contains the application-level identity (name and URLs)
109/// and a `runner` object with process/host details and client context.
110#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
111pub struct Identity {
112    /// Application-level identity name (from rules.conf).
113    pub identity: String,
114
115    /// Identity Management (OAuth2/OIDC) URL for this identity.
116    pub idm_url: String,
117
118    /// Configuration/API server URL for this identity.
119    pub config_url: String,
120
121    /// Authentication token for this identity.
122    pub token: String,
123
124    /// Runner information containing process details and client context.
125    /// This object can be passed directly to a config server.
126    pub runner: Runner,
127}
128
129/// Raw response from the whoami daemon.
130#[derive(Debug, Deserialize)]
131pub(crate) struct DaemonResponse {
132    pub status: String,
133    #[serde(flatten)]
134    pub data: ResponseData,
135}
136
137/// Response data variants.
138#[derive(Debug, Deserialize)]
139#[serde(untagged)]
140pub(crate) enum ResponseData {
141    Success {
142        identity: String,
143        idm_url: String,
144        config_url: String,
145        token: String,
146        runner: Runner,
147    },
148    Error {
149        error_code: String,
150        message: String,
151    },
152}
153
154impl DaemonResponse {
155    /// Check if the response indicates success.
156    pub fn is_ok(&self) -> bool {
157        self.status == "ok"
158    }
159}