Motify tiene dos rieles: HTTP manda, MQTT avisa. Todo lo que cambia en vivo — ofertas, estados de carrera, GPS del conductor, estados de verificación — llega por push sobre MQTT (AWS IoT Core, WebSocket con TLS). Esta guía cubre cómo conectarte, con qué credencial, qué puedes ver según tu rol, y cómo manejar el ciclo de vida de la conexión — incluida la renovación de sesión.
El broker exige pasar por el custom authorizer en cada conexión — no existen conexiones anónimas. La credencial viaja en la URL del WebSocket:
wss://a3p5h9845pzkuc-ats.iot.us-east-1.amazonaws.com/mqtt
?x-amz-customauthorizer-name=motify-auth
&token=<credencial>
// mqtt.js (web) — en Flutter (mqtt_client) el esquema es idéntico
const client = mqtt.connect(url, {
clientId: "pax-<userId>", // OBLIGATORIO: la policy solo permite TU clientId
reconnectPeriod: 0, // maneja la reconexión tú (ver ciclo de vida)
});
clientId no es decorativo: la policy emitida por el authorizer solo
autoriza el clientId de tu clase (pax-{userId}, drv-{userId},
stf-{id} con sufijo opcional para varias pestañas, vfy-{sessionId}). Conectar
con otro id = rechazo. Y si dos clientes usan el MISMO clientId, el broker patea al primero —
por eso cada sesión/pestaña debe tener el suyo.| Clase | Credencial (token) | clientId | Cuándo |
|---|---|---|---|
| Sesión de verificación | verify.<sessionId> (el secreto de la sesión ES la credencial) | vfy-{sessionId} | Pre-autenticación: esperar el estado del flujo de identidad por push |
| Pasajero | JWT Motify (en dev: dev-token dev.passenger.{id}) | pax-{userId} | Toda la sesión de la app |
| Conductor | JWT Motify (dev: dev.driver.{id}) | drv-{userId} | Mientras está en turno |
| Staff (console) | JWT Motify (dev: dev.staff.{id}) | stf-{id} o stf-{id}-* | Monitoreo del backoffice |
verify.*; el cambio a validación del JWT Motify (mismo JWKS que HTTP) es un swap del
validador ya previsto — las policies y este contrato no cambian.| Clase | Publica | Escucha |
|---|---|---|
| Verificación | nada | motify/verify/{sessionId} (solo el suyo) |
| Pasajero | nada (solo observa) | motify/pax/{userId}/inbox · motify/ride/+/loc · motify/ride/+/events |
| Conductor | motify/drv/{userId}/geo (posición gruesa) · motify/ride/+/loc (GPS en viaje) | motify/drv/{userId}/inbox · motify/ride/+/events |
| Staff | nada (solo observa) | motify/drv/+/geo · motify/drv/+/inbox · motify/ride/+/loc · motify/ride/+/events |
ride/+ son una limitación aceptada del MVP (documentada
en el ADR-0002) con plan comprometido: cuando el refresh de policy consulte la carrera activa, se acotará
al rideId exacto. La identidad del PUBLICADOR nunca depende del payload: la posición gruesa
se escribe con clientId() del broker — un conductor no puede publicar por otro.| Regla | Detalle |
|---|---|
| Vida máxima | 24 h por conexión; la policy se re-evalúa cada 15 min con la credencial presentada al conectar — un JWT de 1 h vencerá y el broker te desconectará: es lo esperado. |
| Renovación | Al desconectar: renueva el JWT (login con passkey, en silencio) y reconecta. La desconexión es un evento NORMAL del ciclo, no un error. |
| Backoff | Reintentos con backoff exponencial + jitter (1s → 2s → 4s… tope 30s). Nunca reconectes en loop apretado. |
| Reconciliación | QoS 0, sin retained, sin sesión persistente: lo que pasó mientras estabas desconectado NO se re-entrega por MQTT. Al reconectar, reconstruye el estado por HTTP (GET /rides/active, GET /rides/{id}) y sigue en vivo desde ahí. |
| Un clientId por sesión | Dos conexiones con el mismo clientId se patean mutuamente (kick-loop). Cada instancia/pestaña usa el suyo. |
Conecta con la identidad de prueba
dev.passenger.labmqtt (clientId pax-labmqtt) y se suscribe a su inbox y a
motify/ride/+/events. "Emitir evento de prueba" llama a
POST /v1/dev/push (herramienta SOLO del sandbox, apagada en producción): el servidor
publica un eco a tu inbox y lo ves llegar por el broker — el círculo completo "HTTP manda, MQTT
avisa". También verás actividad real si creas una carrera desde la
referencia de rides o corre el simulador.
// los mensajes del broker aparecerán aquí