Skip to content

Pragmatic.Abstractions -- Complete Interface Catalog

This document lists every public type in Pragmatic.Abstractions with its full member signatures, organized by domain. For a higher-level overview, see the README.


Base contract for all error types in the Result pattern. Supports HTTP status code mapping and RFC 7807 Problem Details.

public interface IError
{
string Code { get; } // Semantic error code, UPPER_SNAKE_CASE (e.g., "NOT_FOUND")
int StatusCode { get; } // HTTP status code
string Title => string.Empty; // Problem Details title (default: empty)
string? Description => null; // Additional context (default: null)
}

Usage: Extend the Error abstract record in Pragmatic.Result for class-based errors. Implement IError directly only for struct-based errors (e.g., ValidationError). For localized errors, implement ILocalizedError which adds LocalizationKey.


Marker interface for all entities. No members.

public interface IEntity;

IEntity<TId> (Pragmatic.Persistence.Entity)

Section titled “IEntity<TId> (Pragmatic.Persistence.Entity)”

Entity with a typed identifier.

public interface IEntity<TId> : IEntity where TId : notnull
{
TId PersistenceId { get; } // Unique persistence identifier
}

Audit tracking for creation and last update.

public interface IAuditable
{
DateTimeOffset CreatedAt { get; set; }
string? CreatedBy { get; set; }
DateTimeOffset? UpdatedAt { get; set; }
string? UpdatedBy { get; set; }
}

The CreatedBy/UpdatedBy fields are populated automatically by the persistence layer using ICurrentUser.IdOrNull().

ISoftDelete (Pragmatic.Persistence.Entity)

Section titled “ISoftDelete (Pragmatic.Persistence.Entity)”

Soft-delete support. Entities are not physically removed; instead IsDeleted is set to true.

public interface ISoftDelete
{
bool IsDeleted { get; set; }
DateTimeOffset? DeletedAt { get; set; }
string? DeletedBy { get; set; }
}

The SG generates a SoftDeleteFilter query filter that automatically excludes soft-deleted entities from queries.

IChangeTracking (Pragmatic.Persistence.Entity)

Section titled “IChangeTracking (Pragmatic.Persistence.Entity)”

Property-level change tracking, implemented automatically by the source generator on entities with generated Set{Property} methods.

public interface IChangeTracking
{
IReadOnlySet<string> ModifiedProperties { get; } // Modified scalar properties
IReadOnlySet<string> CollectionsModified { get; } // Modified collection navigations
void ResetModifiedProperties(); // Clear tracking state
bool IsNew { get; set; } // True for unsaved entities (all props "modified")
}

Enables: selective validation (only modified properties), audit trail, optimized persistence (only changed columns).

ITemporalRelation (Pragmatic.Persistence.Entity)

Section titled “ITemporalRelation (Pragmatic.Persistence.Entity)”

Time-bounded relationship (e.g., user-role assignment valid from Jan 1 to Jun 30).

public interface ITemporalRelation
{
DateTimeOffset ValidFrom { get; set; }
DateTimeOffset? ValidTo { get; set; } // Null means currently active (no end date)
}

Entities implementing this interface get automatic Active() and ActiveAt(date) query extensions.

IEntityFactory<TEntity> (Pragmatic.Persistence.Entity)

Section titled “IEntityFactory<TEntity> (Pragmatic.Persistence.Entity)”

Factory for creating entity instances during mutations.

public interface IEntityFactory<out TEntity> where TEntity : class
{
TEntity Create();
}

When registered in DI, the MutationInvoker uses this factory for MutationMode.Create operations. If no factory is registered, it falls back to new TEntity().


IReadRepository<TEntity, TId> (Pragmatic.Persistence.Repository)

Section titled “IReadRepository<TEntity, TId> (Pragmatic.Persistence.Repository)”

Read-only repository. Uses Specification<T> from Pragmatic.Specification for composable query predicates.

