Ir al contenido

API de defectos

Los defectos son registros de bugs por proyecto con numeración secuencial (defectNumber, mostrado como D-<n> en la interfaz). El reporter se deriva del actor autenticado al crear y no puede enviarse en el cuerpo de la petición.

POST/api/v1/projects/{projectId}/defects

{projectId} es el código del proyecto (por ejemplo ACME).

CampoObligatorioNotas
titleCadena no vacía
descriptionnoTexto Markdown
assigneeUlidnoULID de miembro de la organización
tagsnoArreglo de cadenas
milestoneUlidnoHito del mismo proyecto
customFieldValuesnoArreglo de { fieldUlid, value } para campos de defecto visibles. Los campos de sistema Severity y Priority son obligatorios con opciones por defecto de la organización; si omites valores que siguen siendo el predeterminado, el servidor los persiste. Otras claves omitidas se satisfacen al crear si el campo tiene un valor por defecto almacenado no vacío; en caso contrario el create devuelve 422 validation_failed.

reporter, resolvedAt y closedAt se rechazan si el cliente los envía.

Ventana de terminal
curl -sS -X POST \
-H "Authorization: Bearer $PROBARA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"El login falla con contraseña expirada"}' \
"https://probara.net/api/v1/projects/ACME/defects"
GET/api/v1/projects/{projectId}/defects

Paginación por página (page, pageSize), los más recientes primero. La respuesta sigue el formato de los listados de tabla (items, page, pageSize, total), donde total cuenta todos los defectos que coinciden con los filtros activos y q. Cada ítem incluye los campos del defecto más occurrenceCount, lastSeenAt (agregados desde intentos vinculados) y systemFieldValues (solo entradas de severidad/prioridad del sistema). Sin fields, los ítems del listado no incluyen customFieldValues.

Pasa fields como lista separada por comas de ULIDs de campos personalizados de defecto visibles en el proyecto para embeber customFieldValues en cada ítem (valor guardado o predeterminado materializado, mismo formato que el detalle). Un campo fuera del alcance del proyecto devuelve 422 validation_failed.

Los filtros se combinan con AND entre parámetros y se evalúan en el servidor. Los parámetros con valores de conjunto severity, priority y assigneeUlid aceptan un conjunto de ULID separados por comas y se combinan con OR dentro de cada parámetro; un valor único se acepta como un conjunto de un elemento, por lo que las URL anteriores con un solo valor siguen funcionando.

ParámetroNotas
statusConjunto separado por comas, p. ej. open,in_progress
severityConjunto separado por comas de ULID de opción del campo de sistema defect_severity (OR dentro; coincide con defectos que tengan cualquiera)
priorityConjunto separado por comas de ULID de opción del campo de sistema defect_priority (OR dentro)
assigneeUlidConjunto separado por comas de ULID de miembros de la organización (OR dentro); un ULID que no resuelve a ningún miembro se ignora, y el filtro no coincide con nada solo cuando ninguno resuelve
qSubcadena del título, o número de defecto con D-<n> o entero
agingAntigüedad de defectos abiertos: d0_7, d7_14, d14_30, d30plus (por created_at)
fieldsULIDs de campos personalizados separados por comas para embeber por ítem (customFieldValues)
cfFiltro repetible por campo personalizado: <fieldUlid>:<valor[,valor…]> (ver abajo)

Valores de status inválidos devuelven 422 validation_failed.

Repite el parámetro cf una vez por campo. Varias entradas cf se combinan con AND. Dentro de un campo, los valores separados por comas se combinan con OR.

Tipos admitidos: select, select_multi, checkbox y user_picker. Otros tipos (incluido paragraph) devuelven 422 validation_failed. Los filtros coinciden solo con filas de valor guardadas — un predeterminado materializado en lectura no satisface un filtro por opción hasta persistirse.

Token de valorSignificado
ULID de opciónDefecto guardado con esa opción (select) o que la contiene (select_multi)
true / falseValor guardado de casilla
ULID de miembroMiembro guardado en user_picker
emptySin fila guardada para el campo (incluidos defectos que mostrarían un predeterminado en detalle)

Ejemplo — defectos en Staging o Production (mismo campo, OR por comas):

GET /api/v1/projects/ACME/defects?cf=01HENVFIELD:01HSTAGING,01HPROD

Ejemplo — sin valor de Environment o Staging, y casilla Risk aceptado:

GET /api/v1/projects/ACME/defects?cf=01HENVFIELD:empty,01HSTAGING&cf=01HRISKFIELD:true

Ejemplo — embeber columnas Environment y Owner:

GET /api/v1/projects/ACME/defects?fields=01HENVFIELD,01HOWNERFIELD
GET/api/v1/projects/{projectId}/defects/metrics

Respuesta única para la franja de métricas del listado y la insignia de la barra lateral. Todas las cifras usan la organización y el proyecto activos; peticiones fuera del inquilino devuelven 404 not_found.

CampoDefinición
totalOpenDefectos en open o in_progress
openBySeverityObjeto con options (arreglo de { optionUlid, systemKey, name, icon, color, count } en orden de opción, incluyendo ceros) y unset (defectos abiertos sin fila de severidad)
agingPoblación abierta por antigüedad desde created_at: d0_7, d7_14, d14_30, d30plus
reopenRateDefectos distintos con ≥1 evento defect.reopened ÷ defectos distintos resueltos alguna vez (defect.status_changed con to resolved o closed); null si el denominador es 0
mttrMsMedia de resolved_at − created_at sobre defectos actualmente resolved/closed con resolved_at no nulo; null si no hay ninguno
byMilestonePoblación abierta por hito (ulid, name, count) más unassigned
GET/api/v1/runs/{runUlid}/defects

Lista defectos distintos vinculados a cualquier intento de la ejecución (join defect_result_linkstest_results de la ejecución). Cada ítem incluye los campos públicos del defecto más linkCountInRun (solo vínculos en esta ejecución) y systemFieldValues de severidad/prioridad. Devuelve { items: [...] } (sin paginación). Ejecuciones desconocidas o fuera del inquilino devuelven 404 not_found. Funciona en ejecuciones abiertas y cerradas.

GET/api/v1/defects/{defectUlid}

Devuelve el payload completo del defecto: vocabulario, ULIDs de personas, etiquetas, hito, referencia duplicate-of, marcas de tiempo del ciclo de vida, el resumen derivado (occurrenceCount, lastSeenAt, affectedCaseCount) y customFieldValues embebidos para cada campo de defecto visible en el proyecto (valor guardado o predeterminado materializado, con enriquecimiento de opciones cuando aplica). El listado de defectos del proyecto incluye customFieldValues solo cuando se solicita con fields.

Las definiciones con alcance de defecto se gestionan en GET/POST/PATCH/DELETE /api/v1/orgs/{orgUlid}/custom-fields con entity: defect. Los valores se almacenan por par (campo, defecto).

PUT/api/v1/defects/{defectUlid}/custom-field-values

Cuerpo: { "values": [ { "fieldUlid": "...", "value": ... }, ... ] } — una entrada por campo visible. Los campos obligatorios deben estar en el conjunto de escritura. Emite defect.updated con metadata.customFieldChanges (no un evento custom_field.* aparte).

PATCH/api/v1/defects/{defectUlid}/custom-field-values/{fieldUlid}

Cuerpo: { "value": ... }. En tipos anulables, null borra el valor; los obligatorios rechazan vaciados con 422 validation_failed. Devuelve el arreglo embebido completo customFieldValues del defecto.

PATCH/api/v1/defects/{defectUlid}

Actualización parcial de title, description, status, resolution, assigneeUlid, tags, milestoneUlid y duplicateOfUlid. Severidad y prioridad se editan con los endpoints de valores de campo personalizado, no con este PATCH.

Las transiciones de estado siguen un mapa guiado (open/in_progressresolved/closed; resolvedclosed/open; closedopen). Las transiciones ilegales devuelven 422 validation_failed con ruta de campo status. Los parches sin cambio de estado aplican otros campos sin emitir evento de estado.

  • Pasar a resolved o closed exige resolution.
  • resolution = duplicate exige duplicateOfUlid; las cadenas se aplanan al raíz canónico al escribir.
  • Reabrir a open desde resolved o closed limpia resolution, duplicateOfUlid y las marcas gestionadas; emite defect.reopened en lugar de defect.status_changed.
  • duplicateOfUlid debe apuntar a otro defecto del mismo proyecto cuando se usa.

Requiere rol owner, admin o member en la organización; un viewer recibe 403 forbidden antes de cualquier escritura.

Devuelve 404 not_found si el defecto no pertenece a la organización activa.

DELETE/api/v1/defects/{defectUlid}

Elimina el defecto de forma permanente. Responde 204 si tiene éxito; un GET posterior devuelve 404 not_found.

Los defectos pueden vincularse a intentos inmutables de ejecución (filas de test_results). El par (defecto, resultado) es único; repetir la misma petición devuelve el vínculo existente con 200.

POST/api/v1/defects/{defectUlid}/result-links
CampoObligatorioNotas
resultUlidResultado de una ejecución del mismo proyecto que el defecto
stepSnapshotUlidnoInstantánea de paso congelada perteneciente a ese resultado

Responde 201 en el primer vínculo y 200 si el par ya existía.

GET/api/v1/defects/{defectUlid}/result-links

Paginación por cursor (limit, cursor). Cada ítem incluye el vínculo, el autor, el estado/executedAt del resultado y el contexto de ejecución y caso.

DELETE/api/v1/defects/{defectUlid}/result-links/{linkUlid}

Responde 204. El vínculo debe pertenecer al defecto indicado.

GET/api/v1/test-cases/{caseUlid}/defects

Lista defectos vinculados previamente a cualquier resultado del caso, con occurrenceCount y lastSeenAt acotados al caso. Los defectos abiertos o en progreso aparecen antes que los resueltos o cerrados.

GET/api/v1/defects/{defectUlid}/affected-cases

Paginación por cursor (limit, cursor). Devuelve casos de prueba distintos vinculados mediante asociaciones de resultado. Cada ítem incluye testCaseUlid, testCaseTitle, caseNumber, displayId (la referencia del caso en el repositorio, {PROJECT_CODE}-{caseNumber}), occurrenceCount, lastLinkedAt, latestResult (la ejecución más reciente del caso en general, o null si nunca se ejecutó) y verification.

Cuando el estado del defecto es resolved, verification puede ser:

ValorSignificado
verifiedEl último resultado es passed con executedAt posterior a resolvedAt
failed_after_resolveEl último resultado es failed o blocked después de resolvedAt
pendingNo hay ejecución cualificada tras la resolución

Para defectos no resueltos, verification es null. Devuelve 404 not_found entre inquilinos.

Las mutaciones emiten defect.created, defect.updated, defect.status_changed, defect.reopened, defect.deleted, defect.linked y defect.unlinked en el feed de actividad de la organización (los eventos de vínculo también aparecen en el feed de la ejecución mediante run_id). Las mutaciones de evidencia y discusión también emiten defect.attachment_added, defect.attachment_deleted, defect.commented, defect.comment_updated y defect.comment_deleted. Las resoluciones duplicado incluyen duplicateOfUlid y una etiqueta D-<n> en los metadatos de defect.status_changed. Ver Eventos de auditoría.

GET/api/v1/defects/{defectUlid}/audit-events

Paginación por cursor (limit, cursor) sobre eventos con entityType defect y entityUlid igual al defecto. La respuesta coincide con el endpoint de auditoría de ejecuciones (events, nextCursor). Devuelve 404 not_found si el defecto no pertenece a la organización activa.

Las imágenes de evidencia se almacenan bajo el prefijo R2 de la organización. Tipos permitidos: PNG, JPEG, WebP. Máximo 10 MiB por archivo, hasta 10 archivos por solicitud de subida. Las subidas cargan el contador de almacenamiento defect_attachment de la organización.

