fix: Docker support, WAL race condition, pusher panic fixes

- Add multi-stage Dockerfile with tini, non-root user, healthcheck
- Fix SQLite WAL mode race between bal-server and bal-pusher (busy_timeout + retry)
- Fix tbl_stats missing UNIQUE index for ON CONFLICT clause
- Replace unwrap() panics in bal-pusher with graceful error handling
- Add docker/entrypoint.sh with BAL_PUSHER_NETWORK support
- cargo fmt across all files
This commit is contained in:
2026-07-16 21:24:09 -04:00
parent 56696050ec
commit fbe61a5862
8 changed files with 355 additions and 99 deletions

View File

@@ -6,32 +6,31 @@ use std::path::Path;
#[test]
fn test_open_db_blocks_traversal() {
let res = open_db("../etc/passwd");
assert!(
res.is_err(),
"Path with '..' should be rejected"
);
assert!(res.is_err(), "Path with '..' should be rejected");
let err = match res {
Err(e) => e,
Ok(_) => panic!("Expected error for traversal path"),
};
assert!(err.contains("'..'"), "Error should mention directory traversal: {}", err);
assert!(
err.contains("'..'"),
"Error should mention directory traversal: {}",
err
);
}
#[test]
fn test_open_db_blocks_forbidden_absolute() {
for path in ["/etc/passwd", "/proc/self/mem", "/dev/null", "/usr/bin/ls"] {
let res = open_db(path);
assert!(
res.is_err(),
"Absolute path {} should be rejected", path
);
assert!(res.is_err(), "Absolute path {} should be rejected", path);
let err = match res {
Err(e) => e,
Ok(_) => panic!("Expected error for forbidden path {}", path),
};
assert!(
err.contains("forbidden"),
"Error should mention forbidden prefix: {}", err
"Error should mention forbidden prefix: {}",
err
);
}
}
@@ -41,10 +40,7 @@ fn test_open_db_allows_relative() {
let test_path = "tmp_test_bal.db";
let _ = fs::remove_file(test_path);
let res = open_db(test_path);
assert!(
res.is_ok(),
"Valid relative path should be allowed"
);
assert!(res.is_ok(), "Valid relative path should be allowed");
let db = res.unwrap();
drop(db);
let _ = fs::remove_file(test_path);
@@ -61,10 +57,7 @@ fn test_open_db_wal_pragmas_set() {
let mut stmt = db.prepare("PRAGMA journal_mode;").unwrap();
if let Ok(State::Row) = stmt.next() {
let mode: String = stmt.read(0).unwrap();
assert_eq!(
mode, "wal",
"SQLite journal mode should be WAL"
);
assert_eq!(mode, "wal", "SQLite journal mode should be WAL");
} else {
panic!("Could not read journal_mode pragma");
}
@@ -84,17 +77,15 @@ fn test_open_db_rejects_symlink() {
fs::soft_link(real, link).unwrap();
let res = open_db(link);
assert!(
res.is_err(),
"Symlink DB path should be rejected"
);
assert!(res.is_err(), "Symlink DB path should be rejected");
let err = match res {
Err(e) => e,
Ok(_) => panic!("Expected error for symlink"),
};
assert!(
err.contains("symlink"),
"Error should mention symlink: {}", err
"Error should mention symlink: {}",
err
);
let _ = fs::remove_file(real);