A borda HTTP é o host. Código novo: ASP.NET Core 10 / .NET 10. Linguagem: csharp. Persistência: entity-framework. Contratos: api-design. Realtime: signalr.
Preserve Minimal APIs ou controllers — não migre o estilo numa feature.
Stack e escopo
| Peça | Papel |
|---|---|
| WebApplication | Host, Kestrel, pipeline |
| Minimal APIs / MVC | Endpoints |
| DI | IServiceCollection |
| Auth | JWT bearer, cookies, policies |
| ProblemDetails | Erros HTTP estáveis |
Organização
src/MyApp.Api/
Program.cs # wiring fino
Endpoints/ # ou Controllers/
Filters/
Auth/
src/MyApp.Application/
src/MyApp.Infrastructure/
Program.cssó compose: config, services, pipeline, map.- Handlers magros → application services.
- Groups (
MapGroup) por versão/recurso (/api/v1/orders).
Regras inegociáveis
- Validar input na borda (
DataAnnotations, FluentValidation ouIValidatableObject). - Authn ≠ Authz:
[Authorize(Policy = ...)]/RequireAuthorization+ checagem de ownership no serviço. - Não exponha entidades EF no JSON; DTOs / contracts.
- Erros:
ProblemDetails(type,title,status,detailseguro) + status corretos. - Secrets via env / user secrets / KeyVault — nunca
appsettingscommitado com senha. - Graceful shutdown: Kestrel drena;
IHostApplicationLifetimepara workers. CancellationTokennos handlers (MapGet(..., async (..., ct) =>).
Minimal APIs
var orders = app.MapGroup("/api/v1/orders").RequireAuthorization();
orders.MapGet("/{id:guid}", async (Guid id, IOrderService svc, CancellationToken ct) =>
{
var order = await svc.GetAsync(id, ct);
return order is null ? Results.NotFound() : Results.Ok(order);
});
TypedResultspara OpenAPI honesto.- Filters de endpoint para cross-cutting (correlation id), não regra de negócio.
- OpenAPI/Swagger gerado; schemas alinhados aos DTOs.
Controllers (se o projeto já usa)
[ApiController], bind explícito,ActionResult<T>.- Um controller por recurso; sem “God ApiController”.
FromBody/FromQuerytipados; semJObject.
Pipeline
Ordem típica: exception handler → HTTPS → CORS (se front separado) → authn → authz → endpoints.
- Exception handler global → ProblemDetails; sem stack em produção.
- Rate limiting em auth e rotas caras (
AddRateLimiter). - CORS explícito; sem
AllowAnyOrigin+ credentials. - Forwarded headers só atrás de proxy conhecido.
Auth
- JWT: validar issuer/audience/lifetime/signing. Clock skew consciente.
- Cookies:
HttpOnly,Secure,SameSitealinhado ao front. - Policies por permissão (
orders:write), não só role solta. - Authz profunda:
authentication-authorization.
Anti-padrões
- Lógica de negócio em
Program.cs Results.Okcom 404 no bodyDbContextno endpoint sem UoW/scope claro.GetAwaiter().GetResult()no request- Controllers + Minimal duplicando o mesmo recurso
Integração com outras skills
- Linguagem:
csharp - i18n:
i18n-backend - EF:
entity-framework - Testes:
csharp-testing - SignalR:
signalr - gRPC:
grpc - Go-live:
production-readiness
Critérios de conclusão
- Endpoints tipados, validados, autorizados
- ProblemDetails + status corretos
- DTOs sem vazamento de entidades
- CT + shutdown conscientes
- Config por env; OpenAPI alinhado