// Feature-flag backend for the {{projectName}} project. // // `flagsPlugin` declares flags AS CODE and gates rpc calls two ways: // - declaratively via `gatedBy` (an off flag fails typed FlagDisabled // BEFORE the handler runs), and // - in-handler via `requireFlag(ctx, key)` / `isFlagEnabled(ctx, key)`. // A flag is a bare boolean (kill-switch) OR a rich definition with a // deterministic `% rollout` and OR-of-rules `targeting`. `store: 'memory'` // keeps this zero-infra; `store: 'postgres'` adds runtime-toggleable flags // overlaid on the code baseline. import { defineEnv, envVar } from '@voltro/env' import { flagsPlugin } from '@voltro/plugin-flags' export const env = defineEnv({ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }), }) export default { type: 'api' as const, name: '{{capProjectName}}{{capAppName}}', store: 'memory' as const, plugins: [ flagsPlugin({ flags: { // Bare boolean = kill-switch. `newEditor` is ON — the in-handler // requireFlag guard on notes.create passes. newEditor: true, // OFF — the gatedBy map below blocks notes.export with FlagDisabled. betaExport: false, // Targeting: only subjects whose metadata says plan=pro see it. proDashboard: { targeting: [{ metadata: { plan: 'pro' } }], description: 'Pro-plan dashboard.' }, // Deterministic % rollout — a given subject is stably in or out. gradualRollout: { rollout: 25, description: '25% gradual rollout, bucketed by subject.' }, }, // Declarative gate: tag → flag. An off flag fails FlagDisabled pre-handler. gatedBy: { 'notes.export': 'betaExport' }, store: 'memory', }), ], env, }