La mayoría de los sistemas de autorización se reducen a una pregunta: ¿puede este usuario realizar esta acción en este recurso? Eso funciona hasta que surge un nuevo eje de restricción que debe integrarse con todas las políticas existentes. Para nosotros, ese eje fue el idioma.
Cuando lanzamos el acceso por idioma, el objetivo del producto era claro: permitir que un administrador asigne un traductor de español a contenido regional sin arriesgar cambios en el sitio en inglés. Nuestro modelo de autorización existente manejaba bien las páginas y las colecciones del CMS, pero el idioma no podía modelarse como un recurso más. Implementarlo requirió cuatro cambios de diseño.
De recursos a dimensiones
La mayoría de los sistemas de autorización deniegan el acceso por defecto y lo conceden explícitamente. El de Webflow funciona al revés: el acceso es abierto por defecto y los administradores establecen las restricciones. El idioma fue más difícil de encajar en ese modelo porque, en un sistema abierto por defecto, la falta de contexto omite la restricción sin avisar.
El control de acceso basado en recursos funciona bien porque se aplica a un objeto concreto: una página, una colección, un sitio. Ese objeto tiene un ID, puede enumerarse y puede llevar consigo un dato permanente como «este usuario tiene restringido el acceso a la página XYZ». Cuando verificas el acceso, el objeto que se autoriza es también el objeto que se restringe.
Una dimensión se sitúa junto al recurso y califica el acceso al mismo. Los sistemas basados en atributos pueden expresar esto, pero la mayoría trata los atributos que no son recursos como filtros generales en lugar de restricciones que se integran con la política del recurso. Cuando un diseñador edita la variante en español de una página, la página sigue siendo el objeto que se edita, mientras que el idioma proporciona el contexto para esa acción. El idioma puede aparecer como un objeto de primer nivel en otras partes del sistema, como al listar a qué idiomas puede acceder un usuario, pero la mayoría de las comprobaciones de autorización lo tratan como contexto de la solicitud.

Esa distinción cambia la forma del sistema. Afecta a cómo almacenas los datos de autorización, cómo compones las comprobaciones y cómo manejas las operaciones que abarcan toda la dimensión.
Cambio 1: Es mejor calcular el contexto que persistirlo
Lo primero que cambia es la persistencia. En un modelo de recursos, almacenas un dato de restricción directamente en el elemento restringido: una página, un dato. Una vez que el idioma entra en juego, la versión más simple es una relación para cada par de página-idioma en cada sitio.
Un sitio con 200 páginas y 15 idiomas requeriría 3000 datos de relación solo para representar el estado actual. Cada página nueva significa 15 datos nuevos, y cada idioma nuevo significa 200 datos nuevos. El coste de almacenamiento crece de forma multiplicativa.
La distinción crucial fue esta: los datos de recursos y los datos de dimensiones son tipos de información diferentes. Los datos de recursos deben ser permanentes porque describen el sistema, pero los datos de idioma describen la solicitud, lo que los hace seguros para calcular en lugar de almacenar.
Lo solucionamos haciendo que el contexto del idioma fuera efímero: inyectarlo en el momento de la solicitud, evaluarlo durante el proceso y luego descartarlo.

Cambio 2: Dos ejes de restricción deben integrarse en una sola comprobación
Con los recursos, la autorización es unidimensional: ¿puede este usuario acceder a esta página? Si añades una dimensión, la pregunta se vuelve compuesta: ¿puede este usuario acceder a esta página en este idioma?
Eso introduce una relación de anulación que el modelo de recursos nunca tuvo que manejar. Un usuario que puede editar una página pero tiene restringido el español, aun así debe ser bloqueado para que no edite la variante en español.
El enfoque directo consiste en dos llamadas de política separadas: una para la página y otra para el idioma. Pero eso falla en cuanto la política depende de cómo interactúan ambas. Un rol que otorga acceso a todo el idioma podría anular una restricción de página. Dividida en dos llamadas, esa lógica no tiene dónde residir. Para preservar esa semántica, ambos ejes deben evaluarse en una única decisión de política.
Implementamos esto con una regla de política componible en Oso Cloud, nuestro motor de autorización, que se aplica a todos los tipos de recursos.

