Skip to content

Add empty group detection and pruning to Expression, guard enables - #1036

Open
jnunemaker wants to merge 1 commit into
mainfrom
expression-empty-groups
Open

Add empty group detection and pruning to Expression, guard enables#1036
jnunemaker wants to merge 1 commit into
mainfrom
expression-empty-groups

Conversation

@jnunemaker

Copy link
Copy Markdown
Collaborator

Summary

An expression containing an empty All group evaluates true for every actor, so persisting one silently enables the feature for everyone. This PR detects and guards against that footgun.

  • Expression#empty_groups? detects empty Any/All groups anywhere in the tree, #prune_empty_groups removes them wherever removal cannot broaden the expression, and #always_true? reports expressions that are guaranteed to match every actor.
  • Feature#enable_expression and #add_expression raise ArgumentError when the expression contains empty groups. flipper-api already rescues ArgumentError into the expression_invalid error response, so API clients get a 422 instead of persisting the footgun.
  • Feature#remove_expression of the last condition now disables the expression instead of persisting an empty group (previously it left {"Any":[]} — or worse, {"All":[]}, enabled-for-everyone — in the adapter).

Test plan

  • New unit specs for empty_groups?, prune_empty_groups, and always_true? in spec/flipper/expression_spec.rb
  • New feature specs covering the enable/add guards and the last-condition removal behavior in spec/flipper/feature_spec.rb
  • A seeded property spec (spec/flipper/expression_pruning_property_spec.rb) verifying against the evaluator that pruning never broadens an expression

🤖 Generated with Claude Code

An expression containing an empty All group evaluates true for every
actor, so persisting one silently enables the feature for everyone.

- Expression#empty_groups? detects empty Any/All groups anywhere in
  the tree, #prune_empty_groups removes them wherever removal cannot
  broaden the expression, and #always_true? reports expressions that
  are guaranteed to match every actor.
- Feature#enable_expression and #add_expression raise ArgumentError
  when the expression contains empty groups. flipper-api already
  rescues ArgumentError into the expression_invalid error response,
  so API clients get a 422 instead of persisting the footgun.
- Feature#remove_expression of the last condition now disables the
  expression instead of persisting an empty group (previously it
  left {"Any":[]} — or worse, {"All":[]}, enabled-for-everyone —
  in the adapter).
- Includes a seeded property spec verifying against the evaluator
  that pruning never broadens an expression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant