Migration guide: v0.28.x → v1.0¶
Guía consolidada para adoptar v1.0 desde una versión estable antigua de la línea v0.28.x. La línea v0.40 → v0.53 introdujo features importantes — esta guía agrupa lo que cambia, lo que hay que activar, y lo que rompe (poco).
TL;DR¶
- Schema migra automático al boot — no requiere ALTER manuales.
- Cambios visuales en mensajes de Chatwoot (group prefix con ~tilde, blockquote en replies, reactions split). Tus parsers en downstream necesitan revisión si dependen del formato.
- Endpoints nuevos opt-in: history import, group admin, retroactive reconcile, jobs async.
- Backward-compat en API HTTP y schema Postgres. Todos los endpoints v0.28.x siguen funcionando.
Pre-requisitos¶
- Backup Postgres de
bridgedatabase. Las nuevas tablas no destruyen nada pero un backup vale. - Versión mínima Postgres: 14+ (validado contra 16).
QRSGEN_API_TOKENya en uso para auth — si no, configurarlo antes (los nuevos endpoints son admin-only).
Schema migrations automáticas¶
Al boot, qrsgen ejecuta EnsureXxxSchema que crea/altera tablas
de forma idempotente. Las nuevas:
| Tabla | Versión | Propósito |
|---|---|---|
bridge_msg_history |
v0.41.0 | Retroactive name update (msgID↔WAID, body, name_used) |
bridge_chat_anchor |
v0.49.0 | Anchor por chat para history import on-demand |
ALTER TABLE idempotentes (ADD COLUMN IF NOT EXISTS):
| Tabla | Columnas añadidas | Versión |
|---|---|---|
bridge_msg_history |
waid TEXT, has_prefix BOOLEAN |
v0.44.0 |
No hay DROP COLUMN ni cambios destructivos. Rows pre-existentes
mantienen comportamiento idéntico (has_prefix=true default,
waid='').
Env vars nuevas (todas opt-in con defaults conservadores)¶
Activadas por default (recomendado mantener)¶
QRSGEN_RETROACTIVE_NAME_UPDATE=true
QRSGEN_RETROACTIVE_PERSIST=true
QRSGEN_RETROACTIVE_TTL=720h # 30 días
QRSGEN_RETROACTIVE_CAP_PER_SENDER=200
QRSGEN_MARK_AS_READ_OUTGOING=true # requiere webhook conversation_updated
QRSGEN_READ_RECEIPTS_SYNC=true
QRSGEN_TYPING_SYNC=true
QRSGEN_REACTIONS_SYNC=true
QRSGEN_AVATAR_SYNC=true
QRSGEN_AVATAR_REFRESH_TTL=24h
QRSGEN_GROUP_PREFIX_SENDER=true
Opt-in (desactivadas, activar según necesidad)¶
QRSGEN_HISTORY_IMPORT_ENABLED=false # set true para backfill
QRSGEN_HISTORY_IMPORT_DAYS=7 # 1..30
QRSGEN_HISTORY_IMPORT_RATE_PER_SEC=5
QRSGEN_GROUP_EVENTS_ENABLED=false # set true para activity msgs de cambios de grupo
Templates (default ok)¶
QRSGEN_HEADER_TEMPLATE="`$phone · $name`" # group prefix + reactions
QRSGEN_GROUP_HEADER_SEP=paragraph # \n\n
QRSGEN_REACTION_HEADER_SEP=nl # \n
QRSGEN_MENTION_TEMPLATE="@$name" # v0.53.0 — @LID resolution
QRSGEN_REACTION_AS_REPLY=true # v0.53.2 — reaction como quote-reply
Cambios visuales en mensajes posteados¶
Si tu downstream tiene scripts que parsean el formato de los mensajes incoming en Chatwoot, considera estos cambios:
Group prefix¶
Antes (v0.28.x): +34604021705 - Pepito\nhola buenas
Ahora: `+34604021705 · Pepito`\n\nhola buenas
o con tilde si no saved: `+34604021705 · ~Pepito`
Code block (backticks), middle dot · como separador, tilde ~
para no-saved. Configurable vía QRSGEN_HEADER_TEMPLATE.
Reactions¶
Antes: **~Pepito** reaccionó con 👍
Ahora:
Header en línea separada (separador \n, configurable).
Quote/reply context (NUEVO)¶
Cuando alguien responde a un msg en WhatsApp:
Blockquote con header ↪ +phone · name + texto citado.
Group events (con GROUP_EVENTS_ENABLED=true)¶
Activity msgs en la conv del grupo:
- 📝 **Pepito** cambió el nombre del grupo a _X_
- ➕ **Pepito** añadió a Ana, ~Bea
- 🔒 **Pepito** restringió la edición del grupo a admins
- etc.
Endpoints nuevos¶
Todos bajo /api/instances/:name/... y protegidos por
QRSGEN_API_TOKEN. Consulta cada doc para detalles:
Retroactive name update (v0.40.0+)¶
POST /retroactive/reconcile— bulk reconcile de la agenda (verbridge_msg_history+Incoming.HandleContactUpdateen el código fuente)
History import (v0.46.0+)¶
POST /history/import?chat=<jid>— single chatPOST /history/import-all— bulk síncrono (bloquea hasta terminar)POST /history/import-all-async— bulk async, devuelvejob_id(docs)
Group admin (v0.48.0 + v0.50.0)¶
GET /groups/:jid— infoPOST /groups/:jid/name— renamePOST /groups/:jid/topic— descripciónPOST /groups/:jid/locked— toggle admin-only editPOST /groups/:jid/announce— toggle admin-only msgsPOST /groups/:jid/participants— add/remove/promote/demotePOST /groups— crearDELETE /groups/:jid— leave (docs)
Jobs (v0.52.0)¶
GET /jobs/:id— estado + resultado de un async jobGET /jobs— lista todos los jobs vivos
v0.53.x — mejoras de UX en mensajes posteados¶
A partir de v0.53.0 se incorporaron tres mejoras que cambian cómo se ven mensajes con menciones y reacciones en Chatwoot. Si vienes de v0.52.x el upgrade es transparente (no requiere env nuevas), pero los formatos pueden parsearse distinto en integraciones downstream.
LID mentions resueltas con phone fallback (v0.53.0 + v0.53.1)¶
Problema previo: @140832... (LID anónimo de WhatsApp) aparecía
crudo en Chatwoot — no sabes a qué número o nombre corresponde.
Ahora: qrsgen resuelve el LID en este orden:
- Pushname del contacto si está en el store local.
- Saved name (agenda) si el dueño del bot lo añadió.
- Phone (E.164 con
+) si la mapping LID→PN existe en el store. - RedactedPhone (último dígito enmascarado) si el usuario tiene privacy LID activada.
- LID crudo como fallback final.
Configurable vía QRSGEN_MENTION_TEMPLATE (default @$name).
Cuando un grupo se "abre" por primera vez tras el restart, qrsgen
hace GetGroupInfo on-demand para poblar el LID store (cache de 1h
por grupo). Implementado en internal/bridge/mentions.go.
Reacciones como quote-reply (v0.53.2)¶
Antes: la reacción aparecía como msg separado, sin contexto visual del msg target. El agente no sabía a qué se reaccionó.
Ahora: qrsgen postea la reacción con
content_attributes.in_reply_to apuntando al msg original →
Chatwoot renderiza la reacción como blockquote nativo dentro del
bubble. Default ON. Toggle vía QRSGEN_REACTION_AS_REPLY=false
si tu downstream no es Chatwoot.
Quote-reply outgoing (v0.52.1)¶
El tracker bridge_msg_history ahora también registra mensajes
salientes (fromMe=true), no solo incoming. Esto permite que
cuando alguien hace quote-reply en WhatsApp a un mensaje que TÚ
escribiste desde Chatwoot, qrsgen pueda resolver el in_reply_to
en el siguiente incoming.
v0.53.3 — hardening pre-v1.0¶
Cero cambios de API, tres fixes operativos earned del soak real:
- Goroutines de history sync ahora se cancelan al borrar la
instancia. Antes seguían POSTeando minutos tras
DELETE, generando 404s sin valor en logs. msgHistoryTracker.DropInstancellamada automáticamente desdeManager.Deletevía nuevo callbackSetInstanceDeleteHandler. Libera memoria + filas DB de instancias borradas.- Filtro de logs upstream: el WARN benigno
Failed to delete history sync media from serverqueda suprimido (cientos de líneas por sync, sin valor accionable).
Orden recomendado de adopción¶
Si vienes de v0.28.x y quieres adoptar v1.0 sin riesgos:
- Backup Postgres (
pg_dump bridge > bridge_v0.28.sql). - Deploy v1.0 sin tocar env vars opt-in — schema migra automáticamente al boot. Los formatos visuales cambian pero los flujos básicos (incoming/outgoing) funcionan idéntico.
- Verificar 24h — sin warnings/errors recurrentes en logs, sin spikes anómalos en métricas.
- Activar history import (
HISTORY_IMPORT_ENABLED=true,DAYS=7) si quieres backfill de N días. - Activar group events (
GROUP_EVENTS_ENABLED=true) si quieres ver cambios de grupos como activity msgs. - Probar group admin endpoints con un grupo donde el bot sea admin (rename como test seguro).
Rollback¶
Si necesitas volver a v0.28.x:
docker service update --image qrsgen:0.28.x qrsgen_qrsgen- Las tablas nuevas (
bridge_msg_history,bridge_chat_anchor) quedan huérfanas — no rompen v0.28.x, pero se pueden borrar manualmente si quieres: - Las columnas añadidas a tablas existentes (
waid,has_prefixenbridge_msg_history) tampoco rompen v0.28.x — quedan sin uso.
Rollback es seguro pero pierdes el state del retroactive update, history import tracking y chat anchors. Los mensajes ya posteados en Chatwoot permanecen.
Métricas Prometheus nuevas¶
Mantén tu Grafana / alerting al día con estos labels:
qrsgen_realtime_events_total{feature="retroactive_name", result=...}
qrsgen_realtime_events_total{feature="history_import", result=...}
qrsgen_realtime_events_total{feature="group_event", result=...}
qrsgen_realtime_events_total{feature="reaction|typing|avatar|read_receipt", ...}
Results comunes: ok, ds_error, wa_error, wa_miss,
skip_disabled, skip_fullsync, skip_empty_name, duplicate.
PromQL útil para detectar regresiones tras el upgrade:
# Tasa de errores downstream agrupada por feature
sum by (feature) (rate(qrsgen_realtime_events_total{result="ds_error"}[5m]))
# Volumen de retroactive updates (espera spikes al activar)
sum by (instance) (rate(qrsgen_realtime_events_total{feature="retroactive_name",result="ok"}[5m]))
Soporte¶
- CHANGELOG.md tiene los detalles de cada release individual.
- Issues: https://github.com/rricajos/qrsgen/issues
- Docs operacionales:
docs/operations/