Documentos de Decision Gate

Evaluación de puertas determinista, reproducible con decisiones auditables.

Documentación de Asset Core

Introducción a Decision Gate

A primera vista

Qué: Ejecutar un escenario mínimo de Decision Gate localmente Por qué: Ver el ciclo de vida completo: definir -> iniciar -> evaluar Quién: Desarrolladores que integran Decision Gate en flujos de trabajo de CI/CD, agentes o cumplimiento Requisitos previos: Familiaridad con JSON-RPC 2.0 y curl

Modelo Mental: Ciclo de Vida del Escenario

La puerta de decisión evalúa puertas utilizando condiciones (verificaciones de evidencia). El ciclo de vida es:

1. scenario_define  -> registers a ScenarioSpec
2. scenario_start   -> creates a RunState (new run)
3. scenario_next    -> evaluates current stage and returns a DecisionRecord

Salidas clave de la API:

  • scenario_define devuelve { scenario_id, spec_hash }.
  • scenario_start devuelve el RunState completo.
  • scenario_next devuelve { decision, packets, status } (un NextResult).

¿Qué es un Escenario?

Un escenario es una definición de flujo de trabajo compuesta por:

  • Stages: Ordered steps in the workflow. Think of stages as the top-level Etapas: Pasos ordenados en el flujo de trabajo. Piensa en las etapas como la secuencia de nivel superior por la que te mueves a medida que avanza una ejecución.
  • Gates: Decision points inside a stage. A stage can include one or more Puertas: Puntos de decisión dentro de una etapa. Una etapa puede incluir una o más puertas que deben ser superadas para avanzar.
  • Conditions: Evidence checks used by gates. Each gate evaluates one or more Condiciones: Comprobaciones de evidencia utilizadas por los gates. Cada gate evalúa una o más condiciones para decidir si se aprueba.
  • Providers: Evidence sources (builtin or MCP). Conditions don’t fetch data Proveedores: Fuentes de evidencia (integradas o MCP). Las condiciones no obtienen datos por sí mismas; piden a los proveedores evidencia para evaluar.

Los proveedores pueden ser:

  • Integrado: time, env, json, http
  • MCP externo: cualquier herramienta que implemente el protocolo evidence_query

Inicio Rápido

Paso 0: Obtén la CLI

Si instalaste el CLI, utiliza decision-gate. Si estás ejecutando desde el código fuente, utiliza cargo run:

# Installed binary
decision-gate --help

# From source (repo checkout)
cargo run -p decision-gate-cli -- --help

Prueba de humo de un solo comando: scripts/bootstrap/quickstart.sh (bash/WSL) o scripts/bootstrap/quickstart.ps1 (PowerShell) ejecuta el flujo completo de definir → iniciar → siguiente → ejecutar paquete → prechequeo con IDs únicos.

Paso 1: Elegir un Preset

Elija una configuración preestablecida de configs/presets/ (detalles en preset_configs.md). Para esta guía, utilice Quickstart-Dev para que la primera ejecución sea sin fricciones.

Otros ajustes preestablecidos:

  • Recomendado por defecto: solo local + mapeo principal explícito.
  • Endurecido: se requiere autenticación de portador + firma de esquema.
  • Container-Prod: autenticación de portador + terminación TLS ascendente (línea base del contenedor).

Si deseas editar la configuración, primero copia el ajuste preestablecido:

cp configs/presets/quickstart-dev.toml decision-gate.toml

Notas:

  • El id del espacio de nombres predeterminado 1 está bloqueado a menos que namespace.allow_default = true y el id del inquilino esté listado en namespace.default_tenants.
  • Para enlaces HTTP/SSE que no son de bucle inverso, Decision Gate requiere --allow-non-loopback más TLS o server.tls_termination = "upstream" y autenticación no local. Consulte security_guide.md.
  • Consejo de Windows: PowerShell/CMD no soportan curl en múltiples líneas al estilo bash. Utilice un comando de una sola línea o la cadena aquí @'... '@ de PowerShell.

Paso 2: Iniciar el Servidor MCP

# Installed binary:
decision-gate serve --config configs/presets/quickstart-dev.toml

# From source (repo checkout):
# cargo run -p decision-gate-cli -- serve --config configs/presets/quickstart-dev.toml

Paso 3: Definir un Escenario

Este escenario se basa en una verificación de tiempo: time.after(timestamp).

Si utiliza la configuración Hardened: añada -H 'Authorization: Bearer <token>' a cada curl, y cambie a un espacio de nombres no predeterminado (por ejemplo, namespace_id: 2) porque allow_default = false.

