Fusión de las dos sesiones del 29-sep: el registro del webhook Jira FAC pasa de #71 a #84 (los #71–#83 son las sesiones del 21-ago al 29-sep) y PENDIENTES conserva los dos bloques
This commit is contained in:
@@ -1756,6 +1756,53 @@ La bandeja permite marcar varios tickets (solo los que aún no tienen cotizació
|
||||
|
||||
---
|
||||
|
||||
## 84 · Sep 29, 2026 · Sesión de trabajo · App en modo escritura, token de Jira y plan del webhook FAC → vista previa de cotización ⭐
|
||||
|
||||
> Contexto: sesión de Johann con Claude Code. Nota: la bitácora no tiene entradas entre el #70 (26-ago) y este; el trabajo del 9/10-sep (puente a la UI de BIND para la prefactura) está documentado solo en `balam-plataforma/CLAUDE.md` y se sube al repo en esta misma fecha.
|
||||
>
|
||||
> ⚠️ **Renumerado de #71 a #84 el 30-sep**, al fusionar las dos sesiones paralelas del 29-sep: la otra numeró [#71](REGISTRO.md)–[#83](REGISTRO.md) con las sesiones del 21-ago al 29-sep. Los commits `d76496f`…`e5912bf` de este repo y la documentación de la plataforma dicen "Registro #71" y se refieren a **esta** entrada. La nota de arriba sobre el hueco entre el #70 y este quedó superada por esos registros. A su vez, este registro deja atrás lo que el [#83](REGISTRO.md) da por pendiente: el endpoint interno de la UI **ya está especificado y construido** (`BindUiClient`, `AddInvoiceTransaction`, commit `4d6b3d8` del repo del cliente; ver punto 5).
|
||||
|
||||
**1. Levantar la app en modo escritura.** Se arrancó Docker Desktop (estaba apagado) → Postgres `balam-postgres-dev` en 5438, frontend en 4200 y API en 5078 con `Bind__Mode=Write`, `Bind__Ui__Enabled=true` y `Bind__Ui__Mode=Write` como **variables de entorno de esa corrida** (los user-secrets siguen en `Bind:Mode=ReadOnly`, así que al apagar vuelve sola a solo lectura).
|
||||
- ⚠️ **Choque entre dos sesiones de Claude Code:** otra sesión en la misma máquina levantó su propia API a las 13:24 (y de nuevo a las 15:28, `--no-build`) **sin** las variables de escritura. La API de esta sesión murió sin excepción en el log y el reinicio falló con `address already in use`. La API que quedó viva en 5078 era la de la otra sesión, en `Bind:Mode=ReadOnly`.
|
||||
- Evidencia en pantalla: el paso 3 del wizard (*Vista previa y creación (ADR-001)*) generó la **operación #15 · `POST /api/Quotes`** como dry-run registrado en `WriteOperations`, con el botón *Crear cotización en BIND* deshabilitado: *"el servidor está en modo ReadOnly"*. **No se escribió nada en BIND.**
|
||||
- Lección: una sola sesión debe ser dueña de la API durante una sesión de escritura; verificar el dueño del puerto (no solo que esté escuchando).
|
||||
|
||||
**2. Token de Jira.** Existe `Jira:ApiToken` en user-secrets de `Balam.Api` (junto con `Bind:ApiKey`, `Jwt:SigningKey`, etc.); configuración en `appsettings.Development.json`: `balam-jsm-temp.atlassian.net`, usuario `pedro.ayala@…` (token personal de **Pedro**), proyecto FAC, `Mode=ReadOnly`. No se verificó el valor (el clasificador de permisos bloqueó leerlo, correctamente). Prueba práctica de vigencia: que la bandeja de Solicitudes FAC cargue.
|
||||
|
||||
**3. ¿Se puede leer la creación de un ticket y automatizar la cotización?**
|
||||
- **Leer: sí, hoy.** Polling con JQL delta (`SearchJqlAsync` + `SyncSchedulerService` + checkpoint con solape, ADR-002) o webhook. Recordatorio del 10-ago: el disparador acordado (*En proceso de facturación*) dura ~3 min, así que el poller debe leer el changelog, no el estatus actual.
|
||||
- **Crear la cotización sin humano: técnicamente sí, pero rompe ADR-001** (dry-run + confirmación humana en cada escritura a BIND producción). Propuesta aceptada como camino: **el webhook/poller deja lista la vista previa y un humano confirma con un clic.** Automatización total solo con autorización escrita de Balam y enmienda a ADR-001.
|
||||
|
||||
**4. Webhook / Jira Automation — qué se necesita.** URL pública (ngrok ya instalado en la máquina de Johann; productivo = Azure o dominio fijo), endpoint nuestro `POST /api/jira/webhook` (no existe aún), y el disparador en Jira. Con el token actual: construir el endpoint sí (no requiere permisos de Jira); crear el webhook/regla en Jira solo si el usuario de Pedro es admin **y** con autorización expresa, porque es escribir en la configuración del Jira productivo a su nombre.
|
||||
- **Johann confirma que existe autorización escrita de Pedro** para hacerlo. ⚠️ Aún no archivada en `fuentes/`.
|
||||
|
||||
**Fase 1 del plan — ejecutada el mismo 29-sep (solo GET, nada creado ni ejecutado):** `myself` 200 → Pedro Alberto Ayala Elizondo, activo · `mypermissions` en FAC: **`ADMINISTER` = true** (admin de Jira), `ADMINISTER_PROJECTS` = true, `CREATE_ISSUES` = true, `SYSTEM_ADMIN` = false (no se necesita) · `GET /rest/webhooks/1.0/webhook` 200 → **0 webhooks de sitio** (el endpoint exige admin: acceso confirmado) · API de Automation (`api.atlassian.com/automation/public/jira/{cloudId}/rest/v1/rule/summary`) 200 con el mismo token → **50+ reglas visibles** (primera página), casi todas de alcance sitio; relevantes para FAC: *Confirmación ticket creado - FACT*, *Factura por soporte técnico*, *Facturación Anticipada*. **Conclusión: el token de Pedro puede crear tanto el webhook de sitio (Vía A) como reglas de Automation (Vía B).** Queda archivar la autorización y decidir el evento.
|
||||
|
||||
**Resultado:** plan en [`../planeacion/Plan-Webhook-Jira-2026-09-29.md`](../planeacion/Plan-Webhook-Jira-2026-09-29.md): 5 fases (verificar permisos por GET → endpoint con secreto/idempotencia/relectura → ngrok con traffic policy de una sola ruta → una escritura auditada en Jira, preferentemente webhook de sistema → ticket de prueba y reversa).
|
||||
|
||||
**5. Hallazgos del mismo día hechos en la OTRA sesión de Claude Code** (fuente: `balam-plataforma/CLAUDE.md`, §Puente a la UI; no verificados en esta sesión):
|
||||
- ⭐ **29-sep 16:08 — PRIMERA PREFACTURA REAL DESDE LA PLATAFORMA: folio 2467** (ACUNTIA, **$777,777 MXN**, IVA 0, sin UUID, Activa), desde la cotización 1083 / ticket FAC-166, op #28, por el puente `AddInvoiceTransaction` con el usuario nuevo **`CTO`** (a nombre de Noé Rocha Castillo). BIND dejó la 1083 como Surtida.
|
||||
- Lecciones: el API público tarda más de un minuto en ver lo que crea la web app (hay reintentos); todo lo posterior al POST quedó en try/catch para que **un documento creado nunca se reporte como fallo**.
|
||||
- ⚠️ BIND dejó `CFDIPaymentTerm = PUE` aunque el cuerpo iba en PPD (igual que la 2462 hecha a mano): se define al timbrar. Choca con la salvaguarda #4 (PPD por default); revisar antes del timbrado.
|
||||
- ⚠️ **El API público (`api.bind.com.mx`) responde 500 en TODOS los endpoints** con la API key de `arturo|128469` (pasa autenticación y falla adentro; la web app sí funciona). **El sync no avanza desde el 10-sep.** Hipótesis: Balam tocó el acceso de Arturo al crear el usuario `CTO`. Salida propuesta: API key del usuario `CTO` en `Bind:ApiKey`.
|
||||
- 🔒 **Web app de BIND: una sesión por usuario.** La plataforma entra, opera y sale en cada operación; nadie debe usar el usuario `CTO` en un navegador mientras la plataforma opera.
|
||||
- ⛔ **Escritura accidental:** `QuotesAPI/FillQuote` resultó ser *"Marcar como Surtida"* y **escribe por GET**. Se invocó por error y dejó la **cotización de prueba 1079 en Surtida** (sin documento ni efecto fiscal; irreversible desde la UI). Desde entonces el lector solo permite `/Assets/*`, `/Sales/*Details` y `*API/Get*`.
|
||||
- La web app expone un API interno (66 rutas `InvoicesAPI/*`, 12 `QuotesAPI/*`, 26 `ClientsAPI/Get*`): plan B si el API público sigue caído. `GetClientSelectedById` resuelve las dos suposiciones del builder (`PaymentMethod`, `CFDI_Use`).
|
||||
|
||||
**Repo de la plataforma:** se sube el puente de prefactura por la UI de BIND (`BindUiClient`, `PrefacturaUiEndpoints`, tarjeta del wizard y pruebas) sobre 4 commits remotos de la otra máquina (26-ago: experimento de folio compartido; 15-sep: publicación en paputec.mx, catálogo de servicios, cotización en lote). Tres conflictos resueltos: **se conservó el candado 409 de `POST /api/emision/prefactura`** (el commit remoto del 26-ago noche lo había retirado para el experimento de `Number`, que el 27-ago BIND ignoró), se combinaron los campos de `NewInvoice` (`Number`/`ShowIEPS` + `PrevInvoice`/`IsCFDI`/`QuoteID`) y los usings de `Program.cs`. Verificado después del rebase: **108 pruebas en verde** y frontend compilando; escaneo del diff sin secretos. Commit `4d6b3d8`.
|
||||
|
||||
**ADENDA (29-sep, noche) — PILOTO DEL WEBHOOK VALIDADO DE PUNTA A PUNTA** (autorización expresa de Johann para las tres escrituras de prueba en Jira; Pedro autorizó el uso de su token):
|
||||
- **Plataforma** (commit `d7238da` en el repo del cliente): `POST /api/jira/webhook` con secreto (HMAC `X-Hub-Signature` o token), relectura del ticket por API (solo GET), tabla `JiraTicketEvents` con RLS e idempotencia, `GET /api/jira/eventos`; sin secreto responde 404. 8 pruebas nuevas, suite de la API en 38/38. Instancia expuesta en el puerto 5079 con `Bind:Mode=ReadOnly` y el puente UI apagado; ngrok con *traffic policy* que solo deja pasar el webhook (verificado desde internet: todo lo demás 404).
|
||||
- **Antes de escribir, inventario de Automation (solo GET):** 64 reglas (42 activas); de las 17 que se disparan al crear un ticket, **solo "Confirmación ticket creado - FACT" aplica a FAC** (proyecto 10034) y manda correo al reporter. Notificaciones de FAC al crear/borrar: reporter + watchers → con el ticket de prueba todo le llegó solo a Pedro.
|
||||
- **Jira-op 1 (19:05:53):** webhook de sitio **id 1** registrado — `jira:issue_created`, filtro `project = FAC`, con secreto HMAC, apuntando a `https://gregoria-disjoined-marcelino.ngrok-free.dev/api/jira/webhook`.
|
||||
- **Jira-op 2:** ticket de prueba **FAC-169** creado por API (asignado a Pedro, marcado como prueba). → Jira entregó **una sola vez**, **firmado HMAC**, desde "Atlassian Webhook HTTP Client"; la plataforma lo registró **verificado** (estatus Open) **14.4 s** después del timestamp del evento (la creación por API tardó ~11 s en responder; el aviso llegó ~3 s después).
|
||||
- **Jira-op 3 (19:07:44):** FAC-169 **borrado** (204; GET posterior → 404). En la BD local queda el evento id 1 como evidencia.
|
||||
- **Estado al cierre:** el webhook id 1 sigue registrado y activo, pero el túnel y la instancia 5079 se apagaron al cerrar la sesión → **Jira entrega a una URL caída** hasta moverlo. Destino estable: **`https://paputec.mx/balam/api/jira/webhook`** (Apache ya proxya `/balam/api/`). Script de operación: [`../planeacion/jira-webhook-prueba.py`](../planeacion/jira-webhook-prueba.py) (subcomandos `estado`, `mover`, `borrar-webhook`, `crear-ticket`, `borrar-ticket`).
|
||||
|
||||
> **Lectura estratégica:** el webhook no cambia el protocolo de escritura: lo que acelera es la *captura*, no la *decisión*. Y el caso más valioso no es la creación del ticket sino el cruce de 3 minutos por *En proceso de facturación*, que el polling de 15 min pierde.
|
||||
|
||||
---
|
||||
|
||||
## Resumen ejecutivo del hilo (para contexto rápido)
|
||||
|
||||
### Estado actual (al 29-sep-2026 — Etapa 2 en producción provisional)
|
||||
|
||||
Reference in New Issue
Block a user