public interface IReadRepository<TEntity, TId>
where TEntity : class, IEntity<TId>
where TId : notnull
{
Task<TEntity?> GetByIdAsync(TId id, CancellationToken ct = default);
Task<List<TEntity>> FindAsync(Specification<TEntity> spec, CancellationToken ct = default);
Task<int> CountAsync(Specification<TEntity> spec, CancellationToken ct = default);
Task<bool> ExistsAsync(Specification<TEntity> spec, CancellationToken ct = default);
Task<TEntity?> FirstOrDefaultAsync(Specification<TEntity> spec, CancellationToken ct = default);
IQueryable<TEntity> Query();
}

IRepository<TEntity, TId> (Pragmatic.Persistence.Repository)

Section titled “IRepository<TEntity, TId> (Pragmatic.Persistence.Repository)”

Full CRUD repository, extending IReadRepository.

public interface IRepository<TEntity, TId> : IReadRepository<TEntity, TId>
where TEntity : class, IEntity<TId>
where TId : notnull
{
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
void Update(TEntity entity);
}

IUnitOfWork (Pragmatic.Persistence.Repository)

Section titled “IUnitOfWork (Pragmatic.Persistence.Repository)”

Unit of Work pattern for transactional persistence.

public interface IUnitOfWork : IDisposable, IAsyncDisposable
{
Task<int> SaveChangesAsync(CancellationToken ct = default);
void Add(object entity) { } // Default no-op; used by preset providers
Task<ITransaction> BeginTransactionAsync(CancellationToken ct = default);
}

ITransaction (Pragmatic.Persistence.Repository)

Section titled “ITransaction (Pragmatic.Persistence.Repository)”

Database transaction handle.

public interface ITransaction : IDisposable, IAsyncDisposable
{
Guid TransactionId { get; }
Task CommitAsync(CancellationToken ct = default);
Task RollbackAsync(CancellationToken ct = default);
}

The currently authenticated user in the request scope. Core contract consumed by persistence (auditing), actions (authorization), and endpoints (permission enforcement).

public interface ICurrentUser
{
string Id { get; } // Empty for anonymous users
string? DisplayName { get; } // Null for anonymous
bool IsAuthenticated { get; }
PrincipalKind Kind { get; } // Anonymous, User, Service, System
string? TenantId { get; } // Null when not applicable
IReadOnlyDictionary<string, IReadOnlyList<string>> Claims { get; } // Multi-valued claims
string? ImpersonatedBy { get; } // Impersonator user ID, if any
IUserAuthorization Authorization { get; } // Roles, permissions, groups, scopes
IAuthenticationContext Authentication { get; } // Scheme, issuer, MFA, expiry
}

IAuthenticationContext (Pragmatic.Identity)

Section titled “IAuthenticationContext (Pragmatic.Identity)”

Authentication metadata. Accessed via ICurrentUser.Authentication.

public interface IAuthenticationContext
{
string? Scheme { get; } // e.g., "Bearer", "Cookie"
string? Protocol { get; } // e.g., "oidc", "saml2", "apikey"
string? Issuer { get; } // e.g., "https://login.example.com"
string? Subject { get; } // Subject identifier from IdP
bool IsMfaAuthenticated { get; }
DateTimeOffset? AuthenticatedAt { get; }
DateTimeOffset? ExpiresAt { get; }
string? ExternalIdentityKey { get; } // "{issuer}|{subject}" format
}

User profile data, generated from [PragmaticUser] entity properties.

public interface IUserProfile
{
string? PreferredCulture { get; } // e.g., "it-IT", "en-US"
string? TimeZone { get; } // IANA, e.g., "Europe/Rome"
IReadOnlyDictionary<string, string?> Properties { get; } // Additional profile properties
}
public enum PrincipalKind
{
Anonymous, // No authenticated identity
User, // Human user via identity provider
Service, // Service-to-service (API key, client credentials)
System // Background jobs, seed, migrations
}

Singleton ICurrentUser for unauthenticated requests. Id is empty string, IsAuthenticated is false, Authorization returns NullUserAuthorization.Instance, Authentication returns NullAuthenticationContext.Instance.

public static readonly AnonymousUser Instance;

NullAuthenticationContext (Pragmatic.Identity)

Section titled “NullAuthenticationContext (Pragmatic.Identity)”

Singleton IAuthenticationContext for anonymous/system contexts. All properties return null or false.

public static readonly NullAuthenticationContext Instance;

CurrentUserExtensions (Pragmatic.Identity)

