docs: DB query & schema audit 2026-06-06 — 104 findings, 3 fixes landed (v2.9.13)

Full multi-agent audit of all Drizzle repos, service layer, and schema
files. 104 findings across critical/high/medium/low. Three fixes already
committed to backend in 2484150. Top open items: auth 1+3N rowToUser,
chat table-scan, GIN indexes, missing-transaction on money paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-06-06 19:41:01 +04:00
parent 79dab07243
commit 32e1acc5ef
2 changed files with 1147 additions and 0 deletions

View File

@@ -11,6 +11,57 @@ entries on top. Maintained by agents per the rule in `../AGENTS.md`.
---
## 2026-06-06 — DB Query & Schema Audit + Performance Fixes (v2.9.13)
**Commits:** backend `2484150`
**Audit:** Full multi-agent DB audit (9 agents, 104 findings) across all Drizzle repos, service layer, and schema files. Full report: [[DB Query & Schema Audit - 2026-06-06]].
**Fixes landed (v2.9.13):**
- Stats endpoint: 11 serial queries → 1 `GROUP BY status` (`countPurchaseRequestsByStatus`)
- Offer filter loop: per-offer `sameUser()` N×2 DB calls → resolve seller once, filter in memory
- Seller notification fan-out: in-JS `watchedCategories` filter + 100-row hard cap → SQL JSONB filter, no limit (silent miss for sellers >100 fixed)
**Top open findings from audit (prioritised for next sprint):**
- CRITICAL: `rowToUser` fires 1+3N queries on every auth path (`authStore.ts:345`)
- CRITICAL: `DrizzleChatRepo.findRows` loads entire chats table into memory (`DrizzleChatRepo.ts:544`)
- CRITICAL: `chats.participants` JSONB has no GIN index
- CRITICAL: `findAllPayments` 1+2N queries, unbounded
- CRITICAL: `notifications.user_id` is `text` not `uuid` — no FK
- CRITICAL: `disputes` FK columns are `text` — no referential integrity
- CRITICAL: `savePgUser` writes users/tokens/passkeys without a transaction
- HIGH (×8): Missing transactions on money paths (delivery code TOCTOU, double-accept race, referral reward, RN webhook, dispute create/resolve)
---
## 2026-06-06 — Full MongoDB Removal Complete
**Backend version:** 2.9.12
**Scope:** backend runtime (all src/ files except seeds/scripts/backfill)
### What changed
- **MongoDB and Mongoose fully removed from the backend runtime.** No `from 'mongoose'` or `require('mongoose')` imports remain in any runtime source file.
- `src/models/` directory removed. `src/infrastructure/database/` (Mongoose connection) removed. `mongodb-memory-server` dev dependency removed.
- All 11 repository domains now use `DrizzleXxxRepo` exclusively. Dual-write wrappers decommissioned.
- `PaymentProvider` type and `payment_provider` pgEnum extended with `'escrow'` value.
- `PaymentBlockchain` interface extended: `blockNumber?`, `gasUsed?`, `isSimulated?`.
- `ChatService.ts`: Mongoose document methods (`.addMessage()`, `.markAsRead()`, `.pull()`) replaced with plain TypeScript array operations.
- `services/marketplace/routes.ts` (3300+ lines): All `PurchaseRequest`, `SellerOffer`, `Payment` Mongoose model calls replaced with repository pattern calls via `getMarketplaceRepo()` and `getPaymentRepo()`.
- `toIdString()` fixed to always return `string` (was `string | undefined`).
- `notificationBackfill.ts` deleted (Mongo source no longer exists).
- TypeScript compilation: **0 errors** on full `tsc --noEmit`.
### Key invariants established
- `deliveryDate` and delivery fields are nested inside `deliveryInfo`; use `updatePurchaseRequestDeliveryInfo()`.
- `PaymentDTO.amount` is a decimal string (not `{amount, currency}` object).
- User `_id` is legacy ObjectId kept as `legacy_object_id`; marketplace FKs use `user.pgId` (UUID).
- `PurchaseRequest` has no top-level `paymentId` field.
- `UpdateSellerOfferInput` and `UpdatePaymentInput` have no `updatedAt` field.
---
### 2026-06-06 — backend@ca2b1c4, frontend@aac3304 — Marketplace E2E notification smoke runner
**Commits:** `ca2b1c4` `aac3304`

File diff suppressed because it is too large Load Diff