Em outra linguagem: o protocolo de runtime
O runtime da aplicação — ler quem entrou e consultar o QueryMesh — existe pronto no SDK de TypeScript (@nnumbers/zero/app e @nnumbers/zero/react). O SDK publicado de Go é o cliente da API de gerenciamento, não o runtime; uma aplicação em outra linguagem segue o protocolo de runtime, que é o contrato entre a plataforma e o código da aplicação e está descrito nesta página.
A identidade de quem entrou
A cada requisição que chega pela borda, a plataforma põe em X-NNumbers-Identity um JWS compacto — cabeçalho alg: ES256, typ: nn-identity+jwt, kid — com o payload abaixo. Sem pessoa autenticada, o cabeçalho não vem. Um valor mandado pelo navegador é removido antes de qualquer outra coisa.
A aplicação sempre confere:
- a assinatura, com as chaves públicas do broker (
NNUMBERS_IDENTITY_JWKS; eNNUMBERS_BROKER_URL/v1/jwksquando chega umkiddesconhecido) — guarde as chaves por alguns minutos e não busque de novo a cada requisição; issigual aNNUMBERS_IDENTITY_ISSUER;audigual aNNUMBERS_APP_ID— a identidade entregue a outra aplicação não vale aqui;orgigual aNNUMBERS_ORG_ID;nbfeexp, com até 60 s de tolerância de relógio — a identidade vale por 5 minutos.
Um cabeçalho sem assinatura conferida não prova nada: há caminhos que chegam à aplicação sem passar pela borda (o mesmo namespace, as permissões de rede, a entrada interna). Sem o cabeçalho, a requisição é anônima; com o cabeçalho e qualquer conferência falhando, recuse — nunca trate como pessoa.
| Claim | O que é |
|---|---|
iss, aud, jti | o emissor, a aplicação desta identidade e o identificador dela |
sub | o sujeito da pessoa no IAM da organização |
org, org_slug | a organização |
iam | o emissor do IAM da organização |
sid | a sessão na plataforma — referência opaca, não é o cookie |
name, email, email_verified, preferred_username | quando a conta os tem |
iat, nbf, exp | o prazo; exp é 5 minutos depois de iat |
Os caminhos reservados
Os caminhos em /.nnumbers/ são servidos pela plataforma no endereço da própria aplicação — nunca chegam ao código dela:
| Método e caminho | Resposta |
|---|---|
GET /.nnumbers/auth/login?return_to=<caminho> | 302 para o login do IAM da organização |
GET /.nnumbers/auth/callback | 302 de volta ao return_to, com a sessão criada |
POST /.nnumbers/auth/logout | 303 para /, com a sessão da aplicação encerrada; exige Origin do próprio endereço |
GET /.nnumbers/auth/session | 203 {"user": {...} | null, "organization": {"id", "slug"}} |
GET /.nnumbers/v1/context | 203 {"app": {"id"}, "organization": {"id", "slug"}, "auth": {"login_path", "logout_path"}} |
return_to só aceita caminho do próprio endereço (começa com /, não com //). Os JSON vêm com 203, não 200, e Cache-Control: no-store — é como a borda repassa a resposta da plataforma, e o navegador lê 203 como sucesso.
Sair é da aplicação: encerra a sessão dela, e o login único da organização continua — entrar de novo não pede senha enquanto ele durar.
O broker, de dentro do cluster
NNUMBERS_BROKER_URL só é alcançável de dentro do cluster. A aplicação o usa para as duas operações:
| Método e caminho | O que faz |
|---|---|
GET /v1/jwks | as chaves públicas que assinam a identidade |
POST /v1/querymesh/query | com X-NNumbers-Identity da requisição, executa a consulta no QueryMesh da organização em nome daquela pessoa e devolve colunas e linhas |
A consulta leva a SQL e, opcionalmente, o teto de linhas:
POST {NNUMBERS_BROKER_URL}/v1/querymesh/query
X-NNumbers-Identity: <a identidade da requisição, já conferida>
Content-Type: application/json
{"sql": "SELECT name, regionkey FROM tpch.tiny.nation", "max_rows": 1000}
| Campo | O que é |
|---|---|
sql | a consulta (obrigatória); nunca vai para log |
max_rows | o teto de linhas trazidas, de 1 a 100.000 (padrão 100.000); acima dele, a consulta é cancelada no QueryMesh |
O endereço do QueryMesh é o que o administrador da organização configurou (zero orgs integrations set querymesh --url https://…); a aplicação não o escolhe. Quem consulta é a plataforma, com o token da sessão da pessoa, direto — sem troca de token —, e o token não sai da plataforma. Sem pessoa, não há consulta: nenhum caminho cai para uma credencial "da aplicação".
O sucesso devolve as colunas, com o tipo do Trino, e as linhas, na ordem das colunas:
{
"columns": [{"name": "name", "type": "varchar"}, {"name": "regionkey", "type": "bigint"}],
"rows": [["BRAZIL", 1]]
}
As recusas vêm como {"code", "message"}:
| Status | Código | Quando | O que fazer |
|---|---|---|---|
400 | VALIDATION_FAILED | sem SQL, ou max_rows fora de 1–100.000 | corrija o pedido e repita |
401 | USER_SESSION_REQUIRED | sem identidade, ou a sessão de quem entrou terminou | leve a pessoa ao login e repita |
401 | IDENTITY_ASSERTION_INVALID | a identidade não confere (assinatura, emissor, prazo, organização, aplicação) | use a identidade que a plataforma entrega; não trate como pessoa |
409 | ORGANIZATION_INTEGRATION_NOT_CONFIGURED | a organização não tem o QueryMesh configurado, ou ele está desligado | o administrador da organização configura |
409 | QUERYMESH_NOT_ENABLED | a aplicação não ligou a capacidade querymesh | zero services enable querymesh <serviço> — vale na hora |
502 | QUERYMESH_IDENTITY_REJECTED | o QueryMesh não aceitou o token de quem entrou (emissor, audiência ou scope) | quando falta ao realm o scope que o QueryMesh exige, quem resolve é a administração da plataforma — entrar de novo não resolve |
403 | QUERYMESH_ACCESS_DENIED | as políticas de dados da organização negaram a consulta a esta pessoa | peça o acesso ao administrador de dados |
422 ou 502 | QUERYMESH_QUERY_FAILED | 422: o QueryMesh recusou a consulta ou o resultado passou do teto; 502: o QueryMesh respondeu fora do protocolo ou mandou continuar fora do endereço configurado | confira a consulta e repita; no 502, fale com quem administra o QueryMesh |
503 | QUERYMESH_UNAVAILABLE | o QueryMesh não respondeu ou está ocupado, ou a plataforma está no limite de consultas | repita em instantes |
503 | APPLICATION_IDENTITY_NOT_READY | o broker não tem as chaves disponíveis agora | repita; se persistir, zero services doctor organization-iam <serviço> |
O que a aplicação nunca recebe
Segredo de cliente (não existe: o client de login é público), token de renovação, o token de acesso do IAM — nem para o QueryMesh, porque quem consulta é a plataforma —, e nenhum meio de escolher a pessoa.
Próximos passos
Esta página ajudou?
Reportar um problema nesta páginaNão envie senhas, chaves, tokens ou dados de clientes.