Skip to content

HaydernCenterpoint/Project-Clover

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Study Platform

Multi-school, multi-tenant AI-native learning platform foundation.

Current slice

This repository currently contains the first local foundation POC:

  • FastAPI modular monolith under services/api.
  • Configuration-driven seed data for two isolated tenants.
  • Local identity adapter with a Keycloak/OIDC boundary.
  • Shared-schema PostgreSQL + pgvector migration with fail-closed RLS policies.
  • Tenant-aware deterministic RAG with citation and refusal behavior.
  • M3a text ingestion foundation: durable tenant-scoped jobs, deterministic 1536-dimension embeddings, exact pgvector retrieval, and ACL deny enforcement.
  • M3b grounding/isolation regression gate with a synthetic corpus, strict citation/refusal/isolation metrics, and a CLI runner for both repository modes.
  • M3c STORM-compatible research-job foundation: durable administrator jobs, approved course-source policy, deterministic cited briefs, per-tenant active-job limits, and internal budget units without external provider calls.
  • Managed-Moodle integration foundation: tenant-scoped connections, external-ID mappings, idempotent sync jobs, retry state, and reconciliation reports.
  • M4b.2 Student Web under apps/student-web: tenant-bound grounded chat/citations, a course-content view for lessons and assignments, and the existing student submission/update flow.
  • M4a tenant-health Admin Web under apps/admin-web: an administrator-only, tenant-scoped, read-only integration and reconciliation dashboard.
  • M4b.1 Knowledge Operations under apps/admin-web/knowledge-operations: administrator-only, tenant-scoped review of document lifecycle metadata and safe research-job citation outcomes.
  • M4c Mobile under apps/mobile: React Native + Expo tenant-bound student shell with local development profiles, grounded citations/refusals, learning-flow review, and student submission updates.
  • ADRs, data model, roadmap, and implementation plan under docs/.

The dev identity adapter is for local testing only. It is not a production authentication mechanism.

Run the API

cd services/api
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e ".[test]"
uvicorn app.main:app --reload --port 8000

Test identities:

  • Bearer dev-saodo-admin → Tenant A school administrator for integration APIs

  • Bearer dev-saodo-student → Tenant A seed

  • Bearer dev-demo-student → Tenant B seed

Run the student web

cd apps/student-web
npm install
npm run dev

Open http://localhost:3000. The development tenant switcher reads public/dev-profiles.json; production tenant discovery must come from domain, Keycloak claims, membership, or LTI registration.

  • / has working Trợ lý học tập and Nội dung môn học views. It loads only the authenticated profile's tenant config, identity, courses, and selected-course learning flow.
  • The assistant renders grounded citations or an explicit source-unavailable response. Conversations are scoped to the active local profile and course; changing either clears or hides prior state before fresh data renders.
  • An open assignment can be submitted or updated through the existing student-only submission endpoint. The browser never sends tenant_id; the only Student Web mutations are the existing chat and assignment-submission POST requests.
  • Run npm test for the dependency-free client-state isolation checks, then npm run lint and npm run build.

Run the mobile shell (M4c)

Start the FastAPI service, then run the Expo client:

cd services/api
uvicorn app.main:app --reload --port 8000

cd ../../apps/mobile
npm install
Copy-Item .env.example .env
npm run android

The checked-in .env.example uses http://10.0.2.2:8000, Android emulator access to the host API. For iOS or a physical device, set EXPO_PUBLIC_API_URL to a reachable LAN API origin and restart Expo; expose Uvicorn with --host 0.0.0.0 only on a trusted development network. The profile selector is development-only, no mobile request sends tenant_id, and release builds intentionally have no embedded dev token. See the mobile README for the full network and verification instructions.

Run the Admin Web (M4a and M4b.1)

Start the API with both local web origins allowed:

cd services/api
$env:ALLOWED_ORIGINS = "http://localhost:3000,http://localhost:3001"
uvicorn app.main:app --reload --port 8000

Then start the standalone Admin Web:

cd apps/admin-web
npm install
npm run dev

Open http://localhost:3001. Its local profile selector is development-only: production tenant and identity resolution remain server-owned through the authenticated request context.

  • / is the M4a Tenant Health dashboard. It fetches only GET /api/v1/admin/tenant-health.
  • /knowledge-operations is the M4b.1 review desk. It fetches only GET /api/v1/admin/knowledge-operations and displays document titles/course labels/visibility/lifecycle plus safe research-job/citation metadata.

Neither surface sends a tenant_id, exposes a tenant selector, queues or processes a job, retries work, or returns document content, ACL subjects, worker payloads, idempotency keys, requester details, or research outlines.

Run local infrastructure

docker compose -f infrastructure/docker/docker-compose.yml up -d

