cpvl.mediahubnetwork.net

Continuous Psychometric
Validation Platform

IRT-based measurement embedded in real platforms: social media, radio, and mobile. Real-time theta scoring, CUSUM drift detection, automated governance gates.

87
Tests Passing
16.1x
GPU CUSUM Speedup
5
Live Services
15.3x
GPU EAP Speedup

One Backend, Three Frontends

The CPVL engine scores psychometric data in real-time. Users interact through platforms they already use: no separate testing app required.

💬

Social Feed

A full social media experience: posts, likes, comments, stories. Pop-up assessment questions appear naturally as users browse, measuring mood, engagement, and trust via IRT.

EMA Popups Mood Tracking Engagement Score Trust Index
🎶

Radio Channel

Live radio with real-time engagement scoring. Play/pause controls, listener counts, content engagement events feed directly into the CPVL IRT engine for content-level drift detection.

Live Streaming CUSUM Drift Content Scoring 8 Channels
📱

Flutter Mobile App

Cross-platform APK for Android and iOS. Same social feed, radio, and EMA popup experience. WebSocket-powered real-time scoring with offline queue support.

Flutter/Dart Android + iOS WebSocket Provider State

REST + gRPC API

Full programmatic access to the CPVL engine: start sessions, administer items, score responses, run drift scans, audit governance gates.

30+ Endpoints 6 gRPC Services OpenAPI Spec Python Client
📖

Documentation

20-page Docusaurus site covering architecture, deployment, configuration, REST API, gRPC, GPU acceleration, and step-by-step tutorials for EMA and radio integration.

Docusaurus 20 Pages 3 Sidebars Search

How It All Connects

Users interact with social/radio platforms. Every action: a like, a listen, a response: flows through WebSocket to the CPVL engine, which scores in real-time using IRT.

+-------------------------------------------+ | CPVL Platform Architecture | +-------------------------------------------+ Browser / Flutter App +-----------+-----------+-----------+ | Social | Radio | Profile | | Feed | Player | theta/SE | +-----+-----+-----+----+-----+-----+ | | | +-----------+-----------+ | WebSocket :8200 (real-time scoring) | +-------------+-------------+ | | | +----------+ +----------+ +----------+ | gRPC | | CPVL | | REST | | :50051 | | Engine | | :8000 | +----------+ | +------+ | +----------+ | | IRT | | | | MML | | | +--+---+ | | | | | CUSUM | | Drift | | | | | Governance | Gates | +----+----+ | InMemoryStore (or SQLite/Postgres)
  • 1

    User opens Social/Radio

    Browser connects via WebSocket to port 8200. Session is created with unique user ID.

  • 2

    EMA questions appear

    Every 15-45 seconds, a pop-up question appears. Likert-scale responses (0-4) are sent back over WebSocket.

  • 3

    IRT engine scores in real-time

    Response maps to 0/1. EAP estimates update theta. Standard error shrinks with each item. Aberrant response detection runs per-administration.

  • 4

    Score updates pushed to client

    theta, SE, n_items, aberrant_risk sent back over WebSocket. Client updates the score bar and theta trajectory chart.

  • 5

    Drift detection runs continuously

    CUSUM scan detects if item parameters shift. If signaled, governance gates trigger quarantine or rollback.

  • 6

    GPU acceleration (optional)

    With PyTorch + CUDA: CUSUM 16.1x faster, batch EAP 15.3x faster. Falls back to numpy on CPU.

Quick Start Guide

Get up and running in 5 minutes. The platform is already live at cpvl.mediahubnetwork.net.

1

Open the Platform

Navigate to cpvl.mediahubnetwork.net in your browser. You will see this landing page with links to Social Feed and Radio Channel.

BrowserURL
https://cpvl.mediahubnetwork.net
2

Start Browsing

Click "Social Feed" to enter the social platform. Posts appear in a feed. Every few seconds, a quick check-in question pops up. Answer it to generate psychometric data.

3

Watch Your Score Update

The bottom bar shows your real-time theta and standard error (SE). After 4+ responses, your measurement precision becomes meaningful. After 8 items, the session completes.

