34 lines
2.4 KiB
Markdown
34 lines
2.4 KiB
Markdown
# 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`.
|