curl -s http://127.0.0.1:4000/rpc \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "scenario_define",
      "arguments": {
        "spec": {
          "scenario_id": "quickstart",
          "namespace_id": 1,
          "spec_version": "v1",
          "stages": [
            {
              "stage_id": "main",
              "entry_packets": [],
              "gates": [
                {
                  "gate_id": "after-time",
                  "requirement": { "Condition": "after" }
                }
              ],
              "advance_to": { "kind": "terminal" },
              "timeout": null,
              "on_timeout": "fail"
            }
          ],
          "conditions": [
            {
              "condition_id": "after",
              "query": {
                "provider_id": "time",
                "check_id": "after",
                "params": { "timestamp": 1700000000000 }
              },
              "comparator": "equals",
              "expected": true,
              "policy_tags": []
            }
          ],
          "policies": [],
          "schemas": [],
          "default_tenant_id": 1
        }
      }
    }
  }'

Semántica del tiempo: time.after devuelve true solo si trigger_time > timestamp (estrictamente mayor). La igualdad devuelve false.

Respuesta (envuelta en MCP):

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "json",
        "json": {
          "scenario_id": "quickstart",
          "spec_hash": { "algorithm": "sha256", "value": "<hex>" }
        }
      }
    ]
  }
}

Paso 4: Iniciar una Ejecución

curl -s http://127.0.0.1:4000/rpc \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "scenario_start",
      "arguments": {
        "scenario_id": "quickstart",
        "run_config": {
          "tenant_id": 1,
          "namespace_id": 1,
          "run_id": "run-1",
          "scenario_id": "quickstart",
          "dispatch_targets": [],
          "policy_tags": []
        },
        "started_at": { "kind": "unix_millis", "value": 1710000000000 },
        "issue_entry_packets": false
      }
    }
  }'

Nota: los valores de run_id deben ser únicos. Si vuelve a ejecutar esta guía, cambie run_id (por ejemplo, run-2) o elimine el estado de ejecución local (decision-gate.db por defecto).

Respuesta (envuelta en MCP): scenario_start devuelve el RunState completo dentro de result.content[0].json.

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "json",
        "json": {
          "tenant_id": 1,
          "namespace_id": 1,
          "run_id": "run-1",
          "scenario_id": "quickstart",
          "spec_hash": { "algorithm": "sha256", "value": "<hex>" },
          "current_stage_id": "main",
          "stage_entered_at": { "kind": "unix_millis", "value": 1710000000000 },
          "status": "active",
          "dispatch_targets": [],
          "triggers": [],
          "gate_evals": [],
          "decisions": [],
          "packets": [],
          "submissions": [],
          "tool_calls": []
        }
      }
    ]
  }
}

Paso 5: Evaluación de la Puerta de Decisión

curl -s http://127.0.0.1:4000/rpc \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "scenario_next",
      "arguments": {
        "scenario_id": "quickstart",
        "request": {
          "run_id": "run-1",
          "tenant_id": 1,
          "namespace_id": 1,
          "trigger_id": "trigger-1",
          "agent_id": "agent-1",
          "time": { "kind": "unix_millis", "value": 1710000000000 },
          "correlation_id": null
        }
      }
    }
  }'

Con time.after y timestamp = 1700000000000, la verificación devuelve true porque 1710000000000 > 1700000000000.

Opcional: añade "feedback": "trace" dentro de arguments para obtener el estado de la puerta/condición cuando lo permita la política de retroalimentación del servidor.

Respuesta (envuelta en MCP):

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "json",
        "json": {
          "decision": {
            "decision_id": "decision-1",
            "seq": 1,
            "trigger_id": "trigger-1",
            "stage_id": "main",
            "decided_at": { "kind": "unix_millis", "value": 1710000000000 },
            "outcome": { "kind": "complete", "stage_id": "main" },
            "correlation_id": null
          },
          "packets": [],
          "status": "completed"
        }
      }
    ]
  }
}

Solución de problemas

El resultado de la puerta es hold

Si una puerta no puede ser probada como verdadera o falsa, el resultado de la decisión será mantener y la respuesta incluirá un SafeSummary. Para solicitudes no locales, scenario_next por defecto es retroalimentación solo de resumen; en modo solo local, el valor por defecto es trace. Siempre puedes solicitar feedback: "trace" (si está permitido) o usar precheck para iteraciones rápidas.

{
  "result": {
    "content": [
      {
        "type": "json",
        "json": {
          "decision": {
            "outcome": {
              "kind": "hold",
              "summary": {
                "status": "hold",
                "unmet_gates": ["after-time"],
                "retry_hint": "await_evidence",
                "policy_tags": []
              }
            }
          }
        }
      }
    ]
  }
}

Cómo depurar con precisión:

  1. Exporta el runpack con runpack_export e inspecciona gate_evals y los errores de evidencia en el manifiesto.
  2. Utilice evidence_query (si la política de divulgación lo permite) para reproducir la llamada del proveedor y ver su EvidenceResult.

Autenticación Requerida

Si configuras [server.auth], incluye el encabezado de autenticación apropiado:

curl -s http://127.0.0.1:4000/rpc \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -d '{ ... }'

Próximos Pasos