Cuando no hay una configuración regional en la solicitud, la regla se aprueba incondicionalmente, por lo que la autorización existente no cambia. Una única llamada a authorize() evalúa ambos ejes y, dado que el contexto de la configuración regional se inyecta en lugar de almacenarse, la comprobación se mantiene en tiempo constante.
Cambio 3: Las operaciones que abarcan todas las configuraciones regionales requieren un tipo de comprobación diferente
Las operaciones de una sola configuración regional son sencillas: se comprueba la configuración regional y luego se permite o se deniega. Pero algunas operaciones abarcan todas las configuraciones regionales. Eliminar una página borra todas sus variantes regionales. Si a un usuario se le restringe el acceso al español, permitirle eliminar la página incumple esa promesa.
Aquí es donde la autorización basada en relaciones empieza a flaquear bajo un modelo basado en restricciones. Los sistemas de este tipo suelen estar optimizados para comprobaciones de existencia: ¿existe esta relación? Pero las operaciones que abarcan todas las configuraciones regionales requieren lo contrario: verificar que no exista ninguna configuración regional restringida en el conjunto. Se trata de un tipo de consulta diferente que escala con el tamaño del conjunto en lugar de resolverse en tiempo constante.
Cada enfoque obvio tenía un coste. Las consultas directas de hechos omiten la evaluación de políticas, por lo que las concesiones basadas en roles desaparecen. Los hechos agregados derivados crean riesgos de sincronización. La negación en el lenguaje de políticas requiere enumerar todo el conjunto de configuraciones regionales de antemano, lo que traslada la complejidad a subconsultas correlacionadas y rincones indocumentados del lenguaje de políticas.
Decidimos invertir la pregunta: en lugar de preguntar si el usuario tiene alguna restricción, preguntamos qué configuraciones regionales puede editar mediante una consulta evaluada por políticas, y luego comprobamos si ese conjunto está completo. Esto preserva la semántica de autorización, evita la negación y limita la lógica del lado de la aplicación a la aritmética de conjuntos.

Cambio 4: La autorización debe ser implícita, no opcional
En Webflow, tenemos miles de puntos finales y componentes. Cuando la autorización depende del contexto de la solicitud, como la configuración regional, cada llamador debe pasar ese contexto correctamente. Hacerlo manualmente es lento, frágil y fácil de pasar por alto. Tanto en el frontend como en el backend, la respuesta fue la misma: hacer que la aplicación sea estructural, no opcional.
En el frontend, eso significó reutilizar lo que ya teníamos. Nuestro sistema de restricción de páginas y colecciones ya componía capacidades de alto nivel como "puede editar el contenido de la página" y "puede eliminar la colección". Integramos las comprobaciones de configuración regional en esas mismas capacidades, de modo que los componentes secundarios heredaron las restricciones regionales automáticamente, sin cambios en el código.
El resultado es que los consumidores no necesitan saber nada sobre la configuración regional para aplicarla correctamente.

En el backend, teníamos un problema similar: los hechos de contexto debían generarse de forma fiable en cada punto de entrada. En lugar de dispersar la lógica de resolución de la configuración regional en cientos de puntos finales, la centralizamos en un registro de resolución de relaciones.
Cada resolvedor declara una relación y cómo extraer hechos del contexto de la solicitud; un generador de hechos recorre el gráfico y produce los hechos que necesita el servicio de autorización.

Esto también cerró un modo de fallo sutil: si un punto final llama al autorizador sin contexto de configuración regional, la comprobación de la configuración regional se omite y la restricción se elude. Al hacer que la generación de contexto sea automática, el registro elimina ese paso manual por completo.
Más allá de la configuración regional
Aunque los sistemas de Control de Acceso Basado en Atributos (ABAC) pueden expresar composición dimensional, la mayoría de las implementaciones no facilitan su aplicación en todas las superficies, especialmente en un sistema abierto por defecto. Creamos el acceso específico por configuración regional para resolver eso, pero lo que más nos sorprendió fue cuánto se generalizó la solución. Las piezas que construimos para la configuración regional, como la composición ortogonal y la generación automática de hechos, no dependen de la configuración regional en sí. La siguiente dimensión puede conectarse al mismo registro, a la misma estructura de políticas y al mismo modelo de composición.
Si te encuentras con problemas similares, la verdadera prueba no es si tu lenguaje de políticas puede expresar el nuevo eje, sino si un nuevo punto final puede equivocarse silenciosamente.

¡Estamos contratando!
Buscamos talento en producto e ingeniería para que se una a nuestra misión de poner superpoderes de desarrollo al alcance de todos.




