Skip to content

Testing Workflows - WORKING ENDPOINTS ONLY

This document lists only the workflows that work on the current main branch. No speculation, no unimplemented features.


Prerequisites

  • Backend running at http://localhost:8000
  • Postman collection imported
  • Admin account exists in Supabase

Workflow 1: User Signup & Authentication (2 min)

Goal: Create a student account and get JWT token

Endpoints

  1. POST /auth/signup - Create new student account
  2. POST /auth/signin - Get JWT token

Sample Requests

1. Signup

POST /auth/signup
Content-Type: application/json

{
  "email": "student@example.com",
  "password": "password123",
  "full_name": "Test Student"
}

Expected Response (200 OK):

{
  "success": true,
  "data": {
    "user_id": "uuid-here",
    "email": "student@example.com"
  }
}

2. Signin

POST /auth/signin
Content-Type: application/json

{
  "email": "student@example.com",
  "password": "password123"
}

Expected Response (200 OK):

{
  "success": true,
  "data": {
    "access_token": "jwt-token-here",
    "refresh_token": "refresh-token-here",
    "user": {
      "id": "uuid-here",
      "email": "student@example.com",
      "role": "student"
    }
  }
}

Notes: - Save the access_token to use in subsequent requests - Default role is "student" - No email confirmation required in local mode


Workflow 2: Get User Profile & Wallet Balance (1 min)

Goal: Check authenticated user's profile and token balance

Endpoints

  1. GET /me - Get current user profile
  2. GET /wallet/balance - Get wallet balance

Sample Requests

1. Get Profile

GET /me
Authorization: Bearer {access_token}

Expected Response (200 OK):

{
  "id": "uuid-here",
  "email": "student@example.com",
  "full_name": "Test Student",
  "role": "student",
  "created_at": "2024-01-01T00:00:00Z"
}

2. Get Wallet Balance

GET /wallet/balance
Authorization: Bearer {access_token}

Expected Response (200 OK):

{
  "user_id": "uuid-here",
  "token_balance": 50,
  "subscription_tier": "free",
  "pending_reservations": 0
}

Notes: - New users start with 50 tokens (default) - Default tier is "free"


Workflow 3: Chat Request with Streaming (3 min)

Goal: Ask a question and get streaming response with sources

Endpoints

  1. POST /chat - Send chat request (streaming or JSON)

Sample Request (Streaming)

POST /chat
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "messages": [
    {
      "role": "user",
      "content": "Qu'est-ce que la photosynthèse?"
    }
  ],
  "language": "fr",
  "grade": "12",
  "subject": "sciences",
  "stream": true
}

Expected Response (200 OK, SSE Stream):

event: metadata
data: {"retrieval_query": "photosynthèse", "language": "fr"}

event: token
data: La

event: token
data: photosynthèse

event: token
data: est

event: sources
data: [{"page_number": 5, "pdf_source": "biology.pdf", "chunk_id": "xyz"}]

event: done
data: [DONE]

Sample Request (Non-Streaming)

POST /chat
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "messages": [
    {
      "role": "user",
      "content": "Qu'est-ce que la photosynthèse?"
    }
  ],
  "language": "fr",
  "grade": "12",
  "subject": "sciences",
  "stream": false
}

Expected Response (200 OK):

{
  "answer": "La photosynthèse est le processus...",
  "retrieval_query": "photosynthèse",
  "sources": [
    {
      "page_number": 5,
      "pdf_source": "biology.pdf",
      "chunk_id": "xyz",
      "text": "excerpt from document..."
    }
  ]
}

Notes: - Tokens are deducted from wallet automatically - Requires documents to be ingested first (see Workflow 6) - Arabic questions are auto-translated to French - Streaming is recommended for better UX


Workflow 4: Admin Authentication (1 min)

Goal: Sign in as admin to access admin endpoints

Endpoints

  1. POST /auth/signin - Sign in as admin
  2. GET /admin/test-role - Verify admin role

Sample Requests

1. Admin Signin

POST /auth/signin
Content-Type: application/json

{
  "email": "admin@example.com",
  "password": "admin-password"
}

Expected Response (200 OK):

{
  "success": true,
  "data": {
    "access_token": "jwt-token-here",
    "refresh_token": "refresh-token-here",
    "user": {
      "id": "uuid-here",
      "email": "admin@example.com",
      "role": "admin"
    }
  }
}

2. Test Admin Role

