From dd45528f58d612ea6e6a443a8aca32fd5d138313 Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Sun, 7 Jun 2026 10:22:56 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20sync=20from=20backend=20957c356=20?= =?UTF-8?q?=E2=80=94=20H16-H18=20transaction=20closeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 09 - Audits/Activity Log.md | 10 ++++++++++ .../DB Query & Schema Audit - 2026-06-06.md | 15 +++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/09 - Audits/Activity Log.md b/09 - Audits/Activity Log.md index cc11958..324af9a 100644 --- a/09 - Audits/Activity Log.md +++ b/09 - Audits/Activity Log.md @@ -12,6 +12,16 @@ entries on top. Maintained by agents per the rule in `../AGENTS.md`. --- +### 2026-06-07 — backend@957c356, frontend@f699b15 — DB audit very-high transaction closeout H16-H18 + +**Commits:** `957c356` `f699b15` +**Touched:** backend `src/services/marketplace/RequestTemplateService.ts`, `src/db/repositories/drizzle/DrizzleMarketplaceRepo.ts`, `src/db/repositories/interfaces/IMarketplaceRepo.ts`, `src/services/auth/authController.ts`, `src/services/auth/authStore.ts`, `__tests__/request-template-batch-convert-cache.test.ts`, `__tests__/auth-store-pg-query.test.ts`, `__tests__/db-audit-auth-controller-saves.test.ts`, `package.json`, `package-lock.json`; frontend `Dockerfile`, `package.json`; docs `09 - Audits/DB Query & Schema Audit - 2026-06-06.md`, `09 - Audits/Activity Log.md` +**Why:** Close High H16-H18 from the DB Query & Schema Audit. Proposal-backed batch template conversions now create the request, offer, accepted-offer state, and selected-offer link in one serializable vital-db transaction while leaving template usage accounting explicitly non-vital. Template payment completion uses one serializable bulk status update with an all-rows-updated guard. Email-code registration now deletes the temp verification, increments referrer signup count, and persists the verified user plus refresh token in one serializable auth-store transaction. +**Verification:** backend `npm test -- --runTestsByPath __tests__/request-template-batch-convert-cache.test.ts __tests__/db-audit-money-flow-transactions.test.ts __tests__/db-audit-auth-controller-saves.test.ts __tests__/auth-store-pg-query.test.ts --runInBand` (4 suites / 31 tests), `npm run typecheck`, `scripts/smoke/db-audit-service-regressions.sh` (19 suites / 82 tests), backend/frontend scoped `git diff --check`; frontend/backend version metadata confirmed at v2.9.38. Pushed to Forgejo. +**Linked docs updated:** [[09 - Audits/DB Query & Schema Audit - 2026-06-06]] + +--- + ### 2026-06-07 — backend@259f3fb, frontend@d9a59bd — DB audit H19-H21 auth save consolidation **Commits:** `259f3fb` `d9a59bd` diff --git a/09 - Audits/DB Query & Schema Audit - 2026-06-06.md b/09 - Audits/DB Query & Schema Audit - 2026-06-06.md index 9fa44f9..f66881a 100644 --- a/09 - Audits/DB Query & Schema Audit - 2026-06-06.md +++ b/09 - Audits/DB Query & Schema Audit - 2026-06-06.md @@ -87,6 +87,9 @@ updated: 2026-06-07 | C2/M26: `DrizzleChatRepo.findRows` unbounded chat fetch + JS pagination → bounded row scans, SQL pagination for SQL-pushable predicates, `findOne` `LIMIT 1`/id fast path, type pushdown, and archived-chat index | `8835068` v2.9.35 | | H10: `sweepDerivedDestinations` sequential token-balance RPC probes → bounded parallel balance probe phase before sequential sweep/broadcast handling | `5d7d2af` v2.9.36 | | H19-H21: login, Google sign-in, and Telegram auth duplicate user saves → token helper save bypass plus one final user persistence after audited mutations | `259f3fb` v2.9.37 | +| H16: batch template conversion request/offer/status writes split across service calls → proposal conversions use one serializable vital transaction; template usage remains explicitly non-vital | `957c356` v2.9.38 | +| H17: template payment completion per-request status loop → one serializable bulk status update with an all-rows-updated guard | `957c356` v2.9.38 | +| H18: email-code registration split referrer/user/temp writes → one serializable auth-store registration transaction, with referral bonus left post-commit best-effort | `957c356` v2.9.38 | --- @@ -336,33 +339,33 @@ The AML fee ledger entry (lines 441-471) is written after `db.transaction()` com --- -### 16. batchConvertTemplates creates purchase-requests, offers, and status updates without a transaction +### 16. batchConvertTemplates creates purchase-requests, offers, and status updates without a transaction | **FIXED** `957c356` v2.9.38 > **Category:** Missing Transaction | **File:** `src/services/marketplace/RequestTemplateService.ts:521-598` The per-item loop calls `createPurchaseRequest`, `createTemplateOffer`, `updateOfferStatus`, `updatePurchaseRequest`, `incrementUsageCount`, and `findPurchaseRequestById` as separate non-transactional operations. A crash after `createPurchaseRequest` but before `incrementUsageCount` leaves an orphaned request with the usage counter un-bumped; a crash after `createTemplateOffer` but before `updatePurchaseRequest` leaves the offer unlinked from the request. -**Fix:** Wrap each item's write sequence in a Drizzle `db.transaction()`. At minimum wrap `(createPurchaseRequest + createTemplateOffer + updatePurchaseRequest.selectedOfferId + incrementUsageCount)` for each item. +**Fix:** Implemented in `957c356`: proposal-backed batch conversions now route through `createTemplatePurchaseRequest`, creating the purchase request, template offer, accepted offer state, and selected-offer link inside one serializable vital-db transaction. Template usage accounting remains in the intentionally non-vital `request_templates` store and stays explicit outside the vital money transaction. --- -### 17. completeTemplateRequestsPayment updates multiple purchase-request rows without a transaction +### 17. completeTemplateRequestsPayment updates multiple purchase-request rows without a transaction | **FIXED** `957c356` v2.9.38 > **Category:** Missing Transaction | **File:** `src/services/marketplace/RequestTemplateService.ts:634-641` The method reads all requests with `Promise.all` (line 622) and then updates them one-by-one in a `for` loop (lines 634-639) with no surrounding transaction. A crash mid-loop leaves some requests updated and others not, creating inconsistent payment state across cart items. -**Fix:** Wrap the entire update sequence in a single database transaction, or issue a single `UPDATE … WHERE id = ANY($1)` bulk statement. +**Fix:** Implemented in `957c356`: validated template payment requests are updated through `updatePurchaseRequestStatuses`, a single serializable bulk `UPDATE` over the resolved request ids. The service now fails the completion path if the bulk update returns fewer rows than the validated request set. --- -### 18. verifyEmailWithCode: user save, referrer stat update, and temp-verification delete are not transactional +### 18. verifyEmailWithCode: user save, referrer stat update, and temp-verification delete are not transactional | **FIXED** `957c356` v2.9.38 > **Category:** Missing Transaction | **File:** `src/services/auth/authController.ts:756-868` Registration completes in separate writes: (1) `referrer.save()` increments referralStats, (2) `user.save()` creates the account, (3) `TempVerification.findByIdAndDelete` removes the pending record — all independent. A crash between any two leaves the email address stuck in `temp_verification` (user cannot re-register) or the referrer's count incremented without the user existing. -**Fix:** Wrap steps 1-3 in a single Postgres transaction. Perform the token-generation and second `user.save()` inside the same transaction before responding. +**Fix:** Implemented in `957c356`: `verifyEmailWithCode` stages refresh-token issuance, then `completeEmailVerificationRegistration` deletes the temp verification, atomically increments referrer signup count, persists the verified user and refresh token, and commits in one serializable auth-store transaction. Referral signup bonus points remain post-commit best-effort. ---