4

Try the Radio Channel

Switch to Radio from the nav bar. Pick a channel, press play. Engagement events (listen, like, share) are tracked. Feedback questions appear periodically.

5

Check the REST API

All data is accessible programmatically. List instruments, start sessions, submit responses, and run drift scans via the REST API.

terminalbash
# Health check
curl https://cpvl.mediahubnetwork.net/api/health

# List instruments
curl https://cpvl.mediahubnetwork.net/api/instruments

# Start a session
curl -X POST https://cpvl.mediahubnetwork.net/api/instruments/social_platform/sessions/start \
  -H "Content-Type: application/json" \
  -d '{"user_id": "test_user_01"}'

# Get next item (IRT-adaptive)
curl https://cpvl.mediahubnetwork.net/api/instruments/social_platform/sessions/test_user_01/next-item

# Submit response (binary: 0=disagree, 1=agree)
curl -X POST https://cpvl.mediahubnetwork.net/api/instruments/social_platform/sessions/respond \
  -H "Content-Type: application/json" \
  -d '{"user_id":"test_user_01","item_id":"mood_0","response":1,"response_time_ms":2500}'

# Get current score
curl https://cpvl.mediahubnetwork.net/api/instruments/social_platform/sessions/test_user_01/score
6

Connect via WebSocket

For real-time scoring, connect to the WebSocket server. Send EMA responses, receive live theta updates and drift alerts.

JavaScriptWebSocket
const ws = new WebSocket('wss://cpvl.mediahubnetwork.net/ws/social');

ws.onmessage = (e) => {
  const msg = JSON.parse(e.data);
  if (msg.type === 'ema_popup') {
    // Display question to user
    showQuestion(msg.data);
  }
  if (msg.type === 'score_update') {
    // Update theta display
    console.log(`theta=${msg.data.theta} SE=${msg.data.se}`);
  }
};

// Submit a response
ws.send(JSON.stringify({
  type: 'respond_to_ema',
  item_id: 'mood_0',
  value: 3,        // Likert 0-4
  response_time_ms: 2500
}));
7

Build the Flutter APK

The Flutter app source is on the server. Build it on any machine with Flutter SDK installed.

terminalbash
# Copy from server
scp -r sms@41.33.197.134:/home/sms/cpvl_backend/flutter_app ./

# Build APK
cd flutter_app
flutter pub get
flutter build apk --release

# APK output
# build/app/outputs/flutter-apk/app-release.apk

# Install on Android
adb install build/app/outputs/flutter-apk/app-release.apk

Endpoints and Services

REST API, gRPC services, and WebSocket messages. Full interactive docs at /api/docs.

REST API
gRPC Services
WebSocket Messages
GET/api/healthServer health check
GET/api/infoServer info, version, engine stats
GET/api/instrumentsList all loaded instruments
GET/api/instruments/{id}Get instrument details and item bank
POST/api/instruments/{id}/sessions/startStart a new CAT session for a user
GET/api/instruments/{id}/sessions/{user}/next-itemGet next IRT-adaptive item
POST/api/instruments/{id}/sessions/respondSubmit a response (item_id, response, response_time_ms)
GET/api/instruments/{id}/sessions/{user}/scoreCurrent theta, SE, item count
GET/api/instruments/{id}/sessions/{user}Full session state
POST/api/instruments/{id}/drift/cusumRun CUSUM drift scan on item series
GET/api/instruments/{id}/audit/readyCheck if governance release is ready
GET/api/instruments/{id}/candidatesList candidate item parameters
GET/api/instruments/{id}/audit-logFull governance audit trail
GET/api/instruments/{id}/versionsVersion history
POST/api/instruments/{id}/batch/scoreBatch score multiple users
Python Clientpython
import httpx

BASE = "https://cpvl.mediahubnetwork.net/api"

# Start session
r = httpx.post(f"{BASE}/instruments/social_platform/sessions/start",
    json={"user_id": "user_01"})