Section titled “CurrentUserExtensions (Pragmatic.Identity)”
public static class CurrentUserExtensions
{
static string? IdOrNull(this ICurrentUser user);
static string DisplayNameOrId(this ICurrentUser user);
static string? GetClaim(this ICurrentUser user, string type);
static IReadOnlyList<string> GetClaims(this ICurrentUser user, string type);
static string? GetClaimValue(this ICurrentUser user, string claimType); // Alias for GetClaim
static IReadOnlyList<string> GetClaimValues(this ICurrentUser user, string claimType); // Alias for GetClaims
}

Marks the application’s user entity. The SG generates a profile adapter (IUserProfile) and a user resolver service.

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class PragmaticUserAttribute : Attribute
{
public string MatchClaim { get; set; } = "sub"; // Claim type for user matching
public string? MatchProperty { get; set; } // Entity property for matching (default: ExternalIdentityKey)
}

Marks a property on a [PragmaticUser] entity for IUserProfile generation. Well-known names (PreferredCulture, TimeZone) map to dedicated accessors; others go into Properties dictionary.

[AttributeUsage(AttributeTargets.Property)]
public sealed class ProfilePropertyAttribute : Attribute;

IUserAuthorization (Pragmatic.Authorization)

Section titled “IUserAuthorization (Pragmatic.Authorization)”

Authorization context for the current user. Accessed via ICurrentUser.Authorization.

public interface IUserAuthorization
{
IReadOnlyCollection<string> Roles { get; }
IReadOnlySet<string> Permissions { get; } // Expanded, cached per request
IReadOnlyCollection<string> Groups { get; }
IReadOnlyCollection<string> Scopes { get; } // OAuth/OIDC scopes
bool HasPermission(string permission);
bool HasAnyPermission(IEnumerable<string> permissions); // OR logic
bool HasAllPermissions(IEnumerable<string> permissions); // AND logic
bool IsInRole(string role);
bool IsInGroup(string group);
bool HasScope(string scope);
}

Strongly-typed permission. Each permission is a type with static abstract members.

public interface IPermission
{
static abstract string Name { get; } // e.g., "booking.guests.create"
static abstract string? Description { get; }
static abstract string? Category { get; } // e.g., "Booking"
}

Strongly-typed role with default permission assignments.

public interface IRole
{
static abstract string Name { get; }
static abstract string? Description { get; }
static abstract IReadOnlyList<string> DefaultPermissions { get; } // Supports wildcards ("booking.*")
}

Strongly-typed group with default role assignments.

public interface IGroup
{
static abstract string Name { get; }
static abstract string? Description { get; }
static abstract IReadOnlyList<string> DefaultRoles { get; }
}

Permission template defined by a module. Not an application role. Used as a building block for composing real roles at the host level.

public interface IRoleDefinition
{
static abstract string Name { get; }
static abstract string? Description { get; }
static abstract IReadOnlyList<string> Permissions { get; }
}

Example composition:

authz.MapRole("operations-manager", r => r
.IncludeDefinition<BookingOperator>()
.IncludeDefinition<CatalogReader>()
.WithoutPermissions(BookingPermissions.Reservation.Delete));

IPermissionProvider (Pragmatic.Authorization)

Section titled “IPermissionProvider (Pragmatic.Authorization)”

Resolves permissions from external sources. Multiple providers are composed and merged (union).

public interface IPermissionProvider
{
int Order { get; } // Convention: 0 = claims, 100 = role expansion, 200 = external
ValueTask<IReadOnlySet<string>> ResolvePermissionsAsync(ICurrentUser user, CancellationToken ct = default);
}

IPermissionChecker (Pragmatic.Authorization)

Section titled “IPermissionChecker (Pragmatic.Authorization)”

Async permission checker for scenarios requiring I/O (policy servers, database RBAC).

public interface IPermissionChecker
{
ValueTask<bool> HasPermissionAsync(string permission, CancellationToken cancellationToken = default);
ValueTask<bool> HasAnyPermissionAsync(IEnumerable<string> permissions, CancellationToken cancellationToken = default);
ValueTask<bool> HasAllPermissionsAsync(IEnumerable<string> permissions, CancellationToken cancellationToken = default);
}

