Skip to content

Recover safely when tamper-log seal refresh fails after append #285

Description

@forkwright

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions