Files
vmall/openspec/changes/add-wallet-settlement/specs/wallet/spec.md
T

3.7 KiB

ADDED Requirements

Requirement: Demo wallet recharge

An authenticated user SHALL recharge their wallet through a simulated demo flow that records a wallet recharge row and credits the available monetary account with one signed ledger entry in one transaction, without invoking any external payment channel. The API payload and the wallet UI SHALL clearly label the recharge as simulated/demo. Amounts SHALL be positive integer minor units in the account's currency, and monetary arithmetic SHALL NOT use floating point.

Scenario: demo recharge credits balance

  • WHEN a signed-in buyer submits a demo recharge of 5000 minor units
  • THEN the available balance increases by exactly 5000 minor units and exactly one ledger entry with reason wallet_recharge records the resulting balance

Scenario: flow is labeled as demo

  • WHEN a buyer opens the recharge flow
  • THEN it is visibly marked as a simulated recharge and no external payment provider is contacted

Requirement: Guarded withdrawal freeze

An authenticated user SHALL apply to withdraw a positive amount in their account currency. The application SHALL atomically move the amount from available to frozen balance through guarded conditional updates that succeed only when available balance covers the amount, and each balance change SHALL be paired with a ledger entry in the same transaction. When available balance is insufficient the request SHALL fail without changing any balance, and concurrent applications SHALL never overdraw or produce a negative balance.

Scenario: withdrawal freezes funds

  • WHEN a buyer applies to withdraw 1000 minor units
  • THEN available balance decreases and frozen balance increases by exactly 1000 minor units and two ledger entries record the move

Scenario: concurrent applications cannot overdraw

  • WHEN two withdrawal applications together exceed the available balance
  • THEN at most one application succeeds and all balances remain non-negative

Requirement: One-time withdrawal review

Platform admins SHALL list pending withdrawal applications and approve or reject each exactly once through a guarded status transition that requires the pending status and returns 409 on a repeated review. Approve SHALL deduct the frozen amount with a ledger entry recording that the funds left the platform. Reject SHALL return the frozen amount to available balance with a ledger entry. Every review SHALL record the reviewing admin, timestamp, and optional note.

Scenario: reject returns funds

  • WHEN an admin rejects a pending withdrawal application
  • THEN the frozen amount returns to available balance and the application status becomes rejected

Scenario: approve consumes frozen funds

  • WHEN an admin approves a pending withdrawal application
  • THEN frozen balance decreases by the requested amount and the application status becomes approved

Scenario: repeated review conflicts

  • WHEN an admin reviews an application that was already reviewed
  • THEN the API returns 409 and no balance or ledger row changes

Requirement: Paginated fund entries

An authenticated user SHALL page through their own monetary account entries newest first. Each entry SHALL carry the signed delta minor, resulting balance minor, reason, optional business reference, and timestamp, mapped from the existing append-only ledger rows. Entries SHALL never expose or mutate another user's ledger.

Scenario: entries page maps the ledger

  • WHEN the buyer requests a page of fund entries
  • THEN only their own available/frozen ledger rows appear with signed deltas and resulting balances

Scenario: entries are user-isolated

  • WHEN one user requests fund entries
  • THEN no entry belonging to another user is ever returned