POC educacional de microserviços em .NET para estudar arquitetura de software com código real: Clean Architecture, DDD, PostgreSQL, Kafka, Outbox, Inbox, JWT/JWKS com Keycloak, observabilidade, segurança, contratos e testes automatizados.
Ela demonstra um problema comum em sistemas financeiros: registrar fatos de forma transacional, publicar eventos com confiabilidade, projetar saldos em outro serviço e operar falhas sem esconder consistência eventual. O repositório também mostra contextos de identidade, transferência, pagamento externo e auditoria funcional para exercitar trade-offs de integração.
Este projeto é útil para:
- quem está aprendendo arquitetura e quer ver os conceitos aplicados;
- desenvolvedores .NET que querem executar, testar e alterar uma stack local;
- arquitetos que querem avaliar decisões, limites e riscos;
- avaliadores técnicos que querem entender a proposta rapidamente.
flowchart LR
Client[Cliente ou teste] --> Keycloak[Keycloak OIDC]
Client --> LedgerApi[LedgerService.Api]
Client --> BalanceApi[BalanceService.Api]
Client --> TransferApi[TransferService.Api]
Client --> PaymentApi[PaymentService.Api]
Client --> IdentityApi[IdentityService.Api]
Client --> AuditApi[AuditService.Api]
LedgerApi --> LedgerDb[(PostgreSQL schema ledger)]
LedgerDb --> LedgerWorker[LedgerService.Worker]
LedgerWorker --> Kafka[(Kafka)]
Kafka --> BalanceWorker[BalanceService.Worker]
BalanceWorker --> BalanceDb[(PostgreSQL schema balance)]
BalanceApi --> BalanceDb
TransferApi --> TransferDb[(schema transfer)]
TransferWorker[TransferService.Worker] --> LedgerApi
TransferDb --> TransferWorker
TransferWorker --> Kafka
PaymentApi --> PaymentDb[(schema payment)]
Stripe[Stripe ou provider fake] --> PaymentApi
PaymentDb --> PaymentWorker[PaymentService.Worker]
PaymentWorker --> LedgerApi
IdentityApi --> IdentityDb[(schema identity)]
IdentityApi --> Keycloak
IdentityApi --> Mailpit[Mailpit local]
Kafka --> AuditWorker[AuditService.Worker]
AuditApi --> AuditDb[(schema audit)]
AuditWorker --> AuditDb
No modo local padrão, Kafka é o transporte principal dos workers de Ledger, Balance, Transfer e Audit. Pub/Sub permanece como alternativa explícita/legada apenas para Ledger/Balance. O PaymentService não publica eventos financeiros diretamente: depois de confirmar um pagamento, o worker chama o LedgerService.Api, e o Balance continua sendo atualizado pelos eventos do Ledger.
- Como separar escrita (
Ledger) e leitura (Balance) sem perder rastreabilidade. - Por que Outbox ajuda quando banco e broker precisam andar juntos sem transação distribuída.
- Como Inbox deduplica webhooks externos antes do processamento assíncrono.
- Como idempotência protege retries HTTP, webhooks e consumidores.
- Como uma Saga orquestrada coordena transferência entre merchants.
- Como JWT/JWKS, scopes e autorização por merchant aparecem nas APIs.
- Como health, readiness, logs, traces, métricas, DLQ e replay entram na operação.
- Como ADRs, specs SDD, contratos e runbooks sustentam decisões ao longo do tempo.
| Contexto | Papel no laboratório |
|---|---|
LedgerService |
Fonte de verdade dos fatos financeiros, Outbox, estornos e reprocessamentos. |
BalanceService |
Projeção de saldo consumindo eventos do Ledger. |
TransferService |
Saga de transferência entre merchants, Kafka-only. |
PaymentService |
Pagamentos externos, ACL Stripe/fake provider, webhook assinado, Inbox e materialização no Ledger. |
IdentityService |
Cadastro de usuários, vínculo local, MerchantId, Keycloak Admin API e e-mail local. |
AuditService |
Auditoria funcional por HTTP e consumer Kafka de AuditRecordRequested.v1; os demais domínios ainda não publicam eventos reais de auditoria. |
Auth.Api |
Legado preservado no repositório para rastreabilidade histórica; Keycloak é o emissor principal da stack local. |
Os serviços seguem a separação Api, Application, Domain, Infrastructure e, quando aplicável, Worker. A explicação das fronteiras fica em docs/architecture/boundaries.md.
Pré-requisitos: .NET SDK conforme global.json, CLI docker com docker compose e uma Docker-compatible API acessível.
Valide build e testes:
dotnet tool restore
dotnet restore ./PocArquitetura.slnx
dotnet build ./PocArquitetura.slnx --configuration Release --no-restore
dotnet test ./PocArquitetura.slnx --configuration Release --no-build --settings ./coverlet.runsettingsSuba o core funcional local no Windows:
./scripts/local/create-env-local.ps1
./scripts/local/start-stack.ps1No Linux/macOS:
./scripts/local/create-env-local.sh
./scripts/local/start-stack.shO script sobe PostgreSQL, Kafka, Keycloak, Mailpit, APIs e workers principais, aplica migrations pelo host e preserva volumes. O passo a passo completo, portas, debug, Testcontainers, observabilidade e limpeza ficam em desenvolvimento local.
Para incluir observabilidade local completa:
./scripts/local/start-stack.ps1 -ObservabilityNo Linux/macOS:
OBSERVABILITY=true ./scripts/local/start-stack.shLançamento financeiro
LedgerService.Apirecebe o comando HTTP.- Ledger grava o fato e a mensagem de Outbox na mesma transação.
LedgerService.Workerpublica no Kafka.BalanceService.Workerconsome, aplica idempotência e atualiza a projeção.BalanceService.Apiconsulta o saldo materializado.
Pagamento externo
PaymentService.Apicria o pagamento no provider fake ou Stripe por uma ACL.- Webhooks Stripe entram por endpoint assinado e são persistidos na Inbox.
PaymentService.Workerprocessa a Inbox com retry e lease.- Pagamentos confirmados viram lançamentos no Ledger por chamada HTTP idempotente.
Transferência
TransferService.Apiregistra a Saga.TransferService.Workerchama Ledger para débito e crédito.- Falha após débito dispara compensação por estorno no Ledger.
- Eventos da Saga são publicados no Kafka para rastreabilidade operacional.
| Jornada | Ordem recomendada |
|---|---|
| Rápida, 10 a 15 min | Este README -> FAQ -> Maturidade -> Arquitetura |
| Iniciante | Este README -> docs/README.md -> Boundaries -> Catálogo de padrões -> Mensageria, Outbox e DLQ |
| Desenvolvedor | Desenvolvimento local -> Autenticação -> guias de API em docs/development/*-api.md -> Testes e cobertura |
| Arquitetural | Arquitetura: systemLandscape -> container view -> component view -> dynamic view -> localCoreDeployment -> overlay quando necessário -> ADRs |
| Operacional | Observabilidade -> Runbook de recuperação -> DLQ -> Replay |
O índice completo fica em docs/README.md. A documentação visual LikeC4 publicada fica em https://rodri-oliveira-dev.github.io/poc-arquitetura/.
- Arquitetura
- Catálogo de padrões
- Desenvolvimento local
- Autenticação e autorização
- Mensageria, Outbox e DLQ
- Eventos
- Contratos OpenAPI
- Observabilidade
- Runbooks operacionais
- ADRs
- Specs SDD
- Maturidade
- Roadmap
Esta POC não deve ser lida como pronta para produção. Ela é um laboratório local, com várias decisões deliberadamente proporcionais ao estudo:
- secrets locais ficam fora do Git, mas não há secret store produtivo;
- Kafka local é o caminho padrão; Pub/Sub e legado/opt-in para Ledger/Balance;
- rate limiting é local a cada réplica;
- Nginx, observabilidade, SonarQube e k6 são overlays opcionais;
- não há redrive público versionado para todas as DLQs;
AuditService.Workerconsome o contrato canônico, mas os demais domínios ainda não produzem auditoria funcional real;IdentityServicecria usuários no Keycloak e compensa falhas conhecidas, mas envio de e-mail ainda não usa Outbox durável;- referências ao
Auth.Apisão históricas ou de compatibilidade; Keycloak é a identidade principal.
Para avaliar evolução produtiva, leia baseline de evolução produtiva.
| Tarefa | Comando |
|---|---|
| Testes com cobertura e gate | ./test.ps1 ou ./test.sh |
| Stack local padrão | ./scripts/local/start-stack.ps1 ou ./scripts/local/start-stack.sh |
| Stack completa com Nginx | ./scripts/local/start-full-stack.ps1 ou ./scripts/local/start-full-stack.sh |
| Pub/Sub legado | ./scripts/local/start-stack-pubsub.ps1 ou ./scripts/local/start-stack-pubsub.sh |
| Gerar OpenAPI | ./scripts/contracts/openapi/generate.ps1 ou ./scripts/contracts/openapi/generate.sh |
| Validar eventos | npm run events:validate |
| Gerar LikeC4 | npm run architecture:build |
| Load test smoke Kafka | ./scripts/performance/run-loadtests.ps1 -Mode smoke-kafka ou ./scripts/performance/run-loadtests.sh smoke-kafka |
Leia CONTRIBUTING.md, SECURITY.md e AGENTS.md antes de propor mudanças. Mudanças em contratos HTTP exigem regenerar docs/openapi; mudanças arquiteturais relevantes devem atualizar a documentação correspondente e, quando houver decisão nova, registrar ADR.