fix(machine): re-pair wipes the prior operator's config + watermarks (#70)

A new-seed re-pair UPSERTed the bunker binding but left fee_config, cassettes,
and the created_at replay watermarks intact. The watermarks are the trap: a new
backend whose first config event has a lower created_at than the old operator's
last event is silently dropped as a replay, so re-pairing a long-lived install
to a fresh backend appears to pair but never picks up new config.

Add resetForRepair() (main-process state-store): in one transaction it clears
fee_config and resets both replay watermarks to 0. Wired function → IPC
(state:reset-for-repair) → preload → renderer, and called from the re-pair branch
in signer-resolver, gated on an existing binding (re-pair only; a first pair has
nothing to reset). Deliberately preserves cassettes/cashbox/transactions — those
track PHYSICAL cash that survives an operator handover; a full wipe is the
factory-reset path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-07-02 21:13:40 +02:00 • committed by padreug
commit 78592d89f7
5 changed files with 42 additions and 0 deletions

View file

@ -27,6 +27,7 @@ import {
getBootstrapPublishedAt,
markBootstrapPublished,
resetBootstrapGate,
resetForRepair,
applyOperatorCassettesConfig,
getFeeConfig,
getLastKnownFeeConfigCreatedAt,
@ -355,6 +356,9 @@ ipcMain.handle('state:clear-bunker-binding', (): void => {
ipcMain.handle('state:reset-bootstrap-gate', (): void => {
resetBootstrapGate()
})
ipcMain.handle('state:reset-for-repair', (): void => {
resetForRepair()
})
// QR-pairing wizard (aiolabs/bitspire#52): an unpaired machine scans a
// spire-seed off its camera, and we persist it as VITE_SPIRE_SEED in the