Skip to content

Escrow & Order Lifecycle Architecture ​


1. Executive Summary & Core Philosophy ​

Debelu is built upon a closed-loop escrow financial model. In campus and digital commerce across Nigeria, the absence of trust between unacquainted student buyers and independent merchants is the single greatest barrier to transaction completion.

Debelu bridges this trust gap through an automated escrow state machine:

  • Buyer Protection: Funds are collected at checkout and held securely in Debelu's master escrow settlement account. Funds are never released to the seller prior to verified physical receipt.
  • Seller Protection: Sellers receive an immutable guarantee that payment has been captured and locked before dispatching goods or handing over inventory.
  • Physical Handover Verification (Delivery PIN): Proof-of-delivery relies on a cryptographically secured 4-digit PIN generated for the buyer. When the seller or courier inputs this PIN, the escrow contract executes atomically.
  • Historical Commission Invariant (Fee Freezing): Commission percentages are frozen at the exact millisecond of order placement (fee_snapshot), immunizing historical transactions from future platform fee changes.
mermaid
sequenceDiagram
    autonumber
    actor Buyer
    participant Storefront
    participant API as Backend API
    participant Paystack as Paystack Gateway
    participant DB as Postgres (Supabase)
    actor Vendor

    Buyer->>Storefront: 1. Place Order (Cart items)
    Storefront->>API: 2. POST /api/payments/intent (CheckoutPaymentIntent)
    API->>DB: 3. reserve_checkout_payment() & Snapshot Frozen Fees
    API->>Paystack: 4. POST /transaction/initialize (timeout 15s)
    Paystack-->>API: 5. Return authorization_url & access_code
    API->>DB: 6. complete_checkout_payment_dispatch() (State: ready)
    API-->>Storefront: 7. Deliver Paystack Inline Checkout Modal
    Buyer->>Paystack: 8. Authorize Card / USSD / Bank Transfer
    Paystack-->>API: 9. Webhook charge.success (HMAC SHA-512)
    API->>DB: 10. Update payment_status='paid', status='Processing'
    DB->>DB: 11. Generate 4-digit Delivery PIN in order_verification
    Note over DB,Vendor: Vendor notified to dispatch goods
    Vendor->>Buyer: 12. Physical Delivery / Campus Meetup
    Buyer-->>Vendor: 13. Shares 4-Digit Delivery PIN upon inspection
    Vendor->>API: 14. POST /api/orders/:id/verify-delivery (delivery_code)
    API->>DB: 15. Verify PIN & UPDATE status='Completed', payment_status='released'
    DB->>DB: 16. Trigger trigger_on_order_released()
    DB->>DB: 17. Execute process_order_fund_release() -> ledger_post()
    Note over DB: Escrow unlocked -> Vendor Wallet Balance credited

2. Comprehensive Order Finite State Machine (FSM) ​

The lifecycle of an order is strictly governed by PostgreSQL triggers (guard_order_payment_state) preventing illegal state skips.

mermaid
stateDiagram-v2
    [*] --> PaymentPending : Order Created (Cart Checkout)
    
    PaymentPending --> Processing : Payment Verified (Webhook charge.success)
    PaymentPending --> Cancelled : Payment Window Expired / Cancelled by Buyer
    
    state Processing {
        [*] --> AwaitingFulfillment
        AwaitingFulfillment --> Shipped : Vendor Dispatches / Couriered
        Shipped --> InTransit : Arrived at Campus Hub / Out for Delivery
    }

    Processing --> ReturnInitiated : Defect / Return Case Opened
    Processing --> Disputed : Delivery Dispute Raised

    InTransit --> DeliveredPendingRelease : Courier Handover Attempt
    
    DeliveredPendingRelease --> Completed : Delivery PIN Verified
    DeliveredPendingRelease --> Completed : Auto-Release Timer Expired (72h without dispute)
    
    state ReturnInitiated {
        [*] --> CaseReview
        CaseReview --> PickupConfirmed : Courier Acknowledges Custody
        PickupConfirmed --> Inspected : Vendor Verifies Restock Condition
        Inspected --> Refunded : Atomic Return Approved & Executed
    }

    Disputed --> Completed : Arbiter Releases to Vendor
    Disputed --> Refunded : Arbiter Approves Buyer Refund
    
    Completed --> [*] : Funds Released to Vendor Balance
    Refunded --> [*] : Funds Credited to Buyer Wallet / Original Card
    Cancelled --> [*] : Inventory Restocked

