Skip to content

✨ server: process business onboarding approvals - #1209

Open
aguxez wants to merge 1 commit into
panda-b2bfrom
panda-b2b-approvals
Open

✨ server: process business onboarding approvals#1209
aguxez wants to merge 1 commit into
panda-b2bfrom
panda-b2b-approvals

Conversation

@aguxez

@aguxez aguxez commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

summary

process panda business onboarding approvals.

stacked on #1203.

changes

  • authenticate panda company webhooks with the primary and secondary signature paths
  • deduplicate webhook events and retry temporary failures
  • protect concurrent approval processing
  • adopt the approved panda company user
  • finalize company approval and persist panda identifiers
  • issue business cards with idempotency protection
  • route business card status through the company application endpoint
  • propagate the panda subtenant through approval and card operations
  • add approval-focused tests and a server changeset

test plan

  • run the server typescript check
  • run the server eslint check
  • pass 430 focused server tests
  • pass the full workspace test

notes

  • this pull request uses panda-b2b as its base
  • the full workspace test reaches the dependency audit and reports 28 existing vulnerabilities
  • the local business onboarding script is not part of this pull request

Summary by CodeRabbit

  • New Features

    • Added business onboarding approval processing.
    • Approved business applications can automatically create or reuse eligible signature cards.
    • Business card eligibility now uses company KYC status.
    • Added support for custom card limits and idempotent card creation.
  • Bug Fixes

    • Improved handling of business approval webhooks and repeated events.
    • Added safer retry behavior when account details are unavailable.
    • Improved KYC processing using the originating client IP address.
    • Ignored unsupported webhook resource types to prevent unnecessary processing.

@changeset-bot

changeset-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2841376

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

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 49eee47b-6ca9-4ccd-ae35-c7646edb24bd

📥 Commits

Reviewing files that changed from the base of the PR and between 07e66f6 and e9e4d14.

📒 Files selected for processing (2)
  • infra/utils/modules.ts
  • server/test/hooks/bin.test.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

Changes

Business onboarding and Panda operations

