Fixes gap-3 from coord log 2026-06-01T18:30Z: the operator-fees
subscriber wasn't running during the 'awaiting-fees' maintenance state,
so the maintenance state had no path to clear. Every restart found
empty state.db, entered maintenance, never subscribed, never wrote.
Forever stuck.
Root cause: `initializeForProduction` bailed via early `return` when
the persisted fee config was null. The subscriber starts inside
`initializeWithHalIpc`, which was never reached.
Fix has three pieces:
1. Remove the early return. HAL + Lightning + operator-fees subscriber
all init even when `initError = 'awaiting-fees'` is set. The
maintenance card UI still blocks user interaction (no router-view
renders), and the state machine starts with zero fractions until
the first event lands.
2. New `UPDATE_FEE_CONFIG` event on the state machine, handled at the
root level — assigns `cashInFeeFraction` / `cashOutFeeFraction` onto
context so subsequent cashIn/cashOut entries pick them up via
setCashInFee / setCashOutFee actions. No actor restart needed.
3. `applyFeeConfig` (the operator-fees subscriber's onApply callback)
now dispatches UPDATE_FEE_CONFIG into the running actor AND clears
`initError` when it was 'awaiting-fees'. Operator publishes the
first event → ATM auto-unblocks → UI flips from maintenance card
to IdleView showing the new fee%. No `systemctl restart bitspire`
needed.
Adds three tests covering the new UPDATE_FEE_CONFIG handler:
- updates context fractions
- does not leave idle state
- propagates to context.feeFraction on next cashIn entry
(the load-bearing chain: subscriber → context → setCashInFee → fee
math is correct for the next transaction)
Total state-machine tests: 21 (was 18); apps/machine tests unchanged
at 24. All 12 workspace packages typecheck.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>