Skip to content

Backend App Reference — apps/backend/

Operational reference: endpoints, schema summary, env vars, deploy commands, Alembic cheatsheet. For coding conventions and behavior rules, see apps/backend/CLAUDE.md.

Stats

Item Value
Endpoints 500+ across 48 modules
Tables 107+
Service modules 57

Project Structure

apps/backend/
├── src/
│   ├── main.py              # FastAPI app entry point
│   ├── api/v1/              # 48 route modules
│   ├── core/
│   │   ├── config.py        # Settings (Pydantic)
│   │   ├── security.py      # JWT, password hashing, role-based auth
│   │   └── ai/              # LLM implementation
│   │       ├── llm.py       # LLMGateway with automatic fallback
│   │       ├── prompts.py   # System prompts
│   │       ├── providers/   # Gemini, Anthropic, OpenAI
│   │       └── tools/       # code_executor, web_search, rag, image_generator
│   ├── db/
│   │   ├── base.py          # SQLAlchemy Base, TimestampMixin, SoftDeleteMixin
│   │   └── session.py       # Async session factory, get_db dependency
│   ├── models/              # SQLAlchemy models (38 files, 107+ tables)
│   ├── schemas/             # Pydantic schemas (40+ files)
│   └── services/            # Business logic (57 service modules)
├── alembic/                 # Database migrations
├── Dockerfile
└── pyproject.toml

API Modules (src/api/v1/)

File Prefix Description
auth.py /auth Login, register, token refresh
users.py /users User CRUD, bulk upload, password reset, parent management
schools.py /schools School management, academic structure, promotion
organizations.py /organizations Org hierarchy, settings
org_units.py /org-units Organizational unit management (67 endpoints)
courses.py /courses Course/chapter/lesson CRUD
homework.py /homework Assignments, submissions, grading
curated_courses.py /curated-courses Admin curriculum distribution
presentations.py /presentations AI-powered presentations
ai_tutor.py /ai-tutor Chat with streaming (SSE)
ai_teacher.py /ai-teacher Content generation
ai_evaluation.py /ai-evaluation AI grading with rubrics
ai_quota.py /ai-quota AI usage quota management
deep_research.py /deep-research Topic research
physical_exam.py /physical-exam Paper upload, question extraction, answer sheet evaluation
proctoring.py /proctoring Exam proctoring
attendance.py /attendance Manual + face attendance
admin_analytics.py /admin/analytics Platform analytics, drill-down, export
platform_analytics.py /platform/analytics Platform-wide analytics
analytics.py /analytics General analytics
marketplace.py /marketplace Content buying/selling
marketplace_subscriptions.py /marketplace/subscriptions Marketplace subscription management
subscription_plans.py /subscription-plans Subscription plan management
online_classes.py /online-classes 100ms video integration
calendar.py /calendar Calendar events
dashboard.py /dashboard Dashboard data
parent_dashboard.py /parent-dashboard Parent-specific dashboard
messaging.py /messaging In-app messaging
notifications.py /notifications Push/in-app notifications
feedback.py /feedback User feedback
bug_reports.py /bug-reports Bug report submission
knowledge_base.py /knowledge-base Teacher knowledge base
document_context.py /document-context Document understanding
media.py /media File uploads, GCS
gamification.py /gamification Points, badges, leaderboard
feature_flags.py /feature-flags Feature flag management
hierarchical_feature_flags.py /hierarchical-feature-flags Org-level feature flags
creators.py /creators External educator management
external_courses.py /external-courses External course imports
publications.py /publications Content publications
platform_content.py /platform-content Platform-wide content
platform.py /platform Platform settings
departments.py /departments Department management
college_templates.py /college-templates Higher ed templates
google_classroom.py /google-classroom Google Classroom integration
google_drive.py /google-drive Google Drive integration
report_cards.py /report-cards Report card generation
supported_boards.py /supported-boards Supported education boards
supported_subjects.py /supported-subjects Supported subjects
demo_requests.py /demo-requests Demo request handling

Microservice Integrations

Service Description Client
kwiloai-doc-intelligence OCR, PDF export, evaluation, KB services/doc_intelligence_client.py
kwiloai-deep-research Deep research reports services/deep_research_client.py

Environment Variables

# Required
DATABASE_URL=postgresql+asyncpg://user:pass@host/vidyanet
SECRET_KEY=<long-random-string>
GEMINI_API_KEY=<gemini-api-key>

# AI fallbacks
ANTHROPIC_API_KEY=<key>
OPENAI_API_KEY=<key>
TAVILY_API_KEY=<key>

# Communication
MSG91_AUTH_KEY=<key>
SMTP_EMAIL=<gmail>
SMTP_PASSWORD=<app-password>

# Cloud
GCS_BUCKET=vidyanet-uploads
HMS_APP_ACCESS_KEY=<100ms-key>
HMS_APP_SECRET=<100ms-secret>

