Feature Flags

May 31, 2026 · View on GitHub

DataSurfaceFeatures controls which DataSurface capabilities are active. Flags are an AND-gate kill-switch, not an on-switch:

A feature runs only when its flag is enabled AND its wiring is present (the service is registered / the attribute is applied). Flags default to enabled, so registering the dependency is all you need to turn a feature on. Setting a flag to false force-disables the feature even when it is fully wired.

So you never have to "enable both": wire the feature as usual, and reach for a flag only when you want to turn something off — for example, disabling webhooks in one environment without changing DI, or locking a service down to a minimal surface.

The default (new DataSurfaceFeatures(), used when you don't set opt.Features) permits every feature. The Minimal/Standard presets are opt-in lockdowns that switch features off.


Presets

PresetWhat it permits
(default)Every feature — wire what you need, nothing is killed
FullEvery feature (same as the default)
StandardEverything except webhooks (validation, defaults, computed, projection, all security, observability, caching, hooks, overrides)
MinimalOnly field validation + default values; everything else killed
builder.Services.AddDataSurfaceEfCore(opt =>
{
    // Default: every feature permitted. Lock down with a preset if you want less:
    opt.Features = DataSurfaceFeatures.Minimal;
    // opt.Features = DataSurfaceFeatures.Standard;
});

Individual Flags

Start from the default (all permitted) and turn specific features off:

opt.Features = new DataSurfaceFeatures
{
    EnableMetrics = false,   // kill metrics even if a recorder is registered
    EnableTracing = false,   // kill tracing
    EnableWebhooks = false   // kill webhooks even if an IWebhookPublisher is registered
};

Every flag you don't set stays at its default of true (permitted). Remember the AND-gate: a permitted feature still only runs when its dependency is wired.


Flag Reference

✅ = permitted by that preset, ❌ = killed by that preset. A permitted feature still requires its wiring (the service in the description / the relevant attribute) to actually run.

CategoryFlagMinimalStandardFullRuns when permitted and
Core CRUDEnableFieldValidationthe contract declares constraints (MinLength, MaxLength, Min, Max, Regex, AllowedValues)
EnableDefaultValuesa field declares a DefaultValue
EnableComputedFieldsa field declares a ComputedExpression (EF/static only)
EnableFieldProjectionthe request sends ?fields=
SecurityEnableTenantIsolationthe resource has [CrudTenant] and a tenant can be resolved
EnableRowLevelSecurityan IResourceFilter<T> is registered
EnableResourceAuthorizationan IResourceAuthorizer<T> is registered
EnableFieldAuthorizationan IFieldAuthorizer is registered
ObservabilityEnableAuditLoggingan IAuditLogger is registered
EnableMetricsDataSurfaceMetrics is registered
EnableTracinga listener subscribes to the DataSurface activity source
CachingEnableQueryCachingan IQueryResultCache is registered
ExtensibilityEnableHooksan ICrudHook / ICrudHook<T> is registered
EnableOverridesan override is registered in CrudOverrideRegistry
IntegrationEnableWebhooksan IWebhookPublisher is registered

Always-On Behavior

The following are always enforced regardless of feature flags:

  • Unknown field rejection on create/update
  • RequiredOnCreate validation
  • Immutable field rejection on update
  • Pagination enforcement
  • Filter/sort allowlists
  • Startup contract validation