3. Checkout Payment Intent & Three-Phase Commit ​

Debelu prevents ghost orders, double-charging, and distributed race conditions through CheckoutPaymentIntent ([debelu-backend/src/services/CheckoutPaymentIntent.ts](file:///c:/Users/frank/OneDrive/Desktop/Chisom/Debelu/New%20Debelu%20Marketplace/debelu-backend/src/services/CheckoutPaymentIntent.ts)).

3.1 Strict Reference Specification ​

Payment references are deterministic UUIDv4 mappings: $$\text{Reference} = \text{"checkout-"} + \text{checkoutId.replace(/-/g, "")}$$ Matches regex: /^checkout-[a-f0-9]{32}$/

3.2 The Three-Phase Intent Protocol ​

  1. Reservation Phase (reserve_checkout_payment):
    • Acquires an atomic lock on the order.
    • Generates a cryptographic claimToken (UUID).
    • Verifies emergency platform control assertSubsystemAvailable('checkoutDisabled').
  2. Dispatch Phase (begin_checkout_payment_dispatch):
    • Atomically transitions state to dispatching.
    • Outbound HTTP call to Paystack API (https://api.paystack.co/transaction/initialize) with a strict 15-second timeout.
    • Validates that Paystack's returned authorization_url resides on the HTTPS hostname checkout.paystack.com.
  3. Commit or Uncertainty Isolation:
    • Success (complete_checkout_payment_dispatch): Records ready state, access code, and URL.
    • Failure / Timeout (mark_checkout_payment_uncertain): If the outbound request times out or network drops, the intent is flagged as uncertain. The system rejects subsequent payment attempts on that checkout until status is definitively verified via Paystack transaction check, preventing double-debits.

4. The Frozen Fee Snapshot (fee_snapshot) Invariant ​

A primary enterprise vulnerability in multi-vendor marketplaces is ledger corruption through retroactively modified commission rates. Debelu eliminates this risk through immutable fee snapshots at checkout ([scripts/db-order-fee-snapshot-checks.mjs](file:///c:/Users/frank/OneDrive/Desktop/Chisom/Debelu/New%20Debelu%20Marketplace/scripts/db-order-fee-snapshot-checks.mjs)).

4.1 Snapshot Data Structure ​

At the moment create_order() executes, the database computes and freezes the exact calculation in orders.fee_snapshot (JSONB):

json
{
  "configurationRevision": 4,
  "globalRateBasisPoints": 500,
  "platformFeeMinor": 6900,
  "vendorNetMinor": 33100,
  "discountMinor": 1000,
  "netSubtotalMinor": 39000,
  "lines": [
    {
      "productId": "301e0000-0000-4000-8000-000000000000",
      "categoryId": "101e0000-0000-4000-8000-000000000000",
      "approvedProposalId": "201e0000-0000-4000-8000-000000000000",
      "rateBasisPoints": 1000,
      "rateSource": "category_proposal",
      "netMinor": 9000
    }
  ]
}

4.2 Mathematical Invariants ​

  1. Gross Order Total: $$\text{TotalMinor} = \text{PlatformFeeMinor} + \text{VendorNetMinor} + \text{DiscountMinor}$$
  2. Category Hierarchy Precedence:
    • If a product belongs to a category with an executed proposal $\to$ Use proposed_override basis points.
    • If uncategorized or proposal unexecuted $\to$ Fall back to platform_settings.platform_fee_percent (global_unreviewed_category_override).
  3. Coupon Line-Item Isolation: Targeted coupons apply strictly to eligible line items; fees on non-discounted line items remain invariant.
  4. Historical Isolation: When an administrator updates category commissions via a new proposal, previously placed orders release funds strictly based on their stored fee_snapshot.

5. Delivery Handover & PIN Verification ​

5.1 PIN Generation & Secrecy ​

  • At the moment payment_status shifts to 'paid', a database trigger inserts a random 4-digit code ($0000 - 9999$) into public.order_verification(order_id, delivery_code).
  • Zero-Leak Protection: The PIN is visible only to the purchasing buyer inside their authenticated storefront order view. It is strictly excluded from vendor APIs, courier tracking payloads, and audit exports.
  • Brute-Force Oracle Elimination: The API enforces exponential backoff after 3 invalid PIN attempts.

5.2 Atomic Release Trigger ​

When the buyer inspects the goods and provides the PIN:

  1. Vendor submits PIN via /api/orders/:id/verify-delivery.
  2. Database checks:
    sql
    IF v_order.delivery_code = p_input_pin THEN
        UPDATE public.orders 
        SET status = 'Completed', payment_status = 'released', updated_at = now()
        WHERE id = p_order_id;
    END IF;
  3. PostgreSQL trigger trigger_on_order_released activates immediately:
    • Calls process_order_fund_release().
    • Invokes ledger_post() to credit vendor pending wallet and debit escrow liabilities in a single ACID transaction.

6. Atomic Return Cases & Reverse Logistics ​

When an order arrives defective or incorrect, Debelu initiates an Atomic Return Case governed by AtomicReturnCaseService and validated by [scripts/db-atomic-return-case-checks.mjs](file:///c:/Users/frank/OneDrive/Desktop/Chisom/Debelu/New%20Debelu%20Marketplace/scripts/db-atomic-return-case-checks.mjs).

mermaid
sequenceDiagram
    autonumber
    actor Buyer
    participant ReturnSvc as AtomicReturnCaseService
    actor Courier as Campus Runner / Courier
    actor Vendor
    participant Ledger as Ledger & Refund Engine

    Buyer->>ReturnSvc: 1. File Return Request (photo proof, reason)
    ReturnSvc->>ReturnSvc: 2. Generate evidenceFingerprint (excluding PIN)
    Note over ReturnSvc: Staff reviews return evidence
    ReturnSvc->>ReturnSvc: 3. apply_atomic_return_case('approve') [Revision: 1]
    ReturnSvc-->>Courier: 4. Dispatch Runner for Pickup
    Courier->>ReturnSvc: 5. apply_atomic_return_case('confirm_pickup') [Revision: 2]
    Courier->>Vendor: 6. Handover item to Vendor
    Vendor->>ReturnSvc: 7. apply_atomic_return_case('confirm_inspection', restockEligible: true) [Revision: 3]
    ReturnSvc->>Ledger: 8. Trigger ReviewedWalletRefundService
    Ledger-->>Buyer: 9. Credit Buyer Wallet / Initiate Card Refund

6.1 Sequential Evidence Integrity ​

  • Action confirm_inspection cannot precede confirm_pickup (enforced via error 40001).
  • Action refund cannot be called until inspection is recorded.
  • Stale command replays (replayed: true) return existing receipts without duplicating notifications or audit log records.

6.2 The evidenceFingerprint Shield ​

To prevent a malicious client from using return snapshots to brute-force a buyer's delivery PIN, evidenceFingerprint computes an SHA-256 hash over: $$\text{Fingerprint} = \text{SHA256}(\text{order_id} + \text{total} + \text{items} + \text{vendor_id} + \text{buyer_id})$$ The buyer's delivery_code is explicitly omitted from the hash input.


7. Edge Cases & Concurrency Mitigations ​

Edge CaseFailure ModeMitigation Strategy
Duplicate Paystack WebhooksPaystack retries charge.success 3+ times.Deduplication table processed_webhook_events. Event is processed once; subsequent arrivals return HTTP 200 immediately.
Concurrent PIN Verification & DisputeVendor submits correct PIN while buyer files dispute.PostgreSQL row-level lock (SELECT ... FOR UPDATE). First transaction to commit wins; second receives 40001 Serialization Failure.
Buyer UnresponsivenessGoods delivered at campus station, but buyer fails to share PIN.72-hour automated countdown. After 72 hours with no dispute filed, auto-release worker triggers process_order_fund_release().
Vendor Vacation / Ban Mid-EscrowVendor suspended for fraud while orders are in transit.In-transit orders continue to delivery. Escrow funds unlock into a quarantined balance (ReviewedPayoutBatchService hold).

Released under Proprietary Enterprise License.