# Microservices
DOC_INTELLIGENCE_URL=<url>
DOC_INTELLIGENCE_SERVICE_KEY=<key>
DEEP_RESEARCH_URL=<url>
DEEP_RESEARCH_SERVICE_KEY=<key>

# Observability (default: off; flip per-env)
OTEL_ENABLED=false
OTEL_BACKEND=otlp                           # otlp (Jaeger) | azure_monitor
OTEL_SERVICE_NAME=kwilo-backend
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_TRACES_SAMPLER_ARG=1.0                 # 1.0 staging, 0.1 prod
APPLICATIONINSIGHTS_CONNECTION_STRING=      # required when OTEL_BACKEND=azure_monitor

GCP secrets used on Cloud Run: vidyanet-database-url, vidyanet-gemini-api-key, vidyanet-msg91-auth-key.

Alembic Cheatsheet

cd apps/backend
uv run alembic revision --autogenerate -m "description"
uv run alembic upgrade head
uv run alembic downgrade -1
uv run alembic check          # verify migrations are up to date
uv run alembic history

Rules: always implement both upgrade() and downgrade(). Use DateTime(timezone=True) for timestamps. Index names: ix_<table>_<col>, fk_…, uq_…. Test upgrade + downgrade on staging before merge.

Cloud Run Deployment (manual fallback — normally CI)

cd apps/backend
gcloud run deploy vidyanet-backend \
  --source . \
  --project=vidyanet-prod \
  --region=asia-south1 \
  --allow-unauthenticated \
  --set-secrets=DATABASE_URL=vidyanet-database-url:latest,GEMINI_API_KEY=vidyanet-gemini-api-key:latest \
  --add-cloudsql-instances=vidyanet-prod:asia-south1:vidyanet-postgres-prod

Local Dev

cd apps/backend
uv sync
docker-compose up -d                    # PostgreSQL
uv run alembic upgrade head
uv run uvicorn src.main:app --reload --port 8000

# Observability (local Jaeger)
docker compose -f ../../docker-compose.observability.yml up -d
OTEL_ENABLED=true OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
  uv run uvicorn src.main:app --reload --port 8000
# Traces at http://localhost:16686

Internal Cron Endpoints

These routes live under /internal/* and are protected by CloudTasksAuth (src/core/cloud_tasks_auth.py): every caller must present a Google-signed OIDC token whose audience equals settings.cloud_tasks_service_url (the Cloud Run base URL) and whose email equals settings.cloud_tasks_invoker_sa (the invoker service account). In local dev both settings are unset so the check is a no-op.

KB document reaper

Property Value
Endpoint POST /api/v1/internal/knowledge-base/reap-stuck-documents
Source src/api/v1/internal.pyreap_stuck_knowledge_documents
Purpose Flips TeacherKnowledgeDocument rows stuck in processing past kb_ingestion_max_runtime_seconds to failed, unblocking the teacher's KB upload list
Schedule Every 15 minutes (*/15 * * * *, UTC)
Auth OIDC — audience = Cloud Run service URL, email = invoker SA
Idempotent Yes — uses UPDATE … WHERE status = processing RETURNING id

Setup script: scripts/setup-kb-reaper-scheduler.sh

The script enables cloudscheduler.googleapis.com (currently disabled on staging) and creates or updates the Cloud Scheduler job kb-reap-stuck-documents with the correct OIDC parameters. It is idempotent: describe-then-create-or-update.

Staging:

# Fetch the live Cloud Run URL first (staging service is vidyanet-backend-staging):
SERVICE_URL=$(gcloud run services describe vidyanet-backend-staging \
  --project=vidyanet-staging --region=asia-south1 \
  --format='value(status.url)')

SERVICE_URL="${SERVICE_URL}" bash scripts/setup-kb-reaper-scheduler.sh

Production:

SERVICE_URL=$(gcloud run services describe vidyanet-backend \
  --project=vidyanet-prod --region=asia-south1 \
  --format='value(status.url)')

PROJECT=vidyanet-prod \
SERVICE_URL="${SERVICE_URL}" \
INVOKER_SA=vidyanet-backend-sa@vidyanet-prod.iam.gserviceaccount.com \
  bash scripts/setup-kb-reaper-scheduler.sh

Manual trigger (smoke-test after setup):

gcloud scheduler jobs run kb-reap-stuck-documents \
  --project=vidyanet-staging --location=asia-south1

Evaluation job reaper

Property Value
Endpoint POST /internal/evaluation/reap-stuck-jobs
Source src/api/v1/internal.pyreap_stuck_evaluation_jobs
Purpose Marks EvaluationJob rows stuck in pending/running past eval_job_max_runtime_seconds as failed
Auth Same OIDC model as the KB reaper

Wire with the same script pattern, substituting the endpoint path and a different job name (e.g. eval-reap-stuck-jobs).