When to use: Use IUserAuthorization (synchronous, in-memory) for simple checks. Use IPermissionChecker when authorization needs API calls or database queries.

IResourceAuthorizer<TResource> (Pragmatic.Authorization)

Section titled “IResourceAuthorizer<TResource> (Pragmatic.Authorization)”

Resource-level (ABAC) authorization. Contravariant on TResource.

public interface IResourceAuthorizer<in TResource>
{
ValueTask<bool> CanAccessAsync(
ICurrentUser user,
TResource resource,
string action,
CancellationToken ct = default);
}

NullUserAuthorization (Pragmatic.Authorization)

Section titled “NullUserAuthorization (Pragmatic.Authorization)”

Singleton. All checks return false, all collections empty.

public static readonly NullUserAuthorization Instance;

FullAccessUserAuthorization (Pragmatic.Authorization)

Section titled “FullAccessUserAuthorization (Pragmatic.Authorization)”

Singleton. All checks return true. Used for system-level contexts (background jobs, migrations).

public static readonly FullAccessUserAuthorization Instance;
public sealed record PermissionInfo(string Name, string? Description, string? Category);
public sealed record RoleInfo(string Name, string? Description, IReadOnlyList<string> DefaultPermissions);

[RequirePermission] (Pragmatic.Authorization)

Section titled “[RequirePermission] (Pragmatic.Authorization)”

AND-logic permission enforcement. Applied to endpoints, actions, and mutations.

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class RequirePermissionAttribute(params string[] permissions) : Attribute
{
public string[] Permissions { get; }
public string? Description { get; set; } // For SG-generated constants (Mode 2)
public string? Category { get; set; } // Category override for generated permission
}

Mode 1 (enforcement only): [RequirePermission("booking.reservation.create")] Mode 2 (enforcement + definition): [RequirePermission("refund", Description = "Issue a refund")] — SG derives full name from context.

[RequireAnyPermission] (Pragmatic.Authorization)

Section titled “[RequireAnyPermission] (Pragmatic.Authorization)”

OR-logic permission enforcement.

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class RequireAnyPermissionAttribute(params string[] permissions) : Attribute
{
public string[] Permissions { get; }
}

[ExplicitPermission] / [ExplicitPermission<TPermission>] (Pragmatic.Authorization)

Section titled “[ExplicitPermission] / [ExplicitPermission<TPermission>] (Pragmatic.Authorization)”

Overrides the auto-derived permission name.

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class ExplicitPermissionAttribute(string permission) : Attribute
{
public string Permission { get; }
}
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class ExplicitPermissionAttribute<TPermission> : Attribute
where TPermission : IPermission;

Marker for domain events.

public interface IDomainEvent
{
DateTimeOffset OccurredAt { get; }
}

Events should be immutable records capturing what happened.

Dispatches events to registered handlers.

public interface IDomainEventDispatcher
{
Task DispatchAsync<TEvent>(TEvent @event, CancellationToken ct = default) where TEvent : IDomainEvent;
Task DispatchAsync(IEnumerable<IDomainEvent> events, CancellationToken ct = default);
}

IDomainEventHandler<TEvent> (Pragmatic.Events)

Section titled “IDomainEventHandler<TEvent> (Pragmatic.Events)”

Handles a specific event type. Multiple handlers per event type are supported, executed in ascending Order.

public interface IDomainEventHandler<in TEvent> where TEvent : IDomainEvent
{
int Order => 0; // Lower = earlier
Task HandleAsync(TEvent @event, CancellationToken ct = default);
}

Entity that accumulates domain events for post-persistence dispatch.

public interface IHasDomainEvents
{
IReadOnlyList<IDomainEvent> DomainEvents { get; }
void ClearDomainEvents();
}

EntityPropertyChanged<TEntity> (Pragmatic.Events)

Section titled “EntityPropertyChanged<TEntity> (Pragmatic.Events)”

Built-in event for property change propagation (cascade handlers).

public sealed record EntityPropertyChanged<TEntity> : IDomainEvent where TEntity : class
{
public required object EntityId { get; init; }
public required string PropertyName { get; init; }
public object? NewValue { get; init; }
public object? OldValue { get; init; }
public DateTimeOffset OccurredAt { get; init; } = DateTimeOffset.UtcNow;
}

