diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d6203b5 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,100 @@ +# infra-modumfiscal + +Infraestrutura Docker Swarm do ecossistema Modum Fiscal. Contém configurações de deploy para os ambientes `dev` e `prod`. + +--- + +## Estrutura + +``` +infra-modumfiscal/ +├── dev/ +│ ├── docker-stack.yml # Stack de desenvolvimento/homologação +│ ├── keycloak-stack.yml # Keycloak + banco dedicado (só existe em dev — homolog e prod +│ │ # compartilham a mesma instância, atrás do mesmo nginx) +│ └── nginx/conf.d/ +│ ├── modumfiscal.conf # sistema.modumfiscal.com.br:8080 (API + backoffice + /auth/) +│ └── portal.conf # subdomínios *.modumfiscal.com.br → portal Nuxt (catch-all regex) +└── prod/ + ├── docker-stack.yml # Stack de produção + └── nginx/conf.d/ + ├── modumfiscal.conf # app.modumfiscal.com.br / {tenant}.modumfiscal.com.br:80 + └── portal.conf # subdomínios de cada prefeitura → portal Nuxt (catch-all regex) +``` + +Corrigido em 2026-09-25: a tabela de serviços abaixo e a seção de roteamento estavam incompletas (faltavam `portal-modumfiscal-web`, `portal-redis` e os dois serviços de Dívida Ativa) — atualizado por leitura direta de `dev/docker-stack.yml` e `prod/docker-stack.yml`. + +--- + +## Serviços no Swarm + +| Serviço (nome no stack) | Imagem | Porta interna | Porta exposta | Réplicas em prod | +|------------------------|--------|---------------|---------------|-------------------| +| `nginx` | `nginx:alpine` | 80 | **80** (prod) / **8080** (dev) | 1 | +| `rabbitmq` | `rabbitmq:3-management-alpine` | 5672 (AMQP) / 15672 (UI) | **15672** (UI apenas) | 1 | +| `modumfiscal-api` | `modumfiscal-api:*` | 8090 | — (via Nginx /api/*) | **2** | +| `modumfiscal-front` (core-modumfiscal-web) | `modumfiscal-web:*` | 80 | — (via Nginx /*) | 1 | +| `modumfiscal-arquivo-processor` | `modumfiscal-arquivo-processor:*` | 8091 | — (interna) | 1 | +| `modumfiscal-nfse` | `modumfiscal-nfse:*` | 8091 | — (interna) | 1 | +| `modumfiscal-bancario` | `modumfiscal-bancario:*` | 8093 | — (interna) | 1 | +| `portal-modumfiscal-web` | imagem própria (Nuxt SSR, Node) | 3000 (processo Node, sem Nginx interno) | — (via Nginx `portal.conf`) | **2** | +| `portal-redis` | `redis:7-alpine` (`--appendonly yes`) | 6379 | — (interna, só para o portal) | 1 | +| `modumfiscal-divida-ativa` | imagem própria | 8094 | — (via Nginx `/api/*` no domínio `divida.modumfiscal.com.br`) | 1 | +| `modumfiscal-divida-ativa-web` | imagem própria | 80 | — (via Nginx `/*` no domínio `divida.modumfiscal.com.br`) | 1 | + +Todos na rede externa `app-net` (criada manualmente no Swarm). Volumes nomeados: `rabbitmq-data`, `portal-redis-data`. + +--- + +## Roteamento Nginx + +``` +sistema.modumfiscal.com.br (dev) / app.modumfiscal.com.br + {tenant}.modumfiscal.com.br (prod) +├── /api/* → modumfiscal-api:8090 +├── /auth/* → keycloak (só existe no bloco de dev; prod não roteia /auth/ aqui) +└── /* → modumfiscal-front:80 (SPA, fallback para /index.html) + +*.modumfiscal.com.br (catch-all regex, exclui os hosts acima) → portal-modumfiscal-web:3000 + (portal.conf, com proxy_buffering off para streaming/SSE do Nuxt) + +divida.modumfiscal.com.br + {tenant}.divida.modumfiscal.com.br +├── /api/* → modumfiscal-divida-ativa:8094 +└── /* → modumfiscal-divida-ativa-web:80 (SPA, fallback para /index.html) +``` + +**⚠️ Gap conhecido:** Os endpoints `/webhook/*` do `modumfiscal-arquivo-processor` **não estão roteados via Nginx** em nenhum dos dois ambientes, e o serviço não tem porta publicada no stack. O Banco do Brasil precisa de uma rota exposta para entregar os webhooks. Ação necessária: adicionar `location /webhook/` no nginx apontando para `modumfiscal-arquivo-processor:8091` — ver `docs/planos/PLANO_WEBHOOK_MTLS_BB.md` no workspace, que trata essa rota junto com o requisito de mTLS do Banco do Brasil. + +--- + +## Deploy + +```bash +# Dev +docker stack deploy -c dev/docker-stack.yml modumfiscal-dev + +# Prod +docker stack deploy -c prod/docker-stack.yml modumfiscal +``` + +--- + +## RabbitMQ + +- AMQP `:5672` — **somente interna** (não exposta no host) +- UI `:15672` — **exposta** para gerenciamento +- Credenciais via env: `RABBITMQ_USERNAME`, `RABBITMQ_PASSWORD` +- Serviços que usam: `modumfiscal-api` (publisher) e `modumfiscal-arquivo-processor` (consumer + publisher interno) +- Serviços que **não usam**: `modumfiscal-nfse`, `modumfiscal-bancario` + +--- + +## Variáveis de ambiente no Swarm + +Definidas via `docker secret` ou arquivo `.env` no host: + +| Variável | Quem usa | +|----------|----------| +| `RABBITMQ_HOST` | modumfiscal-api, arquivo-processor | +| `RABBITMQ_USERNAME` | modumfiscal-api, arquivo-processor, rabbitmq | +| `RABBITMQ_PASSWORD` | modumfiscal-api, arquivo-processor, rabbitmq | +| `SPRING_PROFILES_ACTIVE` | todos os serviços Java |