Skip to content

feat: add reauthOnFailure option to FamisClient#103

Merged
matthewtsmith merged 1 commit into
masterfrom
feat/reauth-on-failure
May 5, 2026
Merged

feat: add reauthOnFailure option to FamisClient#103
matthewtsmith merged 1 commit into
masterfrom
feat/reauth-on-failure

Conversation

@matthewtsmith
Copy link
Copy Markdown
Member

Summary

Adds an opt-in reauthOnFailure flag to FamisClient.withLoginCredential. When enabled, the client reactively handles 401 responses — it first tries the refresh-token swap, and if that also fails, falls back to a full re-login with the stored username/password and retries the original request once.

This makes explicit a behavior the legacy connector previously relied on implicitly. When the flag is omitted (default false), behavior is unchanged: 401s propagate as ApiError exactly as before.

Why

The connector platform overhaul wants the silent re-login behavior of the old SDK to be opt-in and explicit, rather than always-on. New connectors should be able to choose: refresh-token-only (default) or full-re-login fallback (opt-in).

Refs: docs/superpowers/plans/2026-05-05-facility360-rebuild.md Task 0.5.

Architectural choices

  • Reactive 401 path is a new dedicated response interceptor, attached only when reauthOnFailure is true. The default code path is byte-for-byte identical to before.
  • Loop prevention via a _reauthRetry marker on the request config — a single request is never retried more than once.
  • Credentials are only stored when the flag is on (this.reauthCredentials stays undefined otherwise).
  • Reuses FamisClient.login and FamisClient.refreshAuthCredential — no new HTTP plumbing.
  • Refresh-token attempted first (cheaper, matches the existing proactive expiry-check interceptor) before falling back to full re-login.
  • The axios instance is configured with validateStatus: () => true, so 401 responses RESOLVE rather than reject. The new interceptor lives in the success arm and inspects response.status === 401.

Test plan

  • New file tests/reauth-on-failure.test.ts covers three behaviors:
    • reauthOnFailure: true rescues a hard 401 (refresh fails, full login succeeds), token swapped, retried exactly once.
    • reauthOnFailure: true does NOT loop on persistent 401 — retries exactly once and surfaces the failure.
    • reauthOnFailure: false (default) propagates the 401 unchanged; refresh and login are never invoked reactively.
  • yarn test — full suite passes (6 tests across 2 suites).
  • yarn build — clean.

Notes / scope

  • The change affects withLoginCredential only. withAccessToken is unaffected: it has no username/password to fall back on, so re-login fundamentally cannot apply there. If callers using withAccessToken later need a similar hook, they'd need to supply a refresh callback, which is out of scope here.

🤖 Generated with Claude Code

…lback

Adds an opt-in `reauthOnFailure` flag to `FamisClient.withLoginCredential`. When
enabled, the client reactively handles 401 responses: it first attempts a
refresh-token swap (preferred), and if that fails, performs a full re-login
using the stored username/password before retrying the original request once.

This makes explicit a behavior the legacy connector relied on implicitly. When
the flag is omitted (default `false`), behavior is unchanged: 401s propagate.

Architectural notes:
- Reactive 401 path implemented as a NEW response interceptor that is only
  attached when `reauthOnFailure` is true, leaving the default code path
  byte-for-byte identical to before.
- Loop prevention via a `_reauthRetry` marker on the request config — a single
  request is never retried more than once.
- Stored credentials are populated only when the flag is on.
- Reuses `FamisClient.login` and `FamisClient.refreshAuthCredential`; no new
  HTTP plumbing.

Tests added in tests/reauth-on-failure.test.ts cover: rescue-on-401,
no-infinite-loop on persistent 401, and unchanged default behavior.

Refs: docs/superpowers/plans/2026-05-05-facility360-rebuild.md Task 0.5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@matthewtsmith matthewtsmith force-pushed the feat/reauth-on-failure branch from 320eedc to 1913321 Compare May 5, 2026 18:20
@matthewtsmith matthewtsmith merged commit 3db7d07 into master May 5, 2026
1 check passed
@matthewtsmith matthewtsmith deleted the feat/reauth-on-failure branch May 5, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant