Add a runtime feature flag (AppConfig-backed on prod, secret fallback off-prod), global by default or optionally gated by workspace id, org id, user id, or plat
复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-add-feature-flag-ee160f94e901 ,按照其中的说明把「add-feature-flag」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
You add a runtime feature flag to Sim that can change on prod with no redeploy (AWS AppConfig). Prefer a global on/off flag unless the rollout actually needs per-workspace, per-organization, per-user, or platform-admin targeting. When AppConfig isn't the source of truth, the flag falls back to a single secret (on/off only).
env-flags.ts@/lib/core/config/feature-flags.ts): runtime global on/off by default, optionally scoped by workspaceId/userId/orgId/admin. This skill.@/lib/core/config/env-flags.ts): deploy-time capability/environment detection (isProd, isHosted, isBillingEnabled). A module-load boolean. Do not add gated flags here.If the user wants a fixed per-deployment toggle, send them to env-flags.ts instead.
A flag's gating rule lives only in the hosted AppConfig document. It is ON for a context when any configured clause matches:
interface FeatureFlagRule {
enabled?: boolean // global default for everyone
workspaceIds?: string[] // allowlisted workspace ids
orgIds?: string[] // allowlisted organization ids
userIds?: string[] // allowlisted user ids
adminEnabled?: boolean // platform admins (user.role === 'admin')
}
Critically, none of this is expressible in code — gating (especially adminEnabled) can only be set through AppConfig, so no environment can grant access from a code literal. Off-AppConfig (self-hosted/OSS/local), a flag is simply on or off, derived from its fallback secret.
Confirm the granularity before editing code. If the user has not already specified it, stop and ask:
Should
<flag-name>be a global on/off flag (recommended), or does it need rollout targeting by workspace, organization, user, and/or platform admin?
env-flags.ts instead.Define the flag. Add one entry to the FEATURE_FLAGS registry in apps/sim/lib/core/config/feature-flags.ts. Each entry is the flag's whole definition — name (kebab-case key), description, and the fallback secret consulted when AppConfig isn't the source of truth (truthy ⇒ on globally):
const FEATURE_FLAGS = {
'<flag-name>': {
description: '<what this gates>',
fallback: '<FLAG_SECRET>',
},
}
fallback is the env/secret key (typed as keyof typeof env), so add <FLAG_SECRET> to apps/sim/lib/core/config/env.ts first (and the deployment's secret store) — it won't typecheck otherwise. Do not add workspace/org/user/admin defaults here — that gating exists only in AppConfig. Adding the entry makes <flag-name> a valid FeatureFlagName.
Gate the call site at the chosen granularity. For the recommended global mode, pass no context:
import { isFeatureEnabled } from '@/lib/core/config/feature-flags'
if (await isFeatureEnabled('<flag-name>')) {
// gated behavior
}
Do not fetch, resolve, or thread through user or organization context solely for a global flag.
For scoped rollout, pass only the dimensions the user selected. Admin status is resolved internally, so ordinary callers pass userId, not a role:
import { isFeatureEnabled } from '@/lib/core/config/feature-flags'
if (await isFeatureEnabled('<flag-name>', { workspaceId, userId, orgId })) {
// gated behavior
}
workspaceId; organization targeting uses orgId; user and platform-admin targeting require userId.userId, the admin clause resolves to false without a DB read.{ userId, isAdmin: true } to skip the role lookup.(Prod) configure in AppConfig. The infra feature-flags profile schema is permissive, so a new flag needs no infra change. Operators add the flag to the hosted feature-flags document using enabled for global rollout or only the selected workspaceIds/orgIds/userIds/adminEnabled clauses for scoped rollout, then start a sim-<env>-fast deployment (see the AppConfig runbook in the infra README — same flow as access-control). The fallback secret only applies when AppConfig is disabled.
Test only new evaluation logic. A flag that reuses the existing clauses is already covered by apps/sim/lib/core/config/feature-flags.test.ts; add no per-flag case. When you change how flags evaluate (a new clause kind, a new fallback path), add a case there that passes the test-audit authoring gate.
Clean up after rollout. When the feature ships to everyone, delete the flag's entry from FEATURE_FLAGS, the <FLAG_SECRET> env entry, the AppConfig document, and the call sites. Leaving dead flags around is the main failure mode of flag systems.
kebab-case.fetch or a new AppConfig client — always go through isFeatureEnabled / getFeatureFlags.dbReplica) and is resolved lazily, so an admin-gated flag adds at most one cheap replica read, and only when adminEnabled is the deciding clause.