# EnCoach Platform -- QA / UAT Assessment Report

**Document Version:** 1.0  
**Date:** March 11, 2026  
**Prepared By:** Architecture & QA Team  
**Audience:** Odoo Developer / Frontend Developer  

**Repositories Assessed:**

- Frontend: `https://git.albousalh.com/devops/encoach_frontend_new_v3.git`
- Backend: `https://git.albousalh.com/devops/encoach_backend_new_v3.git`

**Assessed Against:**

- `ENCOACH_USER_STORIES.md` v2.0 (83 atomic user stories)
- `ENCOACH_WORKFLOWS_FRONTEND_SRS.md` v1.1
- `ENCOACH_WORKFLOWS_BACKEND_SRS.md` v1.1
- `encoach_workflows_v3.pdf` v3.0

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [Assessment Scope and Methodology](#2-assessment-scope-and-methodology)
3. [P0 -- Blocker Issues (Must Fix Immediately)](#3-p0----blocker-issues)
4. [P1 -- High Severity Issues (Must Fix Before UAT)](#4-p1----high-severity-issues)
5. [P2 -- Medium Severity Issues (Should Fix Before Production)](#5-p2----medium-severity-issues)
6. [P3 -- Low Severity / Observations](#6-p3----low-severity--observations)
7. [User Story Coverage Matrix](#7-user-story-coverage-matrix)
8. [Overall Statistics](#8-overall-statistics)
9. [Appendix A -- API Contract Mismatches (Full Detail)](#9-appendix-a----api-contract-mismatches)
10. [Appendix B -- Stub / Placeholder Inventory](#10-appendix-b----stub--placeholder-inventory)

---

## 1. Executive Summary

A thorough code-level audit was performed on both the frontend (React 18 / Vite / TypeScript) and backend (Odoo 19 custom addons) repositories. The codebase was traced line-by-line against all 83 user stories, the frontend and backend SRS documents, and the original workflow specification.

**Key findings:**

- **53 out of 83** user stories (63.9%) are fully implemented and functional end-to-end.
- **11 stories** (13.3%) are partially implemented with minor gaps or caveats.
- **19 stories** (22.9%) are blocked or broken due to API mismatches, missing endpoints, or stub implementations.
- **8 API path mismatches** exist between the frontend service layer and backend controllers. These will cause **runtime 404 errors** and must be resolved before any integration testing.
- **3 backend endpoints** required by the frontend do not exist at all.
- **8 frontend features** are currently stub/placeholder implementations (no real functionality).
- **Zero automated tests** exist in either repository.
- **No deployment configuration** (Docker, requirements.txt) exists in the backend repository.

The platform cannot proceed to UAT until the P0 (blocker) items in Section 3 are resolved.

---

## 2. Assessment Scope and Methodology

### What Was Examined

| Layer | Files Examined | Approach |
|-------|---------------|----------|
| Frontend Routes | `App.tsx` -- 124 route definitions | Every `<Route>` path traced to its component |
| Frontend Services | 54 service files in `src/services/` | Every API endpoint URL and HTTP method extracted |
| Frontend Pages | 130 page components across `admin/`, `student/`, `teacher/`, root | Read source code for critical pages |
| Frontend Types | 40+ type definition files in `src/types/` | Cross-referenced with SRS type inventory |
| Backend Controllers | 24 controller files across all custom modules | Every `@http.route` decorator extracted (approx. 150 endpoints) |
| Backend Models | All `models/*.py` files across 24 modules | Field definitions and business logic reviewed |
| Backend Services | AI services, PDF generator, CSV parser, credential service | Implementation depth assessed (real logic vs stub) |
| Backend Security | 22 `ir.model.access.csv` files, 1 security XML | Access rules reviewed |

### What Was NOT Examined

- Runtime behavior on the staging server (no live testing performed)
- OpenEduCat community/enterprise module internals
- Third-party API integrations (OpenAI, AWS Polly, ELAI) -- only checked that service code exists
- Database content / seed data correctness

---

## 3. P0 -- Blocker Issues

These issues will cause immediate failures. The platform **cannot be tested** until they are resolved.

### BUG-001: Frontend-Backend API Path Mismatches (8 paths)

The frontend service layer calls endpoint URLs that do not match the routes registered in the backend controllers. Every one of these will produce a **404 Not Found** at runtime.

| # | Frontend Path (from service) | Backend Path (from controller) | Service File | Controller File |
|---|------------------------------|-------------------------------|--------------|-----------------|
| 1 | `/api/entity/students/csv/validate` | `/api/entity/students/validate-csv` | `entity-onboarding.service.ts` | `entity_onboard.py` |
| 2 | `/api/entity/students/:id/resend-credential` | `/api/entity/students/:id/resend-credentials` | `entity-onboarding.service.ts` | `entity_onboard.py` |
| 3 | `/api/entity/students/resend-credentials/pending` | `/api/entity/students/resend-all-pending` | `entity-onboarding.service.ts` | `entity_onboard.py` |
| 4 | `/api/adaptive-engine/dashboard` | `/api/adaptive/dashboard` | `adaptive-engine.service.ts` | `adaptive.py` |
| 5 | `/api/adaptive-engine/students/:id/signals` | `/api/adaptive/student/:id/signals` | `adaptive-engine.service.ts` | `adaptive.py` |
| 6 | `/api/adaptive-engine/settings` | `/api/adaptive/settings` | `adaptive-engine.service.ts` | `adaptive.py` |
| 7 | `/api/reset/sendVerification` | **(does not exist)** | `auth.service.ts` | -- |
| 8 | `/api/auth/invite/set-password` | **(does not exist)** | `auth.service.ts` | -- |

**Action required:** Align paths. Either update the frontend service files to match the backend routes, or update the backend routes to match the frontend. Both sides must agree on a single path.

### BUG-002: Send Credentials Payload Key Mismatch

- **Frontend** (`entity-onboarding.service.ts`): sends `{ student_ids: number[] }`
- **Backend** (`entity_onboard.py`): expects `user_ids` in the JSON body

The backend will receive an empty or null `user_ids` list, resulting in no credentials being sent.

**Action required:** Align the JSON key name on both sides.

### BUG-003: OTP Email Not Delivered

- **File:** `encoach_signup/controllers/auth.py`
- **Issue:** When a user registers and an OTP is generated, the OTP code is only written to `_logger.info()` (Python log). There is no `mail.mail` record created, no SMTP call, and no email template invoked.
- **Impact:** Users who register cannot receive their verification code. The entire signup flow (US-SL-01, US-SL-02) is **blocked** for real users.

**Action required:** Implement email delivery for OTP codes using Odoo's `mail.mail` or `mail.template` mechanism.

### BUG-004: Duplicate Route Registration

- **Routes:** `/api/placement/speaking-upload` and `/api/placement/speaking-status`
- **Registered in:** Both `encoach_placement/controllers/placement.py` (`auth='none'` + `@jwt_required`) AND `encoach_ai/controllers/media_controller.py` (`auth='user'`)
- **Impact:** Odoo will load only one implementation based on module install order. The active endpoint may use the wrong authentication mode, causing either 401 or 403 errors.

**Action required:** Remove the duplicate registration from one of the two modules.

### BUG-005: Missing Backend Endpoint -- Exam Status

- **Frontend calls:** `GET /api/exam/:examId/status` (in `exam-session.service.ts`)
- **Backend:** This endpoint does not exist in any controller.
- **Impact:** The `ExamStatus.tsx` page will always fail to load.

**Action required:** Implement the endpoint in the exam session controller, or remove the frontend page if not needed.

---

## 4. P1 -- High Severity Issues

These issues represent broken or non-functional features that must be fixed before UAT can begin.

### BUG-006: Exam Results Page Uses Mock Data

- **File:** `src/pages/student/ExamResults.tsx`
- **Issue:** The page renders static/hardcoded mock data instead of calling `GET /api/exam/:examId/results`.
- **Impact:** Students never see their real exam scores. Affects **US-SL-21, US-SL-22, US-SL-23, US-ES-04, US-ES-06**.

### BUG-007: PDF Download Button Not Wired

- **File:** `src/pages/student/ExamResults.tsx`
- **Issue:** A "Download PDF Report" button is rendered but has **no `onClick` handler**. The `reportService.downloadPdf()` function exists in `report.service.ts` but is never imported or called anywhere in the codebase.
- **Impact:** Students and entity students cannot download their score reports. Affects **US-SL-32, US-ES-08**.

### BUG-008: PDF Report Skill Column Bug

- **File:** `encoach_pdf_report/services/pdf_generator.py`
- **Issue:** The code uses `getattr(score, 'skill_name', '')` and `getattr(score, 'name', ...)`, but the `encoach.score` model defines the field as `skill` (not `skill_name` or `name`). The skill column in generated PDFs will display "N/A" for all rows.
- **Impact:** PDF reports are generated but contain incorrect data.

### BUG-009: CAPTCHA Widget Not Integrated

- **File:** `src/pages/Register.tsx`
- **Issue:** The registration page displays a dashed placeholder box labeled "Verification widget placeholder" and submits a hardcoded `captcha_token: "demo-placeholder"`. No reCAPTCHA, hCaptcha, or Turnstile SDK is loaded. The backend **does** implement CAPTCHA validation and exposes `GET /api/config/captcha` for the provider/site-key, but the frontend never calls it.
- **Impact:** Registration is unprotected against bots. Affects **US-SL-01**.

### BUG-010: Speaking Recording Not Implemented (Both Placement and Exam)

- **Placement** (`src/pages/student/PlacementTest.tsx`): Shows "Recording will be available in a future update" with a disabled button.
- **Exam** (`src/pages/student/ExamSession.tsx`): Shows "Recording interface will appear here."
- **Impact:** Speaking skill assessment is completely non-functional. Affects **US-SL-11, US-SL-19, US-AD-27**.

### BUG-011: Listening Audio Playback Not Implemented

- **File:** `src/pages/student/ExamSession.tsx`
- **Issue:** The listening section displays a fake progress bar and a static timestamp `0:00 / 3:42`. No actual audio element or playback controls exist.
- **Impact:** Listening skill assessment is non-functional. Affects **US-SL-16**.

### BUG-012: Custom Exam Question Pool Uses Fake IDs

- **File:** `src/pages/admin/CustomExamCreate.tsx`
- **Issue:** Step 3 ("Assign Questions") uses `Math.random()` to generate question IDs instead of querying the real content pool API. The "Browse content pool" action navigates away from the wizard.
- **Impact:** Custom exams cannot have real questions assigned. Affects **US-AD-22**.

### BUG-013: No Subscription/Trial Endpoint

- **Frontend calls:** `POST /api/subscription/trial` (in `placement.service.ts`)
- **Backend:** No `/api/subscription` route or payment/billing logic exists anywhere in the backend codebase.
- **Impact:** The payment/access flow after placement results is non-functional. Affects **US-SL-14**.

### BUG-014: Missing Dependency Declaration in `encoach_branding`

- **File:** `encoach_branding/__manifest__.py`
- **Issue:** The module imports JWT helpers from `encoach_api.controllers.base` but does not declare `encoach_api` in its `depends` list. If `encoach_api` is not installed, `encoach_branding` will crash on import.
- **Impact:** Module may fail to load depending on installation order.

### BUG-015: Speaking Transcription Status Always Returns "completed"

- **File:** `encoach_placement/controllers/placement.py`
- **Issue:** The `speaking-status` endpoint always returns `{ status: "completed", transcription: null }` regardless of whether transcription has actually occurred. No Whisper pipeline is wired in the placement controller.
- **Impact:** Speaking placement scores are never actually computed from audio. Affects **US-SL-11**.

### BUG-016: Undeclared Python Dependencies

The following Python packages are imported and used in backend code but are **not declared** in any module's `__manifest__.py` `external_dependencies`:

| Package | Used In | Purpose |
|---------|---------|---------|
| `PyJWT` (as `jwt`) | `encoach_api`, `encoach_exam_session` | JWT token handling |
| `openai` | `encoach_ai/services/openai_service.py` | AI completions |
| `boto3` | `encoach_ai/services/polly_service.py` | AWS Polly TTS |
| `requests` | `encoach_signup/services/captcha_service.py` | CAPTCHA verification |

Additionally, there is **no** `requirements.txt`, `pyproject.toml`, or `setup.py` in the backend repository. A fresh deployment will fail if these packages are not pre-installed.

---

## 5. P2 -- Medium Severity Issues

### BUG-017: No React Error Boundary

No Error Boundary component exists in the frontend. An unhandled JavaScript error in any component will crash the entire application with a white screen. An `ErrorBoundary` should wrap the main `<App>` tree.

### BUG-018: XSS Risk in AI Workbench

- **File:** `src/pages/teacher/AiWorkbench.tsx`
- **Issue:** `generatedContent.content` is rendered via `dangerouslySetInnerHTML` without any sanitization (e.g., DOMPurify). If the AI returns content containing `<script>` tags or event handlers, it will execute in the user's browser.
- **Recommendation:** Use a sanitization library such as `dompurify` before rendering.

### BUG-019: Inconsistent Error Handling Across Pages

Some pages properly handle API error states (e.g., `ExamSession.tsx`, `ScoreVerification.tsx`), while others destructure `isError` from React Query hooks but never display an error message to the user (e.g., `IeltsSkillConfig.tsx`). Users may see empty or broken pages without understanding why.

### BUG-020: Score Approval "View Details" Button Not Wired

- **File:** `src/pages/admin/ScoreApprovalQueue.tsx`
- **Issue:** The "View Details" button has no `onClick` handler. Approve and Reject work correctly.

### BUG-021: Imperative DOM Access in GenerationPage

- **File:** `src/pages/GenerationPage.tsx`
- **Issue:** Uses `document.getElementById()` to read input values instead of React controlled components or refs. This is fragile and can break during concurrent rendering.

### BUG-022: IRT Theta Estimation is Simplified

- **File:** `encoach_placement/controllers/placement.py`
- **Issue:** The SRS specifies MLE (Maximum Likelihood Estimation) for theta updates. The implementation uses a simplified learning-rate heuristic: `theta += LEARNING_RATE * (correct - p)` with clipping. This is functional but less accurate than proper IRT estimation, especially at boundary conditions.

### BUG-023: Adaptive Dashboard `avg_progress` Hardcoded

- **File:** `encoach_adaptive/controllers/adaptive.py`
- **Issue:** The `avg_progress` field in the dashboard response is hardcoded to `0.0` instead of being computed from actual student data.

### BUG-024: Rubric Sub-Scores Not Used in Band Calculation

- **File:** `encoach_scoring/controllers/grading.py`
- **Issue:** The `_recompute_bands` function averages `ans.score` per skill. Rubric sub-scores (stored in `encoach.feedback.rubric_scores` as JSON) are not factored into the band calculation. The SRS specifies rubric-based band derivation.

### BUG-025: No Deployment Configuration in Backend Repo

The backend repository contains no `docker-compose.yml`, `Dockerfile`, `odoo.conf`, or deployment scripts. This makes reproducible deployments difficult.

### BUG-026: No Migration Scripts

No `migrations/` folders exist in any backend module. Database schema changes during upgrades will need manual intervention. For production stability, Odoo migration scripts should be created for any model changes between versions.

---

## 6. P3 -- Low Severity / Observations

### OBS-001: No Automated Tests

- **Frontend:** Only `src/test/example.test.ts` exists (a boilerplate placeholder). Vitest is configured but no actual tests cover any component, service, or hook.
- **Backend:** No `tests/` packages, no `TransactionCase`, `HttpCase`, or any test classes exist in any module.

### OBS-002: No Internationalization (i18n)

The frontend has no i18n framework installed. All UI strings are hardcoded in English. If Arabic or other language support is required for UTAS, this will need to be addressed.

### OBS-003: Two Separate Adaptive Services in Frontend

The frontend has both `adaptive.service.ts` (diagnostics, proficiency, learning plans, topics) and `adaptive-engine.service.ts` (dashboard, students, signals, settings). This split is intentional but may cause confusion. The engine service has the path mismatch documented in BUG-001.

### OBS-004: Token Expiry Handling

The frontend does not decode JWTs or check `exp` client-side. Expired tokens are only detected when an API call returns 401, at which point the token is cleared and the user is redirected to login. This is functional but means users may see a brief error before being redirected.

### OBS-005: `report.service.ts` Uses Direct `fetch`

Unlike all other services that use the centralized `api` client from `api-client.ts`, `report.service.ts` calls `fetch()` directly with a hardcoded `/api` prefix. This bypasses any future interceptor or middleware logic added to the API client.

### OBS-006: No `.env.production` Template

Only `.env.example` and `.env.development` exist. A `.env.production` template documenting required production environment variables would help deployment.

---

## 7. User Story Coverage Matrix

### Section 1: Self-Learning Student Journey (US-SL-01 to US-SL-32)

| ID | Title | Verdict | Blocking Bug |
|----|-------|---------|--------------|
| US-SL-01 | Register a New Account | PARTIAL | BUG-009 (CAPTCHA stub) |
| US-SL-02 | Verify Email Address | BLOCKED | BUG-003 (OTP not emailed) |
| US-SL-03 | Select Learning Goal | PASS | -- |
| US-SL-04 | Set Target Level and Timeline | PASS | -- |
| US-SL-05 | Set Study Preferences | PASS | -- |
| US-SL-06 | Choose Placement Test Decision | PASS | -- |
| US-SL-07 | View Placement Test Briefing | PASS | -- |
| US-SL-08 | Take Placement -- Grammar | PASS | -- |
| US-SL-09 | Take Placement -- Vocabulary | PASS | -- |
| US-SL-10 | Take Placement -- Reading | PASS | -- |
| US-SL-11 | Take Placement -- Speaking | FAIL | BUG-010, BUG-015 |
| US-SL-12 | View Placement Results | PASS | -- |
| US-SL-13 | View Learning Path Preview | PASS | -- |
| US-SL-14 | Choose Payment or Access Option | FAIL | BUG-013 (no subscription endpoint) |
| US-SL-15 | Start Exam Session | PASS | -- |
| US-SL-16 | Answer Listening Questions | FAIL | BUG-011 (audio stub) |
| US-SL-17 | Answer Reading Questions | PASS | -- |
| US-SL-18 | Complete Writing Tasks | PASS | -- |
| US-SL-19 | Record Speaking Responses | FAIL | BUG-010 (recording stub) |
| US-SL-20 | Review and Submit Exam | PASS | -- |
| US-SL-21 | View Exam Results (Auto) | FAIL | BUG-006 (mock data) |
| US-SL-22 | Post-Exam Routing (Pass) | PARTIAL | Depends on BUG-006 |
| US-SL-23 | Post-Exam Routing (Below) | PARTIAL | Depends on BUG-006 |
| US-SL-24 | View Gap Analysis | PASS | -- |
| US-SL-25 | Start Auto-Generated Course | PASS | -- |
| US-SL-26 | Start AI English Course | PASS | -- |
| US-SL-27 | Start AI IELTS Course | PASS | -- |
| US-SL-28 | Progress Through Modules | PASS | -- |
| US-SL-29 | View In-Platform Resources | PASS | -- |
| US-SL-30 | Complete Checkpoint Exercises | PASS | -- |
| US-SL-31 | Take Post-Course Assessment | PASS | -- |
| US-SL-32 | Download PDF Report with QR | FAIL | BUG-007, BUG-008 |

**Result: 21 PASS / 5 FAIL / 3 PARTIAL / 3 BLOCKED-by-dependency = 65.6% pass rate**

### Section 2: Entity Student Journey (US-ES-01 to US-ES-08)

| ID | Title | Verdict | Blocking Bug |
|----|-------|---------|--------------|
| US-ES-01 | Receive Credentials and First Login | PARTIAL | BUG-001 (#7, #8) |
| US-ES-02 | Set New Password on First Login | FAIL | BUG-001 (#8, invite set-password missing) |
| US-ES-03 | Take Mandatory Placement Test | PASS | -- |
| US-ES-04 | View Placement Results (Pending) | PARTIAL | BUG-006 |
| US-ES-05 | Take Exam Assigned by Institution | PASS | -- |
| US-ES-06 | View Exam Results (After Approval) | FAIL | BUG-006 |
| US-ES-07 | Take Teacher-Configured Course | PASS | -- |
| US-ES-08 | Download Entity-Branded PDF | FAIL | BUG-007, BUG-008 |

**Result: 3 PASS / 3 FAIL / 2 PARTIAL = 37.5% pass rate**

### Section 3: Admin / Teacher Journey (US-AD-01 to US-AD-42) + Public (US-PV-01)

| ID | Title | Verdict | Blocking Bug |
|----|-------|---------|--------------|
| US-AD-01 | Upload Student CSV | FAIL | BUG-001 (#1, path mismatch) |
| US-AD-02 | Review CSV Validation Report | FAIL | Depends on US-AD-01 |
| US-AD-03 | Create Bulk Student Accounts | PASS | -- |
| US-AD-04 | Send Credential Emails | FAIL | BUG-002 (payload mismatch) |
| US-AD-05 | Monitor Credential Delivery | FAIL | BUG-001 (#2, #3, path mismatches) |
| US-AD-06 | Configure Level Mapping | PASS | -- |
| US-AD-07 | Configure White-Label Branding | PASS | -- |
| US-AD-08 | Select Exam Template Path | PASS | -- |
| US-AD-09 | Initialise IELTS Exam | PASS | -- |
| US-AD-10 | Configure Listening Skill | PASS | -- |
| US-AD-11 | Configure Reading Skill | PASS | -- |
| US-AD-12 | Configure Writing Skill | PASS | -- |
| US-AD-13 | Configure Speaking Skill | PASS | -- |
| US-AD-14 | Auto-Assemble Questions | PASS | -- |
| US-AD-15 | Manually Assemble Questions | PASS | -- |
| US-AD-16 | Hybrid-Assemble Questions | PASS | -- |
| US-AD-17 | Validate Exam | PASS | -- |
| US-AD-18 | Publish Exam | PASS | -- |
| US-AD-19 | Assign Exam to Students | PASS | -- |
| US-AD-20 | Custom Exam -- Properties | PASS | -- |
| US-AD-21 | Custom Exam -- Sections | PASS | -- |
| US-AD-22 | Custom Exam -- Questions | PARTIAL | BUG-012 (fake question IDs) |
| US-AD-23 | Custom Exam -- Validate/Publish | PASS | -- |
| US-AD-24 | Save as Reusable Template | PASS | -- |
| US-AD-25 | Create from Saved Template | PASS | -- |
| US-AD-26 | Grade Writing Submission | PASS | Minor: BUG-024 |
| US-AD-27 | Grade Speaking Submission | PARTIAL | BUG-010 (audio stub) |
| US-AD-28 | View Student Gap Analysis | PASS | -- |
| US-AD-29 | Configure Course Structure | PASS | -- |
| US-AD-30 | Build Course Modules | PASS | -- |
| US-AD-31 | Attach Resources to Modules | PASS | -- |
| US-AD-32 | Generate AI Content | PASS | -- |
| US-AD-33 | Publish and Assign Course | PASS | -- |
| US-AD-34 | Monitor Student Progress | PASS | -- |
| US-AD-35 | English Quality Gate | PASS | -- |
| US-AD-36 | IELTS Automated Check | PASS | -- |
| US-AD-37 | IELTS Examiner Review | PASS | -- |
| US-AD-38 | Approve Exam Results | PASS | Minor: BUG-020 |
| US-AD-39 | Reject Exam Results | PASS | Minor: BUG-020 |
| US-AD-40 | Adaptive Dashboard | PARTIAL | BUG-023 (avg_progress=0) |
| US-AD-41 | Adaptive Thresholds | FAIL | BUG-001 (#4, #6, path mismatch) |
| US-AD-42 | Student Signals/Decisions | FAIL | BUG-001 (#5, path mismatch) |
| US-PV-01 | Verify Score via QR Code | PASS | -- |

**Result: 29 PASS / 7 FAIL / 4 PARTIAL / 3 with minor notes = 67.4% pass rate**

---

## 8. Overall Statistics

| Metric | Value |
|--------|-------|
| **Total User Stories Assessed** | 83 |
| **Full PASS** | 53 (63.9%) |
| **PARTIAL** (works with caveats) | 11 (13.3%) |
| **FAIL** (blocked or broken) | 19 (22.9%) |
| | |
| **P0 Blocker Bugs** | 5 |
| **P1 High Severity Bugs** | 11 |
| **P2 Medium Severity Bugs** | 10 |
| **P3 Observations** | 6 |
| **Total Issues** | 32 |
| | |
| **API Path Mismatches** | 8 |
| **Missing Backend Endpoints** | 3 |
| **Stub/Placeholder Features** | 8 |
| **Security Concerns** | 3 |
| **Automated Tests** | 0 (1 placeholder file) |

---

## 9. Appendix A -- API Contract Mismatches (Full Detail)

### A.1 Entity Onboarding Paths

```
FRONTEND                                          BACKEND
--------                                          -------
/api/entity/students/csv/validate          !=     /api/entity/students/validate-csv
/api/entity/students/:id/resend-credential !=     /api/entity/students/:id/resend-credentials
/api/entity/students/resend-credentials/pending != /api/entity/students/resend-all-pending
```

**Source files:**
- Frontend: `src/services/entity-onboarding.service.ts`
- Backend: `custom_addons/encoach_entity_onboard/controllers/entity_onboard.py`

### A.2 Adaptive Engine Paths

```
FRONTEND                                          BACKEND
--------                                          -------
/api/adaptive-engine/dashboard             !=     /api/adaptive/dashboard
/api/adaptive-engine/students              !=     /api/adaptive/students
/api/adaptive-engine/students/:id/signals  !=     /api/adaptive/student/:id/signals
/api/adaptive-engine/students/:id/ability  !=     /api/adaptive/student/:id/ability
/api/adaptive-engine/settings              !=     /api/adaptive/settings
```

Note the additional **singular vs plural** mismatch: frontend uses `students/:id`, backend uses `student/:id`.

**Source files:**
- Frontend: `src/services/adaptive-engine.service.ts`
- Backend: `custom_addons/encoach_adaptive/controllers/adaptive.py`

### A.3 Missing Backend Endpoints

| Frontend Path | Called From | Backend Status |
|---------------|------------|----------------|
| `/api/reset/sendVerification` | `auth.service.ts` | Does not exist |
| `/api/auth/invite/set-password` | `auth.service.ts` | Does not exist |
| `/api/exam/:examId/status` | `exam-session.service.ts` | Does not exist |
| `/api/subscription/trial` | `placement.service.ts` | Does not exist |

### A.4 Payload Shape Mismatch

| Endpoint | Frontend Sends | Backend Expects |
|----------|---------------|-----------------|
| `/api/entity/students/send-credentials` | `{ student_ids: number[] }` | `{ user_ids: [...] }` |

---

## 10. Appendix B -- Stub / Placeholder Inventory

These features have UI elements rendered in the frontend but no real functionality behind them.

| Feature | Location | What Exists | What's Missing |
|---------|----------|-------------|----------------|
| CAPTCHA widget | `Register.tsx` | Dashed placeholder box | Real reCAPTCHA/hCaptcha/Turnstile SDK integration |
| Speaking recording (placement) | `PlacementTest.tsx` | Disabled button, text message | MediaRecorder API, audio upload |
| Speaking recording (exam) | `ExamSession.tsx` | Placeholder text | MediaRecorder API, audio upload |
| Listening playback (exam) | `ExamSession.tsx` | Fake progress bar, `0:00 / 3:42` | HTML5 audio element, real playback controls |
| Exam results data | `ExamResults.tsx` | Static mock data rendering | API integration with `/api/exam/:examId/results` |
| PDF download | `ExamResults.tsx` | Button with no handler | Import and call `reportService.downloadPdf()` |
| Custom exam questions | `CustomExamCreate.tsx` | `Math.random()` IDs | Content pool API query and real question selection |
| View Details (scores) | `ScoreApprovalQueue.tsx` | Button with no handler | Navigation or modal to attempt details |

---

*End of Report*
