fix(bank): 90-day lookback is the default: long PSD2 requests make some banks kill the session (#1964)

E2E #11: the account picker's fiscal-year default sent a 365-day request
for a 405-day-old fiscal year; Swedbank answered by TERMINATING the
session: zero transactions, connection expired, no error surfaced
(initial_sync_requested_from 2025-08-26, returned min/max null). 90
days worked.

- Default lookback mode is now 'fast' (90 days), labeled rekommenderas
  on a first connect; the fiscal-year option stays but carries an inline
  'vissa banker avbryter kopplingen' note when its span exceeds 90 days,
  and the long-range helper names the real failure mode + the SIE/CSV
  path for older history.
- SIE drop card: stage + arm in ONE click (three clicks was one too
  many): after the verdict, the single button reads 'Bokför:
  oåterkalleligt (BFL 5 kap 5 §)' and the deliberate click commits with
  confirmed=true.
- Skill: never re-ask an answered question; when a connect card
  rendered, do not paste the URL as text too.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-26 22:36:06 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent 53c4d0d194
commit c2f055b903
4 changed files with 35 additions and 22 deletions
@@ -133,7 +133,12 @@ export function AccountPickerDialog({
const chartError = Boolean(chartLoadError)
const [ledgerByUid, setLedgerByUid] = useState<Record<string, string>>({})
const [lookbackMode, setLookbackMode] = useState<LookbackMode>('fiscal-year')
// Default 'fast' (90 days): the known-good PSD2 window. The fiscal-year
// default used to send 365+-day requests that some banks (Swedbank) answer
// by TERMINATING the session: zero transactions, connection expired, no
// error surfaced (E2E 2026-08-26). Longer ranges stay available as explicit
// choices with the risk spelled out.
const [lookbackMode, setLookbackMode] = useState<LookbackMode>('fast')
const [customSubMode, setCustomSubMode] = useState<CustomSubMode>('date')
const [customDate, setCustomDate] = useState<string>('')
// Newest transaction date this CONNECTION has already imported (date null on
@@ -161,7 +166,7 @@ export function AccountPickerDialog({
)
setSelected(initial)
setSaveError(null)
setLookbackMode('fiscal-year')
setLookbackMode('fast')
setCustomSubMode('date')
setCustomDate('')
lookbackTouched.current = false
@@ -716,7 +721,10 @@ export function AccountPickerDialog({
className="mt-1"
/>
<span>
<span className="block">Senaste 90 dagar <span className="text-muted-foreground">(snabbt)</span></span>
<span className="block">Senaste 90 dagar{!gapFill && <span className="text-muted-foreground"> (rekommenderas)</span>}</span>
<span className="text-xs text-muted-foreground">
det längsta de flesta banker lämnar ut utan extra godkännande
</span>
</span>
</label>
@@ -734,6 +742,7 @@ export function AccountPickerDialog({
<span className="block">Sedan räkenskapsårets början</span>
<span className="text-xs text-muted-foreground tabular-nums">
från {settingsLoaded ? fiscalYearStart : '…'}
{settingsLoaded && daysBetween(fiscalYearStart) > 90 && ': vissa banker avbryter kopplingen vid så långa förfrågningar'}
</span>
</span>
</label>
@@ -793,13 +802,16 @@ export function AccountPickerDialog({
)}
{showLongRangeHelper && (
<p className="text-xs text-muted-foreground">
Din bank returnerar oftast max 90 dagar. Behöver du äldre transaktioner kan du{' '}
<p className="attn text-[12.5px]">
De flesta banker lämnar bara ut cirka 90 dagar utan extra godkännande, och vissa
(till exempel Swedbank) avbryter hela kopplingen vid längre förfrågningar: då hämtas
inget alls och banken måste kopplas om. Säkrast är 90 dagar här och äldre historik
via{' '}
<Link
href="/import?mode=sie"
className="text-foreground underline underline-offset-2"
>
importera via SIE eller bankfil
SIE eller kontoutdrag (CSV)
</Link>
. Vi visar exakt vad banken returnerade efter sparat val.
</p>