Skip to content

🥅 server: bridge credential fallback and retry on timeout#896

Merged
cruzdanilo merged 2 commits intomainfrom
fallback
Mar 27, 2026
Merged

🥅 server: bridge credential fallback and retry on timeout#896
cruzdanilo merged 2 commits intomainfrom
fallback

Conversation

@mainqueg
Copy link
Copy Markdown
Contributor

@mainqueg mainqueg commented Mar 18, 2026

Summary by CodeRabbit

  • New Features

    • Automatic credential fallback by email during customer status changes
    • Onboarding now uses a stable idempotency key and retries on timeouts/5xx
    • Customer records now include an email field
  • Bug Fixes / Data Integrity

    • Bridge identifier is enforced unique across credentials to prevent duplicate pairing
  • Tests

    • Expanded coverage for fallback flows, retries, idempotency, error cases, and event tracking

Open with Devin

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 18, 2026

🦋 Changeset detected

Latest commit: 504c9b6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@exactly/server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds persona email-based credential fallback for bridge webhook handling, idempotent Ramp customer creation with retry-on-timeout/5xx, a Persona accounts search helper, a unique constraint on credentials.bridgeId, and expanded tests covering fallback and retry scenarios.

Changes

Cohort / File(s) Summary
Changeset
.changeset/twco-dcxi-kedl.md
New patch-level changeset documenting bridge credential fallback and retry-on-timeout for @exactly/server.
Bridge Hook
server/hooks/bridge.ts
Adds credential fallback for customer.updated.status_transitioned: calls getCustomer, uses persona.searchAccounts(customer.email) to locate reference-id, attempts conditional credentials update to set bridgeId, emits captureEvent/captureException paths, and handles Drizzle unique-constraint (23505) and "already paired" cases specially.
Persona Utils
server/utils/persona.ts
Adds SearchAccountsResponse schema and exported searchAccounts(email: string) helper that POSTs to /accounts/search and returns parsed account data.
Ramps — Idempotency & Retry
server/utils/ramps/bridge.ts
createCustomer gains optional idempotencyKey; request preserves Idempotency-Key across retries; onboarding generates one idempotency key per run, wraps createCustomer in retry logic for timeouts and 5xx (with Sentry warning captures); CustomerResponse now requires email.
Database Schema
server/database/schema.ts
Changed index("bridge_id_index")uniqueIndex("bridge_id_index") on credentials.bridgeId, enforcing global uniqueness.
Tests — Hooks / Utils / API
server/test/hooks/bridge.test.ts, server/test/utils/bridge.test.ts, server/test/api/ramp.test.ts
Expanded fixtures (emails, additional credentials including conflict case) and added tests for fallback flows (single/multi/no match, already-paired), onboarding retry behavior (timeouts, 5xx, non-retryable 400), idempotency-key consistency, and Sentry captureEvent/captureException assertions.

Sequence Diagram

sequenceDiagram
    participant Client as Client/API
    participant Hook as Bridge Hook
    participant DB as Database
    participant Persona as Persona API
    participant Sentry as Sentry/Events

    Client->>Hook: webhook customer.updated.status_transitioned
    Hook->>DB: lookup credential by account/bridgeId
    alt credential found
        Hook-->>Client: proceed with credential
    else credential missing
        Hook->>Hook: getCustomer(bridgeId)
        alt customer found
            Hook->>Persona: searchAccounts(customer.email)
            Persona-->>Hook: accounts list
            alt single match (reference-id)
                Hook->>DB: update credentials where id==reference-id set bridgeId
                DB-->>Hook: update success / constraint error
                alt update success
                    Hook->>Sentry: captureEvent("bridge credential paired")
                    Hook-->>Client: return updated credential
                else unique constraint (already paired)
                    Hook->>Sentry: captureEvent("bridge credential already paired")
                    Hook-->>Client: credential not found
                end
            else multiple matches
                Hook->>Sentry: captureException(multiple matches)
                Hook-->>Client: credential not found
            else no matches
                Hook->>Sentry: captureException(credential not found)
                Hook-->>Client: credential not found
            end
        else customer missing
            Hook->>Sentry: captureException(credential not found)
            Hook-->>Client: credential not found
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • nfmelendez
  • cruzdanilo
  • dieguezguille
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the two main changes: bridge credential fallback logic and retry-on-timeout behavior for the server bridge utility.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the robustness of the server's Bridge integration. It introduces a fallback mechanism for identifying user credentials when Bridge webhooks are received, leveraging Persona accounts to match users by email if a direct ID lookup fails. Additionally, it adds retry capabilities to Bridge API calls, specifically for customer creation, to handle transient network issues or server errors more gracefully. These changes aim to reduce credential lookup failures and improve the reliability of user onboarding with Bridge.

Highlights

  • Bridge Credential Fallback: Implemented a fallback mechanism in the Bridge webhook handler to search for credentials using Persona accounts via email if a direct bridgeId lookup fails, improving resilience for customer.updated.status_transitioned events.
  • API Call Retry Logic: Introduced retry logic for Bridge API createCustomer calls, specifically for timeouts and 5xx server errors, to enhance reliability during the onboarding process.
  • Sentry Event Capture: Enhanced Sentry integration to capture specific warning events when a Bridge credential is successfully paired via the new fallback mechanism, and fatal errors for ambiguous Persona account matches.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a robust fallback mechanism for bridge credentials and enhances the createCustomer process with retry logic and idempotency. The changes include importing necessary utilities, modifying the bridge.ts webhook to attempt to find credentials via Persona email if the initial lookup fails, and updating the bridge.ts utility to use withRetry for customer creation. Comprehensive test cases have been added to cover the new fallback scenarios, ensuring the reliability of the system. The updates improve the resilience and error handling of the bridge integration.

coderabbitai[bot]

This comment was marked as resolved.

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 18, 2026

Codecov Report

❌ Patch coverage is 85.18519% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.59%. Comparing base (ac4d54a) to head (504c9b6).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
server/hooks/bridge.ts 75.00% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #896      +/-   ##
==========================================
+ Coverage   71.56%   71.59%   +0.03%     
==========================================
  Files         227      227              
  Lines        8194     8214      +20     
  Branches     2617     2626       +9     
==========================================
+ Hits         5864     5881      +17     
- Misses       2102     2104       +2     
- Partials      228      229       +1     
Flag Coverage Δ
e2e 71.59% <85.18%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

@cruzdanilo cruzdanilo marked this pull request as ready for review March 20, 2026 13:40
sentry[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

sentry[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@mainqueg mainqueg force-pushed the fallback branch 2 times, most recently from d143b5f to 7b6305f Compare March 27, 2026 13:16
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

sentry[bot]

This comment was marked as resolved.

@cruzdanilo cruzdanilo merged commit 504c9b6 into main Mar 27, 2026
16 of 18 checks passed
@cruzdanilo cruzdanilo deleted the fallback branch March 27, 2026 19:20
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.

2 participants