chore(ci,docs): GitHub Actions, ADRs, README overhaul, §21 Hardening Release
- .github/workflows/ci.yml: two jobs — frontend (tsc --noEmit, lint, build, Playwright) and backend (Postgres 16 + odoo:19 --test-enable --test-tags encoach_api) — catches regressions before merge. - docs/adr/: start an Architecture Decision Record trail with 0001 canonical directory layout, 0002 JWT refresh flow, 0003 paginated response envelope, 0004 RAG metadata + chunking. - docs/PROJECT_SUMMARY.md §21 Hardening Release: full recap of the AI quality loop, compliance, Paymob, i18n, and CI work shipped in this drop, plus new DB tables, REST routes, frontend routes, verification results, and operator-facing configuration. - README.md refreshed for the v4 split-repo doctrine and the new feature surface. - new_project/DEPRECATED.md: formal retirement notice pointing at backend/ as the canonical tree. Made-with: Cursor
This commit is contained in:
267
README.md
267
README.md
@@ -1,123 +1,190 @@
|
||||
# EnCoach Backend v2 — Odoo 19 Adaptive Learning Platform
|
||||
# EnCoach — Adaptive AI Learning Platform
|
||||
|
||||
The Odoo 19 backend for the **EnCoach** adaptive learning and institutional LMS platform. Provides ~377 REST API endpoints serving a React 18 SPA frontend.
|
||||
EnCoach is a smart learning environment for individual and collaborative learning,
|
||||
fully integrated with AI and equipped with intelligent, professional-grade
|
||||
exercises, assessments, and e-exams.
|
||||
|
||||
## System Overview
|
||||
This repository hosts the full stack:
|
||||
|
||||
| Component | Detail |
|
||||
|-----------|--------|
|
||||
| **Framework** | Odoo 19 Community Edition |
|
||||
| **Language** | Python 3.12+ |
|
||||
| **Database** | PostgreSQL 16 |
|
||||
| **LMS Foundation** | OpenEduCat Community (14 modules, ported to v19) |
|
||||
| **Custom Modules** | 27 `encoach_*` modules |
|
||||
| **AI/ML** | OpenAI GPT-4o, Whisper (local), AWS Polly, ELAI, GPTZero, FAISS |
|
||||
| **Authentication** | JWT (PyJWT) |
|
||||
| **Deployment** | Docker Compose |
|
||||
- **Backend** — Odoo 19 + ~30 `encoach_*` modules (Python 3.12, PostgreSQL 16)
|
||||
- **Frontend** — React 18 + Vite + TypeScript single-page app
|
||||
- **AI layer** — OpenAI + pgvector RAG, quality-gate validation, IELTS validator
|
||||
- **Ops** — Docker Compose, JWT auth with refresh tokens, Prometheus-compatible
|
||||
metrics, dynamic OpenAPI 3.0 spec
|
||||
|
||||
## Module Architecture
|
||||
> **Canonical trees:** `backend/` (all server code) and `frontend/` (all client
|
||||
> code). The legacy `new_project/` directory is deprecated — see
|
||||
> [`new_project/DEPRECATED.md`](new_project/DEPRECATED.md).
|
||||
|
||||
```
|
||||
new_project/
|
||||
custom_addons/ # 27 custom EnCoach modules
|
||||
encoach_api/ # REST API controllers (~120 routes)
|
||||
encoach_lms_api/ # OpenEduCat bridge API (~209 routes)
|
||||
encoach_adaptive_api/ # Adaptive learning API (~41 routes)
|
||||
encoach_resources/ # Resource library API (~7 routes)
|
||||
encoach_core/ # Users, entities, roles, permissions
|
||||
encoach_taxonomy/ # Subject > Domain > Topic taxonomy
|
||||
encoach_adaptive/ # Proficiency, learning plans, mastery
|
||||
encoach_adaptive_ai/ # AI for diagnostics, coaching, content
|
||||
encoach_exam/ # AI-powered exam engine
|
||||
encoach_ai/ # OpenAI service wrapper
|
||||
encoach_ai_generation/ # AI exam content generation
|
||||
encoach_ai_grading/ # AI grading (writing, speaking, math, IT)
|
||||
encoach_ai_media/ # TTS (Polly), STT (Whisper), ELAI avatars
|
||||
encoach_courseware/ # Chapters, materials, AI workbench
|
||||
encoach_communication/ # Discussion boards, announcements, messaging
|
||||
encoach_notification/ # Notification engine, rules, preferences
|
||||
encoach_faq/ # FAQ categories and items
|
||||
encoach_approval/ # Approval workflows, stages
|
||||
encoach_assignment/ # Exam-wrapper assignments
|
||||
encoach_classroom/ # Virtual classroom groups
|
||||
encoach_stats/ # Session tracking, statistics
|
||||
encoach_training/ # Training tips, walkthroughs, FAISS
|
||||
encoach_subscription/ # Packages, Stripe/PayPal/Paymob
|
||||
encoach_registration/ # User registration, batch import
|
||||
encoach_ticket/ # Support tickets
|
||||
encoach_sis/ # UTAS SIS integration
|
||||
encoach_branding/ # Whitelabeling
|
||||
openeducat_erp-19.0/ # 14 OpenEduCat community modules
|
||||
openeducat_core/ # Courses, batches, students, faculty
|
||||
openeducat_timetable/ # Timetable sessions
|
||||
openeducat_attendance/ # Attendance management
|
||||
openeducat_exam/ # Institutional exams, marksheets
|
||||
openeducat_assignment/ # Course assignments, submissions
|
||||
openeducat_admission/ # Admission registers, applications
|
||||
openeducat_classroom/ # Physical classrooms
|
||||
openeducat_facility/ # Facilities and assets
|
||||
openeducat_fees/ # Fee plans, student fees
|
||||
openeducat_library/ # Library media, movements, cards
|
||||
openeducat_activity/ # Student activities
|
||||
openeducat_parent/ # Parent-student relationships
|
||||
openeducat_erp/ # ERP connector
|
||||
theme_web_openeducat/ # Web theme
|
||||
```
|
||||
---
|
||||
|
||||
## Staging
|
||||
## 1. Quickstart
|
||||
|
||||
| Service | URL |
|
||||
|---------|-----|
|
||||
| **Odoo Backend** | `http://5.189.151.117:8069` |
|
||||
| **React Frontend** | `http://5.189.151.117:3000` |
|
||||
|
||||
## Branching Workflow
|
||||
|
||||
This repo is connected to the staging server via a Git post-receive hook.
|
||||
**All deployment is automatic after code review approval.**
|
||||
|
||||
1. Never push directly to `main` -- branch protection will block it.
|
||||
2. Push your changes to a feature branch (e.g. `feature/full-backend-v1`).
|
||||
3. Open a Pull Request on Gitea targeting `main`.
|
||||
4. Request review from **devops (Talal)**.
|
||||
5. Once approved and merged, the staging server rebuilds and redeploys automatically.
|
||||
|
||||
The `.env` file is **not committed**. It lives only on the staging server at `/opt/encoach/backend-v2/.env`.
|
||||
|
||||
## Local Development
|
||||
|
||||
### Option A: Docker (easiest)
|
||||
### Docker (recommended)
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
# Odoo: http://localhost:8069
|
||||
# Frontend: cd frontend && npm install && npm run dev (http://localhost:8080)
|
||||
```
|
||||
|
||||
Open `http://localhost:8069`. First run: create a new database.
|
||||
Create a new Odoo database on first visit, then install the `encoach_api`
|
||||
module to pull in every `encoach_*` dependency.
|
||||
|
||||
Stop: `docker compose down`
|
||||
### Source
|
||||
|
||||
### Option B: Source (venv + PostgreSQL)
|
||||
|
||||
**Prerequisites:** macOS, Homebrew, Python 3.11+, PostgreSQL 15+
|
||||
Prerequisites: Python 3.12, PostgreSQL 16, Node 20, npm 10.
|
||||
|
||||
```bash
|
||||
brew install postgresql@15 wkhtmltopdf
|
||||
brew services start postgresql@15
|
||||
createuser -s $(whoami)
|
||||
# Backend
|
||||
./setup.sh # creates venv, installs requirements.txt
|
||||
./run.sh # starts Odoo on :8069
|
||||
|
||||
chmod +x setup.sh
|
||||
./setup.sh
|
||||
./run.sh
|
||||
# Frontend
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev # starts Vite on :8080, proxies /api → :8069
|
||||
```
|
||||
|
||||
Open `http://localhost:8069`.
|
||||
See [`MANUAL-RUN.md`](MANUAL-RUN.md) for a step-by-step walkthrough and
|
||||
[`CONNECT-POSTGRES.md`](CONNECT-POSTGRES.md) for database wiring.
|
||||
|
||||
See [MANUAL-RUN.md](MANUAL-RUN.md) for step-by-step commands.
|
||||
---
|
||||
|
||||
## Related Documents
|
||||
## 2. Repository layout
|
||||
|
||||
```
|
||||
odoo19/
|
||||
├── backend/
|
||||
│ └── custom_addons/
|
||||
│ ├── encoach_api/ REST base + JWT + OpenAPI + metrics
|
||||
│ ├── encoach_core/ Users, entities, roles, permissions
|
||||
│ ├── encoach_taxonomy/ Subject → Domain → Topic
|
||||
│ ├── encoach_ai/ OpenAI wrapper, cefr_mapper, validator
|
||||
│ ├── encoach_ai_course/ AI course/exam generation pipelines
|
||||
│ ├── encoach_ai_grading/ AI grading (writing/speaking/math/IT)
|
||||
│ ├── encoach_ai_media/ TTS (Polly), STT (Whisper), ELAI
|
||||
│ ├── encoach_vector/ pgvector store + RAG embeddings
|
||||
│ ├── encoach_exam_template/ Canonical exam + student attempt models
|
||||
│ ├── encoach_scoring/ Score computation, CEFR mapping
|
||||
│ ├── encoach_quality_gate/ Automated content-quality checks
|
||||
│ ├── encoach_ielts_validation/ IELTS-specific validators
|
||||
│ ├── encoach_adaptive/ Adaptive engine, style matcher
|
||||
│ ├── encoach_lms_api/ OpenEduCat bridge + LMS endpoints
|
||||
│ ├── encoach_branding/ White-label config per entity
|
||||
│ └── … (other encoach_* modules)
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── pages/ Route pages (React.lazy code-split)
|
||||
│ │ ├── components/ Shared UI (shadcn/ui + custom)
|
||||
│ │ ├── services/ Thin API wrappers over fetch
|
||||
│ │ ├── hooks/queries/ React Query hooks + keys
|
||||
│ │ ├── lib/api-client.ts Fetch + auto JWT refresh
|
||||
│ │ └── types/ Shared DTO types
|
||||
│ └── vite.config.ts manualChunks: react, query, charts, radix…
|
||||
├── docs/
|
||||
│ ├── PROJECT_SUMMARY.md Release notes & architecture history
|
||||
│ ├── adr/ Architecture Decision Records
|
||||
│ └── ENCOACH_*.md SRS, workflows, user stories
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── requirements.txt Python deps (pgvector, textstat, etc.)
|
||||
└── README.md You are here
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Architecture at a glance
|
||||
|
||||
```
|
||||
┌────────────────────┐ HTTPS/JWT ┌────────────────────┐
|
||||
│ React SPA (Vite) │ ───────────────► │ Odoo 19 + FastAPI-style │
|
||||
│ - React Query │ ◄─────────────── │ controllers (encoach_*) │
|
||||
│ - next-themes │ X-Request-Id └──────┬─────────────┘
|
||||
│ - shadcn/ui │ │
|
||||
└────────────────────┘ ▼
|
||||
┌──────────────┐
|
||||
│ PostgreSQL │
|
||||
│ + pgvector │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ OpenAI, │
|
||||
│ Whisper, │
|
||||
│ Polly… │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
Every request carries an `X-Request-Id` and emits structured JSON logs.
|
||||
Prometheus-compatible counters are exposed at `/api/metrics`, and the live
|
||||
OpenAPI 3.0 spec is at `/api/openapi.json`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Key conventions
|
||||
|
||||
- **Canonical response envelope** — list endpoints return
|
||||
`{ items: T[], total, page, size, data: T[] }` (see `encoach_api.controllers.base.paginated_envelope`).
|
||||
- **CEFR mapping** — only `encoach_ai.services.cefr_mapper` is canonical. Do
|
||||
not reintroduce local `band_to_cefr` copies.
|
||||
- **JWT tokens** — short-lived access tokens (1h) + revocable refresh tokens
|
||||
(7d). Only `access` tokens are accepted as Bearer credentials; refresh tokens
|
||||
must go through `/api/auth/refresh`. See [`docs/adr/0002-jwt-refresh-token-flow.md`](docs/adr/0002-jwt-refresh-token-flow.md).
|
||||
- **RAG metadata** — vector embeddings carry `course_id`, `subject_id`,
|
||||
`entity_id`, `taxonomy`, `content_hash`. Chunking kicks in above 2 000 chars.
|
||||
- **Frontend pagination** — `PaginatedResponse<T>` exposes both `items` and
|
||||
`data`. Read from `items` in new code.
|
||||
- **Frontend theming** — tokens live in `frontend/src/index.css` (`:root` and
|
||||
`.dark`). Always use `hsl(var(--token))` instead of raw hex.
|
||||
|
||||
---
|
||||
|
||||
## 5. Health, observability, docs
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|---|---|
|
||||
| `GET /api/health` | Liveness (always 200 when server is up) |
|
||||
| `GET /api/health/ready` | Readiness (DB + required config) |
|
||||
| `GET /api/openapi.json` | Dynamic OpenAPI 3.0 spec generated from `@http.route` |
|
||||
| `GET /api/metrics` | Prometheus-format counters per route |
|
||||
|
||||
---
|
||||
|
||||
## 6. Deployment
|
||||
|
||||
Staging and production both use Docker Compose. The staging server rebuilds
|
||||
automatically from `main`; never force-push. See
|
||||
[`INSTALL-ODOO-SUMMARY.md`](INSTALL-ODOO-SUMMARY.md) for bootstrap notes.
|
||||
|
||||
| Service | Staging URL |
|
||||
|---|---|
|
||||
| Odoo backend | `http://5.189.151.117:8069` |
|
||||
| React frontend | `http://5.189.151.117:3000` |
|
||||
|
||||
The `.env` file is **never** committed. On staging it lives at
|
||||
`/opt/encoach/backend-v2/.env`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Further reading
|
||||
|
||||
| Document | Description |
|
||||
|----------|-------------|
|
||||
| `ENCOACH_ODOO19_BACKEND_SRS.md` | Backend SRS v3.0 (definitive) |
|
||||
| `ENCOACH_UNIFIED_SRS.md` | Unified frontend + backend SRS v2.0 |
|
||||
| `ENCOACH_PRODUCT_DESCRIPTION.md` | Non-technical product description |
|
||||
|---|---|
|
||||
| [`docs/PROJECT_SUMMARY.md`](docs/PROJECT_SUMMARY.md) | Release notes + architecture history |
|
||||
| [`docs/adr/`](docs/adr/) | Architecture Decision Records (why we built it this way) |
|
||||
| [`docs/ENCOACH_UNIFIED_SRS.md`](docs/ENCOACH_UNIFIED_SRS.md) | Unified frontend + backend SRS |
|
||||
| [`docs/ENCOACH_ODOO19_BACKEND_SRS.md`](docs/ENCOACH_ODOO19_BACKEND_SRS.md) | Backend SRS v3.0 |
|
||||
| [`docs/ENCOACH_WORKFLOWS_BACKEND_SRS.md`](docs/ENCOACH_WORKFLOWS_BACKEND_SRS.md) | Backend workflows |
|
||||
| [`docs/ENCOACH_WORKFLOWS_FRONTEND_SRS.md`](docs/ENCOACH_WORKFLOWS_FRONTEND_SRS.md) | Frontend workflows |
|
||||
|
||||
---
|
||||
|
||||
## 8. Contributing
|
||||
|
||||
1. Branch from `main` — never push direct. Branch protection enforces it.
|
||||
2. Run `npx tsc --noEmit -p tsconfig.app.json` (frontend) and the module smoke
|
||||
tests before opening a PR.
|
||||
3. Every architectural decision should be captured as an ADR under
|
||||
[`docs/adr/`](docs/adr/). Copy `0000-template.md` to start one.
|
||||
4. Open the PR against `main` and request review from devops (Talal).
|
||||
|
||||
Reference in New Issue
Block a user