Guards · Check-SQL
Comprobar una sentencia SQL
Endpoint
https://claix.dev/check-sqlEnví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
- Tener una conexión a base de datos activa (PostgreSQL, MySQL o MariaDB).
- Tener al menos un guard activo en esa conexión si quieres limitar escrituras. Sin guards activos, la escritura se permite.
- Si la cuenta tiene varias conexiones activas, conocer el
connection_idde 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.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| sql | string | Sí | Una sola sentencia. Máximo 200.000 caracteres. En PostgreSQL los marcadores son $1, $2… En MySQL y MariaDB son ?. |
| params | array | No | Valores de los marcadores, en el mismo orden. Hasta 5.000 elementos. Acepta string, número, boolean y null. |
| connection_id | uuid | Condicional | Conexió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.tablaen PostgreSQL,base.tablaen 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
- Ten a mano tu API key y la sentencia que el agente propone.
- Si el SQL usa marcadores, pon los valores en
paramsen el mismo orden. - Si hay más de una conexión activa, añade su
connection_id. - Haz un POST JSON a
https://claix.dev/check-sqlcon el header de autenticación. - Un 200 es una comprobación terminada. Lee
allowed:truela permite yfalsela deniega. El código y el motivo van encodeyreason.
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
}| Campo | Descripción |
|---|---|
| allowed | true si la sentencia puede seguir. false si se deniega. |
| decision_id | Identificador de esta comprobación. Sirve para localizarla en Guard Traces del panel. |
| code | Código corto del veredicto. Ver la tabla de abajo. |
| reason | Explicación legible de la decisión. |
| operation | insert, update o delete cuando la sentencia escribe. unknown en lecturas, sentencias de sesión y SQL que no se ha podido clasificar. |
| table | Tabla cualificada de la escritura, o null si la sentencia no apunta a una sola tabla. |
| sql | La sentencia comprobada, tal como se envió. Aparece tanto si se permite como si se deniega. |
| affected_rows | Filas que la sentencia afectaría. null si no se pueden contar. |
| violations | Lista de reglas que la deniegan. Vacía cuando allowed es true. |
| rules_checked | Número de reglas evaluadas. |
| latency_ms | Milisegundos que tardó la comprobación. |
Cada elemento de violations incluye:
| Campo | Descripción |
|---|---|
| guard_id | Identificador del guard. null si la denegación no viene de un guard concreto. |
| guard_name | Nombre del guard. |
| rule_id | Identificador de la regla. |
| rule_title | Título de la regla. |
| code | Mismo tipo de código que el veredicto. |
| message | Texto que explica esa violación. |
Códigos de veredicto que llegan con HTTP 200:
| code | Significado |
|---|---|
| allowed | La escritura cumple los guards que la cubren. |
| no_guards | La conexión no tiene guards activos, así que la sentencia se permite. |
| no_matching_guard | Hay guards activos, y ninguno cubre esta operación y esta tabla. |
| read_only | Es una lectura. Los guards limitan escrituras. |
| session_statement | Es un ajuste de sesión o de transacción. |
| rule_denied | Una regla activa prohíbe la sentencia. |
| omitted_column | Una regla lee una columna que el INSERT no envía. |
| rule_unknown | Falta un valor que la regla necesita y el guard deniega ese caso. |
| unsupported_statement | La forma de SQL no se puede certificar y hay guards activos. |
| parse_error | El SQL no se ha podido leer. |
| multiple_statements | La petición trae más de una sentencia. |
| ambiguous_table | El nombre de la tabla existe en más de un esquema. |
| unqualified_table | La tabla no está cualificada y no pertenece al esquema de la conexión. |
| table_not_found | La tabla no está en la conexión. |
| truncate_guarded | TRUNCATE sobre una tabla vigilada por un guard de DELETE. |
| upsert_update | Un INSERT con actualización, y un guard de UPDATE vigila la tabla. |
| replace_deletes | REPLACE, y un guard de DELETE vigila la tabla. |
| check_failed | La 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.
| HTTP | error | Cuándo |
|---|---|---|
| 401 | missing_api_key | Falta la API key en x-api-key o en Authorization: Bearer. |
| 401 | invalid_api_key | La API key no existe. |
| 401 | inactive_api_key | La API key está desactivada. |
| 401 | expired_api_key | La API key ha caducado. |
| 401 | inactive_user | La cuenta de la API key no está activa. |
| 400 | invalid_json | El cuerpo no es un objeto JSON. |
| 400 | missing_sql | Falta sql o llega vacío. |
| 400 | invalid_params | params no es un array. |
| 400 | invalid_connection_id | connection_id no es un UUID. |
| 400 | connection_required | Hay varias conexiones activas y falta connection_id. |
| 400 | unsupported_engine | La conexión no es PostgreSQL, MySQL ni MariaDB. |
| 404 | connection_not_found | No hay una conexión activa con ese id. |
| 405 | method_not_allowed | Método distinto de POST. |
| 413 | body_too_large | El cuerpo supera 1 MB. |
| 413 | sql_too_large | sql supera 200.000 caracteres. |
| 413 | too_many_params | params tiene más de 5.000 elementos. |
| 500 | internal_error | Error interno del comprobador. |
Ejemplo de error:
{
"error": "missing_sql",
"message": "Falta \"sql\": la sentencia que el agente quiere ejecutar."
}