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):
- Mínimo de confianza en la vía (
min_lane) - Validación de anclaje (si está configurado)
- Verificación de firma (si es necesario)
- 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 + stdiobearer_token: se requiereAuthorization: Bearer <token>HTTPmtls: utiliza el encabezadox-decision-gate-client-subjectde un proxy TLS de confianza
Nota del registro:
schema_registry.acl.allow_local_only = trueomite 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:
--allow-non-loopbackoDECISION_GATE_ALLOW_NON_LOOPBACK=1[server.tls]configurado oserver.tls_termination = "upstream"- Autenticación no local (
bearer_tokenomtls)
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_laneefectivo se convierte enassertedpara la mayoría de los proveedores. - Los proveedores listados en
dev.permissive_exempt_providerspermanecen 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
keyses 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_iddebe coincidir con la cadena de ruta de clave configurada.- La firma se verifica sobre JSON canónico del HashDigest.
- Si
evidence_hashestá 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_typedebe coincidir.anchor_valuedebe 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
valueycontent_typepero 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,-waly-shmjuntos.
Errores Comunes (Corregidos)
- “Los errores de firma devuelven signature_invalid.” -> No. Las fallas de firma aparecen como
provider_errordurante 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.