Grafo Salir
⚙️ service draft critical 👤 ❓ Pendiente de asignar 📅 Wed Feb 18 2026 21:00:00 GMT-0300 (Chile Summer Time)
Framework
Phoenix 1.5.14
Runtime
Elixir 1.13.3 (OTP 24)
Deploy
kubernetes
Entorno
prod

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)

ServicioMétodoEndpoint/Canal
Tótems físicos (semi on-premise)WebSocketoffices:{slug}, devices:{slug}:{device}
SVC-control-panelREST/api/v1/*, /api/v2/*, /api/v3/*
SVC-commandREST/dynasty/*
SVC-command-v2REST/api/v2/dynasty/*, /api/v3/dynasty/*
SVC-webapp-zeroqWebSocket + RESTweb:{slug}, /api/v1/*
SVC-turn-o-maticWebSocketvirtual:lobby
Clientes web (monitores/pantallas)WebSocketcommand:{slug}, admin:lobby
SVC-stats-frontREST/api/v1/state/*, /api/v2/state/*
SVC-botonera-webREST/api/v1/state/:officeSlug/lines (estado público de filas)

Downstream (servicios que este llama)

ServicioMétodoPropósito
INFRA-RabbitMQ (historical)AMQPPublicar eventos de tickets, calls, attentions, modulo_states, reserves
INFRA-RabbitMQ (broker)AMQPPublicar configuraciones de oficinas y eventos de sync
INFRA-New-RelicHTTP (log API)Envío de logs estructurados y reportes de eventos

Infraestructura

ComponenteUsoCrítico
INFRA-PostgreSQLPersistencia principal: oficinas, líneas, tickets, calls, ejecutivos, programas, dispositivos, reservas
INFRA-RedisÁrbol de estado (state tree), cache de configuraciones, sync timestamps, registry de IPs/paths, bloqueo de rutas, permisos de usuario
INFRA-RabbitMQBus de eventos: 2 instancias (historical en rabbitmq-historical.zeroq.cl, broker en broker.zeroq.cl)
INFRA-New-RelicLogging de requests, joins, eventos RabbitMQ y monitoreo de procesosNo
INFRA-KubernetesOrquestación, clustering de nodos Erlang vía DNS, balanceo de carga
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

  1. El tótem se conecta al canal WebSocket offices:{slug} con un token JWT.
  2. 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).
  3. La API consulta el last_sync desde Redis (sync:{slug}) y lo envía para que el tótem identifique eventos pendientes.
  4. El tótem busca eventos locales posteriores al last_sync y envía un evento sync con los datos faltantes.
  5. 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.*.
  6. 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)

  1. Cuando se crea/modifica una configuración en SVC-control-panel, la API recibe la petición REST y persiste en PostgreSQL.
  2. La API publica el cambio de configuración a INFRA-RabbitMQ con routing key zeroq.webapi.1.event.office.config.
  3. SVC-turn-o-matic consume el mensaje y aplica la nueva configuración.
  4. Cuando SVC-turn-o-matic genera eventos (ticket:created, call:created, etc.), los envía al canal virtual:lobby por WebSocket.
  5. 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

  1. 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.
  2. Los endpoints /api/v{1,2,3}/state exponen este árbol (completo o filtrado por usuario).
  3. Los endpoints /dynasty y /api/v{2,3}/dynasty exponen un reflejo del state tree, utilizado por SVC-command (legacy) y SVC-command-v2.
  4. 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

DatoClasificaciónEncriptadoRetención
JWT tokens (usuario)InternoSí (HS512)30 días (TTL)
Credenciales de oficinaInternoNo (en PostgreSQL)Indefinida
Emails de usuarioPIINoIndefinida
IPs de clientesPIINo (registry en Redis)Temporal (Redis TTL)
SECRET_KEY_BASESecretoN/A (env var)N/A
Credenciales RabbitMQSecretoN/A (env var)N/A
Credenciales DBSecretoN/A (env var)N/A

Canales WebSocket

La API registra 9 canales WebSocket a través de UserSocket:

CanalTopic PatternPropósito
OfficeChanneloffices:*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.
DeviceChanneldevices:*Comunicación directa con dispositivos individuales (módulos/puestos de atención).
VirtualChannelvirtual:*Canal para sucursales cloud: recibe eventos de SVC-turn-o-matic y los reenvía a INFRA-RabbitMQ.
WebChannelweb:*Canal para clientes web (webapp): notificaciones de nuevos tickets.
CommandChannelcommand:*Canal para pantallas/monitores de sucursales: mensajes de chat y eco.
AdminChanneladmin:*Canal de administración: consultas de estado, eco entre nodos del cluster.
BlueQueenChannelblue_queen:*Canal de optimización: sincronización de estado y datos de optimización.
OverseerChanneloverseer:*Canal de supervisión: eco y monitoreo entre nodos.
EchoChannelecho:*Canal de pruebas/eco: similar a BlueQueen, usado para diagnóstico.

Eventos principales del OfficeChannel

EventoDirecciónDescripción
ticket:createdTótem → API → RabbitMQTicket creado en sucursal física
ticket:lostTótem → APITicket perdido/vencido
call:createdTótem → API → RabbitMQLlamada a atención de un ticket
call:finishedTótem → API → RabbitMQAtención finalizada
modulo:stateTótem → API → RabbitMQCambio de estado de un módulo/puesto
reserve:createdTótem → API → RabbitMQReserva confirmada
syncTótem → API → RabbitMQSincronización de eventos pendientes tras reconexión
reset:okAPI → TótemConfirmación de reset de sucursal
office:frozen / unfrozenAPI → TótemCongelamiento/descongelamiento de sucursal
device:reloadAPI → TótemSolicitud de recarga de dispositivo
preload_dataAPI → TótemEnvío de configuración completa al conectar

API REST Versionada

Versión 1 (/api/v1/)

GrupoEndpoints principalesDescripción
StateGET /state, GET /state/:id, GET /state/:id/*pathÁrbol de estado completo o por oficina, navegable por path
OfficesCRUD /offices, /offices/:idGestión de sucursales
LinesCRUD /offices/:id/linesGestión de líneas de atención
DevicesCRUD /offices/:id/devicesGestión de módulos/dispositivos
Tickets/offices/:id/ticketsGestión de tickets
PresencesGET /presences, GET /presences/nodesPresencia WebSocket por nodo
MetricsGET /metrics/endpoints, GET /metrics/popular, GET /metrics/errorsMétricas personalizadas
HealthGET /cpu_pct, GET /memory_info, GET /rabbitVerificaciones de salud
AdminPOST /block_path, POST /unblock_path, POST /block_ipBloqueo de rutas/IPs

Versión 2 (/api/v2/)

GrupoEndpoints principalesDescripción
StateGET /state, GET /state/complex, GET /state/:id/*pathEstado con variantes complejas
DynastyGET /dynasty, GET /dynasty/:id/*pathReflejo del state (para SVC-command)
OfficesGET /officesConsulta de oficinas
OrganizationsGET /organizationsConsulta de organizaciones

Versión 3 (/api/v3/)

GrupoEndpoints principalesDescripción
StateGET /state, GET /state/versions, GET /state/syncEstado con versionamiento y sync
DynastyGET /dynasty, POST /dynasty/replicate, POST /dynasty/genDynasty con replicación y generación
OfficesCRUD extendido con last_syncOficinas con sync info
OrganizationsGET /organizationsOrganizaciones
UserEndpoints de usuarioGestión de usuarios

Versión 4 (/api/v4/)

GrupoEndpoints principalesDescripción
Filter KeysGET /filter_keysClaves de filtro
User/OrgsGET /user/organizationsOrganizaciones del usuario
Dynasty AdEndpoints de dynasty adDynasty publicitario

Otros endpoints

EndpointDescripción
GET /metricsPrometheus metrics (scraping)
GET /dynasty, GET /dynasty/:id/*pathDynasty legacy (raíz, sin versionamiento)
/api/dashboardPhoenix LiveDashboard (protegido con basic auth)

Colas RabbitMQ

Producción de mensajes (Publish)

Routing KeyPropósitoOrigen
zeroq.webapi.1.event.ticket.createdTicket creadoOfficeChannel / Sync
zeroq.webapi.1.event.call.finishedAtención finalizadaOfficeChannel / Sync
zeroq.webapi.1.event.attention.finishedAtención completadaOfficeChannel / Sync
zeroq.webapi.1.event.modulo_state.createdCambio de estado de móduloOfficeChannel / Sync
zeroq.webapi.1.event.reserves.confirmedReserva confirmadaOfficeChannel / Sync
zeroq.webapi.1.event.callsEventos de llamadasOfficeChannel
zeroq.webapi.1.event.attentionsEventos de atencionesOfficeChannel
zeroq.webapi.1.event.office.configCambio de configuración de oficinaControlPanel publisher
zeroq.webapi.1.event.office.sync.infoInfo de sincronizaciónInfoSync publisher
zeroq.webapi.1.event.async.dataDatos asíncronosAppSync service

Productores (GenServer / GenStage)

MóduloTipoFunción
Zeroq.AMQP.BrokerProducerGenStageProductor principal de eventos al broker
Zeroq.AMQP.HistoricalGenStageProductor de eventos históricos
Zeroq.Services.Rabbit.ProducerGenServerProductor de mensajes RabbitMQ
Zeroq.Services.Rabbit.BrokerGenServerPublisher al broker
Zeroq.Services.Rabbit.ControlPanelGenServerPublisher de configuraciones
Zeroq.Services.Rabbit.InfoSyncGenServerPublisher de info de sync
Zeroq.Services.Rabbit.LegatorGenServerPublisher a cola legator
Zeroq.Services.HistoricalGenServerBroker de datos históricos
Zeroq.Processes.Records.SenderGenServerEnví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

EscenarioImpactoMitigaciónSeveridad
INFRA-PostgreSQL caídoSin 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ídoSin 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ídoEventos 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 WebSocketTotem opera offline localmente.Al reconectarse: preload_data + last_sync para recuperar el estado y sincronizar eventos pendientes.Medio
Nodo Erlang cae en el clusterTráfico se redistribuye a otros nodos.libcluster con Kubernetes DNS rebalancea automáticamente. PubSub.PG2 propaga estado entre nodos.Medio
INFRA-New-Relic caídoSin 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étricaTipoFuente
http_requests_totalCounterEndpointMonitor (custom)
http_request_durationHistogramEndpointMonitor (custom)
http_errorsCounterEndpointMonitor (custom)
authenticated_requestsCounterEndpointMonitor (custom)
active_requestsGaugeEndpointMonitor (custom)
ticket_operationsCounterEndpointMonitor (custom)
office_operationsCounterEndpointMonitor (custom)
line_operationsCounterEndpointMonitor (custom)
device_operationsCounterEndpointMonitor (custom)
Phoenix controller durationHistogramprometheus_phoenix (buckets en microsegundos)
Pipeline durationHistogramprometheus_plugs (por status_class, method, host, path)
Ecto query durationHistogramprometheus_ecto
VM memory/IOGaugetelemetry_poller (cada 10s)
MétricaUmbral de alertaDashboard
Latencia de request p99Prometheus / LiveDashboard
Tasa de erroresPrometheus
Uso de CPU80% (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:

  1. Plug.Telemetry — Instrumentación
  2. Phoenix.LiveDashboard.RequestLogger — Logging para dashboard
  3. Plug.Static — Archivos estáticos
  4. Plug.RequestId — ID único por request
  5. Corsica — CORS
  6. Plug.Logger — Logging HTTP
  7. Zeroq.Web.Plugs.EndpointMonitorPlug — Métricas de request (duración, status, usuario, operaciones de dominio)
  8. Plug.Parsers — Parsing JSON/URL/Multipart
  9. Plug.MethodOverride — Override de método HTTP
  10. Plug.Head — Soporte HEAD
  11. Plug.Session — Sesiones
  12. Zeroq.Metric.PrometheusExporter — Exposición de métricas Prometheus
  13. Zeroq.Metric.PipelineInstrumenter — Instrumentación del pipeline
  14. Zeroq.Auth — Decodificación y validación de JWT (Guardian, HS512)
  15. Zeroq.Scoper — Extracción de contexto (office, organization, user)
  16. Zeroq.Security — Validación de privilegios (admin/supervisor)
  17. Zeroq.Filter — Filtrado de oficinas por permisos del usuario
  18. 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

  • Autenticación requerida (JWT vía Guardian, HS512, TTL 30 días)
  • Autorización por roles (RBAC: validación de privilegios admin/supervisor en Security plug)
  • Rate limiting configurado (no implementado; existe bloqueo manual de IPs/paths vía Redis)
  • Validación de entrada implementada (Skooma wrapper + Ecto Changesets + validaciones custom)
  • Datos sensibles encriptados en reposo
  • Datos sensibles encriptados en tránsito (TLS vía Ingress/IngressRoute en Kubernetes)
  • Logging de auditoría habilitado (logs de requests pero no audit trail dedicado)
  • No expone datos internos en errores (ErrorView retorna mensajes genéricos: “not found”, “server error”)
  • CORS configurado (vía Corsica)
  • Autenticación JWT en canales WebSocket (token verificado en join)

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

EntornoNamespaceMIX_ENVIngress HostBranch CI
Desarrollolablabdev.zeroq.cldevelop
QAstagingqaqa.zeroq.clqa
QA Pichinchaqa-bppichinchabp.zeroq.cl
Producciónprod

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

Dataview LIST
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