Documentos de Decision Gate

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

Documentación de Asset Core

Guía de Seguridad

A primera vista

Qué: Controles de seguridad para confianza, firmas, divulgación y acceso Por qué: Prevenir la manipulación de pruebas y limitar la exposición de datos Quién: Ingenieros de seguridad, equipos de cumplimiento, operadores de producción Requisitos previos: evidence_flow_and_execution_model.md


Posturas Preestablecidas

Decision Gate envía cuatro preajustes (ver preset_configs.md):

  • Quickstart-Dev: autenticación solo local, bypass del registro solo local, permisos de desarrollo habilitados.
  • Recomendado por defecto: autenticación solo local con asignaciones de principal explícitas; omisión del registro desactivada.
  • Endurecido: autenticación de portador, espacio de nombres predeterminado deshabilitado, firma de esquema requerida.
  • Container-Prod: autenticación de portador, terminación TLS ascendente, valores predeterminados sin estado.

Estos ajustes preestablecidos son intencionalmente explícitos. Si cambias la postura (modo de autenticación, valores predeterminados de espacio de nombres, ACL de registro, carriles de confianza), actualiza el ajuste preestablecido y vuelve a ejecutar las pruebas del sistema.


Arquitectura de Falla Cerrada

La puerta de decisión falla cerrada: la evidencia faltante o inválida produce unknown, lo que mantiene las puertas.

Controles de seguridad aplicados (en orden):

  1. Mínimo de confianza en la vía (min_lane)
  2. Validación de anclaje (si está configurado)
  3. Verificación de firma (si es necesario)
  4. Evaluación del comparador (triestado)

Control de Acceso

Acceso a Herramientas (API MCP)

El acceso a la herramienta está controlado por [server.auth].

[server.auth]
mode = "bearer_token"
bearer_tokens = ["token-1", "token-2"]
allowed_tools = ["scenario_define", "scenario_start", "scenario_next"]

Modos:

  • local_only (predeterminado): solo loopback + stdio
  • bearer_token: se requiere Authorization: Bearer <token> HTTP
  • mtls: utiliza el encabezado x-decision-gate-client-subject de un proxy TLS de confianza

Nota del registro:

  • schema_registry.acl.allow_local_only = true omite el mapeo de principal para los llamadores locales únicamente. Usar solo para incorporación en dev/local.

Vinculación No Loopback

Vincular HTTP/SSE a no-loopback requiere todos los siguientes:

  1. --allow-non-loopback o DECISION_GATE_ALLOW_NON_LOOPBACK=1
  2. [server.tls] configurado o server.tls_termination = "upstream"
  3. Autenticación no local (bearer_token o mtls)

Para mtls en contenedor, server.tls.client_ca_path debe estar configurado y require_client_cert = true. Para la terminación de TLS en upstream, haga cumplir mTLS en el proxy y reenvíe x-decision-gate-client-subject.


Lanes de Confianza

La evidencia se clasifica en carriles:

  • Verificado: evidencia obtenida por el proveedor
  • Afirmado: precheck payloads

El carril mínimo se aplica mediante:

[trust]
min_lane = "verified"   # or "asserted"

Si la pista de evidencia está por debajo del mínimo, la condición se convierte en unknown y se registra un error trust_lane en el runpack.

Modo Dev-Permisivo

[dev]
permissive = true

Efectos:

  • El min_lane efectivo se convierte en asserted para la mayoría de los proveedores.
  • Los proveedores listados en dev.permissive_exempt_providers permanecen estrictos (predeterminado: assetcore, assetcore_read).
  • No permitido cuando namespace.authority.mode = "assetcore_http".

Verificación de Firma

Configurado con trust.default_policy:

[trust]
# Require Ed25519 signatures from these public key files.
default_policy = { require_signature = { keys = ["/etc/decision-gate/keys/provider.pub"] } }

Notas:

  • Cada entrada de keys es una ruta de archivo. El archivo de clave puede contener bytes de clave pública en bruto de 32 bytes o texto en base64.
  • EvidenceResult.signature.key_id debe coincidir con la cadena de ruta de clave configurada.
  • La firma se verifica sobre JSON canónico del HashDigest.
  • Si evidence_hash está presente, debe coincidir con el hash canónico del valor de evidencia.

Si una verificación de firma falla, la llamada al proveedor falla y la condición se convierte en unknown con provider_error registrado.


Validación de Anclaje

Los anclajes se configuran a través de configuración del servidor, no del escenario:

[anchors]
[[anchors.providers]]
provider_id = "assetcore_read"
anchor_type = "assetcore.anchor_set"
required_fields = ["assetcore.namespace_id", "assetcore.commit_id", "assetcore.world_seq"]

Reglas de anclaje (exactas):

  • EvidenceResult.evidence_anchor.anchor_type debe coincidir.
  • anchor_value debe ser una cadena que contenga JSON canónico.
  • Ese JSON debe analizarse como un objeto.
  • Los campos requeridos deben existir y ser de tipo escalar cadena o número (sin booleanos, arreglos, objetos o nulos).

Las violaciones producen anchor_invalid y la condición se convierte en unknown.


Divulgación de Evidencias

evidence_query puede devolver valores en bruto, pero la divulgación está controlada por políticas:

[evidence]
allow_raw_values = false
require_provider_opt_in = true

[[providers]]
name = "json"
type = "builtin"
config = { root = "/var/lib/decision-gate/evidence", root_id = "evidence-root", max_bytes = 1048576, allow_yaml = false }
allow_raw = true

Comportamiento:

  • Si la divulgación en bruto está bloqueada, Decision Gate redacta value y content_type pero aún devuelve hashes y anclajes.
  • Este no es un error de JSON-RPC.
  • Los nombres de los proveedores son únicos; los identificadores incorporados (time, env, json, http) están reservados.

Manejo de Carga Útil de Envío/Disparador

scenario_submit.payload y scenario_trigger.payload son canales de registro de auditoría. Decision Gate persiste estas cargas útiles en el estado de ejecución y los artefactos de runpack por diseño. Las integraciones deben evitar enviar secretos en bruto a través de estos campos.

Patrón recomendado:

  • Enviar referencias/manejadores opacos en las cargas útiles.
  • Resolver secretos de un gestor de secretos dedicado fuera de DG.

Configuración de Producción Segura

[server]
transport = "http"
bind = "0.0.0.0:4000"
mode = "strict"

[server.auth]
mode = "bearer_token"
bearer_tokens = ["token-1"]

[server.tls]
cert_path = "/etc/decision-gate/tls/cert.pem"
key_path = "/etc/decision-gate/tls/key.pem"

[trust]
min_lane = "verified"
default_policy = { require_signature = { keys = ["/etc/decision-gate/keys/provider.pub"] } }

[evidence]
allow_raw_values = false
require_provider_opt_in = true

[anchors]
[[anchors.providers]]
provider_id = "json"
anchor_type = "file_path_rooted"
required_fields = ["root_id", "path"]

[namespace]
allow_default = false

[policy]
engine = "static"

[policy.static]
default = "deny"

[run_state_store]
type = "sqlite"
path = "/var/lib/decision-gate/decision-gate.db"
journal_mode = "wal"
sync_mode = "full"

Importante: Para enlaces que no son de bucle, añada --allow-non-loopback o establezca DECISION_GATE_ALLOW_NON_LOOPBACK=1.


Integridad de SQLite

El almacenamiento del estado de ejecución de SQLite guarda instantáneas JSON canónicas y verifica los hashes al cargar. La corrupción o las discrepancias de hash fallan de manera cerrada.

Mejores prácticas:

  • Utilice un volumen duradero (evite /tmp).
  • Realice una copia de seguridad de los archivos .db, -wal y -shm juntos.

Errores Comunes (Corregidos)

  • “Los errores de firma devuelven signature_invalid.” -> No. Las fallas de firma aparecen como provider_error durante las llamadas al proveedor.
  • “La política de anclaje está en el escenario.” -> No. Está configurada bajo [anchors].
  • “el motor de políticas controla el acceso a las herramientas.” -> No. [policy] controla el despacho de paquetes únicamente. El acceso a las herramientas es [server.auth].
  • “evidence_query devuelve un error cuando los valores en bruto están bloqueados.” -> No. Los valores están redactados, no rechazados.

Referencia cruzada