# Worker durable y consulta de ejecución — T10 El worker usa PostgreSQL como cola durable. `WORKER_ENABLED=true` activa polling, reclamación, renovación y recuperación; false por defecto. Es independiente de REQUEST_API_ENABLED y FLOW_ADMIN_ENABLED, pero siempre exige el runtime DB restringido y Flyway separado. Puede desplegarse como proceso solo worker usando la misma imagen. No se ha desplegado esta versión. Defaults: 10 workers, lote máximo 10, polling 500 ms, lease 60 s y renovación cada 15 s. Variables WORKER_CONCURRENCY/BATCH/POLL_MS/LEASE_SECONDS/RENEW_SECONDS en .env.example y compose.yaml. La renovación debe ser menor que la mitad del lease. El scheduler reclama únicamente capacidad libre; no acumula una cola local de trabajos ya reclamados que caduquen esperando un thread. Los executors locales despachan trabajo; execution/action_execution conservan toda la evidencia durable. ## Protocolo y concurrencia Un CTE con FOR UPDATE SKIP LOCKED reclama PENDING/RETRY_WAIT vencidos y RUNNING con lease expirado. Orden next_attempt_at/created_at/id, límite de lote. En la misma transacción incrementa attempts/fencing_token y fija owner/lease con clock_timestamp de PostgreSQL. Se confirma antes de evaluar o invocar un adapter. Renovar requiere RUNNING, executionId/requestId, owner y token exactos, y lease aún vigente. Un lease vencido no revive por renovación. Reclamarlo aumenta el token; el propietario anterior no puede cargar, iniciar/guardar checkpoints, fallar ni confirmar el trabajo. Escrituras de checkpoint bloquean la ejecución y verifican lease con tiempo DB al inicio y antes del commit. Finalización/fallo bloquean solicitud y después ejecución; no hay transacciones abiertas mientras corre el adapter. El worker carga estado/revisión aceptados y la definición por flow_id fijado. Rechaza una solicitud modificada antes de llamar al adapter y vuelve a comprobar estado, revisión, versión y lease al finalizar. accepted_revision es la revisión posterior a aceptar T09. Un worker obsoleto que retorna después de otro no puede sobrescribir el resultado, aunque el proveedor haya procesado su llamada. ## Acciones y checkpoints WorkerActions es un registro de adapters confiable, consciente de versión, que declara capability/schemas/effect y ejecuta la acción. ActionContext contiene inputs resueltos, identidad mínima y clave externa estable `executionId:actionId`. No se aceptan capacidades ni URLs del evento. NO_OP sigue prohibido fuera de simulación. Antes de invocar se valida input y persiste checkpoint RUNNING, input_hash SHA-256, clave externa, clasificación de efecto e intento. Al retornar, valida output y lo guarda SUCCEEDED antes de avanzar. Tras recuperación, SUCCEEDED se reutiliza solo si hash/clave/effect coinciden; no vuelve a ejecutar el adapter. Los mappings de acciones posteriores usan los resultados recuperados. Cambio incompatible bloquea con error de contrato y conciliación; nunca se usa silenciosamente un resultado ajeno. V3 agrega action_execution.effect. Lo declara el adapter confiable, no el flujo. Checkpoints anteriores a V3 se clasifican conservadoramente NON_IDEMPOTENT_WRITE; no se inventa que eran seguros. V1/V2 no se alteran. Migración/rollback y permisos se verifican contra PostgreSQL 9.6.2 en la base de pruebas. Recuperación inicial: - Acción READ_ONLY o IDEMPOTENT_WRITE en curso puede retomarse con misma clave y hash, respetando maxAttempts del contrato de acción. - NON_IDEMPOTENT_WRITE RUNNING o UNKNOWN no se repite: ejecución pasa a RECONCILIATION_REQUIRED y la solicitud permanece bloqueada. - Un fallo posterior a escrituras exitosas o pendientes tampoco libera la solicitud como FAILED; se conserva para conciliación. - Fallo de persistencia final deja RUNNING/checkpoints existentes para recuperación por lease. Al reanudar no se repiten acciones ya SUCCEEDED. T12 programa reintentos transitorios seguros con backoff/jitter y Retry-After acotados. El checkpoint del intento, RETRY_WAIT y auditoría se confirman juntos; no se pierden éxitos anteriores. Agotamiento seguro termina FAILED; escrituras inciertas conservan el bloqueo para resolución administrativa. RECONCILIATION.md documenta límites, evidencia, replay y autorización. Los adapters T11 limitan sus timeouts y presupuesto de ejecución por debajo del lease y respetar la idempotencia externa; el token local no evita duplicados en el proveedor. ## Finalización Tras las acciones, el evaluador puro T05 decide destino/outcome. Los updates se calculan desde el snapshot original y resultados de acciones, se aplican sobre una copia y se valida dataSchema y límite de 256 KiB antes de confirmar. JSON Pointer admite objetos y posiciones existentes de arrays; no crea índices dispersos ni interpreta append `-`. Padres de objeto ausentes se crean como objetos y el schema final decide su validez. Nunca se actualiza identidad/ACL desde estos mappings. Transacción final comprueba todos los checkpoints esperados SUCCEEDED y actualiza data/estado/revisión de solicitud, resultado SUCCEEDED de execution y auditoría TRANSITION_COMPLETED con transitionId, actionIds, hitPolicy y ruleIds. Cualquier fallo revierte esos cambios juntos, conservando los checkpoints previos. ## Consulta y operación GET /api/v1/executions/{id} ya implementado bajo REQUEST_API_ENABLED. Reutiliza ResourceAccess y filtra owner/scope en SQL. Retorna ExecutionView con estado, resultado de negocio permitido y código de error seguro; no devuelve inputs de acciones, actor_snapshot, tokens, lease_owner ni respuesta cruda del proveedor. Recurso ajeno/inexistente retorna 404. Location de T09 ya puede consultarse. Apagado: detiene reclamación, conserva renovaciones durante hasta 20 s de drenaje, interrumpe trabajos restantes y deja de renovar. Checkpoints/leases permiten la recuperación. Un heartbeat que termina tarde no interrumpe otro trabajo que reutilice el thread. Los adapters deben tener tiempo de espera finito; la interrupción no garantiza cancelar un efecto externo, por eso se conserva la clasificación durable. T11 incorpora adapters HTTP y verificación documental en el registro productivo. Una acción sin contrato/ruta configurados falla con INTEGRATION_UNAVAILABLE. Los catálogos predeterminados están vacíos. Configurar contratos y rutas antes de habilitar integraciones; consultar INTEGRATIONS.md. NO_OP no puede ejecutarse. ## Evidencia y límites WorkerIT usa PostgreSQL real/JWT local y adapters exclusivamente de prueba. Las barreras verifican reclamantes concurrentes, SKIP LOCKED, fencing, retorno tardío, renovación durante acción, checkpoints tras caída, clave externa estable, efecto no seguro, rollback final, decisiones y autorización HTTP. SimulatedCrash abandona el intento sin guardar resultado; se reconstruye el adapter de persistencia y se recupera desde DB. No se anuncia una prueba de caída del proceso/JVM ni integración real con proveedor. La idempotencia del proveedor se demuestra solo con un doble explícito que deduplica por clave; T11/T16 comprobarán los contratos externos. Ejecutar `mvnw.cmd clean verify -Pmigration-tests-external` con credenciales solo en MIGRATION_TEST_DB_* y base orquestador_test. Sin ese perfil, verify necesita Docker para Testcontainers. Los esquemas y roles temporales propios se eliminan al finalizar.