Me
Dados do próprio usuário autenticado — permissões efetivas e tenants.
Endpoints que respondem sobre quem fez a requisição. O usuário sai sempre do token
(não há :userId na rota), então não há como consultar outra pessoa por aqui — por isso são
os únicos endpoints /api/* sem @Permissions e sem @RequireRole. Base path:
/api/me · autenticação de usuário.
| Método | Rota | Scope | Resource | Ação (role) | Sucesso |
|---|---|---|---|---|---|
GET | /api/me/permissions | — | — | — | 200 |
GET | /api/me/tenants | — | — | — | 200 |
Controle de acesso. Qualquer usuário autenticado acessa os dois. A autorização real continua nos demais endpoints (
RolesGuard) — o que vem daqui serve para o painel esconder menus e ações, nunca como decisão de acesso.
Bootstrap: os dois funcionam sem tenant ativo resolvido (RJGDD-16). Toda rota
/api/*normalmente exige um tenant resolvível — semX-Tenant-Ide com 0 ou 2+ tenants, oKeycloakAuthMiddlewaredevolve403(ver Autenticação). Esses dois endpoints são a exceção: resolvem sem tenant/persona em vez de403(resolveTenantScopeAllowingBootstrap). Sem essa válvula, ninguém com 0 ou 2+ tenants conseguiria carregar a própria lista de tenants — a chamada que alimenta o seletor exigiria um tenant já selecionado, um impasse. Com o tenant não resolvido,GET /api/me/permissionsdevolvepermissions: [](nenhuma persona conhecida ainda) até a pessoa escolher um tenant no seletor;GET /api/me/tenantsnão é afetado, porque nunca dependeu do tenant ativo para montar a resposta.
Permissões efetivas
GET /api/me/permissions — roles do token e todo par modulo:acao liberado pela persona do
tenant ativo + essas roles (via listAccessiblePermissions).
rolestraz só o que ainda vem do Keycloak: a personaglobal(se for o caso) e as roles de exceção (modulo:acao[:deny]). A persona por tenant (tenant-admin/coordinator/technician/viewer) não aparece aqui — ela decide o conteúdo depermissions, mas não é exposta neste payload (ver Autenticação).
curl http://localhost:3000/api/me/permissions \
-H "Authorization: Bearer $ACCESS_TOKEN"200 OK
{
"roles": ["documents:delete"],
"permissions": [
"documents:read",
"documents:create",
"documents:update",
"documents:delete",
"document-types:read",
"organizations:read"
]
}Meus tenants
GET /api/me/tenants — tenants a que o usuário autenticado pertence, para montar o seletor de
tenant ativo do painel. O tenant escolhido volta em cada requisição no header
X-Tenant-Id (ver Autenticação).
Só devolve tenants ativos: um tenant inativo não alcança cooperativa nenhuma, e oferecê-lo
na escolha deixaria a tela vazia sem explicação. O payload é enxuto de propósito —
keycloakClientId, allowedScopes e metadata são configuração de infra e só aparecem nas
rotas administrativas de tenants.
curl http://localhost:3000/api/me/tenants \
-H "Authorization: Bearer $ACCESS_TOKEN"200 OK
{
"data": [
{
"id": "t1b2c3d4-e5f6-4789-a123-456789abcdef",
"name": "Acme Tenant",
"description": "Cooperativa de reciclagem da zona norte",
"active": true,
"persona": "technician"
}
]
}| Campo | Tipo | Descrição |
|---|---|---|
id | uuid | valor a enviar em X-Tenant-Id |
name | string | nome técnico do tenant |
description | string | null | label exibido no seletor; quando null, o front usa name |
active | boolean | sempre true neste endpoint (inativos saem) |
persona | string | null | persona do usuário neste vínculo (UserTenant.persona); null quando o vínculo ainda não recebeu persona atribuída — qualquer request feita com esse tenant ativo recebe 403 até a reatribuição manual (ver PLANO-PERSONA-POR-TENANT.md §15) |
Erros
| Status | code | Quando |
|---|---|---|
404 | USER_NOT_FOUND | usuário do token não tem cadastro local |