* fix(enable-banking): recover error-state connections, respect PSD2 balance quota, clean error surface
Three defects from the 2026-07-09 production log triage, all in how the
enable-banking extension handles upstream (Enable Banking / ASPSP) failures:
1. Retry dead-end: a non-session sync failure parked the connection in
status='error', but POST /sync rejected anything not 'active' with 400,
so the UI's "Försök igen" button could never succeed and the connection
stayed stranded until a full re-auth. /sync now accepts 'error' (while
still rejecting 'expired': a dead consent needs re-authorization), and a
successful sync restores status='active' and clears error_message.
2. Balance quota burn: every sync (manual or cron) called the BALANCES
endpoint although PSD2 unattended consents allow only 4 calls/day
(observed 429 "Consent daily limit 4 is exceeded"), and the retry
wrapper retried those 429s twice against a daily quota. The sync now
skips the balance call while the stored balance_updated_at is fresher
than 12 hours, and authenticatedFetchWithRetry fails fast on a 429
whose body signals a daily limit.
3. Raw JSON in UI: sync failures persisted the raw English Enable Banking
error body into bank_connections.error_message, which the settings
panel renders verbatim. Failures are now mapped to short Swedish user
messages (shared constants in api-client.ts); the raw body stays in
server logs only.
Also ratchets the eslint baseline down by 1: the no-explicit-any disable
in the cron route was on the wrong line and never suppressed anything.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(enable-banking): treat future balance timestamps as stale (CodeRabbit)
A future balance_updated_at yielded a negative age that always passed the freshness check, suppressing balance refreshes indefinitely; only 0 <= age < BALANCE_MAX_AGE_MS now counts as fresh.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>