Pace provider traffic and identify genuine foreground bank requests

This commit is contained in:
Lars Nolden
2026-09-10 17:47:44 +02:00
parent ba3ea6ae5a
commit 4324660888
13 changed files with 817 additions and 32 deletions
+4
View File
@@ -299,6 +299,10 @@ func (a *App) Balances(ctx context.Context, id string) ([]banking.Balance, error
// Only typed, locally generated errors are safe to expose; provider errors may
// wrap private response data even when their underlying cause is recognizable.
func bankFailure(err error, fallback string) error {
var background *banking.BackgroundQuotaError
if errors.As(err, &background) {
return fmt.Errorf("Enable Banking: %w", background)
}
var limited *ratelimit.RateLimitError
if errors.As(err, &limited) {
return fmt.Errorf("Enable Banking: %w", limited)
+8 -2
View File
@@ -270,7 +270,7 @@ func TestSyncMissingMembershipStillRejectsAccount(t *testing.T) {
}
func TestSyncTransactionFailuresPreserveProgressAndSafeErrors(t *testing.T) {
for _, scenario := range []string{"rate limit", "reconnect", "private response"} {
for _, scenario := range []string{"rate limit", "background rate limit", "reconnect", "private response"} {
t.Run(scenario, func(t *testing.T) {
a, s, b := backfillApp(t)
s = seed(t, a, s)
@@ -282,6 +282,9 @@ func TestSyncTransactionFailuresPreserveProgressAndSafeErrors(t *testing.T) {
switch scenario {
case "rate limit":
b.fetchErr = bankRateError(t)
case "background rate limit":
quota := &banking.BackgroundQuotaError{RateLimitError: ratelimit.NewError(time.Now().Add(6 * time.Hour))}
b.fetchErr = fmt.Errorf("private provider response: %w", quota)
case "reconnect":
b.fetchErr = fmt.Errorf("private provider response: %w", banking.ErrReconnect)
case "private response":
@@ -295,9 +298,12 @@ func TestSyncTransactionFailuresPreserveProgressAndSafeErrors(t *testing.T) {
if failed.Status.SyncError == "" || meta.Error == "" || strings.Contains(failed.Status.SyncError+meta.Error, "private provider response") {
t.Fatal("transaction failure was lost or exposed provider data")
}
if scenario == "rate limit" && (!strings.Contains(failed.Status.SyncError, "429") || !strings.Contains(meta.Error, "429") || !strings.Contains(meta.Error, "retry")) {
if strings.Contains(scenario, "rate limit") && (!strings.Contains(failed.Status.SyncError, "429") || !strings.Contains(meta.Error, "429") || !strings.Contains(meta.Error, "retry")) {
t.Fatal("transaction rate error was obscured")
}
if scenario == "background rate limit" && !strings.Contains(meta.Error, "background") {
t.Fatal("daily bank quota was confused with a short request throttle")
}
if meta.NeedsReconnect != (scenario == "reconnect") {
t.Fatal("transaction failure classified consent incorrectly")
}