Files
boxmaker/crates/proto/src/audit.rs
T
kyle c6395b16f4 Replace the audit record with chained audit events
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
2026-09-19 00:22:25 -07:00

92 lines
2.4 KiB
Rust

//! Audit log record types. One JSON object per line, hash-chained by the exact bytes of each line.
use serde::{Deserialize, Serialize};
use crate::{CallId, DataClass, DenyReason, Hash32, SessionId, Timestamp};
// JSON: {"outcome":"denied","reason":"no_grant"} ; the tag sits beside the fields
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "outcome", rename_all = "snake_case", deny_unknown_fields)]
pub enum DecisionRecord {
Allowed {},
Ask {},
Denied { reason: DenyReason },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ApprovalAnswer {
Approved,
Refused,
Expired,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ResultStatus {
Result,
Failed,
}
// JSON: {"type":"decision","session":"…",…} ; the tag sits beside the fields
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
pub enum AuditEvent {
Decision {
session: SessionId,
call: CallId,
tool: String,
arguments: String,
outcome: DecisionRecord,
grant: Option<String>,
grant_sha256: Option<Hash32>,
taint: DataClass,
untrusted: bool,
},
Approval {
session: SessionId,
call: CallId,
decision: u64,
answer: ApprovalAnswer,
by: Option<String>,
post: Option<String>,
reason: Option<String>,
outcome: DecisionRecord,
grant: Option<String>,
grant_sha256: Option<Hash32>,
taint: DataClass,
untrusted: bool,
},
Result {
session: SessionId,
call: CallId,
decision: u64,
status: ResultStatus,
class: DataClass,
untrusted: bool,
truncated: bool,
bytes: u64,
sha256: Hash32,
taint_after: DataClass,
},
Recovery {
torn_bytes: u64,
torn_sha256: Hash32,
},
AcceptedBreak {
file: String,
line: u64,
last_good: Hash32,
},
}
// JSON: {"seq":0,"time":"…","prev":"…","event":{"type":"decision",…}} ; `event` is a nested object.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AuditRecord {
pub seq: u64,
pub time: Timestamp,
pub prev: Hash32,
pub event: AuditEvent,
}