GET /admin/test-role
Authorization: Bearer {admin_access_token}

Expected Response (200 OK):

{
  "status": "authorized",
  "is_admin": true,
  "method": "jwt",
  "user_id": "uuid-here",
  "role": "admin"
}

Notes: - Admin account must exist in Supabase with role="admin" - Non-admin users get 403 Forbidden on admin endpoints


Workflow 5: Admin - User Management (3 min)

Goal: List, create, update, and delete users

Endpoints

  1. GET /admin/users - List all users
  2. POST /admin/users - Create new user
  3. PATCH /admin/users/{user_id}/role - Update user role
  4. DELETE /admin/users/{user_id} - Delete user

Sample Requests

1. List Users

GET /admin/users?limit=50&offset=0
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "users": [
    {
      "id": "uuid-1",
      "email": "student@example.com",
      "full_name": "Test Student",
      "role": "student",
      "created_at": "2024-01-01T00:00:00Z"
    }
  ],
  "total_count": 1
}

2. Create User

POST /admin/users
Authorization: Bearer {admin_token}
Content-Type: application/json

{
  "email": "newstudent@example.com",
  "password": "password123",
  "full_name": "New Student",
  "role": "student"
}

Expected Response (200 OK):

{
  "id": "uuid-new",
  "email": "newstudent@example.com",
  "full_name": "New Student",
  "role": "student",
  "created_at": "2024-01-01T00:00:00Z"
}

3. Update User Role

PATCH /admin/users/{user_id}/role
Authorization: Bearer {admin_token}
Content-Type: application/json

{
  "role": "teacher"
}

Expected Response (200 OK):

{
  "id": "uuid-here",
  "email": "student@example.com",
  "full_name": "Test Student",
  "role": "teacher",
  "created_at": "2024-01-01T00:00:00Z"
}

Notes: - Valid roles: "student", "teacher", "admin" - Profile is auto-created via Supabase trigger


Workflow 6: Admin - Curriculum Upload (Direct) (5 min)

Goal: Upload a PDF curriculum document directly

Endpoints

  1. POST /admin/upload-curriculum - Upload PDF and auto-ingest

Sample Request

POST /admin/upload-curriculum
Authorization: Bearer {admin_token}
Content-Type: multipart/form-data

file: [PDF file]
grade: "12"
subject: "sciences"
language: "fr"

Expected Response (200 OK):

{
  "status": "success",
  "namespace": "grade-12-sciences",
  "pages_extracted": 120,
  "chunks_created": 450,
  "vectors_upserted": 450
}

Notes: - PDF is processed synchronously (may take 1-5 minutes) - Namespace is auto-generated: grade-{grade}-{subject} - Vectors are immediately searchable after upload - Document record is created in database


Workflow 7: Admin - Scraping Workflow (3 min)

Goal: Scrape references from Koutoubi and view results

Endpoints

  1. GET /scraping/sources - List supported scrapers
  2. POST /scraping/koutoubi/sync - Run scraper
  3. GET /scraping/koutoubi/references - List discovered references
  4. GET /scraping/koutoubi/runs - View scrape run history

Sample Requests

1. List Sources

GET /scraping/sources

Expected Response (200 OK):

{
  "sources": ["koutoubi"]
}

2. Run Scraper

POST /scraping/koutoubi/sync
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "run_id": "uuid-here",
  "status": "success",
  "found_count": 45,
  "new_count": 45,
  "updated_count": 0,
  "error_count": 0
}

3. List References

GET /scraping/koutoubi/references?status=discovered&limit=50&offset=0

Expected Response (200 OK):

{
  "limit": 50,
  "offset": 0,
  "items": [
    {
      "id": "uuid-here",
      "source": "koutoubi",
      "pdf_source": "https://koutoubi.mr/path/to/file.pdf",
      "grade": "12",
      "subject": "sciences",
      "language": "fr",
      "status": "discovered",
      "last_seen_at": "2024-01-01T00:00:00Z"
    }
  ]
}

Notes: - First sync creates new references with status="discovered" - Second sync updates existing references (new_count=0, updated_count>0) - References need to be ingested separately (see Workflow 8)


Workflow 8: Admin - Ingestion Job Management (10 min)

Goal: Create ingestion jobs for scraped references

Endpoints

  1. POST /admin/ingest/{reference_id} - Create ingestion job
  2. POST /admin/jobs/dispatch - Start processing oldest queued job
  3. GET /admin/jobs - List all jobs
  4. GET /admin/jobs/{job_id} - Get job status
  5. POST /admin/jobs/{job_id}/requeue - Requeue failed job

