# Modelo de datos (PostgreSQL) — esquema común KrakenSim + Skill Matrix

> Modelo conceptual v0. Nombres en inglés para el código, comentarios en español.

## Núcleo de identidad

```sql
users            (id, email, name, role ENUM('agent','trainer','manager','hr','admin'),
                  team_id, hired_at, active, created_at)
teams            (id, name, manager_id)
```

## Simulador — definición de procesos

```sql
processes        (id, code, name, description, area_id, active, version)
                  -- ej.: code='M1', name='Alta de suministro'
process_steps    (id, process_id, position, name, screen_id,
                  expected_actions JSONB, max_time_hint_sec)
screens          (id, name, layout JSONB)
                  -- layout: definición declarativa de la vista tipo Kraken
                  -- (componentes, campos, datos ficticios a inyectar)
validations      (id, step_id, field, rule_type ENUM('regex','format','value','required','order'),
                  rule JSONB, severity ENUM('minor','major','critical'),
                  error_message)
                  -- ej.: field='email', rule_type='regex', rule='^[a-z0-9._%+-]+@...',
                  --      severity='critical',
                  --      error_message='Email en minúsculas: la redistribuidora rechaza mayúsculas'
fake_data_pools  (id, kind ENUM('customer','supply','bank'), template JSONB)
```

## Simulador — ejecución y telemetría

```sql
exercises        (id, process_id, mode ENUM('training','exam'),
                  module_id NULLABLE, assigned_by, config JSONB)
attempts         (id, exercise_id, user_id, started_at, finished_at,
                  total_time_sec, completed BOOL, score NUMERIC,
                  error_count_minor, error_count_major, error_count_critical)
attempt_steps    (id, attempt_id, step_id, started_at, finished_at, time_sec,
                  corrections INT)
attempt_events   (id, attempt_id, step_id, ts, event_type, payload JSONB)
                  -- telemetría fina: focus de campo, valor introducido, click, error disparado
attempt_errors   (id, attempt_id, step_id, validation_id, ts, value_entered)
baselines        (id, process_id, source ENUM('pattern','median_core'),
                  p50_time_sec, p75_time_sec, updated_at)
```

## Skill Matrix — catálogo

```sql
areas            (id, name, position)
competencies     (id, area_id, code, name, description,
                  required_level ENUM('onboarding','junior','core','master','pro'))
level_rules      (id, level, rule JSONB, description)
                  -- ej.: {"requires": {"junior": "100%", "core": ">=80%"},
                  --        "time_percentile_max": 60}
```

## Skill Matrix — evaluación

```sql
items            (id, competency_id, type ENUM('situational','simulator','open_case','manager_signal'),
                  body JSONB, discriminates_levels JSONB, process_id NULLABLE, active)
campaigns        (id, name, starts_at, ends_at, created_by, item_selection JSONB)
responses        (id, campaign_id, item_id, user_id, answer JSONB, score NUMERIC,
                  graded_by ENUM('auto','ai','human'), ts)
accreditations   (id, user_id, competency_id,
                  status ENUM('accredited','not_accredited','pending'),
                  evidence JSONB, updated_at)
                  -- evidence: refs a responses/attempts que la sustentan
user_levels      (id, user_id, level, computed_at, rule_snapshot JSONB,
                  approved_by NULLABLE)
                  -- histórico de niveles con snapshot de la regla aplicada (auditable)
```

## Relación clave entre proyectos

`items.type='simulator'` → apunta a `processes.id` → una `attempt` en modo examen genera automáticamente una `response` puntuada y actualiza `accreditations` vía el motor de reglas.

## Notas

- Todo evento con timestamp → permite recalcular cualquier métrica a posteriori.
- `rule_snapshot` en `user_levels` garantiza auditabilidad: se sabe con qué regla se asignó cada nivel aunque las reglas cambien después.
- Particionar `attempt_events` por mes si el volumen crece.
