docs: sync from backend 957c356 — H16-H18 transaction closeout
This commit is contained in:
@@ -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
|
### 2026-06-07 — backend@259f3fb, frontend@d9a59bd — DB audit H19-H21 auth save consolidation
|
||||||
|
|
||||||
**Commits:** `259f3fb` `d9a59bd`
|
**Commits:** `259f3fb` `d9a59bd`
|
||||||
|
|||||||
@@ -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 |
|
| 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 |
|
| 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 |
|
| 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`
|
> **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.
|
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`
|
> **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.
|
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`
|
> **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.
|
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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user