# Running the bander highly available

The bander has no state that matters between runs: it reads a file, derives salts, bands, commits, signs and writes a batch. That makes high availability simple, and it is tested (`server/bander-ha.test.js`).

## Active-active

- **Setup.** Run two or more bander hosts against the **same HSM key**, with the same custody spec, the same `--expect-kcv` and the same table.
- **They agree byte for byte.** Given the same input file, every host produces **byte-identical commitments**. Banding is deterministic: no clock, no randomness, exact decimal arithmetic. Any host can take any file.
- **Signatures differ, harmlessly.** ECDSA is randomised, so each host's leg signatures differ. The operator identifies a verdict by its **judgement**, not by signature bytes, so a failover resubmission is **one verdict** in every count and one webhook delivery. It is not equivocation either: the same commitments under two signatures are the same statement.

## Degraded mode is a stop

- **HSM check first.** Before reading a single row, the bander asks the HSM for its key check value. No answer means exit 2 and no batch.
- **No fallback, ever.** It never falls back to a key file, even one sitting next to it.
- **Mid-run failure.** If the HSM stops answering during a run, the whole run is abandoned: no batch, and no half-banded file.
- **Rerun later.** Because banding is deterministic, a rerun later produces exactly the batch the failed run would have.

## Failover procedure

1. Host A fails, or its HSM path fails.
2. Run the same file on host B. It bands to the same commitments.
3. Submit. If host A had already submitted some shipments, the resubmissions fold into the same verdicts; nothing is double-counted.

Store-and-forward belongs to the submitting side, not the bander. The bander never touches the network, so a submission gateway holds signed batches until the operator answers. Signed legs stay valid for later submission.

## Reprocessing under a new table

When a corridor ratifies a new table version:

- **Re-band** the retained source file with the new edges and `--table-version`, and submit with the new `corridor_ref`.
- **The result is a new verdict.** Legs under a different table carry a different corridor commitment, so they make a new judgement, not an overwrite. The earlier verdicts stay on the append-only ledger.
- **The operator never re-bands.** It holds no raw value; re-banding happens where the value lives.
- **The report.** `/replay` bounds a period into one signed report.
