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

125 lines
4.0 KiB
Markdown

# 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`:
```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.
### Recommended Direction
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.