Pular para o conteúdo principal
Versão: main (dev) 🚧

ITLab.Template.DevPack.Abstractions

Defines foundational contracts consumed by infrastructure and application layers.

Componentes

TipoNomeResponsabilidade
InterfaceIAppOptionsMarks bindable options and declares the configuration section path
InterfaceICacheServiceCache contract for get/create, set, try-get, remove and diagnostics
InterfaceIDateTimeProviderTime normalization contract for UTC/system/user-local values
Sealed ClassUtcDateTimeProviderDefault IDateTimeProvider — every value resolves to UTC; singleton
Sealed ClassLocalDateTimeProviderIDateTimeProvider that converts to ICurrentUser.LocalTimeZone (IANA), fallback UTC; scoped
Static ClassDateTimeProviderServiceCollectionExtensionsDI helpers AddDevPackUtcDateTimeProvider() / AddDevPackLocalDateTimeProvider()
InterfaceIServiceProviderAccessorProvides controlled access to the active service provider
InterfaceISecretProtectorSymmetric encrypt/decrypt of secret strings for storage at rest
Sealed ClassDataProtectionSecretProtectorDefault ISecretProtector over ASP.NET Core Data Protection
Static ClassSecretProtectorServiceCollectionExtensionsDI helper AddDevPackSecretProtector()

Como usar

// App options contract used by strongly typed configuration.
public sealed class MyFeatureOptions : IAppOptions
{
public static string ConfigSectionPath => "MyFeature";
public bool Enabled { get; init; }
}

// Cache usage with safe fallback factory.
var customer = await cacheService.GetOrCreateAsync(
cacheKey: $"customer:{id}",
factory: () => repository.LoadCustomerAsync(id),
absoluteExpiration: TimeSpan.FromMinutes(10));

DateTimeProvider — escolha por host

HostImplementaçãoLifetimePor quê
Web API com user contextLocalDateTimeProviderScopedUserLocal* resolve via ICurrentUser.LocalTimeZone
Worker / batch / consoleUtcDateTimeProviderSingletonSem user context — degrade para UTC, sem custo de scope
Fallback / testesUtcDateTimeProviderSingletonDeterminístico, sem dependências scoped

Registro

// Pré-requisito para ambos:
services.AddSingleton(TimeProvider.System);

// Web API:
services.AddDevPackLocalDateTimeProvider(); // Scoped
// requer ICurrentUser registrado (do DevPack Identity).

// Worker:
services.AddDevPackUtcDateTimeProvider(); // Singleton

Comportamento de timezone

LocalDateTimeProvider resolve ICurrentUser.LocalTimeZone (IANA) via TimeZoneInfo.TryFindSystemTimeZoneById. Em .NET 8+ no Windows, identificadores IANA são aceitos diretamente — o runtime aplica mapeamento IANA↔Windows internamente. Não é necessário tratamento por plataforma.

Fallback silencioso para UTC quando LocalTimeZone é null, vazio ou desconhecido ao runtime — LocalDateTimeProvider nunca lança exceção.

// Cenário: usuário em São Paulo (IANA "America/Sao_Paulo"), UTC = 2026-05-01 15:00.
// provider.UserLocalTimeOffset = 2026-05-01 12:00 -03:00
// provider.UserTimeZone = TimeZoneInfo for America/Sao_Paulo
// provider.UserLocalTimeOffsetSpan = -03:00:00

// Cenário: usuário sem LocalTimeZone definido (LocalTimeZone == null).
// provider.UserLocalTimeOffset = 2026-05-01 15:00 +00:00 (UTC)
// provider.UserTimeZone = TimeZoneInfo.Utc
// provider.UserLocalTimeOffsetSpan = TimeSpan.Zero

Secret protection

ISecretProtector encrypts secret strings (client secrets, bind passwords) for storage at rest; DataProtectionSecretProtector implements it over ASP.NET Core Data Protection. Register with services.AddDevPackSecretProtector() and consume it from a per-tenant settings store (see ../Identity/Settings/README.md).

services.AddDevPackSecretProtector(); // adds Data Protection + ISecretProtector

var token = protector.Protect(clientSecret); // store this
var clientSecret = protector.Unprotect(token); // read back

Production: configure a persistent Data Protection key ring (Azure Blob/Key Vault, file share, …). The in-memory default loses keys on restart, making previously protected secrets undecryptable.

O que não fazer

  • Do not use IServiceProviderAccessor as a generic service locator in domain code.
  • Do not log the plaintext or the protected token produced by ISecretProtector.
  • Do not rely on the in-memory Data Protection key ring in production — protected secrets won't survive a restart.
  • Do not store mutable runtime state in IAppOptions implementations.
  • Do not rely on cache as the source of truth for business consistency.
  • Do not register LocalDateTimeProvider as Singleton — depends on scoped ICurrentUser.
  • Do not throw or log error when timezone is invalid — LocalDateTimeProvider falls back to UTC by design.

Extensão pelo produto

  • Products can implement custom IDateTimeProvider (e.g. multi-tenant timezone strategies) and replace the registration.
  • Products can replace ICacheService with distributed cache implementations while keeping contract behavior.