Skip to content

fix: protect linked-account flows across wallet session expiry - #932

Merged
greatest0fallt1me merged 1 commit into
Predictify-org:mainfrom
Adedoyinjr:fix/903-linked-account-session-expiry
Aug 30, 2026
Merged

fix: protect linked-account flows across wallet session expiry#932
greatest0fallt1me merged 1 commit into
Predictify-org:mainfrom
Adedoyinjr:fix/903-linked-account-session-expiry

Conversation

@Adedoyinjr

Copy link
Copy Markdown
Contributor

Closes #903

Summary

Hardens the existing linked-wallet flow against stale wallet sessions, identity changes, overlapping operations, duplicate submissions, stale callbacks, invalid persisted state, and unsafe transaction retries.

This change is intentionally scoped to the wallet-session boundary currently implemented by the frontend.

Implementation

  • Adds a global wallet-operation coordinator to WalletProvider.
  • Assigns a monotonic operation ID to every connect, disconnect, and reconciliation operation.
  • Allows wallet state to change only when an asynchronous result still belongs to the current operation.
  • Rejects unsupported wallet IDs before invoking the wallet SDK.
  • Makes disconnect a safety boundary that invalidates pending connect results.
  • Prevents duplicate and concurrent wallet identity mutations.
  • Treats persisted wallet state as untrusted metadata.
  • Structurally validates persisted wallet data and reconciles it with the live provider before restoring a connected state.
  • Adds wallet identity generations and invalidates transaction retry material when identity changes.
  • Adds deterministic, sanitized wallet error classification.
  • Exposes useful failure and recovery UI in LinkedAccounts and WalletModal.
  • Preserves existing connectWallet, disconnectWallet, and signTransaction interfaces with additive result/state fields.
  • Never automatically replays connect, disconnect, or transaction actions.

Acceptance criteria

Deterministic behavior

  • Duplicate and competing wallet operations return deterministic conflict results.
  • Only the current operation ID may commit state.
  • Stale callbacks cannot restore an old wallet identity.

Authorization and validation boundaries

  • Unsupported providers are rejected before SDK invocation.
  • Persisted wallet state is treated as metadata, not authentication proof.
  • Persisted addresses and provider metadata are validated before reconciliation.

Retries, partial failure, and concurrency

  • Connect/connect, disconnect/disconnect, and connect/disconnect races are serialized.
  • Failed disconnect keeps the last verified identity and exposes a recovery error.
  • Retry requires an explicit new user action.
  • Transaction retry data is invalidated when wallet identity changes.

Focused tests

Added coverage for:

  • successful connection
  • successful disconnect
  • rejected provider requests
  • invalid providers
  • malformed persisted state
  • duplicate connect/disconnect
  • concurrent provider attempts
  • connect/disconnect overlap
  • stale callbacks
  • identity mismatch
  • explicit retry
  • disconnect partial failure
  • transaction retry invalidation
  • sanitized error handling

Focused result:

  • 3 test suites passed
  • 19 tests passed

Compatibility

Existing public wallet APIs remain compatible:

  • connectWallet(walletId)
  • disconnectWallet()
  • signTransaction(xdr)

New state and result fields are additive.

Error handling and observability

  • Raw SDK error objects are not logged.
  • Complete wallet addresses, signed XDR, credentials, tokens, cookies, and sensitive callback data are not exposed.
  • Errors are mapped to deterministic categories including validation, conflict, identity change, wallet lock, network, and user rejection.

Repository authentication limitation

The current frontend does not contain an application authentication/session provider, authenticated linked-account API mutation, OAuth callback flow, JWT/cookie handling, or linked-account 401/403 flow.

This change therefore does not claim server-side authorization guarantees the frontend cannot provide. It hardens the actual wallet-session boundary that exists today without introducing fake authentication or backend behavior.

Validation

Focused #903 tests:

  • 3 suites passed
  • 19 tests passed

Changed-file ESLint:

  • Passed

Repository-wide validation is currently blocked by existing unrelated upstream failures:

  • pnpm type-check: existing syntax errors in unrelated files
  • pnpm lint: existing unrelated parse/lint errors
  • pnpm test: existing unrelated failing suites
  • pnpm validate: stops at the existing type-check failures

No unrelated validation rules or tests were weakened.
Closes #903

@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Adedoyinjr is attempting to deploy a commit to the Jagadeesh B's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Adedoyinjr Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

# Conflicts:
#	hooks/useTransaction.hook.ts
#	hooks/useWallet.hook.ts
@Adedoyinjr
Adedoyinjr force-pushed the fix/903-linked-account-session-expiry branch from 78dfa19 to 6dc39bf Compare August 29, 2026 14:29
@greatest0fallt1me
greatest0fallt1me merged commit 4d26a80 into Predictify-org:main Aug 30, 2026
0 of 2 checks passed
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.

[Quality-2][High] Protect linked-account flows across session expiry

2 participants