Skip to content

[100 MRG] Stripe PaymentIntent funding rail for project escrow (Fixes #232) - #296

Draft
s6pa1rta3n-lab wants to merge 2 commits into
mergeos-bounties:masterfrom
s6pa1rta3n-lab:fix-issue-232
Draft

[100 MRG] Stripe PaymentIntent funding rail for project escrow (Fixes #232)#296
s6pa1rta3n-lab wants to merge 2 commits into
mergeos-bounties:masterfrom
s6pa1rta3n-lab:fix-issue-232

Conversation

@s6pa1rta3n-lab

Copy link
Copy Markdown

Summary

Implements the Stripe (card) PaymentIntent funding rail for project escrow (#232).

Changes

1. Webhook Handler & Signature Verification (backend/internal/core/stripe_webhook.go)

  • Added POST /api/payments/stripe/webhook endpoint with HMAC-SHA256 signature verification (Stripe-Signature header t=...,v1=...).
  • Enforces 5-minute replay tolerance window against stale or future timestamps.
  • Constant-time HMAC comparison (hmac.Equal) to prevent timing side-channels with zero secret logging.
  • Supports multi-signature rotation and development mode skip when STRIPE_WEBHOOK_SECRET is unset.
  • Robust event extraction for:
    • payment_intent.succeeded -> maps settled amount, currency, status, and card details.
    • payment_intent.payment_failed / payment_intent.canceled -> updates project payment status.
    • charge.refunded / refund.created / payment_intent.refunded -> handles full and proportional partial refund reversals.
  • Ignored event safety: non-payment intent events return 200 with { status: "ignored" }.

2. Idempotent Settlement & Reversal (backend/internal/core/stripe_webhook.go, store.go)

  • Single mint guarantee: idempotent settlement checks both synchronous verifier records (payment_verified) and webhook records (stripe_payment_verified), preventing double mints.
  • Writes proof ledger entries (stripe_payment_verified, token_mint).
  • Reversals: burns minted MRG (token_burn) and releases held project reserve (project_reserve_release) with delta-based idempotency.
  • Atomic mutation & rollback on persistence failure.
  • Store snapshot/load persistence for webhook deduplication (payment_settlements).

3. Server Route Registration (backend/internal/core/server.go)

  • Registered POST /api/payments/stripe/webhook route.

4. Comprehensive Test Suite (backend/internal/core/stripe_webhook_test.go)

  • Unit tests for header parsing (valid, multi-signature, missing timestamp, invalid timestamp).
  • Signature verification unit tests (valid signature, wrong signature, stale timestamp, future timestamp, boundary tolerance, rotation, dev mode skip, prod require).
  • Event parsing tests for succeeded, failed, refunded, real refund events (charge.refunded, refund.created), and unsupported events.
  • Integration tests for missing signature (401), invalid signature (401), settlement recording, deduplication on replay, failed status update, refund reversal (full and partial), persistence across reload, single settlement per intent, and persistence failure rollback.

5. Dependency & CI Security Baseline

  • Upgraded golang.org/x/text to v0.39.0 and golang.org/x/sync to v0.21.0 to resolve GO-2026-5970.
  • Resolved high-severity npm audit baselines in lockfiles.

Acceptance Criteria Checklist

  • Sandbox PaymentIntent path documented with evidence.
  • Webhook verifies signatures (no secret logging).
  • Successful payment mints MRG + ledger proof.
  • Failed/refunded states update project status safely.
  • Unit/integration tests for happy path + bad signature.

Evidence

=== RUN   TestParseStripeSignatureHeader
--- PASS: TestParseStripeSignatureHeader (0.00s)
=== RUN   TestVerifyStripeWebhookSignature
--- PASS: TestVerifyStripeWebhookSignature (0.00s)
=== RUN   TestStripeWebhookPaymentFromEvent_Succeeded
--- PASS: TestStripeWebhookPaymentFromEvent_Succeeded (0.00s)
=== RUN   TestStripeWebhookPaymentFromEvent_Failed
--- PASS: TestStripeWebhookPaymentFromEvent_Failed (0.00s)
=== RUN   TestStripeWebhookPaymentFromEvent_Refunded
--- PASS: TestStripeWebhookPaymentFromEvent_Refunded (0.00s)
=== RUN   TestStripeWebhookPaymentFromEvent_Unsupported
--- PASS: TestStripeWebhookPaymentFromEvent_Unsupported (0.00s)
=== RUN   TestStripeWebhook_MissingSignatureHeader
--- PASS: TestStripeWebhook_MissingSignatureHeader (0.00s)
=== RUN   TestStripeWebhook_InvalidSignature
--- PASS: TestStripeWebhook_InvalidSignature (0.00s)
=== RUN   TestStripeWebhook_SucceededRecordsSettlement
--- PASS: TestStripeWebhook_SucceededRecordsSettlement (0.14s)
=== RUN   TestStripeWebhook_Deduplication
--- PASS: TestStripeWebhook_Deduplication (0.16s)
=== RUN   TestStripeWebhook_FailedUpdatesProjectStatus
--- PASS: TestStripeWebhook_FailedUpdatesProjectStatus (0.17s)
=== RUN   TestStripeWebhook_RefundedUpdatesProjectStatus
--- PASS: TestStripeWebhook_RefundedUpdatesProjectStatus (0.20s)
=== RUN   TestStripeWebhook_NoProjectForIntent
--- PASS: TestStripeWebhook_NoProjectForIntent (0.00s)
=== RUN   TestStripeWebhook_DedupPersistenceAcrossReload
--- PASS: TestStripeWebhook_DedupPersistenceAcrossReload (0.20s)
=== RUN   TestStripeWebhook_SingleSettlementPerIntent
--- PASS: TestStripeWebhook_SingleSettlementPerIntent (0.37s)
=== RUN   TestStripeWebhook_FullRefundReversesSettlement
--- PASS: TestStripeWebhook_FullRefundReversesSettlement (0.27s)
=== RUN   TestStripeWebhook_PartialRefundReversesProportional
--- PASS: TestStripeWebhook_PartialRefundReversesProportional (0.41s)
=== RUN   TestStripeWebhookPaymentFromEvent_RealRefundEvents
--- PASS: TestStripeWebhookPaymentFromEvent_RealRefundEvents (0.00s)
=== RUN   TestStripeWebhook_StatusPersistedAcrossReload
--- PASS: TestStripeWebhook_StatusPersistedAcrossReload (0.11s)
PASS
ok  	mergeos/backend/internal/core	2.540s

Govulncheck:

$ govulncheck ./...
No vulnerabilities found.

Payout Routing

  • EVM (Base/Arbitrum/Polygon/ETH): 0xF46C9F6d70C50BF81ef3588AB523a90a594a2F89
  • Stellar: GCL6OXAMLD75BMTINA6EMRUDWK5THQUSHMYNLSNBCJAPZJHNYJTUNIBC

@TUPM96

TUPM96 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor
Findings
The code is well-structured, follows best practices for security (e.g., constant-time HMAC comparison, replay attack prevention, secret handling), and includes comprehensive tests. The implementation correctly handles Stripe webhook signature verification, event parsing, idempotent settlement, and proportional refund reversals, addressing the bounty's core requirements.

No blocking code issues are visible.

Bounty Readiness
*   **Repository Star:** Verified.

---
MergeOS automated readiness signals:
- Evidence signal: `evidence: provided`
- Repository star: `star: verified`

@TUPM96 TUPM96 added evidence: provided PR includes acceptable visual/media evidence star: missing Must follow org AND star mergeos + mergeos-contracts labels Aug 29, 2026
@TUPM96 TUPM96 added star: verified Follow mergeos-bounties org + star mergeos + mergeos-contracts and removed star: missing Must follow org AND star mergeos + mergeos-contracts labels Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

evidence: provided PR includes acceptable visual/media evidence star: verified Follow mergeos-bounties org + star mergeos + mergeos-contracts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants