Files
suaveplan/openspec/archive/2026-04-19-enterprise-feature-flags/specs/feature-flags/spec.md
2026-05-27 23:29:53 +01:00

2.4 KiB

Capability Spec: feature-flags

Package: @suaveplan/feature-flags Version: 0.0.0 (genesis) Status: ADDED


ADDED Requirements

FF-01 — Provider contract

BaseFlagProvider MUST implement getFlag(key): FlagDefinition | undefined, listFlags(): FlagDefinitionMap, subscribe(listener): () => void, and close(): void. Concrete providers (MemoryProvider, JsonProvider) MUST satisfy the same contract test suite.

FF-02 — Evaluator contract

Evaluator.evaluate(key, context) MUST resolve the flag definition, run its strategy chain in declared order, short-circuit on the first non-none StrategyResult, and return a FlagEvaluationResult carrying { value, reason, flag, context, duration_ms }. Unknown flag keys MUST throw or return a fallback per EvaluatorOptions.fallbackMode.

FF-03 — Deterministic bucketing

PercentageStrategy MUST use hashToPercentage(combineKeys(flagKey, userKey)) and bucket [0, rolloutPercentage). For fixed inputs it MUST return the same result across processes and platforms; the implementation MUST NOT depend on Math.random.

FF-04 — Composite strategy semantics

CompositeStrategy MUST evaluate children left-to-right. AND MUST short-circuit on the first none/no-match. OR MUST short-circuit on the first match. Errors in a child strategy MUST surface as FEATURE_FLAGS.STRATEGY_ERROR with the child's index in context.

FF-05 — Attribute targeting

AttributeStrategy MUST support AttributeOperator values eq, neq, in, nin, gt, gte, lt, lte, contains, startsWith, endsWith, regex. getNestedValue(ctx, path) MUST walk dot-notation paths safely, returning undefined for missing segments rather than throwing.

FF-06 — Change notification

Any change pushed through a provider (updateFlag, remote poll) MUST emit a FlagChangeEvent on the shared EventBus. FlagManager MUST expose subscribe(listener) that forwards these events to consumers.

FF-07 — Observability

Every Evaluator.evaluate call MUST record a histogram ff.evaluate.duration_ms and increment ff.evaluate.total with labels flag and result (match | no-match | fallback | error).

FF-08 — Definition validation

All flag definitions registered via FlagRegistry MUST pass FlagDefinitionSchema.parse. Invalid shapes MUST surface as FEATURE_FLAGS.INVALID_DEFINITION.