Convenções claras
Padrões compreensíveis e bons valores padrão para reduzir decisões repetidas entre APIs.
Psalms
Ecossistema open source em evolução
Uma coleção modular de bibliotecas para .NET que elimina código repetitivo, estabelece convenções seguras e acelera o desenvolvimento de APIs e microsserviços.
Visão do ecossistema
O Psalms encapsula problemas recorrentes em pacotes independentes e extensíveis. Cada biblioteca pode ser adotada isoladamente, sem obrigar a aplicação a usar o restante do ecossistema.
Padrões compreensíveis e bons valores padrão para reduzir decisões repetidas entre APIs.
Abstrações explícitas e pontos de substituição quando cache, persistência ou templates precisarem evoluir.
Email, autenticação e dados resolvem responsabilidades separadas e podem ser combinados apenas quando fizer sentido.
“Psalms exists to bring grace to your code. No magic, no unnecessary complexity — just best practices distilled into powerful libraries.”
Pacotes publicados
Selecione um pacote para explorar o problema resolvido, as decisões arquiteturais e exemplos de integração.
Email workflows e confirmação de comandos
Uma biblioteca para operações que só devem ser executadas depois que o usuário confirma a ação por um link enviado por email.
Dor recorrente
Cadastro, reset de senha, alteração de email e aprovações exigem token, expiração, cache, template, envio, desserialização e invalidação após uso.
Decisão arquitetural
O IRequest original fica armazenado temporariamente e retorna ao pipeline do MediatR somente após a confirmação.
Arquitetura
Usuário solicita uma operação sensível.
A API cria o comando original.
SendConfirmationEmailCommand
Um token único é gerado.
JSON + IDistributedCache
O template é resolvido pelo tipo concreto do comando.
MailKit e MimeKit enviam o link.
O usuário acessa o link.
O frontend envia o token à API.
ConfirmEmailCommand
O comando é recuperado e desserializado.
O MediatR executa o comando restaurado.
A chave é removida e não pode ser reutilizada.
Template resolver
Cada comando pode implementar IEmailTemplate<TCommand>. O resolver identifica o tipo concreto e procura a implementação correspondente no container de Dependency Injection.
public class RegisterUserEmailTemplate
: IEmailTemplate<RegisterUserCommand>
{
public string TemplatePath => "Templates";
public string EmailType => "confirm-email";
public string Subject => "Confirm your account";
public string FrontEndPage => "confirm-email";
}
services.AddScoped<
IEmailTemplate<RegisterUserCommand>,
RegisterUserEmailTemplate>();
await mediator.Send(
new SendConfirmationEmailCommand(command, email)
);
await mediator.Send(
new ConfirmEmailCommand(token)
);
await mediator.Send(
new SendEmailCommand(
to: "user@email.com",
subject: "Welcome",
htmlPath: "Templates",
emailType: "welcome"
)
);
Tokens
email-confirmation:{guid}IDistributedCacheTemplates HTML
Templates/welcome.htmlO gerador padrão lê arquivos do disco. IEmailHtmlGenerator pode ser substituído por banco de dados, cloud storage, embedded resources ou template engine; essas são extensões possíveis, não integrações incluídas.
Começar
dotnet add package Psalms.AspNetCore.EmailSenderbuilder.Services.AddPsalmsEmailSender();Autenticação, access tokens e refresh tokens
Uma biblioteca leve para emissão de access tokens e gestão de refresh tokens com estratégias substituíveis de persistência.
Nota: o README usa Psalms.AspNetCore.Jwt como nome de apresentação; o ID publicado no NuGet inclui Auth.
Dor recorrente
Issuer, audience, assinatura, validade, geração segura, hash, persistência e rotação de refresh tokens precisam funcionar como um único fluxo.
Decisão arquitetural
IPsalmsRefreshTokenRepository separa o fluxo central da tecnologia usada para guardar refresh tokens.
Componentes
PsalmsJwtTokenServiceGeração de tokens, validação e rotação.
IPsalmsRefreshTokenRepositoryContrato de persistência.
DistributedCacheRepositoryImplementação sobre IDistributedCache.
EFRefreshTokenRepositoryImplementação com Entity Framework Core.
Fluxo 01
Credenciais chegam à aplicação.
A identidade é validada.
Claims → IPsalmsJwtTokenService
O access token é assinado.
Um refresh token aleatório de 32 bytes é gerado.
O hash é persistido.
O cliente recebe o par.
Fluxo 02
O cliente envia access e refresh tokens.
Token e expiração são validados.
O valor é comparado com o hash.
O fluxo solicita a exclusão do token anterior.
Um novo access token é criado.
Um novo refresh token é persistido.
O novo par retorna ao cliente.
Distributed cache
Estratégia para processos distribuídos que compartilham uma implementação de IDistributedCache.
Entity Framework
Usa IPsalmsRefreshTokenEFContext para salvar e remover tokens em banco.
Repositório próprio
A aplicação implementa IPsalmsRefreshTokenRepository sem modificar o núcleo.
Mecanismos de segurança
RandomNumberGeneratorPasswordHasher do ASP.NET Core Identity{
"JWT": {
"Key": "configure-via-secret-manager",
"Issuer": "your-app",
"Audience": "your-app-users",
"Expires": "1"
}
}Exemplo ilustrativo: segredos reais devem vir de secret managers, variáveis de ambiente ou mecanismo equivalente — nunca do repositório.
builder.Services.AddPsalmsJwtAuthentication(
builder.Configuration
);public class AuthService
{
private readonly IPsalmsJwtTokenService _jwt;
public AuthService(IPsalmsJwtTokenService jwt)
{
_jwt = jwt;
}
public async Task<AuthResponse> Authenticate(
IEnumerable<Claim> claims)
{
return await _jwt.GetAuthResponseAsync(claims);
}
}Começar
dotnet add package Psalms.AspNetCore.Auth.JwtPersistência, Repository e Unit of Work
A implementação Entity Framework Core do projeto Psalms.DataManagement, criada para aplicações que optam pelos padrões Repository e Unit of Work.
Dor recorrente
CRUD, predicados, coleções relacionadas, SaveChanges e registro no container costumam reaparecer com contratos diferentes.
Decisão arquitetural
O repositório concentra operações recorrentes; a Unit of Work coordena o contexto e confirma as mudanças.
Arquitetura
IPsalmsUnitOfWork<TContext>Expõe Repository, executa SaveChangesAsync e coordena o descarte do contexto.
IPsalmsEfCoreRepositoryCentraliza consultas e alterações genéricas para diferentes entidades.
DbContextMantém tracking e conversa com o provider configurado.
API confirmada
CreateAsync<T>(T entity)DeleteAsync<T>(int id)GetByIdAsync<T>(int id)GetByAsync<T>(predicate)ExistsAsync<T>(predicate)GetAllAsync<T>()GetCollectionFromEntityAsync<...>(...)RepositorySaveChangesAsync()DisposeAsync()A classe concreta PsalmsEfCoreRepository também contém UpdateAsync<T>, mas a versão 1.0.0 não expõe esse método em IPsalmsEfCoreRepository; por isso ele não aparece como parte do contrato principal acima.
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("Default")));
services.AddScoped<
IPsalmsUnitOfWork<AppDbContext>,
PsalmsUnitOfWork<AppDbContext>>();public class ProductService
{
private readonly IPsalmsUnitOfWork<AppDbContext> _uow;
public ProductService(
IPsalmsUnitOfWork<AppDbContext> uow)
{
_uow = uow;
}
public async Task AddProductAsync(Product product)
{
await _uow.Repository.CreateAsync(product);
await _uow.SaveChangesAsync();
}
public async Task<Product?> GetProductAsync(int id)
{
return await _uow.Repository
.GetByIdAsync<Product>(id);
}
}services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("TestDb"));Útil para testes sem banco externo, considerando as diferenças comportamentais do provider InMemory em relação a um banco relacional real.
Começar
dotnet add package Psalms.EFCore.DataManagementArquitetura integrada
Um cenário possível para uma API ASP.NET Core. A integração é opcional: cada pacote continua independente e pode ser adotado sozinho.
Autentica o usuário e gerencia access e refresh tokens.
Armazena o comando sensível e envia a confirmação.
Encaminha o comando restaurado ao handler.
Repository e Unit of Work persistem a alteração.
Stack
Evolução contínua
O Psalms já possui pacotes públicos e código aberto. Novas melhorias podem entrar sem transformar cada biblioteca em uma dependência obrigatória das demais.