Seguros · .NET · React
Apólice
Seguro de ponta a ponta, da cotação ao pagamento do sinistro: cálculo de prêmio auditável, eventos que não se perdem e API documentada, em .NET 10 e React.
- Cliente
- Projeto pessoal open source
- Cargo
- Engenheiro de Software — projeto independente
- Ano
- 2026
- Tecnologias
- C#
- .NET 10
- ASP.NET Core
- EF Core
- React
- TypeScript
- PostgreSQL
- Aurora DSQL
- RabbitMQ
- Amazon SQS
- AWS Lambda
- Terraform
- xUnit
- Testcontainers
- Playwright
- GitHub Actions































Contexto
Plataforma de seguros open source, construída em outubro de 2026, que cobre o ciclo de vida de uma apólice de Auto, Residencial e Vida: cotação, emissão, endosso, cancelamento e sinistro. Corretor, analista de sinistros e administrador têm autorização por recurso, e o corretor só enxerga a própria carteira. Os dados são 100% fictícios, com login de demonstração por persona. O projeto leva para um back-end em C# e .NET o domínio de seguros que conheci no front-end do ERP da i4Pro, onde consumia APIs .NET, e foi conduzido com Spec-Driven Development: especificação versionada como fonte da verdade, guia de design, 8 ADRs e revisão independente de cada camada antes do merge.
Desafio
Seguro é um domínio em que cada centavo precisa fechar: o prêmio depende de fatores por produto, o endosso cobra ou devolve pro rata, o cancelamento tem três regras de restituição e o sinistro passa por análise, aprovação e pagamento com registro de quem fez o quê. O desafio era entregar esse ciclo completo como um sistema de produção de verdade: regras de negócio testáveis e isoladas da infraestrutura, eventos que não se perdem nem duplicam efeitos, proteção contra acesso à carteira alheia, observabilidade e deploy automatizado na AWS com custo perto de zero.
Resultados
- testes .NET passando: 548 de domínio, 398 de aplicação, 32 de arquitetura e 165 de integração com PostgreSQL e RabbitMQ reais
- 1.143
- de cobertura de linhas no domínio, e cerca de 99,9% na camada de aplicação
- ~99%
- testes do front-end com Vitest, Testing Library e axe, mais E2E em Playwright do fluxo principal contra a produção
- 168
- de custo em produção na AWS, dentro do free tier, com orçamento e alerta configurados
- ~US$ 0
Principais entregas
- 01Arquitetei a API em C# e .NET 10 com Clean Architecture (Domain, Application, Infrastructure, Api e Worker), DDD tático com agregados, value objects e eventos de domínio e Strategy na tarifação de cada produto, com 32 testes de arquitetura (ArchUnitNET) sobre as dependências entre as camadas e as convenções de handlers e agregados.
- 02Desenvolvi 32 operações REST versionadas em /api/v1 com ASP.NET Core Minimal APIs, OpenAPI 3.1 no Scalar e erros em ProblemDetails (RFC 9457), com EF Core 10 na escrita, sob concorrência otimista, e Dapper na leitura, com paginação keyset (CQRS-lite).
- 03Implementei outbox transacional com consumidores idempotentes: RabbitMQ no ambiente local e Amazon SQS com fila de mensagens mortas em produção, em que um relay agendado republica o que ficou pendente.
- 04Protegi a API seguindo o OWASP API Top 10: JWT de 15 minutos com refresh token rotativo em cookie HttpOnly e detecção de reuso, recurso de outra carteira respondendo 404 (anti-BOLA), rate limiting, Idempotency-Key, headers de segurança e auditoria das ações sensíveis.
- 05Construí o front-end em React 19 e TypeScript strict, com TanStack Query, React Hook Form + Zod, Tailwind CSS 4 e Radix UI, mobile first, com tema claro e escuro e meta de acessibilidade WCAG 2.1 AA verificada com axe nos testes.
- 06Automatizei a entrega na AWS com Terraform e GitHub Actions por OIDC (Lambda .NET 10 arm64, Aurora DSQL com autenticação IAM, SQS, EventBridge e segredos no SSM), com 1.143 testes .NET, 165 deles de integração com Testcontainers, e E2E em Playwright do fluxo principal passando contra a produção.
Telas e componentes
Entrada por persona
No login de demonstração, quatro personas entram sem senha: corretora, corretor, analista de sinistros e admin, cada uma com o próprio escopo. Dados fictícios.

Visão da carteira
O dashboard mostra a carteira no escopo de quem entrou: apólices ativas, prêmio emitido nos últimos 12 meses, conversão, sinistralidade e distribuição por produto. Dados fictícios.

Cotação com cálculo ao vivo
Na etapa de coberturas do assistente de 5 passos, o prêmio é recalculado a cada alteração, e a memória de cálculo mostra cada cobertura, cada fator e o IOF. Dados fictícios.

A apólice como certificado
A apólice aparece como um certificado, com vigência, prêmio, parcelamento, coberturas, linha do tempo e as ações de PDF, sinistro, endosso e cancelamento. Dados fictícios.

Cancelamento simulado
Antes de confirmar, o cancelamento simula a restituição pela regra do motivo: tabela de prazo curto a pedido do segurado, pro rata nos demais. Dados fictícios.

Regulação do sinistro
Na visão da analista, o sinistro em análise reúne a triagem automática, o histórico e as ações de aprovar ou negar, aqui no tema escuro. Dados fictícios.

No celular
No celular, o dashboard vira grade de duas colunas, a memória de cálculo abre num painel inferior, a apólice mantém a face de certificado e o histórico do sinistro cabe numa tela. Dados fictícios.
Fundamentos do design system
As cores primitivas viram tokens semânticos com light-dark(), e um mesmo token atende os dois temas. A serifa marca números de apólice e valores, e espaçamento, raios, movimento e botões por variante e estado completam a base.

Componentes de domínio
Os componentes de domínio, em React e TypeScript strict, traduzem o seguro em interface: a apólice como certificado, o cálculo do prêmio com cada fator, os status, o histórico do sinistro, as parcelas e os KPIs. Dados fictícios.

Estados e acessibilidade
As telas preveem vazio, erro com ID de correlação, carregamento e falta de permissão, e o mesmo token muda de valor no tema escuro. O contraste segue a WCAG 2.1 AA, e o axe roda nos testes. Dados fictícios.

API documentada
A API documenta as 32 operações em OpenAPI 3.1 no Scalar, inclusive as simulações de endosso e de cancelamento e o header Idempotency-Key da emissão.

Arquitetura
O quadro segue a requisição de 1 a 10, da SPA na Vercel à Lambda em .NET e ao Aurora DSQL, e o evento pelo outbox até o SQS, o worker e, na falha, a DLQ com alarme por e-mail. A entrega vai de A a G por OIDC e Terraform, e as notas trazem as decisões dos ADRs.

Funcionalidades e as dores que resolvem
Cada funcionalidade nasceu de um problema real da operação.
01
Cotação com cálculo ao vivo
- Dor
- O corretor monta a cotação sem saber quanto cada escolha custa, e um prêmio que ninguém consegue explicar gera desconfiança do segurado.
- Solução
- O assistente de 5 passos recalcula o prêmio a cada alteração, com uma simulação que não grava nada, e mostra a memória de cálculo: prêmio de cada cobertura, fatores aplicados (idade do condutor, região pelo CEP, uso comercial, bônus, tipo de imóvel, fumante), IOF e parcelamento máximo. Cada produto tem a própria estratégia de tarifação.
Impacto: Auto, Residencial e Vida; a cotação gravada vale 30 dias
02
Emissão sem duplicidade
- Dor
- Emitir a partir de uma cotação vencida, ou duas vezes por um clique repetido, gera apólice duplicada e cobrança errada.
- Solução
- A apólice só nasce de cotação aceita e válida, com início da vigência em até 30 dias, número no formato AUTO-2026-000042 e parcelamento em até 10 vezes. A emissão aceita Idempotency-Key: repetir a chave devolve a resposta original, e o PDF da apólice sai com QuestPDF.
03
Endosso pro rata
- Dor
- Mudar o LMI ou incluir uma cobertura no meio da vigência exige cobrar ou devolver só pelos dias restantes, conta que costuma ir para planilha.
- Solução
- O sistema simula antes de confirmar e cobra ou devolve a diferença pro rata pelos dias restantes. Cada agregado tem versão, e uma alteração concorrente vira 409 em vez de sobrescrever a outra.
04
Cancelamento com simulação
- Dor
- Cada motivo de cancelamento tem uma regra de restituição, e aplicar a regra errada devolve dinheiro a mais ou a menos.
- Solução
- Antes de confirmar, o diálogo mostra método, dias decorridos, percentual retido e valor a restituir: integral antes do início da vigência, tabela de prazo curto quando o segurado pede e pro rata die nos demais motivos.
Impacto: O IOF não é restituído, e a tela avisa antes da confirmação
05
Sinistro com triagem e regulação
- Dor
- Sem triagem, um aviso tardio com valor perto do LMI recebe o mesmo tratamento de um caso simples; sem histórico, ninguém sabe quem aprovou o quê.
- Solução
- Cada sinistro novo recebe uma triagem automática e assíncrona, com score de 0 a 100 e alertas (vigência recente, valor perto ou acima do LMI, comunicação tardia). A analista inicia a análise, aprova até o menor valor entre o reclamado e o LMI, nega com motivo ou registra o pagamento, e cada transição entra no histórico com autor e data.
06
Carteira isolada por papel
- Dor
- Num sistema com vários corretores, trocar o id na URL não pode abrir a apólice de outra carteira (BOLA, o primeiro risco do OWASP API Top 10).
- Solução
- A autorização é por recurso: o corretor só vê a própria carteira, e um recurso alheio responde 404, como se não existisse. A analista enxerga tudo, mas não opera cotações nem apólices; o admin altera taxas do catálogo e consulta a trilha de auditoria.
07
Sessão segura
- Dor
- Token de longa duração guardado no navegador pode ser roubado por XSS e não tem como ser revogado.
- Solução
- Access token JWT de 15 minutos só em memória e refresh token rotativo de 7 dias em cookie HttpOnly e SameSite=Strict, guardado no banco apenas como hash. Reutilizar um token já rotacionado revoga a família inteira, e o login bloqueia após 5 senhas erradas, mesmo com tentativas em paralelo.
08
Eventos que não se perdem
- Dor
- Gravar no banco e publicar na fila em passos separados perde o evento quando um dos dois falha, e a reentrega duplica e-mail ou triagem.
- Solução
- O evento vira uma linha do outbox no mesmo SaveChanges do agregado; a API publica logo após o commit e um relay agendado cobre as falhas. O consumidor registra a mensagem na mesma transação do efeito, então a reentrega não repete nada.
Impacto: RabbitMQ no local; SQS com DLQ e alarme em produção
09
Dashboard da carteira
- Dor
- Para saber quanto emitiu, quanto converte e como anda a sinistralidade, o corretor precisa juntar relatórios.
- Solução
- O dashboard mostra apólices ativas, prêmio emitido no mês e nos últimos 12 meses, conversão de cotações, sinistros em aberto, sinistralidade e carteira por produto, no escopo de quem entrou: a própria carteira ou a global. As leituras usam Dapper com SQL parametrizado, separadas da escrita em EF Core.
10
API com contrato sem drift
- Dor
- Integrar com uma API sem contrato atualizado é tentativa e erro, e o front-end quebra em silêncio quando o back-end muda.
- Solução
- As 32 operações em /api/v1 ficam documentadas em OpenAPI 3.1 no Scalar, com erros em ProblemDetails (RFC 9457). O CI regenera o contrato e falha se o commitado estiver desatualizado, e os tipos TypeScript do front-end saem do mesmo OpenAPI.
11
Produção serverless e observável
- Dor
- Servidor ligado o tempo todo para uma demonstração custa caro, e sem logs e traces correlacionados não dá para seguir uma requisição até o worker.
- Solução
- A API roda em AWS Lambda (.NET 10, arm64) atrás de um rewrite da Vercel, na mesma origem do front-end, com Aurora DSQL autenticado por IAM, SQS e EventBridge, tudo em Terraform com deploy por OIDC. Serilog grava logs JSON com correlation id, sem dados pessoais, e o OpenTelemetry leva o trace da requisição até o worker.
Impacto: Custo em produção perto de US$ 0 (free tier)























