# Auction Lifecycle — Manual QA & Operations

## Classification target

**READY AFTER MANUAL QA** until the checklist below is executed against a non-production environment with real MongoDB, wallet balances, cron worker, and Socket.IO.

Concurrency integration test (optional):

```bash
AUCTION_CONCURRENCY_MONGO_URI='mongodb://127.0.0.1:27017/zafirra_auction_test' \
  node --test test/auctionBidConcurrency.integration.test.js
```

## Index deployment

Additive indexes were declared on `Auction`, `Bid`, and `Order.auction`.
Do **not** run `syncIndexes()` blindly in production.
Review and create indexes during a maintenance window.

## Manual lifecycle checklist

1. Provider creates eligible approved Product (media present).
2. `POST /api/provider/auctions` → `approvalStatus=wait`.
3. Admin receives pending-review notification.
4. Admin opens `/dashboard/auctions/wait` (permission enforced).
5. Admin **Request changes** → provider notified; status `changes_requested`.
6. Provider updates and resubmits (pending).
7. Admin approves → upcoming + start/end crons scheduled.
8. Start job → `status=current`, `activatedAt` set.
9. Customer A/B pay deposit (`POST /api/auctions/deposit?auctionId=`) via wallet.
10. Customer A places bid via Socket `auction:bid` (absolute `amount` + required `idempotencyKey`) — see `docs/AUCTION_SOCKET_EVENTS.md`.
10b. Customer B places bid via Socket (HTTP `POST /place-bid` is removed).
10c. Replay the same Socket payload/key → ack `replayed: true`, no second Bid, no second `auction:bid-updated`.
10d. Conflicting reuse of the same key (different amount) → `IDEMPOTENCY_CONFLICT`.
10e. Stale concurrent Socket bid → `STALE_BID` with `minimumNextBid`.
10f. Both clients share the same authoritative `currentPrice` / `endAt` after events; reconnect via `auction:enter` snapshot (`serverNow`).
11. Customer B outbids; A receives outbid notification.
12. Bid inside extension window extends `endAt` once; max extensions enforced; `auction.extended` only when extended.
13. End job (`finalizeAuction`) finalizes exactly once. Socket `auction:ended` is **read-only** and must not mutate settlement when the auction is still live.
14. Cases: no bids / reserve not met / winner awaiting payment.
15. Loser deposits refunded to wallet (idempotent).
16. Winner pays (`POST /api/auctions/winner-payment?auctionId=`) → one Order when provider+product present; settlement `sold`.
17. Missed payment deadline → `winner_defaulted`; deposit `HELD_FOR_REVIEW` (no auto forfeit/2nd winner).
18. Admin resolves held deposit (refund|forfeit) with reason + audit.
19. Live cancel by authorized admin refunds deposits and blocks bids.
20. Arabic/English dashboard + API `lang` header verified.
21. Confirm Agora/live overlay absence does not block core bidding or finalization.

## Socket staging verification (required for READY TO MERGE)

See also `docs/AUCTION_SOCKET.md`.

1. Customer A and Customer B both bid through Socket `auction:bid`.

3. Duplicate Socket request with same idempotency key is stable.
4. Stale Socket Bid is rejected.
5. Socket extension updates `endAt`.
6. Both clients receive the same authoritative state.
7. Reconnect/refetch works (`auction:entered` snapshot).
8. Cron finalizes the Auction.
9. Final auction observe (`auction:ended`) only succeeds after DB finalization.
10. Wallet, winner payment and Order continue correctly.
11. No legacy Haraj/live path mutates canonical settlement state.

## Financial limitations (documented)

- No gateway authorization/hold/capture/refund APIs.
- Online deposit/payment strategies remain partial; wallet path is the supported financial path.
- Do not fake gateway success.

## Recovery procedures

| Stuck state | Action |
|---|---|
| Scheduled past startAt | Re-run/ensure `startAuction` cron; or trigger start path |
| Live past endAt | `finalizeAuction` / end cron; lazy finalize on bid attempt |
| Winner unpaid past deadline | `paymentDeadline` → held deposit; admin resolve |
| Refund failure | Retry refund job / admin wallet adjust with audit |
| Duplicate payment callback | Order unique by auction; FT soft duplicate guards |

## Rollback

- Additive schema only; stop using new endpoints.
- Legacy seller auctions remain readable.
- Do not drop new enum values already written to DB without a migration plan.
