A prova de ponta a ponta terminou. Com o bloco no ar, /planos devolvia bronze
mensal 5,00 contra anual 1.870,00 — e a landing page mostraria os dois lado a
lado.
A contratacao pela landing page. Aqui nao ha catch-all: caminho que nao esta
escrito nao existe — o endpoint respondeu vazio com a imagem ja no ar porque o
servico tinha a rota e o Ingress nao.
internationalizationEnabled vem FALSE por padrao no Keycloak, e ai ele cai no
en — o e-mail sairia em ingles mesmo com o emailTheme certo. defaultLocale
pt-BR e supportedLocales so pt-BR: uma opcao so nao mostra seletor de idioma na
tela de login.
Minha insercao anterior casou por substring e caiu no objeto do cliente spa,
onde loginTheme e emailTheme nao querem dizer nada — entao um tenant novo
continuava nascendo com a tela de fabrica, e o commit anterior dizia o
contrario.
Refeito carregando o JSON, tirando as chaves de onde nao pertenciam e provando
que o resto do documento e identico antes de gravar.
O nginx roteia /bff e /api com proxy_pass de variavel, e ai resolve por
requisicao usando a diretiva resolver. O resolver do nginx nao le os dominios
de busca do /etc/resolv.conf: pergunta o nome cru ao CoreDNS, que responde
NXDOMAIN para servico-bff.
O sintoma engana: 502 com could not be resolved no log do nginx, enquanto
getent hosts servico-bff dentro do MESMO pod resolve — porque o getent usa o
search e o nginx nao. E por isso que o escolinha sempre usou FQDN aqui.
O tenant provisionado subia com a tela de login de fabrica e o sistema vazio.
Quatro mudancas, medidas contra o escolinha que e o que funciona:
- 90-servico-bff.yaml: o quinto Deployment. A SPA chama o BFF para quase tudo;
sem ele /bff devolve 502. As URLs apontam para os RUNTIMES, e nao para os
treze servicos — e a diferenca deste molde para o do escolinha.
- a cota sobe para 10 pods e 2Gi: com quatro Deployments o tenant ja usava
1232Mi de 1536Mi, e o BFF pede 256Mi. Caberia em repouso e estouraria no
primeiro rollout.
- loginTheme athleticmap-v2 no realm, com o tema montado no Keycloak
compartilhado.
- imagens alinhadas: frontend 2.67-csp-script e os runtimes 1.2-auditoria.
O que NAO mudou, e por que: ATM_API_URL continua no runtime-operacao e o
Ingress continua com uma rota. Os dois estao certos — o nginx da SPA roteia
/bff e /api por conta propria, e ATM_API_URL e o destino do que nao pertence a
grupo nenhum, hoje o webhook em /api/public. O cabecalho do molde ja dizia.
Vale para TODO tenant provisionado: eles nao tem Keycloak proprio, usam este,
um realm cada. O tema vem por ConfigMap e nao por imagem porque o login.ftl traz
as imagens em data URI — o ConfigMap e montado read-only sobre o diretorio e nao
sobra resources/ para o Keycloak servir.
Sem ele o Keycloak monta os links e o iss com o KC_HOSTNAME global
(auth-plataforma), e os runtimes do tenant validam contra ATM_ISSUER, que o
molde define como auth.athleticmap.com. Os dois tem de bater.
Nao da para resolver so no KC_HOSTNAME porque ele e um so e a plataforma
depende do valor antigo. Dai o frontendUrl por realm, que e para isto.
O molde do tenant ja apontava para ca — a SPA em ATM_KC_URL e os tres runtimes
em ATM_ISSUER — e o host nao existia. O navegador batia em
ERR_CERT_AUTHORITY_INVALID e, passando por cima, em 404 do Traefik.
Nao e auth-plataforma para o cliente: o endereco aparece na barra dele durante
o login, e o nome do nosso tenant interno nao tem o que fazer ali.
A etapa BANCO_CRIADO reinicia o PgBouncer e espera ele voltar. Com 5, o backoff
da 155s — menos do que o pod novo levou nas tres medicoes de hoje, e os dois
clientes pagos precisaram de retomada a mao. Com 8 da 515s, dentro da janela.
So o hostname faz o Keycloak resolver esquema e porta a partir da requisicao.
O provisionamento chama a Admin API por dentro (http://keycloak:8080), e o link
do convite saiu http://auth-plataforma.athleticmap.com:8080 — o cliente clicava
e dava ERR_CONNECTION_TIMED_OUT.
O deny-cross-tenant libera 443 para a internet e nada mais. O Keycloak batia em
Network is unreachable na 587, e o erro que chegava ao provisionamento era
Failed to send execute actions email — que manda procurar no SMTP, nao na rede.
db-credentials (a senha do papel) e <tenant>-tls (so a existencia, que e como a
etapa DNS_PUBLICADO sabe que o cert-manager terminou). Por tenant porque o nome
do TLS depende dele e resourceNames nao aceita curinga — e dar get em qualquer
Secret do namespace deixaria o provisionamento ler a chave Asaas DO CLIENTE.
RBAC amarrado por resourceNames (db-credentials nos tenants, pgbouncer-userlist
so aqui), netpol do PgBouncer por ROTULO em vez de por nome, e a credencial de
administracao do Postgres compartilhado para o servico-captacao.