Sample Requests

1. Create Ingestion Job

POST /admin/ingest/{reference_id}?force=false
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "status": "queued",
  "job_id": "uuid-job",
  "reference_id": "uuid-ref"
}

2. Dispatch Job (Start Processing)

POST /admin/jobs/dispatch
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "status": "dispatched",
  "job_id": "uuid-job",
  "reference_id": "uuid-ref"
}

3. Get Job Status

GET /admin/jobs/{job_id}
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "id": "uuid-job",
  "reference_id": "uuid-ref",
  "status": "ready",
  "chunks_created": 450,
  "vectors_upserted": 450,
  "created_at": "2024-01-01T00:00:00Z",
  "file_id": "uuid-doc"
}

Status Transitions:

queued → parsing → tokenizing → embedding_request_sent → embedding_upserted → ready

4. List Jobs

GET /admin/jobs?status=ready&limit=50&offset=0
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "items": [
    {
      "id": "uuid-job",
      "reference_id": "uuid-ref",
      "status": "ready",
      "chunks_created": 450,
      "vectors_upserted": 450,
      "created_at": "2024-01-01T00:00:00Z"
    }
  ],
  "total": 1
}

Notes: - Jobs must be dispatched manually (background processing) - Processing takes 1-5 minutes depending on PDF size - Poll job status until status="ready" - Failed jobs can be requeued (max 3 retries)


Workflow 9: Admin - Document Management (2 min)

Goal: View and delete ingested documents

Endpoints

  1. GET /admin/stats - Get dashboard statistics
  2. PATCH /admin/documents/{document_id} - Update document metadata
  3. DELETE /admin/documents/{document_id} - Delete document and vectors

Sample Requests

1. Get Stats

GET /admin/stats
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "documents": {
    "total": 10,
    "ready": 8,
    "processing": 1,
    "failed": 1
  },
  "chunks": {
    "total": 3500
  },
  "references": {
    "total": 45,
    "discovered": 30,
    "ready": 15
  },
  "users": {
    "total": 20,
    "admins": 2,
    "students": 18
  },
  "jobs": {
    "queued": 5,
    "completed": 10,
    "failed": 2
  }
}

2. Delete Document

DELETE /admin/documents/{document_id}
Authorization: Bearer {admin_token}

Expected Response (200 OK):

{
  "status": "deleted",
  "document_id": "uuid-here",
  "chunks_removed": 450
}

Notes: - Deleting document also removes chunks and Pinecone vectors - Reference status is reset to "discovered" if linked


Workflow 10: Curriculum Discovery (Public) (1 min)

Goal: Browse available textbooks (no auth required)

Endpoints

  1. GET /curriculum/subjects - List available subjects
  2. GET /curriculum/textbooks - List textbooks with filters
  3. GET /curriculum/textbooks/{textbook_id} - Get textbook details

Sample Requests

1. List Subjects

GET /curriculum/subjects

Expected Response (200 OK):

{
  "subjects": ["sciences", "mathematics", "français"],
  "total": 3
}

2. List Textbooks

GET /curriculum/textbooks?grade=12&subject=sciences&language=fr

Expected Response (200 OK):

{
  "levels": ["12"],
  "textbooks": [
    {
      "id": "uuid-here",
      "title": "Biology Textbook",
      "pdf_source": "https://example.com/biology.pdf",
      "grade": "12",
      "subject": "sciences",
      "major": null,
      "language": "fr",
      "weight": 0,
      "category": null,
      "page_count": 120,
      "chunk_count": 450,
      "namespace": "grade-12-sciences"
    }
  ]
}

Notes: - All curriculum endpoints are public (no auth required) - Only shows documents with status="ready"


Workflow 11: Admin - Wallet Top-Up (2 min)

Goal: Add tokens to a student's wallet

Endpoints

  1. POST /wallet/topup - Top up student wallet (admin only)
  2. GET /wallet/transactions - View transaction history (admin only)

Sample Request

POST /wallet/topup
Authorization: Bearer {admin_token}
Content-Type: application/json

{
  "user_id": "student-uuid",
  "token_amount": 100,
  "amount_cents": 1000,
  "currency": "MRU",
  "payment_method": "manual",
  "payment_ref": "ADMIN-TOPUP-001",
  "description": "Manual top-up for testing"
}

Expected Response (200 OK):

{
  "user_id": "student-uuid",
  "token_amount": 100,
  "new_balance": 150,
  "transaction_id": "uuid-here",
  "status": "completed"
}

Notes: - Only admins can top up wallets - Creates a transaction record for auditing - Balance is updated immediately


What DOESN'T Work (Yet)

The following features are mentioned in code but NOT fully implemented or accessible:

1. Rate Limiting

  • Status: Middleware exists (RateLimitMiddleware) but NOT applied to the app
  • Location: app/core/middleware.py
  • Issue: Not added to app.add_middleware() in main.py
  • Testing: Cannot test 429 responses without applying middleware

2. Metrics Endpoint

  • Status: Metrics collector exists but NO endpoint to access it
  • Location: app/core/metrics.py
  • Issue: No route like GET /metrics registered
  • Testing: Cannot view Prometheus metrics

3. Circuit Breaker

  • Status: Implementation exists but NOT integrated into services
  • Location: app/services/circuit_breaker.py
  • Issue: Services don't wrap calls with circuit breaker
  • Testing: Cannot test circuit breaker state transitions

4. Quiz Generation

  • Status: Endpoint exists but returns stub response
  • Location: app/api/routers/quiz.py
  • Issue: Line 101-123 show stub implementation
  • Testing: Returns fake data, not real quizzes

5. Wallet Reservations (Internal)

  • Status: Endpoints exist but marked INTERNAL ONLY
  • Location: POST /wallet/internal/reserve, POST /wallet/internal/finalize
  • Issue: Require admin auth, meant for internal use by chat service
  • Testing: Chat service handles automatically, no manual testing needed

6. Request-ID Middleware

  • Status: Middleware exists but NOT applied to the app
  • Location: app/core/middleware.py
  • Issue: Not added to app.add_middleware() in main.py
  • Testing: Cannot test request-ID propagation without applying middleware

Testing Checklist

Use this checklist to verify the system:

Authentication & Authorization

  • [ ] Student signup works
  • [ ] Student signin returns JWT
  • [ ] Admin signin returns JWT with role="admin"
  • [ ] Admin endpoints reject non-admin users (403)
  • [ ] JWT contains valid user data

User Management

  • [ ] Get current user profile works
  • [ ] Admin can list all users
  • [ ] Admin can create new users
  • [ ] Admin can update user roles
  • [ ] Admin can delete users

Wallet & Billing

  • [ ] New users have 50 token balance
  • [ ] Get wallet balance works
  • [ ] Admin can top up student wallet
  • [ ] Chat requests deduct tokens automatically

Chat & RAG

  • [ ] Chat request (non-streaming) returns answer + sources
  • [ ] Chat request (streaming) returns SSE events
  • [ ] French questions work without translation
  • [ ] Arabic questions are auto-translated
  • [ ] Sources include page numbers and file references

Curriculum Management

  • [ ] Direct PDF upload works (admin)
  • [ ] Documents are chunked and embedded
  • [ ] Vectors are searchable immediately
  • [ ] Public endpoints list textbooks

Scraping & Ingestion

  • [ ] Scraper sync discovers new references
  • [ ] Second sync shows updated_count (not duplicates)
  • [ ] Ingestion jobs can be created
  • [ ] Jobs can be dispatched (manual trigger)
  • [ ] Job status transitions correctly
  • [ ] Completed jobs create searchable vectors

Admin Tools

  • [ ] Dashboard stats show correct counts
  • [ ] Documents can be deleted
  • [ ] Deleting document removes vectors from Pinecone
  • [ ] References list shows correct statuses

Summary

Working Features: - User authentication (signup, signin, logout) - User profile management - Wallet balance checking - Chat requests (streaming and non-streaming) - Admin user management - Admin wallet top-up - Direct curriculum upload - Scraping references from Koutoubi - Ingestion job management - Document management - Public curriculum discovery

Not Working / Not Accessible: - Rate limiting (middleware not applied) - Metrics endpoint (no route registered) - Circuit breaker (not integrated) - Quiz generation (stub only) - Request-ID propagation (middleware not applied)

Testing Strategy: 1. Start with Workflow 1-2 (authentication and profile) 2. Test admin workflows (4-9) to ingest content 3. Test student workflows (3) to verify RAG works 4. Use dashboard stats (9) to verify system state

Note: All workflows require a running backend and valid Supabase configuration.