Layer / File(s) Summary
Panda client contracts and authentication
server/utils/panda.ts, server/test/utils/panda.test.ts, server/test/mocks/panda.ts, infra/utils/modules.ts
The Panda client adds company-user retrieval, idempotent card creation, expanded webhook validation, and signature checks. Persona API configuration is added.
Business approval finalization and card provisioning
server/api/kyc.ts, server/api/card.ts, server/api/index.ts, server/utils/panda.ts, server/test/api/*, .changeset/brown-heads-vanish.md
Approved business applications finalize Panda users and signature cards. Card KYC checks use company status for business credentials. Card creation uses options with limits and idempotency keys.
Business approval API and webhook processing
server/hooks/panda.ts, server/workers/hook/worker.ts, server/hooks/bin/panda.ts, server/index.ts, server/test/hooks/*
Company approval webhooks finalize business credentials under an account mutex. Application and company resources bypass normal delivery. Runtime wiring initializes Persona and credit dependencies and closes the credit queue during shutdown.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🟠 High · up to e9e4d

The PR adds business onboarding approval and card issuance flows, but the current implementation can fail startup when a configured secret is missing, permanently issue a card with the maximum default limit after an upstream error, create duplicate provider cards during concurrent requests, trust spoofable onboarding IP headers, and return server errors for malformed webhook signatures. These create material availability, financial, security, and correctness risks, so the change is not ready to merge without fixes or explicit owner acceptance.

Sequence Diagram(s)

sequenceDiagram
  participant PandaAPI as Panda API
  participant Hook as Panda webhook hook
  participant KYC as KYC route
  participant Finalizer as finalizeBusinessApproval
  participant Database
  PandaAPI->>Hook: Send approved company event
  Hook->>Finalizer: Finalize approval under account mutex
  KYC->>Finalizer: Finalize approved business application
  Finalizer->>Database: Persist Panda user and signature card
  Database-->>Finalizer: Return persisted approval state
Loading

Suggested reviewers: cruzdanilo, nfmelendez

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: processing business onboarding approvals in the server.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch panda-b2b-approvals
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch panda-b2b-approvals

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.

@aguxez
aguxez force-pushed the panda-b2b-approvals branch from 14fbd8c to 9e408b8 Compare August 11, 2026 15:07
@aguxez
aguxez force-pushed the panda-b2b-approvals branch from 9e408b8 to 146f4d1 Compare August 13, 2026 10:53

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3c48c2d8-ea42-4d42-ae0d-110eb98c518e

📥 Commits

Reviewing files that changed from the base of the PR and between fd84ca6 and 146f4d1.

📒 Files selected for processing (10)
  • .changeset/brown-heads-vanish.md
  • server/api/card.ts
  • server/api/kyc.ts
  • server/hooks/panda.ts
  • server/hooks/persona.ts
  • server/test/api/card.test.ts
  • server/test/api/kyc.test.ts
  • server/test/hooks/panda.test.ts
  • server/test/hooks/persona.test.ts
  • server/utils/panda.ts

Comment thread server/api/kyc.ts Outdated
Comment thread server/hooks/panda.ts Outdated
Comment thread server/test/api/card.test.ts Outdated
Comment thread server/test/hooks/panda.test.ts Outdated
Comment thread server/utils/panda.ts Outdated
Comment thread server/utils/panda.ts Outdated
Comment thread server/utils/panda.ts Outdated
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9da4361e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated
Comment thread server/utils/panda.ts Outdated
Comment thread server/utils/panda.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 625bcc87-6945-4e39-9145-8f706b3638f8

📥 Commits

Reviewing files that changed from the base of the PR and between c9da436 and fcef25b.

📒 Files selected for processing (13)
  • infra/utils/modules.ts
  • server/api/card.ts
  • server/api/index.ts
  • server/api/kyc.ts
  • server/hooks/bin/panda.ts
  • server/hooks/panda.ts
  • server/index.ts
  • server/test/api/card.test.ts
  • server/test/api/kyc.test.ts
  • server/test/hooks/bin.test.ts
  • server/test/hooks/panda.test.ts
  • server/test/utils/panda.test.ts
  • server/utils/panda.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread server/api/kyc.ts
Comment thread server/api/kyc.ts
Comment thread server/hooks/bin/panda.ts Outdated
Comment thread server/test/hooks/panda.test.ts Outdated
Comment thread server/utils/panda.ts Outdated
Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcef25b6c8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/hooks/bin/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 183c53c6a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/api/kyc.ts
Comment thread server/hooks/panda.ts
@aguxez
aguxez force-pushed the panda-b2b-approvals branch from 183c53c to 07e66f6 Compare August 26, 2026 14:08

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07e66f6b13

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/utils/panda.ts (1)

253-260: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Treat a malformed signature header as invalid instead of throwing.

verifySignature calls timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expectedSignature, "hex")) (server/utils/verifySignature.ts:9-13). Node throws RangeError when the buffers have different lengths. Any request whose signature header is not a 32-byte hex string therefore throws inside the validator, and the endpoint answers 500 instead of 401. An unauthenticated caller controls this header, so it can force error responses and Sentry noise on the webhook route. The new test at server/test/utils/panda.test.ts lines 111-119 sends a correctly sized HMAC, so it does not cover this input.

🛡️ Proposed fix
   function headerValidator() {
     return vValidator("header", object({ signature: string() }), async (r, c) => {
       if (!r.success) return c.text("bad request", 400);
       const payload = await c.req.arrayBuffer();
-      if (verifySignature({ signature: r.output.signature, signingKey: key, payload })) return;
+      try {
+        if (verifySignature({ signature: r.output.signature, signingKey: key, payload })) return;
+      } catch {} // eslint-disable-line no-empty -- malformed signature is unauthorized
       return c.text("unauthorized", 401);
     });
   }
♻️ Duplicate comments (1)
server/utils/panda.ts (1)

936-942: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Look up the conflicting card row by cards.id.

onConflictDoNothing matches when the row for card.id already exists. The fallback query filters on status in ACTIVE or FROZEN. If the stored row has any other status, the query returns nothing, the function returns undefined, and credit.enqueue, segment.track, and sardine.customer never run for the new card. The webhook caller treats that result as a completed finalization, so no retry occurs.

♻️ Proposed fix
   if (!inserted)
     return database.query.cards
-      .findFirst({
-        columns: { id: true },
-        where: and(eq(cards.credentialId, credentialId), inArray(cards.status, ["ACTIVE", "FROZEN"])),
-      })
+      .findFirst({ columns: { id: true }, where: eq(cards.id, card.id) })
       .then((existing) => (existing ? { userId, cardId: existing.id } : undefined));

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fce76f4d-f286-4e29-81de-71e04b828284

📥 Commits

Reviewing files that changed from the base of the PR and between fcef25b and 07e66f6.

📒 Files selected for processing (7)
  • infra/utils/modules.ts
  • server/hooks/bin/panda.ts
  • server/index.ts
  • server/test/hooks/bin.test.ts
  • server/test/hooks/persona.test.ts
  • server/test/utils/panda.test.ts
  • server/utils/panda.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread server/test/hooks/persona.test.ts Outdated
@aguxez
aguxez force-pushed the panda-b2b-approvals branch from 07e66f6 to e9e4d14 Compare August 26, 2026 15:28

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9e4d14936

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/test/hooks/persona.test.ts Outdated
Comment thread server/hooks/panda.ts
Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea79a2e2e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c55eb3522d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bfab111b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a352a63ebf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5fa653c1f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/api/card.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0921500ef1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73de6f6cf8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/api/card.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd1ff9d16a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84c3c1e5a4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread server/utils/panda.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91b310ff5c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/utils/panda.ts Outdated
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.

server: integrate panda b2b

2 participants