Files
balam/planeacion/Investigacion-API-Jira.md
T
JohannVelazquez cbb29086cc Documenta las definiciones Jira→BIND y su validación por API
Consolida el disparador, los huecos de datos y el protocolo de prueba para continuar el desarrollo con decisiones trazables.
2026-08-11 20:23:55 -06:00

33 KiB
Raw Blame History

Investigación de la API de Jira — qué probar exactamente

Fecha: 30-jul-2026 · Actualizado: 10-ago-2026 Propósito: lista cerrada de pruebas y preguntas para habilitar la integración Jira → cotización BIND (estimada en ~10 h, REGISTRO #51). Documento de trabajo interno; sirve también como briefing para el agente/chat especializado en la API de Jira.

Estado validado (30-jul):

  • Sitio: https://balam-jsm-temp.atlassian.net. El token regenerado de Pedro, usado con Basic auth y pedro.ayala@balamtalentoestrategico.com, respondió 200 a GET /rest/api/3/myself.
  • Facturación es el proyecto JSM FAC (projectId: 10034, serviceDeskId: 35), de tipo service_desk y estilo classic (company-managed).
  • La búsqueda de FAC devolvió 66 tickets. La API vigente es GET /rest/api/3/search/jql, con paginación por nextPageToken; el endpoint clásico /rest/api/3/search responde 410 Gone.
  • Estatus confirmados: Open, En proceso de facturación, En espera por colaborador, En validación nacional, En validación extranjera, Facturado y Cancelado. No se observó un estatus llamado “Resuelto”.
  • Límites de consumo ya aclarados por Pedro (sin tope mensual; 3 límites de velocidad; telemetría solo en headers X-RateLimit-*).

Decisiones de negocio recibidas (correo del 7-ago) y su verificación por API (10-ago)

Balam contestó las tres preguntas del 30-jul. Arturo respondió el 4-ago (en verde sobre el correo de Noé), Noé lo reenvió el 7-ago. Fuente: RV_ Seguimiento_ medición de consumo API de Jira y accesos.eml.

Decisión de Balam Quién / cuándo Verificación por API (10-ago)
La cotización BIND se genera al entrar a En proceso de facturación Arturo, 4-ago Estatus y transición Iniciar facturación ya inventariados (Bloque 3)
Todo se tramita como facturación normal; el caso recurrente espera a que se explore el módulo de Proyectos de BIND Arturo, 4-ago ⚠️ El campo Facturación recurrente sigue siendo obligatorio y se está llenando (FAC-100: Si, periodo 12)
Se observan todos los request types de la bandeja de facturación, no solo Facturación adicional Arturo, 4-ago 🔴 10 de 69 tickets no tienen request type alguno y ninguno trae campos de facturación (ver Bloque 1)
Monto y conceptos van como campos de Jira, no del adjunto; omitir el campo de recurrencia Arturo, 4-ago ⚠️ Monto sin IVA ya existe y funciona; conceptos no existe como campo en todo el sitio (ver Bloque 2)
Las pruebas de escritura son prueba acompañada sobre un ticket, no proyecto FACTEST Noé, 7-ago Se descarta el sandbox en la instancia de Balam → aplica el protocolo del Bloque 6 sin excepción

Lo que sigue abierto tras estas respuestas: de dónde salen los conceptos/partidas de la cotización, qué hacer con los tickets sin campos estructurados, si nacional/extranjero cambia la cotización o solo el paquete de salida, PUE vs PPD, la fecha de la prueba acompañada y la migración a cuenta de servicio.


Bloque 0 — Acceso autenticado

El 401 del 29-jul quedó explicado por la combinación de token previo y datos de conexión incompletos. Pedro confirmó el correo, regeneró el token y compartió el dominio del sitio.

Configuración que funcionó:

GET https://balam-jsm-temp.atlassian.net/rest/api/3/myself
Authorization: Basic base64(pedro.ayala@balamtalentoestrategico.com:<token>)
Accept: application/json

El resultado fue HTTP 200. Por tanto, para esta integración se usará la API directa del sitio con Basic auth; no hay evidencia de que se requiera una ruta api.atlassian.com/ex/jira/{cloudId}.

Prueba canónica de auth (la primera que debe correrse siempre):

GET /rest/api/3/myself

Interpretación de la respuesta:

  • 200 → auth OK; además devuelve accountId (identidad con la que la plataforma va a escribir — dato de gobierno, ver Bloque 7).
  • 401 → credencial inválida/inactiva o esquema mal armado.
  • 403 → credencial VÁLIDA pero sin permiso → problema de permisos, no de token. Distinguir 401 de 403 es el diagnóstico más barato que existe.

⚠️ Registrar siempre los headers de la respuesta 401 completos. Ahí vive la pista (WWW-Authenticate, X-Seraph-LoginReason, X-Failure-Category).


Bloque 1 — Topología: Jira Service Management confirmado

FAC está confirmado como Jira Service Management (JSM). Por ello la integración requiere dos familias de API:

API Para qué Cuándo usarla
/rest/api/3/... Issues genéricos: JQL, campos, transiciones, adjuntos, changelog Lectura/sync, transiciones, trazabilidad
/rest/servicedeskapi/... Requests de portal: request types, campos del formulario, aprobaciones, SLA, comentarios públicos vs internos Crear tickets como los crea un humano; leer aprobaciones y SLA

Resultados:

GET /rest/api/3/project/FAC

projectTypeKey: service_desk, style: classic, id: 10034.

GET /rest/servicedeskapi/servicedesk

→ FAC corresponde a serviceDeskId: 35.

Request types publicados en el portal (GET /rest/servicedeskapi/servicedesk/35/requesttype, isLastPage: true):

requestTypeId Nombre Campos obligatorios
84 Bajas 7
83 Facturación adicional 10
389 Automatización 1 (solo summary)
12 Facturación 1 (solo summary)

Contratos verificados el 10-ago con /requesttype/{id}/field:

Request type Hallazgo
Bajas (84) Empresa origen, Summary, adjunto de Cálculo/VoBo de Finiquito, Nombre del Cliente, Nombre del Colaborador, Fecha de la Baja y Motivo de la Baja.
Facturación adicional (83) Empresa origen, MES / DESCRIPCIÓN / CLIENTE (es el summary), Cliente Nuevo, Nombre del Cliente, adjunto de cotización/CSF, Tipo de Moneda, Días de Crédito, Facturación recurrente, Periodo de recurrencia y Monto sin IVA. Es el contrato más completo. ⚠️ Cambió desde el 30-jul: se agregó Monto sin IVA y desapareció Periodo de Incidencias.
Automatización (389) Solo exige Summary.
Facturación (12) Solo exige Summary.

🔴 “Todos los request types” incluye tickets sin request type

La bandeja de FAC muestra en el filtro de la UI 6 de 6 opciones: las 4 de arriba más Empty y Emailed request. Ninguna de esas dos aparece en servicedeskapi porque no están publicadas en el portal. El conteo real sobre los 69 tickets de FAC (10-ago):

Request type Tickets c/Monto c/Moneda c/Cliente c/Adjunto
83 — Facturación adicional 48 2 48 48 48
(sin request type) 10 0 0 0 3
84 — Bajas 6 0 0 6 6
389 — Automatización 4 0 0 0 4
12 — Facturación 1 0 0 0 1

Los 10 tickets sin request type tienen creator y reporter = Automation for Jira: nacen de una regla de Automation desde otras bandejas (HH, SA, IN, RH), no del portal. Y no son ruido: FAC-91 es uno de ellos, está vivo en En validación nacional y su summary es [FACTURA COMPLETA - Staff Augmentation] Axians - Incident Manager — RH-36. Es decir, hay facturación real entrando por una vía que no tiene ni un solo campo estructurado — los datos viajan codificados en el summary y en la description (ADF), más 2 adjuntos.

Emailed request hoy tiene 0 tickets, pero existe en la configuración: cualquier correo a la bandeja aterriza ahí, también sin campos.

Implicación: el acuerdo literal “todos los request types” significa que ~14% de los tickets no puede generar una cotización automática con el diseño de campos estructurados. Hay dos salidas y conviene que Balam elija explícitamente: (a) acotar la automatización a los request types que sí traen campos y dejar los demás en tratamiento manual, o (b) que Automation for Jira propague los campos al crear el ticket en FAC. La opción (b) es trabajo del lado de Balam, no de la plataforma.


Bloque 2 — Modelo de datos del ticket FAC (el mapeo) 🔴

Esto es lo que decide si la integración es de 10 h o de 25. La pregunta de fondo: ¿los datos de facturación vienen en campos estructurados o en texto libre? Si vienen en texto libre, hay que negociar campos nuevos con Pedro o meter parsing frágil.

Lo que la plataforma necesita de cada ticket para armar una cotización en BIND:

Dato requerido Por qué Qué verificar
Cliente Match contra Clients de BIND (por RFC o nombre normalizado) ¿Campo custom? ¿Lista desplegable? ¿Texto libre? ¿Trae RFC?
Monto y moneda Cotización BIND; la cartera jamás mezcla monedas ¿Campo numérico? ¿Viene la moneda separada o embebida en el texto?
Nacional vs internacional Determina PDF+XML (nacional) vs solo PDF (extranjero) ¿Se deduce del cliente o hay campo/etiqueta?
Concepto / descripción Línea de la cotización Ver formato (ver ⚠️ ADF abajo)
Tipo de solicitud adicional / recurrente / baja / headhunting / staff augmentation ¿Request type, issue type, o campo?
Folio FAC-nnn Trazabilidad ticket ↔ cotización ↔ factura (persistir en el modelo) Confirmar formato y estabilidad (ver Bloque 5, ⚠️ moves)
Solicitante / área Auditoría reporter vs requester de JSM (no son lo mismo)
Adjuntos Constancia fiscal, Excel de horas (CEMEX), estado de cuenta Cómo se descargan y con qué auth

Resultados de lectura:

GET /rest/api/3/issue/FAC-98?expand=names,renderedFields

→ caso real de tipo Bajas: cliente Axians, colaborador, fecha y motivo de baja en campos estructurados; una evidencia adjunta; sin descripción. Los valores de texto enriquecido regresan como ADF.

Mapeo de campos confirmado (10-ago)

Campo de Jira fieldId Tipo Valores → BIND
Empresa origen customfield_11423 option Balam, RegioTurk, Helmstone Emisor (multi-empresa)
MES / DESCRIPCIÓN / CLIENTE summary string texto libre Referencia / parseo de respaldo
Cliente Nuevo customfield_10052 option Si, No Decide si hay que dar de alta el cliente
Nombre del Cliente customfield_10202 ADF (textarea) texto enriquecido Match contra Clients de BIND
Tipo de Moneda customfield_10053 option MXN, USD, OTRO Moneda de la cotización
Días de Crédito customfield_10054 option 30, 45, NA Condiciones de pago
Facturación recurrente customfield_10552 option Si, No Fuera de alcance por ahora (Arturo, 4-ago)
Periodo de recurrencia customfield_10553 string texto Fuera de alcance por ahora
Monto sin IVA customfield_11556 number/float Total de la cotización
Approvers customfield_10003 array/user Gobierno (ver Bloque 3)

⚠️ Nombre del Cliente es ADF, no string. El match contra BIND tiene que extraer texto plano de un documento estructurado, no leer un campo de texto. Nada garantiza que el nombre escrito a mano coincida con la razón social en BIND; el campo no trae RFC, que sería la llave confiable.

🔴 Dos huecos que el acuerdo del 4-ago no cierra

  1. Monto sin IVA existe pero está prácticamente vacío. Solo 2 de 69 tickets lo tienen: FAC-100 y FAC-101, ambos creados el 4-ago — el mismo día en que Arturo contestó el correo. El campo se agregó en ese momento; los 67 tickets anteriores lo tienen en null. Es buena noticia (el acuerdo ya se implementó) con dos consecuencias: no hay histórico para validar el mapeo contra facturas reales, y la obligatoriedad solo aplica al crear por portal — un ticket nacido de Automation entra con null igual.

  2. conceptos / partidas no existe como campo en NINGUNA parte del sitio. GET /rest/api/3/field filtrado por monto/concepto/partida/importe/precio/cantidad/RFC devuelve únicamente:

    • customfield_11556Monto sin IVA (en uso)
    • customfield_11522Monto con IVA (existe, no está en el formulario 83)
    • customfield_10031Total forms (de JSM, no es de facturación)

    Con un solo monto agregado no se pueden armar partidas: la cotización BIND queda de una sola línea con la descripción del summary. Eso puede ser aceptable como decisión, pero hay que tomarla explícitamente, y no cubre el caso ACUNTIA. Que exista Monto con IVA sin usar además abre la pregunta de si el IVA lo calcula BIND o viene dado.

El caso ACUNTIA ya tiene evidencia: FAC-100 es exactamente eso — summary Julio/CONSULTORIA Y SERVICIOS (Eduardo Fiallo CEMEXUSA)/ACUNTIA, Helmstone, USD, 45 días, Monto sin IVA = 7594.00, con 2 adjuntos. Un solo monto para un ticket que históricamente representa 4048 facturas (REGISTRO #55 punto 6). El supuesto “un ticket → una cotización” necesita confirmarse contra este caso antes de codificar.

⚠️ ADF (Atlassian Document Format). En Jira Cloud v3, description y los comentarios no son texto plano ni wiki markup: son JSON estructurado. Hay que decidir ya si se parsea ADF o se pide expand=renderedFields (HTML). Y al escribir comentarios/descripciones hay que construir ADF válido, no mandar un string. Es la trampa que más tiempo cuesta si se descubre tarde.

⚠️ Adjuntos: confirmar si content (URL de descarga) requiere el mismo Basic auth y si redirige. Y aplica la misma regla que con BIND: los adjuntos traen datos reales de clientes (constancias, estados de cuenta) — no van a disco del repo ni a documentos.


Bloque 3 — Workflow, estatus y transiciones (el disparador) 🟡

Disparador confirmado por Arturo el 4-ago: la cotización BIND se crea al entrar a En proceso de facturación. El inventario técnico ya estaba levantado, así que la regla de negocio queda cerrada.

Inventario confirmado:

GET /rest/api/3/project/FAC/statuses          → estatus por tipo de issue, con id y statusCategory
Estatus ID Categoría
Open 1 To Do
En proceso de facturación 10305 In Progress
Facturado 10306 Done
En espera por colaborador 10339 In Progress
Cancelado 10372 Done
En validación nacional 10635 In Progress
En validación extranjera 10669 In Progress

Transiciones de lectura confirmadas (son contextuales al estatus actual):

Ticket / estatus actual transitionId Destino
FAC-98 / En proceso de facturación 6 En espera por colaborador
FAC-98 / En proceso de facturación 8 En validación nacional
FAC-98 / En proceso de facturación 9 En validación extranjera
FAC-98 / En proceso de facturación 2 Cancelado
FAC-91 / En validación nacional 2 Cancelado
FAC-89 / Cancelado 12 Open

FAC-97 ya está Facturado y no expone transiciones. Las respuestas consultadas no devolvieron campos obligatorios para las transiciones anteriores. Aun así, no se ejecutará ninguna transición sin la sesión acompañada.

Diagrama de workflow compartido por Balam: confirma la ruta completa y los nombres de transición:

Open --[Iniciar facturación]--> En proceso de facturación
En proceso de facturación --[Pausar actividad]--> En espera por colaborador
En espera por colaborador --[Retomar actividad]--> En proceso de facturación
En proceso de facturación --[Validar documentación nacional]--> En validación nacional
En proceso de facturación --[Validar documentación extranjera]--> En validación extranjera
En validación nacional o extranjera --[Facturación completa]--> Facturado
En validación nacional o extranjera --[Rechazar actividad]--> En proceso de facturación

El diagrama también contempla cancelación desde los estados de trabajo y reapertura; la API confirmó al menos Cancelado --[Reabrir Ticket]--> Open en FAC-89. No existe un estado “Resuelto” en el workflow. Con la respuesta del 4-ago, la regla queda: Iniciar facturación (Open → En proceso de facturación) dispara la cotización; Facturado confirma que la factura se emitió.

🔴 Hallazgo crítico: el estatus disparador dura minutos, no horas

Recorrido real de FAC-100 (45 ago), desde su changelog:

Hora Transición Autor
05-ago 11:51:25 OpenEn proceso de facturación Arturo Rosas
05-ago 11:54:09 En validación extranjera Arturo Rosas
05-ago 12:16:37 Facturado Araceli Sánchez

El ticket estuvo 2 minutos 44 segundos en el estatus disparador, y 25 minutos de punta a punta. Hoy solo 1 de los 69 tickets está parado en En proceso de facturación (65 ya están Facturado).

Consecuencia de diseño, no negociable: un poller de 15 min que pregunte “¿qué tickets están hoy en En proceso de facturación?” se pierde la mayoría de los disparos. La detección tiene que leer el changelog y buscar el cruce de estado dentro de la ventana, exactamente como se resolvió la detección de pagos en BIND (ADR-004). Esto confirma y vuelve obligatorio lo que antes era una preferencia de arquitectura, y refuerza el caso de los webhooks (Bloque 4) para reducir la latencia.

Hallazgo nuevo: el workflow tiene aprobaciones de JSM

Ni FAC-98 ni el diagrama lo mostraban. Tanto FAC-100 como FAC-91 traen:

  • customfield_10003 Approvers = Araceli Sánchez
  • customfield_10025 Approvals = el estatus donde vive la aprobación (En validación extranjera / En validación nacional)

Es decir, el paso a Facturado pasa por una aprobación formal de Araceli, no por una transición simple. Implicaciones: (1) la plataforma no debe intentar aprobar — eso es decisión humana; (2) si algún día tuviera que transicionar a Facturado, la vía correcta es /rest/servicedeskapi/request/{id}/approval, no /transitions; (3) la aprobación es un buen punto de trazabilidad para saber quién autorizó cada factura.

⚠️ Trampas:

  1. Facturado como estatus ≠ campo resolution. Resuelto (10-ago): en FAC-100, status = Facturado y resolution = Done y resolutiondate poblada, todo consistente. Ambas señales sirven; se usará el cruce de estatus en el changelog por coherencia con el resto del diseño.
  2. Las transiciones son contextuales: /transitions solo devuelve las salidas del estado actual, y pueden tener pantallas con campos obligatorios. Probar con expand=transitions.fields para saber si transicionar por API exige llenar algo.
  3. issuetype de FAC es admon, no “Service Request”. Cualquier JQL o creación por API debe usar ese nombre.

Changelog = la fuente de la detección. expand=changelog da cada cambio de estatus con timestamp y autor. Verificado en FAC-100 (total: 6) y FAC-91 (total: 8): vienen completos y sin paginar en tickets de este tamaño. Para tickets con mucho historial hay que usar /rest/api/3/issue/{key}/changelog, que sí pagina.


Bloque 4 — Estrategia de sincronización: polling vs webhooks 🟡

El scheduler de la plataforma ya existe (BackgroundService + PeriodicTimer a 15 min). La pregunta es qué le pega a Jira.

a) Búsqueda por JQL — validado. El endpoint clásico GET /rest/api/3/search respondió 410 Gone. La integración debe usar GET /rest/api/3/search/jql, con nextPageToken. La lectura de FAC recuperó 66 tickets con ese mecanismo.

JQL de delta a validar:

project = FAC AND updated >= "-20m" ORDER BY updated ASC

⚠️ updated en JQL tiene granularidad de minuto, no de segundo → el checkpoint necesita ventana de solape (igual que el re-barrido de facturas abiertas de BIND) o se pierden tickets en el borde.

Validar también: fields= para pedir solo lo necesario (menos payload, menos puntos), y el tope real de maxResults.

b) Webhooks. Tres caminos, con dueños distintos:

