docs: align API reference and data model docs with code reality
API Reference (9 files updated): - Marketplace API: corrected offer endpoints (scoped under /purchase-requests/:id/offers), marked phantom /search /stats /seller/:sellerId /withdraw routes as NOT IMPLEMENTED, documented PUT→PATCH mismatches, removed invalid SellerOffer 'active' status - Dispute API: corrected resolve schema (action enum), categories (no 'fraud'), removed 'under_review' status, added security callouts (3 unguarded endpoints), route shadowing documented, all socket events marked as TODO stubs - Notification API: corrected mark-all-read method+path, fixed broken GET /:id, added unread-count-update event, 90-day TTL documented - Payment API: /create→/save, removed 10+ phantom endpoints, fixed release/refund paths (no /shkeeper/ segment), added 3 unauthenticated endpoint security warnings, stats undercounting documented, export privilege gap documented - Authentication API: 8-digit→6-digit code, no-complexity warning on reset-with-code, rate limiter counts all attempts, passkey stub claims removed, deleteAccount bug noted - Admin API: PUT→PATCH bug documented, wrong status values documented, hard vs soft delete clarified, scanner no-auth security bug, 3 NOT IMPLEMENTED endpoints - Chat API: file upload wrong endpoint bug, archive PUT→PATCH bug, rate limits added - Points API: corrected redeem schema, referral triggers on 'completed' only, leaderboard period ignored, removed 'refund' PointTransaction type - Socket Events: removed request-cancelled, notification-read; added unread-count-update; dispute events all stubs; referral-signup is auth-domain not points-domain Data Models (3 files updated): - SellerOffer: removed 'active' from status enum, withdrawOffer() is dead code - PurchaseRequest: added pending_payment/active statuses, added 'urgent' urgency, corrected description minimum (5 chars), removed finalized/archived - Dispute: corrected action enum, categories (no fraud), removed under_review, security callout on unguarded status/resolve endpoints Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@ tags: [api, socket, realtime, reference]
|
||||
|
||||
# Socket Events
|
||||
|
||||
> **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md))
|
||||
|
||||
The backend runs a Socket.IO server on the same HTTP port as the REST API. It is initialised in [`backend/src/app.ts`](../../backend/src/app.ts) and exposed globally as `global.io`. Helper functions for emitting events from services live in [`backend/src/infrastructure/socket/socketService.ts`](../../backend/src/infrastructure/socket/socketService.ts):
|
||||
|
||||
```ts
|
||||
@@ -58,11 +60,10 @@ Grouped by the service that emits them.
|
||||
|
||||
| Event | Room | Payload | Source |
|
||||
| --- | --- | --- | --- |
|
||||
| `new-purchase-request` | `sellers` | `PurchaseRequest` document | `marketplaceController.createPurchaseRequest` |
|
||||
| `new-purchase-request` | `sellers` (shared global room) | `PurchaseRequest` document | `marketplaceController.createPurchaseRequest` |
|
||||
| `new-offer` | `buyer-<buyerId>` | `{ requestId, offer, sellerId }` | `marketplaceController.createSellerOffer` |
|
||||
| `seller-offer-update` | `seller-<sellerId>` (and global on payment confirm) | `{ sellerId, requestId, eventType: "payment-completed" \| "offer-rejected" \| "offer-accepted", data: { offerId, isSelected, paymentId?, transactionHash?, reason? } }` | `marketplaceController`, `shkeeperRoutes`, `shkeeperWebhook`, `SellerOfferService` |
|
||||
| `purchase-request-update` | `request-<requestId>` | `{ type, requestId, status?, paymentId?, txHash?, provider? }` | `marketplaceController`, `PurchaseRequestService`, `shkeeperRoutes`, `paymentCoordinator` |
|
||||
| `request-cancelled` | `user-<buyerId>`, `user-<sellerId>` | `{ requestId, reason }` | `PurchaseRequestService` |
|
||||
| `transaction-completed` | `user-<buyerId>`, `user-<sellerId>` | `{ requestId, paymentId, amount, currency }` | `marketplaceController` |
|
||||
| `delivery-code-generated` | `request-<requestId>` | `{ requestId, deliveryCode }` (only the seller UI uses this) | `DeliveryService` |
|
||||
| `delivery-update` | `request-<requestId>` | `{ requestId, status, carrier?, trackingNumber? }` | `DeliveryService` |
|
||||
@@ -72,6 +73,8 @@ Grouped by the service that emits them.
|
||||
| `template-checkout-payment-pending` | global | `{ checkoutId }` | `templateCheckoutWebhook` |
|
||||
| `template-checkout-payment-failed` | global | `{ checkoutId, reason }` | `templateCheckoutWebhook` |
|
||||
|
||||
> **Note:** There is **no** `request-cancelled` event. When a purchase request is cancelled, `PurchaseRequestService` emits `purchase-request-update` with `eventType: 'status-changed'` to the `request-<requestId>` room. Any code listening for `request-cancelled` will never fire.
|
||||
|
||||
### Payment
|
||||
|
||||
| Event | Room | Payload | Source |
|
||||
@@ -98,6 +101,8 @@ Grouped by the service that emits them.
|
||||
|
||||
Sources: [`ChatService.ts`](../../backend/src/services/chat/ChatService.ts), [`chatController.ts`](../../backend/src/services/chat/chatController.ts), and `app.ts` socket handlers.
|
||||
|
||||
> **Note:** There is **no** `notification-read` event. Cross-tab unread badge synchronisation is handled by `unread-count-update` (see Notification table below), not by a dedicated read event.
|
||||
|
||||
### Notification
|
||||
|
||||
| Event | Room | Payload |
|
||||
@@ -107,15 +112,21 @@ Sources: [`ChatService.ts`](../../backend/src/services/chat/ChatService.ts), [`c
|
||||
|
||||
Source: [`NotificationService.ts`](../../backend/src/services/notification/NotificationService.ts).
|
||||
|
||||
`unread-count-update` is the canonical cross-tab sync mechanism for the notification badge. It is emitted whenever the unread count changes (new notification or mark-as-read).
|
||||
|
||||
### Points
|
||||
|
||||
| Event | Room | Payload |
|
||||
| --- | --- | --- |
|
||||
| `level-up` | `user-<userId>` | `{ oldLevel, newLevel, lifetimePoints, perks }` |
|
||||
| `referral-reward` | `user-<referrerId>` | `{ referredUserId, points, transactionId }` |
|
||||
| `referral-signup` | `user-<referrerId>` | `{ referredUserId, name, joinedAt }` |
|
||||
| Event | Room | Payload | Source |
|
||||
| --- | --- | --- | --- |
|
||||
| `level-up` | `user-<userId>` | `{ oldLevel, newLevel, lifetimePoints, perks }` | `PointsService` |
|
||||
| `referral-reward` | `user-<referrerId>` | `{ referredUserId, points, transactionId }` | `PointsService` |
|
||||
| `referral-signup` | `user-<referrerId>` | `{ referredUserId, name, joinedAt }` | `authController` (auth domain, **not** `PointsService`) |
|
||||
|
||||
Sources: [`PointsService.ts`](../../backend/src/services/points/PointsService.ts), [`authController.ts`](../../backend/src/services/auth/authController.ts).
|
||||
> **Note on `referral-signup`** — This event is emitted by `authController` when a referred user completes registration, not by `PointsService`. It belongs to the authentication domain. `PointsService` emits only `level-up` and `referral-reward`.
|
||||
|
||||
### Disputes
|
||||
|
||||
> ⚠️ **TODO stubs** — `DisputeService` does not currently emit any Socket.IO events. All socket event handlers in `DisputeService` are placeholder stubs. No real-time dispute notifications fire regardless of dispute status changes.
|
||||
|
||||
## Online status
|
||||
|
||||
|
||||
Reference in New Issue
Block a user