# Evolution 7 — Replay ledger review

Code: `cain/talos/talos_ledger.py`. Tests: `test_e7_ledger.py`. Models: F7-16, F7-19..F7-22.

## Guarantee

For all threads and processes that open **the same SQLite file on the same host**: an authorization is consumed
at most once. One `BEGIN IMMEDIATE` transaction checks the nonce and decision id, the clock high-water mark,
the invalidation floor, key revocation and decision revocation, then inserts the nonce, the execution-intent
row and an audit entry. WAL with `synchronous=FULL`.

| Situation | Behaviour | Evidence |
|---|---|---|
| 12 processes race one envelope | exactly one executes (one line appended by the command) | E7-L-001 |
| 16 threads race one envelope | exactly one executes | E7-L-002 |
| process killed inside the transaction | nothing consumed, nothing executed, envelope usable once | E7-L-010 |
| crash after consumption, before launch | consumed; reconciled to ABORTED; never replayable | E7-L-011 |
| crash after launch, before the outcome is recorded | reconciled to UNCERTAIN; never retried | E7-L-012 |
| clean restart | history kept | E7-L-013 |
| disk full | transaction fails -> INDETERMINATE -> no execution | E7-L-020 |
| file corrupted | integrity check at open; any error at use is a refusal | E7-L-021 |
| file deleted or replaced by an empty file | new ledger refuses everything that could have been issued before it existed | E7-L-022, E7-L-025 |
| lock held by another writer | bounded wait, then INDETERMINATE; works again when released | E7-L-024 |
| revocation racing consumption | serialised: a revocation that committed first always wins | E7-L-004..006 |
| ledger copied to another host, on a network filesystem, a symlink, world-writable, or a foreign database | refused at open | E7-L-030, E7-L-031 |
| audit rows edited, deleted, reordered | detected by the hash chain | E7-L-040 |
| illegal state change of a finished execution | refused | E7-L-041 |

## New-ledger quarantine

A ledger that is new cannot know which nonces an earlier ledger consumed. It sets its invalidation floor to
one second after its creation, and consumption refuses any envelope whose issue stamp minus the verifier's
skew allowance is before the floor. With the default 5 s skew, a new file-backed ledger accepts nothing for
about six seconds. An in-memory ledger has no floor and is refused for execution unless the deployer passes
`require_durable_ledger=False`.

## Limits — stated, not solved

* **Single host only.** Two hosts with two files do not share nonces; the same envelope could execute once on
  each. The ledger refuses to open on a host other than the one it was created on, and refuses network
  filesystems. A multi-host deployment needs a shared, linearizable store for consumption (for example the
  existing PBFT cluster or a single SQL primary with serializable transactions) and audience names per host.
  **This code does not provide distributed exactly-once execution and must not be described as doing so.**
* **Restore of an older copy of the same ledger** is not detected (same ledger id, plausible contents).
  Consumptions made after the backup are forgotten. The operator must call `raise_invalidation_floor()` after
  any restore; E7-L-023 keeps the gap visible and proves the procedure closes it. Pinning the ledger id
  (`expected_ledger_id`) detects replacement by a different ledger, not this.
* **The audit chain's head is stored in the same file.** Someone who can rewrite the file can recompute it.
* **Exactly-once effect is not provided.** The ledger gives at-most-once authorisation. If the worker ran and
  the outcome could not be recorded, the state is STARTED then UNCERTAIN; whether the side effect happened is
  for an operator to establish. Nothing retries automatically.
* **A privileged host user** can edit or delete the file.