Opción Quién la configura Nota
Webhook de sitio (admin) Pedro (requiere admin de Jira) El más limpio; exige endpoint público
Regla de Jira Automation con "Send web request" Pedro, sin escribir código La más realista a corto plazo; se puede acotar a FAC y a un estatus
Webhook dinámico vía OAuth app Desarrollo Expiran a los 30 días, hay que refrescarlos

Recomendación: arrancar con polling y dejar el webhook para después. Ningún webhook sirve hasta que exista un endpoint público, y Azure sigue pendiente del lado de Balam. El polling además es reversible y no depende de que Pedro toque su instancia.

c) Rate limits — headers verificados (10-ago). La respuesta de /rest/api/3/search/jql sí los emite:

X-RateLimit-Limit: 350
X-RateLimit-Remaining: 348
RateLimit-Policy: "jira-burst-based";q=100;w=1
RateLimit: "jira-burst-based";r=348;t=1

Tres notas: (1) la telemetría existe y el autorregulado por headers es viable, como se le dijo a Erika el 29-jul; (2) el límite observado es 350, no los 100/s que mencionó Pedro — hay que leer el header y no hardcodear el número; (3) aparecen también los headers estándar RateLimit-* (RFC) además de los X-RateLimit-*, así que el cliente debe tolerar ambos. X-RateLimit-NearLimit no apareció porque no se llegó al 20% del umbral. No se provocó un 429 deliberadamente contra producción.


