Repository navigation
Primeiros Passos
Para quem é este artigo: para quem quer rodar o projeto pela primeira vez, mesmo sem experiência com .NET, Docker ou PostgreSQL.
O que você vai aprender: o que cada ferramenta faz, duas formas de subir a aplicação, como configurá-la e um roteiro para conversar com a API usando o terminal.
O PolicyDesk é uma API REST. Vale entender as duas palavras:
- API (Application Programming Interface) é um programa feito para ser usado por outros programas, não por pessoas. Não tem telas. Quem usa a API é, por exemplo, um site, um aplicativo de celular ou outro sistema.
-
REST é um estilo de API que usa o protocolo da web, o HTTP. Cada coisa do sistema tem um endereço (uma URL, como
/api/segurados), e você diz o que quer fazer com ela pelo método HTTP:GETpara ler,POSTpara criar ou executar uma ação,PUTpara atualizar,DELETEpara remover. Os dados vão e voltam em JSON, um formato de texto simples.
Para funcionar, a API precisa de um banco de dados, onde guarda segurados, apólices e sinistros. O PolicyDesk usa o PostgreSQL.
flowchart LR
C["Você<br/>(curl, navegador, Swagger)"] -- "HTTP + JSON" --> API["PolicyDesk.Api<br/>porta 8080"]
API -- "SQL" --> DB[("PostgreSQL<br/>porta 5432")]
| Ferramenta | O que é | Para que serve aqui | Obrigatória? |
|---|---|---|---|
| Docker | Roda programas dentro de contêineres: caixas isoladas que já vêm com tudo de que o programa precisa | Subir o PostgreSQL (e a API) sem instalar nada direto na sua máquina | Sim |
| Docker Compose | Parte do Docker que sobe vários contêineres de uma vez, descritos em um arquivo YAML | Subir API e banco com um comando | Vem com o Docker |
| .NET SDK 10 | O kit de desenvolvimento da plataforma .NET, da Microsoft: compilador C#, ferramentas de teste e de execução | Compilar, rodar fora do Docker e rodar os testes | Só para desenvolver |
dotnet-ef |
Ferramenta de linha de comando do Entity Framework Core | Criar e aplicar migrations (mudanças no banco) | Só para mexer no banco |
| Uma IDE | Editor com recursos de programação | Rider, Visual Studio ou VS Code com a extensão C# Dev Kit | Recomendada |
💡 Por que Docker? Sem ele, você teria que instalar o PostgreSQL, criar usuário, criar banco e configurar a porta, e cada pessoa da equipe faria isso de um jeito. Com o Docker, todo mundo roda exatamente o mesmo banco, na mesma versão, com um comando. E, quando você termina, apaga o contêiner sem deixar rastro.
Dois arquivos na raiz garantem que todo mundo use as mesmas versões das ferramentas:
-
global.jsondiz qual SDK do .NET usar (10.0.100ou mais novo dentro do .NET 10). Se você tiver o .NET 9 instalado, o comandodotnetvai avisar que falta o 10, em vez de compilar com a versão errada. -
.config/dotnet-tools.jsoné o manifesto de ferramentas locais. Ele declara odotnet-efna versão 10.0.15. Você não instala nada globalmente: basta rodardotnet tool restorena pasta do projeto.
Use esta opção se você só quer ver a API funcionando, sem abrir o código.
git clone https://github.com/Rodrigosdk/PolicyDesk.git
cd PolicyDesk
docker compose -f docker/compose.yml up --buildO que cada parte faz:
-
docker compose: chama o Compose. -
-f docker/compose.yml: diz qual arquivo usar. Os arquivos do Docker ficam na pastadocker/. -
up: sobe os serviços descritos no arquivo. -
--build: compila a imagem da API antes de subir, para pegar o código mais recente.
O arquivo descreve dois serviços (contêineres):
| Serviço | Imagem | Porta | O que faz |
|---|---|---|---|
db |
postgres:17-alpine |
5432 | O banco. Os dados ficam em um volume chamado policy-desk-data, que sobrevive quando o contêiner é recriado. Um health check (pg_isready) avisa quando o banco está pronto |
api |
Construída a partir do docker/Dockerfile
|
8080 | A API. Só sobe depois que o banco responde ao health check, para não tentar conectar em um banco que ainda está iniciando |
Quando aparecer no terminal algo como Now listening on: http://[::]:8080, abra:
- http://localhost:8080/swagger: o Swagger UI, uma página que lista todos os endpoints e deixa você testá-los clicando em "Try it out".
-
http://localhost:8080/health: deve mostrar
Healthy.
A API roda no ambiente
Developmentdentro do Compose. Nesse ambiente, o Swagger fica disponível e as migrations (os comandos que criam as tabelas) rodam sozinhas quando a API sobe. Em produção, as migrations não rodam ao subir, e o Swagger só aparece porque a variávelSwagger__Enabledvem ligada.
Para parar, aperte Ctrl+C. Para apagar os contêineres, use docker compose -f docker/compose.yml down. Os dados continuam no volume. Para apagar também os dados, acrescente -v.
Um segundo arquivo, docker/compose.dev.yml, complementa o primeiro com duas ferramentas úteis para estudar o sistema:
docker compose -f docker/compose.yml -f docker/compose.dev.yml up -d --buildQuando você passa dois -f, o Compose junta os arquivos: o segundo acrescenta serviços e configurações ao primeiro. O -d (detached) roda tudo em segundo plano e devolve o terminal.
| Serviço | Endereço | O que é |
|---|---|---|
dashboard (Aspire Dashboard) |
http://localhost:18888 | Mostra os logs, os traces (o caminho de cada requisição, inclusive o SQL executado) e as métricas da API. Veja Observabilidade |
pgadmin |
http://localhost:5050 | Interface web para olhar o banco: tabelas, dados, consultas. O servidor PolicyDesk (local) já aparece cadastrado; na primeira conexão, informe a senha policy-desk-local
|
O Compose usa o nome de projeto fixo policydesk, então os dois modos compartilham o mesmo volume de dados.
Use esta opção para desenvolver: você pode colocar breakpoints, alterar o código e reiniciar rápido. O banco continua no Docker.
# 1. Suba só o banco e as ferramentas, sem a API
docker compose -f docker/compose.yml -f docker/compose.dev.yml up -d db dashboard pgadmin
# 2. Informe a connection string (veja a explicação abaixo)
dotnet user-secrets set "ConnectionStrings:DbConnection" \
"Host=localhost;Port=5432;Database=PolicyDesk;Username=admin;Password=policy-desk-local" \
--project src/Backend/PolicyDesk.Api
# 3. Rode a API
dotnet run --project src/Backend/PolicyDesk.ApiA API sobe em http://localhost:5045 (com o Swagger em /swagger).
O que é uma connection string? É o "endereço completo" do banco: onde ele está (Host, Port), qual banco usar (Database) e com que usuário e senha entrar. A API precisa dela para se conectar.
O que são User Secrets? Um lugar fora da pasta do projeto, no seu usuário do sistema operacional, onde o .NET guarda configurações sensíveis em desenvolvimento. Assim, a senha não vai parar no Git por acidente. Em produção, o mesmo valor vem de uma variável de ambiente.
O arquivo Properties/launchSettings.json já define duas coisas para o dotnet run: o ambiente Development e o endereço do Aspire Dashboard (OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317). Por isso a telemetria aparece no dashboard mesmo com a API fora do Docker.
O .NET lê configurações de várias fontes, em camadas. Uma fonte mais abaixo na lista sobrescreve as de cima:
-
appsettings.json: valores padrão, versionados no Git. -
appsettings.Development.json: ajustes para desenvolvimento (só vale no ambienteDevelopment). - User Secrets: só em desenvolvimento.
- Variáveis de ambiente: como produção e o Docker passam configurações.
As chaves usam : para indicar hierarquia (ConnectionStrings:DbConnection). Em variáveis de ambiente, o : vira __ (dois sublinhados), porque nem todo sistema aceita : no nome: ConnectionStrings__DbConnection.
| Chave | Obrigatória | O que configura |
|---|---|---|
ConnectionStrings:DbConnection |
Sim | Onde está o PostgreSQL e como entrar nele |
Business:TimeZone |
Sim (já vem no appsettings.json) |
O fuso usado para decidir que dia é hoje. Padrão: America/Sao_Paulo
|
ASPNETCORE_ENVIRONMENT |
Não |
Development liga o Swagger e os logs legíveis (em outros ambientes, o Swagger depende de Swagger__Enabled=true). Fora de Production, as migrations rodam ao subir |
OTEL_EXPORTER_OTLP_ENDPOINT |
Não | Para onde enviar logs, traces e métricas. Sem ela, nada é enviado |
POSTGRES_PASSWORD |
Não | A senha do banco no Docker Compose. Padrão: policy-desk-local
|
A connection string e o fuso horário são validados no momento em que a API sobe. Se a connection string faltar, ou se o fuso não existir (por exemplo, America/Inexistente), a API não sobe e mostra uma mensagem dizendo o que configurar.
Esse comportamento se chama fail fast (falhar rápido). A alternativa seria a API subir normalmente e quebrar só na primeira requisição que usasse o banco, talvez horas depois, com um erro confuso. É bem melhor descobrir o problema na hora do deploy, com uma mensagem clara. O artigo Design Patterns › Options Pattern mostra como isso é feito.
Agora vamos percorrer o ciclo inteiro do negócio (cadastrar, segurar, abrir sinistro e pagar) usando o curl, um programa de linha de comando que faz requisições HTTP. Se preferir, faça o mesmo pelo Swagger.
API=http://localhost:8080/api1. Cadastre uma segurada.
curl -i -X POST $API/segurados -H "Content-Type: application/json" -d '{
"nome": "Maria Silva",
"cpf": "529.982.247-25",
"dataNascimento": "1990-05-10",
"email": "maria@exemplo.com",
"telefone": "(11) 98765-4321"
}'-
-imostra os cabeçalhos da resposta, além do corpo. -
-X POSTescolhe o método. -
-Hadiciona um cabeçalho: aqui, dizemos que o corpo é JSON. -
-dé o corpo da requisição.
A resposta deve ser HTTP/1.1 201 Created, com o corpo { "id": "..." } e um cabeçalho Location apontando para o novo recurso. Guarde o id.
2. Veja como ela foi gravada.
curl "$API/segurados?pagina=1&tamanhoPagina=10"Repare em três detalhes: o CPF voltou só com dígitos (52998224725), o e-mail está em minúsculas, e o telefone está no formato internacional (+5511987654321). O sistema normaliza os dados na entrada. Repare também que a lista vem dentro de um objeto com itens, pagina e totalItens: as listagens são paginadas.
3. Emita uma apólice para ela.
curl -X POST $API/apolices -H "Content-Type: application/json" -d '{
"seguradoId": "<ID_DA_SEGURADA>",
"descricao": "Seguro auto",
"valorCobertura": 50000,
"valorPremio": 2400,
"inicioVigencia": "2026-01-01",
"fimVigencia": "2026-12-31"
}'4. Abra um sinistro na apólice.
curl -X POST $API/apolices/<ID_DA_APOLICE>/sinistros -H "Content-Type: application/json" -d '{
"descricao": "Colisão traseira",
"valor": 8000,
"dataOcorrencia": "2026-10-15"
}'A data de ocorrência precisa estar dentro da vigência e não pode ser futura.
5. Leve o sinistro até o pagamento.
curl -X POST $API/sinistros/<ID_DO_SINISTRO>/analise
curl -X POST $API/sinistros/<ID_DO_SINISTRO>/aprovacao
curl -X POST $API/sinistros/<ID_DO_SINISTRO>/pagamentoCada comando responde 204 No Content: deu certo, e não há nada para devolver.
6. Confira o resultado.
curl $API/sinistros/<ID_DO_SINISTRO>O status deve ser Pago, com dataAprovacao e dataPagamento preenchidas.
Aprender como o sistema recusa coisas é tão importante quanto vê-lo funcionar:
| Tente | O que deve acontecer |
|---|---|
| Pagar um sinistro recém-aberto |
400: só sinistros aprovados podem ser pagos |
| Abrir sinistros que, somados, passem dos R$ 50.000 |
400: o valor excede o saldo da cobertura |
Enviar "dataOcorrencia": "2026-10-15T00:00:00"
|
400: datas não aceitam horário |
Inativar (DELETE /api/segurados/{id}) a Maria com a apólice em vigor |
400: ela tem apólice ativa |
Repetir qualquer erro com -H "Accept-Language: en"
|
A mesma mensagem, em inglês |
curl -i $API/segurados/00000000-0000-0000-0000-000000000000 |
404, com o corpo de erro padrão |
Todas as respostas de erro têm o mesmo formato, explicado em Tratamento de Erros. Todas trazem o cabeçalho X-Trace-Id: copie esse valor e procure no Aspire Dashboard para ver tudo o que aconteceu naquela requisição.
# Restaurar as ferramentas locais (dotnet-ef)
dotnet tool restore
# Compilar. Qualquer aviso do compilador é tratado como erro
dotnet build
# Rodar todos os testes (o Docker precisa estar rodando)
dotnet test
# Rodar só os testes rápidos, que não precisam de Docker
dotnet test tests/src/PolicyDesk.Domain.Tests
dotnet test tests/src/PolicyDesk.Application.Tests
# Rodar só os testes cujo nome contém um texto
dotnet test --filter "FullyQualifiedName~ClaimWorkflow"
# Medir a cobertura de código
dotnet test --collect:"XPlat Code Coverage"Uma migration é um arquivo de código que descreve uma mudança na estrutura do banco (criar uma tabela, adicionar uma coluna) de um jeito versionado, como um commit para o banco. O Entity Framework compara as classes do código com a última migration e gera a próxima.
# Criar uma migration nova depois de mudar uma entidade ou um mapeamento
dotnet ef migrations add NomeDaMudanca \
--project src/Backend/PolicyDesk.Infrastructure \
--output-dir DataAccess/Migrations
# Ver o SQL que seria executado, sem executar nada
dotnet ef migrations script --idempotent \
--project src/Backend/PolicyDesk.Infrastructure \
--output migrations.sql
# Gerar o executável de migrations usado no deploy
dotnet ef migrations bundle --self-contained -r linux-x64 \
--project src/Backend/PolicyDesk.Infrastructure \
--startup-project src/Backend/PolicyDesk.Infrastructure
# Aplicar as migrations em um banco específico
ConnectionStrings__DbConnection="Host=...;..." \
dotnet ef database update --project src/Backend/PolicyDesk.InfrastructureOs dois primeiros comandos não precisam de banco rodando. O artigo Persistência e Banco de Dados explica o porquê, e como as migrations chegam à produção.
| Sintoma | Causa provável | O que fazer |
|---|---|---|
port is already allocated ao subir o Compose |
Outro programa já usa a porta 5432 ou 8080 (talvez um PostgreSQL instalado na máquina) | Pare o outro programa ou mude a porta no compose.yml
|
A API sai logo depois de subir, falando de ConnectionStrings:DbConnection
|
A connection string não foi configurada | Refaça o passo 2 da Opção 2 |
| Os testes falham com erro de Docker | O Docker não está rodando | Inicie o Docker e rode de novo |
A compatible .NET SDK was not found |
Falta o .NET 10 | Instale o .NET SDK 10 |
400 em toda data enviada |
A data foi enviada com horário | Use só "AAAA-MM-DD"
|
- O PolicyDesk é uma API REST que guarda dados em um PostgreSQL.
- O Docker sobe tudo com um comando; o
compose.dev.ymlacrescenta o dashboard de telemetria e o pgAdmin. - Configurações vêm em camadas, e as obrigatórias são validadas na subida (fail fast).
- O sistema normaliza o que recebe (CPF, e-mail, telefone) e recusa o que quebra as regras, sempre com o mesmo formato de erro.
- Para entender como o código está organizado: Arquitetura.
- Para conhecer todos os endpoints: Referência da API.
- Para publicar na nuvem: CI/CD e Deploy.
PolicyDesk · Distribuído sob a licença MIT · Repositório
Comece aqui
Como o sistema é feito
A API
Engenharia
Prática
Consulta