Skip to content

Normalize Bridge webhook payload envelopes#406

Merged
islandbitcoin merged 4 commits into
tmp/bridge-rebase-pr-readyfrom
vandana/bridge-webhook-envelope-normalization
Jun 18, 2026
Merged

Normalize Bridge webhook payload envelopes#406
islandbitcoin merged 4 commits into
tmp/bridge-rebase-pr-readyfrom
vandana/bridge-webhook-envelope-normalization

Conversation

@islandbitcoin

Copy link
Copy Markdown
Contributor

Summary

  • Normalizes Bridge deposit webhook payloads across transfer, virtual-account, and bridge-wallet activity shapes.
  • Handles Bridge customer/external-account KYC webhook field differences (id/customer_id, status/kyc_status).
  • Normalizes transfer webhook envelopes from event_object while keeping legacy fallback fields.
  • Writes normalized deposit events into the ERPNext transfer-request audit path.

Verification

  • git diff --check
  • eslint --no-ignore src/services/bridge/webhook-server/routes/deposit.ts src/services/bridge/webhook-server/routes/kyc.ts src/services/bridge/webhook-server/routes/transfer.ts src/services/frappe/BridgeTransferRequestWriter.ts

@islandbitcoin islandbitcoin left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reviewed the webhook envelope normalization (deposit/kyc/transfer + the ERPNext writer). The normalization approach is reasonable and the graceful-degradation logging is a nice touch. A few correctness concerns inline — the strongest are the destination_payment_rail-as-currency fallback (in two files) and a silent audit-skip in the writer.

Comment thread src/services/bridge/webhook-server/routes/deposit.ts Outdated
Comment thread src/services/bridge/webhook-server/routes/deposit.ts Outdated
Comment thread src/services/bridge/webhook-server/routes/kyc.ts
Comment thread src/services/frappe/BridgeTransferRequestWriter.ts Outdated
Comment thread src/services/frappe/BridgeTransferRequestWriter.ts
@linear

linear Bot commented Jun 18, 2026

Copy link
Copy Markdown

ENG-415

@islandbitcoin islandbitcoin self-assigned this Jun 18, 2026
@islandbitcoin

Copy link
Copy Markdown
Contributor Author

Addressed in 52e42f70f:

  • Removed destination_payment_rail as a currency fallback in both the deposit webhook route and ERPNext writer.
  • Valid Bridge activity events that lack amount/customer fields are now acknowledged with a 200 skip instead of returning 400 and causing provider retry storms.
  • ERPNext audit skips without a stable Bridge request id now log a warning instead of silently returning.
  • Confirmed repeated approved KYC webhooks route through the existing idempotent createVirtualAccount path, which checks for a stored VA before creating one.

Focused verification run:

  • yarn test:unit test/flash/unit/services/bridge/webhook-server/deposit.spec.ts
  • yarn test:unit test/flash/unit/services/frappe/BridgeTransferRequestWriter.spec.ts

…yc status type

- transfer.spec.ts now posts Bridge's real webhook envelope (event_type/event_object,
  nested source.failure_reason) instead of the legacy { event, data } shape the
  handler no longer reads; restores coverage for failed-cashout audit and
  already_terminal paths.
- kyc.ts: cast bridgeKycStatus to Account["bridgeKycStatus"] (BridgeKycStatus was
  referenced but never defined/imported).
@islandbitcoin

Copy link
Copy Markdown
Contributor Author

Review comments addressed (902cafe)

All five review threads resolved. Summary:

Thread Resolution
deposit.ts rail-as-currency Removed destination_payment_rail fallback → currency ?? "usd". Confirmed via Bridge API docs that payment_rail/destination_payment_rail carries rail values (ach/wire/sepa/base/fednow), always a sibling of currency. Regression test added.
deposit.ts 400 retry-storm Missing amount/customer now returns 200 skipped instead of 400, so bridge_wallet.activity shapes don't trigger Bridge retries. Test added.
kyc.ts duplicate VA creation Confirmed safe — createVirtualAccount has the ENG-284 idempotency guard (findVirtualAccountByAccountId early-return) before any mutation.
BridgeTransferRequestWriter.ts rail-as-currency Same fix — currency ?? "usd", no rail fallback.
BridgeTransferRequestWriter.ts silent drop No-stableRequestId skip now logs baseLogger.warn before return true.

Additional fixes in this push

  • transfer.spec.ts: updated to post Bridge's real webhook envelope (event_type/event_object, nested source.failure_reason) — the handler rewrite changed its input contract but the spec still sent the legacy { event, data } shape, so failed-cashout-audit and already_terminal coverage had silently regressed. Now 10/10 pass.
  • kyc.ts: fixed a TS error — bridgeKycStatus was cast to BridgeKycStatus which is never defined/imported; now Account["bridgeKycStatus"].

Verification

  • deposit.spec.ts 13/13, transfer.spec.ts 10/10, BridgeTransferRequestWriter.spec.ts 7/7, verify-signature.spec.ts pass
  • tsc clean on kyc.ts/transfer.ts/transfer.spec.ts
  • eslint clean on changed files

Out of scope (pre-existing on base, not introduced here)

@islandbitcoin islandbitcoin merged commit 8c508cf into tmp/bridge-rebase-pr-ready Jun 18, 2026
2 checks passed
@islandbitcoin islandbitcoin deleted the vandana/bridge-webhook-envelope-normalization branch June 18, 2026 21:48
heyolaniran pushed a commit to heyolaniran/flash that referenced this pull request Jun 20, 2026
* fix(bridge): normalize webhook payload envelopes

* fix: key bridge deposit audit rows by stable id

* fix: handle uncreditable bridge deposit activity

* test(bridge): update transfer webhook spec to Bridge envelope + fix kyc status type

- transfer.spec.ts now posts Bridge's real webhook envelope (event_type/event_object,
  nested source.failure_reason) instead of the legacy { event, data } shape the
  handler no longer reads; restores coverage for failed-cashout audit and
  already_terminal paths.
- kyc.ts: cast bridgeKycStatus to Account["bridgeKycStatus"] (BridgeKycStatus was
  referenced but never defined/imported).

---------

Co-authored-by: Vandana <forge@getflash.io>
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.

3 participants