# Get adaptive item
r = httpx.get(f"{BASE}/instruments/social_platform/sessions/user_01/next-item")
item = r.json()
print(f"Next item: {item['item_id']} (b={item['difficulty']})")

# Submit response
r = httpx.post(f"{BASE}/instruments/social_platform/sessions/respond",
    json={"user_id": "user_01", "item_id": item["item_id"],
          "response": 1, "response_time_ms": 2500})

# Check score
r = httpx.get(f"{BASE}/instruments/social_platform/sessions/user_01/score")
score = r.json()
print(f"theta={score['theta_hat']}, SE={score['se']}, N={score['n_items']}")
ServiceMethodsDescription
HealthServiceCheckServer health and readiness probes
InstrumentServiceListInstruments, GetInstrument, StartSession, NextItem, SubmitResponse, GetScoreFull IRT session management
SessionServiceGetSession, ListSessions, UpdateSessionSession lifecycle management
DriftServiceRunCUSUM, RunKSTest, GetDriftStatusDistribution shift detection
GovernanceServiceCheckRelease, AuditLog, RollbackVersionAutomated governance gates
BatchScoringServiceScoreBatch, GetBatchStatusHigh-throughput batch scoring
Python gRPC Clientpython
import grpc
from server.grpc import cpvl_pb2, cpvl_pb2_grpc

channel = grpc.insecure_channel("cpvl.mediahubnetwork.net:50051")
stub = cpvl_pb2_grpc.InstrumentServiceStub(channel)

# Start session
resp = stub.StartSession(cpvl_pb2.StartSessionRequest(
    instrument_id="social_platform",
    user_id="user_01"
))

# Get next item
item = stub.NextItem(cpvl_pb2.NextItemRequest(
    instrument_id="social_platform",
    user_id="user_01"
))
print(f"Item: {item.item_id}, b={item.difficulty}")
Message TypeDirectionFields
welcomeServer to Clientuser_id, platform, theta, se
ema_popupServer to Clientitem_id, text, construct, scale[]
respond_to_emaClient to Serveritem_id, value (0-4), response_time_ms
score_updateServer to Clienttheta, se, n_items, aberrant_risk, finished
feedServer to Clientposts[] (social feed)
radio_feedServer to Clientchannels[] (radio channels)
engageClient to Servercontent_id, event_type (like/share/listen/play)
drift_checkClient to ServerTriggers CUSUM scan on user's response series
drift_resultServer to Clientsignals: {item_key: signaled}
get_emaClient to ServerRequest an immediate EMA question
Quick Testwscat
# Install wscat
npm install -g wscat

# Connect to social platform
wscat -c wss://cpvl.mediahubnetwork.net/ws/social

# Request an EMA question
> {"type": "get_ema"}

# Respond to it
> {"type": "respond_to_ema", "item_id": "mood_0", "value": 3, "response_time_ms": 2500}

# Watch for score_update messages

Server Management

The platform runs on cpvl.mediahubnetwork.net behind nginx. Use the manage script for all operations.

terminalbash
# SSH into the server
ssh sms@41.33.197.134

# Check status of all services
~/cpvl-manage.sh status

# Start all services
~/cpvl-manage.sh start

# Stop all services
~/cpvl-manage.sh stop

# Restart everything
~/cpvl-manage.sh restart

# View server logs
~/cpvl-manage.sh logs

# View iptables routing rules
cat ~/routes.sh

# Apply iptables rules (after editing routes.sh)
echo 'root' | sudo -S bash ~/routes.sh

Service Ports and Proxy Routes

Everything runs on a single port (3080). Configure one proxy in nginx to forward to http://10.10.8.230:3080.

PathRoutes ToPublic URL
/Landing pagecpvl.mediahubnetwork.net
/socialFrontend (:3333)cpvl.mediahubnetwork.net/social
/radioFrontend (:3333)cpvl.mediahubnetwork.net/radio
/apiREST API (:8000)cpvl.mediahubnetwork.net/api
/api/docsSwagger UI (:8000)cpvl.mediahubnetwork.net/api/docs
/wsWebSocket (:8200)wss://cpvl.mediahubnetwork.net/ws
/docsDocusaurus (:3400)cpvl.mediahubnetwork.net/docs
Port 50051gRPC (direct TCP)cpvl.mediahubnetwork.net:50051
nginx proxy manager configconf
# Add ONE proxy host in Nginx Proxy Manager
# Domain: cpvl.mediahubnetwork.net
# Forward to: http://10.10.8.230:3080
# Enable: Websockets Support
# Enable: Block Common Exploits (optional)

