# TOPIQ Referral Engine Implementation Report (Phase 3)

**Execution Date**: 2026-10-09  
**Technology Stack**: Node.js v25.9.0 | Express.js 5.2.1 | MySQL 9.7.1 (`mysql2/promise`) | Jest | Supertest  
**Status**: Completed and Fully Verified  

---

## 1. Executive Summary

This report documents the design, implementation, and verification of the **Referral Engine (Phase 3)** for the TOPIQ backend. 

The referral engine establishes a traceable, cryptographically secure attribution mechanism that enforces the strict TOPIQ hierarchy:
* **ASM** refers and onboards **Coordinators** (`coordinator_profiles` with `asm_id = asm.id`).
* **Coordinator** refers and onboards **Students** (`student_profiles` with matching `coordinator_id` and `asm_id`).
* **Student** can refer peers without crossing or violating organizational boundaries.

All operations are transaction-safe, preventing partial records, duplicate attributions, and self-referrals.

---

## 2. Audit Findings

Prior to Phase 3, an audit of the repository (`docs/referral-audit.md`) established:
1. **Database Schema Readiness**:
   - `referral_codes` was created in `migrations/001_baseline.sql` with unique code constraints and usage counters.
   - `referral_events` was created in `migrations/002_add_referral_events_classes_audit.sql` with a critical `UNIQUE(referred_user_id)` constraint guaranteeing that each referred user can only have one primary attribution.
   - `student_profiles` has composite foreign key constraint `fk_student_coordinator_asm (coordinator_id, asm_id)` enforced in `migrations/003_enforce_hierarchy_composite_fk.sql`.
2. **Application Layer Gaps**:
   - No referral routes, controllers, or services existed in `src/`.
   - `AuthService.register()` did not accept or validate `referralCode`.
   - No code generation utilities existed with collision handling.

---

## 3. Confirmed Business Rules

1. **Role Derivation on Referral**:
   - When a user registers using an **ASM's referral code**, the referred user is onboarded as a **COORDINATOR** and assigned to that ASM in `coordinator_profiles`.
   - When a user registers using a **Coordinator's referral code**, the referred user is onboarded as a **STUDENT** and assigned to that Coordinator and the same ASM in `student_profiles`.
   - When no referral code is supplied, public registration strictly defaults to **STUDENT**. Privileged role self-assignment (`ADMIN`, `ASM`, `COORDINATOR`) remains forbidden.
2. **Code Generation & Normalization**:
   - Cryptographically secure random tokens generated using `crypto.randomBytes` with unambiguous characters (`CHARS = '23456789ABCDEFGHJKMNPQRSTUVWXYZ'`).
   - Standard format: `TPQ-<ROLE_PREFIX>-<6_CHARS>` (e.g., `TPQ-ASM-A7X9K2`, `TPQ-CRD-M3P8R1`, `TPQ-STU-4D9W1L`).
   - Normalization converts input to uppercase and trims whitespace.
   - Collision retry loop handles database unique constraint collisions up to 5 times.
3. **Transaction Safety & Atomicity**:
   - Account creation, role assignment, hierarchy profile creation, referral attribution event insertion, and `use_count` increment execute within a single MySQL transaction (`connection.beginTransaction()`).
   - If any step fails (such as duplicate phone/email or invalid code), the entire transaction rolls back cleanly.
4. **Self-Referral & Duplicate Prevention**:
   - Users cannot redeem their own referral code.
   - Matching contact details (mobile or email) between referrer and registering applicant triggers immediate rejection (`SELF_REFERRAL_PROHIBITED`).
   - Database constraint `UNIQUE(referred_user_id)` on `referral_events` permanently prevents duplicate primary referral attributions.
5. **No Financial or Commission Logic**:
   - No commission, cashback, points, or monetary payouts have been implemented in accordance with strict scope boundaries.

---

## 4. Files Created and Modified

| File | Status | Description |
|---|---|---|
| `docs/referral-audit.md` | Created | Comprehensive audit of existing schema, constraints, and missing capabilities. |
| `src/shared/utils/referralCode.js` | Created | Cryptographically secure referral code generator and string normalizer. |
| `src/modules/referral/referral.service.js` | Created | Business logic for referral code creation, validation, transactional attribution, summaries, and paginated scoped lists. |
| `src/modules/referral/referral.validation.js` | Created | Joi validation schemas for code validation and paginated queries. |
| `src/modules/referral/referral.controller.js` | Created | Request handlers for `/my-code`, `/validate`, `/summary`, and `/list`. |
| `src/modules/referral/referral.routes.js` | Created | Express router mounting all referral endpoints with authentication and validation middleware. |
| `src/middleware/validate.js` | Modified | Added safe query validation support without breaking Express 5 property getter restrictions. |
| `src/app.js` | Modified | Mounted `/api/v1/referrals` route prefix. |
| `src/modules/auth/auth.validation.js` | Modified | Added optional `referralCode` field to `registerSchema`. |
| `src/modules/auth/auth.service.js` | Modified | Integrated transactional referral code validation and attribution in `AuthService.register()`. |
| `tests/referral.test.js` | Created | Automated test suite verifying all 12 referral criteria. |
| `docs/referral-implementation-report.md` | Created | Complete implementation report. |

---

## 5. Database Schema & Tables Utilized

No new migrations or schema changes were required. The engine utilizes existing tables:

1. **`referral_codes`**:
   - `id`: Primary key
   - `code`: `VARCHAR(50) UNIQUE`
   - `owner_user_id`: Foreign key to `users.id`
   - `purpose`: `VARCHAR(50)` (`COORDINATOR_ONBOARDING`, `STUDENT_ONBOARDING`, `STUDENT_REFERRAL`)
   - `status`: `ENUM('ACTIVE', 'EXPIRED', 'REVOKED')`
   - `use_count`: Number of redemptions
2. **`referral_events`**:
   - `id`: Primary key
   - `referral_code_id`: Foreign key to `referral_codes.id`
   - `referrer_user_id`: Foreign key to `users.id`
   - `referred_user_id`: Foreign key to `users.id`, `UNIQUE`
   - `attribution_type`: `VARCHAR(50)` (`HIERARCHY_ONBOARDING`, `PEER_REFERRAL`)
3. **`coordinator_profiles`**:
   - `user_id`, `asm_id`, `area_id`
   - `UNIQUE KEY uq_coordinator_asm (user_id, asm_id)`
4. **`student_profiles`**:
   - `user_id`, `coordinator_id`, `asm_id`, `registration_status`
   - `CONSTRAINT fk_student_coordinator_asm FOREIGN KEY (coordinator_id, asm_id) REFERENCES coordinator_profiles (user_id, asm_id)`

---

## 6. API Endpoint Contracts

Base Path: `/api/v1/referrals`

### 1. `GET /api/v1/referrals/my-code`
* **Authentication**: Required (`Bearer <token>`)
* **Role**: Any active user (`ASM`, `COORDINATOR`, `STUDENT`)
* **Description**: Returns the active referral code for the user, or creates one if none exists.
* **Response (200 OK)**:
  ```json
  {
    "success": true,
    "data": {
      "id": 12,
      "code": "TPQ-ASM-K8P92R",
      "purpose": "COORDINATOR_ONBOARDING",
      "status": "ACTIVE",
      "expiresAt": null,
      "maxUses": null,
      "useCount": 0,
      "createdAt": "2026-10-09T13:15:00.000Z"
    }
  }
  ```

### 2. `POST /api/v1/referrals/validate`
* **Authentication**: Public (no token required)
* **Request Body**:
  ```json
  {
    "referralCode": "TPQ-ASM-K8P92R"
  }
  ```
* **Response (200 OK)**:
  ```json
  {
    "success": true,
    "data": {
      "valid": true,
      "code": "TPQ-ASM-K8P92R",
      "purpose": "COORDINATOR_ONBOARDING",
      "referrer": {
        "fullName": "Jane Doe",
        "role": "ASM",
        "areaId": 4
      }
    }
  }
  ```
* **Error Responses**:
  - `400 VALIDATION_ERROR`: Code missing or malformed.
  - `404 INVALID_REFERRAL_CODE`: Referral code does not exist.
  - `400 INACTIVE_REFERRAL_CODE`: Code revoked or deactivated.
  - `400 EXPIRED_REFERRAL_CODE`: Code passed its expiration date.
  - `400 USAGE_LIMIT_EXCEEDED`: Code usage cap reached.

