ADR-006 — Tenant global query filter + stamping interceptor
Data: 2026-06-19
Status: Aceito
Contexto: DevPack 10.5.0
Pareado com: ADR-009 do template ITLab.Template.Next (decisão primária — canon claim-based + Tenant aggregate)
Base de referência: padrão de query filter por combinação de interfaces portado de ITLab.WorkGuardian
Contexto
A maquinaria de tenancy do DevPack já existia na 10.4.0 — IMultiTenant (int? TenantId), ICurrentUser.TenantId, UserInfo.TenantId, EntityHelper.TrySetTenantId e o pipeline de resolução (ITenantResolver + contributors). Faltava o lado de persistência: o applicator que aplica o global query filter de tenant (leitura) e o interceptor que stampa/guarda o tenant na escrita. Sem isso, qualquer consumidor (incluindo o template) teria que reescrever no seu DbContext a mesma reflexão sobre o model — um helper universal (G-01).
Decisão
Adicionar três peças universais em Infrastructure/EfCore/, e ler o claim de tenant no bridge de identidade.
1. MultiTenantModelBuilderExtensions.ApplyMultiTenantQueryFilters(this ModelBuilder, IMultiTenantDbContext)
Varre modelBuilder.Model.GetEntityTypes() e, por entidade, aplica uma única lambda de query filter combinando tenant + soft-delete, despachando por reflexão via um switch de 4 vias (isMultiTenant, isSoftDeletable):
IMultiTenant | ISoftDeletable | Filtro aplicado |
|---|---|---|
| ✓ | ✓ | e.TenantId == ctx.CurrentTenantId && !e.IsDeleted |
| ✓ | ✗ | e.TenantId == ctx.CurrentTenantId |