Skip to content

📄 feature.flags.js

📄 src/config/feature.flags.js
// FEATURE FLAGS CHAOS - ANTIPATTERN: Feature flags everywhere with no management
// Flags are stored in: environment variables, database, config files, 
// hardcoded values, localStorage (if this were frontend), cookies, headers, 
// query params, and random global variables
// 
// Nobody knows which flags are still used or what they do

import { helpers, log } from '../helpers.js'

// ============================================================
// GLOBAL FLAGS (Hardcoded)
// ============================================================

// These were supposed to be temporary (2019)
export const ENABLE_NEW_FEATURE = true
export const ENABLE_NEW_FEATURE_V2 = true
export const ENABLE_NEW_FEATURE_V3 = false // Broke in prod
export const ENABLE_NEW_FEATURE_FINAL = true
export const ENABLE_NEW_FEATURE_REAL_FINAL = false
export const ENABLE_NEW_FEATURE_ACTUALLY_FINAL = true

// Nobody remembers what these do
export const FLAG_A = true
export const FLAG_B = false
export const FLAG_C = null // Null? Really?
export const FLAG_D = undefined
export const FLAG_E = 1 // Is 1 truthy? Is 0 falsy?
export const FLAG_F = 'true' // String "true" vs boolean true
export const FLAG_G = 'yes'
export const FLAG_H = 'enabled'

// Feature flags for features that were never built
export const ENABLE_AI_CHAT = true // AI chat was never implemented
export const ENABLE_BLOCKCHAIN = true // What blockchain?
export const ENABLE_QUANTUM_COMPUTING = false // Lol
export const ENABLE_WEB3 = true // We don't have Web3
export const ENABLE_METAVERSE = false // Thank god this is false

// Flags that contradict each other
export const ENABLE_DARK_MODE = true
export const DISABLE_DARK_MODE = true // Both are true!
export const DARK_MODE_ENABLED = false
export const DARK_MODE_DISABLED = false // Both are false!

// Feature flags with typos
export const ENBALE_NOTIFICATIONS = true
export const ENABEL_EMAILS = true
export const ENABLE_NOTIFCATIONS = false
export const EANBLE_SMS = true

// ============================================================
// DYNAMIC FLAGS (Runtime)
// ============================================================

// ANTIPATTERN: Mutable global state for flags
let runtimeFlags = {
  debug: process.env.DEBUG === 'true' || process.env.DEBUG === '1' || process.env.DEBUG === 'yes',
  verbose: process.env.VERBOSE !== 'false', // Note: defaults to true
  experimental: !process.env.PRODUCTION,
  maintenance: false,
  readonly: false,
  godMode: true, // Always true because why not
}

// ANTIPATTERN: Multiple ways to set flags
export function setFlag(name, value) {
  runtimeFlags[name] = value
  console.log(`[FLAGS] Set ${name} = ${value}`)
  // No validation, no persistence, no sync
}

export function getFlag(name) {
  // ANTIPATTERN: Complex fallback chain
  return runtimeFlags[name] ?? 
         process.env[name] ?? 
         process.env[name.toUpperCase()] ?? 
         process.env[`FEATURE_${name.toUpperCase()}`] ?? 
         process.env[`FLAG_${name.toUpperCase()}`] ??
         process.env[`ENABLE_${name.toUpperCase()}`] ??
         global[name] ??
         globalThis[name] ??
         false
}

// ============================================================
// USER-SPECIFIC FLAGS (Per-request)
// ============================================================

export function getUserFlags(req) {
  const flags = { ...runtimeFlags }
  
  // ANTIPATTERN: Flags from query params (can be manipulated!)
  if (req?.query) {
    Object.keys(req.query).forEach(key => {
      if (key.startsWith('flag_') || key.startsWith('enable_')) {
        flags[key.replace('flag_', '').replace('enable_', '')] = 
          req.query[key] === 'true' || req.query[key] === '1'
      }
    })
  }
  
  // ANTIPATTERN: Flags from headers (can be manipulated!)
  if (req?.headers) {
    const flagHeader = req.headers['x-feature-flags']
    if (flagHeader) {
      try {
        Object.assign(flags, JSON.parse(flagHeader))
      } catch (e) {
        console.log('[FLAGS] Failed to parse x-feature-flags header')
      }
    }
    
    // Individual headers
    if (req.headers['x-debug'] === 'true') flags.debug = true
    if (req.headers['x-admin'] === 'true') flags.admin = true
    if (req.headers['x-god-mode'] === 'true') flags.godMode = true
  }
  
  // ANTIPATTERN: Flags from cookies (persistent manipulation!)
  if (req?.cookies) {
    if (req.cookies.isAdmin === 'true') flags.admin = true
    if (req.cookies.debug === 'true') flags.debug = true
    if (req.cookies.experimental === 'true') flags.experimental = true
  }
  
  return flags
}