### 3. `GET /api/v1/referrals/summary`
* **Authentication**: Required (`Bearer <token>`)
* **Description**: Returns referral attribution counts scoped to caller's role.
* **Response (200 OK for ASM)**:
  ```json
  {
    "success": true,
    "data": {
      "role": "ASM",
      "directCoordinatorsReferred": 5,
      "totalHierarchyStudents": 42
    }
  }
  ```
* **Response (200 OK for Coordinator)**:
  ```json
  {
    "success": true,
    "data": {
      "role": "COORDINATOR",
      "directStudentsReferred": 18,
      "totalAssignedStudents": 18
    }
  }
  ```

### 4. `GET /api/v1/referrals/list`
* **Authentication**: Required (`Bearer <token>`)
* **Query Parameters**:
  - `page`: Integer (default: 1)
  - `limit`: Integer (default: 20, max: 100)
* **Scoping & Authorization**:
  - **ASM**: Can view only coordinators and students belonging to their ASM tree.
  - **Coordinator**: Can view only students assigned under their coordinator profile.
  - **Student**: Can view only direct peer referrals they originated.
* **Response (200 OK)**:
  ```json
  {
    "success": true,
    "data": {
      "items": [
        {
          "id": 45,
          "fullName": "John Smith",
          "role": "COORDINATOR",
          "status": "ACTIVE",
          "referralCode": "TPQ-ASM-K8P92R",
          "referredAt": "2026-10-09T13:20:00.000Z"
        }
      ],
      "pagination": {
        "page": 1,
        "limit": 20,
        "total": 1,
        "totalPages": 1
      }
    }
  }
  ```

---

## 7. Registration Integration (`POST /api/v1/auth/register`)

The registration endpoint now accepts an optional `referralCode`:
```json
{
  "fullName": "Alex Mercer",
  "mobile": "9876543211",
  "email": "alex@example.com",
  "password": "Password123!",
  "referralCode": "TPQ-ASM-K8P92R"
}
```
* If the code belongs to an **ASM**, the newly created user is automatically assigned role `COORDINATOR` and a `coordinator_profiles` record is created linking to that ASM.
* If the code belongs to a **Coordinator**, the user is assigned role `STUDENT` and a `student_profiles` record is created linking to that Coordinator and their ASM.
* Referral event is atomically logged in `referral_events`.
* Returns `201 Created` with referral attribution metadata.

---

## 8. Test Execution Results

All automated test suites were executed on the test database:

```
Test Suites: 4 passed, 4 total
Tests:       34 passed, 34 total
Snapshots:   0 total
Time:        1.813 s
```

### Breakdown by Test Suite:

1. **`tests/referral.test.js`** (12 criteria tested, 100% Passed):
   - `1. Generates and retrieves referral code for an eligible user`: **PASSED**
   - `2. Enforces database uniqueness on referral codes and retries on collision`: **PASSED**
   - `3. Rejects unknown referral codes with 404 INVALID_REFERRAL_CODE`: **PASSED**
   - `4. Rejects self-referrals when registering using own details`: **PASSED**
   - `5. Prevents duplicate referral attribution for the same referred user`: **PASSED**
   - `6. Builds and validates consistent ASM -> Coordinator -> Student hierarchy`: **PASSED**
   - `7. Prohibits cross-ASM visibility in referral listings`: **PASSED**
   - `8. Rejects unauthenticated requests with 401 UNAUTHORIZED`: **PASSED**
   - `9. Rolls back user and referral attribution if registration fails`: **PASSED**
   - `10. Creates referral_events and protects against duplicate DB inserts`: **PASSED**
   - `11. Returns paginated referral list with proper metadata and sanitation`: **PASSED**
   - `Returns accurate referral summary counts by role`: **PASSED**

2. **`tests/auth.test.js`** (16 tests, 100% Passed): **PASSED**
3. **`tests/hierarchy-and-class-integrity.test.js`** (4 tests, 100% Passed): **PASSED**
4. **`tests/database-integrity.test.js`** (2 tests, 100% Passed): **PASSED**

---

## 9. Known Limitations & Out-of-Scope Items

* **Monetary / Commission Rewards**: In accordance with project instructions, no cashback, points, or commissions are calculated or credited.
* **Notification Dispatch**: No SMS, WhatsApp, or email notifications are triggered on referral redemption (deferred to notification phase).
* **Direct UI Views**: No mobile frontend or administrative dashboard views were altered in this backend phase.

---

## 10. Conclusion

Phase 3 is complete, validated by automated integration tests, and ready for review.
