Files
athletic-map-deploy/tenants/plataforma/30-ingress.yaml
T
deploy 7090f2a1b3 feat(plataforma): auth.athleticmap.com, o host de autenticacao DOS TENANTS
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.
2026-09-24 23:08:19 +00:00

207 lines
12 KiB
YAML

# Ingress do tenant `plataforma`.
#
# ── Por que este arquivo foi escrito, e nao copiado ───────────────────────────
#
# O piloto guarda o Ingress dentro de `30-apps-stubs.yaml`, junto com o stub
# `backend`. Copiar aquele arquivo traria duas coisas que este tenant nao deve
# herdar:
#
# 1. O proprio stub `backend`, que P0.5 mediu nao atender trafego nenhum (11
# requisicoes externas em 50 dias, todas 401) e que esta em fila para ser
# aposentado. Tenant novo nao nasce com divida.
# 2. A rota catch-all `/api` -> `backend`. Aqui nao ha catch-all: o que nao
# casa com um prefixo conhecido devolve 404, que e a resposta honesta.
#
# Os nomes de Service tambem divergem de proposito: o piloto publica `frontend`,
# e aqui o Service se chama `frontend-spa` (veja `95-frontend-spa.yaml`). Copiar
# o do piloto daria um Ingress apontando para um Service inexistente.
#
# ── Por que o dominio e `.influxdigital.com.br`, e nao `.athleticmap.com` ─────
#
# O canonico decidido com o usuario em 2026-09-16 (P0.9) e
# `<tenant>.athleticmap.com`. Ele ainda NAO vale, e nascer nele hoje quebraria
# justamente o criterio deste card ("login funciona"):
#
# - `plataforma.athleticmap.com` e `auth-plataforma.athleticmap.com` nao tem
# registro A nenhum (conferido em 2026-09-17 por nslookup);
# - o apex `athleticmap.com` resolve para 72.61.42.87, que NAO e o cluster —
# o cluster e 187.77.37.184;
# - cert-manager usa desafio HTTP-01, entao sem o host resolvindo para o
# cluster o certificado nao e emitido, e sem certificado nao ha login.
#
# Ja `*.athleticmap.influxdigital.com.br` e wildcard para o cluster (conferido:
# ate um subdominio inventado resolve para 187.77.37.184). Entao este tenant
# sobe hoje e atravessa o corte de dominio junto com os demais, no passo 5 do
# `docs/p09-plano-de-corte-dominio.md` — e nao numa migracao propria.
#
# ── As rotas publicas ────────────────────────────────────────────────────────
#
# Duas, e ambas por desenho:
#
# `/api/public/leads` quem preenche o formulario da landing page
# ainda nao e cliente, e portanto nao tem token.
# `/api/public/webhooks/asaas` o aviso de pagamento chega dos servidores do
# provedor, que tambem nao tem token nosso; quem
# autentica e o cabecalho `asaas-access-token`.
#
# Nenhuma outra rota esta aberta, e nao ha catch-all — o que significa que uma
# rota publica NOVA em qualquer servico precisa ser acrescentada aqui a mao, ou
# devolve 404. O `scripts/conferir_rotas_publicas.py` existe para isso nao
# depender de alguem lembrar.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: plataforma
namespace: plataforma-prod
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.middlewares: plataforma-prod-redirect-https@kubernetescrd
spec:
ingressClassName: traefik
tls:
- hosts:
- plataforma.athleticmap.influxdigital.com.br
- plataforma.athleticmap.com
- auth-plataforma.athleticmap.influxdigital.com.br
- auth-plataforma.athleticmap.com
# O host de autenticacao DOS TENANTS. Ver a regra la embaixo.
- auth.athleticmap.com
secretName: plataforma-tls
rules:
- host: plataforma.athleticmap.influxdigital.com.br
http:
paths:
# PUBLICA — sem token, por desenho. Vem primeiro porque o Traefik
# ordena por tamanho do prefixo, mas deixar explicito evita que alguem
# reordene sem perceber.
- { path: /api/public/leads, pathType: Prefix, backend: { service: { name: servico-captacao, port: { number: 80 } } } }
# PUBLICA — a tela de espera depois do pagamento (P5.8). Quem acabou de
# pagar AINDA NAO TEM CONTA, logo nao tem token: se esta rota exigisse
# um, a tela que existe para tranquilizar quem pagou seria a primeira a
# recusa-lo.
#
# O que ela entrega e deliberadamente pouco: se a conta ficou pronta e
# o endereco do tenant. Nem nome, nem e-mail, nem plano, nem realm — o
# id da assinatura na URL e a unica "credencial" da tela, e ha teste
# guardando esse limite. Acrescentar um campo aqui e acrescentar o que
# um link vazado entrega.
#
# Estava PREPARADA e nao publicada desde 2026-09-19: o controlador
# existe (`EstadoDaContaController`) e a cadeia ja a liberava
# (`SecurityConfig`, permitAll), mas sem esta linha o Ingress devolvia
# 404 — nao ha catch-all aqui, por desenho.
- { path: /api/public/conta, pathType: Prefix, backend: { service: { name: servico-captacao, port: { number: 80 } } } }
# PUBLICA — o aviso de ASSINATURA do Asaas (P5.1), que e outra coisa do
# `/api/public/webhooks/asaas` logo abaixo: aquele avisa que uma COBRANCA
# de cliente foi paga e vai para o financeiro do tenant; este avisa que
# alguem assinou a Athletic Map, e e o que dispara o provisionamento de
# um tenant NOVO. Contas diferentes no Asaas, servicos diferentes aqui.
#
# Chega da internet sem token nosso; quem autentica e o
# `PLATAFORMA_WEBHOOK_TOKEN`, conferido no `WebhookDeAssinatura`. Sem o
# segredo selado, o endpoint RECUSA tudo de proposito, e o log diz isso.
#
# Sem esta linha o Ingress devolvia 404: alguem assinaria, pagaria, e
# nenhum tenant seria criado — sem erro em lugar nenhum do nosso lado.
- { path: /api/public/webhooks/assinatura, pathType: Prefix, backend: { service: { name: servico-captacao, port: { number: 80 } } } }
# PUBLICA — o aviso de pagamento do Asaas, que chega da internet sem
# token nenhum (P3.3). NAO casa com /api/financeiro: o controlador
# atende em /api/public/webhooks/asaas, e como aqui nao ha catch-all,
# a ausencia desta linha daria 404 em todo aviso — a cobranca seria
# paga e nunca baixada. Quem autentica e o cabecalho
# `asaas-access-token`, conferido no WebhookAsaasController.
- { path: /api/public/webhooks/asaas, pathType: Prefix, backend: { service: { name: servico-financeiro, port: { number: 80 } } } }
# O resto exige token, como em qualquer tenant.
- { path: /api/configuracao, pathType: Prefix, backend: { service: { name: servico-configuracao, port: { number: 80 } } } }
- { path: /api/cadastro, pathType: Prefix, backend: { service: { name: servico-cadastro, port: { number: 80 } } } }
- { path: /api/financeiro, pathType: Prefix, backend: { service: { name: servico-financeiro, port: { number: 80 } } } }
- { path: /bff, pathType: Prefix, backend: { service: { name: servico-bff, port: { number: 80 } } } }
- { path: /, pathType: Prefix, backend: { service: { name: frontend-spa, port: { number: 80 } } } }
- host: plataforma.athleticmap.com
http:
paths:
# PUBLICA — sem token, por desenho. Vem primeiro porque o Traefik
# ordena por tamanho do prefixo, mas deixar explicito evita que alguem
# reordene sem perceber.
- { path: /api/public/leads, pathType: Prefix, backend: { service: { name: servico-captacao, port: { number: 80 } } } }
# PUBLICA — a tela de espera depois do pagamento (P5.8). Quem acabou de
# pagar AINDA NAO TEM CONTA, logo nao tem token: se esta rota exigisse
# um, a tela que existe para tranquilizar quem pagou seria a primeira a
# recusa-lo.
#
# O que ela entrega e deliberadamente pouco: se a conta ficou pronta e
# o endereco do tenant. Nem nome, nem e-mail, nem plano, nem realm — o
# id da assinatura na URL e a unica "credencial" da tela, e ha teste
# guardando esse limite. Acrescentar um campo aqui e acrescentar o que
# um link vazado entrega.
#
# Estava PREPARADA e nao publicada desde 2026-09-19: o controlador
# existe (`EstadoDaContaController`) e a cadeia ja a liberava
# (`SecurityConfig`, permitAll), mas sem esta linha o Ingress devolvia
# 404 — nao ha catch-all aqui, por desenho.
- { path: /api/public/conta, pathType: Prefix, backend: { service: { name: servico-captacao, port: { number: 80 } } } }
# PUBLICA — o aviso de ASSINATURA do Asaas (P5.1), que e outra coisa do
# `/api/public/webhooks/asaas` logo abaixo: aquele avisa que uma COBRANCA
# de cliente foi paga e vai para o financeiro do tenant; este avisa que
# alguem assinou a Athletic Map, e e o que dispara o provisionamento de
# um tenant NOVO. Contas diferentes no Asaas, servicos diferentes aqui.
#
# Chega da internet sem token nosso; quem autentica e o
# `PLATAFORMA_WEBHOOK_TOKEN`, conferido no `WebhookDeAssinatura`. Sem o
# segredo selado, o endpoint RECUSA tudo de proposito, e o log diz isso.
#
# Sem esta linha o Ingress devolvia 404: alguem assinaria, pagaria, e
# nenhum tenant seria criado — sem erro em lugar nenhum do nosso lado.
- { path: /api/public/webhooks/assinatura, pathType: Prefix, backend: { service: { name: servico-captacao, port: { number: 80 } } } }
# PUBLICA — o aviso de pagamento do Asaas, que chega da internet sem
# token nenhum (P3.3). NAO casa com /api/financeiro: o controlador
# atende em /api/public/webhooks/asaas, e como aqui nao ha catch-all,
# a ausencia desta linha daria 404 em todo aviso — a cobranca seria
# paga e nunca baixada. Quem autentica e o cabecalho
# `asaas-access-token`, conferido no WebhookAsaasController.
- { path: /api/public/webhooks/asaas, pathType: Prefix, backend: { service: { name: servico-financeiro, port: { number: 80 } } } }
# O resto exige token, como em qualquer tenant.
- { path: /api/configuracao, pathType: Prefix, backend: { service: { name: servico-configuracao, port: { number: 80 } } } }
- { path: /api/cadastro, pathType: Prefix, backend: { service: { name: servico-cadastro, port: { number: 80 } } } }
- { path: /api/financeiro, pathType: Prefix, backend: { service: { name: servico-financeiro, port: { number: 80 } } } }
- { path: /bff, pathType: Prefix, backend: { service: { name: servico-bff, port: { number: 80 } } } }
- { path: /, pathType: Prefix, backend: { service: { name: frontend-spa, port: { number: 80 } } } }
- host: auth-plataforma.athleticmap.influxdigital.com.br
http:
paths:
- { path: /, pathType: Prefix, backend: { service: { name: keycloak, port: { number: 8080 } } } }
- host: auth-plataforma.athleticmap.com
http:
paths:
- { path: /, pathType: Prefix, backend: { service: { name: keycloak, port: { number: 8080 } } } }
# O HOST DE AUTENTICACAO DOS TENANTS.
#
# O mesmo Keycloak, outro nome. 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 page not found` do Traefik. Medido em 2026-09-24, no
# primeiro login de um tenant provisionado.
#
# Nao e `auth-plataforma` para o cliente: o endereco aparece na barra do
# navegador dele durante o login, e o nome do NOSSO tenant interno nao tem
# o que fazer ali.
#
# O realm de cada tenant recebe `frontendUrl` com este endereco, senao o
# Keycloak geraria os links com o `KC_HOSTNAME` global — que continua sendo
# o `auth-plataforma`, porque a plataforma depende dele.
- host: auth.athleticmap.com
http:
paths:
- { path: /, pathType: Prefix, backend: { service: { name: keycloak, port: { number: 8080 } } } }