From 7e50c71791b0b5d70092ba7406710ead3cfbf1a3 Mon Sep 17 00:00:00 2001 From: Johann Date: Wed, 30 Sep 2026 00:31:55 -0600 Subject: [PATCH] =?UTF-8?q?Registro=20#85:=20el=20webhook=20de=20Jira=20FA?= =?UTF-8?q?C=20queda=20en=20producci=C3=B3n=20(paputec)=20=E2=80=94=20publ?= =?UTF-8?q?icaci=C3=B3n=20de=205145801,=20secreto=20nuevo,=20PUT=20del=20w?= =?UTF-8?q?ebhook=20id=201=20y=20prueba=20e2e=20con=20FAC-170=20detectada?= =?UTF-8?q?=20en=201.05=20s=20(HMAC,=20verificada)=20y=20borrada;=20produc?= =?UTF-8?q?ci=C3=B3n=20sigue=20en=20Bind=5F=5FMode=3DWrite=20por=20decisi?= =?UTF-8?q?=C3=B3n=20de=20Johann?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bitacora/PENDIENTES.md | 20 ++++++++++++------ bitacora/REGISTRO.md | 34 +++++++++++++++++++++++++++++-- planeacion/jira-webhook-prueba.py | 25 +++++++++++++++-------- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/bitacora/PENDIENTES.md b/bitacora/PENDIENTES.md index f19d22b..ac70518 100644 --- a/bitacora/PENDIENTES.md +++ b/bitacora/PENDIENTES.md @@ -2,14 +2,22 @@ Acciones vivas del proyecto. Formato: `[ ]` abierta · `[x]` cerrada (no se borran, dejan rastro). Cada una con responsable y, si aplica, fecha. Ver contexto en [REGISTRO.md](REGISTRO.md). -_Última actualización: **2026-09-30** — fusión de las dos sesiones paralelas del 29-sep: la del webhook Jira FAC → vista previa de cotización pasa a ser el [#84](REGISTRO.md) (nació como #71 en la otra máquina). Anterior: **2026-09-29** — ⭐ Balam entrega **login web a BIND** con permisos de prefactura; endpoint interno de la UI confirmado (*Generar Venta → Prefactura*, petición `InvoiceDetails`) y el modelo de dos endpoints corroborado con el SDK oficial ([REGISTRO #83](REGISTRO.md)). **Huecos de registro cerrados:** las sesiones del 21-ago al 10-sep se reconstruyeron desde el buzón ([#71](REGISTRO.md)–[#82](REGISTRO.md)). Anterior: **2026-09-15** — corte de horas 10-ago→15-sep reconstruido y huecos de registro listados (seis sesiones sin bitácora). Anterior: **2026-08-21, mediodía** — ⭐ primera cotización real emitida (folio 1026; la 2.ª, corregida, pendiente de confirmar). Anterior: **2026-08-20, noche.** Cruce completo del buzón contra la bitácora (MCP ms365): se incorporaron 9 comunicaciones faltantes y se corrigieron 2 errores de registro. **Hay sesión mañana viernes 21-ago, 7:00 am** con Noé, Ara y Pedro sobre el formulario modificado y `FAC-106`. Ver [REGISTRO #65](REGISTRO.md)–[#68](REGISTRO.md)._ +_Última actualización: **2026-09-30** — ⭐ el webhook de Jira FAC queda **en producción (paputec)**: publicado, secreto nuevo, webhook id 1 movido y prueba de punta a punta con FAC-170 en 1.05 s ([REGISTRO #85](REGISTRO.md)). Además, fusión de las dos sesiones paralelas del 29-sep: la del webhook pasa a ser el [#84](REGISTRO.md) (nació como #71 en la otra máquina). Anterior: **2026-09-29** — ⭐ Balam entrega **login web a BIND** con permisos de prefactura; endpoint interno de la UI confirmado (*Generar Venta → Prefactura*, petición `InvoiceDetails`) y el modelo de dos endpoints corroborado con el SDK oficial ([REGISTRO #83](REGISTRO.md)). **Huecos de registro cerrados:** las sesiones del 21-ago al 10-sep se reconstruyeron desde el buzón ([#71](REGISTRO.md)–[#82](REGISTRO.md)). Anterior: **2026-09-15** — corte de horas 10-ago→15-sep reconstruido y huecos de registro listados (seis sesiones sin bitácora). Anterior: **2026-08-21, mediodía** — ⭐ primera cotización real emitida (folio 1026; la 2.ª, corregida, pendiente de confirmar). Anterior: **2026-08-20, noche.** Cruce completo del buzón contra la bitácora (MCP ms365): se incorporaron 9 comunicaciones faltantes y se corrigieron 2 errores de registro. **Hay sesión mañana viernes 21-ago, 7:00 am** con Noé, Ara y Pedro sobre el formulario modificado y `FAC-106`. Ver [REGISTRO #65](REGISTRO.md)–[#68](REGISTRO.md)._ + +## ⭐ 30-sep — webhook de Jira en producción ([REGISTRO #85](REGISTRO.md)) + +- [ ] 🔧 **Siguiente meta:** con cada `JiraTicketEvent` verificado, armar la **vista previa (dry-run) de la cotización** en BIND y marcar el ticket "lista para revisar" en la bandeja. La confirmación sigue siendo humana (ADR-001). ⚠️ El prellenado resuelve moneda, ubicación, almacén y servicio con los catálogos del API público de BIND (`/api/emision/catalogos`), que hoy responde 500: se puede construir y probar con `FakeHandler`, pero no validar contra BIND hasta que vuelva. +- [ ] ⚠️ **Producción corre con `Bind__Mode=Write`** (así estaba en `/opt/balam/.env`; el contenedor anterior llevaba 3 semanas arriba). **Johann decidió dejarlo así el 30-sep.** El runbook y el `CLAUDE.md` de la plataforma siguen diciendo que producción corre en ReadOnly: falta alinear esa documentación con la decisión, o regresarlo a ReadOnly cuando Johann lo indique. +- [ ] 🔑 **El secreto del webhook cambió:** el vigente está en `/opt/balam/.env` (`Jira__Webhook__Secret`) y en `~/jira-webhook-secret.txt` de la MacBook donde se hizo el despliegue. El `~/jira-webhook-secret.txt` de la otra máquina (piloto del 29-sep) **ya no sirve**: reemplazarlo por un canal seguro antes de usar ahí el subcomando `mover`/`registrar`. +- [ ] 🧹 Imagen de rollback `balam-api:pre-webhook-20260930` en paputec: borrarla cuando la versión nueva lleve unos días estable. +- [ ] 🔧 **Poller de respaldo** del webhook (JQL delta con checkpoint): sigue sin construirse; hoy un aviso perdido no se recupera solo. ## 🔥 29-sep — login web a BIND y endpoint interno de la UI ([REGISTRO #83](REGISTRO.md)) - [ ] 🔑 **Guardar las credenciales del login web fuera del repo** (`dotnet user-secrets` en desarrollo; `/opt/balam/.env` en paputec) y **destruir el TXT** en correo y disco. Misma lección del token de julio (VALIDACION-API.md §8.12). - [ ] 🔴 **Johann — revisar el error que impide cargar la solicitud al crear una cotización en BIND** (visto en la sesión) y **crear la cotización** después de corregirlo. Puntos de acción del informe de Read AI. -- [ ] ⭐ **Especificar el endpoint interno `InvoiceDetails` con la sesión propia:** URL, método, `Content-Type`, shape del payload, respuesta, cookies y `__RequestVerificationToken`, y el flujo de `/Login/Login`. Capturar con DevTools o con el script Playwright `captura-prefactura.mjs` (planeado en el #70; **aún no existe**); sanitizar (sin cookies ni token) y escribirlo en la bitácora como contrato antes de codificar. Crear UNA prefactura de prueba (no fiscal, borrable) y cancelarla al terminar; avisar a Pedro (candado del 12-ago). -- [ ] 🔧 **Construir `BindUiClient`** (sesión por cookie) con el mismo protocolo ADR-001: dry-run → confirmación humana → verificación por lectura (fila `IsFiscalInvoice=false` + `UUID=null` en la secuencia compartida de folios). Reemplaza el 409 de `POST /api/emision/prefactura`. +- [x] ~~⭐ **Especificar el endpoint interno `InvoiceDetails` con la sesión propia**~~ → **YA ESTABA HECHO en la otra máquina** (se supo al fusionar el 30-sep): el contrato real es `POST /InvoicesAPI/AddInvoiceTransaction`, capturado el 10-sep y documentado en `balam-plataforma/CLAUDE.md` (§Puente a la UI de BIND); el login de formulario `/Login/Login` también. Ver [#84](REGISTRO.md), punto 5. ⚠️ El contrato sigue **sin escribirse en esta bitácora** (hueco del 9/10-sep, abajo). Original: URL, método, `Content-Type`, shape del payload, respuesta, cookies y `__RequestVerificationToken`, y el flujo de `/Login/Login`; capturar con DevTools o Playwright, sanitizar y escribirlo como contrato antes de codificar. +- [x] ~~🔧 **Construir `BindUiClient`**~~ → **YA ESTABA HECHO** (commit `4d6b3d8` del repo del cliente): dry-run → confirmación humana → verificación por lectura, con el candado `ValidarEsPrefactura`; primera prefactura real el 29-sep, folio 2467 ([#84](REGISTRO.md)). No reemplaza el 409 de `POST /api/emision/prefactura`: ese candado se conservó y el puente vive en `POST /api/emision/prefactura-ui`. En paputec el puente está **apagado** (no hay `Bind__Ui__*` en el `.env`). - [ ] ⚠️ **Acordar con Balam que las prefacturas creadas así llevan `CreatedByName` = cuenta de Noé** (o pedir un usuario de servicio dedicado). - [ ] 📧 **Pedir en paralelo a soporte BIND el campo/endpoint oficial de prefactura**, con la evidencia del #70 + el swagger del SDK (`NewInvoice` sin campo de tipo) + la solicitud pública "agregar PREFACTURA" de su foro. Replicar la UI es frágil y posiblemente ajeno a sus términos de servicio. - [ ] 📼 **Recuperar los informes completos de Read AI** (al menos 9, 10 y 29-sep) desde app.read.ai con sesión — los correos solo traen el extracto — y guardarlos en `../fuentes/`. @@ -23,9 +31,9 @@ _Última actualización: **2026-09-30** — fusión de las dos sesiones paralela - [x] ~~🌐 **Fase 3:** ngrok con traffic policy de una sola ruta; API en ReadOnly mientras el túnel esté abierto.~~ → **HECHO (29-sep)**; túnel apagado al cerrar la sesión. - [x] ~~✍️ **Fase 4:** alta del webhook/regla como operación numerada (id, URL, fecha, autorización).~~ → **HECHO: webhook de sitio id 1** (19:05:53). - [x] ~~🧪 **Fase 5:** ticket de prueba → "lista para revisar" → verificar que BIND no recibió escritura. Reversa documentada.~~ → **HECHO: FAC-169** creado → detectado en 14.4 s (HMAC, verificado) → borrado. Ver adenda del [#84](REGISTRO.md). -- [ ] 🔥 **Mover el webhook id 1 a paputec** (`https://paputec.mx/balam/api/jira/webhook`): publicar `d7238da` en paputec, poner `Jira__Webhook__Secret` en `/opt/balam/.env`, `PUT` del webhook con la URL nueva y ese secreto (solo HMAC, sin token en la URL). **Hoy Jira entrega a una URL caída** (el túnel ngrok se apagó). -- [ ] 🔧 **Siguiente paso de la meta:** con cada `JiraTicketEvent` verificado, armar la **vista previa (dry-run) de la cotización** y marcar el ticket "lista para revisar" en la bandeja — la confirmación sigue siendo humana (ADR-001). -- [ ] ☁️ **Destino productivo del webhook:** ngrok con dominio fijo (de pago) vs Azure (sigue bloqueado por el cliente). +- [x] ~~🔥 **Mover el webhook id 1 a paputec** (`https://paputec.mx/balam/api/jira/webhook`)~~ → **HECHO el 30-sep** ([#85](REGISTRO.md)): plataforma publicada (`5145801`), secreto nuevo en `/opt/balam/.env`, `PUT` del webhook 1 → 200 (solo HMAC, sin token en la URL) y prueba con **FAC-170** detectada en 1.05 s y borrada. +- [ ] 🔧 **Siguiente paso de la meta:** vista previa (dry-run) de la cotización por cada detección → pasa al bloque del 30-sep, arriba. +- [x] ~~☁️ **Destino productivo del webhook:** ngrok con dominio fijo (de pago) vs Azure (sigue bloqueado por el cliente).~~ → **Resuelto por ahora con paputec** (30-sep), el mismo ambiente provisional de la plataforma. Cuando exista Azure, el webhook se mueve con otro `PUT`. - [ ] ⚠️ **Una sola sesión de Claude Code dueña de la API** en sesiones de escritura (el 29-sep otra sesión la relanzó en ReadOnly). - [ ] 🔥 **API público de BIND en 500 en todos los endpoints** (key de Arturo) — sync detenido desde el 10-sep. Pedir a Balam la API key del usuario `CTO` o revisar el acceso de Arturo. - [ ] 🔥 **Prefactura 2467 ($777,777 MXN, ACUNTIA, FAC-166):** confirmar con Balam si es prueba (cancelar/borrar antes de que alguien la timbre) o real; revisar que al timbrar quede **PPD**, no el PUE que BIND le puso. diff --git a/bitacora/REGISTRO.md b/bitacora/REGISTRO.md index 381bd34..875b519 100644 --- a/bitacora/REGISTRO.md +++ b/bitacora/REGISTRO.md @@ -1803,11 +1803,41 @@ La bandeja permite marcar varios tickets (solo los que aún no tienen cotizació --- +## 85 · Sep 30, 2026 — madrugada (≈12:10–12:45 AM) · Despliegue · El webhook de Jira FAC queda EN PRODUCCIÓN (paputec): publicado, secreto nuevo, webhook id 1 movido y prueba de punta a punta con FAC-170 en 1.05 s ⭐ + +> Contexto: sesión de Johann con Claude Code, continuación del [#84](REGISTRO.md) en la otra máquina (la que tiene la llave SSH de paputec). **Autorizaciones de Johann dadas en la sesión, una por una:** ejecutar el plan (pull, publicación, secreto), el `PUT` del webhook, y crear + borrar el ticket de prueba. Evidencia: commit `9351aa4` del repo del cliente, fila id 1 de `JiraTicketEvents` en la BD de paputec y log del contenedor `balam-api`. + +**1. Las dos bitácoras del 29-sep chocaban.** Esta máquina tenía sin publicar los registros [#71](REGISTRO.md)–[#83](REGISTRO.md) (commit `3de2739`); la otra publicó la sesión del webhook también como "#71". Al fusionar (commit `e88b5e1`) la del webhook pasó a ser el [#84](REGISTRO.md), con nota de renumeración. Lección: antes de numerar un registro, `git pull`. + +**2. Publicación en paputec.** Plataforma en `5145801` (cuatro commits nuevos para producción: `4d6b3d8` puente a la UI de BIND, `d7238da` webhook, `8479e96`, `5145801`). Antes de publicar: **116 pruebas en verde** (13 + 14 + 51 + 38), respaldo manual de la BD (`balam-20260930-062117.sql.gz`) y la imagen anterior etiquetada `balam-api:pre-webhook-20260930` para rollback. `deploy/paputec/deploy.sh` completo (frontend + API) → API sana, frontend 200. La migración `20260930005018_JiraTicketEvents` se aplicó al arrancar (la última aplicada era la del 12-ago). Log de arranque: solo los dos mensajes benignos del runbook. **El puente a la UI de BIND queda apagado en producción** (no hay `Bind__Ui__*` en el `.env`; default `Enabled=false`). + +**3. Secreto nuevo.** `openssl rand -base64 32`, guardado en `~/jira-webhook-secret.txt` (0600) de esta máquina y agregado a `/opt/balam/.env` como **`Jira__Webhook__Secret`** (doble guion bajo: la clave de configuración es `Jira:Webhook:Secret`). Nunca se imprimió; se compararon los sha256 de ambos lados y coinciden. `docker compose up -d api`. El secreto del piloto del 29-sep (el que iba en la URL de ngrok) queda sin uso. + +**4. Verificación sin tocar Jira, a través de Apache** (`https://paputec.mx/balam/api/jira/webhook`): antes del secreto → 404 (receptor apagado); con `?token=malo` → **401**; sin credencial → 401; `X-Hub-Signature` inventada → 401; firma HMAC correcta con un evento no suscrito → **202 ignorado** (no toca Jira ni la BD), también con un cuerpo de 280 KB; GET → 405. **Apache no bloquea el POST anónimo**; el cuerpo grande, con HTML y SQL en el texto, pasó sin filtro. + +**5. Escrituras en el Jira del cliente (continúan la numeración del [#84](REGISTRO.md)):** +- **Jira-op 4 (00:25:18):** `PUT /rest/webhooks/1.0/webhook/1` → **200** (el PUT existe; no hizo falta borrar y registrar). Releído por GET: nombre "Balam plataforma · FAC ticket creado", destino `https://paputec.mx/balam/api/jira/webhook` **sin query** (solo HMAC), habilitado, `jira:issue_created`, filtro `project = FAC`. +- **Jira-op 5 (00:28:29):** ticket de prueba **FAC-170** (id 17865) creado por API, asignado a Pedro → producción lo registró como **evento id 1: `Verified = true`, `AuthMethod = hmac`, estatus Open, 1.05 s** después del timestamp del evento (emitido 00:28:29.530, recibido 00:28:30.579). Log: `[jira-webhook] jira:issue_created FAC-170 detectado · verificado=True · auth=hmac · retraso=1.0s`. +- **Jira-op 6 (00:28:38):** FAC-170 **borrado** (204; GET posterior → 404). Vivió 9 segundos. Como con FAC-169, a Pedro le llega el correo de la regla "Confirmación ticket creado - FACT". + +**6. Hallazgo: producción corre con `Bind__Mode=Write`.** Así estaba `/opt/balam/.env` (el contenedor reemplazado llevaba 3 semanas arriba), contra lo que dicen el runbook y el [#77](REGISTRO.md). No se tocó. **Johann decidió dejarlo en Write** (30-sep). El receptor del webhook no escribe en BIND en ningún caso, y `Jira__Mode` sigue en ReadOnly. + +**7. Script de operación** ([`../planeacion/jira-webhook-prueba.py`](../planeacion/jira-webhook-prueba.py)): `esperar CLAVE paputec` consulta la BD de producción por ssh (antes solo el contenedor local), y la fecha del ticket de prueba ya no va fija en 29-sep. + +**Estado al cierre:** la detección de tickets creados en FAC funciona en producción y ya no depende de ninguna máquina encendida. Ninguna escritura en BIND. Sigue abierto lo urgente del [#84](REGISTRO.md): el API público de BIND en 500 (sync detenido desde el 10-sep) y la prefactura 2467 por confirmar con Balam. + +> **Lectura estratégica:** +> - **El primer eslabón de "ticket creado → cotización" ya es infraestructura, no demo.** Falta lo que le da valor: que cada detección arme sola la vista previa (dry-run) y el ticket aparezca como "lista para revisar". La confirmación sigue siendo humana (ADR-001). +> - ⚠️ **Ese siguiente paso choca con el bloqueo del API de BIND:** el prellenado de la cotización resuelve moneda, ubicación, almacén y servicio con los catálogos del API público (`GET /api/emision/catalogos`), que hoy responde 500. Sin la API key del usuario `CTO` (o el acceso de Arturo reparado), la vista previa automática se puede construir y probar con `FakeHandler`, pero no validar contra BIND. +> - **El webhook es de un solo intento útil:** sin el poller de respaldo, un aviso que Jira no logre entregar (paputec caído, despliegue en curso) se pierde. Conviene construirlo junto con la vista previa. + +--- + ## Resumen ejecutivo del hilo (para contexto rápido) -### Estado actual (al 29-sep-2026 — Etapa 2 en producción provisional) +### Estado actual (al 30-sep-2026 — Etapa 2 en producción provisional) -**La plataforma está publicada en https://paputec.mx/balam/** desde el 3-sep (ambiente provisional propio; Azure sigue sin entregarse, [#74](REGISTRO.md)/[#76](REGISTRO.md)) y Balam ya la opera en sesiones acompañadas: cotizaciones reales desde tickets, individuales y en lote, con `Bind:Mode=ReadOnly` fuera de sesión ([#77](REGISTRO.md)–[#79](REGISTRO.md)). **La cadena termina hoy en la cotización.** La prefactura por el API público es imposible — `false` = remisión, `true` = CFDI timbrado; incidente 2386 del 26-ago ([#70](REGISTRO.md)) — y el SDK oficial lo confirma ([#83](REGISTRO.md)). El camino es el **endpoint interno de la UI** (*Generar Venta → Prefactura*, petición `InvoiceDetails`, [#80](REGISTRO.md)), para el que Balam entregó **login web** el 29-sep. **Siguiente hito:** especificar ese endpoint con la sesión propia y construir `BindUiClient` bajo ADR-001. **Seguimiento con Pedro** (sesiones "Seguimiento PAF" a las 7:00 am o 1:00 pm; informes de Read AI de Noé). Horas al 16-sep: 94.58 h; Excel de avance en Google Sheets ([#82](REGISTRO.md)). **Abiertos:** cancelación SAT de la 2386, remisiones 1000/1001, Azure, a quién se reportan horas, y el error al cargar la solicitud al crear cotización visto el 29-sep. +**La plataforma está publicada en https://paputec.mx/balam/** desde el 3-sep (ambiente provisional propio; Azure sigue sin entregarse, [#74](REGISTRO.md)/[#76](REGISTRO.md)) y Balam ya la opera en sesiones acompañadas: cotizaciones reales desde tickets, individuales y en lote ([#77](REGISTRO.md)–[#79](REGISTRO.md)). Producción corre con `Bind__Mode=Write` por decisión de Johann del 30-sep ([#85](REGISTRO.md)). **La cadena ya llegó a la prefactura:** por el API público es imposible — `false` = remisión, `true` = CFDI timbrado; incidente 2386 del 26-ago ([#70](REGISTRO.md)), confirmado con el SDK oficial ([#83](REGISTRO.md)) — pero el puente a la UI de BIND (`BindUiClient`, *Generar Venta → Prefactura*, con el login web que Balam entregó el 29-sep) creó ese mismo día la **primera prefactura real, folio 2467** ([#84](REGISTRO.md)); en paputec el puente sigue apagado. **Y la cadena ya arranca sola:** desde el 30-sep el webhook de Jira avisa a producción cada ticket creado en FAC ([#85](REGISTRO.md)). **Siguiente hito:** con cada detección, armar la vista previa (dry-run) de la cotización y marcar el ticket "lista para revisar"; la confirmación sigue siendo humana (ADR-001). **Seguimiento con Pedro** (sesiones "Seguimiento PAF" a las 7:00 am o 1:00 pm; informes de Read AI de Noé). Horas al 16-sep: 94.58 h; Excel de avance en Google Sheets ([#82](REGISTRO.md)). **Abiertos:** API público de BIND en 500 con la key de Arturo (sync detenido desde el 10-sep), prefactura 2467 por confirmar con Balam, cancelación SAT de la 2386, remisiones 1000/1001, Azure, a quién se reportan horas, y el error al cargar la solicitud al crear cotización visto el 29-sep. ### Datos duros confirmados por Balam - **BIND ERP:** API existe y es viable (confirmado 25-may). Límite 20K req/día. PAC para CFDI integrado en BIND. diff --git a/planeacion/jira-webhook-prueba.py b/planeacion/jira-webhook-prueba.py index e2854fe..af2efaf 100644 --- a/planeacion/jira-webhook-prueba.py +++ b/planeacion/jira-webhook-prueba.py @@ -4,7 +4,8 @@ # url → lee la URL pública del túnel ngrok local (solo lectura) # registrar → POST /rest/webhooks/1.0/webhook (ESCRIBE: 1 webhook de sitio) # crear-ticket → POST /rest/api/3/issue (ESCRIBE: 1 ticket de prueba en FAC) -# esperar CLAVE → espera la detección en la BD local (solo lectura) +# esperar CLAVE [paputec] → espera la detección en la BD local o, con "paputec", +# en la de producción por ssh (solo lectura) # borrar-ticket CLAVE → DELETE /rest/api/3/issue/CLAVE (ESCRIBE: borra el ticket de prueba) # borrar-webhook → DELETE del webhook registrado (reversa total) # mover URL_BASE → PUT del webhook a otra URL base (ESCRIBE), p. ej. @@ -12,7 +13,8 @@ # estado → webhooks de sitio actuales (solo lectura) # # Estado del piloto: webhook de sitio id 1 registrado el 29-sep apuntando al -# túnel ngrok de Johann; prueba FAC-169 creada, detectada y borrada. +# túnel ngrok de Johann; prueba FAC-169 creada, detectada y borrada. El 30-sep +# se movió a https://paputec.mx/balam (solo HMAC, secreto nuevo). # # El token de Jira y el secreto del webhook nunca se imprimen ni se versionan: # token → propuesta/token-jira.txt (gitignoreado) o $JIRA_TOKEN_FILE @@ -61,10 +63,16 @@ def url_publica(): return None -def sql(consulta): - # Superusuario local del docker-compose: ve la tabla pese a RLS. - out = subprocess.run(["docker", "exec", "balam-postgres-dev", "psql", "-U", "balam", "-d", "balam", - "-At", "-F", " | ", "-c", consulta], capture_output=True, text=True, encoding="utf-8") +def sql(consulta, destino="local"): + # Superusuario del docker-compose (local o paputec): ve la tabla pese a RLS. + if destino == "paputec": + # La consulta viaja por stdin: sin comillas que escapar a través de ssh + sudo. + out = subprocess.run(["ssh", "-o", "BatchMode=yes", "johann@paputec.mx", + "sudo docker exec -i balam-postgres psql -U balam -d balam -At -F ' | '"], + input=consulta, capture_output=True, text=True, encoding="utf-8") + else: + out = subprocess.run(["docker", "exec", "balam-postgres-dev", "psql", "-U", "balam", "-d", "balam", + "-At", "-F", " | ", "-c", consulta], capture_output=True, text=True, encoding="utf-8") return out.stdout.strip() or out.stderr.strip() @@ -100,7 +108,7 @@ elif cmd == "registrar": elif cmd == "crear-ticket": adf = {"type": "doc", "version": 1, "content": [{"type": "paragraph", "content": [{"type": "text", "text": - "Ticket de PRUEBA de la plataforma Balam (29-sep-2026), autorizado por Pedro Ayala, para validar " + f"Ticket de PRUEBA de la plataforma Balam ({time.strftime('%d/%m/%Y')}), autorizado por Pedro Ayala, para validar " "que la plataforma detecta la creación de tickets por webhook. Se elimina en cuanto se confirma."}]}]} st, r = jira("POST", "/rest/api/3/issue", {"fields": { "project": {"key": "FAC"}, "issuetype": {"id": "10073"}, @@ -114,12 +122,13 @@ elif cmd == "crear-ticket": elif cmd == "esperar": clave = sys.argv[2] + destino = sys.argv[3] if len(sys.argv) > 3 else "local" for i in range(60): fila = sql(f"""SELECT "Id","IssueKey","Verified","AuthMethod","JiraStatus", to_char("JiraTimestampUtc" AT TIME ZONE 'America/Mexico_City','HH24:MI:SS.MS'), to_char("ReceivedAtUtc" AT TIME ZONE 'America/Mexico_City','HH24:MI:SS.MS'), round(extract(epoch from ("ReceivedAtUtc"-"JiraTimestampUtc"))::numeric,2), - coalesce("Error",'') FROM "JiraTicketEvents" WHERE "IssueKey"='{clave}'""") + coalesce("Error",'') FROM "JiraTicketEvents" WHERE "IssueKey"='{clave}'""", destino) if fila and "|" in fila: print(f"DETECTADO tras ~{i}s de espera: id | llave | verificado | auth | estatus Jira | emitido (MX) | recibido (MX) | retraso s | error") print(" " + fila)