Finding
TamperLog::append writes and flushes a new chain entry, advances its in-memory tail, and only then refreshes the authenticated entry-count sidecar. If the sidecar write fails, the method returns an error after the log has advanced. Reopening that otherwise valid log classifies the newer log/older seal state as truncation and refuses it as compromised; there is no supported recovery path.
Evidence
crates/koinon/src/tamper_log.rs:581-600 performs write_all, flush, updates prev_hash, sequence, and bytes_written, then calls self.refresh_seal()?.
crates/koinon/src/tamper_log_seal.rs:158-180 can fail while creating, writing, syncing, or renaming the seal's temporary file.
On the next open, terminal_result at tamper_log.rs:434-456 maps every valid-seal count mismatch to ChainStatus::Truncated; open_with_config at lines 524-529 accepts only Intact or Empty and returns ChainCompromised for the log-ahead state.
#231 concerns vault-mutation/audit atomicity and #226 concerns concurrent writers. Neither covers failure between the log append and its seal sidecar update.
Why this matters
A transient filesystem error at the sidecar boundary can convert a successfully written, cryptographically valid audit record into a log the library will no longer open. For a tamper-evident log, treating a known two-file commit window as indistinguishable from adversarial truncation creates an avoidable availability failure and pressures operators toward unsafe manual repair.
Desired correction
Define and implement a crash-consistent two-file protocol. At minimum, distinguish a fully verified log-ahead state from log truncation and safely re-seal it before allowing further writes; retain fail-closed behavior for missing or invalid links. Document the durability boundary and use failure injection around create/write/sync/rename.
Done when tests fail each seal-write stage after an appended entry, reopen the log, recover only when every extra keyed link verifies, and preserve detection of genuine tail removal or modification.
Finding
TamperLog::appendwrites and flushes a new chain entry, advances its in-memory tail, and only then refreshes the authenticated entry-count sidecar. If the sidecar write fails, the method returns an error after the log has advanced. Reopening that otherwise valid log classifies the newer log/older seal state as truncation and refuses it as compromised; there is no supported recovery path.Evidence
crates/koinon/src/tamper_log.rs:581-600performswrite_all,flush, updatesprev_hash,sequence, andbytes_written, then callsself.refresh_seal()?.crates/koinon/src/tamper_log_seal.rs:158-180can fail while creating, writing, syncing, or renaming the seal's temporary file.On the next open,
terminal_resultattamper_log.rs:434-456maps every valid-seal count mismatch toChainStatus::Truncated;open_with_configat lines 524-529 accepts onlyIntactorEmptyand returnsChainCompromisedfor the log-ahead state.#231 concerns vault-mutation/audit atomicity and #226 concerns concurrent writers. Neither covers failure between the log append and its seal sidecar update.
Why this matters
A transient filesystem error at the sidecar boundary can convert a successfully written, cryptographically valid audit record into a log the library will no longer open. For a tamper-evident log, treating a known two-file commit window as indistinguishable from adversarial truncation creates an avoidable availability failure and pressures operators toward unsafe manual repair.
Desired correction
Define and implement a crash-consistent two-file protocol. At minimum, distinguish a fully verified log-ahead state from log truncation and safely re-seal it before allowing further writes; retain fail-closed behavior for missing or invalid links. Document the durability boundary and use failure injection around create/write/sync/rename.
Done when tests fail each seal-write stage after an appended entry, reopen the log, recover only when every extra keyed link verifies, and preserve detection of genuine tail removal or modification.