docs: add MILESTONES.md and SPECS.md for project tracking

This commit is contained in:
Funky Waddle 2026-02-12 00:54:19 -06:00
parent 141554a854
commit 5043031a33
2 changed files with 113 additions and 0 deletions

59
MILESTONES.md Normal file
View file

@ -0,0 +1,59 @@
# FlagPole Milestones
This document outlines the roadmap for enhancing FlagPole with advanced targeting, persistence, and observability features.
## Table of Contents
- [Milestone 1: Advanced Rule Engine](#milestone-1-advanced-rule-engine)
- [Milestone 2: Pluggable Targeting Keys](#milestone-2-pluggable-targeting-keys)
- [Milestone 3: Persistent Repositories](#milestone-3-persistent-repositories)
- [Milestone 4: Observability & Logging](#milestone-4-observability--logging)
- [Milestone 5: Documentation & Polish](#milestone-5-documentation--polish)
- [Milestone 6: Refactoring & DRY](#milestone-6-refactoring--dry)
- [Milestone 7: Validation & Safety](#milestone-7-validation--safety)
## Milestone 1: Advanced Rule Engine
Move beyond simple allow-lists to support complex attribute-based targeting.
- [x] Define `Rule` DTO/Interface (`src/Rule.php`).
- [x] Add `rules` collection to `Flag` DTO.
- [x] Implement rule evaluation logic in `Evaluator` (supporting operators like `eq`, `gt`, `lt`, `in`, `contains`).
- [x] Update `Evaluator::evaluate` precedence: `allowList` > `enabled` > `rules` > `rolloutPercentage`.
## Milestone 2: Pluggable Targeting Keys
Allow explicit control over which context attribute is used for rollout hashing.
- [x] Add optional `targetingKey` property to `Flag`.
- [x] Refactor `Evaluator::resolveTargetingKey` to honor `Flag->targetingKey` if present.
- [x] Modernize hashing implementation in `Evaluator::computeBucket` for PHP 8.2+.
## Milestone 3: Persistent Repositories
Provide out-of-the-box support for non-volatile flag storage.
- [x] Implement `JsonFileRepository` in `src/Repository/JsonFileRepository.php`.
- [x] Ensure robust JSON parsing and mapping to `Flag` objects.
## Milestone 4: Observability & Logging
Provide insights into why flags are being enabled or disabled.
- [x] Integrate PSR-3 `LoggerInterface` into `FeatureManager` and `Evaluator`.
- [x] Implement detailed logging for evaluation outcomes (e.g., which rule or strategy matched).
- [x] (Optional) Create `EvaluationResult` DTO for programmatic access to evaluation reasons.
## Milestone 5: Documentation & Polish
- [x] Update `README.md` with examples for new features.
- [x] Add comprehensive tests for Rule Engine and JSON Repository.
- [x] Verify zero regression for existing simple flag usage.
## Milestone 6: Refactoring & DRY
Centralize logic and remove duplication to improve maintainability.
- [x] Extract flag hydration logic into a dedicated `FlagHydrator` class to be reused across repositories.
- [x] Refactor `InMemoryFlagRepository` to use the new hydration logic.
- [x] Refactor `JsonFileRepository` to use the new hydration logic.
## Milestone 7: Validation & Safety
Enhance the engine to be more robust and developer-friendly.
- [x] Add validation to the rule engine to handle or log unknown operators instead of failing silently.
- [x] Implement configuration validation to ensure `Flag` and `Rule` objects are correctly formed before evaluation.
- [x] Optimize `JsonFileRepository` to avoid unnecessary parsing or consider lazy-loading if the config grows large.

54
SPECS.md Normal file
View file

@ -0,0 +1,54 @@
# FlagPole Specifications
This document describes the current technical specifications and architecture of the FlagPole feature flagging library.
## Core Concepts
### Flag
An immutable data object representing a feature flag and its evaluation strategies.
- **Properties**:
- `name` (string): Unique identifier.
- `enabled` (bool|null): Explicit override. If `true`/`false`, evaluation stops here.
- `rolloutPercentage` (int|null): 0-100 value for gradual rollout.
- `allowList` (list<string>): Keys that always receive `true`.
- `rules` (list<Rule>): Complex attribute-based targeting rules.
- `targetingKey` (string|null): Optional override for the attribute used in rollout/allowList.
### Context
A container for attributes (e.g., `userId`, `email`, `userGroup`) used during evaluation.
- **Targeting Keys**: By default, the evaluator looks for `key`, `userId`, `id`, or `email` (in that order), unless overridden by `Flag->targetingKey`.
### Evaluator
The engine that applies flag strategies against a context.
- **Precedence**:
1. `allowList`: If the targeting key is in the list, return `true`.
2. `enabled`: If non-null, return its boolean value.
3. `rules`: If any rule matches the context attributes, return `true`.
4. `rolloutPercentage`: Hash-based stable bucketing (0-99).
5. `fallback`: Returns the user-provided default.
### FeatureManager
The main entry point for the consumer.
- **Method**: `isEnabled(string $flagName, ?Context $context = null, bool $default = false): bool`
- **Logging**: Supports PSR-3 logging of evaluation reasons.
## Technical Details
### Rollout Hashing
- Algorithm: `xxh3(flagName + ":" + targetingKey)`.
- Normalization: `hexdec(substr(hash, 0, 8)) % 100`.
- Bucketing: 0-99.
### Repositories
- `FlagRepositoryInterface`: Defines `get(string $name)` and `all()`.
- `InMemoryFlagRepository`: Provided for testing and simple setups.
- `JsonFileRepository`: Loads flags from a JSON file. Now supports lazy-loading hydration for better performance.
### FlagHydrator
A dedicated component responsible for transforming raw configuration arrays into validated `Flag` and `Rule` objects.
- **Validation**: Ensures all rules have required fields and valid operators (`eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`, `contains`).
- **Reuse**: Used by both `InMemoryFlagRepository` and `JsonFileRepository` to ensure consistent flag creation.
## Constraints
- PHP 8.2+ required.
- No external dependencies (PSR interfaces excepted in future).