///|
pub struct AuditRecord {
sequence : Int
event_id : String
provider : String
status : String
risk_level : String
route_handler : String
digest : String
} derive(Eq, Debug)
///|
pub fn AuditRecord::new(
sequence : Int,
event_id : String,
provider : String,
status : String,
risk_level : String,
route_handler : String,
digest : String,
) -> AuditRecord {
{ sequence, event_id, provider, status, risk_level, route_handler, digest }
}
///|
pub fn audit_digest(previous : String, output : GuardPipelineOutput) -> String {
stable_sign(
"audit",
previous +
"\n" +
output.verification.provider +
"\n" +
output.verification.event_id +
"\n" +
output.risk.level,
).value
}
///|
pub fn audit_record(
sequence : Int,
previous_digest : String,
output : GuardPipelineOutput,
) -> AuditRecord {
let status = if output.verification.is_ok() { "accepted" } else { "rejected" }
let handler = if output.route.matched { output.route.handler } else { "" }
AuditRecord::new(
sequence,
output.verification.event_id,
output.verification.provider,
status,
output.risk.level,
handler,
audit_digest(previous_digest, output),
)
}
///|
pub fn build_audit_log(
outputs : Array[GuardPipelineOutput],
) -> Array[AuditRecord] {
let mut previous = "root"
Array::makei(outputs.length(), i => {
let record = audit_record(i, previous, outputs[i])
previous = record.digest
record
})
}
///|
pub fn audit_log_markdown(records : Array[AuditRecord]) -> String {
let builder = StringBuilder::new()
builder.write_string(
"| seq | provider | event_id | status | risk | handler | digest |\n",
)
builder.write_string("| ---: | --- | --- | --- | --- | --- | --- |\n")
for i in 0.. Bool {
if records.length() != outputs.length() {
return false
}
let mut previous = "root"
for i in 0..