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.py — reap_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.py — reap_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).