Skip to main content

Concessões de rota (route grants) — API

Habilita, para uma instância de integração específica, uma capability do catálogo público — o mecanismo que decide se essa integração pode chamar uma rota da API pública, com que perfil de rate limit, e com que de-para declarativo de resposta. Sem um grant habilitado, a instância não acessa nenhuma rota, mesmo estando ACTIVE.

Funcionamento​

O catálogo de capabilities​

RouteCapabilityCatalog é um catálogo compilado em código, não uma tabela — configuração não cria rota nova, só habilita uma capability que já existe no catálogo. Cada RouteCapability tem:

  • uma chave (public-api.<domínio>.<ação>, ex. public-api.exam.read);
  • um owner (DIAGNOSIS, ORGANIZATION, REPORT ou INTEGRATION_PLATFORM);
  • um efeito (READ ou WRITE);
  • uma ou mais operações canônicas (método + operationId + path, sempre sob /v1/) — agrupadas quando representam a mesma permissão (ex. ler uma unidade e listar as unidades de um tenant são a mesma leitura).
ChaveEfeitoOwnerOperaçõesRota implementada hoje?
public-api.organization.tenant.createWRITEORGANIZATIONPOST /v1/tenantsNão
public-api.organization.tenant.readREADORGANIZATIONGET /v1/tenants, GET /v1/tenants/{tenantId}Sim
public-api.organization.tenant.updateWRITEORGANIZATIONPATCH /v1/tenants/{tenantId}Não
public-api.organization.unit.createWRITEORGANIZATIONPOST /v1/tenants/{tenantId}/unitsNão
public-api.organization.unit.readREADORGANIZATIONGET /v1/tenants/{tenantId}/units, GET /v1/units/{unitId}Sim
public-api.organization.unit.updateWRITEORGANIZATIONPATCH /v1/units/{unitId}Não
public-api.organization.module.readREADORGANIZATIONGET /v1/units/{unitId}/modulesSim
public-api.exam.readREADDIAGNOSISGET /v1/exams, GET /v1/exams/{examId}Sim
public-api.exam.updateWRITEDIAGNOSISPATCH /v1/exams/{examId}Não
public-api.report.readREADREPORTGET /v1/reports/{reportId}Não
public-api.report.updateWRITEREPORTPATCH /v1/reports/{reportId}Não

A confirmar — responsável: time de Integration Platform; data: 24/09/2026. As capabilities marcadas "Não" nesta tabela não têm nenhum controller correspondente em public-api-edge neste levantamento — são reservas de superfície futura, não rotas quebradas. public-api.report.read corresponde, no Bitrix, à feature legada F-004 — Recuperar laudo assinado digitalmente, ainda não reescrita na API atual.

Habilitar uma chave fora do catálogo é sempre rejeitado (UnknownRouteCapabilityError, 422) — a configuração nunca inventa uma superfície pública nova.

O grant​

Um IntegrationPlatformRouteGrant liga (integrationInstanceId, capabilityKey) a um status (ENABLED/DISABLED), um rateProfile (STANDARD por default) e, opcionalmente, um de-para declarativo de resposta (ver seção abaixo).

  • Habilitar (PUT): cria o grant se não existir, ou atualiza rateProfile/mapping se já existir. É idempotente: repetir com os mesmos valores devolve o mesmo grant e não gera outro evento de auditoria.
  • Desabilitar (DELETE): marca DISABLED sem apagar o registro — desabilitar de novo é no-op. Não existe grant "removido"; existe habilitado ou desabilitado.
  • Listar: devolve todos os grants da instância, com o owner de cada capability resolvido pelo catálogo.

Como uma chamada é autorizada​

ResolveIntegrationPlatformRouteGrantService.resolveAuthorizedCapability é o que PublicApiMachineAuthGuard chama a cada requisição da API pública (ver Autenticação e autorização de máquina). A ordem é fixa e deny-by-default, sem revelar qual passo falhou:

  1. a capabilityKey existe no catálogo compilado;
  2. a instância (resolvida pelo oauthClientId do token) existe e está ACTIVE;
  3. existe um grant para (instância, capability) e ele está ENABLED.

Só então a chamada segue para o alcance de unidade (resolvido separadamente, ver Instâncias de integração) e para o controller da rota.

De-para declarativo de resposta​

Um grant pode carregar um mapping declarativo (DeclarativeResponseMapping) que transforma a resposta canônica no formato que aquele parceiro específico espera — sem que a rota canônica saiba disso. É deliberadamente burro: uma lista ordenada de passos, cada um uma operação fechada, nunca uma expressão ou condicional. No pior caso (campo ausente), o passo é ignorado — aplicar um mapping não pode falhar de formas interessantes.

