Guards

Check-SQL

Comprueba una sentencia SQL contra los guards activos de una base conectada. La llamada devuelve si está permitida.

Guards · Check-SQL

Comprobar una sentencia SQL

Endpoint

POSThttps://claix.dev/check-sql

Envía la sentencia que un agente quiere ejecutar y Claix responde si los guards activos de esa conexión la permiten. La comprobación es determinista: lee el SQL, aplica los guards publicados y devuelve un veredicto.

Llama siempre a https://claix.dev/check-sql.

Pensado para integraciones server-to-server. El sistema que llama decide qué hacer con el veredicto. Claix devuelve la decisión y deja la ejecución en ese sistema.

1. Autenticación

Toda petición debe incluir tu API key. Es una credencial de servidor, distinta de cualquier token de sesión.

Opción A — Header dedicado (recomendado):

x-api-key: <TU_API_KEY>

Opción B — Header estándar Authorization:

Authorization: Bearer <TU_API_KEY>

Con uno de los dos es suficiente. Si envías ambos, x-api-key tiene prioridad.

El sistema valida que la key exista, esté activa y la cuenta no esté suspendida. Si falla, responde 401.

2. Requisitos previos

  1. Tener una conexión a base de datos activa (PostgreSQL, MySQL o MariaDB).
  2. Tener al menos un guard activo en esa conexión si quieres limitar escrituras. Sin guards activos, la escritura se permite.
  3. Si la cuenta tiene varias conexiones activas, conocer el connection_id de la que quieres comprobar.

3. Formato de la petición

Método: POST · Content-Type: application/json

El cuerpo es un objeto JSON. Solo sql es obligatorio.

CampoTipoObligatorioDescripción
sqlstringSíUna sola sentencia. Máximo 200.000 caracteres. En PostgreSQL los marcadores son $1, $2… En MySQL y MariaDB son ?.
paramsarrayNoValores de los marcadores, en el mismo orden. Hasta 5.000 elementos. Acepta string, número, boolean y null.
connection_iduuidCondicionalConexión que se comprueba. Omítelo si la cuenta tiene una sola conexión activa. Con varias, es obligatorio.

Ejemplo para PostgreSQL:

{
  "sql": "INSERT INTO shop.orders (customer_id, total) VALUES ($1, $2)",
  "params": ["c-1042", 6200],
  "connection_id": "8f14e45f-ceea-4e6f-8b23-1e2d3c4b5a6f"
}

En MySQL o MariaDB la misma sentencia usa ?: VALUES (?, ?). El cuerpo de la petición sigue siendo el mismo. El cuerpo completo puede medir hasta 1 MB.

  • Las comparaciones de texto distinguen mayúsculas, acentos y espacios finales.
  • Cualifica las tablas (esquema.tabla en PostgreSQL, base.tabla en MySQL). Un nombre que existe en más de un esquema se deniega.
  • Una columna que un guard lee y el INSERT omite hace que la sentencia se deniegue.

4. Cómo construir la llamada

  1. Ten a mano tu API key y la sentencia que el agente propone.
  2. Si el SQL usa marcadores, pon los valores en params en el mismo orden.
  3. Si hay más de una conexión activa, añade su connection_id.
  4. Haz un POST JSON a https://claix.dev/check-sql con el header de autenticación.
  5. Un 200 es una comprobación terminada. Lee allowed: true la permite y false la deniega. El código y el motivo van en code y reason.

5. Ejemplos de llamada

Consulta el panel de la derecha para ver ejemplos en cURL, JavaScript, Node.js, Python, PHP y n8n.

6. Formato de la respuesta

200 OK · Content-Type: application/json

El 200 cubre tanto el permiso como la denegación. La decisión está en allowed. El campo sql repite la sentencia comprobada, tal como se envió, en los dos casos. Si en Guard Traces hay un endpoint de aviso, Claix envía este mismo JSON con un POST a la URL de permitidos o a la de denegados.

Permiso:

{
  "allowed": true,
  "decision_id": "1a2b3c4d-5e6f-4789-a012-3456789abcde",
  "code": "allowed",
  "reason": "Ninguna regla prohíbe esta operación.",
  "operation": "insert",
  "table": "shop.orders",
  "sql": "INSERT INTO shop.orders (customer_id, total) VALUES ($1, $2)",
  "affected_rows": 1,
  "violations": [],
  "rules_checked": 1,
  "latency_ms": 840
}

Denegación:

{
  "allowed": false,
  "decision_id": "9ff38974-1392-4c1a-83e5-3b2f09bb43dc",
  "code": "rule_denied",
  "reason": "No se pueden crear pedidos con un total superior a 5000.",
  "operation": "insert",
  "table": "shop.orders",
  "sql": "INSERT INTO shop.orders (customer_id, total) VALUES ($1, $2)",
  "affected_rows": 1,
  "violations": [
    {
      "guard_id": "b7c1d2e3-4f56-4789-a012-3456789abcde",
      "guard_name": "Límite de total en pedidos",
      "rule_id": "e2a9c4b1-6d70-4e85-9f12-abcdef012345",
      "rule_title": "Total máximo",
      "code": "rule_denied",
      "message": "No se pueden crear pedidos con un total superior a 5000."
    }
  ],
  "rules_checked": 1,
  "latency_ms": 1104
}
CampoDescripción
allowedtrue si la sentencia puede seguir. false si se deniega.
decision_idIdentificador de esta comprobación. Sirve para localizarla en Guard Traces del panel.
codeCódigo corto del veredicto. Ver la tabla de abajo.
reasonExplicación legible de la decisión.
operationinsert, update o delete cuando la sentencia escribe. unknown en lecturas, sentencias de sesión y SQL que no se ha podido clasificar.
tableTabla cualificada de la escritura, o null si la sentencia no apunta a una sola tabla.
sqlLa sentencia comprobada, tal como se envió. Aparece tanto si se permite como si se deniega.
affected_rowsFilas que la sentencia afectaría. null si no se pueden contar.
violationsLista de reglas que la deniegan. Vacía cuando allowed es true.
rules_checkedNúmero de reglas evaluadas.
latency_msMilisegundos que tardó la comprobación.

Cada elemento de violations incluye:

CampoDescripción
guard_idIdentificador del guard. null si la denegación no viene de un guard concreto.
guard_nameNombre del guard.
rule_idIdentificador de la regla.
rule_titleTítulo de la regla.
codeMismo tipo de código que el veredicto.
messageTexto que explica esa violación.

Códigos de veredicto que llegan con HTTP 200:

codeSignificado
allowedLa escritura cumple los guards que la cubren.
no_guardsLa conexión no tiene guards activos, así que la sentencia se permite.
no_matching_guardHay guards activos, y ninguno cubre esta operación y esta tabla.
read_onlyEs una lectura. Los guards limitan escrituras.
session_statementEs un ajuste de sesión o de transacción.
rule_deniedUna regla activa prohíbe la sentencia.
omitted_columnUna regla lee una columna que el INSERT no envía.
rule_unknownFalta un valor que la regla necesita y el guard deniega ese caso.
unsupported_statementLa forma de SQL no se puede certificar y hay guards activos.
parse_errorEl SQL no se ha podido leer.
multiple_statementsLa petición trae más de una sentencia.
ambiguous_tableEl nombre de la tabla existe en más de un esquema.
unqualified_tableLa tabla no está cualificada y no pertenece al esquema de la conexión.
table_not_foundLa tabla no está en la conexión.
truncate_guardedTRUNCATE sobre una tabla vigilada por un guard de DELETE.
upsert_updateUn INSERT con actualización, y un guard de UPDATE vigila la tabla.
replace_deletesREPLACE, y un guard de DELETE vigila la tabla.
check_failedLa comprobación no pudo terminar. La sentencia se deniega.

7. Errores frecuentes

Estos códigos HTTP son fallos de la llamada. Una denegación de la sentencia sigue siendo 200 con allowed: false.

HTTPerrorCuándo
401missing_api_keyFalta la API key en x-api-key o en Authorization: Bearer.
401invalid_api_keyLa API key no existe.
401inactive_api_keyLa API key está desactivada.
401expired_api_keyLa API key ha caducado.
401inactive_userLa cuenta de la API key no está activa.
400invalid_jsonEl cuerpo no es un objeto JSON.
400missing_sqlFalta sql o llega vacío.
400invalid_paramsparams no es un array.
400invalid_connection_idconnection_id no es un UUID.
400connection_requiredHay varias conexiones activas y falta connection_id.
400unsupported_engineLa conexión no es PostgreSQL, MySQL ni MariaDB.
404connection_not_foundNo hay una conexión activa con ese id.
405method_not_allowedMétodo distinto de POST.
413body_too_largeEl cuerpo supera 1 MB.
413sql_too_largesql supera 200.000 caracteres.
413too_many_paramsparams tiene más de 5.000 elementos.
500internal_errorError interno del comprobador.

Ejemplo de error:

{
  "error": "missing_sql",
  "message": "Falta \"sql\": la sentencia que el agente quiere ejecutar."
}

Ejemplos de petición

curl -X POST "https://claix.dev/check-sql" \
  -H "x-api-key: <TU_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{  "sql": "INSERT INTO shop.orders (customer_id, total) VALUES ($1, $2)",  "params": ["c-1042", 6200],  "connection_id": "8f14e45f-ceea-4e6f-8b23-1e2d3c4b5a6f"}'