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

50 lines
3.7 KiB
Markdown

## 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