# ANTIGRAVITY BUG REGISTER

| ID | Severity | Module | Finding | Root Cause | Evidence | Impact | Recommendation | Status |
|----|----------|--------|---------|------------|----------|--------|----------------|--------|
| BUG-001 | P1 (Critical) | Appointments / Core | Cross-tenant data leakage in public appointment status endpoint | BranchScope aborts when BranchContext is null (unauthenticated). Public endpoints do not set a default branch context, bypassing the global scope entirely. | app/Support/Branch/BranchScope.php, PublicBookingService::status() | An attacker can brute-force the short reference string on the public booking API to read appointment times and doctors from ANY clinic. | Explicitly set BranchContext for public requests, or throw an exception in BranchScope if context is null instead of silently ignoring it. | FIXED |
| BUG-002 | P2 (High) | Documents/Security | Host Header Injection in PDF QR Codes | The verificationUrl() method uses Laravel's route() helper which relies on the HTTP Host header. An attacker can spoof the Host header to point the QR code to an external malicious domain. | app/Models/IssuedDocument.php, IssuedDocument::verificationUrl() | A pharmacist scanning the QR code could be directed to a fake verification page controlled by the attacker, completely defeating the document authenticity mechanism. | Enforce APP_URL or configure trusted proxies strictly, or generate absolute URLs using a known tenant domain configuration instead of the request Host header. | FIXED |
| BUG-003 | P3 (Medium) | Auditing | Race condition in print counters | PrescriptionService::recordPrint and LabOrderService::recordPrint use non-atomic $model->print_count + 1 increments. Concurrent requests will cause lost updates, allowing users to print multiple copies while only incrementing the counter by 1. | app/Modules/Prescriptions/Services/PrescriptionService.php, app/Modules/Laboratory/Services/LabOrderService.php | Clinicians or cashiers can bypass print limits/audits by firing concurrent requests to the print record endpoint. | Use Eloquent's increment('print_count') method which translates to an atomic SQL UPDATE ... SET print_count = print_count + 1 query. | FIXED |
| BUG-004 | P3 (Medium) | Database | Soft Deletes Break Unique Constraints | The users table has a simple UNIQUE (email) constraint. The patients table has a UNIQUE (branch_id, mrn) constraint. Both tables use SoftDeletes. If a record is soft-deleted, its unique values cannot be reused, causing database Integrity constraint violation errors when creating new records with those values. | database/migrations/0001_01_01_000000_create_users_table.php, database/migrations/2026_02_01_000001_create_patients_table.php | Administrators cannot recreate a user account using the email address of a deleted user. | Include deleted_at in the unique constraints (e.g., UNIQUE (email, deleted_at)) or use a conditional unique index if supported by the database engine. | FIXED |
| BUG-005 | P4 (Low) | Database | Concurrency Deadlocks in Pharmacy Dispensing | DispensingService iterates through a prescription's drugs in the order they were prescribed. If two transactions dispense different multi-drug prescriptions for the same drugs but in a different sequence, they can deadlock waiting for each other's locks on MedicineBatch. | app/Modules/Pharmacy/Support/FefoAllocator.php, app/Modules/Pharmacy/Services/DispensingService.php | A rare race condition where two simultaneous dispenses cause a database deadlock, resulting in a 500 error for one cashier. No data corruption occurs. | Sort the DispenseLineData array by drugId before processing to ensure a deterministic locking order across all transactions. | FIXED |