# That's it. All paths are handled by the proxy:
#   /         -> Landing page
#   /social   -> Social Feed
#   /radio    -> Radio Channel
#   /api      -> REST API
#   /api/docs -> Swagger UI
#   /ws       -> WebSocket
#   /docs     -> Documentation

# For gRPC, add a separate TCP proxy:
#   Port: 50051 -> 10.10.8.230:50051

Project Structure

/home/sms/cpvl_backendtree
cpvl_backend/
+-- cpvl/                  # Core psychometric engine (zero deps)
|   +-- models.py          # ItemParams, Session, ResponseRecord
|   +-- scoring.py         # IRT MML EAP estimation
|   +-- drift.py           # CUSUM + KS distribution shift
|   +-- governance.py      # Automated release/quarantine gates
|   +-- loop.py            # CPVLEngine orchestrator
|   +-- storage.py         # InMemoryStore (+ SQLite/Postgres)
|   +-- gpu.py             # PyTorch CUDA acceleration
|   +-- instruments.py     # Pre-built instrument definitions
+-- server/                # Production server
|   +-- app.py             # FastAPI REST (30+ endpoints)
|   +-- grpc/server.py     # gRPC (6 services)
|   +-- ws/realtime.py     # WebSocket (real-time scoring)
|   +-- config.py          # Environment configuration
|   +-- deps.py            # Dependency injection
|   +-- main.py            # Entrypoint (REST + gRPC + WS)
+-- proto/cpvl.proto       # gRPC service definitions
+-- frontend/              # Next.js social/radio platform
|   +-- src/
|       +-- app/            # Pages: social, radio, profile
|       +-- components/     # Feed, RadioPlayer, EMAPopup
|       +-- lib/            # WebSocket, API client
+-- flutter_app/            # Flutter mobile app
|   +-- lib/
|       +-- screens/        # Social, Radio, Profile screens
|       +-- widgets/        # PostCard, ChannelCard, EMAPopup
|       +-- services/       # WebSocket + REST services
+-- docs/                  # Docusaurus documentation (20 pages)
+-- tests/                 # 87 tests (33 core + 48 + 6 GPU)
+-- analysis/              # Validation studies + figure generation
+-- requirements.txt       # Python dependencies
+-- Dockerfile             # Container build
+-- docker-compose.yml     # Full deployment stack
+-- CPVL2.tex              # Research paper (LaTeX)
+-- demo.py                # EMA + Radio demo runner
+-- gpu_benchmark.py       # GPU acceleration benchmarks

Get the Mobile App

Flutter APK for Android. Build from source or use the web version.

CPVL Platform APK

Social feed, radio channel, real-time psychometric scoring in your pocket.

v1.0.0 Flutter 3.x Android 6.0+ ~15 MB
Build from Source Use Web Version

Build Instructions

terminalbash
# 1. Copy Flutter app from server
scp -r sms@41.33.197.134:/home/sms/cpvl_backend/flutter_app ./

# 2. Enter the project
cd flutter_app

# 3. Install Flutter dependencies
flutter pub get

# 4. Build release APK
flutter build apk --release

# 5. Output location
#    build/app/outputs/flutter-apk/app-release.apk

# 6. Install on connected device
adb install build/app/outputs/flutter-apk/app-release.apk

# For iOS (requires macOS)
flutter build ios --release
open ios/Runner.xcworkspace

Quick Deploy (Docker)

terminalbash
# Clone the project
git clone ... && cd cpvl_backend

# Build and run with Docker
docker compose up -d --build

# Services available at:
#   :3000  Frontend
#   :8000  REST API
#   :8200  WebSocket
#   :50051 gRPC