using BigRegister.Domain.Features;
namespace BigRegister.Api.Data;
/// One persisted runtime override for a feature flag (only stored once toggled; otherwise the
/// catalog default applies). Key = the flag key from the code catalog (FeatureFlags.Catalog).
public sealed class FeatureFlagEntity
{
public required string Key { get; init; }
public bool Enabled { get; set; }
}
/// A flag resolved for a consumer: catalog default overlaid with any stored override.
public sealed record ResolvedFlag(string Key, string Description, bool Enabled);
///
/// Runtime feature-flag state (WP-47). SQLite-backed like , same
/// single-gate idiom. The CATALOG (which flags exist + their defaults) is code
/// (); this store only holds the admin's on/off overrides. An unknown
/// key is never writable/enabled — the code catalog is the authority.
///
public static class FeatureFlagStore
{
private static readonly object _gate = new();
/// Catalog defaults overlaid with stored overrides — the whole flag set for the admin UI + FE.
public static IReadOnlyList All()
{
Dictionary overrides;
lock (_gate)
{
using var db = Db.Create();
overrides = db.FeatureFlags.ToDictionary(f => f.Key, f => f.Enabled);
}
return FeatureFlags.Catalog
.Select(d => new ResolvedFlag(d.Key, d.Description,
overrides.TryGetValue(d.Key, out var e) ? e : d.DefaultEnabled))
.ToList();
}
/// Server-side enforcement helper. Unknown key → false (fail closed).
public static bool IsEnabled(string key)
{
var def = FeatureFlags.Catalog.FirstOrDefault(d => d.Key == key);
if (def is null) return false;
lock (_gate)
{
using var db = Db.Create();
return db.FeatureFlags.Find(key)?.Enabled ?? def.DefaultEnabled;
}
}
/// Set an override for a KNOWN flag; returns false for an unknown key (caller → 404).
public static bool Set(string key, bool enabled)
{
if (!FeatureFlags.Catalog.Any(d => d.Key == key)) return false;
lock (_gate)
{
using var db = Db.Create();
var row = db.FeatureFlags.Find(key);
if (row is null) db.FeatureFlags.Add(new FeatureFlagEntity { Key = key, Enabled = enabled });
else row.Enabled = enabled;
db.SaveChanges();
}
return true;
}
}