Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# OpenSpec Change: enterprise-feature-flags
- **Change ID**: enterprise-feature-flags
- **Package**: `@suaveplan/feature-flags`
- **Category**: universal
- **Target path**: `universal/config/feature-flags`
- **Status**: PROPOSED
- **Date**: 2026-04-19
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/feature-flags.md`
## Summary
Greenfield build of `@suaveplan/feature-flags` — provider-agnostic flag evaluation with a `FlagRegistry` + `FlagManager` façade, an `Evaluator` that runs strategy chains, provider adapters (memory, JSON), and composable targeting strategies (`PercentageStrategy`, `UserTargetStrategy`, `AttributeStrategy`, `ScheduleStrategy`, `CompositeStrategy`). Typed `FlagValue` with deterministic bucketing via `hashToPercentage`.
## Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
## Dependencies
- Workspace: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/logger`
- External (via catalog): `zod` → `catalog:forms`; `@opentelemetry/api` → `catalog:observability`; `tslib` → `catalog:build`
- Dev (via catalog): `vitest`, `@vitest/coverage-istanbul`, `fast-check`, `mitata` → `catalog:testing`
## Preserved public surface (from main)
### Core
- `FlagRegistry`, `FlagRegistryOptions`
- `FlagManager`, `FlagManagerOptions`
- `Evaluator`, `EvaluatorOptions`
### Providers
- `BaseFlagProvider`, `BaseFlagProviderOptions`
- `MemoryProvider`
- `JsonProvider`, `JsonProviderOptions`, `JsonFlagConfig`, `parseJsonFlags`
### Strategies
- `PercentageStrategy`, `PercentageStrategyOptions`
- `UserTargetStrategy`, `UserTargetStrategyOptions`
- `AttributeStrategy`, `AttributeStrategyOptions`, `AttributeOperator`, `AttributeRule`, `compareValues`, `getNestedValue`
- `ScheduleStrategy`, `ScheduleStrategyOptions`
- `CompositeStrategy`, `CompositeStrategyOptions`, `CompositeOperator`
### Types
`FlagDefinition`, `FlagDefinitionMap`, `FlagValue`, `FlagProvider`, `FlagChangeEvent`, `FlagChangeListener`, `FlagEvaluationResult`, `EvaluationContext`, `EvaluationReason`, `Strategy`, `StrategyResult`
### Utilities
- `hashToPercentage`, `combineKeys`
## New genesis additions
- Structured errors with codes `FEATURE_FLAGS.UNKNOWN_FLAG`, `FEATURE_FLAGS.PROVIDER_ERROR`, `FEATURE_FLAGS.STRATEGY_ERROR`, `FEATURE_FLAGS.INVALID_DEFINITION`.
- Zod schemas for every `FlagDefinition`, `EvaluationContext`, `JsonFlagConfig`.
- OTel histogram `ff.evaluate.duration_ms`; counter `ff.evaluate.total{flag, result}`.
- Property tests: `hashToPercentage` uniform over random keys within statistical tolerance; `PercentageStrategy` bucketing is monotonic in rollout percentage.
- mitata benchmarks for `Evaluator.evaluate` across strategy depths.
## Impact
- Adds one new package: `universal/config/feature-flags`
- Adds one new spec capability: `feature-flags`

View File

@@ -0,0 +1,33 @@
# 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`.

View File

@@ -0,0 +1,50 @@
# Tasks: enterprise-feature-flags
## 1. Scaffold
- [x] 1.1 Create `universal/config/feature-flags/` skeleton; 100/100/100/100 coverage; istanbul.
- [x] 1.2 Cross-cutting guard tests; add to CLAUDE.md/README/FOLDERS.yml.
## 2. Errors + schemas
- [x] 2.1 `src/errors/feature-flags-error.ts` — `FeatureFlagsError` extends `SuaveplanError`; codes `FEATURE_FLAGS.*`.
- [x] 2.2 Auto-register codes via side-effect import.
- [x] 2.3 Zod schemas for `FlagDefinition`, `EvaluationContext`, `JsonFlagConfig`, `FlagEvaluationResult`.
## 3. Core types + utilities
- [x] 3.1 `src/types/common.ts` — all preserved type exports.
- [x] 3.2 `src/utils/hash.ts` — `hashToPercentage`, `combineKeys` (FNV-1a or xxhash32 over `combineKeys(flagKey, userKey)`).
- [x] 3.3 Co-located `.md` + property tests for uniformity.
## 4. Strategies
- [x] 4.1 `src/strategies/percentage-strategy/*` — `PercentageStrategy`; deterministic bucketing.
- [x] 4.2 `src/strategies/user-target-strategy/*`.
- [x] 4.3 `src/strategies/attribute-strategy/*` — `compareValues`, `getNestedValue`, `AttributeOperator`, `AttributeRule`.
- [x] 4.4 `src/strategies/schedule-strategy/*` — time-windowed rollout.
- [x] 4.5 `src/strategies/composite-strategy/*` — AND/OR over child strategies.
- [x] 4.6 Co-located `.md` + unit tests each.
## 5. Providers
- [x] 5.1 `src/providers/provider-interface/*` — `BaseFlagProvider` abstract class.
- [x] 5.2 `src/providers/memory-provider/*` — `MemoryProvider`.
- [x] 5.3 `src/providers/json-provider/*` — `JsonProvider`, `parseJsonFlags`.
- [x] 5.4 Co-located `.md` + tests; provider contract test suite reused across implementations.
## 6. Core evaluator
- [x] 6.1 `src/core/flag-registry/*` — `FlagRegistry`; validates definitions via Zod.
- [x] 6.2 `src/core/evaluator/*` — `Evaluator`; OTel histogram + counter.
- [x] 6.3 `src/core/flag-manager/*` — `FlagManager` façade.
- [x] 6.4 Emits `FlagChangeEvent` via `@suaveplan/events`.
## 7. Index + exports
- [x] 7.1 Barrel `src/index.ts` — re-exports only.
- [x] 7.2 Subpath exports per feature module.
## 8. Docs
- [x] 8.1 Root `README.md`.
- [x] 8.2 Co-located `.md` per `.ts`.
## 9. Benchmarks
- [x] 9.1 `src/__benchmarks__/evaluate.bench.ts` — 1 / 5 / 25 strategy chain depth.
## 10. Ship gate
- [x] 10.1 Verification sequence green.
- [x] 10.2 Fold spec + archive.