The compose file provides PostgreSQL with pgvector, Redis, and Keycloak dev mode. The API uses the deterministic repository by default; set USE_DATABASE_REPOSITORY=true to use PostgreSQL-backed reads.

PostgreSQL is exposed on host port 55432 to avoid conflicts with a local PostgreSQL service; the container still listens on 5432.

To seed and use PostgreSQL-backed reads locally:

cd services/api
pip install -e ".[test]"
python scripts/seed_db.py
$env:USE_DATABASE_REPOSITORY = "true"
uvicorn app.main:app --reload --port 8000

For an existing Docker volume, apply the learning-flow, integration, and document-ingestion migrations once before seeding:

docker compose -f infrastructure/docker/docker-compose.yml exec -T postgres psql -U platform -d platform -f /docker-entrypoint-initdb.d/002_learning_flow.sql
docker compose -f infrastructure/docker/docker-compose.yml exec -T postgres psql -U platform -d platform -f /docker-entrypoint-initdb.d/003_integrations.sql
docker compose -f infrastructure/docker/docker-compose.yml exec -T postgres psql -U platform -d platform -f /docker-entrypoint-initdb.d/004_document_ingestion.sql
docker compose -f infrastructure/docker/docker-compose.yml exec -T postgres psql -U platform -d platform -f /docker-entrypoint-initdb.d/005_research_jobs.sql

Document ingestion (M3a)

Only school_admin and platform_admin contexts can queue or inspect a text-ingestion job. The public API never executes ingestion inline: a worker receives the persisted job metadata and calls the worker adapter under the original tenant/requester context.

$headers = @{ Authorization = "Bearer dev-saodo-admin"; "Idempotency-Key" = "local-document-001" }
$body = '{"title":"Market note","source_uri":"moodle://course-saodo-eco101/resources/market-note","content":"Supply and demand meet at market equilibrium.","visibility":"course","course_id":"course-saodo-eco101"}'
Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/v1/documents/ingestion-jobs -Headers $headers -ContentType "application/json" -Body $body

The current provider is deterministic and dependency-free so the local pilot works without an external API key. It is an interface-compatible development/pilot adapter, not a semantic-quality claim. PostgreSQL performs exact cosine search after tenant, course, publication, and ACL filters; a production embedding provider, ANN index, queue runtime, file parsing, and evaluation corpus remain later M3 work.

Research jobs (M3c)

Only school_admin and platform_admin contexts can queue or inspect a research job. The request selects one to five existing, published documents from the specified course. The worker recreates the persisted requester context and produces a deterministic, cited brief; there is intentionally no public endpoint that executes a job.

$headers = @{ Authorization = "Bearer dev-saodo-admin"; "Idempotency-Key" = "local-research-001" }
$body = '{"topic":"How does market equilibrium change when demand shifts?","course_id":"course-saodo-eco101","source_document_ids":["doc-saodo-eco-market"],"budget_units":20}'
Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/v1/research-jobs -Headers $headers -ContentType "application/json" -Body $body

The current foundation does not crawl URLs, call web search, or call an LLM. It uses a per-tenant limit of one queued/running job and checks an internal estimate of 10 units per source against the supplied 10–100 unit budget. A future external STORM adapter needs a school-approved source policy, credentials, spending/rate limits, model/version choice, retention controls, and Architecture Review Board approval. See the research worker contract.

Integration sandbox

Only school_admin and platform_admin contexts can view integration metadata, queue a sync, inspect mappings, or read reconciliation status. A queued job is idempotent per tenant, integration, and Idempotency-Key; the worker-facing processor is intentionally not exposed as a public HTTP route.

$headers = @{ Authorization = "Bearer dev-saodo-admin"; "Idempotency-Key" = "local-course-sync-001" }
Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/v1/integrations/integration-saodo-moodle/sync-jobs -Headers $headers -ContentType "application/json" -Body '{"operation":"course_catalog"}'

The checked-in Moodle connections are deterministic sandbox records. A managed connection uses a secret reference only; never place a Moodle token in seed data, the database, source control, or a public API response. See the Moodle connector contract for onboarding requirements.

Verify

cd services/api
pytest -q
python scripts/run_evaluations.py
python -c "from app.main import app; print(app.title)"

cd ../../apps/student-web
npm test
npm run build

cd ../admin-web
npm run lint
npm run build

cd ../mobile
npm test
npm run typecheck
npm run export:android

Architecture and next gate

Read the foundation design, the M4b.2 design, the M4c design, the M3a design, the M3c design, ADR-002, the data model, and the Moodle connector contract. M4 experience surfaces are complete. The next gate is deferred pilot hardening: managed-Moodle onboarding, real Keycloak validation, queue deployment, SIS audit, operational controls, and closed-beta readiness.

About

An simple project

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors