Ir al contenido

API de configuración de ejecución

Cada proyecto tiene doce configuraciones de ejecución que gobiernan el comportamiento del marcado durante la ejecución de pruebas: si un run cerrado sigue aceptando escrituras de resultado, si aplica un bloqueo por responsable asignado, qué ocurre después de registrar un resultado, y más. Once de las doce heredan a través de una cadena de tres niveles, proyecto → organización → valor por defecto del código; la duodécima, defaultAssigneeUserId, es exclusiva del proyecto y no hereda en absoluto.

{projectId} es el código del proyecto (por ejemplo ACME) en todo lo siguiente; {orgUlid} es el ULID de la organización del solicitante.

Vocabulario y valores por defecto del código

Sección titulada «Vocabulario y valores por defecto del código»
ClaveTipoValor por defecto¿Hereda?
autoCompleteRunbooleantrueSí
allowResultsInClosedRunsbooleantrueSí
fastPassbooleantrueSí
defectToggleDefaultbooleantrueSí
autoAssignOnOpenbooleantrueSí
failCaseOnStepFailbooleanfalseSí
autoPassWhenAllStepsPassbooleanfalseSí
assigneeResultLockbooleanfalseSí
requireCommentOnNegativeResultbooleanfalseSí
afterAddingResult"stay" | "next_pending_by_number" | "next_pending_visual""next_pending_visual"Sí
timeTracking"off" | "optional" | "required""optional"Sí
defaultAssigneeUserIdULID de miembro | nullnullNo — exclusiva del proyecto

Un proyecto y una organización que no almacenan ningún valor para ninguna clave se comportan exactamente como el producto lo hacía antes de que existiera esta capacidad — cada valor por defecto del código anterior reproduce el comportamiento observable de hoy, con una excepción deliberada: allowResultsInClosedRuns tiene por defecto true, lo que formaliza un comportamiento de relajación del congelamiento que ya estaba vigente en la ruta de marcado individual antes de que esta capacidad se publicara. Una organización que prefiera el comportamiento anterior, más estricto, puede fijarlo en false.

  • autoCompleteRun — si un run se cierra automáticamente en cuanto todos sus casos tienen un resultado. Cuando es false, el run permanece abierto hasta que un miembro lo cierra explícitamente.
  • allowResultsInClosedRuns — si un run cerrado y no abortado sigue aceptando escrituras de resultado (marcados, marcados de paso, ediciones de notas de resultado, adjuntos de resultado). Un run abortado permanece congelado sin importar el valor de esta configuración, siempre. Consulta Casos de ejecución para el comportamiento exacto del 409.
  • fastPass / defectToggleDefault / requireCommentOnNegativeResult — experiencia de ejecución exclusiva del cliente web: si marcar passed/skipped omite el modal de resultado, el valor inicial del interruptor de defecto en el modal, y si un resultado negativo exige un comentario antes de enviarlo. Consulta la limitación conocida más abajo para la única configuración de este grupo sin contraparte en el servidor.
  • autoAssignOnOpen — si abrir un caso sin asignar autoasigna al usuario que actúa.
  • failCaseOnStepFail / autoPassWhenAllStepsPass — si un resultado a nivel de paso deriva automáticamente el estado del caso padre. Precedencia cuando ambas aplican: un paso fallido gana sobre un paso bloqueado, que gana sobre un conjunto de pasos completamente aprobado.
  • assigneeResultLock — si solo el tester asignado (o un solicitante exento) puede registrar un resultado para un caso asignado. Consulta Casos de ejecución para el comportamiento del 403.
  • afterAddingResult — qué caso enfoca el tablero de ejecución después de un marcado, únicamente en el cliente web. No es observable a través de la API.
  • timeTracking — si elapsedMs es opcional u obligatorio en un marcado individual con estado terminal. Consulta Casos de ejecución para el comportamiento del 422.
  • defaultAssigneeUserId — precompleta el responsable predeterminado de un run nuevo. Consulta Precedencia en la creación de runs más abajo.

Cada una de las once claves heredables se resuelve en este orden: un override explícito a nivel de proyecto gana; si no, un valor por defecto explícito a nivel de organización gana; si no, aplica el valor por defecto del código. Un null almacenado en cualquier nivel significa “sin override en ese nivel” — nunca se trata como el valor false o una cadena vacía.

La respuesta de cada clave heredable incluye:

CampoSignificado
valueEl valor efectivo resuelto — lo que realmente gobierna el comportamiento ahora mismo
source"project", "organization" o "default" — qué nivel produjo value
projectValueEl override crudo almacenado a nivel de proyecto, o null
organizationValueEl override crudo almacenado a nivel de organización, o null
organizationEffectiveEl valor efectivo propio de la organización (su override, o el valor por defecto del código)

source es lo que un cliente debe usar para mostrar el indicador de “sobrescrito” / “heredado de la organización” / “por defecto” — nunca comparar value contra organizationEffective. Un valor de proyecto que coincide con el valor efectivo de la organización sigue siendo un override almacenado: debe seguir mostrándose como tal y seguir siendo posible borrarlo, o un cambio posterior del valor por defecto de la organización afectaría silenciosamente a un proyecto que el usuario creía fijo.

defaultAssigneeUserId está exenta de la cadena — no tiene nivel de organización en absoluto, así que su entrada solo incluye value y source ("project" o "default"), nunca projectValue, organizationValue ni organizationEffective.

GET/api/v1/projects/{projectId}/run-settings

Abierto a cualquier lector del proyecto (viewer o superior). Devuelve 200 con las doce entradas.

{
"settings": {
"autoCompleteRun": {
"value": true,
"source": "default",
"projectValue": null,
"organizationValue": null,
"organizationEffective": true
},
"fastPass": {
"value": false,
"source": "project",
"projectValue": false,
"organizationValue": null,
"organizationEffective": true
},
"timeTracking": {
"value": "required",
"source": "organization",
"projectValue": null,
"organizationValue": "required",
"organizationEffective": "required"
},
"defaultAssigneeUserId": {
"value": "01J...MEMBER",
"source": "project"
}
}
}

(Abreviado — la respuesta real incluye las doce claves.)

PATCH/api/v1/projects/{projectId}/run-settings

Cada clave es opcional — una clave ausente se deja sin cambios, y un null explícito restablece esa clave a heredar (para defaultAssigneeUserId, de vuelta a ningún precompletado). Se requiere al menos una clave; un cuerpo vacío se rechaza con 422 validation_failed. Las claves desconocidas se rechazan de la misma manera (.strict()).

{ "fastPass": false, "requireCommentOnNegativeResult": null }

defaultAssigneeUserId acepta el ULID de un miembro, nunca el id entero interno, resuelto contra la membresía activa de la organización del proyecto — un ULID desconocido o ajeno se rechaza con 404 not_found, y no se persiste nada.

Devuelve 200 con la respuesta completa recién resuelta (misma forma que GET).

Requiere el permiso projects.manage (que tienen owner/admin), o el propietario actual del proyecto. Un miembro que solo puede leer el proyecto (viewer/member) recibe 403 forbidden.

Ventana de terminal
curl -sS -X PATCH \
-H "Authorization: Bearer $PROBARA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"fastPass": false, "assigneeResultLock": true}' \
"https://app.probara.net/api/v1/projects/ACME/run-settings"

Leer los valores predeterminados de la organización

Sección titulada «Leer los valores predeterminados de la organización»
GET/api/v1/orgs/{orgUlid}/run-settings

Abierto a cualquier miembro de la organización. Devuelve 200 con las once claves heredables únicamente — defaultAssigneeUserId nunca aparece aquí, porque no tiene nivel de organización.

{
"settings": {
"autoCompleteRun": { "value": true, "source": "default", "organizationValue": null },
"fastPass": { "value": true, "source": "organization", "organizationValue": true }
}
}

(Abreviado — la respuesta real incluye las once claves.)

Actualizar los valores predeterminados de la organización

Sección titulada «Actualizar los valores predeterminados de la organización»
PATCH/api/v1/orgs/{orgUlid}/run-settings

Misma semántica de “ausente = sin cambios” / “null explícito restablece al valor por defecto del código” que el endpoint de proyecto, restringida a las once claves heredables. Enviar defaultAssigneeUserId aquí se rechaza con 422 validation_failed como clave desconocida — nunca como un no-op silencioso, ya que el esquema solo declara las once claves heredables.

{ "timeTracking": "required" }

Requiere el permiso org-settings.manage.

Ventana de terminal
curl -sS -X PATCH \
-H "Authorization: Bearer $PROBARA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"autoCompleteRun": false}' \
"https://app.probara.net/api/v1/orgs/01J...ORG/run-settings"

«Fijar como valor predeterminado de la organización»

Sección titulada ««Fijar como valor predeterminado de la organización»»

Cambiar un valor predeterminado de la organización mueve el valor efectivo de cada proyecto que no almacena un override propio para esa clave — un proyecto que ya tiene su propio override con source: "project" no se ve afectado. El panel de configuración de proyecto de la aplicación web ofrece una acción «Fijar como valor predeterminado de la organización» en el menú de la fila de cualquier clave sobrescrita a nivel de proyecto (visible solo para quien tiene org-settings.manage), que es exactamente un PATCH al endpoint de organización con el valor de esa única clave a nivel de proyecto — no existe una superficie de API separada para ello.

Limitación conocida: requireCommentOnNegativeResult se aplica solo en el cliente

Sección titulada «Limitación conocida: requireCommentOnNegativeResult se aplica solo en el cliente»

Esta única configuración no tiene contraparte en el servidor. El texto del comentario llega en una solicitud separada de la del propio marcado (PATCH /api/v1/runs/{runUlid}/results/{resultUlid}), así que ninguna solicitud individual al servidor puede observar “este caso se marcó como fallido sin comentario” — aplicarlo en el servidor implicaría ampliar la solicitud de marcado con un cambio disruptivo desproporcionado para una única configuración de interfaz, o un barrido posterior sin disparador natural. Un cliente de API o de reportes puede marcar un caso como failed o blocked sin comentario mientras esta configuración está activa — el modal de resultado de la aplicación web es el único lugar donde se aplica esta regla. Cada una de las demás configuraciones de este documento hereda hacia un comportamiento del lado del servidor o tiene una brecha explícita y documentada por separado (consulta Casos de ejecución para la aplicación en el servidor de timeTracking, que sí es real).

Dónde aplica y dónde no timeTracking: "required"

Sección titulada «Dónde aplica y dónde no timeTracking: "required"»

El rechazo 422 elapsed_ms_required de timeTracking: "required" (consulta Casos de ejecución) solo se activa en una ruta de código que realmente invoca la lógica de marcado individual. Esta tabla es la auditoría completa de la superficie:

Superficie¿Llega al control?Aplica o está exenta
Marcado individual — PATCH /api/v1/runs/{runUlid}/cases/{runCaseUlid}Sí, directamenteAplica el 422
Herramienta MCP mark_run_caseSí — despacha al mismo endpoint textualmenteAplica — sin manejo especial en la herramienta, hereda el 422 del endpoint
Marcado en bloque — POST .../cases/bulk-mark (y MCP bulk_mark_run_cases)No — el esquema de la solicitud no lleva ningún campo de duración por casoExenta a nivel de esquema — no existe forma de construir una solicitud que lo viole
Envío de resultados en bloque — POST .../cases/bulk-submit-result (y MCP bulk_submit_result)No — pasa por un servicio distinto, nunca por la ruta de marcado individualExenta por diseño — el envío en bloque queda explícitamente fuera del alcance de este rechazo
Enriquecimiento de notas de resultado — PATCH /api/v1/runs/{runUlid}/results/{resultUlid}No — modifica una fila de resultado ya agregada (notes); nunca genera un cambio de estadoExenta — fuera de alcance estructuralmente, no lleva status
Ruta automatizada de ingesta de resultadosN/D — esta API no tiene hoy una superficie de ingesta de resultados por CSV/webhook/CINo aplica

defaultAssigneeUserId solo decide con qué empieza un run recién creado — cambiar la configuración del proyecto nunca reescribe el responsable ya almacenado de un run existente. POST /api/v1/projects/{projectId}/runs resuelve el responsable predeterminado del run en este orden:

  1. defaultAssigneeUlid presente en el cuerpo de la solicitud de creación del run (incluido un null explícito, que significa “deliberadamente ninguno”) — siempre gana.
  2. Si no, la configuración defaultAssigneeUserId del proyecto, cuando está definida.
  3. Si no, null — el comportamiento de hoy, sin cambios.