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}