Ir al contenido

Arquitectura

SoftSys Edu Analytics es una plataforma multi-tenant de analítica de aprendizaje para Moodle. Captura eventos vía un plugin nativo, los procesa en infraestructura edge serverless, mantiene un OLTP de baja latencia, materializa informes precomputados y los sirve a una SPA — todo bajo una superficie unificada de política que aísla rigurosamente los datos por tenant y rol.

PiezaFunción
Plugin Moodle (local_ssea)Captura eventos, sincroniza dimensiones, emite JWT con rol y course_ids
Ingest (ssea-ingest)Acepta eventos en el edge, normaliza, valida, encola
Cola de eventos + Processor (ssea-processor)Deduplicación, upsert en OLTP
OLTPEventos, dimensiones (users, courses, enrollments), agregados
Report worker (ssea-report-worker)Cron horario: agrega y emite artifacts JSON+CSV + snapshots
Almacenamiento de objetosArtifacts pre-computados de informes, exportes, archivos diarios
Snapshots key-valueResumen del último artifact por tenant + tipo (TTL 35 min)
API (ssea-api)REST autenticado; superficie de política que gobierna cada lectura
Dashboard (ssea-dashboard)SPA React; consume sólo lecturas pre-calculadas
Router de dominio (ssea-router)Resuelve dominios custom (analytics.cliente.edu) al tenant correcto
Alerts (ssea-alerts)Cron horario; calcula scores de riesgo y dispara webhooks
Export (ssea-export)Streams a CSV/JSON role-gated; archivado diario JSONL

Entre la autenticación y el acceso a datos vive una única superficie de política. Cada endpoint declara la capability que requiere; un módulo central decide allow/deny y construye el filtro de scope que se concatena al SQL.

Request
authenticate() ← extrae rol, tenant_id, course_ids
policy.decide({ ← un solo punto de decisión
ctx, capability,
resource: {tenant_id, id}
})
↓ allow deny
├─→ scope.clause aplicado al SQL → datos ↓
└─→ audit row vía waitUntil envelope uniforme + audit row
  • 28 capabilities registradas en producción (matriz completa).
  • Decisiones se asientan en una tabla de auditoría unificada (policy_audit_log) con discriminadores actor_role y acting_as_tenant.
  • Una prueba de contrato build-time (capabilities.contract.test.ts) bloquea CI si un endpoint nuevo intenta llegar a producción sin capability registrada o sin tests cross-tenant + cross-role.
  • La superficie es extensible a roles futuros (e.g., reseller) sin tocar handlers existentes — sólo se registran nuevas reglas.

Garantía no-negociable (constitución, principio I): ningún rol distinto de superadmin puede observar datos de otro tenant.

  • Toda consulta al OLTP incluye WHERE tenant_id = ? antes de cualquier otro filtro.
  • Toda clave de objeto en almacenamiento se prefija con {tenant_id}/.
  • Los JWT firmados embeben tenant_id como claim obligatorio; el middleware rechaza tokens sin él.
  • Los super-admins que entran en otro tenant lo hacen explícitamente vía tenant.switch; cada lectura se registra con acting_as_tenant puesto.
  • Tests cross-tenant son obligatorios para cada endpoint nuevo, validados por la prueba de contrato build-time.
CapaNaturalezaRetención
OLTPEventos crudos + dimensiones + agregados horarios/diariosVariable por tenant + plan (retención de datos)
Almacenamiento de objetos — reports/Artifacts JSON+CSV de informes (último por tipo + histórico)90 días por defecto
Almacenamiento de objetos — archive/JSONL diario de eventos365 días
Snapshots key-valueÚltimo artifact por (tenant, tipo)TTL 35 minutos
Audit log (policy_audit_log)Una fila por decisión de la política90 días general; 365 días para operadores

Cada tenant puede operar bajo un dominio propio (analytics.cliente.edu). El router resuelve el host al tenant, aplica branding (logo, colores, nombre) y expone el dashboard SPA sin filtrar referencias a infraestructura. La marca SoftSys aparece sólo bajo el dominio principal; resellers y clientes finales obtienen un producto enteramente blanqueado.

ComponentePresupuesto
Ingest de eventos (P95)< 100 ms en el edge
Decisión de política (policy.decide, parte síncrona, P95)< 1 ms in-process (verificado en CI por tests/policy/perf.test.ts)
Audit log list endpoint (P95, 100 k filas)< 500 ms
Dashboard inicial (cold cache)< 2 s
Generación de informe horario< 30 s para tenant típico

El presupuesto de la decisión de política se enforce en CI: una regresión que cruce el doble del nominal (2 ms en runners CI) falla npm test. Esto previene que cambios en el módulo de política impacten silenciosamente la latencia de cada request autenticada.

TareaTriggerFrecuencia
Ingest de eventosPush del pluginContinuo (500+ req/min)
Sync incremental Moodle ↔ OLTPPlugin scheduled task5 min
Sync completo Moodle ↔ OLTPPlugin scheduled taskDiario, madrugada
Generación de informesCron en report workerCada hora
Cálculo de risk scoresCron en alertsCada hora
Archivado diario JSONLCron en exportDiario
Limpieza de audit logCron en api (futuro)Diario