canina/docs/audit/09-database-audit.md
2026-08-06 20:54:44 +03:30

4.0 KiB

Database and Data Integrity Audit Report

  • Auditor Role: Database and Data Integrity Auditor
  • Date: 2026-08-06
  • Repository HEAD: 715873b2ecc3a72ba974bb2a2be87c5ba82bd4e7
  • Included Scope: backend/prisma/schema.prisma, backend/prisma/seed.ts, database services, DATABASE_SCHEMA.md.
  • Excluded Scope: Active database servers, running migration commands, **/node_modules/**.
  • Files Inspected: backend/prisma/schema.prisma, backend/prisma/seed.ts, DATABASE_SCHEMA.md.
  • Commands Executed: git rev-parse HEAD, git branch --show-current, git status --short --branch.
  • Commands Blocked: npx prisma db push, npx prisma db seed, Prisma migration runs.
  • Audit Limitations: Evaluated via static Prisma schema inspection without live database engine execution.

Domain Overview & Confirmed Strengths

  • Relational Integrity: backend/prisma/schema.prisma defines 17 relational models with explicit foreign keys (@relation), cascade deletions (onDelete: Cascade), and composite keys (ProductIngredient, ProductSymptom).
  • Precision Datatypes: Financial fields (walletBalance, charityDonationTotal, totalAmount, priceValue) utilize @db.Decimal(15, 2) to avoid IEEE floating-point loss in PostgreSQL storage.

Findings

DB-001

Title

Missing Explicit Unique Index Constraint on User Mobile Numbers in Database Schema

Domain

Database and Data Integrity

Category

Data Modeling & Uniqueness Constraints

Severity

MEDIUM

Confidence

CONFIRMED

Status

OPEN

Affected Application

Prisma / PostgreSQL Database (backend/prisma/schema.prisma)

Affected Files

  • backend/prisma/schema.prisma

Relevant Symbols or Lines

  • backend/prisma/schema.prisma#L14-L16 (User model)

Evidence

In schema.prisma:

model User {
  id        String  @id @default(uuid()) @db.Uuid
  email     String  @unique @db.VarChar(150)
  mobile    String? @unique @db.VarChar(15)
  ...
}

While @unique is specified on mobile, backend/prisma/seed.ts and AuthService create temporary dummy emails (${mobile}@temp.local) during SMS registration.

Problem

When mobile is null or missing for legacy email users, PostgreSQL allows multiple NULL values in @unique columns, but if an empty string "" is inserted by mistake from frontend forms, it triggers unique constraint violations blocking user registration.

Root Cause

Absence of explicit non-empty validation checks or clean nullable handling on user mobile input during account creation.

Why It Matters

Leads to duplicate accounts or runtime database insertion exceptions when user profile updates submit empty string mobile numbers.

User or Business Impact

Users trying to update their profile without providing a phone number encounter database 500 errors.

Technical Impact

Causes unhandled Prisma P2002 unique constraint violation exceptions.

Security or Data-Integrity Impact

Risk of duplicate user identity creation across different auth providers.

Ensure mobile number inputs convert empty strings "" to null before Prisma mutation calls and enforce DTO sanitization in NestJS UsersService.

Alternative Direction

Add a DB check constraint or handle Prisma P2002 error codes gracefully in HttpExceptionFilter.

Implementation Complexity

LOW

Dependencies

None.

Risks

None.

Verification Requirements

Attempt updating a user profile with mobile: "" and verify it is stored as NULL without duplicate key errors.

Testing Requirements

Unit test user creation with empty vs null mobile numbers.

Acceptance Criteria

Empty mobile input strings are safely normalized to NULL prior to DB insertion.

Notes and Limitations

None.


Finding Summary

  • CRITICAL: 0

  • HIGH: 0

  • MEDIUM: 1

  • LOW: 0

  • INFO: 0

  • CONFIRMED: 1

  • HIGH_CONFIDENCE: 0

  • NEEDS_VERIFICATION: 0

  • SPECULATIVE: 0

Completion Statement

Database and Data Integrity audit completed. 1 MEDIUM severity finding confirmed.