Skip to content

✨ server: new infra and refund automation - #1220

Open
cruzdanilo wants to merge 25 commits into
mainfrom
refund
Open

✨ server: new infra and refund automation#1220
cruzdanilo wants to merge 25 commits into
mainfrom
refund

Conversation

@cruzdanilo

Copy link
Copy Markdown
Member

closes #799

@cruzdanilo
cruzdanilo requested a review from nfmelendez as a code owner August 12, 2026 20:16
@changeset-bot

changeset-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 94f69e1

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

This PR includes changesets to release 4 packages
Name Type
@exactly/server Patch
@exactly/infra Minor
@exactly/common Patch
@exactly/mobile 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 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 136 files, which is 36 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b7ebddc8-307a-4787-bc7f-99311aa890fb

📥 Commits

Reviewing files that changed from the base of the PR and between 38fc251 and 94f69e1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (136)
  • .changeset/brave-otters-refund.md
  • .changeset/bumpy-toes-jump.md
  • .changeset/olive-sheep-sink.md
  • .changeset/proud-states-fold.md
  • .changeset/short-radios-stand.md
  • .changeset/spicy-ideas-mix.md
  • .changeset/ten-planets-prove.md
  • .changeset/tender-geese-own.md
  • .changeset/twenty-gifts-relax.md
  • .changeset/version.sh
  • .github/matcher.json
  • .github/workflows/docs.yaml
  • .github/workflows/mobile-expo.yaml
  • .github/workflows/server-base-sepolia.yaml
  • .github/workflows/server-base.yaml
  • .github/workflows/server-build.yaml
  • .github/workflows/server-deploy.yaml
  • .github/workflows/server-production.yaml
  • .github/workflows/server-sandbox.yaml
  • .github/workflows/substreams-build.yaml
  • .github/workflows/test.yaml
  • .github/workflows/version.yaml
  • AGENTS.md
  • common/stack.js
  • common/wagmi.config.ts
  • cspell.json
  • infra/Pulumi.base-sepolia.yaml
  • infra/Pulumi.meta.yaml
  • infra/Pulumi.sandbox.yaml
  • infra/Pulumi.yaml
  • infra/eslint.config.mjs
  • infra/index.ts
  • infra/meta.ts
  • infra/package.json
  • infra/tsconfig.json
  • infra/utils/modules.ts
  • infra/utils/rejectSecrets.ts
  • package.json
  • pnpm-workspace.yaml
  • server/Dockerfile
  • server/api/activity.ts
  • server/api/auth/authentication.ts
  • server/api/auth/registration.ts
  • server/api/card.ts
  • server/api/index.ts
  • server/api/kyc.ts
  • server/api/passkey.ts
  • server/api/pax.ts
  • server/api/ramp.ts
  • server/api/webhook.ts
  • server/drizzle.config.ts
  • server/hooks/activity.ts
  • server/hooks/block.ts
  • server/hooks/bridge.ts
  • server/hooks/manteca.ts
  • server/hooks/panda.ts
  • server/hooks/persona.ts
  • server/index.ts
  • server/instrument.cjs
  • server/middleware/auth.ts
  • server/middleware/org.ts
  • server/package.json
  • server/script/e2e.ts
  • server/script/openapi.ts
  • server/supervise.ts
  • server/test/api/activity.test.ts
  • server/test/api/api.test.ts
  • server/test/api/auth.test.ts
  • server/test/api/card.test.ts
  • server/test/api/kyc.test.ts
  • server/test/api/pax.test.ts
  • server/test/api/ramp.test.ts
  • server/test/api/webhook.test.ts
  • server/test/e2e.ts
  • server/test/hooks/activity.test.ts
  • server/test/hooks/block.test.ts
  • server/test/hooks/bridge.test.ts
  • server/test/hooks/hook.test.ts
  • server/test/hooks/manteca.test.ts
  • server/test/hooks/panda.test.ts
  • server/test/hooks/persona.test.ts
  • server/test/middleware/org.test.ts
  • server/test/mocks/alchemy.ts
  • server/test/mocks/bridge.ts
  • server/test/mocks/keeper.ts
  • server/test/mocks/manteca.ts
  • server/test/mocks/onesignal.ts
  • server/test/mocks/panda.ts
  • server/test/mocks/pax.ts
  • server/test/mocks/persona.ts
  • server/test/mocks/sardine.ts
  • server/test/mocks/segment.ts
  • server/test/mocks/sentry.ts
  • server/test/mocks/wallet.ts
  • server/test/supervise.test.ts
  • server/test/utils/alchemy.test.ts
  • server/test/utils/auth.test.ts
  • server/test/utils/bridge.test.ts
  • server/test/utils/intercom.test.ts
  • server/test/utils/manteca.test.ts
  • server/test/utils/maturity.test.ts
  • server/test/utils/onesignal.test.ts
  • server/test/utils/panda.test.ts
  • server/test/utils/persona.test.ts
  • server/test/utils/secret.test.ts
  • server/test/utils/wallet.test.ts
  • server/test/workers/bin.test.ts
  • server/test/workers/refund.test.ts
  • server/test/workers/worker.test.ts
  • server/tsconfig.json
  • server/utils/activityWebhook.ts
  • server/utils/alchemy.ts
  • server/utils/auth.ts
  • server/utils/authSecret.ts
  • server/utils/createCredential.ts
  • server/utils/intercom.ts
  • server/utils/maturity.ts
  • server/utils/onesignal.ts
  • server/utils/panda.ts
  • server/utils/pax.ts
  • server/utils/persona.ts
  • server/utils/ramps/bridge.ts
  • server/utils/ramps/manteca.ts
  • server/utils/redis.ts
  • server/utils/sardine.ts
  • server/utils/secret.ts
  • server/utils/segment.ts
  • server/utils/wallet.ts
  • server/utils/walletExtension.ts
  • server/vitest.config.mts
  • server/workers/queue.ts
  • server/workers/refund/bin.ts
  • server/workers/refund/job.ts
  • server/workers/refund/queue.ts
  • server/workers/refund/worker.ts
  • server/workers/worker.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

