# Plano de desacoplamento do monorepo Monetarie

Data: 2026-07-10
Autor: sessão de mapeamento e documentação (mandato do dono)
Status: PROPOSTA para decisão dos sócios. Nada foi extraído ainda.

## 1. Contexto e motivação

Hoje todo o ecossistema vive em um único repositório (`git@github.com:VulciBR/monetarie.git`). Com a base de clientes crescendo e o time assumindo o desenvolvimento, o monorepo passa a ser um gargalo: deploys acoplados, histórico gigante, permissões de acesso indivisíveis e onboarding pesado. A decisão do time é: core é core, pix é pix, spb é spb, cada sistema no seu repositório.

Fato importante que facilita muito: **os sistemas já são desacoplados em runtime**. Cada um tem seu banco próprio, seu serviço ECS próprio e a comunicação entre eles é por NATS (eventos) e HTTP (consultas pontuais). O acoplamento que existe é de REPOSITÓRIO, não de arquitetura. O desacoplamento é, portanto, uma operação de engenharia de repositório + CI, não uma reescrita.

## 2. Estado atual do repositório (verificado no código em 2026-07-10)

| Diretório | Conteúdo | Tecnologia | Serviço(s) ECS |
|---|---|---|---|
| `core/` | Core bancário: backend Phoenix único (app `:monetarie`, namespace `Monetarie.*`, TigerBeetle vendorizado em `core/backend/lib/tigerbeetlex`), UIs admin/banking/merchant em `core/apps/`, `core/packages/shared`, docs-site | Elixir + Vue | core-api, core-admin-ui, core-banking-ui, core-merchant-ui |
| `pix/` | Cabine PIX: umbrella Elixir (`pix/backend/apps/{spi_service,dict_service,settlement_service,shared}`), frontend admin, simulator-frontend | Elixir + Vue | pix-api, pix-admin-ui |
| `spb/` | Cabine SPB: `spb/services/` com bacen_gateway (Elixir), bacen_gateway_mq_sidecar (Java/JMS), e services auxiliares (api_gateway, cash, extract, forex, message_processor, securities, settlement, transaction, user_management), frontend-vue, simulator, simulator-frontend | Elixir + Java + Vue | spb-api, spb-admin-ui |
| `npc/` | NPC: backend + frontend + simulator-frontend | Elixir + Vue | npc-api, npcadmin |
| `sta/` | STA (transferência de arquivos BACEN): backend + frontend + admin-portal | Elixir + Vue | sta-api, staadmin |
| `clst/` | CLST: app Elixir único | Elixir | clst-api |
| `backoffice/` | Backoffice | Vue | backoffice |
| `docs-portal/` | Portal de documentação | Node | docs |
| `mobile/` | App Flutter | Flutter | (lojas) |
| `packages/` | `mobile-ui` compartilhado | | |
| `infra/` | Terraform AWS (HML 10.45 + PROD 10.50) | Terraform | n/a |
| `etl/`, `migration/`, `audit/`, `benchmark/` | Ferramentas de carga de legado, auditoria e benchmark | misto | n/a |
| `docs/` | Handoffs, relatórios, planos, runbooks (memória operacional do projeto) | Markdown | n/a |
| `scripts/` | Scripts de deploy, captura de evidência, relatórios | misto | n/a |

Não existe CI no GitHub hoje (não há `.github/workflows`); deploy é manual por scripts (`scripts/deploy_hml_arm64.sh` para HML, retag + task definition manual para PROD). Os `cloudbuild.yaml` encontrados em `pix/` e `clst/` são resíduo de GCP e não estão em uso.

## 3. Mapa de repositórios proposto

| Novo repositório | Origem no monorepo | Observações |
|---|---|---|
| `monetarie-core` | `core/` | Inclui as 3 UIs do Core (admin, banking/IB, merchant) e a Partner API. Se o time preferir, as UIs podem sair depois em um segundo passo; começar junto reduz risco. |
| `monetarie-pix` | `pix/` | Umbrella inteira + pix-admin-ui + simulador PIX. O app `shared` da umbrella (namespace `Shared.*`) é interno da cabine e VAI JUNTO. |
| `monetarie-spb` | `spb/` | bacen_gateway + sidecar MQ + spb-admin-ui + simulador SPB. Services auxiliares não deployados devem ser avaliados: arquivar ou levar. |
| `monetarie-npc` | `npc/` | |
| `monetarie-sta` | `sta/` | |
| `monetarie-clst` | `clst/` | |
| `monetarie-backoffice` | `backoffice/` | |
| `monetarie-mobile` | `mobile/` + `packages/mobile-ui` | |
| `monetarie-docs-portal` | `docs-portal/` | |
| `monetarie-infra` | `infra/` + scripts de deploy | Terraform e operação. Acesso restrito (é onde mora a topologia). |
| `monetarie-contracts` | NOVO (extraído de docs + código) | Contratos entre sistemas: subjects NATS + schema de payload de cada evento, códigos de conta/ledger TigerBeetle, convenções de idempotência. Ver seção 5. |
| `monetarie-workspace` | NOVO | Repositório leve de desenvolvimento: script que clona todos os repos lado a lado + `dev_up_all.sh` adaptado + docs de onboarding. |
| `monetarie-archive` | monorepo atual congelado | Vira somente leitura após o corte. Preserva TODO o histórico e os handoffs. |

Ferramentas de época (`etl/`, `migration/`, `audit/`, `benchmark/`) ficam no archive; se alguma voltar a ser usada, extrai na hora.

## 4. Mecânica de extração (preservando histórico)

Usar `git filter-repo` (não `git subtree split`): é a ferramenta mantida, rápida e preserva o histórico completo do subdiretório. Cada novo repo nasce com todo o histórico de commits que tocou aquele diretório.

Receita por sistema (exemplo PIX):

```bash
# 1. clone limpo (filter-repo exige clone fresco)
git clone git@github.com:VulciBR/monetarie.git monetarie-pix-extract
cd monetarie-pix-extract

# 2. filtra só o que pertence ao PIX, movendo pra raiz
git filter-repo \
  --path pix/ \
  --path docs/handoff/ --path docs/reports/ --path docs/plans/ \
  --path-rename pix/:

# 3. aponta pro repo novo e sobe
git remote add origin git@github.com:VulciBR/monetarie-pix.git
git push -u origin main
```

Decisão a tomar por repo: levar ou não `docs/` (handoffs contêm contexto de TODOS os sistemas juntos). Recomendação: handoffs e relatórios ficam no `monetarie-archive` como fonte histórica única, e cada repo novo nasce com um `docs/` limpo contendo apenas: o doc de arquitetura do sistema, o dicionário de dados, o relatório de fidelidade do simulador (PIX/SPB) e o CLAUDE.md recortado para aquele sistema.

Cuidados:

- `git filter-repo` reescreve hashes: os SHAs citados nos handoffs antigos só valem no archive. Por isso o archive é obrigatório e permanente.
- Fazer a extração a partir de um commit de corte único (tag `pre-split-2026-XX-XX`) para todos os repos, com o monorepo congelado (janela sem merge).
- PRs abertos precisam ser mesclados ou portados antes do corte.
- O `.gitignore` de cada repo novo deve ser revisado (hoje `.scratch/` com PII é ignorado no monorepo; garantir o mesmo em cada repo).

## 5. O contrato entre sistemas: `monetarie-contracts`

O único acoplamento real em runtime é o que trafega no fio. Depois do split, uma mudança de payload NATS feita no repo do PIX pode quebrar o Core sem ninguém perceber no PR. O antídoto é tornar o contrato explícito:

1. **Catálogo de eventos**: um arquivo por subject NATS (nome, produtor, consumidores, payload com schema JSON, exemplo real, versão). A matriz completa produtor/consumidor está em `docs/architecture/2026-07-10-integracao-ecossistema.md` e é o insumo inicial.
2. **Constantes compartilhadas**: códigos de ledger/conta TigerBeetle (ex.: 1_004 escrow), unidade monetária (TigerBeetle é SUBCENTAVO, Postgres do Core é centavo: essa diferença já causou o bug 100x duas vezes), enum de status canônico (`Shared.Spi.StatusCodes` no PIX, `Shared.Bacen.Iso20022.RejectCodes`).
3. **Regra de evolução**: payload só evolui de forma aditiva; remoção/renome de campo exige janela de dupla publicação e aprovação dos times consumidores (CODEOWNERS do repo contracts com pelo menos 1 sócio de cada sistema).
4. **Testes de contrato**: cada repo consumidor ganha um teste que valida os payloads que consome contra o schema do contracts (fixture versionada). Roda no CI de todos os repos.

Formato recomendado: repo só de Markdown + JSON Schema no início (barato, legível). Publicar como pacote Hex privado só se/quando o time quiser dependência compilada.

## 6. CI/CD por repositório (não existe hoje, o split é o momento de criar)

Cada repo de sistema ganha o mesmo esqueleto de GitHub Actions:

