# Auction Socket Event Inventory (pre-implementation)

Branch: `auction-lifecycle-delivery`
Inspected: `listeners/socketManger/socket.js`, `auctionHelper/`, `auctionValidation/`, `liveHelper/`, `liveValidation.js`, `validation/`, chat auction refs.

| Event | Current handler | Domain service | Canonical/legacy | Risk | Required action |
|---|---|---|---|---|---|
| handshake / connection | `socketValidation` | none | shared auth attach | Handshake trusts query `userId` (same as existing project) | Keep; bid mutations still authorize via DB identity |
| `connected` (emit) | socketConfig | none | core | low | keep |
| `auction:enter` | `handleAuctionEnter` | Auction.find + notify | canonical + legacy seller populate | No authoritative snapshot emit; seller-first notify | Emit server snapshot; prefer provider ownership for notify |
| `auction:bid` | `handleAuctionBid` | `placeBidAtomic` | **canonical** | No idempotencyKey forwarded; `price` treated as **increment** vs HTTP absolute; emits on every success including replay; no ack | Require key; absolute `amount`/`price`; skip broadcast on replay; add ack |
| `auction:error` (emit) | various | — | canonical channel | Message-only; no stable codes | Add `code` + safe extras; keep `message` |
| `auction:bid-updated` (emit) | after bid commit | — | **canonical public** | Also emitted on replay | Emit only for new bids |
| `auction.bidAccepted` (emit) | after bid commit | — | legacy alias | Duplicate of bid-updated | Keep as compatibility; same gate as bid-updated |
| `auction.priceUpdated` (emit) | after bid commit | — | legacy alias | Duplicate | Keep compatibility; no new names |
| `auction.extended` (emit) | when extended | — | canonical | Correctly gated | Keep; never on replay |
| `auction:ended` | inline in socket.js | Auction.save liveStatus | **obsolete / conflicting** | Client can set LIVE_ENDED without finalize/settlement | Make read-only: only ack if already finished; no mutation |
| `auction:finished` (emit) | from auction:ended | — | mixed | Fired after liveStatus mutate | Emit only when DB already finalized |
| `start-live` | `handleStartLive` | liveHelper + package gate | **optional live overlay** | Agora tokens commented; uses seller/haraj | Keep overlay; do not touch settlement |
| `enter-live` | `handleEnterLive` | liveHelper / viewer gate | optional overlay | seller checks | Keep; no bid/settle |
| `add-comment` | `handleAddComment` | live comments | optional overlay | subscriber gate | Keep |
| `exit-live` | `handleExitLive` | liveHelper | optional overlay | may set NOT_LIVE | Overlay only; not auction finalize |
| `exist-live` | commented out | — | obsolete | n/a | Leave commented |
| `live:started` / `live:viewers-updated` / `live:comment` / `live:exit` | liveHelper | — | optional overlay | low for core | Document as overlay |
| `auction:viewers-updated` | live tracking | — | overlay | low | Document |
| disconnect cleanup | clears live viewers; may emit live:exit | live status NOT_LIVE for publisher | overlay | Must not finalize auction | Verify no settlement mutation |
| `auction:leave` | **absent** | — | — | — | Optional leave via room leave on ended only |
| `auction:cancelled` | **absent** | — | — | Cancellation is HTTP/dashboard | No socket cancel command |
| Agora token events | commented / disabled | auctionLiveToken | optional overlay | incomplete | Document disabled; not merge blocker |
| chat:* with auction type | chatHelper | Chat | adjacent | Uses legacy `seller` for auction chat | Out of scope unless it mutates auction finance (it does not) |

## Persistence-before-emit (current)

- `auction:bid` → `placeBidAtomic` then emit: **yes** for success path
- Replay currently still re-emits accepted events: **bug**
- `auction:ended` mutates before emit: **yes mutate, wrong domain**

## Idempotency (current)

- HTTP: optional `idempotencyKey` / header; absolute `price`
- Socket: helper accepts key but socket.js **does not pass it**
- Replay lookup: auction+key only; **no client/amount conflict check**
