Documentación

Alcance y scopes

Las tres capas que deciden qué puede hacer una credencial — y por qué te dio 403.

Una credencial no otorga acceso: lo recorta. Actúa siempre en nombre de la persona que la creó, con sus permisos y su licencia, y los scopes solo achican ese alcance. Nunca lo amplían.

        lo que el USUARIO puede hacer hoy
                    ∩
        los SCOPES del access token
                    ∩
        los RECURSOS que la credencial alcanza
        ─────────────────────────────────────
        = lo que este request puede hacer

Las tres capas se evalúan en cada request, contra el estado vivo. No hay foto congelada del día del alta.

1. Los permisos del usuario

Es el techo. Si al rol del usuario le quitan skills.update.own, el scope skills:write de todas sus credenciales deja de valer en el request siguiente, sin tocar ninguna credencial. No hace falta buscarlas ni revocarlas una por una.

Lo mismo vale hacia arriba: si le dan un permiso nuevo, las credenciales que ya tenían ese scope concedido empiezan a poder usarlo. Por eso GET /me puede devolver scopes distintos de un día para otro con el mismo token.

2. Los scopes del token

Cada operación declara el scope que exige. Falta uno y la respuesta es 403 con WWW-Authenticate: Bearer error="insufficient_scope", scope="…", que nombra exactamente cuál falta.

ScopeQué habilitaPermisos que lo respaldan
chat:readListar y leer chats, mensajes y el catálogo de recursos del chat.sidebar.chat
chat:writeCrear chats, enviar turnos, responder interacciones y renombrar o borrar chats. Consume el pool de niucredits de la licencia del usuario.sidebar.chat
areas:readListar y leer las áreas visibles para el usuario.areas.read.all, areas.read.area
skills:readListar y leer habilidades.skills.read.all, skills.read.area, skills.read.own
skills:writeCrear, editar, activar/desactivar y eliminar habilidades.skills.create, skills.create.public, skills.create.shared, skills.update.all, skills.update.own, skills.delete.all, skills.delete.own
rules:readListar y leer reglas de la organización.rules.read
rules:writeCrear, editar, activar/desactivar y eliminar reglas.rules.create.company, rules.create.area, rules.update, rules.delete
permissions:readConsultar roles, el catálogo de permisos y los permisos efectivos del usuario.roles.read
libraries:readListar y leer bibliotecas y sus archivos.workspaces.read.all, workspaces.read.area, workspaces.read.own
libraries:writeCrear y editar bibliotecas. No incluye subir ni eliminar archivos.workspaces.create, workspaces.update.all, workspaces.update.area, workspaces.update.own
connectors:useConsultar el catálogo de conectores y permitir que el chat ejecute sus herramientas. No autoriza conectores nuevos: usa los que el usuario ya conectó.mcps.read.all, mcps.read.area
profile:readConsultar el perfil del usuario en cuyo nombre actúa la credencial.— (opera sobre el propio perfil)
profile:writeActualizar datos del perfil del usuario en cuyo nombre actúa la credencial.— (opera sobre el propio perfil)
users:readListar los usuarios de la empresa (id, nombre, correo, estado y áreas). Necesario para armar shared_user_ids al compartir una habilidad.users.read.all, users.read.area
analytics:readConsultar métricas de uso y consumo de tokens.metrics.read.all, metrics.read.area

Nota

Basta uno de los permisos listados para que el scope sea concedible. skills:write cubre crear, editar y borrar; un rol que solo pueda crear igual necesita el scope. El permiso fino se vuelve a verificar dentro de la operación — el scope es la primera capa, nunca la única.

3. Los recursos

Una credencial puede además estar acotada a bibliotecas, habilidades, áreas o conectores concretos. Ver Credenciales para cómo se configura.

Un recurso fuera del alcance responde `404`, no `403`, cuando el cliente no lo nombró explícitamente. Un 403 confirmaría que el recurso existe, y con ids secuenciales eso alcanza para inventariar lo ajeno.

La excepción es cuando el cliente sí lo nombró: un area_id en una regla, un workspace_id en una habilidad. Ahí la respuesta es 403 api_v1_resource_not_allowed, porque fingir que no existe algo que el cliente acaba de pedir sería confuso y no protege nada.

Scopes compañeros del chat

chat:write autoriza conversar, no leer lo que se adjunte. Adjuntar un recurso a un turno exige además el scope de lectura de ese recurso:

AdjuntoScope adicional
attachments.workspace_idslibraries:read
attachments.file_idslibraries:read
attachments.skill_idsskills:read
attachments.mcp_server_idsconnectors:use

Atención

Sin esta regla, chat:write sola alcanzaría para que el modelo leyera el contenido de una biblioteca que la credencial no puede abrir: el turno sería el canal de fuga. La validación ocurre antes de reservar la idempotencia, así que un 403 acá no consume tu key.

Qué herramientas ve el modelo

En un turno de la API, el modelo recibe un conjunto acotado de herramientas internas, decidido por los mismos scopes:

HerramientaRequiere
list_workspaces, list_documents, search_documentslibraries:read
ask_user_choice— (produce una interacción)
submit_plan, update_plan— (reportan progreso)
search_tools

Nota

Es una lista de permitidos, no de prohibidos: una capacidad nueva de la plataforma no entra sola a un turno de la API. Las herramientas que vuelven a entrar a NiuCore con la sesión del usuario quedan fuera de la v1.0, porque en un turno delegado esa sesión no existe.

Los conectores (Gmail, Drive, Calendar…) sí funcionan, con connectors:use, pero solo los que el usuario ya conectó desde la aplicación. La API no puede autorizar un conector nuevo: eso necesita un navegador y una persona.

Diagnosticar un 403

  1. Llamá a GET /me. scopes dice con qué estás operando de verdad, y permissions por qué.
  2. Si el scope está en la credencial pero no en scopes, al usuario le falta el permiso que lo respalda.
  3. Si el scope está y el 403 persiste, es la capa de recursos: la credencial está acotada y ese recurso quedó afuera.
  4. En un turno, revisá data.required_scopes: nombra el scope compañero que falta para el adjunto que mandaste.