1. **PR**: `mix format --check-formatted`, `mix compile --warnings-as-errors` (quando o repo estiver saneado), `mix test` da suíte estável do sistema, lint do frontend, teste de contrato.
2. **Merge em main**: build da imagem arm64, push pro ECR com tag imutável `hml-<sha>`, deploy automático em HML (nova task definition + `ecs update-service`), smoke de `/health`.
3. **Produção**: SEMPRE manual (workflow_dispatch), retag `prod-<sha>` + task definition, exigindo aprovação. Regra do dono continua valendo: em produção não existe teste, validação é com a primeira transação real acompanhada.

Autenticação do CI na AWS por OIDC (role por repo com permissão mínima: ECR push + ECS deploy dos SEUS serviços apenas). Isso também resolve o problema de acesso: quem trabalha no PIX não precisa de credencial que alcance o Core.

## 7. Sequência recomendada (ondas, menor risco primeiro)

| Onda | O quê | Por quê primeiro |
|---|---|---|
| 0 | Congelar contratos: escrever o `monetarie-contracts` a partir da matriz de integração; adicionar testes de contrato ainda DENTRO do monorepo | Garante que o fio está documentado antes de separar os times |
| 1 | `monetarie-infra` + `monetarie-workspace` | Zero risco de runtime; destrava CI/OIDC |
| 2 | Satélites: `monetarie-clst`, `monetarie-sta`, `monetarie-npc`, `monetarie-backoffice`, `monetarie-docs-portal`, `monetarie-mobile` | Sistemas menores, menos tráfego, valida a receita de extração + CI de ponta a ponta |
| 3 | `monetarie-spb` | Cabine com menos superfície que o PIX; sidecar MQ junto |
| 4 | `monetarie-pix` | Cabine maior; simulador precisa estar fiel (relatório de fidelidade) antes, pois vira a bancada oficial do time |
| 5 | `monetarie-core` | O hub sai por último, quando todos os vizinhos já provaram CI e contratos |
| 6 | Monorepo vira `monetarie-archive` (somente leitura, README apontando para os novos repos) | |

Cada onda só fecha com: repo novo buildando no CI, imagem deployada em HML a partir do repo novo, health 200, e um deploy de PROD feito a partir do repo novo (validado vivo). A partir daí, o diretório correspondente no monorepo é congelado (PR bloqueado por CODEOWNERS) até o corte final.

Estimativa honesta: ondas 0-2 cabem em uma semana de trabalho focado; SPB, PIX e Core são um corte por semana com folga para estabilizar. O calendário real depende do time.

## 8. Regras de fronteira pós-split (para não regredir)

1. Nenhum sistema lê o banco de outro. A exceção histórica (Core consultando a API admin da cabine PIX por E2E) é HTTP, não SQL, e continua permitida.
2. Todo dado que cruza sistema passa por NATS ou HTTP versionado no contracts.
3. TigerBeetle é do Core. Cabines não escrevem no TB (hoje já é assim, manter).
4. Assinatura BACEN (HSM) é exclusiva das cabines PIX e SPB, nunca do Core (regra absoluta 13 do CLAUDE.md).
5. Cada repo tem seu próprio CLAUDE.md, recortado do atual, só com o que vale para aquele sistema.
6. Segredos continuam SÓ no AWS Secrets Manager `monetarie/{env}/*`; o split não muda isso.

## 9. Riscos e mitigação

| Risco | Mitigação |
|---|---|
| Quebra silenciosa de contrato NATS entre repos | Onda 0 (contracts + testes de contrato) ANTES de qualquer split |
| Dupla manutenção durante a transição | Congelamento por diretório assim que o repo novo assume o deploy |
| Perda de contexto histórico (handoffs, SHAs) | `monetarie-archive` permanente e somente leitura |
| CI novo deployando errado em PROD | PROD sempre manual com aprovação; HML é o campo de prova |
| Time sem ambiente local após o split | `monetarie-workspace` com clone de todos + `dev_up_all.sh` (já criado nesta sessão) adaptado para multi-repo |
| Services SPB não deployados virando zumbis | Decisão explícita na onda 3: arquivar ou levar cada um |

## 10. Decisões que ficam com os sócios

1. UIs do Core no mesmo repo do core-api ou separadas? (Recomendação: juntas na primeira extração.)
2. Levar handoffs históricos para os repos novos ou só archive? (Recomendação: só archive.)
3. Nome da organização/prefixo dos repos (assumido `VulciBR/monetarie-*`).
4. Quem é CODEOWNER de `monetarie-contracts` (recomendação: 1 sócio por sistema, mínimo 2 aprovações).
5. Data do corte da onda 0 e da janela de congelamento.