Los visualizadores pueden listar adjuntos; solo miembros y roles superiores pueden subir o eliminar.

GET/api/v1/defects/{defectUlid}/attachments

Devuelve { attachments: [...] } en orden de subida (más antiguos primero). Cada ítem incluye ulid, mime, dimensiones, byteSize, originalFilename, uploadedBy, url, thumbUrl y createdAt.

POST/api/v1/defects/{defectUlid}/attachments

multipart/form-data con una o más partes file. Devuelve 201 con { attachments: [...] }. MIME no permitido o tamaño excesivo devuelve 422 validation_failed. Emite defect.attachment_added.

DELETE/api/v1/defects/{defectUlid}/attachments/{attachmentUlid}

Devuelve 204. Elimina la fila, ambos objetos R2 y reembolsa bytes de almacenamiento. Emite defect.attachment_deleted. Un ULID de adjunto de otro defecto devuelve 404 not_found.

Al eliminar un defecto se quitan todos los objetos de evidencia y se reembolsan los bytes antes del cascade.

Los comentarios son texto plano (recortado, no vacío, máximo 5000 caracteres) y admiten un nivel de respuestas en hilo, fijado y resolución de menciones @. La superficie de comentarios de defectos es estructuralmente idéntica a los comentarios de casos de prueba — consulta esa página para la referencia completa (semántica de respuestas, reglas de fijado, resolución de menciones, forma de la respuesta y eliminación en cascada). Esta sección solo lista las rutas y acciones de auditoría específicas de defectos.

Los visualizadores pueden listar comentarios; solo miembros y roles superiores pueden crear, editar, eliminar o fijar/desfijar. El listado usa paginación por cursor sobre comentarios de primer nivel (parentUlid ausente), con orden predeterminado del más antiguo al más reciente; el arreglo replies[] de cada elemento se mantiene cronológico sin importar el orden.

GET/api/v1/defects/{defectUlid}/comments

Consulta: limit (predeterminado 50, máximo 200), cursor, sort (oldest | newest, predeterminado oldest). Cada elemento lleva parentUlid, pinnedAt, pinnedBy, replyCount, mentions, y replies[] en línea; el pinned[] de la respuesta contiene el conjunto completo de fijados para el defecto. Las respuestas no se enumeran en el items[] plano — ver comentarios de casos de prueba para la forma completa de la respuesta y la advertencia sobre las respuestas.

POST/api/v1/defects/{defectUlid}/comments
CampoObligatorioNotas
bodyTexto recortado, 1–5000 caracteres
parentUlidnoResponde a un comentario de primer nivel existente en el mismo defecto (solo profundidad 1)

Devuelve 201. Emite defect.commented con un extracto de 140 caracteres.

PATCH/api/v1/defects/{defectUlid}/comments/{commentUlid}
CampoObligatorioNotas
bodyMisma validación que en crear

Solo el autor — los administradores no pueden editar el comentario de otro miembro (403 forbidden). Establece editedAt al tener éxito y vuelve a resolver las menciones. Emite defect.comment_updated.

DELETE/api/v1/defects/{defectUlid}/comments/{commentUlid}

Devuelve 204. El autor puede eliminar su propio comentario. Los administradores de la organización pueden eliminar cualquier comentario. Otros miembros reciben 403. Eliminar un comentario de primer nivel elimina en cascada sus respuestas, purgando sus adjuntos. Emite defect.comment_deleted (una vez por el comentario eliminado, más una vez por cada respuesta eliminada en cascada).

POST / DELETE /api/v1/defects/{defectUlid}/comments/{commentUlid}/pin

Cualquier miembro o rol superior puede fijar o desfijar cualquier comentario de primer nivel, sin importar la autoría; los visualizadores reciben 403. Fijar una respuesta devuelve 422 validation_failed. No hay límite de comentarios fijados por defecto. Emite defect.comment_pinned / defect.comment_unpinned.