Saltar para a documentação
API

Âmbitos

O que uma chave tem autorização para fazer.

O vocabulário

Um conjunto fechado, resource:action. Pequeno o suficiente para mostrar a uma pessoa numa lista de caixas de seleção, e estável o suficiente para que uma concessão guardada continue a significar o mesmo um ano depois. É o mesmo vocabulário em que uma FUNÇÃO de espaço de trabalho é escrita e que controla as ferramentas MCP, por isso um cliente só de leitura não consegue sequer ver uma ferramenta de envio. Um alfabeto, três superfícies.

ÂmbitoConcede
emails:sendEnviar email
emails:readLer as mensagens enviadas e o seu estado de entrega
drafts:readLer rascunhos
drafts:writeCriar e editar rascunhos
threads:readLer conversas e mensagens
threads:writeEtiquetar, ler e arquivar conversas
labels:readLer etiquetas
labels:writeCriar e editar etiquetas
contacts:readLer contactos
contacts:writeAdicionar, editar e remover contactos
audiences:readLer audiências e quem está nelas
audiences:writeCriar e editar audiências, e alterar quem está nelas
calendar:readLer eventos e convites de calendário
calendar:writeCriar, alterar e responder a eventos de calendário
templates:readLer modelos de email e pré-visualizá-los
templates:writeCriar, editar e enviar com modelos de email
domains:readLer domínios e o seu estado de DNS
domains:writeVerificar e configurar domínios
webhooks:readLer endpoints de webhook e entregas
webhooks:writeCriar, editar e testar webhooks
rules:readLer regras de correio e testá-las
rules:writeCriar, editar e reordenar regras de correio
connections:readLer que caixas de correio estão ligadas
members:readVer quem está no espaço de trabalho e o que tem
members:writeAdicionar e remover pessoas, e alterar o que podem alcançar
roles:readLer as funções que este espaço de trabalho define
roles:writeCriar, editar e eliminar funções
settings:readLer as definições da caixa de correio, incluindo a assinatura
settings:writeAlterar as definições da caixa de correio e a assinatura
keys:writeSubstituir o seu próprio segredo sem ninguém abrir a consola

Uma chave criada sem uma lista de âmbitos pensada fica com emails:send e mais nada. O valor seguro por omissão para uma credencial é a coisa mais estreita que a torna útil.

Uma chave é limitada pela função que está por trás dela

Uma chave pode ser emitida contra uma FUNÇÃO, e uma função é um tecto e não uma segunda concessão. O que a chave pode realmente fazer são os seus próprios âmbitos INTERSETADOS com as permissões dessa função (key.scopes ∩ role.permissions), calculado uma vez na fronteira, em todos os pedidos, antes de se chegar a qualquer endpoint. Nada a jusante sabe que as funções existem: um âmbito que a função não tem simplesmente não está na lista que as verificações de âmbito leem.

Por isso as duas listas leem-se em conjunto e nenhuma ganha sozinha. Uma chave com emails:send sob uma função que não o tem não pode enviar; uma função com emails:send não dá nada a uma chave que nunca o pediu. Marcar um âmbito é pedir autoridade, e a função decide quanto do que pediu recebe.

Uma chave SEM função não tem tecto, e é por isso tão ampla como o espaço de trabalho para o qual foi emitida. É o que todas as chaves criadas antes de as funções existirem trazem e o que um proprietário continua a obter se deixar o campo em branco, por isso uma função nula é o estado MAIS AMPLO em que uma chave pode estar, não o mais estreito. É também por isso que eliminar uma função o obriga a dizer para onde vão as suas chaves: deixá-las órfãs promovê-las-ia todas em silêncio.

A interseção é resolvida por pedido em vez de ficar carimbada na chave no momento da emissão. Isso torna estreitar uma função uma revogação imediata, em vigor na chamada seguinte de quem a usa sem que a chave tenha de ser rodada, e alargar uma é imediato exatamente da mesma maneira, que é a metade que vale a pena recordar.

GET /ping e GET /keys/self comunicam scopes ao lado de grantedScopes e roleId por causa de uma falha em particular. scopes é a lista efetiva e a única que autoriza o que quer que seja; grantedScopes é aquilo com que a chave foi emitida. Tudo o que esteja na segunda e falte na primeira foi retirado pela função, e essa diferença é toda a resposta a "a minha chave tem emails:send e estou a receber insufficient_scope". A correção é uma alteração de função e não mais uma chave.

Uma chave que a função estreitou
curl "$OE/ping" -H "$AUTH" {  "ok": true,  "keyId": "4c1b257a66287fd113bd89d0",  "mode": "live",  "scopes": ["emails:read", "threads:read"],  "roleId": "role_c40a95f21cc65d31c2a89e07",  "grantedScopes": ["emails:send", "emails:read", "threads:read"],  "workspaceId": "10417196-e324-4283-af98-66ec62167c47"}

Cinco permissões nunca podem chegar a uma chave: api-keys:read, api-keys:write, billing:read, billing:write e workspace:manage. São permissões mas não são âmbitos, por isso nenhuma função, por mais generosa que seja, as pode pôr num token: criar outra chave, alterar o que outra chave pode fazer, ou mudar de plano é algo que só uma pessoa com sessão iniciada faz. A única coisa que uma chave pode fazer a si própria é substituir o seu próprio segredo, atrás do âmbito keys:write. GET /roles/permissions marca as cinco com scope: false, que é o que permite a um único componente apresentar tanto a matriz de funções como a lista de caixas de seleção da criação de chaves.

roles:write é, na prática, o vocabulário inteiro, e fingir o contrário seria a documentação mais perigosa. Uma chave que o tenha pode fazer PATCH à própria função que a limita e dar a si mesma tudo o resto, e como o tecto é resolvido por pedido, o mais amplo aplica-se logo na chamada seguinte. Não é um buraco a tapar, já que um editor de funções que não pode editar funções não é um editor de funções. É uma razão para não pôr roles:write numa chave que só precisava de ler a lista de membros.

Âmbito de envio

Independentemente dos âmbitos, uma chave pode ser restringida quanto aos remetentes que pode usar. Traz duas listas. domainAllowlist contém domínios inteiros, e uma chave que tenha um domínio pode enviar como qualquer endereço nele, incluindo endereços criados depois da chave. addressAllowlist contém endereços individuais. Deixe ambas vazias e a chave é tão ampla como o espaço de trabalho, nunca mais. GET /keys/self mostra as duas listas e GET /addresses comunica o que uma dada chave pode efetivamente usar, que é a resposta a um from_address_forbidden inexplicado.

O mesmo conjunto restringe o que a chave lê. O correio enviado, o tracking e o calendário só respondem para endereços que a chave pode usar como remetente, por isso uma chave limitada a um domínio não envia nem lê em nome de outro. Um domínio inteiro permite também à chave definir o host de tracking desse domínio, o que uma chave limitada a endereços individuais não pode fazer.

Três restrições, portanto, e compõem-se em vez de se sobreporem: os âmbitos da chave, as permissões da função acima dela, e os domínios e endereços que pode pôr num cabeçalho From. Um envio precisa das três, e uma recusa nomeia apenas a primeira com que se cruzou.