@cruzdanilo

Copy link
Copy Markdown
Member Author

@codex review

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.30308% with 330 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.64%. Comparing base (a429122) to head (94f69e1).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
server/hooks/panda.ts 90.95% 25 Missing and 32 partials ⚠️
server/hooks/block.ts 81.72% 44 Missing and 11 partials ⚠️
server/api/auth/registration.ts 64.22% 36 Missing and 8 partials ⚠️
server/api/auth/authentication.ts 74.28% 26 Missing and 10 partials ⚠️
server/api/card.ts 92.43% 17 Missing and 10 partials ⚠️
server/hooks/persona.ts 84.05% 5 Missing and 17 partials ⚠️
server/api/kyc.ts 90.41% 4 Missing and 17 partials ⚠️
server/api/activity.ts 93.44% 3 Missing and 16 partials ⚠️
server/hooks/activity.ts 93.22% 5 Missing and 8 partials ⚠️
server/api/ramp.ts 95.81% 2 Missing and 9 partials ⚠️
... and 7 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1220      +/-   ##
==========================================
+ Coverage   65.31%   74.64%   +9.33%     
==========================================
  Files         252      270      +18     
  Lines       10338    14345    +4007     
  Branches     3490     5170    +1680     
==========================================
+ Hits         6752    10708    +3956     
+ Misses       3321     3278      -43     
- Partials      265      359      +94     
Flag Coverage Δ
e2e 73.44% <85.76%> (+31.67%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@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: 8cbf0d8ef2

ℹ️ 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/supervise.ts Outdated
Comment thread server/script/openapi.ts
Comment thread server/utils/createCredential.ts
Comment thread server/hooks/panda.ts Outdated
).catch((error: unknown) => captureException(error, { level: "error" }));
}
try {
await refund.enqueue(payload.id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Queue Panda withdrawals after refund success

Because this runs before wallet.exaSend, any refund attempt that later fails or is treated as a Replay still has a withdrawal job scheduled. For redelivered refund webhooks, the on-chain refund can be skipped as a replay while the worker still withdraws the same amount from Panda again, so the withdrawal should be enqueued only after a successful refund receipt.

Useful? React with 👍 / 👎.

Comment thread server/index.ts
Comment thread .github/workflows/server-deploy.yaml
Comment thread server/workers/refund/worker.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: 5fbca97c0a

ℹ️ 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/workers/refund/queue.ts Outdated
Comment thread .github/workflows/server-production.yaml 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: f9f268bb69

ℹ️ 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/index.ts Outdated
activityKey: env.ALCHEMY_ACTIVITY_KEY,
executor: keeper,
onesignalKey: env.ONESIGNAL_API_KEY,
postgresUrl: parse(pipe(string(), nonEmpty()), env.POSTGRES_URL),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Share the database pool in the monolith

In the Docker dist/index.cjs path this process still mounts the API plus all hook apps together, but each factory that receives postgresUrl now creates and closes its own drizzle(postgresUrl, ...) client internally. This is the first of several separate pools created in the same server instance (activity, bridge, manteca, panda, persona, plus the default maturity database), whereas the previous monolith shared one database singleton; with multiple replicas this can exhaust managed Postgres connection limits before any traffic increase. Please share the database handle for the monolith path or avoid instantiating all split factories in one process.

Useful? React with 👍 / 👎.

@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: ca35b71f65

ℹ️ 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 .github/workflows/server-sandbox.yaml

@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: 79ec6e98ff

ℹ️ 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 infra/package.json Outdated
Comment thread infra/index.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: 62f19c909d

ℹ️ 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 infra/index.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: 94f69e1025

ℹ️ 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 on lines +146 to +150
await (receipt &&
settle.enqueue(
{ blockNumber: Number(receipt.blockNumber), hash: parse(Hash, receipt.transactionHash) },
webhookId,
));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve settlement publishing across replay retries

If settle.enqueue fails after the atomic refund transaction has mined, BullMQ retries the refund job, but the retry hits Replay() and exaSend returns no receipt, so this conditional skips the settlement queue and marks the job complete. The on-chain refund then permanently lacks its database transaction update, notification, and risk/analytics feedback. Fresh evidence in this revision is the new atomic Replay() ignore path, which returns no receipt on the retry; settlement publication therefore needs to be recoverable independently of the original receipt.

Useful? React with 👍 / 👎.

Comment thread infra/meta.ts
Comment on lines +190 to +194
new kms.CryptoKey(
`${stack.name}-${key}`,
{
keyRing: keyRing.id,
name: `${stack.name}-${key}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Grant the HSM refunder its keeper role

For every newly created ${stack}-refunder HSM key, its derived address differs from the fixed acct("keeper") address granted KEEPER_ROLE when Refunder is deployed in contracts/script/Refunder.s.sol, and a repo-wide search finds no subsequent grantRole provisioning for this signer. Even after the separate gas-funding problem is addressed, every worker batch therefore reaches Refunder.refund with the HSM address as msg.sender and reverts Unauthorized; provision the derived address on the contract before enabling the worker.

Useful? React with 👍 / 👎.

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.

monitoring: automate panda refund

2 participants