use super::super::*;
use super::support::*;
fn open_seeded_store(
prefix: &str,
receipts: usize,
) -> Result<(std::path::PathBuf, SqliteReceiptStore, Keypair), Box<dyn std::error::Error>> {
let path = unique_db_path(prefix);
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..receipts {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-head-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
Ok((path, store, keypair))
}
#[test]
fn seed_verified_head_matches_persisted_state() -> Result<(), Box<dyn std::error::Error>> {
let (path, store, keypair) = open_seeded_store("chio-head-seed", 5)?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let head = seed_verified_head(&connection)?;
assert_eq!(head.claim_log_count, 5);
assert_eq!(head.claim_log_max_seq, 5);
assert_eq!(head.checkpoint_seq(), 1);
assert_eq!(head.checkpointed_entry_seq(), 3);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn verify_head_accepts_matching_head_and_catches_up_forward(
) -> Result<(), Box<dyn std::error::Error>> {
let (path, store, keypair) = open_seeded_store("chio-head-accept", 4)?;
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
verify_head_against_latest_checkpoint(&connection, &mut head)?;
store.create_next_receipt_checkpoint(4, &keypair)?;
verify_head_against_latest_checkpoint(&connection, &mut head)?;
assert_eq!(head.checkpoint_seq(), 1);
assert_eq!(head.checkpointed_entry_seq(), 4);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn verify_head_rejects_tampered_latest_checkpoint_with_conflict(
) -> Result<(), Box<dyn std::error::Error>> {
let (path, store, keypair) = open_seeded_store("chio-head-tamper", 3)?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
let error = verify_head_against_latest_checkpoint(&connection, &mut head)
.err()
.ok_or("tampered checkpoint must be rejected")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("chio receipt audit"),
"Conflict must point the operator at the audit CLI, got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn claim_log_delta_aggregate_is_scoped_to_the_floor() -> Result<(), Box<dyn std::error::Error>> {
let (path, store, _keypair) = open_seeded_store("chio-head-delta", 6)?;
let connection = store.connection()?;
assert_eq!(claim_log_delta_count_and_max_seq(&connection, 0)?, (6, 6));
assert_eq!(claim_log_delta_count_and_max_seq(&connection, 4)?, (2, 6));
assert_eq!(claim_log_delta_count_and_max_seq(&connection, 6)?, (0, 6));
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn incremental_append_updates_the_head_and_stays_correct() -> Result<(), Box<dyn std::error::Error>>
{
let path = unique_db_path("chio-head-incremental");
let store = SqliteReceiptStore::open(&path)?; assert!(store.incremental_verification_enabled());
let keypair = receipt_test_keypair();
for i in 0..7 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-inc-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let snapshot = store.writer_head_snapshot();
assert_eq!(snapshot.claim_log_count, 7);
assert_eq!(snapshot.claim_log_max_seq, 7);
let connection = store.connection()?;
let reference = seed_verified_head(&connection)?;
assert_eq!(snapshot.claim_log_count, reference.claim_log_count);
assert_eq!(snapshot.claim_log_max_seq, reference.claim_log_max_seq);
assert_eq!(snapshot.checkpoint_seq, reference.checkpoint_seq());
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn append_denies_when_head_diverges() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-deny");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-deny-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
store.flush_receipt_writes()?;
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
drop(connection);
let receipt = sample_receipt_with_keypair("rcpt-deny-after-tamper", 99, &keypair);
let error = store
.append_chio_receipt_returning_seq(&receipt)
.err()
.ok_or("append after tamper must be denied")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(message.contains("chio receipt audit"), "got: {message}");
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let status = store.receipt_checkpoint_status(Some(1))?;
assert!(!status.healthy);
let checkpoint_error = status
.checkpoint_error
.ok_or("audit must report the fault")?;
assert!(
checkpoint_error.contains("checkpoint") || checkpoint_error.contains("1"),
"audit must localize the divergent checkpoint: {checkpoint_error}"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn writer_routed_inserts_do_not_false_conflict_the_next_append(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-resync");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
let receipt = sample_receipt_with_keypair("rcpt-resync-0", 1, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
store.flush_receipt_writes()?;
let child = sample_child_receipt_with_keypair_and_timestamp("child-resync-1", 2, &keypair);
store.append_child_receipt_record(&child)?;
store.create_next_receipt_checkpoint(2, &keypair)?;
for i in 1..4 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-resync-{i}"), (i + 2) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let snapshot = store.writer_head_snapshot();
assert_eq!(snapshot.claim_log_max_seq, 5); assert_eq!(snapshot.checkpoint_seq, 1);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn full_verification_fallback_still_catches_projection_drift(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-fallback");
let keypair = receipt_test_keypair();
let receipt_id = {
let store = SqliteReceiptStore::open(&path)?;
let receipt = sample_receipt_with_keypair("rcpt-fallback-0", 1, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
store.flush_receipt_writes()?;
receipt.id.clone()
};
let store = SqliteReceiptStore::open_existing_with_options(
&path,
crate::SqliteStoreOptions {
pool: crate::SqlitePoolConfig::default(),
incremental_verification: false,
},
)?;
assert!(!store.incremental_verification_enabled());
tamper_claim_log_tool_receipt(&store, &receipt_id, |receipt| {
receipt.tool_name = "tampered".to_string();
});
let receipt = sample_receipt_with_keypair("rcpt-fallback-1", 2, &keypair);
let error = store
.append_chio_receipt_returning_seq(&receipt)
.err()
.ok_or("full-path append after tamper must be denied")?;
assert!(matches!(error, ReceiptStoreError::Conflict(_)));
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn reseed_clears_a_poisoned_head_after_repairing_the_database(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-reseed");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-reseed-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let original: String = connection.query_row(
"SELECT statement_json FROM kernel_checkpoints WHERE checkpoint_seq = 1",
[],
|row| row.get(0),
)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
drop(connection);
let receipt = sample_receipt_with_keypair("rcpt-reseed-denied", 50, &keypair);
assert!(store.append_chio_receipt_returning_seq(&receipt).is_err());
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = ?1 WHERE checkpoint_seq = 1",
rusqlite::params![original],
)?;
drop(connection);
store.reseed_verified_head()?;
let receipt = sample_receipt_with_keypair("rcpt-reseed-ok", 51, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
store.flush_receipt_writes()?;
let health = store.receipt_store_health()?;
assert!(
health.writer.last_error.is_none(),
"reseed must clear last_error"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn reseed_on_still_corrupt_store_stays_poisoned() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-reseed-fail");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-reseed-fail-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let original: String = connection.query_row(
"SELECT statement_json FROM kernel_checkpoints WHERE checkpoint_seq = 1",
[],
|row| row.get(0),
)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
drop(connection);
let denied_before_reseed =
sample_receipt_with_keypair("rcpt-reseed-fail-denied-before", 50, &keypair);
assert!(store
.append_chio_receipt_returning_seq(&denied_before_reseed)
.is_err());
let reseed_error = store
.reseed_verified_head()
.err()
.ok_or("reseed on a still-corrupt store must return Err")?;
match &reseed_error {
ReceiptStoreError::Conflict(_) => {}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let health = store.receipt_store_health()?;
let last_error = health
.writer
.last_error
.clone()
.ok_or("writer last_error must be set after a failed reseed")?;
assert_eq!(
last_error,
reseed_error.to_string(),
"writer last_error must mirror the reseed failure"
);
let denied_after_reseed =
sample_receipt_with_keypair("rcpt-reseed-fail-denied-after", 51, &keypair);
let error = store
.append_chio_receipt_returning_seq(&denied_after_reseed)
.err()
.ok_or("append on a still-poisoned store must be denied")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("chio receipt audit"),
"poisoned Conflict must point the operator at the audit CLI, got: {message}"
);
assert!(
message.contains("verified head is unavailable"),
"poisoned Conflict must come from the Poisoned head_state (not a stale \
predecessor-check Conflict), got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = ?1 WHERE checkpoint_seq = 1",
rusqlite::params![original],
)?;
drop(connection);
store.reseed_verified_head()?;
let receipt = sample_receipt_with_keypair("rcpt-reseed-fail-recovered", 52, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
store.flush_receipt_writes()?;
let health = store.receipt_store_health()?;
assert!(
health.writer.last_error.is_none(),
"reseed after a real repair must clear last_error"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn poisoned_head_reports_writer_serving_closed() -> Result<(), Box<dyn std::error::Error>> {
let (temp_dir, path) = temp_db("chio-head-poison-serving")?;
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt = sample_receipt_with_keypair(
&format!("rcpt-poison-serving-{i}"),
(i + 1) as u64,
&keypair,
);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
assert!(
!store.writer_serving_closed(),
"a healthy writer with a verified head must serve"
);
let connection = store.connection()?;
let original: String = connection.query_row(
"SELECT statement_json FROM kernel_checkpoints WHERE checkpoint_seq = 1",
[],
|row| row.get(0),
)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
drop(connection);
let denied = sample_receipt_with_keypair("rcpt-poison-serving-denied", 50, &keypair);
assert!(store.append_chio_receipt_returning_seq(&denied).is_err());
assert!(
store.reseed_verified_head().is_err(),
"a reseed over a corrupt log must fail closed and poison the head"
);
assert!(
store.writer_serving_closed(),
"a poisoned head must report the writer serving-closed"
);
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = ?1 WHERE checkpoint_seq = 1",
rusqlite::params![original],
)?;
drop(connection);
store.reseed_verified_head()?;
assert!(
!store.writer_serving_closed(),
"a reseeded, verified head must serve again"
);
drop(store);
temp_dir.close()?;
Ok(())
}
#[test]
fn poisoned_head_reads_store_unhealthy() -> Result<(), Box<dyn std::error::Error>> {
let (temp_dir, path) = temp_db("chio-head-poison-health")?;
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt = sample_receipt_with_keypair(
&format!("rcpt-head-poison-health-{i}"),
(i + 1) as u64,
&keypair,
);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let baseline = store.receipt_store_health()?;
assert!(
baseline.healthy,
"a verified head with no write error must read healthy"
);
assert!(!store.writer_serving_closed());
store.receipt_commit_actor.health.set_head_poisoned(true);
assert!(
store.writer_serving_closed(),
"a poisoned head must fail the pre-dispatch gate closed"
);
let report = store.receipt_store_health()?;
assert!(
report.writer.last_error.is_none(),
"the poison window records no per-batch last_error"
);
assert_eq!(
report.writer_level,
HealthLevel::Healthy,
"the supervised writer thread is still alive"
);
assert!(
!report.healthy,
"a store whose verified head is poisoned must read unhealthy so readiness and the pre-dispatch gate agree"
);
drop(store);
temp_dir.close()?;
Ok(())
}
#[test]
fn reseed_clears_stale_flush_error() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-reseed-clears-flush-error");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt = sample_receipt_with_keypair(
&format!("rcpt-reseed-flush-{i}"),
(i + 1) as u64,
&keypair,
);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let original: String = connection.query_row(
"SELECT statement_json FROM kernel_checkpoints WHERE checkpoint_seq = 1",
[],
|row| row.get(0),
)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
drop(connection);
let denied = sample_receipt_with_keypair("rcpt-reseed-flush-denied", 50, &keypair);
assert!(store.append_chio_receipt_returning_seq(&denied).is_err());
assert!(
store.flush_receipt_writes().is_err(),
"a poisoned append must leave the standalone flush returning the stale error"
);
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = ?1 WHERE checkpoint_seq = 1",
rusqlite::params![original],
)?;
drop(connection);
store.reseed_verified_head()?;
let report = store.flush_receipt_writes();
assert!(
report.is_ok(),
"reseed success must clear the stale flush error: {report:?}"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn retention_repair_clears_stale_flush_error() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-repair-clears-flush-error");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt = sample_receipt_with_keypair(
&format!("rcpt-repair-flush-{i}"),
(i + 1) as u64,
&keypair,
);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let original: String = connection.query_row(
"SELECT statement_json FROM kernel_checkpoints WHERE checkpoint_seq = 1",
[],
|row| row.get(0),
)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = replace(statement_json, '\"batch_end_seq\":3', '\"batch_end_seq\":2')",
[],
)?;
drop(connection);
let denied = sample_receipt_with_keypair("rcpt-repair-flush-denied", 50, &keypair);
assert!(store.append_chio_receipt_returning_seq(&denied).is_err());
assert!(
store.flush_receipt_writes().is_err(),
"a poisoned append must leave the standalone flush returning the stale error"
);
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET statement_json = ?1 WHERE checkpoint_seq = 1",
rusqlite::params![original],
)?;
drop(connection);
store.retention_repair("unused-archive.sqlite3")?;
let report = store.flush_receipt_writes();
assert!(
report.is_ok(),
"retention repair success must clear the stale flush error: {report:?}"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn catch_up_validates_checkpoint_projections() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-catchup-bad-projections");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..6 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-catchup-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let checkpoint_one = store
.load_checkpoint_by_seq(1)?
.ok_or("checkpoint 1 missing")?;
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
assert_eq!(head.checkpoint_seq(), 1);
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_project_tree_head;")?;
let range_bytes = canonical_receipt_bytes(&store, 4, 6);
let checkpoint_two = build_checkpoint_with_previous(
2,
4,
6,
&range_bytes,
&keypair,
Some(&checkpoint_one),
&[chio_kernel::checkpoint::checkpoint_chain_leaf_hash(
&checkpoint_one.body,
)?],
)?;
insert_checkpoint_row(&store, &checkpoint_two, checkpoint_two.body.batch_end_seq);
let error = verify_head_against_latest_checkpoint(&connection, &mut head)
.err()
.ok_or("catch-up must reject a checkpoint with missing projection rows")?;
assert!(
matches!(error, ReceiptStoreError::Conflict(_)),
"expected a fail-closed Conflict, got {error:?}"
);
assert_eq!(
head.checkpoint_seq(),
1,
"the head must NOT adopt a checkpoint whose projection rows are invalid"
);
drop(connection);
let _ = fs::remove_file(path);
let good_path = unique_db_path("chio-catchup-good-projections");
let good_store = SqliteReceiptStore::open(&good_path)?;
for i in 0..6 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-catchup-ok-{i}"), (i + 1) as u64, &keypair);
good_store.append_chio_receipt_returning_seq(&receipt)?;
}
good_store.flush_receipt_writes()?;
good_store.create_next_receipt_checkpoint(3, &keypair)?; let good_connection = good_store.connection()?;
let mut good_head = seed_verified_head(&good_connection)?;
assert_eq!(good_head.checkpoint_seq(), 1);
good_store.create_next_receipt_checkpoint(3, &keypair)?; verify_head_against_latest_checkpoint(&good_connection, &mut good_head)?;
assert_eq!(
good_head.checkpoint_seq(),
2,
"a valid extension with intact projection rows must be adopted"
);
drop(good_connection);
let _ = fs::remove_file(good_path);
Ok(())
}
#[test]
fn catch_up_rejects_divergent_chain_root_before_advancing_head(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-catchup-divergent-chain-root");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..6 {
let receipt = sample_receipt_with_keypair(
&format!("rcpt-catchup-root-{i}"),
(i + 1) as u64,
&keypair,
);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let checkpoint_one = store
.load_checkpoint_by_seq(1)?
.ok_or("checkpoint 1 missing")?;
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
let verified_frontier = head
.chain_frontier
.clone()
.ok_or("seed must retain the verified chain frontier")?;
assert_eq!(verified_frontier.leaf_count(), 1);
assert_eq!(verified_frontier.root(), checkpoint_one.body.chain_root);
let range_bytes = canonical_receipt_bytes(&store, 4, 6);
let mut forged = build_checkpoint_with_previous(
2,
4,
6,
&range_bytes,
&keypair,
Some(&checkpoint_one),
&[chio_kernel::checkpoint::checkpoint_chain_leaf_hash(
&checkpoint_one.body,
)?],
)?;
assert_ne!(
forged.body.chain_root,
Some(chio_core::hashing::Hash::zero())
);
forged.body.chain_root = Some(chio_core::hashing::Hash::zero());
forged.signature = keypair.sign(&canonical_json_bytes(&forged.body)?);
insert_checkpoint_row(&store, &forged, forged.body.batch_end_seq);
let error = verify_head_against_latest_checkpoint(&connection, &mut head)
.err()
.ok_or("a divergent peer chain_root must fail closed")?;
assert!(
error
.to_string()
.contains("checkpoint 2 chain_root does not match the persisted chain"),
"unexpected catch-up error: {error}"
);
assert_eq!(
head.latest_checkpoint.as_ref(),
Some(&checkpoint_one),
"root rejection must not advance the verified checkpoint"
);
assert_eq!(
head.chain_frontier.as_ref(),
Some(&verified_frontier),
"root rejection must not mutate the verified frontier"
);
head.chain_frontier = None;
assert!(
verify_head_against_latest_checkpoint(&connection, &mut head).is_err(),
"cache-miss catch-up must also reject the divergent signed root"
);
assert_eq!(head.latest_checkpoint.as_ref(), Some(&checkpoint_one));
assert!(head.chain_frontier.is_none());
drop(connection);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn catch_up_preserves_v1_frontier_for_v2_successor() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-catchup-v1-frontier");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..6 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-catchup-v1-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let mut checkpoint_one =
build_checkpoint(1, 1, 2, &canonical_receipt_bytes(&store, 1, 2), &keypair)?;
checkpoint_one.body.schema = chio_kernel::checkpoint::CHECKPOINT_SCHEMA_V1.to_string();
checkpoint_one.body.chain_root = None;
checkpoint_one.signature = keypair.sign(&canonical_json_bytes(&checkpoint_one.body)?);
insert_checkpoint_row(&store, &checkpoint_one, checkpoint_one.body.batch_end_seq);
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
assert_eq!(head.checkpoint_seq(), 1);
head.chain_frontier = None;
let checkpoint_one_leaf =
chio_kernel::checkpoint::checkpoint_chain_leaf_hash(&checkpoint_one.body)?;
let mut checkpoint_two = build_checkpoint_with_previous(
2,
3,
4,
&canonical_receipt_bytes(&store, 3, 4),
&keypair,
Some(&checkpoint_one),
&[checkpoint_one_leaf],
)?;
checkpoint_two.body.schema = chio_kernel::checkpoint::CHECKPOINT_SCHEMA_V1.to_string();
checkpoint_two.body.chain_root = None;
checkpoint_two.signature = keypair.sign(&canonical_json_bytes(&checkpoint_two.body)?);
insert_checkpoint_row(&store, &checkpoint_two, checkpoint_two.body.batch_end_seq);
verify_head_against_latest_checkpoint(&connection, &mut head)?;
assert_eq!(head.latest_checkpoint.as_ref(), Some(&checkpoint_two));
let checkpoint_two_leaf =
chio_kernel::checkpoint::checkpoint_chain_leaf_hash(&checkpoint_two.body)?;
let legacy_frontier =
CheckpointChainFrontier::from_leaves(&[checkpoint_one_leaf, checkpoint_two_leaf]);
assert_eq!(head.chain_frontier.as_ref(), Some(&legacy_frontier));
let checkpoint_three = build_checkpoint_with_previous(
3,
5,
6,
&canonical_receipt_bytes(&store, 5, 6),
&keypair,
Some(&checkpoint_two),
&[checkpoint_one_leaf, checkpoint_two_leaf],
)?;
insert_checkpoint_row(
&store,
&checkpoint_three,
checkpoint_three.body.batch_end_seq,
);
verify_head_against_latest_checkpoint(&connection, &mut head)?;
assert_eq!(head.latest_checkpoint.as_ref(), Some(&checkpoint_three));
assert_eq!(
head.chain_frontier
.as_ref()
.and_then(CheckpointChainFrontier::root),
checkpoint_three.body.chain_root,
"the first v2 root must commit the complete v1 prefix"
);
drop(connection);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn writer_routed_fallback_append_catches_uncheckpointed_drift(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-writer-fallback-drift");
let keypair = receipt_test_keypair();
let receipt_id = {
let store = SqliteReceiptStore::open(&path)?;
let receipt = sample_receipt_with_keypair("rcpt-wfd-0", 1, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
store.flush_receipt_writes()?;
receipt.id.clone()
};
let store = SqliteReceiptStore::open_existing_with_options(
&path,
crate::SqliteStoreOptions {
pool: crate::SqlitePoolConfig::default(),
incremental_verification: false,
},
)?;
assert!(!store.incremental_verification_enabled());
tamper_claim_log_tool_receipt(&store, &receipt_id, |receipt| {
receipt.tool_name = "tampered".to_string();
});
let child = sample_child_receipt_with_keypair_and_timestamp("child-wfd-1", 2, &keypair);
let error = store
.append_child_receipt_record(&child)
.err()
.ok_or("writer-routed append after uncheckpointed tamper must be denied")?;
assert!(
matches!(error, ReceiptStoreError::Conflict(_)),
"expected fail-closed Conflict, got {error:?}"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn stale_head_validates_adopted_delta_before_trusting() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-stale-head-delta");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-stale-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
{
let connection = store.connection()?;
connection.execute(
r#"
INSERT INTO claim_receipt_log_entries (
entry_seq, receipt_id, receipt_kind, source_seq, timestamp,
capability_id, tool_server, tool_name, raw_json
) VALUES (4, 'orphan-oob-4', 'tool_receipt', 999, 1, 'cap-oob', 'shell', 'bash', '{}')
"#,
[],
)?;
}
let mut stale_head = VerifiedHead {
latest_checkpoint: None,
chain_frontier: None,
claim_log_count: 3,
claim_log_max_seq: 3,
};
let receipt = sample_receipt_with_keypair("rcpt-stale-append", 10, &keypair);
let raw_json = serde_json::to_string(&receipt)?;
let (response, _rx) = std::sync::mpsc::sync_channel(1);
let requests = vec![ReceiptCommitRequest {
receipt,
raw_json,
ensure_lineage: false,
response,
}];
let error = append_receipt_batch(&store.pool, &mut stale_head, true, &requests)
.err()
.ok_or("stale-head append over an out-of-band orphan row must be denied")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("chio receipt audit"),
"fail-closed Conflict must point at the audit CLI, got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let mut fresh_head = VerifiedHead {
latest_checkpoint: None,
chain_frontier: None,
claim_log_count: 4,
claim_log_max_seq: 4,
};
let receipt = sample_receipt_with_keypair("rcpt-stale-fresh", 11, &keypair);
let raw_json = serde_json::to_string(&receipt)?;
let (response, _rx) = std::sync::mpsc::sync_channel(1);
let requests = vec![ReceiptCommitRequest {
receipt,
raw_json,
ensure_lineage: false,
response,
}];
let results = append_receipt_batch(&store.pool, &mut fresh_head, true, &requests)?;
assert!(
results.iter().all(|result| result.is_ok()),
"empty-delta append must add no validation and succeed: {results:?}"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn resync_validates_adopted_delta() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-resync-delta");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-resync-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
{
let connection = store.connection()?;
connection.execute(
r#"
INSERT INTO claim_receipt_log_entries (
entry_seq, receipt_id, receipt_kind, source_seq, timestamp,
capability_id, tool_server, tool_name, raw_json
) VALUES (4, 'orphan-resync-4', 'tool_receipt', 999, 1, 'cap-oob', 'shell', 'bash', '{}')
"#,
[],
)?;
}
let mut stale_head = VerifiedHead {
latest_checkpoint: None,
chain_frontier: None,
claim_log_count: 3,
claim_log_max_seq: 3,
};
let connection = store.connection()?;
let error = resync_head_after_write(&connection, &mut stale_head)
.err()
.ok_or("resync over an out-of-band orphan row must be rejected")?;
match &error {
ReceiptStoreError::Conflict(message) => assert!(
message.contains("chio receipt audit"),
"fail-closed Conflict must point at the audit CLI, got: {message}"
),
other => return Err(format!("expected Conflict, got {other}").into()),
}
assert_eq!(
stale_head.claim_log_max_seq, 3,
"a rejected resync must not adopt the divergent delta"
);
let mut fresh_head = VerifiedHead {
latest_checkpoint: None,
chain_frontier: None,
claim_log_count: 4,
claim_log_max_seq: 4,
};
resync_head_after_write(&connection, &mut fresh_head)?;
assert_eq!(
fresh_head.claim_log_max_seq, 4,
"empty-delta resync must be a no-op"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn write_job_response_reflects_resync_failure() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-write-resync-fail");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-wrf-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let result: Result<(), ReceiptStoreError> =
store.writer_handle().run_write(move |connection| {
connection.execute(
r#"
INSERT INTO claim_receipt_log_entries (
entry_seq, receipt_id, receipt_kind, source_seq, timestamp,
capability_id, tool_server, tool_name, raw_json
) VALUES (4, 'orphan-wrf-4', 'tool_receipt', 999, 1, 'cap-oob', 'shell', 'bash', '{}')
"#,
[],
)?;
Ok(())
});
let error = result
.err()
.ok_or("a committed Write whose resync fails must return the resync error, not Ok")?;
match &error {
ReceiptStoreError::Conflict(message) => assert!(
message.contains("chio receipt audit"),
"resync failure must surface the fail-closed Conflict, got: {message}"
),
other => return Err(format!("expected Conflict, got {other}").into()),
}
let next: Result<(), ReceiptStoreError> = store.writer_handle().run_write(|_connection| Ok(()));
assert!(next.is_err(), "resync failure must poison the head");
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn writer_job_validates_adopted_delta_before_commit() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-writer-preval-delta");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-preval-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
{
let connection = store.connection()?;
connection.execute(
r#"
INSERT INTO claim_receipt_log_entries (
entry_seq, receipt_id, receipt_kind, source_seq, timestamp,
capability_id, tool_server, tool_name, raw_json
) VALUES (4, 'orphan-preval-4', 'tool_receipt', 999, 1, 'cap-oob', 'shell', 'bash', '{}')
"#,
[],
)?;
}
let result: Result<(), ReceiptStoreError> =
store.writer_handle().run_write_receipt(move |connection| {
connection.execute(
r#"
INSERT INTO claim_receipt_log_entries (
entry_seq, receipt_id, receipt_kind, source_seq, timestamp,
capability_id, tool_server, tool_name, raw_json
) VALUES (5, 'writer-job-row-5', 'tool_receipt', 5, 1, 'cap-job', 'shell', 'bash', '{}')
"#,
[],
)?;
Ok(())
});
let error = result
.err()
.ok_or("a receipt-appending writer job over a pre-existing orphan must be denied")?;
match &error {
ReceiptStoreError::Conflict(message) => assert!(
message.contains("chio receipt audit"),
"fail-closed Conflict must point at the audit CLI, got: {message}"
),
other => return Err(format!("expected Conflict, got {other}").into()),
}
let connection = store.connection()?;
let job_row: i64 = connection.query_row(
"SELECT COUNT(*) FROM claim_receipt_log_entries WHERE entry_seq = 5",
[],
|row| row.get(0),
)?;
assert_eq!(
job_row, 0,
"the writer job's receipt must NOT be durably inserted when a pre-existing orphan blocks the adopted baseline"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn head_trust_checks_all_checkpoint_columns() -> Result<(), Box<dyn std::error::Error>> {
let (path, store, keypair) = open_seeded_store("chio-head-allcols", 3)?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
verify_head_against_latest_checkpoint(&connection, &mut head)?;
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
let tampered = connection.execute(
"UPDATE kernel_checkpoints SET batch_end_seq = batch_end_seq + 1 WHERE checkpoint_seq = 1",
[],
)?;
assert_eq!(tampered, 1, "expected to tamper exactly one checkpoint row");
let error = verify_head_against_latest_checkpoint(&connection, &mut head)
.err()
.ok_or("a tampered signed-body column must be rejected on the fast path")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("batch_end_seq"),
"Conflict should name the tampered column, got: {message}"
);
assert!(
message.contains("chio receipt audit"),
"Conflict must point the operator at the audit CLI, got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn adopted_delta_rejects_interior_gap() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-adopted-delta-gap");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..4 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-gap-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let connection = store.connection()?;
validate_adopted_claim_log_delta(&connection, 0, 4)?;
connection.execute_batch("DROP TRIGGER IF EXISTS claim_receipt_log_entries_reject_delete;")?;
let deleted = connection.execute(
"DELETE FROM claim_receipt_log_entries WHERE entry_seq = 3",
[],
)?;
assert_eq!(deleted, 1, "expected to remove exactly one claim-log row");
let error = validate_adopted_claim_log_delta(&connection, 0, 4)
.err()
.ok_or("a non-contiguous adopted delta must be rejected")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("not contiguous") && message.contains('3'),
"Conflict should identify the interior gap, got: {message}"
);
assert!(
message.contains("chio receipt audit"),
"Conflict must point the operator at the audit CLI, got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn adopted_delta_ignores_untrusted_watermark() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-adopted-delta-bogus-watermark");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..4 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-bogus-wm-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let connection = store.connection()?;
connection.execute_batch("DROP TRIGGER IF EXISTS claim_receipt_log_entries_reject_delete;")?;
let deleted = connection.execute(
"DELETE FROM claim_receipt_log_entries WHERE entry_seq = 3",
[],
)?;
assert_eq!(deleted, 1, "expected to remove exactly one claim-log row");
connection.execute(
"INSERT INTO receipt_retention_watermark \
(archived_through_entry_seq, archived_through_timestamp, archive_path, rotated_at) \
VALUES (4, 0, '', 0)",
[],
)?;
let error = validate_adopted_claim_log_delta(&connection, 0, 4)
.err()
.ok_or("an untrusted watermark must not let a non-contiguous delta pass")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("not contiguous") && message.contains('3'),
"Conflict should identify the interior gap, got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn tampered_checkpoint_signature_column_denies_append() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-sig-column-tamper");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-sigcol-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
store.append_chio_receipt_returning_seq(&sample_receipt_with_keypair(
"rcpt-sigcol-prime",
4,
&keypair,
))?;
store.flush_receipt_writes()?;
let tampered_signature_hex = keypair
.sign(b"unrelated-bytes-for-a-different-valid-signature")
.to_hex();
{
let connection = store.connection()?;
let original: String = connection.query_row(
"SELECT signature FROM kernel_checkpoints WHERE checkpoint_seq = 1",
[],
|row| row.get(0),
)?;
assert_ne!(original, tampered_signature_hex);
connection.execute_batch("DROP TRIGGER IF EXISTS kernel_checkpoints_reject_update;")?;
connection.execute(
"UPDATE kernel_checkpoints SET signature = ?1 WHERE checkpoint_seq = 1",
rusqlite::params![tampered_signature_hex],
)?;
}
let receipt = sample_receipt_with_keypair("rcpt-sigcol-after", 5, &keypair);
let error = store
.append_chio_receipt_returning_seq(&receipt)
.err()
.ok_or("append after signature-column tamper must be denied")?;
match &error {
ReceiptStoreError::Conflict(message) => {
assert!(
message.contains("chio receipt audit"),
"Conflict must point the operator at the audit CLI, got: {message}"
);
}
other => return Err(format!("expected Conflict, got {other}").into()),
}
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn divergent_newly_projected_row_is_rejected_before_head_advance(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-head-newproj-drift");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-newproj-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
let head_before = store.writer_head_snapshot().claim_log_max_seq;
assert_eq!(head_before, 3);
let connection = store.connection()?;
connection.execute_batch(
r#"
DROP TRIGGER IF EXISTS chio_tool_receipts_project_claim_log_entry;
CREATE TRIGGER chio_tool_receipts_project_claim_log_entry
AFTER INSERT ON chio_tool_receipts
BEGIN
INSERT INTO claim_receipt_log_entries (
receipt_id,
receipt_kind,
source_seq,
timestamp,
capability_id,
session_id,
parent_request_id,
request_id,
subject_key,
issuer_key,
tool_server,
tool_name,
raw_json
) VALUES (
NEW.receipt_id,
'tool_receipt',
NEW.seq,
NEW.timestamp,
NEW.capability_id,
NULL,
NULL,
NULL,
NEW.subject_key,
NEW.issuer_key,
NEW.tool_server,
'divergent-projected-tool-name',
NEW.raw_json
);
END;
"#,
)?;
drop(connection);
let receipt = sample_receipt_with_keypair("rcpt-newproj-divergent", 4, &keypair);
let error = store
.append_chio_receipt_returning_seq(&receipt)
.err()
.ok_or("a divergent newly-projected row must be rejected before the head advances")?;
assert!(
matches!(error, ReceiptStoreError::Conflict(_)),
"expected a fail-closed Conflict, got {error:?}"
);
let head_after = store.writer_head_snapshot().claim_log_max_seq;
assert_eq!(
head_after, head_before,
"the head must not advance past a divergent newly-projected row"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn reseed_runs_full_verification_in_non_incremental_mode() -> Result<(), Box<dyn std::error::Error>>
{
let path = unique_db_path("chio-reseed-nonincremental-fullverify");
let keypair = receipt_test_keypair();
let receipt_id = {
let store = SqliteReceiptStore::open(&path)?;
let mut first_id = String::new();
for i in 0..3 {
let receipt = sample_receipt_with_keypair(
&format!("rcpt-reseed-fv-{i}"),
(i + 1) as u64,
&keypair,
);
if i == 0 {
first_id = receipt.id.clone();
}
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
first_id
};
let store = SqliteReceiptStore::open_existing_with_options(
&path,
crate::SqliteStoreOptions {
pool: crate::SqlitePoolConfig::default(),
incremental_verification: false,
},
)?;
assert!(!store.incremental_verification_enabled());
tamper_claim_log_tool_receipt(&store, &receipt_id, |receipt| {
receipt.tool_name = "tampered".to_string();
});
let error = store.reseed_verified_head().err().ok_or(
"reseed in non-incremental mode must run the full verify and reject a corrupt log",
)?;
assert!(
matches!(error, ReceiptStoreError::Conflict(_)),
"expected a fail-closed Conflict from the full reseed verification, got {error:?}"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn writer_routed_write_increments_accepted_total() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-writer-routed-accepted");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
let parent = sample_receipt_with_keypair("rcpt-writer-routed-parent", 1, &keypair);
store.append_chio_receipt_returning_seq(&parent)?;
let baseline = store.flush_receipt_writes()?.writer.accepted_total;
let child = sample_child_receipt_with_keypair_and_timestamp("child-writer-routed", 2, &keypair);
store.append_child_receipt_record(&child)?;
let accepted = store.flush_receipt_writes()?.writer.accepted_total;
assert_eq!(
accepted,
baseline + 1,
"a successfully-enqueued writer-routed write must increment accepted_total"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn writer_routed_write_outcome_updates_committed_and_failed(
) -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-writer-routed-outcome");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
let parent = sample_receipt_with_keypair("rcpt-outcome-parent", 1, &keypair);
store.append_chio_receipt_returning_seq(&parent)?;
let baseline = store.flush_receipt_writes()?.writer;
let child = sample_child_receipt_with_keypair_and_timestamp("child-outcome", 2, &keypair);
store.append_child_receipt_record(&child)?;
let after_commit = store.flush_receipt_writes()?.writer;
assert_eq!(
after_commit.committed_total,
baseline.committed_total + 1,
"a writer-routed success must increment committed_total"
);
assert_eq!(
after_commit.failed_total, baseline.failed_total,
"a writer-routed success must not increment failed_total"
);
let failed =
store
.writer_handle()
.run_write(move |_connection| -> Result<(), ReceiptStoreError> {
Err(ReceiptStoreError::Conflict(
"intentional writer job failure".to_string(),
))
});
assert!(failed.is_err(), "the failing job must surface its error");
let after_fail = store.flush_receipt_writes()?.writer;
assert_eq!(
after_fail.failed_total,
after_commit.failed_total + 1,
"a writer-routed failure must increment failed_total"
);
assert_eq!(
after_fail.committed_total, after_commit.committed_total,
"a writer-routed failure must not increment committed_total"
);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn seq_unchanged_recheck_catches_projection_tamper() -> Result<(), Box<dyn std::error::Error>> {
let path = unique_db_path("chio-seq-unchanged-projection-tamper");
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-seq-tamper-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
store.create_next_receipt_checkpoint(3, &keypair)?;
let connection = store.connection()?;
let mut head = seed_verified_head(&connection)?;
assert_eq!(head.checkpoint_seq(), 1);
verify_head_against_latest_checkpoint(&connection, &mut head)?;
assert_eq!(head.checkpoint_seq(), 1);
connection.execute_batch("DROP TRIGGER IF EXISTS checkpoint_tree_heads_reject_update;")?;
connection.execute(
"UPDATE checkpoint_tree_heads SET merkle_root = ?1 WHERE checkpoint_seq = 1",
rusqlite::params!["00".repeat(32)],
)?;
let error = verify_head_against_latest_checkpoint(&connection, &mut head)
.err()
.ok_or("the seq-unchanged recheck must reject a tampered projection row")?;
assert!(
matches!(error, ReceiptStoreError::Conflict(_)),
"expected a fail-closed Conflict, got {error:?}"
);
drop(connection);
let _ = fs::remove_file(path);
Ok(())
}
#[test]
fn store_wide_append_failure_poisons_the_head() -> Result<(), Box<dyn std::error::Error>> {
let (temp_dir, path) = temp_db("chio-store-wide-poison")?;
let keypair = receipt_test_keypair();
let store = SqliteReceiptStore::open(&path)?;
for i in 0..3 {
let receipt =
sample_receipt_with_keypair(&format!("rcpt-poison-{i}"), (i + 1) as u64, &keypair);
store.append_chio_receipt_returning_seq(&receipt)?;
}
store.flush_receipt_writes()?;
{
let connection = store.connection()?;
connection.execute(
r#"
INSERT INTO claim_receipt_log_entries (
entry_seq, receipt_id, receipt_kind, source_seq, timestamp,
capability_id, tool_server, tool_name, raw_json
) VALUES (4, 'orphan-poison-4', 'tool_receipt', 999, 1, 'cap-oob', 'shell', 'bash', '{}')
"#,
[],
)?;
}
let health = ReceiptCommitWriterHealth::default();
health.set_head_poisoned(false);
let mut head_state = WriterHeadState::Verified(Box::new(VerifiedHead {
latest_checkpoint: None,
chain_frontier: None,
claim_log_count: 3,
claim_log_max_seq: 3,
}));
let receipt = sample_receipt_with_keypair("rcpt-poison-append", 10, &keypair);
let raw_json = serde_json::to_string(&receipt)?;
let (response, _rx) = std::sync::mpsc::sync_channel(1);
let requests = vec![ReceiptCommitRequest {
receipt,
raw_json,
ensure_lineage: false,
response,
}];
let flush_error = commit_receipt_batch(&store.pool, &mut head_state, true, requests, &health);
assert!(
flush_error.is_some(),
"a store-wide append failure must surface a flush error"
);
assert!(
health.head_poisoned.load(Ordering::SeqCst),
"a store-wide append failure must poison the head so the pre-dispatch gate fails closed"
);
assert!(
matches!(head_state, WriterHeadState::Poisoned(_)),
"a store-wide append failure must transition the head to Poisoned"
);
drop(store);
temp_dir.close()?;
Ok(())
}