SVC-webapi-v2
Descripción General
API principal de ZeroQ. Servicio central que gestiona la comunicación en tiempo real con los tótems físicos (semi on-premise) vía WebSocket, expone una API RESTful versionada (v1–v4) para el backoffice (SVC-control-panel) y otros servicios internos, y mantiene un árbol de estado (state tree) en Redis con el snapshot en tiempo real de cada sucursal (líneas, módulos, opciones, ejecutivos, etc.).
Históricamente ha sido el servicio con mayor responsabilidad en la plataforma ZeroQ. Progresivamente se le ha ido descargando responsabilidad hacia microservicios especializados, con la visión de que a futuro quede enfocado como API RESTful para backoffice y configuración de sucursales.
Propósito
¿Por qué existe este servicio? ¿Qué problema de negocio resuelve?
- Problema que resuelve: Centralizar la gestión de estado y configuración de todas las sucursales (físicas y cloud), coordinar la comunicación en tiempo real con tótems/dispositivos, y servir como hub de eventos que alimenta al resto de la plataforma vía INFRA-RabbitMQ.
- Usuarios/consumidores principales: Tótems físicos (WebSocket), SVC-control-panel (REST), SVC-command y SVC-command-v2 (dynasty REST), SVC-turn-o-matic (eventos vía RabbitMQ), SVC-webapp-zeroq (WebSocket/REST), consumidores históricos de RabbitMQ.
- Alternativa si no existiera: Cada servicio tendría que gestionar directamente el estado de las sucursales y la comunicación con dispositivos, duplicando lógica y eliminando la fuente única de verdad del estado.
Resumen de Arquitectura
graph TB
subgraph Upstream
TOTEMS[Tótems físicos<br/>semi on-premise]
CP[SVC-control-panel<br/>backoffice]
CMD[SVC-command / SVC-command-v2]
TOM[SVC-turn-o-matic]
WEBAPP[SVC-webapp-zeroq]
STATS[SVC-stats-front]
BOT[SVC-botonera-web]
DISPLAYS[Pantallas / Monitores]
end
subgraph WEBAPI [SVC-webapi · Phoenix/Elixir :4000]
REST[REST API v1-v4]
WS[WebSocket Channels]
DYNASTY[Dynasty Controller]
VIRTUAL[VirtualChannel]
end
subgraph Infraestructura
PG[(INFRA-PostgreSQL<br/>Fuente de verdad)]
REDIS[(INFRA-Redis<br/>State tree · Cache · Sync)]
RABBIT[INFRA-RabbitMQ<br/>historical + broker]
ETS[ETS Caches<br/>L1 in-memory]
NR[INFRA-New-Relic]
end
TOTEMS <-->|WS offices:*| WS
CP -->|REST /api/v1-v4| REST
CMD -->|REST /dynasty| DYNASTY
TOM <-->|WS virtual:lobby| VIRTUAL
WEBAPP -->|WS web:* + REST| WEBAPI
STATS -->|REST /api/v1/state| REST
BOT -->|REST /api/v1/state| REST
DISPLAYS -->|WS command:*| WS
WEBAPI --> PG
WEBAPI --> REDIS
WEBAPI -->|publish eventos| RABBIT
WEBAPI --> ETS
WEBAPI --> NR
- Tipo: service
- Lenguaje/Framework: Elixir / Phoenix 1.5.14
- Runtime: Elixir 1.13.3 (OTP 24.3.4.17)
- Destino de despliegue: Kubernetes (Helm chart v1.4.2, AWS EKS)
- Puerto: 4000
- Protocolo: HTTP/REST + WebSocket
- Réplicas en prod: ❓ Pendiente de verificar (clustering habilitado vía libcluster con estrategia Kubernetes DNS)
- Versión de app: 5.0.1
Dependencias
Upstream (servicios que llaman a este)
| Servicio | Método | Endpoint/Canal |
|---|
| Tótems físicos (semi on-premise) | WebSocket | offices:{slug}, devices:{slug}:{device} |
| SVC-control-panel | REST | /api/v1/*, /api/v2/*, /api/v3/* |
| SVC-command | REST | /dynasty/* |
| SVC-command-v2 | REST | /api/v2/dynasty/*, /api/v3/dynasty/* |
| SVC-webapp-zeroq | WebSocket + REST | web:{slug}, /api/v1/* |
| SVC-turn-o-matic | WebSocket | virtual:lobby |
| Clientes web (monitores/pantallas) | WebSocket | command:{slug}, admin:lobby |
| SVC-stats-front | REST | /api/v1/state/*, /api/v2/state/* |
| SVC-botonera-web | REST | /api/v1/state/:officeSlug/lines (estado público de filas) |
Downstream (servicios que este llama)
| Servicio | Método | Propósito |
|---|
| INFRA-RabbitMQ (historical) | AMQP | Publicar eventos de tickets, calls, attentions, modulo_states, reserves |
| INFRA-RabbitMQ (broker) | AMQP | Publicar configuraciones de oficinas y eventos de sync |
| INFRA-New-Relic | HTTP (log API) | Envío de logs estructurados y reportes de eventos |
Infraestructura
| Componente | Uso | Crítico |
|---|
| INFRA-PostgreSQL | Persistencia principal: oficinas, líneas, tickets, calls, ejecutivos, programas, dispositivos, reservas | Sí |
| INFRA-Redis | Árbol de estado (state tree), cache de configuraciones, sync timestamps, registry de IPs/paths, bloqueo de rutas, permisos de usuario | Sí |
| INFRA-RabbitMQ | Bus de eventos: 2 instancias (historical en rabbitmq-historical.zeroq.cl, broker en broker.zeroq.cl) | Sí |
| INFRA-New-Relic | Logging de requests, joins, eventos RabbitMQ y monitoreo de procesos | No |
| INFRA-Kubernetes | Orquestación, clustering de nodos Erlang vía DNS, balanceo de carga | Sí |
| ETS (in-memory) | Caché L1 para Office, State, Category, Organization (TTL 600s configurable) | No (degradación graceful) |
Flujo de Datos
Flujo 1: Totem físico conecta y sincroniza
- El tótem se conecta al canal WebSocket
offices:{slug} con un token JWT.
- Al unirse (
join), la API verifica el token, carga la oficina desde PostgreSQL/Redis y envía el preload_data con toda la configuración actual (líneas, dispositivos, segmentos, reservas, programas, contadores).
- La API consulta el
last_sync desde Redis (sync:{slug}) y lo envía para que el tótem identifique eventos pendientes.
- El tótem busca eventos locales posteriores al
last_sync y envía un evento sync con los datos faltantes.
- La API procesa los eventos de sync (tickets, calls, attentions, modulo_states, reserves) y los publica en INFRA-RabbitMQ con routing keys
zeroq.webapi.1.event.*.
- Los consumidores downstream procesan y persisten los eventos en INFRA-MongoDB (vía servicios de consumo histórico).
Flujo 2: Sucursal Cloud (Turn-o-matic)
- Cuando se crea/modifica una configuración en SVC-control-panel, la API recibe la petición REST y persiste en PostgreSQL.
- La API publica el cambio de configuración a INFRA-RabbitMQ con routing key
zeroq.webapi.1.event.office.config.
- SVC-turn-o-matic consume el mensaje y aplica la nueva configuración.
- Cuando SVC-turn-o-matic genera eventos (ticket:created, call:created, etc.), los envía al canal
virtual:lobby por WebSocket.
- El
VirtualChannel de la API recibe estos eventos y los reenvía a una cola de INFRA-RabbitMQ para consumo histórico.
Flujo 3: State Tree y Dynasty
- La API construye un árbol de estado gigante en Redis con el snapshot de cada sucursal: oficina base, líneas, módulos, opciones, ubicación, ejecutivos, estadísticas, programas.
- Los endpoints
/api/v{1,2,3}/state exponen este árbol (completo o filtrado por usuario).
- Los endpoints
/dynasty y /api/v{2,3}/dynasty exponen un reflejo del state tree, utilizado por SVC-command (legacy) y SVC-command-v2.
- El state se puede navegar por path:
/api/v1/state/:id/lines/linea-1/modulos para acceder a nodos específicos del árbol.
Datos sensibles manejados
| Dato | Clasificación | Encriptado | Retención |
|---|
| JWT tokens (usuario) | Interno | Sí (HS512) | 30 días (TTL) |
| Credenciales de oficina | Interno | No (en PostgreSQL) | Indefinida |
| Emails de usuario | PII | No | Indefinida |
| IPs de clientes | PII | No (registry en Redis) | Temporal (Redis TTL) |
| SECRET_KEY_BASE | Secreto | N/A (env var) | N/A |
| Credenciales RabbitMQ | Secreto | N/A (env var) | N/A |
| Credenciales DB | Secreto | N/A (env var) | N/A |
Canales WebSocket
La API registra 9 canales WebSocket a través de UserSocket:
| Canal | Topic Pattern | Propósito |
|---|
OfficeChannel | offices:* | Canal principal: comunicación bidireccional con tótems físicos. Gestiona preload_data, sync, eventos de tickets/calls/módulos, resets, congelamiento de líneas. |
DeviceChannel | devices:* | Comunicación directa con dispositivos individuales (módulos/puestos de atención). |
VirtualChannel | virtual:* | Canal para sucursales cloud: recibe eventos de SVC-turn-o-matic y los reenvía a INFRA-RabbitMQ. |
WebChannel | web:* | Canal para clientes web (webapp): notificaciones de nuevos tickets. |
CommandChannel | command:* | Canal para pantallas/monitores de sucursales: mensajes de chat y eco. |
AdminChannel | admin:* | Canal de administración: consultas de estado, eco entre nodos del cluster. |
BlueQueenChannel | blue_queen:* | Canal de optimización: sincronización de estado y datos de optimización. |
OverseerChannel | overseer:* | Canal de supervisión: eco y monitoreo entre nodos. |
EchoChannel | echo:* | Canal de pruebas/eco: similar a BlueQueen, usado para diagnóstico. |
Eventos principales del OfficeChannel
| Evento | Dirección | Descripción |
|---|
ticket:created | Tótem → API → RabbitMQ | Ticket creado en sucursal física |
ticket:lost | Tótem → API | Ticket perdido/vencido |
call:created | Tótem → API → RabbitMQ | Llamada a atención de un ticket |
call:finished | Tótem → API → RabbitMQ | Atención finalizada |
modulo:state | Tótem → API → RabbitMQ | Cambio de estado de un módulo/puesto |
reserve:created | Tótem → API → RabbitMQ | Reserva confirmada |
sync | Tótem → API → RabbitMQ | Sincronización de eventos pendientes tras reconexión |
reset:ok | API → Tótem | Confirmación de reset de sucursal |
office:frozen / unfrozen | API → Tótem | Congelamiento/descongelamiento de sucursal |
device:reload | API → Tótem | Solicitud de recarga de dispositivo |
preload_data | API → Tótem | Envío de configuración completa al conectar |
API REST Versionada
Versión 1 (/api/v1/)
| Grupo | Endpoints principales | Descripción |
|---|
| State | GET /state, GET /state/:id, GET /state/:id/*path | Árbol de estado completo o por oficina, navegable por path |
| Offices | CRUD /offices, /offices/:id | Gestión de sucursales |
| Lines | CRUD /offices/:id/lines | Gestión de líneas de atención |
| Devices | CRUD /offices/:id/devices | Gestión de módulos/dispositivos |
| Tickets | /offices/:id/tickets | Gestión de tickets |
| Presences | GET /presences, GET /presences/nodes | Presencia WebSocket por nodo |
| Metrics | GET /metrics/endpoints, GET /metrics/popular, GET /metrics/errors | Métricas personalizadas |
| Health | GET /cpu_pct, GET /memory_info, GET /rabbit | Verificaciones de salud |
| Admin | POST /block_path, POST /unblock_path, POST /block_ip | Bloqueo de rutas/IPs |
Versión 2 (/api/v2/)
| Grupo | Endpoints principales | Descripción |
|---|
| State | GET /state, GET /state/complex, GET /state/:id/*path | Estado con variantes complejas |
| Dynasty | GET /dynasty, GET /dynasty/:id/*path | Reflejo del state (para SVC-command) |
| Offices | GET /offices | Consulta de oficinas |
| Organizations | GET /organizations | Consulta de organizaciones |
Versión 3 (/api/v3/)
| Grupo | Endpoints principales | Descripción |
|---|
| State | GET /state, GET /state/versions, GET /state/sync | Estado con versionamiento y sync |
| Dynasty | GET /dynasty, POST /dynasty/replicate, POST /dynasty/gen | Dynasty con replicación y generación |
| Offices | CRUD extendido con last_sync | Oficinas con sync info |
| Organizations | GET /organizations | Organizaciones |
| User | Endpoints de usuario | Gestión de usuarios |
Versión 4 (/api/v4/)
| Grupo | Endpoints principales | Descripción |
|---|
| Filter Keys | GET /filter_keys | Claves de filtro |
| User/Orgs | GET /user/organizations | Organizaciones del usuario |
| Dynasty Ad | Endpoints de dynasty ad | Dynasty publicitario |
Otros endpoints
| Endpoint | Descripción |
|---|
GET /metrics | Prometheus metrics (scraping) |
GET /dynasty, GET /dynasty/:id/*path | Dynasty legacy (raíz, sin versionamiento) |
/api/dashboard | Phoenix LiveDashboard (protegido con basic auth) |
Colas RabbitMQ
Producción de mensajes (Publish)
| Routing Key | Propósito | Origen |
|---|
zeroq.webapi.1.event.ticket.created | Ticket creado | OfficeChannel / Sync |
zeroq.webapi.1.event.call.finished | Atención finalizada | OfficeChannel / Sync |
zeroq.webapi.1.event.attention.finished | Atención completada | OfficeChannel / Sync |
zeroq.webapi.1.event.modulo_state.created | Cambio de estado de módulo | OfficeChannel / Sync |
zeroq.webapi.1.event.reserves.confirmed | Reserva confirmada | OfficeChannel / Sync |
zeroq.webapi.1.event.calls | Eventos de llamadas | OfficeChannel |
zeroq.webapi.1.event.attentions | Eventos de atenciones | OfficeChannel |
zeroq.webapi.1.event.office.config | Cambio de configuración de oficina | ControlPanel publisher |
zeroq.webapi.1.event.office.sync.info | Info de sincronización | InfoSync publisher |
zeroq.webapi.1.event.async.data | Datos asíncronos | AppSync service |
Productores (GenServer / GenStage)
| Módulo | Tipo | Función |
|---|
Zeroq.AMQP.BrokerProducer | GenStage | Productor principal de eventos al broker |
Zeroq.AMQP.Historical | GenStage | Productor de eventos históricos |
Zeroq.Services.Rabbit.Producer | GenServer | Productor de mensajes RabbitMQ |
Zeroq.Services.Rabbit.Broker | GenServer | Publisher al broker |
Zeroq.Services.Rabbit.ControlPanel | GenServer | Publisher de configuraciones |
Zeroq.Services.Rabbit.InfoSync | GenServer | Publisher de info de sync |
Zeroq.Services.Rabbit.Legator | GenServer | Publisher a cola legator |
Zeroq.Services.Historical | GenServer | Broker de datos históricos |
Zeroq.Processes.Records.Sender | GenServer | Envío de registros |
Nota: El consumer (Zeroq.Services.Rabbit.Consumer) está comentado/deshabilitado. La API actúa principalmente como productor de mensajes, no como consumidor.
Árbol de Supervisión (OTP)
Zeroq.Supervisor (one_for_one)
├── Zeroq.Repo (PostgreSQL via Ecto)
├── Phoenix.PubSub (PG2 adapter, nombre: Zeroq.PubSub)
├── Redix (conexión Redis)
├── Zeroq.AMQP.BrokerProducer (GenStage)
├── Zeroq.API.V1.Rabbit (consumer/listener)
├── Cluster.Supervisor (libcluster, Kubernetes DNS)
├── Zeroq.Services.Supervisor
│ ├── Zeroq.API.V1.Timey (tracking temporal)
│ └── Zeroq.API.V1.Watcher (health check Redis cada 1s)
├── Zeroq.Cache.Supervisor
│ ├── Office.Cache (ETS, TTL 7200s/600s configurable)
│ ├── State.Cache (ETS, TTL 7200s/600s configurable)
│ ├── CategoryCache (ETS, TTL 7200s)
│ └── OrganizationCache (ETS, TTL 7200s)
├── Zeroq.Telemetry
├── Zeroq.Endpoint (Phoenix HTTP/WebSocket, puerto 4000)
└── ZeroqWeb.Presence (tracking de presencia WebSocket)
Supervisor de RabbitMQ
Zeroq.Supervisors.Rabbit
├── Zeroq.Services.Rabbit (handler principal)
├── Zeroq.Services.Rabbit.Broker
├── Zeroq.Services.Rabbit.Producer
├── Zeroq.Services.Rabbit.ControlPanel
├── Zeroq.Services.Rabbit.InfoSync
├── Zeroq.Services.Rabbit.Sync
└── Zeroq.Processes.Records.Sender
Almacenamiento Multi-capa
graph LR
PG[(INFRA-PostgreSQL<br/>Fuente de verdad)] -->|Ecto queries| REDIS[(INFRA-Redis<br/>Hot data + State tree)]
REDIS -->|Cache miss fill| ETS[ETS Cache<br/>L1 in-memory · TTL 600s]
ETS -->|Serve| STATE[State Tree<br/>API /state + /dynasty]
- PostgreSQL: Fuente de verdad. Tablas: offices, lines, calls, tickets, devices, executives, reserves, informations, programs, counters, modulos_states, users.
- Redis: Almacena el state tree (
office:{slug}, office:{slug}:lines:*, office:{slug}:modulos, etc.), timestamps de sync (sync:{slug}), permisos de usuario, registry de IPs, bloqueo de rutas.
- ETS: Caché in-memory L1 con TTL configurable para Office, State, Category y Organization. Reduce la carga a Redis/PostgreSQL.
- State Tree: Construido desde Redis, expuesto por los controllers de
/state y /dynasty.
Modos de Falla
| Escenario | Impacto | Mitigación | Severidad |
|---|
| INFRA-PostgreSQL caído | Sin persistencia de cambios. API no puede cargar configuración de oficinas. | Caché ETS y Redis mantienen datos temporalmente. Reconexión automática vía Ecto. | Crítico |
| INFRA-Redis caído | Sin state tree, sin sync, sin caché. Degradación severa. | Watcher verifica Redis cada 1s. Reconstrucción desde PostgreSQL posible pero lenta. | Crítico |
| INFRA-RabbitMQ caído | Eventos no se publican. Consumidores no reciben datos históricos. | GenServers con reconexión automática cada 5s (Process.send_after(:reconnect, 5000)). Eventos se pierden durante la desconexión. | Alto |
| Totem pierde conexión WebSocket | Totem opera offline localmente. | Al reconectarse: preload_data + last_sync para recuperar el estado y sincronizar eventos pendientes. | Medio |
| Nodo Erlang cae en el cluster | Tráfico se redistribuye a otros nodos. | libcluster con Kubernetes DNS rebalancea automáticamente. PubSub.PG2 propaga estado entre nodos. | Medio |
| INFRA-New-Relic caído | Sin logging externo. | No crítico; logs locales siguen funcionando vía Logger console. | Bajo |
Política de Reintentos / Circuit Breaker
- Intentos de reintento: Los GenServers de RabbitMQ implementan reconexión periódica cada 5 segundos (
Process.send_after(self(), :reconnect, 5000))
- Estrategia de backoff: Fija (5s), sin backoff exponencial
- Umbral de circuit breaker: No implementado
- Comportamiento de fallback: Los eventos se pierden durante desconexión de RabbitMQ. Los tótems mantienen eventos localmente y los envían al reconectarse vía sync.
Monitoreo
Health Check
- Endpoint de CPU:
GET /api/v1/cpu_pct (retorna 200 si CPU < umbral, 500 si excede; umbral configurable vía env CPU_PCT, default 80%)
- Endpoint de memoria:
GET /api/v1/memory_info (requiere auth)
- Endpoint RabbitMQ:
GET /api/v1/rabbit (verifica estado de conexión AMQP)
- Prometheus:
GET /metrics (scraping de métricas)
- LiveDashboard:
GET /api/dashboard (protegido con basic auth)
- Liveness/Readiness probes: Configurados en Helm values pero vacíos (
{}) — ❓ Pendiente de verificar implementación real en el chart
Métricas clave
| Métrica | Tipo | Fuente |
|---|
http_requests_total | Counter | EndpointMonitor (custom) |
http_request_duration | Histogram | EndpointMonitor (custom) |
http_errors | Counter | EndpointMonitor (custom) |
authenticated_requests | Counter | EndpointMonitor (custom) |
active_requests | Gauge | EndpointMonitor (custom) |
ticket_operations | Counter | EndpointMonitor (custom) |
office_operations | Counter | EndpointMonitor (custom) |
line_operations | Counter | EndpointMonitor (custom) |
device_operations | Counter | EndpointMonitor (custom) |
| Phoenix controller duration | Histogram | prometheus_phoenix (buckets en microsegundos) |
| Pipeline duration | Histogram | prometheus_plugs (por status_class, method, host, path) |
| Ecto query duration | Histogram | prometheus_ecto |
| VM memory/IO | Gauge | telemetry_poller (cada 10s) |
| Métrica | Umbral de alerta | Dashboard |
|---|
| Latencia de request p99 | ❓ | Prometheus / LiveDashboard |
| Tasa de errores | ❓ | Prometheus |
| Uso de CPU | 80% (configurable via CPU_PCT) | /api/v1/cpu_pct |
| Uso de memoria | ❓ | /api/v1/memory_info |
| Profundidad de cola RabbitMQ | ❓ | ❓ |
Logs
- Formato: Texto estructurado (
$date $time $metadata $message)
- Nivel por defecto:
:debug (prod), :info (Docker)
- Metadata:
[:module, :function] (prod), [:request_id, :user_id, :endpoint] (Docker)
- Backend: Console (stdout)
- Destino externo: INFRA-New-Relic (log API vía HTTPoison)
- Retención: ❓ Pendiente de verificar
Pipeline de Middlewares (Plugs)
Orden de ejecución en cada request HTTP:
Plug.Telemetry — Instrumentación
Phoenix.LiveDashboard.RequestLogger — Logging para dashboard
Plug.Static — Archivos estáticos
Plug.RequestId — ID único por request
Corsica — CORS
Plug.Logger — Logging HTTP
Zeroq.Web.Plugs.EndpointMonitorPlug — Métricas de request (duración, status, usuario, operaciones de dominio)
Plug.Parsers — Parsing JSON/URL/Multipart
Plug.MethodOverride — Override de método HTTP
Plug.Head — Soporte HEAD
Plug.Session — Sesiones
Zeroq.Metric.PrometheusExporter — Exposición de métricas Prometheus
Zeroq.Metric.PipelineInstrumenter — Instrumentación del pipeline
Zeroq.Auth — Decodificación y validación de JWT (Guardian, HS512)
Zeroq.Scoper — Extracción de contexto (office, organization, user)
Zeroq.Security — Validación de privilegios (admin/supervisor)
Zeroq.Filter — Filtrado de oficinas por permisos del usuario
Zeroq.Router — Enrutamiento a controllers
Plugs especiales en pipelines del Router
Zeroq.Regypath — Registra IPs y paths en Redis (pipeline :registry)
Zeroq.BlockerPath — Bloquea paths según registro en Redis (pipeline :blocker_path)
:admins_only — Basic auth para rutas admin (LiveDashboard)
Consideraciones de Seguridad
Estrategia de Escalamiento
- Tipo: Horizontal (clustering Erlang)
- Clustering: libcluster con estrategia Kubernetes DNS (
Cluster.Strategy.Kubernetes.DNS)
- Servicio headless:
webapi-v2-headless (para descubrimiento de nodos)
- Auto-scaling: ❓ Pendiente de verificar (HPA no definido en values)
- Réplicas mínimas: ❓ Pendiente de verificar
- Réplicas máximas: ❓ Pendiente de verificar
- Trigger de escalamiento: ❓ Pendiente de verificar
- Limitaciones conocidas: Estado en ETS es local por nodo (no compartido). Phoenix.PubSub.PG2 sincroniza broadcasts pero no estado de caché. Redis es el punto de convergencia para estado compartido entre nodos.
Entornos de Despliegue
| Entorno | Namespace | MIX_ENV | Ingress Host | Branch CI |
|---|
| Desarrollo | lab | lab | dev.zeroq.cl | develop |
| QA | staging | qa | qa.zeroq.cl | qa |
| QA Pichincha | qa-bp | pichincha | bp.zeroq.cl | ❓ |
| Producción | ❓ | prod | ❓ | ❓ |
CI/CD
- Plataforma: GitLab CI
- Build: Kaniko (sin Docker-in-Docker)
- Registry: AWS ECR
- Deploy: Helm upgrade via OCI chart (
zeroqchart v1.4.2)
- Chart externo:
oci://${AWS_ECR_HELM_REPOSITORY}
Consideraciones de DRP
- RTO: ❓ (Objetivo de Tiempo de Recuperación)
- RPO: ❓ (Objetivo de Punto de Recuperación)
- Estrategia de respaldo: PostgreSQL en AWS RDS con backups automáticos (inferido). Redis en ElastiCache (inferido).
- Failover automático: Clustering Erlang permite redistribución de tráfico si un nodo cae. PostgreSQL RDS cluster soporta failover (inferido).
- Resiliencia ante desconexión de tótems: El mecanismo de
preload_data + last_sync + sync permite recuperación completa del estado sin pérdida de datos.
- Runbook: PROC-DRP-webapi-v2
Servicios Relacionados
LIST
FROM "01-Architecture/Services"
WHERE contains(related_services, this.file.link)
Esta query se ejecuta dinámicamente en Obsidian.
Preguntas Abiertas
- ❓ Owner: Pendiente de asignar responsable del servicio
- ❓ Réplicas en producción: No se encontró configuración de réplicas en los values de Helm disponibles
- ❓ HPA (Auto-scaling): No hay HorizontalPodAutoscaler definido en los values; verificar si existe en el chart externo
- ❓ Liveness/Readiness probes: Los values de Helm definen probes vacíos (
{}); verificar configuración real en el chart base
- ❓ Entorno de producción: No se encontró
values_prod.yaml ni configuración CI para producción en el repositorio
- ❓ Retención de logs: No documentada
- ❓ Umbrales de alerta: No se encontraron alertas configuradas para latencia, errores o colas
- ❓ Rate limiting: No implementado; considerar agregar para endpoints públicos
- ❓ Circuit breaker: No implementado para conexiones a RabbitMQ/Redis/PostgreSQL; los GenServers reconectan con intervalo fijo
- ❓ Pérdida de eventos RabbitMQ: Durante desconexión del broker, los eventos publicados se pierden; evaluar buffer local o persistencia temporal
- ❓ Encriptación de datos sensibles en reposo: Credenciales de oficina y emails de usuario no están encriptados en PostgreSQL
- ❓ Audit trail: No existe un log de auditoría dedicado para cambios de configuración
- ❓ SECRET_KEY_BASE hardcodeado: Se detectó un
secret_key_base en config.exs y en el CI; verificar si se sobreescribe en producción vía env vars
- ❓ Tests: No se verificó la cobertura de tests del proyecto
- ❓ Consumer RabbitMQ deshabilitado: El módulo
Zeroq.Services.Rabbit.Consumer está comentado; verificar si fue reemplazado por otro mecanismo