Bloque 5 — La bandeja padre: de dónde nacen realmente los tickets 🟡

Pedro dijo que procesos que se cierran en RH o Administración General caen en Facturación. Técnicamente eso puede ser cuatro cosas distintas, y cada una se sincroniza diferente:

Mecanismo Cómo detectarlo Implicación
Issue link (RH-45 relacionado con FAC-89) issuelinks en el issue Escuchar FAC basta; el link da contexto
Clon / creación por Automation changelog + campo creator (usuario de automation) Escuchar FAC basta
Subtarea / hijo parent / subtasks Relevante para ACUNTIA (1 ticket ↔ 40 facturas)
Move entre proyectos changelog con cambio del campo project 🔴 La llave del ticket CAMBIA (RH-45 → FAC-89). Cualquier folio persistido se rompe

Resultado de la prueba (10-ago): es creación por Automation, no move.

Los 10 tickets sin request type tienen creator = reporter = Automation for Jira, y sus changelogs (revisados en FAC-91) no muestran cambios de project ni de key. El patrón es: la regla de Automation crea un ticket nuevo en FAC y lo liga al original con issuelinks. Ejemplos de summary, que llevan el origen embebido:

FAC-91   [FACTURA COMPLETA - Staff Augmentation] Axians - Incident Manager — RH-36
FAC-1    Seguimiento del Ticket Cerrado: HH-1 - Prueba #1
FAC-28   Seguimiento del Ticket con pago anticipado: HH-8 - TLE

