feat(settings): panel-tunable feature flags

Add a Feature Flags card to the Settings page that toggles env-gated
subsystems (external/internal PR review, web research, strategy engine,
pitch provisioning, RAG auto-update, transcript pruning) directly from
the panel instead of hand-editing environment variables.

Flags persist in system_settings as 'true'/'false' and are overlaid onto
the live config singleton at startup; an unset flag keeps its
environment/config default. A toggle takes effect on the next backend
restart — no per-consumer re-routing.

Backend: FEATURE_FLAGS registry + bool validator + get_bool accessor on
SettingsService; feature_flag_effective_values and
apply_persisted_feature_flags; GET /settings/feature-flags; best-effort
startup overlay in the app lifespan.

Frontend: settingsApi.getFeatureFlags / setFeatureFlag and a
FeatureFlagsCard rendered full-width below the settings grid.
This commit is contained in:
Renn F
2026-06-17 16:50:11 +02:00
parent eec35c0357
commit f27a9f9447
8 changed files with 328 additions and 3 deletions
+20
View File
@@ -4,6 +4,17 @@ export interface SettingsResponse {
settings: Record<string, string>;
}
export interface FeatureFlag {
key: string;
label: string;
enabled: boolean;
}
export interface FeatureFlagsResponse {
flags: FeatureFlag[];
note: string;
}
export const settingsApi = {
// GET /api/settings — all runtime-editable settings as a flat key→value map.
getAll: async (): Promise<Record<string, string>> => {
@@ -15,4 +26,13 @@ export const settingsApi = {
const { data } = await api.put<SettingsResponse>(`/settings/${key}`, { value });
return data.settings;
},
// GET /api/settings/feature-flags — effective flag values (override, else env).
getFeatureFlags: async (): Promise<FeatureFlagsResponse> => {
const { data } = await api.get<FeatureFlagsResponse>("/settings/feature-flags");
return data;
},
// PUT /api/settings/{key} — persist a feature flag as "true"/"false".
setFeatureFlag: async (key: string, enabled: boolean): Promise<void> => {
await api.put<SettingsResponse>(`/settings/${key}`, { value: enabled ? "true" : "false" });
},
};