| { |
| "description": "Multiverse Campus system architecture, operational constraints, and confirmed audit findings", |
| "triples": [ |
| { |
| "subject": "campus_runtime", |
| "predicate": "implemented_with", |
| "object": "Node.js 20" |
| }, |
| { |
| "subject": "campus_language", |
| "predicate": "implemented_with", |
| "object": "TypeScript" |
| }, |
| { |
| "subject": "campus_server", |
| "predicate": "implemented_with", |
| "object": "Express 4" |
| }, |
| { |
| "subject": "campus_client", |
| "predicate": "implemented_with", |
| "object": "React 18 + Vite 7 + Tailwind CSS 4" |
| }, |
| { |
| "subject": "campus_state", |
| "predicate": "implemented_with", |
| "object": "Zustand (49 stores)" |
| }, |
| { |
| "subject": "campus_database", |
| "predicate": "implemented_with", |
| "object": "PostgreSQL 16 (120 tables, 377 migrations)" |
| }, |
| { |
| "subject": "campus_cache", |
| "predicate": "implemented_with", |
| "object": "Redis 7 (data + Socket.IO pub/sub)" |
| }, |
| { |
| "subject": "campus_real-time", |
| "predicate": "implemented_with", |
| "object": "Socket.IO 4 (Redis adapter, PM2 cluster)" |
| }, |
| { |
| "subject": "campus_process_mgr", |
| "predicate": "implemented_with", |
| "object": "PM2 cluster mode (max instances)" |
| }, |
| { |
| "subject": "campus_jobs", |
| "predicate": "implemented_with", |
| "object": "pg-boss 12 (durable, PostgreSQL-backed)" |
| }, |
| { |
| "subject": "campus_queue", |
| "predicate": "implemented_with", |
| "object": "NATS JetStream (sprite generation)" |
| }, |
| { |
| "subject": "campus_monorepo", |
| "predicate": "implemented_with", |
| "object": "npm workspaces: shared, design-system, server, client" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "Matrix (Synapse) (Chat)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "Stripe (Payments)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "LiveKit (Video/audio)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "BigBlueButton (Lectures)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "Groq (LLM (primary))" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "Anthropic (LLM (Claude))" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "OpenRouter (LLM (fallback))" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "PixelLab (Sprite generation)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "SendGrid (Email)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "AWS S3 (Storage)" |
| }, |
| { |
| "subject": "campus", |
| "predicate": "integrates", |
| "object": "GCP Secret Manager (Secrets (optional))" |
| }, |
| { |
| "subject": "staging_environment", |
| "predicate": "shares_database_with", |
| "object": "production_environment" |
| }, |
| { |
| "subject": "campus_migrations", |
| "predicate": "must_be", |
| "object": "additive_only" |
| }, |
| { |
| "subject": "campus_migrations", |
| "predicate": "must_be", |
| "object": "backward_compatible_and_reversible" |
| }, |
| { |
| "subject": "campus_auth", |
| "predicate": "uses", |
| "object": "bearer_jwt_15min_access_7day_refresh" |
| }, |
| { |
| "subject": "campus_auth", |
| "predicate": "middleware_chain", |
| "object": "verifyToken -> rejectIfIneligible -> requireAdmin/requireModerator" |
| }, |
| { |
| "subject": "websocket_auth", |
| "predicate": "verified_via", |
| "object": "handshake.auth.token -> verifyToken()" |
| }, |
| { |
| "subject": "campus_deploy", |
| "predicate": "flows_through", |
| "object": "push_to_main -> coolify_rebuild (webhook flaky)" |
| }, |
| { |
| "subject": "deploy-safe.sh", |
| "predicate": "provides", |
| "object": "snapshot + smoke test + rollback" |
| }, |
| { |
| "subject": "audit_finding_C1", |
| "predicate": "severity", |
| "object": "CRITICAL" |
| }, |
| { |
| "subject": "audit_finding_C1", |
| "predicate": "describes", |
| "object": "Lecture instructor_id type mismatch \u2014 all lectures broken" |
| }, |
| { |
| "subject": "audit_finding_C1", |
| "predicate": "remediation", |
| "object": "socket.userId is a numeric string but lecture_sessions.instructor_id is a UUID column. Use consistent ID types; never compare socket IDs to DB UUIDs with ===." |
| }, |
| { |
| "subject": "audit_finding_C1", |
| "predicate": "located_at", |
| "object": "server/src/services/lectureCapture.ts:48" |
| }, |
| { |
| "subject": "audit_finding_C2", |
| "predicate": "severity", |
| "object": "CRITICAL" |
| }, |
| { |
| "subject": "audit_finding_C2", |
| "predicate": "describes", |
| "object": "Webhook signature bypass when env var is unset" |
| }, |
| { |
| "subject": "audit_finding_C2", |
| "predicate": "remediation", |
| "object": "Never skip signature verification when a secret env var is missing \u2014 reject the request instead, or require NODE_ENV=development for any bypass." |
| }, |
| { |
| "subject": "audit_finding_C2", |
| "predicate": "located_at", |
| "object": "server/src/routes/webhook.ts:219" |
| }, |
| { |
| "subject": "audit_finding_H1", |
| "predicate": "severity", |
| "object": "HIGH" |
| }, |
| { |
| "subject": "audit_finding_H1", |
| "predicate": "describes", |
| "object": "JWT_SECRET falls back to empty string" |
| }, |
| { |
| "subject": "audit_finding_H1", |
| "predicate": "remediation", |
| "object": "Startup must be fatal (process.exit(1)) when JWT_SECRET is empty or a placeholder. Never sign or verify with a defaulted secret." |
| }, |
| { |
| "subject": "audit_finding_H1", |
| "predicate": "located_at", |
| "object": "server/src/middleware/auth.ts:12" |
| }, |
| { |
| "subject": "audit_finding_H2", |
| "predicate": "severity", |
| "object": "HIGH" |
| }, |
| { |
| "subject": "audit_finding_H2", |
| "predicate": "describes", |
| "object": "connect_error triggers rapid reconnection loop" |
| }, |
| { |
| "subject": "audit_finding_H2", |
| "predicate": "remediation", |
| "object": "All reconnect paths need exponential backoff. Only refresh tokens on 401/403, not on every connect_error." |
| }, |
| { |
| "subject": "audit_finding_H2", |
| "predicate": "located_at", |
| "object": "client/src/stores/presenceStore.ts:578" |
| }, |
| { |
| "subject": "audit_finding_H3", |
| "predicate": "severity", |
| "object": "HIGH" |
| }, |
| { |
| "subject": "audit_finding_H3", |
| "predicate": "describes", |
| "object": "Gem debit without transaction protection" |
| }, |
| { |
| "subject": "audit_finding_H3", |
| "predicate": "remediation", |
| "object": "debitGems/creditGems plus any dependent operation must share one DB transaction. A crash between them loses currency permanently." |
| }, |
| { |
| "subject": "audit_finding_H3", |
| "predicate": "located_at", |
| "object": "server/src/routes/store.ts:1108" |
| }, |
| { |
| "subject": "audit_finding_H4", |
| "predicate": "severity", |
| "object": "HIGH" |
| }, |
| { |
| "subject": "audit_finding_H4", |
| "predicate": "describes", |
| "object": "Trade system has no accept handler \u2014 feature incomplete" |
| }, |
| { |
| "subject": "audit_finding_H4", |
| "predicate": "remediation", |
| "object": "trade:create-offer exists but accept/decline/cancel do not. Don't build on the trade flow assuming it completes." |
| }, |
| { |
| "subject": "audit_finding_H4", |
| "predicate": "located_at", |
| "object": "server/src/services/socketHandlers/tradeHandlers.ts" |
| }, |
| { |
| "subject": "audit_finding_M1", |
| "predicate": "severity", |
| "object": "MEDIUM" |
| }, |
| { |
| "subject": "audit_finding_M1", |
| "predicate": "describes", |
| "object": "JWT_SECRET prefix leaked into NPC Matrix password" |
| }, |
| { |
| "subject": "audit_finding_M1", |
| "predicate": "remediation", |
| "object": "Never derive user-visible values from signing secrets. Use a separate secret or an HMAC derivation." |
| }, |
| { |
| "subject": "audit_finding_M1", |
| "predicate": "located_at", |
| "object": "server/src/services/shopkeeperTools.ts:368" |
| }, |
| { |
| "subject": "audit_finding_M2", |
| "predicate": "severity", |
| "object": "MEDIUM" |
| }, |
| { |
| "subject": "audit_finding_M2", |
| "predicate": "describes", |
| "object": "Matrix admins receive isAdmin=true in client response" |
| }, |
| { |
| "subject": "audit_finding_M2", |
| "predicate": "remediation", |
| "object": "Client-facing admin flags must reflect server-enforced roles only; Matrix server admin is not campus admin." |
| }, |
| { |
| "subject": "audit_finding_M2", |
| "predicate": "located_at", |
| "object": "server/src/routes/auth.ts:87" |
| }, |
| { |
| "subject": "audit_finding_M3", |
| "predicate": "severity", |
| "object": "MEDIUM" |
| }, |
| { |
| "subject": "audit_finding_M3", |
| "predicate": "describes", |
| "object": "No security headers (helmet/CSP/HSTS missing)" |
| }, |
| { |
| "subject": "audit_finding_M3", |
| "predicate": "remediation", |
| "object": "Add helmet middleware with an appropriate CSP." |
| }, |
| { |
| "subject": "audit_finding_M3", |
| "predicate": "located_at", |
| "object": "server/src/index.ts" |
| }, |
| { |
| "subject": "audit_finding_M4", |
| "predicate": "severity", |
| "object": "MEDIUM" |
| }, |
| { |
| "subject": "audit_finding_M4", |
| "predicate": "describes", |
| "object": "Faculty can kick/ban other faculty and admins" |
| }, |
| { |
| "subject": "audit_finding_M4", |
| "predicate": "remediation", |
| "object": "Moderation handlers must check the TARGET's role, not just the actor's \u2014 no acting on equal/higher privilege." |
| }, |
| { |
| "subject": "audit_finding_M4", |
| "predicate": "located_at", |
| "object": "server/src/services/socketHandlers/facultyPanelHandlers.ts:259" |
| }, |
| { |
| "subject": "audit_finding_M5", |
| "predicate": "severity", |
| "object": "MEDIUM" |
| }, |
| { |
| "subject": "audit_finding_M5", |
| "predicate": "describes", |
| "object": "No per-student message cap on agent conversations" |
| }, |
| { |
| "subject": "audit_finding_M5", |
| "predicate": "remediation", |
| "object": "Every new LLM-calling path needs a per-student daily cap or token budget." |
| }, |
| { |
| "subject": "audit_finding_M5", |
| "predicate": "located_at", |
| "object": "server/src/services/socketHandlers/agentHandlers.ts" |
| }, |
| { |
| "subject": "audit_finding_L1", |
| "predicate": "severity", |
| "object": "LOW" |
| }, |
| { |
| "subject": "audit_finding_L1", |
| "predicate": "describes", |
| "object": "Foreign keys without ON DELETE break agent deletion" |
| }, |
| { |
| "subject": "audit_finding_L1", |
| "predicate": "remediation", |
| "object": "New FKs referencing agents (or similar parents) need ON DELETE CASCADE or explicit dependent cleanup." |
| }, |
| { |
| "subject": "audit_finding_L1", |
| "predicate": "located_at", |
| "object": "migrations 193/223/303" |
| }, |
| { |
| "subject": "audit_finding_L2", |
| "predicate": "severity", |
| "object": "LOW" |
| }, |
| { |
| "subject": "audit_finding_L2", |
| "predicate": "describes", |
| "object": "Agent job payments without transaction" |
| }, |
| { |
| "subject": "audit_finding_L2", |
| "predicate": "remediation", |
| "object": "gem_balance and earnings updates must share one transaction." |
| }, |
| { |
| "subject": "audit_finding_L2", |
| "predicate": "located_at", |
| "object": "server/src/services/agentAutonomy.ts:1704" |
| }, |
| { |
| "subject": "antipattern_env_fallback_disables_security", |
| "predicate": "warns", |
| "object": "Env var fallback that silently degrades security (audit pattern 4)." |
| }, |
| { |
| "subject": "antipattern_parseint_no_nan_guard", |
| "predicate": "warns", |
| "object": "parseInt on route params without a NaN guard (audit pattern 3)." |
| }, |
| { |
| "subject": "antipattern_socket_on_without_off", |
| "predicate": "warns", |
| "object": "Socket listener registration \u2014 confirm matching socket.off cleanup (audit pattern 2)." |
| } |
| ] |
| } |