pub struct LogEntry<'a> {
pub user_id: i64,
pub action_type: ActionType,
pub model_name: &'a str,
pub object_id: i64,
pub ip_address: Option<&'a str>,
pub summary: String,
pub correlation_id: Option<&'a str>,
pub session_id: Option<i64>,
pub metadata: Option<Value>,
pub actor_user_id: Option<i64>,
pub event: Option<AuditEvent>,
}Fields§
§user_id: i64§action_type: ActionType§model_name: &'a str§object_id: i64§ip_address: Option<&'a str>§summary: String§correlation_id: Option<&'a str>Per-request UUID (R0). All audit rows written under one HTTP
request share this id so a future /admin/history/<id> page
can reconstruct the chain of events (“admin reset password →
all sessions revoked → security email dispatched”).
session_id: Option<i64>The session that performed the action, when applicable. CLI
emergency actions write None.
metadata: Option<Value>Structured before/after / extra metadata. JSONB column.
R2 emissions populate this with an object (not a scalar
or array) — the merge layer in record inserts
actor_user_id and similar typed sidecars into the object
before persistence, and a non-object value disables that
merge (the row still writes; a warning is logged).
actor_user_id: Option<i64>The acting principal when this row records one user
performing an action on another (admin password reset,
admin lock/unlock, admin revoke-sessions, etc.). Persisted
under metadata.actor_user_id — the column itself doesn’t
change.
R2 emissions set this via LogEntry::with_actor; R0/R1
emissions leave it None. The legacy Self::user_id
field continues to carry the actor for backwards-compat
with /admin/history’s “who did what” view; actor_user_id
is the typed mirror that lets metadata consumers (SIEM,
future per-user audit pivots) read the actor without
relying on heuristics about which row-shape sets
user_id to actor vs. target.
When Some(id) is set and metadata is also Some(obj),
record inserts the key into the object. If the existing
metadata already contains actor_user_id, the typed-field
value wins — the struct field is the source of truth.
event: Option<AuditEvent>When Some, supersedes action_type.as_str() as the
persisted rustio_admin_actions.action_type string. Set via
LogEntry::with_event; the action_type field becomes a
placeholder in that case (the convention is to pass
ActionType::Update). Used by R1+ recovery / authority /
identity emissions that need the richer typed vocabulary —
see DESIGN_AUDIT.md §3 + DESIGN_RECOVERY.md §6.
Implementations§
Source§impl<'a> LogEntry<'a>
impl<'a> LogEntry<'a>
Sourcepub fn new(
user_id: i64,
action_type: ActionType,
model_name: &'a str,
object_id: i64,
) -> Self
pub fn new( user_id: i64, action_type: ActionType, model_name: &'a str, object_id: i64, ) -> Self
Builder helper for the common case (every field that R0
added defaults to None). Existing call sites can migrate
incrementally.
Sourcepub fn with_actor(self, actor_user_id: i64) -> Self
pub fn with_actor(self, actor_user_id: i64) -> Self
Mark this entry as an admin acting on another user. The id
is persisted under metadata.actor_user_id by record,
not as a separate column. Pair with .with_event(...) for
the canonical R2 admin-action shape, e.g.
LogEntry::new(target_id, ActionType::Update, "users", target_id)
.with_event(AuditEvent::PasswordResetByOther)
.with_actor(admin_identity.user_id)Auto-throttle (no actor) leaves this None; the row’s
user_id column carries the affected user as the
closest-reasonable subject. See DESIGN_R2_ORGANISATIONAL.md
§5.2.
Sourcepub fn with_event(self, event: AuditEvent) -> Self
pub fn with_event(self, event: AuditEvent) -> Self
Promote this entry’s persisted action_type string from the
legacy ActionType (create/update/delete) trio to the
richer typed AuditEvent. The action_type field becomes
a placeholder; the convention is to pass ActionType::Update
to Self::new and chain .with_event(...).
let entry = LogEntry::new(user_id, ActionType::Update, "users", user_id)
.with_event(AuditEvent::PasswordChangedSelf);Use this for framework-internal authority + identity +
recovery audit rows per DESIGN_AUDIT.md §3 +
DESIGN_RECOVERY.md §6. Project code that records generic
CRUD on its own models continues to use Self::new alone
with the legacy ActionType trio.
Auto Trait Implementations§
impl<'a> Freeze for LogEntry<'a>
impl<'a> RefUnwindSafe for LogEntry<'a>
impl<'a> Send for LogEntry<'a>
impl<'a> Sync for LogEntry<'a>
impl<'a> Unpin for LogEntry<'a>
impl<'a> UnsafeUnpin for LogEntry<'a>
impl<'a> UnwindSafe for LogEntry<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more