Saltar a contenido

Documento histórico

Este documento se conserva solo para trazabilidad. Consulte el índice maestro para la fuente vigente.

Documento histórico — no usar como fuente de decisiones actuales

Reemplazado por la versión canónica del 2026-07-11. Conservar solo como trazabilidad histórica.


CU-015: Integración con agencia aliada (webhook + polling)

Caso de uso detallado para la integración con la agencia aliada en Cuba, incluyendo webhooks entrantes y sincronización de estado de envíos.


Metadatos

Campo Valor
ID CU-015
Nombre Integración con agencia aliada
Actor primario Sistema de Agencia (externo)
Actores secundarios Sistema de Notificaciones, Usuarios, Operadores
Módulo Despacho y envío
Prioridad Alta (MVP)
Frecuencia esperada Alta (decenas de eventos diarios)
Trazabilidad SRS RF-027, RF-028, RF-029, RN-104

Descripción

La agencia aliada en Cuba es la entidad que recibe los envíos de IslaBox en La Habana y los entrega a los destinatarios finales. La integración es bidireccional:

  • IslaBox → Agencia: envío de paquetes consolidados, generación de guía maestra, instrucción de entrega.
  • Agencia → IslaBox: notificaciones de cambios de estado (en aduana, liberado, en reparto, entregado), confirmaciones, excepciones.

Este caso de uso cubre los 3 modos de integración soportados:

  1. Webhook entrante (principal): la agencia notifica cambios de estado a IslaBox.
  2. API polling (secundario): IslaBox consulta periódicamente el estado de envíos activos.
  3. Outbound webhook (Fase 2): IslaBox notifica a la agencia de nuevas guías.

Precondiciones

  • Acuerdo comercial firmado con la agencia.
  • Configuración de AGENCY_API_URL, AGENCY_API_KEY, AGENCY_WEBHOOK_SECRET en el sistema.
  • La agencia expone un endpoint público con HTTPS válido.
  • El contrato de eventos está firmado por ambas partes (ver preguntas.md).

Postcondiciones

Éxito (webhook entrante): - shipment.status actualizado al nuevo estado. - shipment_events con timestamp y metadata de la agencia. - notifications enviadas al usuario. - audit_logs con el cambio.

Fallo: - HTTP 400 + log + reintento por parte de la agencia. - Alerta al equipo técnico si hay 3+ fallos consecutivos.


Flujo principal — webhook entrante de la agencia

  1. La agencia envía POST /api/v1/webhooks/agency con:
    {
      "event_id": "AGE-EVT-1234",
      "event_type": "shipment.status_changed",
      "timestamp": "2026-06-07T14:30:00Z",
      "data": {
        "master_guide": "ISB-2026-00042",
        "new_status": "liberado_de_aduana",
        "location": "Aduana Habana",
        "notes": "Liberado sin cargos adicionales"
      }
    }
    
  2. El sistema lee el header X-Agency-Signature.
  3. Verifica la firma HMAC-SHA256 con AGENCY_WEBHOOK_SECRET.
  4. Si la firma es inválida → HTTP 400 + log de seguridad.
  5. Busca el evento en webhook_events por event_id.
  6. Si ya existe y está procesado → HTTP 200 (idempotencia).
  7. Si no, lo inserta y procesa.
  8. Valida que master_guide exista en shipments.
  9. Transacción DB:
  10. shipments.status = nuevo_estado
  11. shipment_events nuevo registro
  12. notifications creado (push + email al usuario)
  13. Si el nuevo estado es entregado:
    • Disparar cobro de almacenaje final.
    • Cerrar shipments de paquetes relacionados.
  14. Marca webhook_events.processed = true.
  15. HTTP 200 a la agencia en < 5 segundos.

Estados que la agencia puede reportar

Estado Descripción
recibido_en_cuba Agencia recibió el envío en La Habana
en_aduana Aduana cubana está procesando
liberado_de_aduana Aduana liberó el envío
en_reparto En camino al destinatario
entregado Entregado al destinatario (con prueba)
incidencia Problema reportado por la agencia
devuelto Devuelto a IslaBox (caso raro)

Flujo principal — polling de la agencia

  1. Cron job cada 6 horas (tracking-poller worker).
  2. Selecciona todos los shipments con status en {despachado_desde_almacen, en_transito_a_cuba, recibido_en_cuba, en_aduana, en_reparto}.
  3. Para cada shipment, llama a GET {AGENCY_API_URL}/shipments/{master_guide}.
  4. Compara el estado retornado con el estado local.
  5. Si hay diferencia, ejecuta el mismo flujo que el webhook.
  6. Log en polling_logs.

Flujos alternativos

FA-1: Agencia no disponible

  • Si la API de la agencia no responde:
  • Reintentar 3 veces con backoff exponencial.
  • Si sigue fallando, marcar shipment.stale_polling = true.
  • Notificar al equipo técnico.

FA-2: master_guide no encontrado

  • Si la agencia reporta un master_guide que no existe localmente:
  • Log de error.
  • Notificar al admin.
  • HTTP 404 a la agencia.

FA-3: Estado inválido

  • Si la agencia envía un estado que no está en la lista permitida:
  • Log de error.
  • HTTP 400.
  • No actualizar.

FA-4: Disputa de estado

  • Si el estado reportado por la agencia contradice el último estado local conocido:
  • Tomar el más reciente por timestamp.
  • Si la diferencia es > 24h, escalar a admin.

FA-5: Cambios fuera de horario

  • Si la agencia envía webhooks fuera del horario operativo (00:00–06:00):
  • Procesar igual, pero agrupar notificaciones push para la mañana siguiente.

Reglas de negocio

  • RN-104: El mapeo de estados de la agencia debe ser 1:1 con shipment.status (ver estados.md).
  • RN-105: La firma del webhook es obligatoria (HMAC-SHA256).
  • RN-106: La idempotencia se garantiza por webhook_events.event_id con UK.
  • RN-107: La agencia tiene hasta 24h para reportar la entrega final; pasado eso, se considera "entrega pendiente de confirmación" y se contacta.

Endpoints API

  • POST /api/v1/webhooks/agency — webhook entrante
  • GET /api/v1/shipments/{id}/agency-status — estado según agencia
  • POST /api/v1/admin/agency/sync/{shipment_id} — fuerza sync manual
  • GET /api/v1/admin/agency/polling-logs — logs del poller

Eventos generados

  • SHIPMENT_STATUS_CHANGED_BY_AGENCY
  • SHIPMENT_DELIVERED
  • SHIPMENT_INCIDENT_REPORTED

Notificaciones generadas

  • Push al usuario: "Tu envío está en aduana" / "liberado" / "en reparto" / "entregado"
  • Email al usuario con número de guía de la agencia y enlace de seguimiento externo
  • Push al operador: solo en eventos críticos (incidencia, devolución)

Configuración

AGENCY_API_URL=https://api.agencia-aliada.cu
AGENCY_API_KEY=...
AGENCY_WEBHOOK_SECRET=...
AGENCY_POLLING_INTERVAL_HOURS=6
AGENCY_RETRY_MAX_ATTEMPTS=3
AGENCY_TIMEOUT_SECONDS=10

Monitoreo

  • Dashboard con tasa de éxito de webhooks.
  • Latencia entre cambio en agencia y notificación al usuario.
  • Alertas si > 5 webhooks fallan en 1 hora.
  • Alertas si el último polling exitoso fue hace > 12h.