Testable time abstraction wrapping TimeProvider for .NET 8+ interop.

public interface IClock
{
DateTimeOffset UtcNow { get; }
DateTimeOffset Now { get; }
DateOnly UtcToday { get; }
DateOnly Today { get; }
TimeOnly UtcTimeOfDay { get; }
TimeOnly TimeOfDay { get; }
TimeProvider GetTimeProvider();
}

Current tenant identity, scoped per request.

public interface ITenantContext
{
string? TenantId { get; }
string? TenantName { get; }
bool IsResolved { get; }
}

Transport-agnostic tenant resolution.

public interface ITenantResolver
{
ValueTask<string?> ResolveAsync(CancellationToken cancellationToken = default);
}

Resolution strategies: HTTP header, subdomain, JWT claim, API key, route parameter.

Marker for row-level tenant isolation.

public interface ITenantEntity
{
string TenantId { get; set; } // Set automatically on creation, filtered on read
}

UnresolvedTenantContext (Pragmatic.MultiTenancy)

Section titled “UnresolvedTenantContext (Pragmatic.MultiTenancy)”

Singleton fallback. All properties null, IsResolved is false.

public static readonly UnresolvedTenantContext Instance;

Unified caching abstraction with stampede protection and tag-based invalidation. Default implementation: HybridCacheStack in Pragmatic.Caching (L1 memory + L2 distributed via Microsoft.Extensions.Caching.Hybrid).

public interface ICacheStack
{
ValueTask<T> GetOrSetAsync<T>(string key,
Func<CancellationToken, ValueTask<T>> factory,
CacheEntryOptions? options = null, CancellationToken ct = default);
ValueTask<T?> GetAsync<T>(string key, CancellationToken ct = default);
ValueTask<(bool Found, T? Value)> TryGetAsync<T>(string key, CancellationToken ct = default);
ValueTask SetAsync<T>(string key, T value,
CacheEntryOptions? options = null, CancellationToken ct = default);
ValueTask RemoveAsync(string key, CancellationToken ct = default);
ValueTask InvalidateByTagAsync(string tag, CancellationToken ct = default);
ValueTask InvalidateByTagsAsync(IEnumerable<string> tags, CancellationToken ct = default);
}

Options for a cache entry including duration, tags, and eviction priority.

public sealed class CacheEntryOptions
{
public TimeSpan? Duration { get; init; }
public TimeSpan? SlidingDuration { get; init; }
public ImmutableArray<string> Tags { get; init; } = [];
public CachePriority Priority { get; init; } = CachePriority.Normal;
public static CacheEntryOptions Default { get; } // 5 min duration
public static CacheEntryOptions WithDuration(TimeSpan duration);
public static CacheEntryOptions WithSliding(TimeSpan slidingDuration);
}

Eviction priority under memory pressure.

public enum CachePriority
{
Low = 0, // First to be evicted
Normal = 1, // Default
High = 2, // Less likely to be evicted
NeverRemove = 3 // Never auto-evicted (use sparingly)
}

Predefined category marker types for routing cache operations to different backends or configurations. Each nested sealed class is used as a generic type parameter with CachingBuilder.ForCategory<T>() and CacheStackProvider.ForCategory<T>().

public static class CacheCategories
{
public sealed class Default; // General-purpose business cache
public sealed class OutputCache; // ASP.NET Core HTTP response caching
public sealed class RateLimiting; // Cross-instance rate limit counters
public sealed class Permissions; // Authorization permission set caching
public sealed class Configuration; // Remote configuration value caching
}

Custom categories are defined as additional sealed marker classes.


IConfigurationStore (Pragmatic.Configuration)

Section titled “IConfigurationStore (Pragmatic.Configuration)”

Backend-agnostic configuration store with tenant-scoped overrides and change watching.

