fix(subscriptions): atomic UsageRecord metering to prevent quota bypass

- Add @@unique([subscriptionId, metric, periodStart, periodEnd]) constraint
  to UsageRecord model with corresponding migration
- Replace racy findFirst+update/create pattern with Prisma upsert using
  INSERT ON CONFLICT DO UPDATE SET count = count + delta
- Fix CheckQuotaHandler to use period-scoped findUnique instead of
  unscoped findFirst, preventing stale cross-period reads
- Update tests to reflect atomic upsert pattern

Closes GOO-4

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-22 23:22:59 +07:00
parent 65bd641e1f
commit ee6d6d4c17
16 changed files with 180 additions and 79 deletions

View File

@@ -0,0 +1,2 @@
-- CreateIndex
CREATE UNIQUE INDEX "UsageRecord_subscriptionId_metric_periodStart_periodEnd_key" ON "UsageRecord"("subscriptionId", "metric", "periodStart", "periodEnd");

View File

@@ -0,0 +1,7 @@
-- AlterEnum
-- Add ROOM_RENTAL, CONDOTEL, and SERVICED_APARTMENT to the PropertyType enum.
-- These new values support phòng trọ (room rentals), condotels, and serviced apartment listings.
ALTER TYPE "PropertyType" ADD VALUE 'ROOM_RENTAL';
ALTER TYPE "PropertyType" ADD VALUE 'CONDOTEL';
ALTER TYPE "PropertyType" ADD VALUE 'SERVICED_APARTMENT';