@agent-native/core 0.107.1 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/actions.mdx +48 -0
- package/corpus/core/docs/content/locales/ar-SA/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/de-DE/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/es-ES/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/fr-FR/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/hi-IN/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/ja-JP/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/ko-KR/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/pt-BR/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/zh-CN/actions.mdx +38 -0
- package/corpus/core/docs/content/locales/zh-TW/actions.mdx +38 -0
- package/corpus/core/package.json +5 -1
- package/corpus/core/src/a2a/artifact-response.ts +32 -10
- package/corpus/core/src/a2a-claims.ts +52 -0
- package/corpus/core/src/action.ts +6 -2
- package/corpus/core/src/audit/record.ts +6 -0
- package/corpus/core/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
- package/corpus/core/src/client/feature-flags/helpers.ts +77 -0
- package/corpus/core/src/client/feature-flags/index.ts +13 -0
- package/corpus/core/src/client/feature-flags/types.ts +29 -0
- package/corpus/core/src/client/feature-flags/use-feature-flag.ts +26 -0
- package/corpus/core/src/client/index.ts +11 -0
- package/corpus/core/src/extensions/routes.ts +1 -1
- package/corpus/core/src/feature-flags/a2a-action-route.ts +56 -0
- package/corpus/core/src/feature-flags/actions/get-feature-flags.ts +24 -0
- package/corpus/core/src/feature-flags/actions/list-feature-flags.ts +69 -0
- package/corpus/core/src/feature-flags/actions/set-feature-flag.ts +89 -0
- package/corpus/core/src/feature-flags/index.ts +21 -0
- package/corpus/core/src/feature-flags/permissions.ts +53 -0
- package/corpus/core/src/feature-flags/plugin.ts +44 -0
- package/corpus/core/src/feature-flags/registry.ts +96 -0
- package/corpus/core/src/feature-flags/store.ts +176 -0
- package/corpus/core/src/index.ts +15 -0
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +107 -3
- package/corpus/core/src/integrations/pending-tasks-store.ts +98 -1
- package/corpus/core/src/integrations/plugin.ts +129 -4
- package/corpus/core/src/integrations/webhook-handler.ts +339 -36
- package/corpus/core/src/localization/default-messages.ts +47 -0
- package/corpus/core/src/server/action-discovery.ts +12 -0
- package/corpus/core/src/server/action-routes.ts +47 -5
- package/corpus/core/src/server/agent-chat-plugin.ts +93 -8
- package/corpus/core/src/server/index.ts +1 -0
- package/corpus/core/src/settings/org-settings.ts +13 -0
- package/corpus/core/src/settings/store.ts +57 -0
- package/corpus/core/src/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/default/AGENTS.md +1 -0
- package/corpus/core/src/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/core/src/templates/workspace-core/AGENTS.md +1 -1
- package/corpus/core/src/templates/workspace-root/AGENTS.md +1 -1
- package/corpus/core/src/vite/action-types-plugin.ts +12 -0
- package/corpus/templates/analytics/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/analytics/AGENTS.md +15 -3
- package/corpus/templates/analytics/actions/list-workspace-feature-flags.ts +15 -0
- package/corpus/templates/analytics/actions/navigate.ts +2 -2
- package/corpus/templates/analytics/actions/set-workspace-feature-flag.ts +45 -0
- package/corpus/templates/analytics/actions/view-screen.ts +13 -0
- package/corpus/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +243 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +11 -3
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +3 -1
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +17 -0
- package/corpus/templates/analytics/app/i18n-data.ts +251 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +22 -2
- package/corpus/templates/analytics/changelog/2026-07-17-manage-feature-flag-rollouts-across-your-organization-s-apps.md +6 -0
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +13 -5
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +347 -0
- package/corpus/templates/assets/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/brain/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/calendar/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/clips/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/clips/server/plugins/feature-flags.ts +11 -0
- package/corpus/templates/clips/shared/feature-flags.ts +30 -37
- package/corpus/templates/content/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/design/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/design/AGENTS.md +5 -3
- package/corpus/templates/design/actions/add-fusion-screens.ts +4 -6
- package/corpus/templates/design/actions/apply-fusion-edits.ts +4 -6
- package/corpus/templates/design/actions/create-fusion-app.ts +5 -4
- package/corpus/templates/design/actions/deploy-fusion-app.ts +4 -3
- package/corpus/templates/design/actions/get-fusion-deploy-status.ts +4 -6
- package/corpus/templates/design/actions/list-fusion-edits.ts +4 -3
- package/corpus/templates/design/actions/push-fusion-app.ts +4 -6
- package/corpus/templates/design/actions/queue-fusion-edit.ts +4 -3
- package/corpus/templates/design/actions/send-fusion-message.ts +4 -6
- package/corpus/templates/design/actions/sync-fusion-app.ts +4 -3
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +1 -1
- package/corpus/templates/design/app/pages/Index.tsx +8 -6
- package/corpus/templates/design/server/plugins/feature-flags.ts +5 -0
- package/corpus/templates/design/shared/full-app.ts +10 -7
- package/corpus/templates/dispatch/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/forms/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/macros/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/mail/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/plan/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/slides/.agents/skills/feature-flags/SKILL.md +169 -0
- package/corpus/templates/tasks/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/a2a/artifact-response.d.ts +5 -1
- package/dist/a2a/artifact-response.d.ts.map +1 -1
- package/dist/a2a/artifact-response.js +18 -12
- package/dist/a2a/artifact-response.js.map +1 -1
- package/dist/a2a-claims.d.ts +10 -0
- package/dist/a2a-claims.d.ts.map +1 -0
- package/dist/a2a-claims.js +41 -0
- package/dist/a2a-claims.js.map +1 -0
- package/dist/action.d.ts +6 -2
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/audit/record.d.ts +3 -0
- package/dist/audit/record.d.ts.map +1 -1
- package/dist/audit/record.js +3 -0
- package/dist/audit/record.js.map +1 -1
- package/dist/client/feature-flags/FeatureFlagsPanel.d.ts +10 -0
- package/dist/client/feature-flags/FeatureFlagsPanel.d.ts.map +1 -0
- package/dist/client/feature-flags/FeatureFlagsPanel.js +143 -0
- package/dist/client/feature-flags/FeatureFlagsPanel.js.map +1 -0
- package/dist/client/feature-flags/helpers.d.ts +16 -0
- package/dist/client/feature-flags/helpers.d.ts.map +1 -0
- package/dist/client/feature-flags/helpers.js +50 -0
- package/dist/client/feature-flags/helpers.js.map +1 -0
- package/dist/client/feature-flags/index.d.ts +5 -0
- package/dist/client/feature-flags/index.d.ts.map +1 -0
- package/dist/client/feature-flags/index.js +4 -0
- package/dist/client/feature-flags/index.js.map +1 -0
- package/dist/client/feature-flags/types.d.ts +27 -0
- package/dist/client/feature-flags/types.d.ts.map +1 -0
- package/dist/client/feature-flags/types.js +2 -0
- package/dist/client/feature-flags/types.js.map +1 -0
- package/dist/client/feature-flags/use-feature-flag.d.ts +8 -0
- package/dist/client/feature-flags/use-feature-flag.d.ts.map +1 -0
- package/dist/client/feature-flags/use-feature-flag.js +15 -0
- package/dist/client/feature-flags/use-feature-flag.js.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +1 -1
- package/dist/extensions/routes.js.map +1 -1
- package/dist/feature-flags/a2a-action-route.d.ts +14 -0
- package/dist/feature-flags/a2a-action-route.d.ts.map +1 -0
- package/dist/feature-flags/a2a-action-route.js +50 -0
- package/dist/feature-flags/a2a-action-route.js.map +1 -0
- package/dist/feature-flags/actions/get-feature-flags.d.ts +3 -0
- package/dist/feature-flags/actions/get-feature-flags.d.ts.map +1 -0
- package/dist/feature-flags/actions/get-feature-flags.js +18 -0
- package/dist/feature-flags/actions/get-feature-flags.js.map +1 -0
- package/dist/feature-flags/actions/list-feature-flags.d.ts +28 -0
- package/dist/feature-flags/actions/list-feature-flags.d.ts.map +1 -0
- package/dist/feature-flags/actions/list-feature-flags.js +60 -0
- package/dist/feature-flags/actions/list-feature-flags.js.map +1 -0
- package/dist/feature-flags/actions/set-feature-flag.d.ts +26 -0
- package/dist/feature-flags/actions/set-feature-flag.d.ts.map +1 -0
- package/dist/feature-flags/actions/set-feature-flag.js +78 -0
- package/dist/feature-flags/actions/set-feature-flag.js.map +1 -0
- package/dist/feature-flags/index.d.ts +5 -0
- package/dist/feature-flags/index.d.ts.map +1 -0
- package/dist/feature-flags/index.js +5 -0
- package/dist/feature-flags/index.js.map +1 -0
- package/dist/feature-flags/permissions.d.ts +13 -0
- package/dist/feature-flags/permissions.d.ts.map +1 -0
- package/dist/feature-flags/permissions.js +37 -0
- package/dist/feature-flags/permissions.js.map +1 -0
- package/dist/feature-flags/plugin.d.ts +17 -0
- package/dist/feature-flags/plugin.d.ts.map +1 -0
- package/dist/feature-flags/plugin.js +29 -0
- package/dist/feature-flags/plugin.js.map +1 -0
- package/dist/feature-flags/registry.d.ts +23 -0
- package/dist/feature-flags/registry.d.ts.map +1 -0
- package/dist/feature-flags/registry.js +59 -0
- package/dist/feature-flags/registry.js.map +1 -0
- package/dist/feature-flags/store.d.ts +31 -0
- package/dist/feature-flags/store.d.ts.map +1 -0
- package/dist/feature-flags/store.js +124 -0
- package/dist/feature-flags/store.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +62 -5
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/pending-tasks-store.d.ts +3 -0
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-store.js +75 -1
- package/dist/integrations/pending-tasks-store.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +81 -5
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +23 -2
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +257 -35
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +42 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +42 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +12 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts +3 -0
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +45 -5
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +6 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +71 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/settings/org-settings.d.ts +2 -0
- package/dist/settings/org-settings.d.ts.map +1 -1
- package/dist/settings/org-settings.js +5 -1
- package/dist/settings/org-settings.js.map +1 -1
- package/dist/settings/store.d.ts +8 -0
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +48 -0
- package/dist/settings/store.js.map +1 -1
- package/dist/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/default/AGENTS.md +1 -0
- package/dist/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
- package/dist/templates/workspace-core/AGENTS.md +1 -1
- package/dist/templates/workspace-root/AGENTS.md +1 -1
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +12 -0
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/docs/content/actions.mdx +48 -0
- package/docs/content/locales/ar-SA/actions.mdx +38 -0
- package/docs/content/locales/de-DE/actions.mdx +38 -0
- package/docs/content/locales/es-ES/actions.mdx +38 -0
- package/docs/content/locales/fr-FR/actions.mdx +38 -0
- package/docs/content/locales/hi-IN/actions.mdx +38 -0
- package/docs/content/locales/ja-JP/actions.mdx +38 -0
- package/docs/content/locales/ko-KR/actions.mdx +38 -0
- package/docs/content/locales/pt-BR/actions.mdx +38 -0
- package/docs/content/locales/zh-CN/actions.mdx +38 -0
- package/docs/content/locales/zh-TW/actions.mdx +38 -0
- package/package.json +5 -1
- package/src/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/default/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/default/AGENTS.md +1 -0
- package/src/templates/headless/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/workspace-core/.agents/skills/feature-flags/SKILL.md +169 -0
- package/src/templates/workspace-core/AGENTS.md +1 -1
- package/src/templates/workspace-root/AGENTS.md +1 -1
- package/corpus/templates/clips/actions/get-feature-flags.ts +0 -30
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineAction } from "../../action.js";
|
|
3
|
+
import { requireFeatureFlagManager } from "../permissions.js";
|
|
4
|
+
import { getFeatureFlagDefinition } from "../registry.js";
|
|
5
|
+
import { defaultFeatureFlagRules, mutateFeatureFlagRules, normalizeFeatureFlagRules, } from "../store.js";
|
|
6
|
+
const rulesSchema = z.object({
|
|
7
|
+
mode: z.enum(["off", "on", "rules"]),
|
|
8
|
+
emails: z.array(z.string().email()).max(500).optional(),
|
|
9
|
+
orgIds: z.array(z.string().min(1).max(200)).max(500).optional(),
|
|
10
|
+
percentage: z.number().int().min(0).max(100).optional(),
|
|
11
|
+
});
|
|
12
|
+
const schema = z.discriminatedUnion("operation", [
|
|
13
|
+
z.object({
|
|
14
|
+
operation: z.literal("enable-for-current-user"),
|
|
15
|
+
key: z.string(),
|
|
16
|
+
}),
|
|
17
|
+
z.object({ operation: z.literal("off"), key: z.string() }),
|
|
18
|
+
z.object({
|
|
19
|
+
operation: z.literal("replace-rules"),
|
|
20
|
+
key: z.string(),
|
|
21
|
+
rules: rulesSchema,
|
|
22
|
+
}),
|
|
23
|
+
]);
|
|
24
|
+
export default defineAction({
|
|
25
|
+
description: "Atomically manage one registered feature flag: enable it for the current user, turn it off immediately for the active scope, or replace its full rules. Organization owner/admin only (or the explicit no-org administrator).",
|
|
26
|
+
schema,
|
|
27
|
+
// Keep the strict discriminated union for runtime validation, but advertise
|
|
28
|
+
// an object-shaped schema so agent tool registries can expose the action.
|
|
29
|
+
// Root-level JSON Schema unions are intentionally rejected by the agent.
|
|
30
|
+
agentInputSchema: z.object({
|
|
31
|
+
operation: z.enum(["enable-for-current-user", "off", "replace-rules"]),
|
|
32
|
+
key: z.string(),
|
|
33
|
+
rules: rulesSchema.optional(),
|
|
34
|
+
}),
|
|
35
|
+
toolCallable: false,
|
|
36
|
+
audit: {
|
|
37
|
+
target: (args, _result, meta) => ({
|
|
38
|
+
type: "feature-flag",
|
|
39
|
+
id: args.key,
|
|
40
|
+
ownerEmail: meta.userEmail,
|
|
41
|
+
visibility: meta.orgId ? "org" : "private",
|
|
42
|
+
}),
|
|
43
|
+
summary: (args) => `Feature flag ${args.key}: ${args.operation}`,
|
|
44
|
+
},
|
|
45
|
+
run: async (args, ctx) => {
|
|
46
|
+
const manager = await requireFeatureFlagManager(ctx ?? {});
|
|
47
|
+
if (!getFeatureFlagDefinition(args.key)) {
|
|
48
|
+
throw new Error(`Unknown feature flag: ${args.key}`);
|
|
49
|
+
}
|
|
50
|
+
const persistedRules = await mutateFeatureFlagRules(args.key, manager, (current) => {
|
|
51
|
+
let rules;
|
|
52
|
+
if (args.operation === "off") {
|
|
53
|
+
rules = defaultFeatureFlagRules();
|
|
54
|
+
}
|
|
55
|
+
else if (args.operation === "replace-rules") {
|
|
56
|
+
rules = normalizeFeatureFlagRules(args.rules);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
rules = normalizeFeatureFlagRules({
|
|
60
|
+
...current,
|
|
61
|
+
// A globally-on flag already includes this user. Do not
|
|
62
|
+
// accidentally narrow it to a one-email rollout.
|
|
63
|
+
mode: current.mode === "on" ? "on" : "rules",
|
|
64
|
+
emails: [...current.emails, manager.email],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return { ...rules, updatedAt: Date.now(), updatedBy: manager.email };
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
contractVersion: 1,
|
|
71
|
+
status: "ready",
|
|
72
|
+
key: args.key,
|
|
73
|
+
rules: persistedRules,
|
|
74
|
+
scope: { orgId: manager.orgId },
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=set-feature-flag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-feature-flag.js","sourceRoot":"","sources":["../../../src/feature-flags/actions/set-feature-flag.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { requireFeatureFlagManager } from \"../permissions.js\";\nimport { getFeatureFlagDefinition } from \"../registry.js\";\nimport {\n defaultFeatureFlagRules,\n mutateFeatureFlagRules,\n normalizeFeatureFlagRules,\n} from \"../store.js\";\n\nconst rulesSchema = z.object({\n mode: z.enum([\"off\", \"on\", \"rules\"]),\n emails: z.array(z.string().email()).max(500).optional(),\n orgIds: z.array(z.string().min(1).max(200)).max(500).optional(),\n percentage: z.number().int().min(0).max(100).optional(),\n});\n\nconst schema = z.discriminatedUnion(\"operation\", [\n z.object({\n operation: z.literal(\"enable-for-current-user\"),\n key: z.string(),\n }),\n z.object({ operation: z.literal(\"off\"), key: z.string() }),\n z.object({\n operation: z.literal(\"replace-rules\"),\n key: z.string(),\n rules: rulesSchema,\n }),\n]);\n\nexport default defineAction({\n description:\n \"Atomically manage one registered feature flag: enable it for the current user, turn it off immediately for the active scope, or replace its full rules. Organization owner/admin only (or the explicit no-org administrator).\",\n schema,\n // Keep the strict discriminated union for runtime validation, but advertise\n // an object-shaped schema so agent tool registries can expose the action.\n // Root-level JSON Schema unions are intentionally rejected by the agent.\n agentInputSchema: z.object({\n operation: z.enum([\"enable-for-current-user\", \"off\", \"replace-rules\"]),\n key: z.string(),\n rules: rulesSchema.optional(),\n }),\n toolCallable: false,\n audit: {\n target: (args, _result, meta) => ({\n type: \"feature-flag\",\n id: args.key,\n ownerEmail: meta.userEmail,\n visibility: meta.orgId ? \"org\" : \"private\",\n }),\n summary: (args) => `Feature flag ${args.key}: ${args.operation}`,\n },\n run: async (args, ctx) => {\n const manager = await requireFeatureFlagManager(ctx ?? {});\n if (!getFeatureFlagDefinition(args.key)) {\n throw new Error(`Unknown feature flag: ${args.key}`);\n }\n\n const persistedRules = await mutateFeatureFlagRules(\n args.key,\n manager,\n (current) => {\n let rules;\n if (args.operation === \"off\") {\n rules = defaultFeatureFlagRules();\n } else if (args.operation === \"replace-rules\") {\n rules = normalizeFeatureFlagRules(args.rules);\n } else {\n rules = normalizeFeatureFlagRules({\n ...current,\n // A globally-on flag already includes this user. Do not\n // accidentally narrow it to a one-email rollout.\n mode: current.mode === \"on\" ? \"on\" : \"rules\",\n emails: [...current.emails, manager.email],\n });\n }\n return { ...rules, updatedAt: Date.now(), updatedBy: manager.email };\n },\n );\n return {\n contractVersion: 1 as const,\n status: \"ready\" as const,\n key: args.key,\n rules: persistedRules,\n scope: { orgId: manager.orgId },\n };\n },\n});\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, } from "./registry.js";
|
|
2
|
+
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./store.js";
|
|
3
|
+
export { createFeatureFlagsPlugin } from "./plugin.js";
|
|
4
|
+
export { createFeatureFlagA2AActionRouteAuth } from "./a2a-action-route.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feature-flags/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,mCAAmC,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, } from "./registry.js";
|
|
2
|
+
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, } from "./store.js";
|
|
3
|
+
export { createFeatureFlagsPlugin } from "./plugin.js";
|
|
4
|
+
export { createFeatureFlagA2AActionRouteAuth } from "./a2a-action-route.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/feature-flags/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,GAI1B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,mCAAmC,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["export {\n defineFeatureFlag,\n defineFeatureFlags,\n getFeatureFlagDefinition,\n listFeatureFlags,\n registerFeatureFlags,\n type FeatureFlagDefinition,\n} from \"./registry.js\";\nexport {\n defaultFeatureFlagRules,\n evaluateFeatureFlag,\n evaluateFeatureFlagRules,\n isFeatureFlagEnabled,\n getFeatureFlagRules,\n normalizeFeatureFlagRules,\n type FeatureFlagMode,\n type FeatureFlagRules,\n type FeatureFlagScope,\n} from \"./store.js\";\nexport { createFeatureFlagsPlugin } from \"./plugin.js\";\nexport { createFeatureFlagA2AActionRouteAuth } from \"./a2a-action-route.js\";\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class FeatureFlagPermissionError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
constructor(message: string, statusCode: number);
|
|
4
|
+
}
|
|
5
|
+
/** Require an org admin/owner, or an explicit production no-org allowlist entry. */
|
|
6
|
+
export declare function requireFeatureFlagManager(scope: {
|
|
7
|
+
userEmail?: string;
|
|
8
|
+
orgId?: string | null;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
email: string;
|
|
11
|
+
orgId: string | null;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/feature-flags/permissions.ts"],"names":[],"mappings":"AAGA,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,UAAU,EAAE,MAAM,CAAC;IAEnB,YAAY,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAG9C;CACF;AAWD,oFAAoF;AACpF,wBAAsB,yBAAyB,CAAC,KAAK,EAAE;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA2BnD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getOrgRoleForEmail } from "../mcp/actions/service-token-access.js";
|
|
2
|
+
import { canManageOrg } from "../org/permissions.js";
|
|
3
|
+
export class FeatureFlagPermissionError extends Error {
|
|
4
|
+
statusCode;
|
|
5
|
+
constructor(message, statusCode) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function productionAdminAllowlist() {
|
|
11
|
+
return new Set((process.env.AGENT_NATIVE_FEATURE_FLAG_ADMIN_EMAILS ?? "")
|
|
12
|
+
.split(",")
|
|
13
|
+
.map((email) => email.trim().toLowerCase())
|
|
14
|
+
.filter(Boolean));
|
|
15
|
+
}
|
|
16
|
+
/** Require an org admin/owner, or an explicit production no-org allowlist entry. */
|
|
17
|
+
export async function requireFeatureFlagManager(scope) {
|
|
18
|
+
const email = scope.userEmail?.trim().toLowerCase();
|
|
19
|
+
if (!email) {
|
|
20
|
+
throw new FeatureFlagPermissionError("Sign in to manage feature flags.", 401);
|
|
21
|
+
}
|
|
22
|
+
const orgId = scope.orgId?.trim() || null;
|
|
23
|
+
if (orgId) {
|
|
24
|
+
const role = await getOrgRoleForEmail(orgId, email);
|
|
25
|
+
if (!canManageOrg(role)) {
|
|
26
|
+
throw new FeatureFlagPermissionError("Only organization owners or admins can manage feature flags.", 403);
|
|
27
|
+
}
|
|
28
|
+
return { email, orgId };
|
|
29
|
+
}
|
|
30
|
+
if (process.env.NODE_ENV !== "production")
|
|
31
|
+
return { email, orgId: null };
|
|
32
|
+
if (!productionAdminAllowlist().has(email)) {
|
|
33
|
+
throw new FeatureFlagPermissionError("Feature flag management without an organization requires an explicit admin allowlist entry.", 403);
|
|
34
|
+
}
|
|
35
|
+
return { email, orgId: null };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/feature-flags/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,UAAU,CAAS;IAEnB,YAAY,OAAe,EAAE,UAAkB;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED,SAAS,wBAAwB;IAC/B,OAAO,IAAI,GAAG,CACZ,CAAC,OAAO,CAAC,GAAG,CAAC,sCAAsC,IAAI,EAAE,CAAC;SACvD,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;SAC1C,MAAM,CAAC,OAAO,CAAC,CACnB,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAG/C;IACC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,0BAA0B,CAClC,kCAAkC,EAClC,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAC1C,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,0BAA0B,CAClC,8DAA8D,EAC9D,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzE,IAAI,CAAC,wBAAwB,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,0BAA0B,CAClC,6FAA6F,EAC7F,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAChC,CAAC","sourcesContent":["import { getOrgRoleForEmail } from \"../mcp/actions/service-token-access.js\";\nimport { canManageOrg } from \"../org/permissions.js\";\n\nexport class FeatureFlagPermissionError extends Error {\n statusCode: number;\n\n constructor(message: string, statusCode: number) {\n super(message);\n this.statusCode = statusCode;\n }\n}\n\nfunction productionAdminAllowlist(): Set<string> {\n return new Set(\n (process.env.AGENT_NATIVE_FEATURE_FLAG_ADMIN_EMAILS ?? \"\")\n .split(\",\")\n .map((email) => email.trim().toLowerCase())\n .filter(Boolean),\n );\n}\n\n/** Require an org admin/owner, or an explicit production no-org allowlist entry. */\nexport async function requireFeatureFlagManager(scope: {\n userEmail?: string;\n orgId?: string | null;\n}): Promise<{ email: string; orgId: string | null }> {\n const email = scope.userEmail?.trim().toLowerCase();\n if (!email) {\n throw new FeatureFlagPermissionError(\n \"Sign in to manage feature flags.\",\n 401,\n );\n }\n const orgId = scope.orgId?.trim() || null;\n if (orgId) {\n const role = await getOrgRoleForEmail(orgId, email);\n if (!canManageOrg(role)) {\n throw new FeatureFlagPermissionError(\n \"Only organization owners or admins can manage feature flags.\",\n 403,\n );\n }\n return { email, orgId };\n }\n if (process.env.NODE_ENV !== \"production\") return { email, orgId: null };\n if (!productionAdminAllowlist().has(email)) {\n throw new FeatureFlagPermissionError(\n \"Feature flag management without an organization requires an explicit admin allowlist entry.\",\n 403,\n );\n }\n return { email, orgId: null };\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type FeatureFlagDefinition } from "./registry.js";
|
|
2
|
+
type NitroPluginDef = (nitroApp: any) => void | Promise<void>;
|
|
3
|
+
/** A tiny startup plugin for app-local, explicit feature-flag registration. */
|
|
4
|
+
export declare function createFeatureFlagsPlugin(options: {
|
|
5
|
+
flags: readonly FeatureFlagDefinition[];
|
|
6
|
+
/**
|
|
7
|
+
* One-time compatibility bridge for apps that previously stored global
|
|
8
|
+
* booleans together in a single settings object. Only legacy `true` values
|
|
9
|
+
* are copied, and an explicit rule in the new store always wins.
|
|
10
|
+
*/
|
|
11
|
+
legacyBooleanSetting?: {
|
|
12
|
+
settingKey: string;
|
|
13
|
+
flagKeys: readonly string[];
|
|
14
|
+
};
|
|
15
|
+
}): NitroPluginDef;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/feature-flags/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAGvB,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D,+EAA+E;AAC/E,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAChD,KAAK,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACxC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;KAC7B,CAAC;CACH,GAAG,cAAc,CAsBjB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getSetting } from "../settings/store.js";
|
|
2
|
+
import { registerFeatureFlags, } from "./registry.js";
|
|
3
|
+
import { mutateFeatureFlagRules } from "./store.js";
|
|
4
|
+
/** A tiny startup plugin for app-local, explicit feature-flag registration. */
|
|
5
|
+
export function createFeatureFlagsPlugin(options) {
|
|
6
|
+
return async () => {
|
|
7
|
+
registerFeatureFlags(options.flags);
|
|
8
|
+
if (!options.legacyBooleanSetting)
|
|
9
|
+
return;
|
|
10
|
+
const legacy = await getSetting(options.legacyBooleanSetting.settingKey);
|
|
11
|
+
if (!legacy)
|
|
12
|
+
return;
|
|
13
|
+
await Promise.all(options.legacyBooleanSetting.flagKeys.map(async (key) => {
|
|
14
|
+
if (legacy[key] !== true)
|
|
15
|
+
return;
|
|
16
|
+
await mutateFeatureFlagRules(key, {}, (current) => {
|
|
17
|
+
if (current.updatedAt !== null)
|
|
18
|
+
return current;
|
|
19
|
+
return {
|
|
20
|
+
...current,
|
|
21
|
+
mode: "on",
|
|
22
|
+
updatedAt: Date.now(),
|
|
23
|
+
updatedBy: "legacy-settings-migration",
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}));
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/feature-flags/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAIpD,+EAA+E;AAC/E,MAAM,UAAU,wBAAwB,CAAC,OAWxC;IACC,OAAO,KAAK,IAAI,EAAE;QAChB,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,oBAAoB;YAAE,OAAO;QAE1C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACtD,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI;gBAAE,OAAO;YACjC,MAAM,sBAAsB,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE;gBAChD,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI;oBAAE,OAAO,OAAO,CAAC;gBAC/C,OAAO;oBACL,GAAG,OAAO;oBACV,IAAI,EAAE,IAAI;oBACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,SAAS,EAAE,2BAA2B;iBACvC,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { getSetting } from \"../settings/store.js\";\nimport {\n registerFeatureFlags,\n type FeatureFlagDefinition,\n} from \"./registry.js\";\nimport { mutateFeatureFlagRules } from \"./store.js\";\n\ntype NitroPluginDef = (nitroApp: any) => void | Promise<void>;\n\n/** A tiny startup plugin for app-local, explicit feature-flag registration. */\nexport function createFeatureFlagsPlugin(options: {\n flags: readonly FeatureFlagDefinition[];\n /**\n * One-time compatibility bridge for apps that previously stored global\n * booleans together in a single settings object. Only legacy `true` values\n * are copied, and an explicit rule in the new store always wins.\n */\n legacyBooleanSetting?: {\n settingKey: string;\n flagKeys: readonly string[];\n };\n}): NitroPluginDef {\n return async () => {\n registerFeatureFlags(options.flags);\n if (!options.legacyBooleanSetting) return;\n\n const legacy = await getSetting(options.legacyBooleanSetting.settingKey);\n if (!legacy) return;\n await Promise.all(\n options.legacyBooleanSetting.flagKeys.map(async (key) => {\n if (legacy[key] !== true) return;\n await mutateFeatureFlagRules(key, {}, (current) => {\n if (current.updatedAt !== null) return current;\n return {\n ...current,\n mode: \"on\",\n updatedAt: Date.now(),\n updatedBy: \"legacy-settings-migration\",\n };\n });\n }),\n );\n };\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App-owned feature-flag definitions. Core intentionally starts with an empty
|
|
3
|
+
* registry: a flag key is part of an app's stable contract, not framework
|
|
4
|
+
* configuration that Core should guess at.
|
|
5
|
+
*/
|
|
6
|
+
export interface FeatureFlagDefinition {
|
|
7
|
+
key: string;
|
|
8
|
+
/** Boolean flags are always default-off; explicit in operator metadata. */
|
|
9
|
+
defaultValue?: false;
|
|
10
|
+
displayName?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Define one app-local feature flag for registration at server startup. */
|
|
14
|
+
export declare function defineFeatureFlag(definition: FeatureFlagDefinition): FeatureFlagDefinition;
|
|
15
|
+
/** Define a small app-owned feature-flag registry. */
|
|
16
|
+
export declare function defineFeatureFlags(definitions: readonly FeatureFlagDefinition[]): readonly FeatureFlagDefinition[];
|
|
17
|
+
/** Register definitions once at Nitro startup. Re-registering identical data is safe for HMR. */
|
|
18
|
+
export declare function registerFeatureFlags(definitions: readonly FeatureFlagDefinition[]): void;
|
|
19
|
+
export declare function listFeatureFlags(): readonly FeatureFlagDefinition[];
|
|
20
|
+
export declare function getFeatureFlagDefinition(key: string): FeatureFlagDefinition | null;
|
|
21
|
+
/** Test-only registry reset; not exported from package entrypoints. */
|
|
22
|
+
export declare function _resetFeatureFlagRegistryForTests(): void;
|
|
23
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/feature-flags/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAyBD,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,qBAAqB,GAChC,qBAAqB,CAEvB;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,SAAS,qBAAqB,EAAE,GAC5C,SAAS,qBAAqB,EAAE,CAYlC;AAED,iGAAiG;AACjG,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,SAAS,qBAAqB,EAAE,GAC5C,IAAI,CAiBN;AAED,wBAAgB,gBAAgB,IAAI,SAAS,qBAAqB,EAAE,CAEnE;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,GACV,qBAAqB,GAAG,IAAI,CAE9B;AAED,uEAAuE;AACvE,wBAAgB,iCAAiC,IAAI,IAAI,CAExD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
function normalizeDefinition(definition) {
|
|
3
|
+
const key = definition.key.trim();
|
|
4
|
+
if (!/^[A-Za-z][A-Za-z0-9._-]{0,63}$/.test(key)) {
|
|
5
|
+
throw new Error("Feature flag keys must be stable strings containing only letters, numbers, dots, underscores, or hyphens (1-64 characters).");
|
|
6
|
+
}
|
|
7
|
+
return {
|
|
8
|
+
key,
|
|
9
|
+
defaultValue: false,
|
|
10
|
+
...(definition.displayName?.trim() && {
|
|
11
|
+
displayName: definition.displayName.trim(),
|
|
12
|
+
}),
|
|
13
|
+
...(definition.description?.trim() && {
|
|
14
|
+
description: definition.description.trim(),
|
|
15
|
+
}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Define one app-local feature flag for registration at server startup. */
|
|
19
|
+
export function defineFeatureFlag(definition) {
|
|
20
|
+
return Object.freeze(normalizeDefinition(definition));
|
|
21
|
+
}
|
|
22
|
+
/** Define a small app-owned feature-flag registry. */
|
|
23
|
+
export function defineFeatureFlags(definitions) {
|
|
24
|
+
const seen = new Set();
|
|
25
|
+
return Object.freeze(definitions.map((definition) => {
|
|
26
|
+
const normalized = defineFeatureFlag(definition);
|
|
27
|
+
if (seen.has(normalized.key)) {
|
|
28
|
+
throw new Error(`Duplicate feature flag key: ${normalized.key}`);
|
|
29
|
+
}
|
|
30
|
+
seen.add(normalized.key);
|
|
31
|
+
return normalized;
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
/** Register definitions once at Nitro startup. Re-registering identical data is safe for HMR. */
|
|
35
|
+
export function registerFeatureFlags(definitions) {
|
|
36
|
+
for (const rawDefinition of definitions) {
|
|
37
|
+
const definition = defineFeatureFlag(rawDefinition);
|
|
38
|
+
const existing = registry.get(definition.key);
|
|
39
|
+
if (!existing) {
|
|
40
|
+
registry.set(definition.key, definition);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (existing.displayName !== definition.displayName ||
|
|
44
|
+
existing.description !== definition.description) {
|
|
45
|
+
throw new Error(`Feature flag ${definition.key} was registered with conflicting metadata.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function listFeatureFlags() {
|
|
50
|
+
return [...registry.values()].sort((a, b) => a.key.localeCompare(b.key));
|
|
51
|
+
}
|
|
52
|
+
export function getFeatureFlagDefinition(key) {
|
|
53
|
+
return registry.get(key) ?? null;
|
|
54
|
+
}
|
|
55
|
+
/** Test-only registry reset; not exported from package entrypoints. */
|
|
56
|
+
export function _resetFeatureFlagRegistryForTests() {
|
|
57
|
+
registry.clear();
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/feature-flags/registry.ts"],"names":[],"mappings":"AAaA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAC;AAE1D,SAAS,mBAAmB,CAC1B,UAAiC;IAEjC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,6HAA6H,CAC9H,CAAC;IACJ,CAAC;IACD,OAAO;QACL,GAAG;QACH,YAAY,EAAE,KAAK;QACnB,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI;YACpC,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE;SAC3C,CAAC;QACF,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI;YACpC,WAAW,EAAE,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE;SAC3C,CAAC;KACH,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,iBAAiB,CAC/B,UAAiC;IAEjC,OAAO,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,kBAAkB,CAChC,WAA6C;IAE7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,MAAM,CAAC,MAAM,CAClB,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QAC7B,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,oBAAoB,CAClC,WAA6C;IAE7C,KAAK,MAAM,aAAa,IAAI,WAAW,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,IACE,QAAQ,CAAC,WAAW,KAAK,UAAU,CAAC,WAAW;YAC/C,QAAQ,CAAC,WAAW,KAAK,UAAU,CAAC,WAAW,EAC/C,CAAC;YACD,MAAM,IAAI,KAAK,CACb,gBAAgB,UAAU,CAAC,GAAG,4CAA4C,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,GAAW;IAEX,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,iCAAiC;IAC/C,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC","sourcesContent":["/**\n * App-owned feature-flag definitions. Core intentionally starts with an empty\n * registry: a flag key is part of an app's stable contract, not framework\n * configuration that Core should guess at.\n */\nexport interface FeatureFlagDefinition {\n key: string;\n /** Boolean flags are always default-off; explicit in operator metadata. */\n defaultValue?: false;\n displayName?: string;\n description?: string;\n}\n\nconst registry = new Map<string, FeatureFlagDefinition>();\n\nfunction normalizeDefinition(\n definition: FeatureFlagDefinition,\n): FeatureFlagDefinition {\n const key = definition.key.trim();\n if (!/^[A-Za-z][A-Za-z0-9._-]{0,63}$/.test(key)) {\n throw new Error(\n \"Feature flag keys must be stable strings containing only letters, numbers, dots, underscores, or hyphens (1-64 characters).\",\n );\n }\n return {\n key,\n defaultValue: false,\n ...(definition.displayName?.trim() && {\n displayName: definition.displayName.trim(),\n }),\n ...(definition.description?.trim() && {\n description: definition.description.trim(),\n }),\n };\n}\n\n/** Define one app-local feature flag for registration at server startup. */\nexport function defineFeatureFlag(\n definition: FeatureFlagDefinition,\n): FeatureFlagDefinition {\n return Object.freeze(normalizeDefinition(definition));\n}\n\n/** Define a small app-owned feature-flag registry. */\nexport function defineFeatureFlags(\n definitions: readonly FeatureFlagDefinition[],\n): readonly FeatureFlagDefinition[] {\n const seen = new Set<string>();\n return Object.freeze(\n definitions.map((definition) => {\n const normalized = defineFeatureFlag(definition);\n if (seen.has(normalized.key)) {\n throw new Error(`Duplicate feature flag key: ${normalized.key}`);\n }\n seen.add(normalized.key);\n return normalized;\n }),\n );\n}\n\n/** Register definitions once at Nitro startup. Re-registering identical data is safe for HMR. */\nexport function registerFeatureFlags(\n definitions: readonly FeatureFlagDefinition[],\n): void {\n for (const rawDefinition of definitions) {\n const definition = defineFeatureFlag(rawDefinition);\n const existing = registry.get(definition.key);\n if (!existing) {\n registry.set(definition.key, definition);\n continue;\n }\n if (\n existing.displayName !== definition.displayName ||\n existing.description !== definition.description\n ) {\n throw new Error(\n `Feature flag ${definition.key} was registered with conflicting metadata.`,\n );\n }\n }\n}\n\nexport function listFeatureFlags(): readonly FeatureFlagDefinition[] {\n return [...registry.values()].sort((a, b) => a.key.localeCompare(b.key));\n}\n\nexport function getFeatureFlagDefinition(\n key: string,\n): FeatureFlagDefinition | null {\n return registry.get(key) ?? null;\n}\n\n/** Test-only registry reset; not exported from package entrypoints. */\nexport function _resetFeatureFlagRegistryForTests(): void {\n registry.clear();\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type FeatureFlagDefinition } from "./registry.js";
|
|
2
|
+
export type FeatureFlagMode = "off" | "on" | "rules";
|
|
3
|
+
export interface FeatureFlagRules {
|
|
4
|
+
version: 1;
|
|
5
|
+
mode: FeatureFlagMode;
|
|
6
|
+
emails: string[];
|
|
7
|
+
orgIds: string[];
|
|
8
|
+
percentage: number;
|
|
9
|
+
updatedAt: number | null;
|
|
10
|
+
updatedBy: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface FeatureFlagScope {
|
|
13
|
+
userEmail?: string;
|
|
14
|
+
/** Canonical authenticated identity. V1 callers use normalized email. */
|
|
15
|
+
userKey?: string;
|
|
16
|
+
orgId?: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare const FEATURE_FLAG_SETTINGS_PREFIX = "feature-flag:";
|
|
19
|
+
export declare function defaultFeatureFlagRules(): FeatureFlagRules;
|
|
20
|
+
export declare function normalizeFeatureFlagRules(value: unknown): FeatureFlagRules;
|
|
21
|
+
export declare function getFeatureFlagRules(key: string, scope: Pick<FeatureFlagScope, "orgId">): Promise<FeatureFlagRules>;
|
|
22
|
+
/**
|
|
23
|
+
* Atomically derive one flag's scoped rules. An org's first override starts
|
|
24
|
+
* from the global fallback, then becomes independently CAS-protected.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mutateFeatureFlagRules(key: string, scope: Pick<FeatureFlagScope, "orgId">, updater: (current: FeatureFlagRules) => FeatureFlagRules | Promise<FeatureFlagRules>): Promise<FeatureFlagRules>;
|
|
27
|
+
export declare function evaluateFeatureFlagRules(key: string, rules: FeatureFlagRules, scope: FeatureFlagScope): boolean;
|
|
28
|
+
export declare function evaluateFeatureFlag(key: string, scope?: FeatureFlagScope): Promise<boolean>;
|
|
29
|
+
/** Ergonomic app-action guard. Accepts either a registered definition or its key. */
|
|
30
|
+
export declare function isFeatureFlagEnabled(flag: string | FeatureFlagDefinition, scope?: FeatureFlagScope): Promise<boolean>;
|
|
31
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/feature-flags/store.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,eAAO,MAAM,4BAA4B,kBAAkB,CAAC;AAM5D,wBAAgB,uBAAuB,IAAI,gBAAgB,CAU1D;AAcD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CA0B1E;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GACrC,OAAO,CAAC,gBAAgB,CAAC,CAS3B;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,EACtC,OAAO,EAAE,CACP,OAAO,EAAE,gBAAgB,KACtB,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAChD,OAAO,CAAC,gBAAgB,CAAC,CAiB3B;AAYD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAST;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,gBAAqB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAYlB;AAED,qFAAqF;AACrF,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,GAAG,qBAAqB,EACpC,KAAK,GAAE,gBAAqB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAElB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { getOrgSetting, mutateOrgSetting } from "../settings/org-settings.js";
|
|
2
|
+
import { getSetting, mutateSetting } from "../settings/store.js";
|
|
3
|
+
import { getFeatureFlagDefinition, } from "./registry.js";
|
|
4
|
+
export const FEATURE_FLAG_SETTINGS_PREFIX = "feature-flag:";
|
|
5
|
+
function settingKey(key) {
|
|
6
|
+
return `${FEATURE_FLAG_SETTINGS_PREFIX}${key}`;
|
|
7
|
+
}
|
|
8
|
+
export function defaultFeatureFlagRules() {
|
|
9
|
+
return {
|
|
10
|
+
version: 1,
|
|
11
|
+
mode: "off",
|
|
12
|
+
emails: [],
|
|
13
|
+
orgIds: [],
|
|
14
|
+
percentage: 0,
|
|
15
|
+
updatedAt: null,
|
|
16
|
+
updatedBy: null,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function stringList(value) {
|
|
20
|
+
if (!Array.isArray(value))
|
|
21
|
+
return [];
|
|
22
|
+
return [
|
|
23
|
+
...new Set(value
|
|
24
|
+
.filter((item) => typeof item === "string")
|
|
25
|
+
.map((item) => item.trim())
|
|
26
|
+
.filter(Boolean)),
|
|
27
|
+
].sort();
|
|
28
|
+
}
|
|
29
|
+
export function normalizeFeatureFlagRules(value) {
|
|
30
|
+
if (!value || typeof value !== "object")
|
|
31
|
+
return defaultFeatureFlagRules();
|
|
32
|
+
const raw = value;
|
|
33
|
+
const mode = raw.mode === "on" || raw.mode === "rules" || raw.mode === "off"
|
|
34
|
+
? raw.mode
|
|
35
|
+
: "off";
|
|
36
|
+
const percentage = typeof raw.percentage === "number" && Number.isFinite(raw.percentage)
|
|
37
|
+
? Math.max(0, Math.min(100, Math.floor(raw.percentage)))
|
|
38
|
+
: 0;
|
|
39
|
+
return {
|
|
40
|
+
version: 1,
|
|
41
|
+
mode,
|
|
42
|
+
emails: stringList(raw.emails).map((email) => email.toLowerCase()),
|
|
43
|
+
orgIds: stringList(raw.orgIds),
|
|
44
|
+
percentage,
|
|
45
|
+
updatedAt: typeof raw.updatedAt === "number" && Number.isSafeInteger(raw.updatedAt)
|
|
46
|
+
? raw.updatedAt
|
|
47
|
+
: null,
|
|
48
|
+
updatedBy: typeof raw.updatedBy === "string" && raw.updatedBy.trim()
|
|
49
|
+
? raw.updatedBy.trim().toLowerCase()
|
|
50
|
+
: null,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function getFeatureFlagRules(key, scope) {
|
|
54
|
+
if (!getFeatureFlagDefinition(key))
|
|
55
|
+
return defaultFeatureFlagRules();
|
|
56
|
+
// An organization-specific rule overrides the global rule. The fallback is
|
|
57
|
+
// what makes global exact-org targeting meaningful for callers in an org.
|
|
58
|
+
const stored = scope.orgId?.trim()
|
|
59
|
+
? ((await getOrgSetting(scope.orgId, settingKey(key))) ??
|
|
60
|
+
(await getSetting(settingKey(key))))
|
|
61
|
+
: await getSetting(settingKey(key));
|
|
62
|
+
return normalizeFeatureFlagRules(stored);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Atomically derive one flag's scoped rules. An org's first override starts
|
|
66
|
+
* from the global fallback, then becomes independently CAS-protected.
|
|
67
|
+
*/
|
|
68
|
+
export async function mutateFeatureFlagRules(key, scope, updater) {
|
|
69
|
+
if (!getFeatureFlagDefinition(key)) {
|
|
70
|
+
throw new Error(`Unknown feature flag: ${key}`);
|
|
71
|
+
}
|
|
72
|
+
const mutate = async (stored) => {
|
|
73
|
+
const fallback = stored == null && scope.orgId?.trim()
|
|
74
|
+
? await getSetting(settingKey(key))
|
|
75
|
+
: null;
|
|
76
|
+
return {
|
|
77
|
+
...(await updater(normalizeFeatureFlagRules(stored ?? fallback))),
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const persisted = scope.orgId?.trim()
|
|
81
|
+
? await mutateOrgSetting(scope.orgId, settingKey(key), mutate)
|
|
82
|
+
: await mutateSetting(settingKey(key), mutate);
|
|
83
|
+
return normalizeFeatureFlagRules(persisted);
|
|
84
|
+
}
|
|
85
|
+
function rolloutBucket(input) {
|
|
86
|
+
// FNV-1a is deliberately tiny, deterministic, and independent of runtime.
|
|
87
|
+
let hash = 0x811c9dc5;
|
|
88
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
89
|
+
hash ^= input.charCodeAt(index);
|
|
90
|
+
hash = Math.imul(hash, 0x01000193);
|
|
91
|
+
}
|
|
92
|
+
return (hash >>> 0) % 100;
|
|
93
|
+
}
|
|
94
|
+
export function evaluateFeatureFlagRules(key, rules, scope) {
|
|
95
|
+
if (rules.mode === "off")
|
|
96
|
+
return false;
|
|
97
|
+
if (rules.mode === "on")
|
|
98
|
+
return true;
|
|
99
|
+
const email = scope.userEmail?.trim().toLowerCase();
|
|
100
|
+
if (email && rules.emails.includes(email))
|
|
101
|
+
return true;
|
|
102
|
+
if (scope.orgId && rules.orgIds.includes(scope.orgId))
|
|
103
|
+
return true;
|
|
104
|
+
const userKey = scope.userKey?.trim() || email;
|
|
105
|
+
if (!userKey || rules.percentage <= 0)
|
|
106
|
+
return false;
|
|
107
|
+
return rolloutBucket(`${key}:${userKey}`) < rules.percentage;
|
|
108
|
+
}
|
|
109
|
+
export async function evaluateFeatureFlag(key, scope = {}) {
|
|
110
|
+
if (!getFeatureFlagDefinition(key))
|
|
111
|
+
return false;
|
|
112
|
+
try {
|
|
113
|
+
return evaluateFeatureFlagRules(key, await getFeatureFlagRules(key, scope), scope);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// A feature flag must never become an availability dependency.
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Ergonomic app-action guard. Accepts either a registered definition or its key. */
|
|
121
|
+
export async function isFeatureFlagEnabled(flag, scope = {}) {
|
|
122
|
+
return evaluateFeatureFlag(typeof flag === "string" ? flag : flag.key, scope);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/feature-flags/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { getOrgSetting, mutateOrgSetting } from \"../settings/org-settings.js\";\nimport { getSetting, mutateSetting } from \"../settings/store.js\";\nimport {\n getFeatureFlagDefinition,\n type FeatureFlagDefinition,\n} from \"./registry.js\";\n\nexport type FeatureFlagMode = \"off\" | \"on\" | \"rules\";\n\nexport interface FeatureFlagRules {\n version: 1;\n mode: FeatureFlagMode;\n emails: string[];\n orgIds: string[];\n percentage: number;\n updatedAt: number | null;\n updatedBy: string | null;\n}\n\nexport interface FeatureFlagScope {\n userEmail?: string;\n /** Canonical authenticated identity. V1 callers use normalized email. */\n userKey?: string;\n orgId?: string | null;\n}\n\nexport const FEATURE_FLAG_SETTINGS_PREFIX = \"feature-flag:\";\n\nfunction settingKey(key: string): string {\n return `${FEATURE_FLAG_SETTINGS_PREFIX}${key}`;\n}\n\nexport function defaultFeatureFlagRules(): FeatureFlagRules {\n return {\n version: 1,\n mode: \"off\",\n emails: [],\n orgIds: [],\n percentage: 0,\n updatedAt: null,\n updatedBy: null,\n };\n}\n\nfunction stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [\n ...new Set(\n value\n .filter((item): item is string => typeof item === \"string\")\n .map((item) => item.trim())\n .filter(Boolean),\n ),\n ].sort();\n}\n\nexport function normalizeFeatureFlagRules(value: unknown): FeatureFlagRules {\n if (!value || typeof value !== \"object\") return defaultFeatureFlagRules();\n const raw = value as Record<string, unknown>;\n const mode: FeatureFlagMode =\n raw.mode === \"on\" || raw.mode === \"rules\" || raw.mode === \"off\"\n ? raw.mode\n : \"off\";\n const percentage =\n typeof raw.percentage === \"number\" && Number.isFinite(raw.percentage)\n ? Math.max(0, Math.min(100, Math.floor(raw.percentage)))\n : 0;\n return {\n version: 1,\n mode,\n emails: stringList(raw.emails).map((email) => email.toLowerCase()),\n orgIds: stringList(raw.orgIds),\n percentage,\n updatedAt:\n typeof raw.updatedAt === \"number\" && Number.isSafeInteger(raw.updatedAt)\n ? raw.updatedAt\n : null,\n updatedBy:\n typeof raw.updatedBy === \"string\" && raw.updatedBy.trim()\n ? raw.updatedBy.trim().toLowerCase()\n : null,\n };\n}\n\nexport async function getFeatureFlagRules(\n key: string,\n scope: Pick<FeatureFlagScope, \"orgId\">,\n): Promise<FeatureFlagRules> {\n if (!getFeatureFlagDefinition(key)) return defaultFeatureFlagRules();\n // An organization-specific rule overrides the global rule. The fallback is\n // what makes global exact-org targeting meaningful for callers in an org.\n const stored = scope.orgId?.trim()\n ? ((await getOrgSetting(scope.orgId, settingKey(key))) ??\n (await getSetting(settingKey(key))))\n : await getSetting(settingKey(key));\n return normalizeFeatureFlagRules(stored);\n}\n\n/**\n * Atomically derive one flag's scoped rules. An org's first override starts\n * from the global fallback, then becomes independently CAS-protected.\n */\nexport async function mutateFeatureFlagRules(\n key: string,\n scope: Pick<FeatureFlagScope, \"orgId\">,\n updater: (\n current: FeatureFlagRules,\n ) => FeatureFlagRules | Promise<FeatureFlagRules>,\n): Promise<FeatureFlagRules> {\n if (!getFeatureFlagDefinition(key)) {\n throw new Error(`Unknown feature flag: ${key}`);\n }\n const mutate = async (stored: Record<string, unknown> | null) => {\n const fallback =\n stored == null && scope.orgId?.trim()\n ? await getSetting(settingKey(key))\n : null;\n return {\n ...(await updater(normalizeFeatureFlagRules(stored ?? fallback))),\n };\n };\n const persisted = scope.orgId?.trim()\n ? await mutateOrgSetting(scope.orgId, settingKey(key), mutate)\n : await mutateSetting(settingKey(key), mutate);\n return normalizeFeatureFlagRules(persisted);\n}\n\nfunction rolloutBucket(input: string): number {\n // FNV-1a is deliberately tiny, deterministic, and independent of runtime.\n let hash = 0x811c9dc5;\n for (let index = 0; index < input.length; index += 1) {\n hash ^= input.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0) % 100;\n}\n\nexport function evaluateFeatureFlagRules(\n key: string,\n rules: FeatureFlagRules,\n scope: FeatureFlagScope,\n): boolean {\n if (rules.mode === \"off\") return false;\n if (rules.mode === \"on\") return true;\n const email = scope.userEmail?.trim().toLowerCase();\n if (email && rules.emails.includes(email)) return true;\n if (scope.orgId && rules.orgIds.includes(scope.orgId)) return true;\n const userKey = scope.userKey?.trim() || email;\n if (!userKey || rules.percentage <= 0) return false;\n return rolloutBucket(`${key}:${userKey}`) < rules.percentage;\n}\n\nexport async function evaluateFeatureFlag(\n key: string,\n scope: FeatureFlagScope = {},\n): Promise<boolean> {\n if (!getFeatureFlagDefinition(key)) return false;\n try {\n return evaluateFeatureFlagRules(\n key,\n await getFeatureFlagRules(key, scope),\n scope,\n );\n } catch {\n // A feature flag must never become an availability dependency.\n return false;\n }\n}\n\n/** Ergonomic app-action guard. Accepts either a registered definition or its key. */\nexport async function isFeatureFlagEnabled(\n flag: string | FeatureFlagDefinition,\n scope: FeatureFlagScope = {},\n): Promise<boolean> {\n return evaluateFeatureFlag(typeof flag === \"string\" ? flag : flag.key, scope);\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { createAgentChatPlugin, defaultAgentChatPlugin, type AgentChatPluginOpti
|
|
|
9
9
|
export { createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, type AgentNativeEmbeddedPluginOptions, } from "./server/embedded.js";
|
|
10
10
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, type AutomationCapabilities, type BuiltInChannelId, type ChannelCapabilities, type IntegrationAvailability, type IntegrationCatalogEntry, type IntegrationCategory, type IntegrationCredentialRequirement, type IntegrationIconKey, type IntegrationSupportMaturity, } from "./integrations/catalog.js";
|
|
11
11
|
export { AutomationConnectorError, createAutomationCallbackHandler, createAutomationRuntime, createInvokeAutomationWorkflowAction, type AutomationCallbackAuthentication, type AutomationCallbackInput, type AutomationCallbackResult, type AutomationInboundDefinition, type AutomationInvocation, type AutomationInvocationResult, type AutomationInvocationStatus, type AutomationOutboundDefinition, type AutomationResponseMode, type AutomationRetryPolicy, type AutomationRuntime, type AutomationRuntimeOptions, type AutomationWorkflowCapabilities, type AutomationWorkflowDefinition, type JsonSchema, } from "./automation/index.js";
|
|
12
|
+
export { createFeatureFlagsPlugin, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./feature-flags/index.js";
|
|
12
13
|
export { createServer, createSSEHandler, defineNitroPlugin, autoMountAuth, getSession, type CreateServerOptions, type SSEHandlerOptions, type AuthSession, type AuthOptions, } from "./server/index.js";
|
|
13
14
|
export { agentChat, type AgentChatCallOptions, type AgentChatResponse, } from "./shared/index.js";
|
|
14
15
|
export { EMBED_MODE_QUERY_PARAM, EMBED_SESSION_COOKIE, EMBED_START_PATH, EMBED_TOKEN_QUERY_PARAM, } from "./shared/embed-auth.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export { createAgentChatPlugin, defaultAgentChatPlugin, } from "./server/agent-c
|
|
|
14
14
|
export { createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, } from "./server/embedded.js";
|
|
15
15
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, } from "./integrations/catalog.js";
|
|
16
16
|
export { AutomationConnectorError, createAutomationCallbackHandler, createAutomationRuntime, createInvokeAutomationWorkflowAction, } from "./automation/index.js";
|
|
17
|
+
export { createFeatureFlagsPlugin, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, } from "./feature-flags/index.js";
|
|
17
18
|
// Server
|
|
18
19
|
export { createServer, createSSEHandler, defineNitroPlugin, autoMountAuth, getSession, } from "./server/index.js";
|
|
19
20
|
// Client
|