OperaçãoEfeitoExige
RENAMErenomeia um campo (from → to); se from não existir, não faz nadafrom, to
SELECTmantém só os campos listadosfields (≥ 1)
OMITremove os campos listadosfields (≥ 1)
CONSTANTdefine um campo com um valor fixoto, value
DEFAULTpreenche to só se estiver ausente/null; um valor falsy existente é preservadoto, value
ENUMtraduz o valor de from por uma tabela; valor fora da tabela fica como estáfrom, values
FORMATDATE_ONLY (primeiros 10 caracteres), LOWERCASE, UPPERCASE ou TRIM (default) sobre um campo stringfrom, format

A especificação é validada na configuração (ao habilitar o grant), não na requisição — o parceiro nunca descobre um mapping inválido só quando chama a rota de verdade.

Endpoints​

MétodoRotaDescrição
PUT/v1/integration-platform/instances/:instanceId/route-grants/:capabilityKeyHabilita (ou atualiza) a capability para a instância
DELETE/v1/integration-platform/instances/:instanceId/route-grants/:capabilityKeyDesabilita a capability
GET/v1/integration-platform/instances/:instanceId/route-grantsLista os grants da instância

Versão: v1

Swagger: Integration Platform — Route grants · Rota (Dev): http://localhost:3000/v1/integration-platform/instances/:instanceId/route-grants

Estas rotas rodam na API principal (porta 3000) — ver visão geral do módulo.

Permissões​

RotaGuardsPerfil / escopo exigido
Todas deste grupoJwtAuthenticationGuardvínculo TENANT/UNIT da instância: assertCanManageTenantIntegrations; vínculo PLATFORM: assertCanManagePlatformIntegrations

Headers​

HeaderObrigatórioDescrição
AuthorizationSimBearer <token de sessão de usuário>

Path parameters​

NomeTipoObrigatórioDescrição
instanceIduuidSimInstância que recebe a concessão
capabilityKeystringSimChave do catálogo, ex. public-api.exam.read

Body​

EnableIntegrationPlatformRouteGrantRestRequest (PUT):

json
{
"rate_profile": "STANDARD",
"response_mapping": [
{ "operation": "RENAME", "from": "accession_number", "to": "accessionNumber" },
{ "operation": "OMIT", "fields": ["patient"] },
{ "operation": "CONSTANT", "to": "source", "value": "mobilemed" }
]
}
CampoTipoObrigatórioValidação
rate_profileenum STANDARD/INTERACTIVE/BULKNãodefault STANDARD
response_mappingarray de passosNãover tabela de operações acima; validado inteiro na escrita

Response​

200 — IntegrationPlatformRouteGrantRestResponse:

json
{
"grant_id": "0198f3a4-...-uuid",
"integration_instance_id": "0198f3a4-...-uuid",
"capability_key": "public-api.exam.read",
"owner_domain": "DIAGNOSIS",
"rate_profile": "STANDARD",
"response_mapping": null,
"status": "ENABLED"
}

Erros​

Classe de erroerrorCodeStatusQuando ocorre
UnknownRouteCapabilityErrorINTEGRATION_PLATFORM_UNKNOWN_ROUTE_CAPABILITY422capabilityKey fora do catálogo compilado
RouteCapabilityNotGrantedErrorINTEGRATION_PLATFORM_ROUTE_CAPABILITY_NOT_GRANTED403/404 (conforme rota)desabilita uma capability sem grant existente; ou (no data plane) chamada sem grant habilitado
InvalidResponseMappingErrorINTEGRATION_PLATFORM_RESPONSE_MAPPING_INVALID400especificação de response_mapping malformada

Regras de negócio​

IDRegraComportamento esperado
RN-01Configuração nunca cria rotasó uma capabilityKey já compilada no catálogo pode virar grant
RN-02Habilitar é idempotenterepetir com os mesmos valores não gera evento de auditoria duplicado
RN-03Grant nunca é apagadodesabilitar marca DISABLED; o histórico do grant permanece
RN-04Deny-by-default sem distinguir motivogrant ausente e grant desabilitado produzem a mesma resposta ao chamador da API pública
RN-05Mapping é validado na configuraçãoum response_mapping inválido nunca chega a ser aplicado numa resposta real
RN-06Mapping nunca falha "de forma interessante"campo ausente é ignorado pelo passo, nunca lança erro em tempo de requisição

Compliance​

Órgão / normaExigênciaComo a rota atende
LGPDminimização — expor só o necessário a cada parceiroSELECT/OMIT no de-para permitem remover campos (ex. dados de paciente) da resposta a um parceiro específico
ANVISA (indireto)rastreabilidade de quem concedeu o quêevento de auditoria integration_platform.route_grant.enabled/disabled, com snapshot antes/depois

Variáveis de ambiente​

Nenhuma específica desta rota.

Requisitos não funcionais​

RequisitoDefinição
IdempotênciaSim para habilitar com os mesmos valores; desabilitar repetido também é no-op
PaginaçãoNão — lista todos os grants da instância
Rate limitO rate_profile do grant é o que a API pública aplica na chamada real — ver Autenticação e autorização de máquina
AuditoriaSim — evento por habilitação/desabilitação, via outbox assinado

Relacionado​