Flags Diagnostics & Source Generator
COCFLAG001 — Non-Static ExpiresAt
Severity: Warning
ExpiresAt must be a static DateTimeOffset literal so the source generator can embed it in the generated descriptor. Dynamic expressions can't be evaluated at compile time.
// ❌ Warning: ExpiresAt can't be determined at compile time
public class MyFlags : FeatureFlags
{
public override DateTimeOffset ExpiresAt => DateTimeOffset.UtcNow.AddMonths(6);
}// ✓ Compliant: Static literal
public class MyFlags : FeatureFlags
{
public override DateTimeOffset ExpiresAt => new(2026, 6, 1, 0, 0, 0, TimeSpan.Zero);
}If the generator can't determine ExpiresAt, it defaults to DateTimeOffset.MinValue — the class is treated as already expired and health reports Degraded.
COCFLAG002 — Abstract Type Registered
Severity: Warning
Register<T>() was called with an abstract class. Abstract classes can't be instantiated as flag or entitlement instances.
// ❌ Warning: Can't instantiate abstract class
public abstract class BaseFlags : FeatureFlags { }
.UseFeatureFlags(f => f.Register<BaseFlags>())// ✓ Fix: Register the concrete subclass
public class AppFlags : BaseFlags { }
.UseFeatureFlags(f => f.Register<AppFlags>())COCFLAG003 — Missing Description
Severity: Info
A flag or entitlement property has no <summary> XML doc comment. Descriptions are surfaced through IFeatureFlagsDescriptors and IEntitlementsDescriptors — without them, operators see empty descriptions in tooling and the REST API.
// ℹ️ Info: No description
public class AppFlags : FeatureFlags
{
public FeatureFlag<bool> NewDashboard { get; }
}// ✓ Fix: Add a summary
public class AppFlags : FeatureFlags
{
/// <summary>Enables the redesigned billing dashboard.</summary>
public FeatureFlag<bool> NewDashboard { get; }
}Source Generator
The source generator is a core part of the flags system — not optional. It produces the descriptor metadata that the runtime uses for health monitoring, REST endpoints, and the IFeatureFlagsDescriptors / IEntitlementsDescriptors APIs. It ships with the Cocoar.Configuration package and runs automatically at compile time.
What It Generates
When you call Register<T>() in your UseFeatureFlags() or UseEntitlements() setup, the generator produces a CocoarFlagsDescriptors class containing:
- A dictionary of
FeatureFlagClassDescriptorentries (one per flag class) - A dictionary of
EntitlementClassDescriptorentries (one per entitlement class)
Each descriptor includes:
- The class
Type ExpiresAt(flags only)- A list of property descriptors (name + description from XML doc)
How It's Used
The generated descriptors are consumed internally by:
IFeatureFlagsDescriptors— providesAllandExpiredcollections for querying flag metadataIEntitlementsDescriptors— providesAllcollection for entitlement metadata- Health monitoring — checks
Expiredto determine if health should reportDegraded - REST endpoints — uses descriptors to generate endpoint routes
You don't reference the generated class directly — it's wired up automatically during DI registration.
Deterministic Output
The generator sorts all types alphabetically by full name, ensuring the same input always produces identical output. This prevents unnecessary rebuilds and diff noise in source control.