// ============================================================
// PERCENTAGE ROLLOUT (Broken)
// ============================================================

// ANTIPATTERN: No consistent hashing, different result each time
export function isFeatureEnabledForUser(featureName, userId) {
  // Should use consistent hashing, but uses Math.random instead
  const percentage = featurePercentages[featureName] || 0
  const random = Math.random() * 100
  
  // User will get different result on each request!
  return random < percentage
}

const featurePercentages = {
  newHomePage: 50,
  darkMode: 100,
  betaFeatures: 10,
  experimentalApi: 5,
  newCheckout: 0, // Disabled
  aiPowered: 100, // "AI powered" but there's no AI
}

// ANTIPATTERN: Percentage that can exceed 100
export function setFeaturePercentage(feature, percentage) {
  // No validation!
  featurePercentages[feature] = percentage
  console.log(`[FLAGS] ${feature} now at ${percentage}%`)
  // 150% means everyone gets it? Or does it error?
}

// ============================================================
// FLAG DEPENDENCIES (Nightmare)
// ============================================================

export function isFeatureAvailable(feature) {
  // ANTIPATTERN: Flags that depend on other flags
  switch (feature) {
    case 'superFeature':
      return ENABLE_NEW_FEATURE && FLAG_A && !FLAG_B && runtimeFlags.experimental
    
    case 'megaFeature':
      return isFeatureAvailable('superFeature') && FLAG_E === 1 && FLAG_F === 'true'
    
    case 'ultraFeature':
      return isFeatureAvailable('megaFeature') && 
             ENABLE_NEW_FEATURE_V2 && 
             !ENABLE_NEW_FEATURE_V3 && 
             ENABLE_NEW_FEATURE_FINAL
    
    case 'godFeature':
      // Circular dependency! isFeatureAvailable calls itself
      return runtimeFlags.godMode && isFeatureAvailable('ultraFeature')
    
    default:
      // Unknown features are... enabled? disabled? who knows!
      return Math.random() > 0.5
  }
}

// ============================================================
// KILL SWITCHES
// ============================================================

let killSwitches = {
  api: false,
  database: false,
  auth: false,
  payments: false,
  everything: false,
}

export function activateKillSwitch(name) {
  killSwitches[name] = true
  console.log(`[KILL SWITCH] ${name} ACTIVATED!`)
  
  // ANTIPATTERN: Kill switch that kills everything
  if (name === 'everything') {
    Object.keys(killSwitches).forEach(k => killSwitches[k] = true)
    console.log('[KILL SWITCH] EVERYTHING IS DEAD!')
  }
}

export function isKilled(name) {
  return killSwitches[name] || killSwitches.everything
}

// ============================================================
// FLAG HISTORY (Memory leak)
// ============================================================

const flagHistory = []

export function recordFlagChange(name, oldValue, newValue, source) {
  flagHistory.push({
    name,
    oldValue,
    newValue,
    source,
    timestamp: Date.now(),
    stack: new Error().stack, // Store stack trace for debugging!
  })
  
  // ANTIPATTERN: Never clean up history
  if (flagHistory.length > 100000) {
    console.log('[FLAGS] History has 100k+ entries, but not cleaning up!')
  }
}

// ============================================================
// EXPORTS (Chaotic)
// ============================================================

export {
  runtimeFlags,
  featurePercentages,
  killSwitches,
  flagHistory,
}

// Also export as default with different structure
export default {
  // Static flags
  static: {
    ENABLE_NEW_FEATURE,
    ENABLE_NEW_FEATURE_V2,
    ENABLE_NEW_FEATURE_V3,
    FLAG_A, FLAG_B, FLAG_C, FLAG_D, FLAG_E, FLAG_F, FLAG_G, FLAG_H,
    ENABLE_AI_CHAT, ENABLE_BLOCKCHAIN, ENABLE_WEB3,
  },
  
  // Runtime flags
  runtime: runtimeFlags,
  
  // Functions
  get: getFlag,
  set: setFlag,
  getUserFlags,
  isEnabled: isFeatureEnabledForUser,
  isAvailable: isFeatureAvailable,
  kill: activateKillSwitch,
  isKilled,
  
  // History
  history: flagHistory,
}