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.