Skip to main content

dinio_sdk/models/
audit_log.rs

1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4/// One audit log entry: who did what to which resource, and how it ended
5/// ([`AuditLogs`](crate::api::AuditLogs)). Fields Core does not know, or does not show the
6/// caller, are `None`. Enum values are kept as strings (forward compatibility); the known
7/// ones are listed per field.
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct AuditLog {
10    /// UUIDv7, time-ordered.
11    pub id: Uuid,
12    /// When, ISO 8601 in UTC with milliseconds (`2026-10-27T09:14:03.120Z`).
13    pub ts: String,
14    /// Shared by every entry one API request produced.
15    #[serde(default, skip_serializing_if = "Option::is_none")]
16    pub request_id: Option<Uuid>,
17    /// `api` (a REST call), `relay` (a Relay connecting or syncing), `auth` (sign-in and
18    /// key checks) or `system` (Core's own work).
19    pub category: String,
20    /// `<resource>.<verb>`, e.g. `record.create`, `zone.api_key.delete`.
21    pub action: String,
22    /// `success`, or why not: `denied` (401/403), `not_found`, `conflict`, `invalid`
23    /// (other 4xx), `error` (5xx).
24    pub outcome: String,
25    /// HTTP status of an API call.
26    #[serde(default, skip_serializing_if = "Option::is_none")]
27    pub http_status: Option<u16>,
28    /// `user` (web app), `user_key` (`du_…`), `zone_key` (`dz_…`), `edge` (a Relay),
29    /// `system` or `anonymous`.
30    pub actor_type: String,
31    /// The user who acted.
32    #[serde(default, skip_serializing_if = "Option::is_none")]
33    pub actor_user_id: Option<Uuid>,
34    /// The zone of a zone key that acted.
35    #[serde(default, skip_serializing_if = "Option::is_none")]
36    pub actor_zone_id: Option<Uuid>,
37    /// Readable actor (email, Relay name), kept after the actor is deleted.
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub actor_label: Option<String>,
40    /// Client IP; shown only on the caller's own actions (to an Admin on all).
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub ip: Option<String>,
43    /// e.g. `record`, `zone`.
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub resource_type: Option<String>,
46    /// Id of the resource (usually a uuid, not always).
47    #[serde(default, skip_serializing_if = "Option::is_none")]
48    pub resource_id: Option<String>,
49    /// Readable target, e.g. a zone name or `www.example.com A`.
50    #[serde(default, skip_serializing_if = "Option::is_none")]
51    pub resource_name: Option<String>,
52    /// The zone the operation belongs to.
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    pub zone_id: Option<Uuid>,
55    /// For a PATCH: names of the fields sent, never their values.
56    #[serde(default, skip_serializing_if = "Option::is_none")]
57    pub fields: Option<Vec<String>>,
58    /// Core's error code (`FORBIDDEN`, `MANAGED_RECORD`, …) when it did not succeed.
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub error_code: Option<String>,
61}