Se ven tres bandejas de origen: HH (headhunting), SA (staff augmentation), IN, y RH. Dos patrones de regla: Seguimiento del Ticket Cerrado: y Seguimiento del Ticket con pago anticipado: — el segundo probablemente implique PUE y toca la pregunta pendiente de PUE/PPD.

Conclusiones para el modelo de datos:

  • Escuchar FAC basta para detectar el disparo; el origen se obtiene de issuelinks sin salir del proyecto.
  • No hay evidencia de moves, así que la llave FAC-nnn parece estable. Aun así conviene persistir el issue.id numérico (FAC-100 = 17308, FAC-91 = 14348): es inmutable por diseño y el costo de guardarlo es cero.
  • ⚠️ Estos tickets son la vía sin campos estructurados del Bloque 1. Si la automatización debe cubrirlos, la regla de Automation de Balam tendría que propagar los campos al crear el ticket en FAC.

Bloque 6 — Escritura (CRUD): qué probar, cómo aprobarlo y dónde 🔴

Confirmado por Noé el 7-ago: prueba acompañada sobre un ticket acordado. No habrá proyecto FACTEST. Eso cierra la pregunta pero deja el riesgo intacto: se escribirá en producción, y el token tiene permisos para crear, editar, transicionar, comentar, adjuntar e incluso borrar tickets en FAC. El protocolo de abajo pasa de recomendación a requisito, y el sandbox propio (ver recuadro al final del bloque) pasa de opcional a necesario para desarrollar sin tocar Balam.

Protocolo obligatorio para cualquier prueba de escritura:

  1. Preparar un script idempotente y de una sola operación; sin bucles, sin búsquedas masivas y sin credenciales embebidas.
  2. Compartir el script y el payload de ejemplo con Pedro/Arturo antes de la sesión; documentar endpoint, ticket destino, efecto esperado y reversión.
  3. Acordar el ticket de prueba y una ventana de ejecución. Preferir un proyecto sandbox (FACTEST) o un ticket creado expresamente para la prueba.
  4. Ejecutarlo acompañado, registrar el HTTP status, el issue.id/key y verificar el resultado por API.
  5. No probar DELETE; no es una capacidad necesaria para la plataforma y no es reversible en producción.

Operaciones a validar, en este orden (de menos a más invasivo):

  1. ComentarPOST /rest/api/3/issue/{key}/comment (cuerpo en ADF). ⚠️ En JSM hay comentarios públicos (los ve el cliente) vs internos: POST /rest/servicedeskapi/request/{id}/comment con public: true|false. La plataforma debe escribir SIEMPRE internos. Publicar por error un comentario visible al cliente es el error más caro y menos reversible de este bloque.
  2. AdjuntarPOST /rest/api/3/issue/{key}/attachments. ⚠️ Exige el header X-Atlassian-Token: no-check y multipart/form-data. Sin ese header falla con un error que no explica nada. Es la vía para dejar el PDF/XML como evidencia en el ticket.
  3. TransicionarPOST /rest/api/3/issue/{key}/transitions con el transition.id del Bloque 3.
  4. Crear — decisión real de diseño: POST /rest/api/3/issue (crudo, se salta el request type y el ticket queda "raro" en el portal) vs POST /rest/servicedeskapi/request (respeta request type y se ve como uno normal). Si es JSM, la segunda es la correcta.
  5. EditarPUT /rest/api/3/issue/{key}.
  6. BorrarDELETE /rest/api/3/issue/{key}. Requiere permiso de admin de proyecto. Probablemente ni se tenga ni convenga tenerlo; en producción el borrado no debe ser una capacidad de la plataforma.

