File size: 8,755 Bytes
0e76632 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | # MAC β MBM AI Cloud Β· Build Progress
**Project:** Self-hosted AI inference platform for MBM University Jodhpur
**Stack:** FastAPI Β· SvelteKit Β· PostgreSQL Β· Redis Β· vLLM Β· Nginx Β· Docker
**Repo:** `D:\mac2` (push to `github.com/mbmuniversity2026/MAC`)
---
## β
Completed
### Session 1 β Backend Foundation
#### Database / Migrations
- Alembic wired β `alembic/env.py` imports all models
- `20260426_0001_initial_schema.py` β full initial schema capture
- `20260427_0002_session1_tables.py` β feature_flags, system_config, branches, sections, cluster_heartbeats, shared_files, file_downloads, video_projects, video_jobs + user columns
#### New Models (`mac/models/`)
| File | Tables |
|------|--------|
| `feature_flag.py` | `FeatureFlag` |
| `academic.py` | `Branch`, `Section` |
| `cluster.py` | `ClusterNode`, `ClusterHeartbeat` |
| `file_share.py` | `SharedFile`, `FileDownload` |
| `video.py` | `VideoProject`, `VideoJob` |
| `system_config.py` | `SystemConfig` |
#### New Routers (`mac/routers/`)
| File | Endpoints |
|------|-----------|
| `features.py` | GET /features/status, PATCH /admin/features/{key} |
| `hardware.py` | GET /hardware/local, /hardware/recommendations |
| `network.py` | GET /network/local-ip, /network/discover |
| `system.py` | GET /system/version, /system/update-status, POST /admin/system/restart |
| `setup.py` | GET /setup/status, POST /setup/create-admin, GET /setup/recovery |
#### New Services (`mac/services/`)
- `feature_seeder.py` β seeds default flags on startup
- `setup_service.py` β JWT secret management via system_config
- `token_blacklist_service.py` β JWT blacklist via Redis (TTL-matched)
#### Security Improvements
- JWT `jti` claim added to all access tokens (`mac/utils/security.py`)
- `auth_middleware.py` checks blacklist on every request
- Logout blacklists current access token + revokes refresh tokens
---
### Session 2 β SvelteKit Frontend
**Full PWA frontend at `frontend/`:**
| File | Description |
|------|-------------|
| `src/app.html` | PWA shell, Google Fonts, SW registration |
| `src/app.css` | Full design system β dark theme, mac-blue palette, all component classes |
| `src/lib/api.js` | Complete API client (auth, query, models, usage, quota, keys, features, hardware, network, system, users, guardrails, rag, notifications, cluster, academic, files) |
| `src/lib/stores.js` | authStore, chatStore, setupStore, featureStore, toast, sidebarOpen |
| `src/lib/i18n.js` | 19 Indian languages with lazy loading + RTL support |
| `src/lib/components/ParticleCanvas.svelte` | Physics particle animation (login/splash) |
| `src/lib/components/Sidebar.svelte` | Navigation sidebar with all routes |
| `src/lib/components/Toast.svelte` | Toast notification component |
| `src/lib/components/ChatMessage.svelte` | Chat bubble with markdown rendering |
| `src/routes/+layout.svelte` | Auth guard, setup check, shell layout |
| `src/routes/+page.svelte` | Landing / redirect |
| `src/routes/login/+page.svelte` | Animated login page with particle canvas |
| `src/routes/setup/+page.svelte` | First-run admin setup wizard |
| `src/routes/chat/+page.svelte` | SSE streaming chat with model picker |
| `src/routes/dashboard/+page.svelte` | Activity heatmap, quota rings, model distribution |
| `src/routes/admin/+page.svelte` | Admin panel: Users, Models, Features, Hardware, System tabs |
| `src/routes/cluster/+page.svelte` | Cluster management: node list, detail, actions, history chart, enrollment tokens |
| `src/routes/keys/+page.svelte` | API key management (generate, copy, revoke) |
| `src/routes/settings/+page.svelte` | Profile, change password, language picker |
| `src/routes/notifications/+page.svelte` | Notification list with mark-read |
| `src/routes/rag/+page.svelte` | RAG document upload (drag-and-drop) + list |
**Static assets:**
- `static/manifest.json` β PWA manifest with shortcuts
- `static/sw.js` β Service worker (cache-first shell, network-first API, SSE passthrough)
**Infrastructure:**
- `nginx/nginx.conf` β HTTP server (production)
- `nginx/nginx.https.conf` β HTTPS server with TLS, HSTS, WebSocket proxy
- `docker-compose.yml` β Master node: MAC API + vLLM + Postgres + Redis + Nginx + Qdrant + SearXNG
- `docker-compose.worker.yml` β Worker node: vLLM + optional Jupyter + worker-agent
---
### Session 2 β Distributed Cluster Backend
#### Cluster Architecture
```
Master node (this machine)
βββ MAC API (FastAPI) β receives all user requests
βββ PostgreSQL β DB (master-only)
βββ Redis β cache, rate limiting, JWT blacklist
βββ Nginx β reverse proxy + frontend
βββ Qdrant β vector DB for RAG
βββ SearXNG β web search
Worker nodes (any PC on same network)
βββ vLLM β GPU inference (OpenAI-compatible)
βββ Jupyter kernel gateway β notebook execution (optional)
βββ worker_agent.py β heartbeat + registration agent
```
#### Cluster Services
- `mac/services/load_balancer.py` β score-based routing: `gpu_utilΓ0.5 + vram_ratioΓ0.3`, 30s stale threshold
- `mac/services/llm_service.py` β updated `_resolve_model_cluster` to use load balancer before local vLLM
- `mac/models/node.py` β `WorkerNode` + `NodeModelDeployment` + `EnrollmentToken`; added `notebook_port`, `tags`
- `mac/models/cluster.py` β `ClusterHeartbeat` time-series
#### Cluster Router (`mac/routers/cluster.py`)
| Endpoint | Description |
|----------|-------------|
| `POST /cluster/enroll-token` | Admin generates one-time enrollment token |
| `GET /cluster/enroll-tokens` | List all tokens |
| `POST /cluster/register` | Worker self-registers (no JWT β uses enrollment token) |
| `POST /cluster/heartbeat` | Worker sends heartbeat every 10s |
| `GET /cluster/nodes` | List all nodes with live health |
| `GET /cluster/nodes/{id}` | Node detail with deployments |
| `POST /cluster/nodes/{id}/action` | approve / drain / reactivate / remove |
| `POST /cluster/nodes/{id}/deploy` | Register vLLM deployment on node |
| `DELETE /cluster/nodes/{id}/deploy/{dep_id}` | Remove deployment |
| `GET /cluster/nodes/{id}/history` | Heartbeat time-series (for charts) |
#### Worker Agent (`worker_agent.py`)
Standalone Python script for worker PCs:
- Reads `MAC_MASTER_URL`, `MAC_ENROLL_TOKEN`, `MAC_VLLM_PORT`, etc. from env
- Self-registers on startup via enrollment token
- Sends heartbeats every 10s with GPU/CPU/RAM metrics (via `pynvml` + `psutil`)
- Queries local vLLM `/v1/models` to report active models
- Handles stale/auth errors gracefully
#### Other New Routers
| File | Endpoints |
|------|-----------|
| `mac/routers/academic.py` | CRUD for branches and sections |
| `mac/routers/file_share.py` | Admin upload, user download, stats |
---
## π² Remaining / Optional
| Item | Priority | Notes |
|------|----------|-------|
| Frontend PWA icons | Medium | `static/icon-192.png`, `static/icon-512.png`, `static/favicon.ico` β need actual PNG files |
| Frontend: refresh token flow | Medium | Silent JWT refresh in `api.js` before expiry |
| Multi-stage Dockerfile | Low | Stage 1: node build frontend; Stage 2: python + nginx |
| Feature flag wiring | Low | `feature_required("ai_chat")` on `/query/*`, etc. |
| HTTPS cert setup | Deployment | Use `nginx.https.conf` + Let's Encrypt / self-signed |
| `alembic/versions/0003` | When schema changes | Node notebook_port and tags columns |
| Video generation service | Future | `VideoProject` / `VideoJob` models exist, router not yet created |
---
## Deployment Quick-Start
### Master node
```bash
# 1. Build frontend
cd frontend && npm install && npm run build && cd ..
# 2. Configure environment
cp .env.example .env # edit DB, Redis, model settings
# 3. Run DB migrations
docker compose up postgres -d
docker compose run --rm mac alembic upgrade head
# 4. Start all services
docker compose up -d
```
### Adding a worker node
```bash
# On the master β generate enrollment token
curl -X POST http://MASTER_IP:8000/api/v1/cluster/enroll-token \
-H "Authorization: Bearer ADMIN_JWT" \
-d '{"label":"Lab PC 1","expires_hours":24}'
# On the worker PC
MAC_MASTER_URL=http://MASTER_IP:8000 \
MAC_ENROLL_TOKEN=<token_from_above> \
MAC_VLLM_PORT=8001 \
docker compose -f docker-compose.worker.yml up -d
# Then approve the node in MAC admin panel β Cluster tab
```
### HTTPS (production)
```bash
# Place certs in nginx/ssl/
# Swap nginx config:
# In docker-compose.yml, change:
# volumes: ./nginx/nginx.conf β ./nginx/nginx.https.conf
# Then restart nginx
```
---
*Last updated: 2026-04-27 β Session 2 complete*
|