Audit writer: open a record-less log, share the log-name rule, keep the lock file
M3a review findings 1, 2, 4 and part of 5. One empty log file made brokerd panic at startup (files[len - 2]); it now opens as an empty log. brokerd's name check tested one month digit, so a file bxctl ignored could become brokerd's latest file; both now use proto::is_audit_log_name. Writer no longer unlinks audit/.lock, which opened a two-writer window. No unwrap in short_check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,3 +91,16 @@ pub struct AuditRecord {
|
||||
pub prev: Hash32,
|
||||
pub event: AuditEvent,
|
||||
}
|
||||
|
||||
/// True if `name` is an audit log file: `YYYY-MM-DD.jsonl`, ASCII digits with `-` at positions 4
|
||||
/// and 7. `brokerd` and `bxctl audit verify` both decide with this, so they read the same files.
|
||||
pub fn is_audit_log_name(name: &str) -> bool {
|
||||
let Some(date) = name.strip_suffix(".jsonl") else {
|
||||
return false;
|
||||
};
|
||||
date.len() == 10
|
||||
&& date.bytes().enumerate().all(|(i, b)| match i {
|
||||
4 | 7 => b == b'-',
|
||||
_ => b.is_ascii_digit(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ pub mod ids;
|
||||
pub mod log;
|
||||
pub mod wire;
|
||||
|
||||
pub use audit::{ApprovalAnswer, AuditEvent, AuditRecord, DecisionRecord, ResultStatus};
|
||||
pub use audit::{
|
||||
ApprovalAnswer, AuditEvent, AuditRecord, DecisionRecord, ResultStatus, is_audit_log_name,
|
||||
};
|
||||
pub use chain::{ChainFailure, ChainReport, ChainVerifier, Location, TornTail};
|
||||
pub use class::DataClass;
|
||||
pub use frame::{FrameError, MAX_FRAME, read_frame, write_frame};
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//! Which file names are audit log files. `brokerd` and `bxctl audit verify` both use this one rule,
|
||||
//! so they always read the same set of files.
|
||||
|
||||
use proto::is_audit_log_name;
|
||||
|
||||
#[test]
|
||||
fn a_date_and_jsonl_is_a_log_file() {
|
||||
for name in ["2026-09-17.jsonl", "0000-00-00.jsonl", "9999-12-31.jsonl"] {
|
||||
assert!(is_audit_log_name(name), "{name}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_other_name_is_not() {
|
||||
for name in [
|
||||
"",
|
||||
".lock",
|
||||
"2026-0x-17.jsonl", // the second month digit
|
||||
"2026-x9-17.jsonl",
|
||||
"2026-09-1x.jsonl",
|
||||
"x026-09-17.jsonl",
|
||||
"2026_09-17.jsonl",
|
||||
"2026-09_17.jsonl",
|
||||
"2026-09-17.json",
|
||||
"2026-09-17.jsonl.bak",
|
||||
"2026-9-17.jsonl",
|
||||
"12026-09-17.jsonl",
|
||||
"2026-09-17.JSONL",
|
||||
"2026-09-17.jsonl", // a full-width digit is not an ASCII digit
|
||||
] {
|
||||
assert!(!is_audit_log_name(name), "{name}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user