---
title: Authorization Matrix - REST and Socket.IO
tags: [audit, security, authorization, matrix, reference]
created: 2026-05-24
status: living
reviewers: [backend, security]
---

# Authorization Matrix - REST and Socket.IO

**Purpose:** Canonical reference mapping every REST endpoint and Socket.IO event to its required access level, ownership checks, state preconditions, rate-limit tier, and audit-log requirement. Implementation tasks reference individual rows by ID.

**How to read this document:**
- Each row is a discrete authorization rule identified by a unique ID (e.g., `AUTH-R001`).
- "Current State" reflects the documented and audited behavior as of 2026-05-24, based on [[Platform Logical Audit - 2026-05-24]], [[Backend Stack Security and Refactor Assessment - 2026-05-24]], and [[Threat Model - Amanat Escrow Platform]].
- "Required State" is what this matrix mandates for launch. Gaps are enumerated in Section 4.
- `[VERIFY]` indicates uncertainty from documentation alone; the implementation must be inspected.

**Cross-references:**
- [[Threat Model - Amanat Escrow Platform]] -- T03 (Socket.IO room join), T09 (admin privilege escalation), T21 (unauthenticated data exfiltration)
- [[Security Architecture]] -- current auth/role model, rate limiting
- [[Backend Architecture]] -- route registration, middleware chain
- [[Real-time Layer]] -- Socket.IO rooms and events
- [[Security Ownership and Launch Decision Criteria]] -- launch checklist items 2.1-2.6

---

## Section 1: Access Level Definitions

| Access Level | Criteria | Enforcement Mechanism |
|---|---|---|
| **Public** | No authentication required. No `req.user`. | No middleware. Rate-limited at IP level. |
| **Authenticated** | Valid Bearer JWT. `req.user = { id, email, role }` is populated. | `authenticateToken` middleware on route. |
| **Owner** | Authenticated + `req.user.id` matches the resource owner. Ownership is determined per resource type: (a) User profile/addresses/wallet: `user._id === req.params.userId`; (b) PurchaseRequest: `request.buyerId === req.user.id`; (c) SellerOffer: `offer.sellerId === req.user.id`; (d) Payment: `payment.buyerId === req.user.id || payment.sellerId === req.user.id`; (e) Chat: `chat.participants.includes(req.user.id)`; (f) Notification: `notification.userId === req.user.id`; (g) Dispute: `dispute.buyerId === req.user.id || dispute.sellerId === req.user.id`; (h) RequestTemplate: `template.sellerId === req.user.id`; (i) BlogPost: N/A (admin-only writes); (j) File: uploader ownership via metadata association. | `authenticateToken` + ownership query in controller/service. |
| **Buyer** | Authenticated + user is the buyer on the specific purchase request (i.e., `request.buyerId === req.user.id`). | `authenticateToken` + service-layer buyer check. |
| **Seller** | Authenticated + user is the selected seller on the purchase request (`request.selectedOffer.sellerId === req.user.id`) or has a seller role making an offer. | `authenticateToken` + service-layer seller check. |
| **Admin** | Authenticated + `req.user.role === 'admin'`. All admin actions MUST be audit-logged. | `authenticateToken` + `roleGuard('admin')` or `authorizeRoles('admin')`. |
| **Support** | Authenticated + `req.user.role === 'support'`. Read-only access to user data, dispute records, and chat. Can reset passwords and escalate to admin. Cannot modify financial records or release funds. | `authenticateToken` + `roleGuard('support')`. Controller must enforce read-only constraint. |
| **Service** | Internal service-to-service calls. Authenticated via shared secret (`X-Internal-Secret` header) or restricted to localhost network. Not user-facing. | Custom middleware verifying internal header or `req.ip === '127.0.0.1'`. |
| **Step-up** | Admin + re-authenticated within configured window (default 5 minutes). Required for high-risk admin actions (role changes, user deletion, payout/release, manual overrides, sensitive wallet operations). | `authenticateToken` + `roleGuard('admin')` + step-up timestamp check from Redis session. |
| **HMAC** | No user auth. Verified via HMAC-SHA256 signature on raw body using `SHKEEPER_WEBHOOK_SECRET`. Signature-verified, not identity-verified. | `express.raw()` body parser + timing-safe HMAC comparison. |

---

## Section 2: REST Endpoint Authorization Matrix

### Rate-Limit Tiers (reference)

| Tier | Limit | Scope | Applies to |
|---|---|---|---|
| Tier 1 (strict) | 5 req / 5 min / IP | Login, register, password reset, verification | Auth mutation paths |
| Tier 2 (auth-financial) | 20 req / 15 min / user | Payment operations, AI calls, file uploads | Financial and cost-bearing |
| Tier 3 (moderate) | 60 req / 15 min / user | Chat messages, notifications, marketplace writes | User interaction |
| Tier 4 (relaxed) | 200 req / 15 min / IP | Public reads, browsing | Public data access |
| Tier 5 (webhook) | Provider-specific; signature-verified | SHKeeper inbound webhooks | External callbacks |
| Tier 6 (admin) | 60 req / 15 min / user | Admin write operations | Admin mutations |

### 2.1 Auth Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| AUTH-R001 | POST | /api/auth/register | Public | None | None | Tier 1 | No | No rate limit. Code logged to stdout. T07. | Public + Tier 1 + remove code logging | Triggers email send. |
| AUTH-R002 | POST | /api/auth/verify-email-code | Public | None | TempVerification exists and not expired | Tier 1 | No | No rate limit. T07. | Public + Tier 1 | Creates User + issues JWT. |
| AUTH-R003 | GET | /api/auth/verify-email/:token | Public | None | Token not expired | Tier 1 | No | Legacy path. | Public + Tier 1 | Legacy URL-based verification. |
| AUTH-R004 | POST | /api/auth/resend-verification | Public | None | User/TempVerification exists | Tier 1 | No | No rate limit. T07. | Public + Tier 1 | Email cost abuse vector. |
| AUTH-R005 | POST | /api/auth/force-verify-user | Service | None | NODE_ENV=development only | Tier 1 | Yes | No auth gate. Exposed in production. | Disable in production builds | Dev-only. Must be removed from prod. |
| AUTH-R006 | POST | /api/auth/login | Public | None | Account not locked | Tier 1 | Yes (failure) | Redis lockout exists. No global rate limit. T12. | Public + Tier 1 + audit failure | Lockout after N failures. |
| AUTH-R007 | POST | /api/auth/refresh-token | Public | Token belongs to user | Refresh token valid and not revoked | Tier 1 | No | No rate limit. | Public + Tier 1 | Rotation detects reuse. |
| AUTH-R008 | POST | /api/auth/logout | Authenticated | Token belongs to user | None | Tier 3 | No | Auth enforced. | Authenticated | Clears Redis session. |
| AUTH-R009 | POST | /api/auth/google/signup | Public | None | Google ID token valid | Tier 1 | No | No rate limit. | Public + Tier 1 | Creates user if new email. |
| AUTH-R010 | POST | /api/auth/google/signin | Public | None | Google ID token valid, user exists | Tier 1 | No | No rate limit. | Public + Tier 1 | Returns JWT for existing user. |
| AUTH-R011 | POST | /api/auth/passkey/authenticate/challenge | Public | None | None | Tier 1 | No | Stubbed implementation. T10. | Disable or fix | Passkeys are broken per T10. |
| AUTH-R012 | POST | /api/auth/passkey/authenticate | Public | None | Challenge valid (in-memory) | Tier 1 | No | In-memory challenge store breaks at scale. T10. | Disable or fix | Public key is stub string. |
| AUTH-R013 | POST | /api/auth/passkey/register/challenge | Authenticated | None | None | Tier 1 | No | Auth required. | Authenticated | Challenge in process memory. |
| AUTH-R014 | POST | /api/auth/passkey/register | Authenticated | None | Challenge valid | Tier 1 | No | Auth required. | Authenticated | Stores stub public key. |
| AUTH-R015 | GET | /api/auth/passkey/list | Authenticated | Owner | None | Tier 3 | No | Auth required. | Authenticated | Returns caller's passkeys. |
| AUTH-R016 | DELETE | /api/auth/passkey/:passkeyId | Authenticated | Owner | Passkey belongs to user | Tier 3 | Yes | Auth required. | Authenticated + audit | |
| AUTH-R017 | POST | /api/auth/request-password-reset | Public | None | User with email exists | Tier 1 | No | Redis rate limit exists. Code logged to stdout. T22. | Public + Tier 1 + remove code logging | Always returns success to avoid enumeration. |
| AUTH-R018 | POST | /api/auth/reset-password | Public | None | Reset token valid and not expired | Tier 1 | Yes | No rate limit. | Public + Tier 1 + audit | Wipes refresh tokens. |
| AUTH-R019 | POST | /api/auth/reset-password-with-code | Public | None | Code valid and not expired | Tier 1 | Yes | No rate limit. | Public + Tier 1 + audit | Alternative reset path. |
| AUTH-R020 | POST | /api/auth/change-password | Authenticated | Owner | Current password correct | Tier 3 | Yes | Auth enforced. | Authenticated + audit | Clears all refresh tokens. |
| AUTH-R021 | GET | /api/auth/profile | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Returns full user doc. |
| AUTH-R022 | PUT | /api/auth/profile | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | |
| AUTH-R023 | POST | /api/auth/update-profile | Authenticated | Owner | None | Tier 3 | No | Auth enforced. Legacy alias. | Authenticated | Duplicate of R022. |
| AUTH-R024 | DELETE | /api/auth/account | Authenticated | Owner | Password re-verified | Tier 3 | Yes | Auth + password required. | Authenticated + audit | Permanent deletion. |
| AUTH-R025 | POST | /api/auth/step-up | Admin | None | Valid challenge context or credentials | Tier 6 | Yes | Not implemented | Admin + Step-up | Required by ADR for high-risk admin actions. Creates 5-minute elevated session in Redis. |
| AUTH-R026 | GET | /api/auth/sessions | Authenticated | Owner | Current refresh session exists | Tier 3 | Yes | Not implemented | Authenticated | Returns active sessions with device, IP, and session age. |
| AUTH-R027 | POST | /api/auth/revoke-session | Authenticated | Owner | Target session belongs to user | Tier 3 | Yes | Not implemented | Authenticated + audit | Revokes one session by sessionTokenHash. |
| AUTH-R028 | POST | /api/auth/revoke-all-sessions | Authenticated | Owner | Multiple active sessions loaded | Tier 3 | Yes | Not implemented | Authenticated + audit | Revokes all sessions except current. |

### 2.2 User Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| USER-R001 | GET | /api/user/profile | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | New controller path. |
| USER-R002 | PUT | /api/user/profile | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | |
| USER-R003 | GET | /api/users/profile | Authenticated | Owner | None | Tier 3 | No | Auth enforced. Legacy. | Authenticated | Legacy alias. |
| USER-R004 | GET | /api/users/profile/:userId | Authenticated | Owner or Admin | None | Tier 3 | No | Auth enforced. Public/private split based on isPublic flag. | Authenticated | Returns limited fields for non-owners. |
| USER-R005 | GET | /api/user/wallet-address | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Returns stored wallet. |
| USER-R006 | PATCH | /api/user/wallet-address | Authenticated | Owner | Signature verification passes | Tier 3 | Yes | Auth enforced. EIP-191 verify. | Authenticated + audit | Financial implications. |
| USER-R007 | GET | /api/users/contacts | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Role-filtered contact list. |
| USER-R008 | GET | /api/users/search | Authenticated | None | q.length >= 2 | Tier 3 | No | Auth enforced. | Authenticated | Returns max 20 results. |
| USER-R009 | GET | /api/users | Authenticated | None | None | Tier 3 | No | Auth enforced. No admin gate. [VERIFY] | Authenticated | Paginated user directory. Should restrict non-admin to limited fields. |

### 2.3 User Admin Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| UADM-R001 | POST | /api/user/admin/create | Admin | None | Email not taken | Tier 6 | Yes | Inline role check. [VERIFY] consistent enforcement. | Admin + Step-up + audit | Creates user with arbitrary role. T09. |
| UADM-R002 | DELETE | /api/user/admin/:userId | Admin | Cannot delete self or other admins | Target user exists | Tier 6 | Yes | Inline role check. | Admin + Step-up + audit | Hard delete. T09. |
| UADM-R003 | PATCH | /api/user/admin/:userId/status | Admin | None | Target user exists | Tier 6 | Yes | Inline role check. | Admin + audit | Activate/suspend. |
| UADM-R004 | PATCH | /api/user/admin/:userId/toggle-status | Admin | None | Target user exists | Tier 6 | Yes | Inline role check. | Admin + audit | Flip active/suspended. |
| UADM-R005 | PATCH | /api/user/admin/:userId/role | Admin | None | Target user exists; valid role | Tier 6 | Yes | Inline role check. | Admin + Step-up + audit | Role change is high-risk. T09. |
| UADM-R006 | GET | /api/user/admin/list | Admin | None | None | Tier 6 | No | Inline role check. | Admin | Paginated user directory. |
| UADM-R007 | GET | /api/user/admin/:userId/dependencies | Admin | None | Target user exists | Tier 6 | No | Inline role check. | Admin | Pre-delete check. |
| UADM-R008 | GET | /api/users/admin/stats | Admin | None | None | Tier 6 | No | Inline role check. | Admin | Aggregated stats. |
| UADM-R009 | GET | /api/users/admin/:userId | Admin | None | Target user exists | Tier 6 | No | Inline role check. | Admin | Full user detail. |
| UADM-R010 | PUT | /api/users/admin/:userId | Admin | None | Target user exists | Tier 6 | Yes | Inline role check. | Admin + audit | Mass update user. |
| UADM-R011 | PUT | /api/users/admin/update/:email | Admin | None | User with email exists | Tier 6 | Yes | Inline role check. | Admin + audit | Mass update by email. |
| UADM-R012 | PATCH | /api/users/admin/:userId/password | Admin | None | Target user exists | Tier 6 | Yes | Inline role check. | Admin + Step-up + audit | Wipes all sessions. |
| UADM-R013 | POST | /api/users/admin/:userId/resend-verification | Admin | None | User not already verified | Tier 6 | Yes | Inline role check. | Admin + audit | Triggers email. |

### 2.3A Admin Approval Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| APV-R001 | GET | /api/admin/approvals | Admin | None | None | Tier 6 | Yes | Not implemented | Admin + Step-up | Pending approval queue for high-value actions. |
| APV-R002 | POST | /api/admin/approvals/{id}/confirm | Admin | None | Approval exists, status = PENDING, approver != creator | Tier 6 | Yes | Not implemented | Admin + Step-up + audit | Confirms pending approval and executes action. |
| APV-R003 | POST | /api/admin/approvals/{id}/reject | Admin | None | Approval exists, status = PENDING | Tier 6 | Yes | Not implemented | Admin + Step-up + audit | Rejects pending approval and records reason. |

### 2.4 Address Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| ADDR-R001 | GET | /api/addresses | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Lists caller's addresses. |
| ADDR-R002 | POST | /api/addresses | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | First auto-primary. |
| ADDR-R003 | PUT | /api/addresses/:addressId | Authenticated | Owner | Address belongs to user | Tier 3 | No | Auth enforced. 404 if not owned. | Authenticated | |
| ADDR-R004 | DELETE | /api/addresses/:addressId | Authenticated | Owner | Address belongs to user | Tier 3 | No | Auth enforced. | Authenticated | Promotes next primary. |
| ADDR-R005 | PATCH | /api/addresses/:addressId/primary | Authenticated | Owner | Address belongs to user | Tier 3 | No | Auth enforced. | Authenticated | |

### 2.5 Purchase Request Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| PR-R001 | POST | /api/marketplace/purchase-requests | Buyer | None | None | Tier 3 | No | Auth enforced. | Authenticated (Buyer) | Emits to sellers room. |
| PR-R002 | POST | /api/marketplace/purchase-requests/bulk | Buyer | None | None | Tier 3 | No | Auth enforced. | Authenticated (Buyer) | Template checkout. |
| PR-R003 | GET | /api/marketplace/purchase-requests | Authenticated | None (filtered by role) | None | Tier 3 | No | Auth enforced. | Authenticated | Buyers see own; sellers see routed; admins see all. |
| PR-R004 | GET | /api/marketplace/purchase-requests/my | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Shortcut for caller's requests. |
| PR-R005 | GET | /api/marketplace/purchase-requests/:id | Public | None | None | Tier 4 | No | No auth. Public read for shareable links. | Public | Exposes request data to unauthenticated users. Consider limiting fields. |
| PR-R006 | PATCH | /api/marketplace/purchase-requests/:id | Owner (Buyer) | buyerId match | Status in [draft, pending] | Tier 3 | No | Auth enforced. Owner check via controller. | Owner (Buyer) | |
| PR-R007 | PATCH | /api/marketplace/purchase-requests/:id/status | Owner or Admin | buyerId match or admin | Valid state transition | Tier 3 | Yes | Auth enforced. Owner or admin. | Owner or Admin + audit | State machine must enforce transitions. |
| PR-R008 | DELETE | /api/marketplace/purchase-requests/:id | Owner (Buyer) | buyerId match | No committed payment | Tier 3 | Yes | Auth enforced. Owner check. | Owner (Buyer) + audit | Must verify no payment attached. |
| PR-R009 | GET | /api/marketplace/purchase-requests/:id/workflow-steps | Public | None | None | Tier 4 | No | No auth. | Public | Returns workflow metadata. |
| PR-R010 | GET | /api/marketplace/purchase-requests/:id/payment-status | Authenticated | Buyer or Seller or Admin | None | Tier 3 | No | Auth enforced. | Authenticated | Returns payment + escrow state. |
| PR-R011 | POST | /api/marketplace/purchase-requests/:id/sync-payment-status | Authenticated | Buyer or Seller | Request has payment | Tier 3 | No | Auth enforced. | Authenticated | Triggers provider re-check. |
| PR-R012 | POST | /api/marketplace/purchase-requests/:id/confirm-payment | Buyer | buyerId match | Payment exists | Tier 3 | No | Auth enforced. | Authenticated (Buyer) | Legacy endpoint. |
| PR-R013 | POST | /api/marketplace/purchase-requests/:id/release-payment | Admin | None | Payment funded; escrowState=funded | Tier 6 | Yes | Auth enforced. Admin check. | Admin + Step-up + audit | Escrow release. T06: must check no active dispute. |
| PR-R014 | PUT | /api/marketplace/purchase-requests/:id/delivery | Seller (selected) | sellerId match on selectedOffer | Status in [payment, processing, delivery] | Tier 3 | No | Auth enforced. Seller check. | Authenticated (Seller) | Shipping details. |
| PR-R015 | POST | /api/marketplace/requests/:id/start-delivery | Seller (selected) | sellerId match | Status = processing | Tier 3 | No | Auth enforced. Seller check. | Authenticated (Seller) | Emits status update. |
| PR-R016 | PATCH | /api/marketplace/purchase-requests/:id/confirm-delivery | Buyer | buyerId match | Status in [delivery] | Tier 3 | No | Auth enforced. Buyer check. | Authenticated (Buyer) | Should NOT allow pre-delivery confirmation. T20. |
| PR-R017 | POST | /api/marketplace/purchase-requests/:id/final-approval | Buyer | buyerId match | Status = delivered | Tier 3 | Yes | Auth enforced. | Authenticated (Buyer) + audit | Triggers escrow release. |
| PR-R018 | GET | /api/marketplace/buyers/:buyerId/purchase-requests | Authenticated | None (admin/seller view) | None | Tier 3 | No | Auth enforced. | Authenticated | Admin or seller view of buyer history. |

### 2.6 Delivery Code Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| DC-R001 | POST | /api/marketplace/purchase-requests/:id/delivery-code/generate | Buyer | buyerId match | Status = delivery | Tier 3 | No | Auth enforced. Buyer check. | Authenticated (Buyer) | |
| DC-R002 | POST | /api/marketplace/purchase-requests/:id/delivery-code/verify | Seller (selected) | sellerId match on selectedOffer | Status = delivery; code not expired | Tier 1 | Yes | Auth enforced. NO rate limit on attempts. T20. | Authenticated (Seller) + Tier 1 | Max 5 attempts per 15 min per request. |
| DC-R003 | GET | /api/marketplace/purchase-requests/:id/delivery-code | Authenticated | Buyer or Seller | None | Tier 3 | No | Auth enforced. | Authenticated | Returns code metadata. |
| DC-R004 | GET | /api/marketplace/purchase-requests/:id/delivery-code/status | Authenticated | Buyer or Seller | None | Tier 3 | No | Auth enforced. | Authenticated | Returns validity state. |

### 2.7 Seller Offer Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| OFF-R001 | POST | /api/marketplace/purchase-requests/:id/offers | Seller | None (any seller can offer) | Request status = pending or in_negotiation | Tier 3 | No | Auth enforced. Seller role. | Authenticated (Seller) | Emits to buyer room. |
| OFF-R002 | PUT | /api/marketplace/purchase-requests/:id/offers | Seller | Offer belongs to seller | Offer status = pending | Tier 3 | No | Auth enforced. Legacy. | Authenticated (Seller) | Legacy alias. |
| OFF-R003 | GET | /api/marketplace/purchase-requests/:id/offers | Public | None | None | Tier 4 | No | No auth. | Public | Exposes all offers for a request. |
| OFF-R004 | GET | /api/marketplace/purchase-requests/:id/has-offer | Seller | None | None | Tier 3 | No | Auth enforced. Seller role. | Authenticated (Seller) | Helper for seller UI. |
| OFF-R005 | GET | /api/marketplace/purchase-requests/:id/offers/:sellerId | Public | None | None | Tier 4 | No | No auth. | Public | Specific seller's offer. |
| OFF-R006 | PATCH | /api/marketplace/offers/:id | Owner (Seller) | offer.sellerId match | offer.status = pending | Tier 3 | No | Auth enforced. Owner check. | Owner (Seller) | Must reject if status != pending. T19. |
| OFF-R007 | DELETE | /api/marketplace/offers/:id | Owner (Seller) | offer.sellerId match | offer.status = pending | Tier 3 | No | Auth enforced. Owner check. | Owner (Seller) | Withdraw offer. |
| OFF-R008 | PUT | /api/marketplace/offers/:id/status | Admin | None | Valid status transition | Tier 6 | Yes | Auth enforced. No admin gate documented. [VERIFY] | Admin + audit | Direct status mutation. T09. |
| OFF-R009 | POST | /api/marketplace/purchase-requests/:id/select-offer | Buyer | buyerId match | Request has offers; no payment yet | Tier 3 | Yes | Auth enforced. | Authenticated (Buyer) + audit | Triggers payment intent. |
| OFF-R010 | POST | /api/marketplace/offers/:id/accept | Buyer | buyerId match | Legacy compatibility | Tier 3 | No | Auth enforced. Legacy. | Authenticated (Buyer) | Legacy alias for select-offer. |

### 2.8 Request Template Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| TPL-R001 | POST | /api/marketplace/request-templates | Seller | None | None | Tier 3 | No | Auth enforced. Seller role. | Authenticated (Seller) | Creates template. |
| TPL-R002 | GET | /api/marketplace/request-templates | Seller | Owner | None | Tier 3 | No | Auth enforced. Seller's own templates. | Authenticated (Seller) | Paginated. |
| TPL-R003 | GET | /api/marketplace/request-templates/stats | Seller | Owner | None | Tier 3 | No | Auth enforced. | Authenticated (Seller) | Aggregate stats. |
| TPL-R004 | GET | /api/marketplace/request-templates/:id | Seller | Owner | Template exists | Tier 3 | No | Auth enforced. Owner check. | Authenticated (Seller) | |
| TPL-R005 | PUT | /api/marketplace/request-templates/:id | Seller | Owner | Template exists | Tier 3 | No | Auth enforced. Owner check. | Authenticated (Seller) | |
| TPL-R006 | DELETE | /api/marketplace/request-templates/:id | Seller | Owner | Template exists | Tier 3 | No | Auth enforced. Owner check. | Authenticated (Seller) | |
| TPL-R007 | PATCH | /api/marketplace/request-templates/:id/toggle-status | Seller | Owner | Template exists | Tier 3 | No | Auth enforced. Owner check. | Authenticated (Seller) | |
| TPL-R008 | GET | /api/marketplace/request-templates/public/:shareableLink | Public | None | Template active and not expired | Tier 4 | No | No auth. Public read. | Public | Shop preview page. |
| TPL-R009 | POST | /api/marketplace/request-templates/:shareableLink/convert | Buyer | None | Template active and not expired | Tier 3 | No | Auth enforced. | Authenticated (Buyer) | Creates PurchaseRequest. |
| TPL-R010 | POST | /api/marketplace/request-templates/batch-convert | Buyer | None | Templates active and not expired | Tier 3 | No | Auth enforced. | Authenticated (Buyer) | Cart checkout. |
| TPL-R011 | POST | /api/marketplace/request-templates/complete-payment | Authenticated | Buyer | Requests exist; payment data provided | Tier 3 | No | Auth enforced. | Authenticated | Marks batch requests as paid. |

### 2.9 Shop Settings Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SHOP-R001 | GET | /api/marketplace/shop/settings/:sellerId | Public | None | None | Tier 4 | No | No auth. Public read. | Public | Shop landing page. |
| SHOP-R002 | GET | /api/marketplace/shop/settings | Seller | Owner | None | Tier 3 | No | Auth enforced. Seller role. | Authenticated (Seller) | Own settings. |
| SHOP-R003 | PUT | /api/marketplace/shop/settings | Seller | Owner | None | Tier 3 | No | Auth enforced. Seller role. | Authenticated (Seller) | |

### 2.10 Category and Seller Directory Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| CAT-R001 | GET | /api/marketplace/categories | Public | None | None | Tier 4 | No | No auth. | Public | |
| CAT-R002 | GET | /api/marketplace/categories/tree | Public | None | None | Tier 4 | No | No auth. | Public | Nested tree. |
| CAT-R003 | GET | /api/marketplace/categories/:id | Public | None | Category exists | Tier 4 | No | No auth. | Public | |
| CAT-R004 | GET | /api/marketplace/sellers | Public | None | None | Tier 4 | No | No auth. | Public | Seller directory. |
| CAT-R005 | GET | /api/marketplace/request-templates/sellers | Public | None | None | Tier 4 | No | No auth. | Public | Sellers with active templates. |
| CAT-R006 | GET | /api/marketplace/request-templates/sellers/:sellerId | Public | None | Seller has active templates | Tier 4 | No | No auth. | Public | Shop profile page. |

### 2.11 Review Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| REV-R001 | GET | /api/marketplace/reviews/:subjectType/:subjectId | Public | None | Reviews enabled by seller | Tier 4 | No | No auth. | Public | Paginated. |
| REV-R002 | GET | /api/marketplace/reviews/:subjectType/:subjectId/summary | Public | None | Reviews enabled | Tier 4 | No | No auth. | Public | Stats only. |
| REV-R003 | POST | /api/marketplace/reviews | Authenticated | None (one review per user per subject) | Subject exists; reviews enabled; no duplicate | Tier 3 | No | Auth enforced. | Authenticated | Computes isVerifiedBuyer. |

### 2.12 Payment Routes (General)

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| PAY-R001 | POST | /api/payment/configuration | Public | None | None | Tier 4 | No | No auth. | Public | Returns widget config. |
| PAY-R002 | GET | /api/payment/health | Public | None | None | Tier 4 | No | No auth. | Public | Health probe. |
| PAY-R003 | GET | /api/payment/shkeeper/config | Public | None | None | Tier 4 | No | No auth. CORS *. | Public | SHKeeper widget config. |
| PAY-R004 | POST | /api/payment | Authenticated | Buyer or Admin | purchaseRequestId, sellerOfferId valid | Tier 2 | Yes | Auth enforced. | Authenticated + audit | Manual payment creation. |
| PAY-R005 | PUT | /api/payment/:id | Authenticated | Owner or Admin | Payment exists | Tier 2 | Yes | Auth enforced. | Authenticated + audit | Status mutation. |
| PAY-R006 | GET | /api/payment | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Caller's payments. |
| PAY-R007 | GET | /api/payment/:id | Authenticated | Owner or Admin | Payment exists | Tier 3 | No | Auth enforced. [VERIFY] ownership | Authenticated | |
| PAY-R008 | GET | /api/payment/:id/debug | Admin | None | Payment exists | Tier 6 | No | Auth enforced. Admin intended. [VERIFY] | Admin | Debug bundle. |
| PAY-R009 | GET | /api/payment/user/:userId | Authenticated | Owner or Admin | User exists | Tier 3 | No | Auth enforced. Ownership check [VERIFY]. | Authenticated | Payments for user. |
| PAY-R010 | GET | /api/payment/stats | Authenticated | Owner or Admin | None | Tier 3 | No | Auth enforced. | Authenticated | Aggregated stats. |
| PAY-R011 | GET | /api/payment/stats/:userId | Authenticated | Owner or Admin | User exists | Tier 3 | No | Auth enforced. | Authenticated | |
| PAY-R012 | GET | /api/payment/export | Authenticated | Owner | None | Tier 3 | Yes | Auth enforced. | Authenticated + audit | Financial data export. |
| PAY-R013 | GET | /api/payment/export/:userId | Admin | None | User exists | Tier 6 | Yes | Auth enforced. Admin check [VERIFY]. | Admin + audit | Export other user's payments. |
| PAY-R014 | POST | /api/payment/payments/cleanup-pending | Admin | None | None | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Deletes stale payments. |
| PAY-R015 | POST | /api/payment/payments/:id/fetch-tx | Admin | None | Payment exists | Tier 6 | No | Auth enforced. [VERIFY] admin gate. | Admin | Re-queries chain. |
| PAY-R016 | POST | /api/payment/payments/auto-fetch-missing | Admin | None | None | Tier 6 | No | Auth enforced. [VERIFY] admin gate. | Admin | Batch backfill. |
| PAY-R017 | POST | /api/payment/callback | Service | paymentRef match | None | Tier 5 | Yes | No user auth. paymentRef-based. | Service | Generic callback. [VERIFY] security of paymentRef. |
| PAY-R018 | POST | /api/payment/verify | Authenticated | Buyer | Payment exists | Tier 2 | Yes | Auth enforced. | Authenticated (Buyer) + audit | Frontend Web3 verification. |

### 2.13 Payment Routes (SHKeeper Pay-in)

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SHK-R001 | POST | /api/payment/shkeeper/intents | Authenticated (Buyer) | Buyer on the purchase request | Request and offer exist; no existing payment | Tier 2 | Yes | Auth enforced. Buyer check. | Authenticated (Buyer) + audit | Creates pay-in intent. |
| SHK-R002 | POST | /api/payment/shkeeper/webhook | HMAC | None | Signature valid; payment exists | Tier 5 | Yes | HMAC verification. Returns 202 on all errors. T02. | HMAC + proper error codes + audit | Must return 400/500 not just 202. |
| SHK-R003 | POST | /api/payment/shkeeper/confirm-transaction | Authenticated | Buyer | Payment exists; not already completed | Tier 2 | Yes | Auth enforced. | Authenticated (Buyer) + audit | Manual fallback. |
| SHK-R004 | POST | /api/payment/shkeeper/test | Service | None | NODE_ENV=development | Tier 1 | No | No auth. Dev only. | Disable in production | T01, T11. |
| SHK-R005 | POST | /api/payment/shkeeper/callback-test | Service | None | NODE_ENV=development | Tier 1 | No | No auth. Dev only. | Disable in production | Echo endpoint. |
| SHK-R006 | GET | /api/payment/shkeeper/callback-test | Service | None | NODE_ENV=development | Tier 1 | No | No auth. Dev only. | Disable in production | GET equivalent. |
| SHK-R007 | POST | /api/payment/shkeeper/create-test-payment | Service | None | NODE_ENV=development | Tier 1 | No | NO AUTH. Exposed in production. T11, T21. | Disable in production | Injects fake payment records. |
| SHK-R008 | POST | /api/payment/shkeeper/trigger-webhook | Authenticated | None | None | Tier 2 | No | Auth enforced. | Authenticated | Sends fake webhook. Dev tool. |
| SHK-R009 | GET | /api/payment/shkeeper/wallet-monitor/status | Public | None | None | Tier 4 | No | No auth. | Public | Monitor state. |
| SHK-R010 | GET | /api/payment/shkeeper/auto-webhook/status | Public | None | None | Tier 4 | No | No auth. | Public | Fallback monitor state. |
| SHK-R011 | GET | /api/payment/shkeeper/webhook-stats | Admin | None | None | Tier 6 | No | Auth enforced. Admin. | Admin | Webhook telemetry. |

### 2.14 Payment Routes (SHKeeper Release/Refund)

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| REL-R001 | POST | /api/payment/shkeeper/:id/release | Admin | None | Payment funded; no active dispute (T06); escrowState=funded | Tier 6 | Yes | Auth enforced. Admin. NO dispute check. T06. | Admin + Step-up + dispute check + audit, + two-person approval for payout > 1000 USD equivalent (see APV-R002/APV-R003) | Builds release tx payload. |
| REL-R002 | POST | /api/payment/shkeeper/:id/release/confirm | Admin | None | Release tx pending; valid txHash | Tier 6 | Yes | Auth enforced. Admin. | Admin + Step-up + audit | Confirms release on-chain. |
| REL-R003 | POST | /api/payment/shkeeper/:id/refund | Admin | None | Payment funded; no active dispute; escrowState=funded | Tier 6 | Yes | Auth enforced. Admin. NO dispute check. T06. | Admin + Step-up + dispute check + audit, + two-person approval for payout > 1000 USD equivalent (see APV-R002/APV-R003) | Builds refund tx. |
| REL-R004 | POST | /api/payment/shkeeper/:id/refund/confirm | Admin | None | Refund tx pending; valid txHash | Tier 6 | Yes | Auth enforced. Admin. | Admin + Step-up + audit | Confirms refund on-chain. |

### 2.15 Payment Routes (SHKeeper Payout)

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| PO-R001 | POST | /api/payment/shkeeper/payout | Admin | None | No existing pending payout for same escrow | Tier 6 | Yes | Auth enforced. Admin. | Admin + Step-up + audit, + two-person approval for payout > 1000 USD equivalent (see APV-R002/APV-R003) | Creates payout task. T05. |
| PO-R002 | GET | /api/payment/shkeeper/payout/status/:taskId | Authenticated | Owner or Admin | Task exists | Tier 3 | No | Auth enforced. | Authenticated | Poll payout status. |
| PO-R003 | POST | /api/payment/shkeeper/payout/webhook | HMAC | None | Signature valid | Tier 5 | Yes | HMAC verification. | HMAC + audit | Payout state changes. |

### 2.16 Payment Routes (Decentralized / Web3)

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| DEC-R001 | POST | /api/payment/decentralized/save | Authenticated (Buyer) | Buyer on referenced purchase request | Request exists | Tier 2 | Yes | NO AUTH. T11, T21. Critical gap. | Authenticated (Buyer) + audit | Persists Web3 payment. |
| DEC-R002 | GET | /api/payment/decentralized/status/:paymentId | Authenticated | Owner or Admin | Payment exists | Tier 3 | No | NO AUTH. T21. | Authenticated | Payment status. |
| DEC-R003 | PUT | /api/payment/decentralized/update | Authenticated (Buyer) | Buyer on referenced purchase request | Payment exists | Tier 2 | Yes | NO AUTH. T11. | Authenticated (Buyer) + audit | Updates payment status/confirmations. |
| DEC-R004 | GET | /api/payment/decentralized/receiver | Public | None | None | Tier 4 | No | No auth. Public escrow address. | Public | Returns escrow wallet. |
| DEC-R005 | GET | /api/payment/decentralized/history/:userId | Authenticated | Owner or Admin | User exists | Tier 3 | No | NO AUTH. T21. Critical gap. | Authenticated | Payment history. |
| DEC-R006 | POST | /api/payment/decentralized/verify/:paymentId | Authenticated | Buyer or Admin | Payment exists; pending status | Tier 2 | Yes | NO AUTH. T01, T11. | Authenticated + audit | Re-verifies on chain. Must decode Transfer event. |
| DEC-R007 | POST | /api/payment/decentralized/verify-all-pending | Admin | None | None | Tier 6 | Yes | NO AUTH. T11. | Admin + audit | Batch verification. |
| DEC-R008 | POST | /api/payment/decentralized/admin-payout | Admin | None | Valid request; valid wallet | Tier 6 | Yes | Auth enforced. Admin. | Admin + Step-up + audit | Direct wallet payout. |

### 2.17 Marketplace Payment Routes (Legacy)

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| MPAY-R001 | POST | /api/marketplace/payments | Authenticated | Buyer | Valid request/offer | Tier 2 | Yes | Auth enforced. | Authenticated + audit | Legacy. Prefer PAY-R004. |
| MPAY-R002 | GET | /api/marketplace/payments | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Legacy. |
| MPAY-R003 | GET | /api/marketplace/payments/:paymentId | Authenticated | Owner or Admin | Payment exists | Tier 3 | No | Auth enforced. | Authenticated | Legacy. |
| MPAY-R004 | PATCH | /api/marketplace/payments/:paymentId | Authenticated | Owner or Admin | Payment exists | Tier 2 | Yes | Auth enforced. | Authenticated + audit | Legacy. |
| MPAY-R005 | POST | /api/marketplace/payments/verify | Authenticated (Buyer) | Buyer on purchase request | Valid request/offer | Tier 2 | Yes | Auth enforced. | Authenticated (Buyer) + audit | Legacy Web3 verification. |

### 2.18 Chat Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| CHAT-R001 | POST | /api/chat | Authenticated | None | 2+ participant IDs | Tier 3 | No | Auth enforced. | Authenticated | Creates chat. |
| CHAT-R002 | POST | /api/chat/purchase-request | Authenticated | Buyer or Seller on request | Request exists | Tier 3 | No | Auth enforced. | Authenticated | Idempotent. |
| CHAT-R003 | POST | /api/chat/support | Authenticated | None | None | Tier 3 | No | Auth enforced. | Authenticated | Support chat. |
| CHAT-R004 | GET | /api/chat | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Caller's chats. |
| CHAT-R005 | GET | /api/chat/stats | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Aggregate counts. |
| CHAT-R006 | GET | /api/chat/:id/info | Authenticated | Participant | Chat exists; user in participants | Tier 3 | No | Auth enforced. Participant check. | Authenticated | Chat metadata. |
| CHAT-R007 | PATCH | /api/chat/:id/archive | Authenticated | Participant | Chat exists | Tier 3 | No | Auth enforced. | Authenticated | Toggle archive. |
| CHAT-R008 | POST | /api/chat/:id/participants | Authenticated | Creator or Admin | Chat is group type | Tier 3 | No | Auth enforced. | Authenticated | Add participant. |
| CHAT-R009 | DELETE | /api/chat/:id/participants/:participantId | Authenticated | Creator or Admin | Chat is group type | Tier 3 | No | Auth enforced. | Authenticated | Remove participant. |
| CHAT-R010 | GET | /api/chat/:id/messages | Authenticated | Participant | Chat exists | Tier 3 | No | Auth enforced. Participant check. | Authenticated | Paginated messages. |
| CHAT-R011 | POST | /api/chat/:id/messages | Authenticated | Participant | Chat exists | Tier 3 | No | Auth enforced. Participant check. | Authenticated | Send text message. |
| CHAT-R012 | POST | /api/chat/:id/messages/file | Authenticated | Participant | Chat exists; file within limits | Tier 2 | No | Auth enforced. Participant check. | Authenticated | File attachment. |
| CHAT-R013 | PATCH | /api/chat/:id/messages/read | Authenticated | Participant | Chat exists | Tier 3 | No | Auth enforced. | Authenticated | Mark as read. |
| CHAT-R014 | PUT | /api/chat/:id/messages/:messageId | Authenticated | Message author | Message exists; within edit window | Tier 3 | No | Auth enforced. Author check. | Authenticated | Edit message. |
| CHAT-R015 | DELETE | /api/chat/:id/messages/:messageId | Authenticated | Author or Admin | Message exists | Tier 3 | No | Auth enforced. Author or admin. | Authenticated | Soft-delete. |

### 2.19 Notification Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| NOTIF-R001 | GET | /api/notifications | Authenticated | Owner | None | Tier 3 | No | Controller route: auth enforced. Legacy route: NO AUTH, ?userId= param. T21. | Authenticated | Legacy router must be removed or gated. |
| NOTIF-R002 | GET | /api/notifications/unread-count | Authenticated | Owner | None | Tier 3 | No | Controller route: auth enforced. | Authenticated | |
| NOTIF-R003 | GET | /api/notifications/:id | Authenticated | Owner | Notification belongs to user | Tier 3 | No | Controller route: auth enforced. | Authenticated | |
| NOTIF-R004 | PATCH | /api/notifications/:id/read | Authenticated | Owner | Notification belongs to user | Tier 3 | No | Controller: auth. Legacy: { userId } in body. T21. | Authenticated | Legacy path must be removed. |
| NOTIF-R005 | PATCH | /api/notifications/mark-all-read | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | |
| NOTIF-R006 | PATCH | /api/notifications/bulk/mark-read | Authenticated | Owner | All IDs belong to user | Tier 3 | No | Auth enforced. | Authenticated | |
| NOTIF-R007 | DELETE | /api/notifications/:id | Authenticated | Owner | Notification belongs to user | Tier 3 | No | Auth enforced. | Authenticated | |
| NOTIF-R008 | DELETE | /api/notifications/bulk/delete | Authenticated | Owner | All IDs belong to user | Tier 3 | No | Auth enforced. | Authenticated | |
| NOTIF-R009 | POST | /api/notifications | Authenticated | None (creates for any userId) | None | Tier 3 | Yes | Controller: auth. Legacy: OPEN. T21. | Authenticated (Admin or Service) + audit | Should restrict who can create notifications for other users. |

### 2.20 Dispute Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| DIS-R001 | POST | /api/disputes | Authenticated | Buyer or Seller on request | Request exists; no open dispute for same request | Tier 3 | Yes | Auth enforced. Participant check. | Authenticated + audit | Must set escrowState=disputed. T06. |
| DIS-R002 | GET | /api/disputes | Authenticated | Owner or Admin | None | Tier 3 | No | Auth enforced. | Authenticated | Own disputes or all (admin). |
| DIS-R003 | GET | /api/disputes/statistics | Admin | None | None | Tier 6 | No | Auth enforced. Admin. | Admin | Dashboard data. |
| DIS-R004 | GET | /api/disputes/:id | Authenticated | Participant or Admin | Dispute exists | Tier 3 | No | Auth enforced. Participant or admin check. | Authenticated | |
| DIS-R005 | POST | /api/disputes/:id/assign | Admin | None | Dispute exists; status=open | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Assigns moderator. |
| DIS-R006 | PATCH | /api/disputes/:id/status | Admin | None | Valid status transition | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Status update. |
| DIS-R007 | POST | /api/disputes/:id/resolve | Admin | None | Dispute in under_review status; no pending payout | Tier 6 | Yes | Auth enforced. Admin. | Admin + Step-up + audit | Triggers escrow release/refund. T06. |
| DIS-R008 | POST | /api/disputes/:id/evidence | Authenticated | Participant or Admin | Dispute exists; not closed | Tier 3 | No | Auth enforced. Participant or admin check. | Authenticated | Attach evidence. |

### 2.21 AI Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| AI-R001 | POST | /api/ai/generate | Authenticated | None | None | Tier 2 | No | NO AUTH. T08. Cost abuse. | Authenticated | OpenAI cost-bearing. |
| AI-R002 | POST | /api/ai/analyze | Authenticated | None | None | Tier 2 | No | NO AUTH. T08. | Authenticated | Moderation/sentiment. |
| AI-R003 | POST | /api/ai/translate | Authenticated | None | None | Tier 2 | No | NO AUTH. T08. | Authenticated | Translation. |
| AI-R004 | POST | /api/ai/assist | Authenticated | None | None | Tier 2 | No | NO AUTH. T08. | Authenticated | Conversational assistant. |

### 2.22 Blog Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| BLOG-R001 | GET | /api/blog/posts | Public | None | None | Tier 4 | No | No auth. Public. | Public | Paginated. |
| BLOG-R002 | GET | /api/blog/posts/featured | Public | None | None | Tier 4 | No | No auth. | Public | |
| BLOG-R003 | GET | /api/blog/posts/recent | Public | None | None | Tier 4 | No | No auth. | Public | |
| BLOG-R004 | GET | /api/blog/posts/search | Public | None | q.length >= 2 | Tier 4 | No | No auth. | Public | |
| BLOG-R005 | GET | /api/blog/posts/:slug | Public | None | Post published | Tier 4 | No | No auth. Increments viewsCount on GET. | Public | Move view count to separate beacon. |
| BLOG-R006 | GET | /api/blog/admin/posts | Admin | None | None | Tier 6 | No | Auth enforced. Admin. | Admin | Includes drafts. |
| BLOG-R007 | GET | /api/blog/admin/posts/:id | Admin | None | Post exists | Tier 6 | No | Auth enforced. Admin. | Admin | |
| BLOG-R008 | POST | /api/blog/posts | Admin | None | None | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Create post. |
| BLOG-R009 | PUT | /api/blog/posts/:id | Admin | None | Post exists | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Update post. |
| BLOG-R010 | DELETE | /api/blog/posts/:id | Admin | None | Post exists | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Hard delete. |

### 2.23 Points Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| PTS-R001 | GET | /api/points/my-points | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Balance and level. |
| PTS-R002 | GET | /api/points/transactions | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Paginated ledger. |
| PTS-R003 | GET | /api/points/referrals | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | Referral history. |
| PTS-R004 | GET | /api/points/levels | Authenticated | None | None | Tier 3 | No | Auth enforced. Data is non-sensitive. | Authenticated | Level config list. |
| PTS-R005 | GET | /api/points/leaderboard | Authenticated | None | None | Tier 3 | No | Auth enforced. | Authenticated | Top referrers. |
| PTS-R006 | POST | /api/points/redeem | Authenticated | Owner | Sufficient balance | Tier 2 | Yes | Auth enforced. | Authenticated + audit | Redeems points. |
| PTS-R007 | POST | /api/points/generate-referral-code | Authenticated | Owner | None | Tier 3 | No | Auth enforced. | Authenticated | |
| PTS-R008 | POST | /api/points/admin/add | Admin | None | Target user exists; amount valid | Tier 6 | Yes | Auth enforced. Admin. | Admin + audit | Grant/deduct points. |

### 2.24 File Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| FILE-R001 | POST | /api/files/upload/avatar | Authenticated | Owner | File within size/type limits | Tier 2 | No | Auth enforced. | Authenticated | |
| FILE-R002 | POST | /api/files/upload/file | Authenticated | Owner | File within limits | Tier 2 | No | Auth enforced. | Authenticated | Generic upload. |
| FILE-R003 | POST | /api/files/upload/files | Authenticated | Owner | Up to 5 files; within limits | Tier 2 | No | Auth enforced. | Authenticated | Multi-file. |
| FILE-R004 | POST | /api/files/upload/request-template-images | Authenticated (Seller) | Owner | Up to 10 images; valid types | Tier 2 | No | Auth enforced. Seller role. | Authenticated (Seller) | Template images. |
| FILE-R005 | POST | /api/files/upload/blog-images | Admin | None | Up to 10 images; valid types | Tier 2 | No | Auth enforced. [VERIFY] admin gate. | Admin | Blog images. |
| FILE-R006 | DELETE | /api/files/delete | Authenticated | Owner (uploader) | File exists; path within uploads/ | Tier 3 | No | Auth enforced. | Authenticated | |
| FILE-R007 | GET | /api/files/info/:filePath | Authenticated | None | File exists | Tier 3 | No | Auth enforced. | Authenticated | |
| FILE-R008 | GET | /api/files/stats | Admin | None | None | Tier 6 | No | Auth enforced. Admin gating planned. | Admin | Upload statistics. |
| FILE-R009 | GET | /uploads/* | Public | None | File exists | Tier 4 | No | No auth. Static serving. | Public | No auth on file access. Sensitive dispute evidence is accessible. |

### 2.25 Admin Data Cleanup Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| ADM-R001 | GET | /api/admin/cleanup/stats | Admin | None | None | Tier 6 | No | Auth + role enforced. | Admin | Collection stats. |
| ADM-R002 | GET | /api/admin/cleanup/collections | Admin | None | None | Tier 6 | No | Auth + role enforced. | Admin | Collection list. |
| ADM-R003 | POST | /api/admin/cleanup/clean | Admin | None | confirm="DELETE_ALL_DATA" for real execution | Tier 6 | Yes | Auth + role enforced. | Admin + Step-up + audit | Bulk delete. |
| ADM-R004 | DELETE | /api/admin/cleanup/user/:userId | Admin | Cannot delete self | confirm=DELETE_USER_DATA | Tier 6 | Yes | Auth + role enforced. | Admin + Step-up + audit | GDPR deletion. |
| ADM-R005 | POST | /api/admin/cleanup/temp | Admin | None | None | Tier 6 | Yes | Auth + role enforced. | Admin + audit | Purge temp data. |
| ADM-R006 | POST | /api/admin/cleanup/seed-templates | Admin | None | None | Tier 6 | No | Auth + role enforced. | Admin | Re-seed templates. |
| ADM-R007 | POST | /api/admin/cleanup/seed-all | Admin | None | None | Tier 6 | No | Auth + role enforced. | Admin | Full seed. |

### 2.26 Health and Discovery Routes

| ID | Method | Path | Access Level | Ownership Check | State Preconditions | Rate-Limit Tier | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SYS-R001 | GET | /health | Public | None | None | Tier 4 | No | Public. | Public | Docker healthcheck. |
| SYS-R002 | GET | /api | Public | None | None | Tier 4 | No | Public. | Public | API discovery. |

---

## Section 3: Socket.IO Event Authorization Matrix

### 3.1 Connection and Handshake Events

| ID | Event Name | Direction | Access Level | Room Membership | Payload Restrictions | Rate-Limit | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SOCK-E001 | `connection` | Client -> Server | Authenticated | None at connect; rooms joined after | JWT in handshake.auth.token | N/A | No | JWT verified; invalid token disconnects. [VERIFY] enforcement. | Authenticated | Server sets socket.data.user. |
| SOCK-E002 | `disconnect` | Client -> Server | Authenticated | All rooms left | None | N/A | No | No user-offline broadcast. | Authenticated | Should emit user-status-change offline. |

### 3.2 Room Join Events

| ID | Event Name | Direction | Access Level | Room Membership | Payload Restrictions | Rate-Limit | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SOCK-E003 | `join-user-room` | Client -> Server | Authenticated | `user-{userId}` | userId MUST equal socket.data.user.id | Tier 3 | No | Client-supplied userId. Server verification UNCERTAIN. T03. | Server-derived; remove client event | Server should auto-join on handshake. T03. |
| SOCK-E004 | `join-request-room` | Client -> Server | Authenticated | `request-{requestId}` | User must be participant (buyer or selected seller) of request | Tier 3 | No | Client-supplied requestId. Server verification UNCERTAIN. T03. | Authenticated + participant check | Must verify user is buyer/seller on request. |
| SOCK-E005 | `leave-request-room` | Client -> Server | Authenticated | Leaves `request-{requestId}` | User must currently be in room | Tier 3 | No | Client-supplied. [VERIFY] auth. | Authenticated | |
| SOCK-E006 | `join-seller-room` | Client -> Server | Authenticated (Seller) | `seller-{sellerId}` + `sellers` | sellerId MUST equal socket.data.user.id; user role must include seller | Tier 3 | No | Client-supplied sellerId. Server verification UNCERTAIN. T03. | Server-derived from JWT role + id | Auto-join if role=seller. |
| SOCK-E007 | `leave-seller-room` | Client -> Server | Authenticated (Seller) | Leaves both | Must currently be in room | Tier 3 | No | Client-supplied. | Authenticated | |
| SOCK-E008 | `join-buyer-room` | Client -> Server | Authenticated (Buyer) | `buyer-{buyerId}` + `buyers` | buyerId MUST equal socket.data.user.id; user role must include buyer | Tier 3 | No | Client-supplied buyerId. Server verification UNCERTAIN. T03. | Server-derived from JWT role + id | Auto-join if role=buyer. |
| SOCK-E009 | `leave-buyer-room` | Client -> Server | Authenticated (Buyer) | Leaves both | Must currently be in room | Tier 3 | No | Client-supplied. | Authenticated | |
| SOCK-E010 | `join-chat-room` | Client -> Server | Authenticated | `chat-{chatId}` | User must be in chat.participants | Tier 3 | No | Client-supplied chatId. Server verification UNCERTAIN. T03. | Authenticated + participant check | Must verify membership. |
| SOCK-E011 | `leave-chat-room` | Client -> Server | Authenticated | Leaves `chat-{chatId}` | Must currently be in room | Tier 3 | No | Client-supplied. | Authenticated | |

### 3.3 Chat Events

| ID | Event Name | Direction | Access Level | Room Membership | Payload Restrictions | Rate-Limit | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SOCK-E012 | `typing-start` | Client -> Server | Authenticated | Must be in `chat-{chatId}` | chatId, userId, userName; userId must match socket | Tier 3 | No | No auth documented on event handler. | Authenticated + room member | Broadcasts to chat room. |
| SOCK-E013 | `typing-stop` | Client -> Server | Authenticated | Must be in `chat-{chatId}` | chatId, userId; userId must match socket | Tier 3 | No | No auth documented. | Authenticated + room member | |

### 3.4 Presence Events

| ID | Event Name | Direction | Access Level | Room Membership | Payload Restrictions | Rate-Limit | Audit Log | Current State | Required State | Notes |
|---|---|---|---|---|---|---|---|---|---|---|
| SOCK-E014 | `user-online` | Client -> Server | Authenticated | Joins `user-{userId}` | userId must match socket.data.user.id | Tier 3 | No | Client-supplied. Broadcasts user-status-change. | Authenticated | Should be server-derived. |

### 3.5 Server-to-Client Events (Emission Authorization)

Server-to-client events are emitted by backend services after REST-level authorization. The socket layer does NOT re-authorize emissions; it relies on room membership to limit audience. This table documents which rooms receive which events and what data they contain.

| ID | Event Name | Direction | Emitted By | Target Rooms | Payload Sensitivity | Audit Log | Notes |
|---|---|---|---|---|---|---|---|
| SOCK-E015 | `new-notification` | Server -> Client | NotificationService | `user-{recipientId}` | Contains notification body; PII if notification content includes it | No | Relies on correct room membership. |
| SOCK-E016 | `unread-count-update` | Server -> Client | NotificationService | `user-{userId}` | Low (count only) | No | |
| SOCK-E017 | `new-purchase-request` | Server -> Client | PurchaseRequestService | `sellers` | Contains request details; some fields may be sensitive | No | Broadcast to all sellers. |
| SOCK-E018 | `new-offer` | Server -> Client | SellerOfferService | `buyer-{buyerId}` | Contains offer price; financial data | No | |
| SOCK-E019 | `seller-offer-update` | Server -> Client | SellerOfferService | `seller-{sellerId}` + global on payment | Contains offer status and payment info | No | Global emit leaks data. |
| SOCK-E020 | `purchase-request-update` | Server -> Client | PurchaseRequestService | `request-{requestId}` | Contains status and tx hashes | No | |
| SOCK-E021 | `request-cancelled` | Server -> Client | PurchaseRequestService | `user-{buyerId}`, `user-{sellerId}` | Contains request ID | No | |
| SOCK-E022 | `transaction-completed` | Server -> Client | MarketplaceController | `user-{buyerId}`, `user-{sellerId}` | Contains amount and currency | No | |
| SOCK-E023 | `delivery-code-generated` | Server -> Client | DeliveryService | `request-{requestId}` | Contains 6-digit code. HIGH sensitivity. | No | Code exposed to room; only seller should see it. |
| SOCK-E024 | `delivery-update` | Server -> Client | DeliveryService | `request-{requestId}` | Contains carrier/tracking | No | |
| SOCK-E025 | `delivery-confirmed` | Server -> Client | DeliveryService | `request-{requestId}` | Contains request ID only | No | |
| SOCK-E026 | `buyer-confirmed-delivery` | Server -> Client | DeliveryService | `user-{sellerId}` | Contains buyerId | No | |
| SOCK-E027 | `payment-created` | Server -> Client | PaymentService | Global | Contains paymentId, amount, currency, parties | No | Global emit leaks financial metadata. |
| SOCK-E028 | `payment-received` | Server -> Client | PaymentRoutes | `user-{sellerId}` | Contains amount, buyerId | No | |
| SOCK-E029 | `payment-update` | Server -> Client | PaymentCoordinator | Global + room-specific | Contains status, escrowState, txHash | No | Global emit is too broad. |
| SOCK-E030 | `payout-created` | Server -> Client | PayoutService | Global | Contains payoutId, sellerId, amount | No | Global emit. Should be targeted. |
| SOCK-E031 | `payout-completed` | Server -> Client | PayoutService | Global, `user-{sellerId}` | Contains txHash | No | |
| SOCK-E032 | `payout-updated` | Server -> Client | PayoutService | Global | Contains status | No | |
| SOCK-E033 | `new-message` | Server -> Client | ChatService | `chat-{chatId}` | Contains message content; potentially sensitive | No | |
| SOCK-E034 | `messages-read` | Server -> Client | ChatService | `chat-{chatId}` | Low (read receipt) | No | |
| SOCK-E035 | `message-edited` | Server -> Client | ChatService | `chat-{chatId}` | Contains new content | No | |
| SOCK-E036 | `message-deleted` | Server -> Client | ChatService | `chat-{chatId}` | Low (messageId) | No | |
| SOCK-E037 | `participants-added` | Server -> Client | ChatService | `chat-{chatId}` | Contains user IDs | No | |
| SOCK-E038 | `participant-removed` | Server -> Client | ChatService | `chat-{chatId}` | Contains user ID | No | |
| SOCK-E039 | `user-typing` | Server -> Client | Socket handler | `chat-{chatId}` | Contains userId, userName | No | |
| SOCK-E040 | `user-status-change` | Server -> Client | Socket handler | Broadcast | Contains userId, lastSeen | No | |
| SOCK-E041 | `level-up` | Server -> Client | PointsService | `user-{userId}` | Low (level info) | No | |
| SOCK-E042 | `referral-reward` | Server -> Client | PointsService | `user-{referrerId}` | Contains points earned | No | |
| SOCK-E043 | `referral-signup` | Server -> Client | AuthController | `user-{referrerId}` | Contains referred user info | No | |
| SOCK-E044 | `template-checkout-payment-confirmed` | Server -> Client | PaymentCoordinator | Global + `template-checkout-{id}` | Contains paymentId, requestIds | No | Global emit. |
| SOCK-E045 | `template-checkout-payment-pending` | Server -> Client | PaymentCoordinator | Global | Contains checkoutId | No | Global emit. |
| SOCK-E046 | `template-checkout-payment-failed` | Server -> Client | PaymentCoordinator | Global | Contains checkoutId, reason | No | Global emit. |

---

## Section 4: Current Gaps and Required Fixes

### 4.1 CRITICAL -- Authentication Missing but Required

| Gap ID | Endpoint / Event | Threat IDs | Description | Impact |
|---|---|---|---|---|
| GAP-C001 | POST /api/payment/decentralized/save | T11, T21 | No authentication. Anyone can persist Web3 payment records. | Payment fraud; data poisoning |
| GAP-C002 | PUT /api/payment/decentralized/update | T11 | No authentication. Anyone can update decentralized payment status/confirmations. | Payment status manipulation |
| GAP-C003 | GET /api/payment/decentralized/history/:userId | T21 | No authentication. Anyone can read any user's payment history. | Privacy breach; data exfiltration |
| GAP-C004 | POST /api/payment/decentralized/verify/:paymentId | T01, T11 | No authentication. Anyone can trigger chain re-verification. | DoS; payment fraud if verification is flawed |
| GAP-C005 | POST /api/payment/decentralized/verify-all-pending | T11 | No authentication. Anyone can trigger batch verification. | DoS; resource exhaustion |
| GAP-C006 | GET /api/payment/decentralized/status/:paymentId | T21 | No authentication. Payment status exposed. | Information disclosure |
| GAP-C007 | POST /api/payment/shkeeper/create-test-payment | T11, T21 | No authentication. Injects fake payment records. | Data poisoning in production |
| GAP-C008 | POST /api/ai/generate | T08 | No authentication. Unlimited OpenAI cost abuse. | Financial cost; DoS |
| GAP-C009 | POST /api/ai/analyze | T08 | No authentication. | Financial cost |
| GAP-C010 | POST /api/ai/translate | T08 | No authentication. | Financial cost |
| GAP-C011 | POST /api/ai/assist | T08 | No authentication. | Financial cost |
| GAP-C012 | POST /api/auth/force-verify-user | T09 | No authentication gate. Bypasses email verification. | Account takeover |
| GAP-C013 | POST /api/payment/shkeeper/test | T11 | No authentication in production. | Test data in production |
| GAP-C014 | POST /api/payment/shkeeper/callback-test | T11 | No authentication in production. | Test data in production |
| GAP-C015 | GET /api/payment/shkeeper/callback-test | T11 | No authentication in production. | Test data in production |
| GAP-C016 | Legacy notification router (mounted without auth) | T21 | Accepts ?userId= query parameter for notification read/modify. | Privacy breach; notification manipulation |
| GAP-C017 | Socket.IO room join events | T03 | Client-supplied userId/requestId/chatId; server verification uncertain. Any authenticated user may subscribe to any other user's rooms. | Private data exfiltration; real-time surveillance |

### 4.2 CRITICAL -- Ownership Check Missing but Required

| Gap ID | Endpoint / Event | Threat IDs | Description | Impact |
|---|---|---|---|---|
| GAP-C018 | PATCH /api/marketplace/offers/:id (post-acceptance) | T19 | updateOffer does not enforce status check. Seller can change price after acceptance. | Financial fraud |
| GAP-C019 | POST /api/payment/shkeeper/:id/release | T06 | No check for active dispute before release. Escrow released during active dispute. | Fund loss |
| GAP-C020 | POST /api/payment/shkeeper/:id/refund | T06 | Same as above for refund. | Fund loss |
| GAP-C021 | Web3 payment verification (BSCTransactionVerifier) | T01 | Only checks receipt.status, does not verify recipient address, token contract, or amount. | Payment fraud |

### 4.3 HIGH -- Rate Limiting Missing but Required

| Gap ID | Endpoint / Event | Threat IDs | Description | Impact |
|---|---|---|---|---|
| GAP-H001 | Global rate limiting disabled | T12 | express-rate-limit disabled in app.ts. All endpoints unprotected. | All abuse vectors open |
| GAP-H002 | POST /api/auth/register | T07 | No rate limit. Email spam. | SMTP cost; reputation damage |
| GAP-H003 | POST /api/auth/resend-verification | T07 | No rate limit. Email spam. | SMTP cost |
| GAP-H004 | POST /api/auth/login | T12 | Redis lockout exists but no IP-level rate limit. | Brute force |
| GAP-H005 | POST /api/marketplace/purchase-requests/:id/delivery-code/verify | T20 | No rate limit on 6-digit code verification. 900K combinations brute-forceable. | Delivery fraud |
| GAP-H006 | POST /api/ai/* (all four) | T08 | No rate limit. No per-user budget. | OpenAI cost explosion |
| GAP-H007 | POST /api/payment/decentralized/* | T11 | No rate limit even when auth is added. | Database flooding |
| GAP-H008 | POST /api/chat/:id/messages | T12 | No rate limit on chat messages. | Chat spam |

### 4.4 HIGH -- State Precondition Check Missing but Required

| Gap ID | Endpoint / Event | Threat IDs | Description | Impact |
|---|---|---|---|---|
| GAP-H009 | POST /api/disputes (dispute creation) | T06 | Does not set escrowState=disputed. No escrow hold on dispute creation. | Funds released during dispute |
| GAP-H010 | PATCH /api/marketplace/purchase-requests/:id/confirm-delivery | T20 | Buyer can confirm delivery before seller ships (manual fast-track). | Escrow released without delivery |
| GAP-H011 | PUT /api/marketplace/offers/:id/status | T09 | No documented admin-only enforcement on direct status mutation. | Unauthorized offer manipulation |

### 4.5 MEDIUM -- Audit Logging Missing but Required

| Gap ID | Endpoint / Event | Description | Impact |
|---|---|---|---|
| GAP-M001 | All admin routes (user management) | No structured audit log for admin user management actions. | No accountability for admin actions |
| GAP-M002 | POST /api/payment/shkeeper/:id/release | No append-only audit log for escrow release. | No financial audit trail |
| GAP-M003 | POST /api/payment/shkeeper/:id/refund | No append-only audit log for escrow refund. | No financial audit trail |
| GAP-M004 | POST /api/payment/shkeeper/payout | No append-only audit log for payout creation. | No financial audit trail |
| GAP-M005 | POST /api/disputes/:id/resolve | No append-only audit log for dispute resolution. | No dispute resolution trail |
| GAP-M006 | PATCH /api/user/admin/:userId/role | No audit log for role changes. | No accountability |
| GAP-M007 | DELETE /api/user/admin/:userId | No audit log for user deletion. | No accountability |
| GAP-M008 | POST /api/points/admin/add | No structured audit log for manual point grants. | No points audit trail |
| GAP-M009 | POST /api/auth/change-password | No audit log for password changes. | No security event trail |
| GAP-M010 | Global emit events (payment-created, payment-update, payout-created, etc.) | Sensitive financial data broadcast globally via Socket.IO. Should be targeted. | Data overexposure |

### 4.6 Socket.IO-Specific Gaps

| Gap ID | Issue | Threat IDs | Description | Impact |
|---|---|---|---|---|
| GAP-S001 | No handshake JWT authentication | T03 | Socket Events doc states "no token-based handshake" -- ownership checked at REST layer only. | Unauthenticated socket connections |
| GAP-S002 | Client-driven room joins | T03 | All join-* events accept arbitrary IDs. Server must verify socket.data.user.id matches. | Eavesdropping on other users |
| GAP-S003 | delivery-code-generated event to request room | T03 | 6-digit code emitted to request room where both buyer and seller are present. Code should only go to seller. | Buyer can intercept own code |
| GAP-S004 | Global payment events | T03, T21 | payment-created, payment-update, payout-created emitted globally. Financial data exposed to all connected sockets. | Data overexposure |
| GAP-S005 | No socket event rate limiting | T12 | No per-event rate limiting on typing, messages, or room joins. | Socket spam; DoS |
| GAP-S006 | No offline status tracking | -- | No userId-to-socketId mapping stored; no offline broadcast on disconnect. | Stale presence data |

---

## Section 5: Implementation Priority

### P0 -- Fix Immediately (Blocks Launch)

These gaps allow unauthenticated or unauthorized access to financial data or fund manipulation. They must be resolved before any public deployment.

| Priority | Gap IDs | Work Required | Threat IDs | Estimated Effort |
|---|---|---|---|---|
| P0-1 | GAP-C001, C002, C003, C004, C005, C006 | Add Bearer JWT auth to all /api/payment/decentralized/* endpoints. Add ownership check (buyer on referenced purchase request, or admin). | T11, T21 | 1-2 days |
| P0-2 | GAP-C007, C013, C014, C015 | Remove or disable test/demo endpoints in production builds. Add NODE_ENV gate that returns 404 in production. | T11 | 0.5 days |
| P0-3 | GAP-C008, C009, C010, C011 | Add Bearer JWT auth to all /api/ai/* endpoints. Add per-user daily token budget. | T08 | 0.5 days |
| P0-4 | GAP-C012 | Remove /api/auth/force-verify-user from production builds or gate behind NODE_ENV + admin role. | T09 | 0.5 hours |
| P0-5 | GAP-C016 | Remove legacy notification router or add authenticateToken to all its routes. Ensure controller router wins for all shared paths. | T21 | 1 day |
| P0-6 | GAP-C019, C020, H009 | Add escrowState=disputed check before release/refund. DisputeService.createDispute must set escrow hold. PaymentCoordinator must enforce it. | T06 | 1 day |
| P0-7 | GAP-C021 | Decode Transfer event in BSCTransactionVerifier. Verify recipient==ESCROW_WALLET, value>=expectedAmount, token contract matches. | T01 | 1 day |
| P0-8 | GAP-C017, S001, S002 | Require JWT in Socket.IO handshake. Server auto-joins user-{decoded.id}. For role rooms, derive from decoded.role. For chat rooms, verify participants. Remove client-driven join-* events. | T03 | 2-3 days |
| P0-9 | GAP-H001 | Enable global rate limiting in app.ts. Configure tiered limits per Section 2. | T12 | 0.5 days |

### P1 -- Fix Before Launch

These gaps involve missing ownership checks, rate limits on authentication paths, and state precondition enforcement. They represent significant security risks but are slightly lower priority than unauthenticated financial access.

| Priority | Gap IDs | Work Required | Threat IDs | Estimated Effort |
|---|---|---|---|---|
| P1-1 | GAP-C018 | Reject PATCH /api/marketplace/offers/:id if offer.status !== 'pending'. Snapshot offer amount at payment creation. | T19 | 0.5 days |
| P1-2 | GAP-H002, H003 | Add Tier 1 rate limiting on /api/auth/register, resend-verification. 5 req/5 min/IP. | T07 | 0.5 days |
| P1-3 | GAP-H004 | Add Tier 1 rate limiting on /api/auth/login. 5 req/5 min/IP. Existing Redis lockout remains. | T12 | 0.5 days |
| P1-4 | GAP-H005 | Add Redis-backed rate limit on delivery code verify. 5 attempts/15 min/request. | T20 | 0.5 days |
| P1-5 | GAP-H006 | Add Tier 2 rate limiting on /api/ai/*. 20 req/15 min/user. | T08 | 0.5 days |
| P1-6 | GAP-H008 | Add Tier 3 rate limiting on /api/chat/:id/messages. 60 req/15 min/user. | T12 | 0.5 days |
| P1-7 | GAP-H010 | Restrict delivery confirmation to status=delivery only. Remove manual fast-track or require admin override. | T20 | 0.5 days |
| P1-8 | GAP-H011 | Add roleGuard('admin') to PUT /api/marketplace/offers/:id/status. | T09 | 0.5 hours |
| P1-9 | GAP-S003 | Emit delivery-code-generated only to seller, not to entire request room. | T03 | 0.5 hours |
| P1-10 | GAP-S004 | Change payment-created, payment-update, payout-created from global emit to targeted room emits (user-{buyerId}, user-{sellerId}). | T03, T21 | 1 day |
| P1-11 | GAP-S005 | Add per-socket rate limiting for high-frequency events (typing, messages). | T12 | 1 day |

### P2 -- Fix Post-Launch

These gaps involve audit logging and presence tracking. They are important for operational security and compliance but do not represent immediate attack vectors.

| Priority | Gap IDs | Work Required | Estimated Effort |
|---|---|---|---|
| P2-1 | GAP-M001, M002, M003, M004, M005 | Implement append-only audit log collection for all admin actions, payment mutations, dispute resolutions. Include actor, target, action, before/after diff, request ID. | 3-5 days |
| P2-2 | GAP-M006, M007, M008 | Add structured audit logging for role changes, user deletions, manual point grants. | 1 day |
| P2-3 | GAP-M009 | Add audit logging for password changes and account deletions. | 0.5 days |
| P2-4 | GAP-M010 | Audit all global emit events; convert to targeted room emits where possible. | 1 day |
| P2-5 | GAP-S006 | Implement userId-to-socketId mapping. Emit user-status-change offline on disconnect. | 0.5 days |
| P2-6 | GAP-H007 | Add rate limiting on /api/payment/decentralized/* once auth is in place. | 0.5 days |

---

## Section 6: Summary Statistics

### REST Endpoint Count

| Route Group | Endpoints |
|---|---|
| Auth | 28 |
| User | 9 |
| User Admin | 13 |
| Admin Approval | 3 |
| Address | 5 |
| Purchase Request | 18 |
| Delivery Code | 4 |
| Seller Offer | 10 |
| Request Template | 11 |
| Shop Settings | 3 |
| Category / Seller Directory | 6 |
| Review | 3 |
| Payment (General) | 18 |
| Payment (SHKeeper Pay-in) | 11 |
| Payment (SHKeeper Release/Refund) | 4 |
| Payment (SHKeeper Payout) | 3 |
| Payment (Decentralized) | 8 |
| Marketplace Payment (Legacy) | 5 |
| Chat | 15 |
| Notification | 9 |
| Dispute | 8 |
| AI | 4 |
| Blog | 10 |
| Points | 8 |
| File | 9 |
| Admin Cleanup | 7 |
| System | 2 |
| **Total REST Endpoints** | **255** |

### Socket.IO Event Count

| Category | Events |
|---|---|
| Connection/Handshake | 2 |
| Room Join/Leave | 9 |
| Chat Events | 2 |
| Presence Events | 1 |
| Server-to-Client | 32 |
| **Total Socket Events** | **46** |

### Gap Summary

| Severity | Count | Gap IDs |
|---|---|---|
| CRITICAL (auth missing) | 17 | GAP-C001 through GAP-C017 |
| CRITICAL (ownership missing) | 4 | GAP-C018 through GAP-C021 |
| HIGH (rate limit missing) | 8 | GAP-H001 through GAP-H008 |
| HIGH (state precondition missing) | 3 | GAP-H009 through GAP-H011 |
| MEDIUM (audit log missing) | 10 | GAP-M001 through GAP-M010 |
| Socket.IO specific | 6 | GAP-S001 through GAP-S006 |
| **Total Gaps** | **48** | |

### Priority Distribution

| Priority | Gap Count | Work Estimate |
|---|---|---|
| P0 (blocks launch) | 9 work items covering 24 gaps | ~8-10 days |
| P1 (before launch) | 11 work items covering 11 gaps | ~5-6 days |
| P2 (post-launch) | 6 work items covering 13 gaps | ~7-8 days |

---

*This document was produced on 2026-05-24 as part of the Amanat authorization audit. It must be updated when: new endpoints are added, existing endpoint access levels change, new Socket.IO events are introduced, or the role model is extended. Implementation tasks should reference specific AUTH-R, USER-R, UADM-R, APV-R, ADDR-R, PR-R, DC-R, OFF-R, TPL-R, SHOP-R, CAT-R, REV-R, PAY-R, SHK-R, REL-R, PO-R, DEC-R, MPAY-R, CHAT-R, NOTIF-R, DIS-R, AI-R, BLOG-R, PTS-R, FILE-R, ADM-R, SYS-R, and SOCK-E IDs from this matrix.*
