El acceso a campos no puede ver el valor entrante: gobierne las escrituras en Drupal con una restricción de validación
Gobernamos lo que los agentes de IA pueden hacer en un sitio Drupal: qué entidades pueden tocar, si pueden publicar y (novedad de esta semana) si pueden apuntar una redirección fuera del dominio. El hook obvio para "un agente no puede establecer el campo X al valor Y" es el acceso a campos. Es el hook equivocado, y la razón es lo bastante sutil como para costarle una versión. Este patrón de validación de escrituras lo usa MCP Sentinel, nuestro módulo de Drupal para acceso gobernado de agentes.
La trampa: el acceso a campos comprueba el valor almacenado
En una escritura JSON:API o REST, el EntityResource de Drupal comprueba el acceso de edición al campo contra el valor original, almacenado de la entidad, no contra el valor que la solicitud intenta establecer. Así que un control en hook_entity_field_access() que lee el valor actual del campo ve lo que ya está en la base de datos, nunca el objetivo entrante.
Nos topamos con esto con un control de publicación. La regla era "un agente no puede pasar contenido a publicado". Implementada como acceso a campos, leía el moderation_state actual del nodo —ya publicado para una página en vivo— y denegaba todas las escrituras a ese campo, incluida la transición legítima de published to draft que un agente necesita para preparar una edición. El control veía el valor equivocado y bloqueaba lo equivocado.
La costura: una restricción de validación
La validación se ejecuta sobre la entidad analizada —la que lleva los valores entrantes— antes de guardarse, en toda escritura JSON:API, REST y de formulario. Esa es exactamente la capa que puede comparar lo que se está estableciendo con la política.
// Attached to the entity type; runs on the incoming values
public function validate($entity, $constraint) {
if (!$this->governed()) return; // only govern agent traffic
$target = $entity->get('redirect_redirect')->uri;
if ($this->isExternal($target) && !$this->allowed($target)) {
$this->context->buildViolation($constraint->message)
->atPath('redirect_redirect')->addViolation();
}
}Una escritura denegada devuelve un 422 limpio con el campo infractor nombrado, en lugar de un 403 confuso de una comprobación de acceso que razonaba sobre datos obsoletos.
Por qué es la capa correcta para la gobernanza de agentes
- Ve la intención. El destino de redirección entrante, el estado de moderación objetivo: lo que usted realmente quiere permitir o denegar.
- Es uniforme. Una restricción cubre JSON:API, REST y el formulario de administración. Sin un control por transporte.
- Falla en modo cerrado y se explica. Una violación es un mensaje específico, anclado a una ruta, no una denegación genérica.
- Es barato de acotar. Retorno anticipado para el tráfico que no es de agentes, y adjunte la restricción solo cuando el módulo correspondiente esté instalado, de modo que los sitios ordinarios no se ven afectados.
La regla general
Si su política depende de lo que la solicitud intenta establecer, póngala en una restricción de validación. El acceso a campos responde "quién puede tocar este campo", juzgado contra lo que ya está ahí, no "qué puede contener esta escritura".