public interface IConfigurationStore
{
Task<string?> GetAsync(string key, CancellationToken ct = default);
Task<string?> GetAsync(string key, string tenantId, CancellationToken ct = default);
Task<IReadOnlyDictionary<string, string>> GetSectionAsync(string prefix, CancellationToken ct = default);
Task<IReadOnlyDictionary<string, string>> GetSectionAsync(string prefix, string tenantId, CancellationToken ct = default);
Task SetAsync(string key, string value, string? tenantId = null, CancellationToken ct = default);
Task DeleteAsync(string key, string? tenantId = null, CancellationToken ct = default);
IAsyncEnumerable<ConfigurationChange> WatchAsync(string keyPattern, CancellationToken ct = default);
}

Read-only store for secrets (vault, CI/CD, user-secrets).

public interface ISecretStore
{
Task<string?> GetSecretAsync(string key, CancellationToken ct = default);
Task<string?> GetSecretAsync(string key, string tenantId, CancellationToken ct = default);
}

ConfigurationChange (Pragmatic.Configuration)

Section titled “ConfigurationChange (Pragmatic.Configuration)”
public sealed record ConfigurationChange(
string Key, string? OldValue, string? NewValue, string? TenantId, DateTimeOffset Timestamp);

EnvironmentProfile (Pragmatic.Configuration)

Section titled “EnvironmentProfile (Pragmatic.Configuration)”

Wraps IHostEnvironment with Pragmatic conventions.

public sealed class EnvironmentProfile
{
public required string Name { get; init; } // e.g., "Development", "Production"
public string? Tag { get; init; } // e.g., "eu-west", "canary"
public IReadOnlyList<string> ResolutionChain { get; init; } // e.g., ["base", "staging", "staging-eu-west"]
public bool IsDevelopment { get; }
public bool IsStaging { get; }
public bool IsProduction { get; }
public bool IsTesting { get; }
public bool IsEnvironment(string environmentName);
public static EnvironmentProfile From(string environmentName, string? tag = null);
}

Strongly-typed feature flag marker.

public interface IFeatureFlag
{
static abstract string Name { get; }
static abstract string? Description { get; }
}

IFeatureFlagStore (Pragmatic.FeatureFlags)

Section titled “IFeatureFlagStore (Pragmatic.FeatureFlags)”

Evaluation-aware flag store with context-based targeting.

public interface IFeatureFlagStore
{
Task<bool> IsEnabledAsync(string flagName, CancellationToken ct = default);
Task<bool> IsEnabledAsync(string flagName, FeatureFlagContext context, CancellationToken ct = default);
Task<FeatureFlagDefinition?> GetDefinitionAsync(string flagName, CancellationToken ct = default);
Task<IReadOnlyList<FeatureFlagDefinition>> GetAllAsync(CancellationToken ct = default);
IAsyncEnumerable<FeatureFlagChange> WatchAsync(CancellationToken ct = default);
}

IFeatureFlagContextProvider (Pragmatic.FeatureFlags)

Section titled “IFeatureFlagContextProvider (Pragmatic.FeatureFlags)”

Builds evaluation context from ambient state.

public interface IFeatureFlagContextProvider
{
Task<FeatureFlagContext> GetContextAsync(CancellationToken ct = default);
}

FeatureFlagContext (Pragmatic.FeatureFlags)

Section titled “FeatureFlagContext (Pragmatic.FeatureFlags)”
public sealed record FeatureFlagContext
{
public string? TenantId { get; init; }
public string? UserId { get; init; }
public string? Plan { get; init; }
public string? Environment { get; init; }
public IReadOnlyDictionary<string, string> Properties { get; init; }
public static FeatureFlagContext Empty { get; }
}

FeatureFlagDefinition (Pragmatic.FeatureFlags)

Section titled “FeatureFlagDefinition (Pragmatic.FeatureFlags)”
public sealed record FeatureFlagDefinition
{
public required string Name { get; init; }
public bool Enabled { get; init; }
public string? Description { get; init; }
public IReadOnlyList<FeatureFlagRule> Rules { get; init; }
}

Defined in FeatureFlagDefinition.cs alongside FeatureFlagDefinition.

public sealed record FeatureFlagRule
{
public required string Type { get; init; } // "tenant", "user", "plan", "percentage", "property"
public IReadOnlyList<string> Values { get; init; }
public bool Enabled { get; init; } = true;
}

FeatureFlagChange (Pragmatic.FeatureFlags)

