Servicio de autenticación y autorización. Integra Keycloak (OIDC + Google Identity, ADR-0007/0055) para autenticación. Autorización vía Keycloak Realm Roles validados localmente en PermissionGuard (sin PDP externo, ADR-0055). CASL se mantiene solo en frontend para checks UI declarativos.
- ✅ Esquema DB y migraciones (ADR-0010 + external_identities)
- ✅ TrustTokenSigner (ADR-0026 §1, contraparte de svc-audit)
- ✅ Health probes + métricas Prometheus
- ✅ JwtVerifier con JWKS Keycloak + errores tipados
- ✅ ForwardAuth endpoint POST|GET /v1/auth/verify (ADR-0008)
- ✅ Cache hardening completo: jitter + single-flight + SWR + circuit-breaker + deny-list + TTL superadmin (ADR-0008 §1-6)
- ✅ Endpoint admin POST /v1/admin/sessions/:userId/revoke-now
- ✅ Migración a PermissionGuard local (ADR-0055 PR-I4): elimina /v1/authorize HTTP + subsistema CASL completo
- ✅ Audit emission a svc-audit por NATS JetStream (reyva.identity.access)
- ✅ Health probes completos (Postgres/Redis/NATS) con detail per-dep + métricas
- ✅ Graceful shutdown hooks: NATS drain, Redis quit, Postgres pool end (rolling deploys K8s/Cloud Run)
- ✅ Hardening env hardcoded: DATABASE_URL obligatoria sin fallback dev (production-ready, sin secretos en code)
- ✅ Tests integración + e2e (156 con docker-compose: postgres+keycloak+redis+nats)
- ✅ Rate limiting endpoints públicos (@nestjs/throttler + Fastify trustProxy + métrica Prom identity_rate_limited_total)
- ✅ Trust token con exp + nonce anti-replay (ADR-0026)
- ✅ Audit event decision_source diferencia fail-open de allow real (auditoría 2026-05-12 alto #7 + #12)
- ✅ POST /v1/authorize endpoint PDP central (ADR-0009)
- ✅ Catálogo de permisos Keycloak Realm Roles (ADR-0055 PR-I1): 32 atómicos + 8 Composite Roles en @reyva/shared-contracts + check-permissions-sync CI
- ✅ Endpoints HTTP proxy Keycloak Admin API (ADR-0055 PR-I4): GET/PUT/DELETE /v1/admin/keycloak/{roles,users/:id/role}
- ✅ Eliminación /v1/authorize (ADR-0055 PR-I4): validación pasó a PermissionGuard local en cada svc-*, 0 HTTP calls a auth por request
- ✅ JwtRoleGuard any-of (JWT Keycloak admin OR trust token S2S) + GET catalog + GET users search (ADR-0054 PR-H5 C1)
- ✅ Lockout-prevention DELETE /v1/permissions/roles last_admin_role_protected (ADR-0054 PR-H5 A)
- ✅ Métrica Prometheus identity_jwt_role_guard_total (PR-H5 closeout)
- ✅ GET /v1/admin/keycloak/users/:userId/roles (ADR-0055 PR-I4 — consumido por UserRolesAssigner)
- ✅ Motor de permisos consolidado en PermissionGuard local (ADR-0055 PR-I8) + cleanup del sidecar previo (PR-H7)
- ✅ Cierre auditoría 2026-05-12 (altos): CWE-117 log sanitization + bloqueo Unicode confusables en forwardedUri
- ✅ Application layer migrado a Result<T, E> (errores tipados, sin throw en use-cases/repos)
- ✅ Lazy provisioning Google OIDC (ADR-0011) — MVP: schema + use-case + FOR UPDATE + dominio whitelist + Workspace port stub
- ✅ Migración ADMIN_API_TOKEN fallback → trust token vía Traefik ForwardAuth (escape hatch IDENTITY_DEV_AUTH_BYPASS=1 para dev local)
- ✅ Reverse-proxy GET /v1/admin/audit-events a svc-audit (firma trust token con principal admin, consumido por web-admin P12)
- ✅ Endpoint admin GET /v1/admin/business-subjects con paginación + filtro subject_kind + enrichment teléfono vía RPC NATS a svc-legacy-bridge (P5)
- ✅ Endpoints admin detalle/PATCH/CRUD atributos business_subjects (P6) + publisher reyva.identity.business_subject_changed + repo user_attributes con soft-delete versionado
- ✅ Endpoints admin invitaciones (LIST/CREATE/EXPIRE/REFRESH) (P7+P8) + publisher reyva.identity.invitation_changed sobre pending_user_provisioning
- ✅ Reverse-proxy admin chat-sessions + bot-settings a svc-conversation (P3/P4/P11) — SvcConversationClient firma trust token con principal admin
- ✅ KeycloakAdminClient con cache de admin token + 5 métodos REST (ADR-0055 PR-I4)
- ✅ AdminRolesController: proxy Keycloak para gestión de roles desde apps/web (ADR-0055 PR-I4)
- ✅ PermissionChangedPublisher: emite reyva.identity.permission_changed tras assign/revoke (ADR-0055 FU-3)
- ✅ POST /v1/admin/business-subjects/:userId/reveal-phone + PiiRevealedPublisher (audit P0-3 S2.4 — granularidad fina LFPDPPP ADR-0027 §6)
- ✅ Catálogo permisos: agregado Identidad.Contacto.Revelar (admin_security/admin_plataforma/superadmin) + sync Keycloak realm-reyva.json
- ✅ Restauración GET /v1/permissions/users (ADR-0055 PR-I4 follow-up): lookup admin read-only
- ✅ S5.4: VendedorSnapshotConsumer NATS materializa business_subjects (kind=vendedor) desde reyva.legacy.vendedor.changed — gemelo del consumer de subdistribuidor (S5.1), tier default ACT (vendedores legacy sin enum tier)
- ✅ S4.6: TrustToken guards (JwtRoleGuard + TrustTokenOnlyGuard) deny-by-default sin IDENTITY_TRUST_HMAC_SECRET — opt-in dev local via IDENTITY_TRUST_HMAC_BYPASS_DEV=1 (audit P1-3, cierra ventana staging/preview auth-less)
- ✅ S4.6: JwtRoleGuard valida x-user-id == claims.sub pre-rewrite (audit P1-7 v2) — bloquea forge attempt antes del rewrite a users.id interno, cierra impersonation forense LFPDPPP §3.1 ARCO en TODOS los endpoints admin (audit-events, business-subjects, invitations, conversation, sessions). Métrica deny_header_user_mismatch + log forensic con email_hash
Pasarela de recargas telefónicas (Telcel, Movistar, AT&T) y productos digitales. Conecta con TurboCarga vía bridge ACL. Maneja idempotencia exactly-once para garantizar que un cliente nunca pague dos veces.
- ✅ Scaffold NestJS + Fastify + health probes + bootstrap (PR-A)
- ✅ RechargeProviderPort + MockProvider (ADR-0050 §1)
- ✅ Schema DB inicial (recharge_requests, attempts, sim_reservations, outcomes)
- ✅ NATS publisher/consumer + stream REYVA_RECHARGE + event RechargeRequested (ADR-0050 §4)
- ✅ Saga orchestrator + state machine + ports stub (ADR-0050 §3 PR-1)
- ✅ Saga + ports migrados a Result<T, E> (errores tipados, sin throw en orchestrator)
- ✅ Compensaciones saga + trail recharge_attempts + handling provider_exception (ADR-0050 §3 PR-2)
- ✅ Manejo indeterminate + pending_reconciliation (ADR-0050 §3 PR-3)
- ✅ Fix: conciliación escala filas con provider sin QUERY_STATUS capability (ADR-0050 §6, evita filas huérfanas)
- ✅ Fix: claimBatch atómico claim-and-mark con lease (audit P1-10, evita doble-claim entre réplicas del cron)
- ✅ Lock distribuido Redis anti doble-tap (ADR-0050 §4 PR-4)
- ✅ Política reintentos por capability (ADR-0050 §6 PR-5)
- ✅ API REST POST /v1/recharges (sin auth, pre-prod) (ADR-0050 §3 PR-6)
- ✅ TrustTokenGuard HMAC en endpoint REST (ADR-0026 / PR-F)
- ✅ Nonce store anti-replay Redis SET NX EX en TrustTokenGuard (ADR-0026 §Notas P0-2, audit 2026-06-14 P0-2): bloquea replay del mismo token v2 → recarga duplicada; fail-closed ante Redis caído
- ✅ Aislamiento del secret HMAC s2s per-caller (ADR-0026 §Notas #31): el verifier solo acepta tokens firmados por svc-conversation (su caller autorizado); comprometer otro servicio NO permite forjar recargas (CRIT-11)
- ✅ Authorization via PermissionGuard local con shared-infrastructure (ADR-0055 PR-I5): elimina HTTP call a /v1/authorize
- ✅ PermissionGuard con @RequirePermission(Permissions.Recargas.Recarga.Crear) (ADR-0055 PR-I5)
- ✅ SLI de éxito de recarga (reyva_recharge_initiated/executed_total) para SLO ≥95% (ADR-0056)
- ✅ Tests integración + e2e saga (7 escenarios — scenario 8 audit hash chain diferido a svc-audit integration)
- ⏳ Adapter `primary` real Recargaki (BLOQUEADO 2026-05-26: requiere ficha técnica del proveedor — ver claudedocs/solicitud-recargaki-ficha-tecnica-2026-05-26.md)
- ✅ HttpVinculacionAdapter consume svc-vinculacion (Ola 2)
- ✅ Endpoint admin POST /v1/admin/recharges/:id/dispute (ADR-0050 §7, Ola 2)
- ✅ Endpoint admin POST /v1/admin/recharges/:id/refund capability-gated (Ola 2)
- ✅ Endpoint admin POST /v1/admin/recharges/:id/reconcile (Ola 2)
- ✅ Eventos NATS reyva.recharge.{disputed,refunded,reconciled} (Ola 2)
- ✅ Tabla recharge_admin_actions (audit append-only, PR-8 Ola 2)
- ✅ HttpInventoryAdapter consume endpoints svc-inventory /v1/sims/* (Ola 2 follow-up PR-2)
- ✅ Job conciliación nocturna BullMQ + cruce SIMs↔recargas (ADR-0050 §6, Ola 2)
- ✅ AnomalyDetectionService cross-service (sim_sold_no_recharge + recharge_succeeded_no_sim_sold) + métrica recharge_reconciliation_anomalies_total
- ✅ Emit reyva.recharge.reconciled tras resoluciones del job nocturno (ADR-0050 §5)
- ✅ Persist-first del tRequestID antes del cobro + reconciliación real con queryStatus(tRequestID) + rescate de executing_provider (Incremento 0, ADR-0050/0058)
- ⏳ Deploy staging
- ⏳ Deploy producción + canary
- ✅ Eliminación AuthorizeClient + PermissionsBootstrapService (-1,222 LOC, ADR-0055 PR-I5)
- ✅ Audit P0-3 fix: orden mark-sold ANTES de emit reyva.recharge.completed (workflow S3.7)
- ✅ Contract tests s2s svc-recharge ↔ svc-inventory ↔ svc-vinculacion via @reyva/shared-contracts/contracts (workflow S4.1)
- ✅ Retención stream REYVA_RECHARGE 7d→365d (prep Ola 3: rebuild read-models history/distributors/reports desde NATS replay, ADR-0052 §3/§313)
- ✅ ADR-0058: adaptador SOAP RecargaAqui (GetTRequestID→doT→checkTransaction, fail-fast por env) + reserva pesimista sobre id_linea vía bridge ANTES de cobrar (anti doble-cargo bot↔portal legacy, persistir-luego-actuar)
- ✅ Política fail-open/fail-closed de vinculación configurable por operadora (VINCULACION_FAILMODE__<OP>, default fail-closed CRT 2026, override auditado, ADR-0051 §A7)
- ✅ Detector huérfanas succeeded↔TBL_REYVA_TURBOCARGA (Fase 3 reconciliación nocturna): cruce por dn+ventana fecha_recarga (RPC list_by_window, índice IDX_TB_fecha_recarga, anti full-scan) + clasificación recuperable/no-recuperable + auto-re-asiento flag-gated DETECTOR_ASIENTO_AUTORESEAT (default off), cierra deuda ADR-0058
Bot conversacional sobre WhatsApp Business API (Meta). Procesa mensajes entrantes, valida firmas de webhook, y orquesta flujos de venta vía estados. Modular: cada flujo (recargas, soporte, ventas) es un módulo independiente.
- ✅ Bootstrap svc (PR-A): scaffold Nest+Fastify + pgSchema conversation + Redis dedupe/rate-limit + NATS publisher reyva.conversation.* + BullMQ queue process-message
- ✅ Webhook Meta (PR-B): HMAC fail-closed + anti-replay timestamp+dedupe + phone rate limit + ack optimista <200ms p99 (ADR-0029)
- ✅ Domain state machine (PR-C): aggregate FSM + value objects + ports (LineValidator/Vinculacion/Recharge/Sender) + stub adapters (ADR-0015)
- ✅ Orchestrator (PR-D): svc-recharge client HMAC trust token + Meta outbound sender HSM templates + ConversationOrchestrator + timeout sweep
- ✅ Hardening (PR-E): observabilidad Prometheus + rate limit Traefik + security tests + runbook rotación Meta App Secret
- ⏳ Tests integración + e2e end-to-end con Meta Cloud API real
- ✅ Endpoints admin chat-sessions + bot-settings (P3/P4/P11) con PermissionGuard + InternalRequestGuard de @reyva/shared-infrastructure (ADR-0055 PR-I6) + tabla bot_settings singleton + publisher reyva.conversation.bot_settings_changed
- ✅ docker-compose dev incluye svc-conversation (HMAC compartido con identity para reverse-proxy admin)
- ✅ Catálogo plantillas HSM (P9/P10): schema conversation.hsm_templates + endpoints admin GET /templates [+:id] + seed mock 3 plantillas (recarga_exitosa, recarga_fallida, linea_no_vinculada) hasta entrega cliente
- ✅ Migración a PermissionGuard + InternalRequestGuard de shared-infrastructure (ADR-0055 PR-I6): elimina TrustTokenGuard local duplicado
- ✅ Traefik IP rate limit en docker-compose dev via labels (conv-ratelimit, avg=30/min, burst=50) — audit P0-4 (ADR-0029 §5)
- ✅ Respuestas in-session del bot como texto libre, no HSM (Regla #13): bot 100% user-initiated → send_text dentro de ventana 24h; gate CI check-template-usage impide regresión
- ✅ Monto de recarga server-authoritative desde el inventario (ADR-0015 addendum §A4): elimina el prompt de monto (AWAITING_AMOUNT) — la SIM se vende con su recarga ya definida (modelo venta-de-SIM, SCOPE §3.1/§3.2)
- ✅ Acuse de vinculación verificada en el happy path (ADR-0015 addendum §A5.2): el bot confirma "línea verificada y vinculada" antes del prompt de confirmación — cierra el gap de feedback reportado por pilotos (send_text, Regla #13)
Anti-Corruption Layer (ACL) read-only hacia el MySQL legacy de REYVA. Único componente con acceso al legacy; traduce schema legacy al modelo nuevo de la plataforma. NO maneja TurboCarga (vive en svc-recharge) ni vinculación con operadora (vive en svc-vinculacion).
- ✅ Bootstrap PR-A (scaffold Nest+Fastify+Drizzle, health + métricas, schema legacy_bridge.bridge_sync_state, Dockerfile + compose)
- ✅ PR-B: MySQL pool (charset utf8) + RPC subdistribuidor/vendedor + mapping operador/estatus/sim + cache Redis + TrustToken
- ✅ PR-C: RPC handlers inventario (find_by_dn + is_assigned con filtro dn != 0)
- ✅ PR-D: scheduler full-scan + diff contra snapshot Postgres + publisher reyva.legacy.*.changed (JetStream + dedup por content_hash)
- ✅ PR-E: hardening (mysql_user_is_read_only probe + circuit breaker + runbook)
- ✅ Tests unit (96/96 verdes — adapter + use-cases + sync + hardening)
- ✅ S5.3: SyncVendedoresJob (snapshot vendedor + cron 5min + publisher reyva.legacy.vendedor.changed) — habilita listado vendedores en panel "Contactos del bot"
- ✅ S5.2: endpoint admin POST /v1/admin/sync/replay-subdistribuidores (backfill one-shot 58k subdistribuidores → events `reyva.legacy.subdistribuidor.changed` para hydrate business_subjects en svc-identity tras S5.1)
- ✅ S5.4: POST /v1/admin/sync/replay-vendedores (TrustTokenGuard HMAC) — backfill on-demand re-publica events para los 633 vendedores cuando el consumer downstream arranca tras dedup window
- ✅ ADR-0058: conector write segregado (GRANTs ⊆ INSERT TURBOCARGA + UPDATE INVENTARIO, guard legacy_write_grants_compliant) + 4 RPCs de reserva pesimista (inventario.reserve/release, turbocarga.register, sku.resolve) — anti doble-cargo bot↔portal
Lectura read-only del inventario REYVA legacy. Verifica que cada línea consultada por el bot pertenezca al inventario activo de REYVA antes de procesar cualquier recarga.
- ✅ Esquema DB y migraciones
- ✅ Bootstrap MVP (mock provider determinístico, GET /v1/inventory/lines/:dn, TrustToken, audit log phone_hash SHA-256)
- ✅ API REST/gRPC implementada
- ✅ Schema inventory.sims (status enum available→reserved→sold + reserva TTL, Ola 2)
- ✅ Endpoints POST /v1/sims/:id/{reserve,unreserve,mark-sold} consumidos por saga (Ola 2)
- ✅ GET /v1/sims/by-phone/:phone lookup local (Ola 2)
- ✅ GET /v1/sims?status=sold&since= paginado cursor-based (ADR-0050 §6 — base para anomaly detection svc-recharge)
- ✅ LegacyBridgeInventoryProvider reemplaza mock (ADR-0013, Ola 2)
- ✅ RPC subjects en svc-legacy-bridge reyva.legacy.inventario.* (PR-B mergeado)
- ✅ Job liberación reservas expiradas BullMQ @Cron cada 5min + evento NATS reservation_expired (Ola 2)
- ✅ Lectura read-through vía svc-legacy-bridge
- ⏳ Tests integración contra réplica MySQL legacy (Ola 2)
- ⏳ Tests integración + e2e
- ⏳ Deploy staging
- ⏳ Deploy producción + canary
Verificación de vinculación con AT&T, Movistar y Unefon. Consulta a cada operadora si una línea está vinculada con su titular (requisito CRT 2026). Solo retorna sí/no — no almacena datos personales (LFPDPPP, ADR-0027).
- ✅ Scaffold NestJS + estructura hexagonal + value objects
- ✅ Puerto VinculacionProviderPort + registry por operadora (ADR-0051 §1)
- ✅ Use case check-vinculacion con métricas + emisión audit
- ✅ TrustTokenGuard HMAC + controllers HTTP
- ✅ Adapter AT&T scaffold con payload getClientesBiometricos
- ✅ Esquema vinculacion.query_log extendido (result/reason/elapsed_ms/saga_id) + retención 5y (ADR-0027, Ola 2)
- ✅ Endpoint admin GET /v1/admin/vinculacion/checks (RequirePermission Verificar, Ola 2)
- ✅ Job de retención 5y + migración phone_hmac HMAC-SHA256 (ADR-0027 addendum 2026-05-29, S2.11)
- ⏳ Spike AT&T: validar auth real contra sandbox/prod (Ola 2)
- ⏳ Spike Movistar: descubrir response shape contra QA (Ola 2)
- ✅ Adapter AT&T real WSNED (getClientesBiometricos, parseo robusto jsonResponse + 408, portado del legacy)
- ✅ Adapter Movistar real (GET enrolamiento, parseo enrolado, credenciales por env)
- ✅ Adapter Unefon real (reusa cliente WSNED de AT&T, operator propio)
- ✅ Credenciales/endpoints de operadoras por env (Secret Manager en prod, fail-fast prod+real, .env.legacy gitignored en dev)
- ⏳ Spike AT&T/Movistar: validar auth real contra sandbox/prod (requiere credenciales)
- ✅ Política fail-closed validada con tests (ADR-0051 §3)
- ⏳ Métricas + alertas unknown_rate > 5% por operador
- ✅ Integración saga svc-recharge paso 2 CHECK_VINCULACION
- ⏳ Tests integración + e2e contra sandbox/QA
- ⏳ Deploy staging
- ⏳ Deploy producción + canary
Trazabilidad interna de REYVA: registro permanente e inalterable de cada operación del sistema (recargas, validaciones, cambios de permisos, accesos, configuración). Cubre módulos actuales y futuros. Hash chain criptográfico + WORM en Cloud Storage (ADR-0033) — nadie, ni siquiera un administrador, puede borrar o alterar registros sin que sea detectable.
- ✅ Esquema DB y migraciones
- ✅ Hash chain HMAC + función append_event (ADR-0033 §1)
- ✅ Idempotencia exactly-once por envelope_event_id (ADR-0028)
- ✅ Verificación periódica de tampering (ADR-0033 §1.4)
- ✅ API POST /audit/events
- ✅ API GET /audit/events con filtros + paginación cursor-based
- ✅ Auth s2s ADR-0026 (X-User-Trust-Token)
- ✅ Export periódico a Cloud Storage WORM (ADR-0033 §2)
- ✅ Métricas Prometheus + endpoint /metrics
- ✅ Consumer reyva.identity.access (JetStream durable + Nats-Msg-Id dedup)
- ✅ Consumer reyva.identity.permission_changed: JetStream durable + Nats-Msg-Id dedup → hash chain (ADR-0055 FU-3)
- ✅ Tests integración + e2e (87 con docker-compose: postgres+nats)
- ✅ Cloud Run staging deploy (Fase 0)
- ✅ Application layer migrado a Result<T, E> (errores tipados, sin throw en use-cases/repos)
- ✅ docker-compose dev incluye svc-audit (Dockerfile dev tsx watch, puerto 47412, HMAC compartido con svc-identity para reverse-proxy P12)
- ✅ PII en payload hasheada/truncada (ip_hash + user_agent_truncated, audit P1-3 / ADR-0033 addendum 2026-05-29)
- ✅ Rotación trimestral de signing keys (cron 90d + NATS reyva.audit.signing_key_rotated, audit P0-4 / ADR-0033 §rotación)
- ✅ Deploy producción (Fase 2): bucket WORM reyva-audit-worm-prod retención 5a + export-to-worm + 2 consumers REYVA_IDENTITY + pantalla /admin/auditoria (Patrón B)
- ⏳ Lock del bucket WORM (is_locked=true) tras validar ventana lock-later
Pantalla en tiempo real de la operación (recargas hoy, bloqueadas, fallidas por operador), alertas inteligentes de negocio (operador caído, distribuidor con fallas, tasa de vinculación anómala) y paneles técnicos para soporte.
- ✅ Scaffold NestJS + Fastify + health probes (BFF stateless, ADR-0057)
- ✅ Cliente Prometheus API + consumer NATS read-only (ADR-0057)
- ✅ Métricas de negocio en tiempo real
- ✅ Reglas de alerta inteligente (SLOs ADR-0056)
- ✅ Alertas de negocio (operador caído) + publish reyva.monitoring.alert_triggered (ADR-0057 §5)
- ✅ Alerta no_traffic con horario operativo + heartbeat scheduler (ADR-0057 addendum)
- ✅ Pantalla /admin/monitor en el panel (Patrón B vía svc-identity, ADR-0057)
- ✅ Integración con Grafana (dashboard svc-monitoring + scrape target)
- ⏳ Tests integración + e2e
- ✅ Deploy staging
- ✅ Deploy producción (recharge-live por NATS; monitoreo técnico SLO diferido a Cloud Monitoring)
- ⏳ Monitoreo técnico SLO en prod vía Google Cloud Monitoring (trigger: módulo infra-observability)
Consulta histórica de cada recarga ejecutada vía bot: número, timestamp, operador, autor, resultado y transacción. Filtros por fecha, operador y punto de venta. Exportación a Excel/CSV.
- ✅ Scaffold NestJS + Fastify + health probes + bootstrap
- ✅ Esquema DB history.recharges + processed_events + migración (ADR-0052 §2.1)
- ✅ Consumer NATS proyección reyva.recharge.* con dedupe por event_id (ADR-0052 §1)
- ✅ API REST GET /history/recharges con filtros + paginación
- ✅ Exportación CSV/Excel streaming (límite 50k filas, ADR-0052 §2.1)
- ✅ Métricas Prometheus read_model_* (lag, processed, duration) (ADR-0052 §5)
- ✅ Job retención nocturno + pseudonimización PII >5 años (ADR-0052 §4)
- ✅ Tests unit consumer (mapeo + dedupe + outcomes)
- ✅ Auth s2s (reverse-proxy svc-identity → svc-history + enrichment display_name)
- ✅ Pantalla panel /admin/historial (tabla filtrable + export CSV/Excel)
- ✅ Test rebuild desde NATS — invariante idempotencia (ADR-0052 §3)
- ⏳ Tests integración consumer + e2e proyección end-to-end
- ✅ Deploy staging
- ✅ Deploy producción
Resúmenes automáticos diarios, semanales y mensuales en PDF. Comparativas contra periodos anteriores. Envío automático por email a stakeholders configurados, sin necesidad de entrar al sistema.
- ✅ Servicio read-model on-demand (registry + serializers Excel/PDF)
- ✅ Reportes semilla: desempeño por distribuidor + resumen diario
- ✅ Evento reyva.reports.generated a NATS (auditoría)
- ✅ Tests unitarios (registry, serializers, transformaciones)
- ✅ Auth s2s (reverse-proxy svc-identity → svc-reports con trust token)
- ✅ Pantalla panel /admin/reportes (selector plantilla + filtros + descarga Excel/PDF)
- ⏳ Schedule via BullMQ (ADR-0024) — Ola 4
- ⏳ Envío email vía svc-notifications — Ola 4
- ✅ Deploy staging
- ✅ Deploy producción
Vista de actividad por punto de venta o subdistribuidor: recargas hechas, monto, tasa de éxito, última actividad. Distingue subdistribuidor vs vendedor (rol de primera clase) y el status administrativo (active/inactive/suspended).
- ✅ Scaffold NestJS + Fastify + health probes + bootstrap
- ✅ Schema DB (subject_dim + kpi_snapshots + recharge_ref + processed_events) + migración (ADR-0052 §2.3)
- ✅ Consumer NATS agregación KPIs por (distribuidor, día, fuente) + tabla puente para tasa de éxito
- ✅ Dimensión local rol+status: seed de business_subjects + consumer business_subject_changed
- ✅ Distinción subdistribuidor/vendedor (rol best-effort; resuelto en read-time vía COALESCE, no bloquea la persistencia del hecho)
- ✅ Columna source extensible (whatsapp_bot + futuras fuentes sin migración)
- ✅ API REST GET /distributors/ranking + /:id/kpis con filtro por rol
- ✅ Métricas Prometheus read_model_* + tests unit consumer
- ✅ Rebuild desde NATS (script rebuild-from-nats + test de integración del invariante, ADR-0052 §3)
- ✅ Auth s2s (reverse-proxy svc-identity → svc-distributors con trust token)
- ✅ Pantalla panel /admin/distribuidores (ranking con filtros + semaforización)
- ⏳ Tests e2e (panel admin Inteligencia de negocio)
- ⏳ Contador vinculacion_blocked (requiere evento reyva.vinculacion.checked, pendiente)
- ✅ Deploy staging
- ✅ Deploy producción
Avisos automáticos por email a puntos de venta, distribuidores y dirección (recarga ejecutada por monitoreo, línea no vinculada a tiempo, corte diario de pendientes, fallas de operador, recordatorios). Mensajes masivos / por segmento y notificaciones configurables. WhatsApp se reserva al bot de venta.
- ✅ Scaffold NestJS + Fastify + health probes + bootstrap
- ✅ Esquema DB notifications.templates + migración (ADR-0053)
- ✅ Sync de estado de plantillas desde Meta (consumer NATS + Graph API) + endpoint admin
- ✅ Panel admin reapuntado a svc-notifications (rejection_reason real, sin mock)
- ✅ Sync automático de plantillas (scheduler 6h + botón real + last_synced_at visible, ADR-0053)
- ⏳ Plantillas WhatsApp aprobadas por Meta
- ⏳ Canal email: proveedor de envío (infra notificación por correo)
- ⏳ Consumidor de eventos monitor (recarga OK / expirado) → email al vendedor
- ⏳ Corte diario por vendedor (pendientes de monitoreo) → email
- ⏳ Envío de reportes svc-reports por email a dirección
- ✅ Worker de envío BullMQ + opt-out + error policies (ADR-0053, flag META_SEND_ENABLED)
- ✅ API REST POST /send + consumer NATS reyva.notification.requested
- ✅ Emisor recarga_fallida_retry (svc-recharge → reyva.notification.requested, fuera ventana 24h)
- ⏳ Tests integración + e2e
- ⏳ Deploy staging
- ⏳ Deploy producción + canary