🔴 Dónde probar. Pedir a Pedro un proyecto de pruebas FACTESTdescartado por Noé el 7-ago: será prueba acompañada sobre un ticket. Queda entonces una sola vía de mitigación:

Crear un sitio propio y gratuito de Jira Cloud (plan Free, hasta 10 usuarios) con un proyecto JSM que replique el workflow de FAC. Sirve para desarrollar el cliente, el parser de ADF, la paginación, las aprobaciones y las transiciones sin tocar nada de Balam ni depender de que respondan. Es el sandbox que BIND nunca tuvo. Contra producción solo se corre lectura y, al final, la única prueba acompañada.

Con el FACTEST descartado, esto ya no es una alternativa: es el único lugar donde se puede equivocar sin costo.


Bloque 7 — Gobierno y seguridad 🟡

  • propuesta/token-jira.txt NO está en .gitignoreResuelto: ignorado en .gitignore:9. Sigue pendiente mover el token a user-secrets / Key Vault y borrarlo de disco. Mismo pendiente que arrastra bind_token_api.txt.
  • Cuenta de servicio vs cuenta personal de Pedro (ya planteado en el borrador de correo del 29-jul): hoy todo lo que la plataforma escriba en Jira queda firmado con el nombre de Pedro, y una rotación suya deja la integración muerta. Verificar con GET /rest/api/3/myself con qué identidad se está actuando. Sin respuesta al 10-ago.
  • 🔴 Alcance de permisos: validado con GET /rest/api/3/mypermissions para FAC. El token puede navegar, crear, editar, transicionar, comentar, adjuntar y borrar tickets. Es un alcance excesivo para producción; la integración no debe implementar borrado y conviene migrar a una cuenta de servicio con permisos mínimos.
  • Vigencia 27-jul-2027 → dejar registrado el vencimiento y el plan de rotación desde ahora.
  • Datos de clientes en adjuntos y descripciones — misma regla que BIND: nunca a disco del repo ni a documentos compartidos.