Section titled “FeatureFlagChange (Pragmatic.FeatureFlags)”
public sealed record FeatureFlagChange(
string FlagName, bool WasEnabled, bool IsEnabled, DateTimeOffset Timestamp);

FeatureFlagStoreExtensions (Pragmatic.FeatureFlags)

Section titled “FeatureFlagStoreExtensions (Pragmatic.FeatureFlags)”
public static class FeatureFlagStoreExtensions
{
static Task<bool> IsEnabledAsync<TFlag>(this IFeatureFlagStore store, CancellationToken ct = default);
static Task<bool> IsEnabledAsync<TFlag>(this IFeatureFlagStore store, FeatureFlagContext context, CancellationToken ct = default);
static Task<FeatureFlagDefinition?> GetDefinitionAsync<TFlag>(this IFeatureFlagStore store, CancellationToken ct = default);
}

IGlobalizationContext (Pragmatic.Internationalization.Context)

Section titled “IGlobalizationContext (Pragmatic.Internationalization.Context)”

Current globalization context for formatting operations.

public interface IGlobalizationContext
{
CultureInfo Culture { get; }
TimeZoneInfo? TimeZone => null; // Null falls back to UTC
string? CurrencyCode => null; // e.g., "EUR", "USD"; null derives from culture
}

Tracks whether the current execution is system-initiated (internal call). When IsInternalCall is true, authorization filters skip permission checks. Event handlers automatically run as internal calls.

public interface ICallContext
{
bool IsInternalCall { get; }
IDisposable EnterInternalCall(); // Returns disposable that restores previous state; supports nesting
}

Fluent builder for configuring module strategies at startup.

public interface IPragmaticBuilder
{
IServiceCollection Services { get; }
IConfiguration Configuration { get; }
IHostEnvironment Environment { get; }
}

Each module contributes Use*() extension methods on this interface (e.g., UseMultiTenancy, UseAuthentication).

IPackageDefinition (Pragmatic.Composition)

Section titled “IPackageDefinition (Pragmatic.Composition)”

Defines a reusable package that can be imported into a module via [UsePackage<T>].

public interface IPackageDefinition
{
static abstract string PackageName { get; }
static abstract string? RoutePrefix { get; }
static abstract string? Description { get; }
static virtual IReadOnlyList<string> RequiredTypeNames => [];
}

ServiceCollectionDecorateExtensions (Pragmatic.Composition.Extensions)

Section titled “ServiceCollectionDecorateExtensions (Pragmatic.Composition.Extensions)”

Decorator support for IServiceCollection.

public static class ServiceCollectionDecorateExtensions
{
static IServiceCollection Decorate<TService, TDecorator>(this IServiceCollection services);
static IServiceCollection Decorate(this IServiceCollection services, Type serviceType, Type decoratorType);
static IServiceCollection Decorate<TService>(this IServiceCollection services, Func<TService, IServiceProvider, TService> decorator);
}

PragmaticDatabase (Pragmatic.Composition.Database)

Section titled “PragmaticDatabase (Pragmatic.Composition.Database)”

Abstract base class for database declarations.

public abstract class PragmaticDatabase
{
public virtual IEnumerable<string> GetRequiredConfigKeys();
}

All in Pragmatic.Composition.Attributes. See the README for a summary table. Full signatures:

public sealed class ModuleAttribute : Attribute
{
public string? Name { get; set; }
public string[] DependsOn { get; set; }
public string? Version { get; set; }
public string? Description { get; set; }
}
public sealed class ServiceAttribute : Attribute
{
public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Scoped;
public Type? As { get; set; }
public bool AsSelf { get; set; }
public string? Key { get; set; }
}
public sealed class ServiceAttribute<TInterface> : Attribute where TInterface : class
{
public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Scoped;
public string? Key { get; set; }
}
public sealed class DecoratorAttribute : Attribute
{
public int Order { get; set; }
}
public sealed class InjectAttribute : Attribute
{
public bool Required { get; set; }
public string? Key { get; set; }
}
public sealed class ServiceFactoryAttribute : Attribute;
public sealed class FactoryAttribute : Attribute
{
public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Scoped;
}
public sealed class IncludeAttribute<TModule> : Attribute;
public sealed class IncludeAttribute<TModule, TDatabase> : Attribute;
public sealed class IncludeAttribute<TModule, TDatabase, TDbContext> : Attribute;
public sealed class IncludeModuleAttribute<TModule> : Attribute;
public sealed class IncludeModuleAttribute : Attribute { public Type ModuleType { get; } }

Use [IncludeModule<T>] instead. Both generic and non-generic forms exist for backward compatibility.

[Obsolete("Use [IncludeModule<T>] instead.")]
public sealed class DependsOnAttribute<TModule> : Attribute where TModule : class;
[Obsolete("Use [IncludeModule(typeof(T))] instead.")]
public sealed class DependsOnAttribute : Attribute
{
public Type ModuleType { get; }
}
public sealed class StartupStepAttribute : Attribute;
public sealed class PragmaticDatabaseAttribute : Attribute
{
public DatabaseProvider Provider { get; set; }
public string ConfigKey { get; set; }
}
public sealed class RequiresConfigAttribute : Attribute
{
public string SectionPath { get; }
public string? Description { get; set; }
}
public sealed class UsePackageAttribute<TPackage> : Attribute where TPackage : class, IPackageDefinition
{
public string? RoutePrefix { get; set; }
}
public sealed class RemoteBoundaryAttribute<TModule> : Attribute where TModule : class
{
public string? BaseUrl { get; set; }
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class PragmaticMetadataAttribute : Attribute
{
public MetadataCategory Category { get; }
public string SchemaVersion { get; }
public string JsonData { get; }
}

ServiceLifetime (Pragmatic.Composition.Attributes)

Section titled “ServiceLifetime (Pragmatic.Composition.Attributes)”
public enum ServiceLifetime { Singleton = 0, Scoped = 1, Transient = 2 }

DatabaseProvider (Pragmatic.Composition.Enums)

Section titled “DatabaseProvider (Pragmatic.Composition.Enums)”
public enum DatabaseProvider { SqlServer, PostgreSql, SQLite, MySql, InMemory }

MetadataCategory (Pragmatic.Composition.Metadata)

Section titled “MetadataCategory (Pragmatic.Composition.Metadata)”
public enum MetadataCategory
{
DI = 0, Mapping = 1, Actions = 2, Startup = 3, Validation = 4,
Endpoints = 5, HealthChecks = 6, Identifiers = 7, Module = 8,
Translations = 9, Persistence = 10, EventHandlers = 11,
HostTopology = 12, Caching = 13, Configuration = 14
}

Extension methods for System.Diagnostics.Activity.

public static class ActivityHelper
{
static Activity? RecordException(this Activity? activity, Exception ex);
static Activity? SetSuccess(this Activity? activity);
static Activity? SetFailure(this Activity? activity, string errorCode, string? description = null);
static Activity? AddNamedEvent(this Activity? activity, string name, params KeyValuePair<string, object?>[] tags);
}
public sealed class TelemetryOptions
{
public bool Enabled { get; set; } = true;
public bool Tracing { get; set; } = true;
public bool Metrics { get; set; } = true;
public bool Logging { get; set; } = true;
public bool UseOtlpExporter { get; set; } // Default false; console in Development
public string? ServiceName { get; set; } // Null = assembly name
public double SamplingRatio { get; set; } = 0.1; // 10% in production, always 1.0 in dev
}

Telemetry Convention Classes (Pragmatic.Telemetry.Conventions)

Section titled “Telemetry Convention Classes (Pragmatic.Telemetry.Conventions)”
ClassTag Constants
ErrorTagsType, Message, Stacktrace
ActionTagsName, Kind, Result, ErrorCode, MutationMode, EntityType, FilterCount
DbTagsSystem, Operation, CollectionName, RowsAffected, BulkBatchSize, FilterCount, FilterMode
CacheTagsHit, Key, Operation, Tags
ResilienceTagsPolicy, Attempt, Outcome, CircuitState
EventTagsName, Handler, HandlerCount
I18NTagsUICulture, DataCulture, Currency, TimeZone, Source, RequestedCulture, ResolvedCulture, ValidationResult, ProviderName, ProviderPriority, LocalizationKey, LocalizationCulture, FallbackUsed, Missing, Count, PluralCategory, FilePath, StringsCount, PluralsCount