Skip to content

Feature/feature flag system#1051

Open
sweetesty wants to merge 4 commits into
Shelterflex:mainfrom
sweetesty:feature/feature-flag-system
Open

Feature/feature flag system#1051
sweetesty wants to merge 4 commits into
Shelterflex:mainfrom
sweetesty:feature/feature-flag-system

Conversation

@sweetesty
Copy link
Copy Markdown

Closes #978


This PR builds a lightweight, config-file-backed feature flag system for both the backend and frontend with no external service dependency.

Backend

backend/src/config/featureFlags.ts — single source of truth

  • Typed FeatureFlagConfig record defining all flags with default values and sensitive classification
  • All flag names in SCREAMING_SNAKE_CASE
  • Adding a new flag requires only this one file change

backend/src/services/featureFlags.ts

  • isEnabled(flag: string, context?: { userId?, role? }): boolean — synchronous for config-backed flags; reads defaults from config, applies FEATURE_FLAG_<NAME>=true/false env overrides, then applies user/role targeting if context is provided
  • FEATURE_FLAG_* env overrides take precedence over config defaults — works correctly in test and CI environments
  • No external service dependency; no DB calls at this stage

GET /api/config/feature-flags

  • Auth-aware response: filters out sensitive: true flags for guests and tenants; admins receive the full flag set
  • Returns only the flags the calling client is allowed to see

requireFlag(flag: string) middleware

  • Express middleware wrapping route handlers; calls isEnabled() and returns 403 if the flag is off
  • Applied to existing staking routes and other ad-hoc guarded endpoints

Frontend

frontend/config/featureFlags.ts — static SSR fallbacks

  • Default values mirroring the backend config; used during SSR and hydration before the client fetch resolves
  • Client hook returns the static default during SSR — no hydration mismatch

frontend/lib/featureFlags.tsx

  • FeatureFlagProvider — fetches flags from /api/config/feature-flags on app load; stores result in React context; falls back to static defaults on fetch failure
  • useFeatureFlag(flag: string): boolean — reads from context; returns static default during SSR/hydration

Migration — 3 existing ad-hoc guards replaced

  • INSPECTOR_DASHBOARD_ENABLED env check → useFeatureFlag('INSPECTOR_DASHBOARD_ENABLED')
  • Staking route boolean guard → requireFlag('STAKING_ENABLED')
  • Mock data guard → useFeatureFlag('MOCK_DATA_ENABLED')

Acceptance criteria met:

  • ✅ All flags defined in a single typed config file; no undeclared flag checks
  • isEnabled synchronous for config-backed flags
  • ✅ Client hook returns default during SSR/hydration
  • FEATURE_FLAG_* env overrides work in test and CI
  • ✅ At least 3 existing ad-hoc guards migrated
  • ✅ Adding a new flag requires only one config file change

Regain and others added 3 commits May 30, 2026 21:45
…ard with 60s memory caching and neobrutalist Recharts charts
Implements Shelterflex#953. Adds a dedicated rent-to-own calculator page at
/calculator/rent-to-own with real-time equity accumulation chart,
plan comparison card (vs. standard renting), and edge-case handling
for budgets too low to reach ownership. Links added to the main
payment calculator (tab) and property detail pages (secondary CTA).
Pure frontend — no API calls; all maths in lib/rentToOwnCalc.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements Shelterflex#978. Introduces a config-file-backed feature flag system
for both backend and frontend with no external dependencies.

Backend:
- backend/src/config/featureFlags.ts — single typed source of truth
  for all flags (STAKING_ENABLED, INSPECTOR_DASHBOARD_ENABLED,
  RENT_TO_OWN_ENABLED, ADVANCED_WALLET_OPS_ENABLED,
  BACKEND_HEALTH_INDICATOR_ENABLED)
- backend/src/services/featureFlags.ts — isEnabled() with
  FEATURE_FLAG_<NAME>=true env override support; getAllFlags() snapshot
- backend/src/middleware/requireFlag.ts — requireFlag('FLAG') Express
  middleware; returns 403 when flag is off
- backend/src/routes/featureFlags.ts — GET /api/config/feature-flags;
  auth-aware (admin > authenticated > guest flag subsets)
- Wired requireFlag onto /api/staking and /api/inspector routes;
  /api/config/feature-flags mounted in app.ts

Frontend:
- frontend/config/featureFlags.ts — static defaults used during SSR
  before the client fetch resolves
- frontend/lib/featureFlags.ts — FeatureFlagProvider (React context,
  fetches from /api/config/feature-flags on mount) + useFeatureFlag()
  hook; falls back to static defaults on error or during SSR
- Wired FeatureFlagProvider into root layout

Migrations (3 existing ad-hoc guards replaced):
- tenant/page.tsx: featureFlags.enableExperimentalStaking
  → useFeatureFlag('STAKING_ENABLED')
- BackendHealthCompact.tsx: NEXT_PUBLIC_SHOW_BACKEND_HEALTH env check
  → useFeatureFlag('BACKEND_HEALTH_INDICATOR_ENABLED')
- /api/staking + /api/inspector: manual checks
  → requireFlag() middleware

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 30, 2026

@sweetesty is attempting to deploy a commit to the pope-h's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 30, 2026

@sweetesty Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Flag System — Server-Side & Client-Side Toggle Infrastructure

1 participant