Bloque 8 — Preguntas para Pedro / Balam (no se resuelven con la API)

Cerradas con el correo del 7-ago:

  1. ¿Puede crear un proyecto de pruebas FACTEST?No. Prueba acompañada sobre un ticket (Noé, 7-ago).
  2. ¿Debe observarse Facturación adicional (83), Facturación (12) u otro?Todos los request types de la bandeja (Arturo, 4-ago). ⚠️ Con la salvedad del Bloque 1: 10 tickets no tienen request type ni campos.
  3. ¿Cuál estatus dispara la cotización?En proceso de facturación (Arturo, 4-ago).
  4. ¿Monto del adjunto o como campo?Campo de Jira. Ya implementado (customfield_11556), omitiendo recurrencia (Arturo, 4-ago).

Abiertas:

  1. 🔴 ¿De dónde salen los CONCEPTOS/partidas? El acuerdo resolvió el monto pero no los conceptos, y no existe campo para ellos en el sitio. ¿Cotización de una sola línea con el summary como descripción, o se agrega un campo?
  2. 🔴 ¿Qué pasa con los tickets creados por Automation for Jira (10 de 69, sin ningún campo estructurado, incluido FAC-91 que está vivo)? ¿Se acota la automatización o la regla de Automation propaga los campos?
  3. 🔴 ACUNTIA / FAC-100: ¿un ticket con Monto sin IVA único debe generar una cotización, o sigue siendo el caso de 4048 facturas?
  4. ¿Nacional vs extranjero cambia la cotización o solo el paquete de salida (PDF+XML vs PDF)? Hay dos estatus de validación distintos y una aprobación por cada rama.
  5. ¿Quién puede crear webhooks o reglas de Automation apuntando a una URL nuestra, y bajo qué proceso? Gana urgencia: el estatus disparador dura minutos (Bloque 3).
  6. PUE vs PPD — la pregunta que no se ha alcanzado a hacer en cuatro sesiones (REGISTRO #52). Los tickets Seguimiento del Ticket con pago anticipado: sugieren que sí hay casos PUE reales.
  7. Cuenta de servicio en lugar de la cuenta personal de Pedro, y fecha para la prueba acompañada.

Orden de ataque sugerido

# Acción Bloqueado por
1 Blindar el token (.gitignore) — falta secrets/Key Vault
2 Mapeo de campos y contratos de request type verificados (10-ago)
3 Implementar lectura con /search/jql, cursor y ventana de solape
4 Detección por changelog del cruce a En proceso de facturación — (ya desbloqueado por el acuerdo del 4-ago)
5 Parser de ADF para Nombre del Cliente + match contra Clients de BIND ⚠️ Sin RFC; definir tolerancia del match
6 Armado de la cotización BIND 🔴 Definición de conceptos/partidas (pregunta 5)
7 Levantar un sandbox Jira propio (plan Free) — (ya no depende de Balam)
8 Preparar y compartir el script de escritura mínimo para revisión
9 Ejecutar una única prueba de escritura acompañada Fecha de Balam + script revisado + ticket acordado

Lo que puede avanzar ya: el cliente de lectura, manejo de ADF, paginación por cursor, mapeo de campos, detección incremental por changelog y el sandbox propio. Lo único que sigue bloqueado es el armado final de la cotización, por la definición de conceptos. La escritura queda fuera del flujo automático hasta la sesión acompañada.


Briefing corto para desarrollo / revisión técnica

Contexto validado: Jira Cloud JSM en balam-jsm-temp.atlassian.net; proyecto FAC company-managed (projectId: 10034, serviceDeskId: 35). La autenticación directa con Basic email:token funciona. El token tiene permisos de escritura amplios, pero no se debe ejecutar ningún POST, PUT o DELETE fuera de una prueba acompañada y aprobada.

Para la capa de lectura, usar GET /rest/api/3/search/jql, paginar por nextPageToken y aplicar una ventana de solape al checkpoint de updated. No usar /rest/api/3/search: responde 410.

Para JSM, usar /rest/servicedeskapi al consultar request types y su contrato de campos. FAC publica 4 request types: Bajas (84), Facturación adicional (83), Automatización (389) y Facturación (12); los cuatro contratos están verificados. Facturación adicional (83) es el único con datos de facturación e incluye Monto sin IVA (customfield_11556, number). No existe campo de conceptos/partidas en el sitio.

El disparador acordado es el cruce a En proceso de facturación, y dura minutos (FAC-100: 2m44s). La detección debe leer el changelog y buscar el cruce dentro de la ventana; consultar el estatus actual no sirve. El issuetype es admon. El workflow tiene aprobaciones de JSM con Araceli como aprobadora en las ramas de validación nacional/extranjera: la plataforma nunca aprueba.

10 de 69 tickets nacen de Automation for Jira desde HH/SA/IN/RH, sin request type y sin ningún campo estructurado; los datos van en el summary y la description (ADF), con el origen en issuelinks. Persistir el issue.id numérico además de la llave.

Pendientes técnicos: parser de ADF para Nombre del Cliente (no trae RFC), armado de la cotización cuando se defina el tema de conceptos, y diseñar un script de escritura de una sola operación para revisión previa. El script debe ser idempotente, no incluir credenciales y ejecutarse únicamente en el sandbox propio o acompañado en el ticket de prueba acordado. No habrá FACTEST.