# Targeting rules

Build ordered rule groups with predictable matching and explicit outcomes.

Targeting rules serve different values to defined cohorts inside one environment. FeatureGate checks
groups in order and returns the outcome of the first match.

Use targeting for staged releases, internal access, customer-approved cohorts, and durable runtime
configuration. Do not use caller-supplied attributes as an authorization boundary.

<FlowDiagram
  ariaLabel="Targeting evaluation"
  items={[
    "Emergency override",
    "Rule group 1",
    "Rule group 2",
    "Later groups",
    "Environment fallback",
  ]}
/>

![Flag targeting workbench showing ordered staff and Pro-account rules](/images/hero-console-flow.png)

## Rule groups and conditions

A **match all** group requires every condition to match. A **match any** group requires at least one.
Each matching group has one typed outcome.

Attribute conditions use dot-separated paths such as `account.plan`. Supported operators are:

| Operator   | Matches when                                             |
| ---------- | -------------------------------------------------------- |
| Equals     | The attribute exactly equals the configured value        |
| Not equals | A present attribute differs from the configured value    |
| In         | The attribute equals one value in a configured set       |
| Not in     | A present attribute equals none of the configured values |

Missing attributes are misses, including negative operators. An absent `account.plan` does not match
`account.plan not equals free`.

## Build a rule

Open a flag, choose the environment, and keep the workbench in Flow, Visual, or Code view. These are
three views of one ordered model, not separate configurations.

For a staff cohort:

1. Add a rule group before broad rollout rules.
2. Choose **Match any**.
3. Add `user.role equals admin`.
4. Add `user.role equals staff`.
5. Set the outcome to the new typed value.
6. Save with a concise change note.

Test an admin, a staff member, an ordinary user, and a context without `user.role`. The missing path
must fall through rather than match accidentally.

## Order rules deliberately

Put narrow exceptions before broad cohorts. A support override for one account normally precedes a
plan-wide or percentage rule.

Suppose production contains:

1. `account.id in [internal_account]` → `true`
2. `account.plan equals pro` and 20% by `account.id` → `true`
3. Fallback → `false`

The internal account always receives `true`. Other Pro accounts participate in the stable rollout.
Everyone else receives `false`.

Moving the Pro rule above an explicit off exception could make the exception unreachable. Review the
complete order whenever a broad rule changes.

## Change notes and permissions

Members, admins, and owners can change targeting. Viewers can inspect non-secret configuration only.
Production changes appear in activity and may trigger configured notifications.

Record the reason, expected observation period, owner, and rollback condition. Do not include emails,
raw targeting values, secrets, or incident payloads.

## Failure cases

- **No group matches:** verify exact path, type, normalization, and group mode.
- **The wrong group wins:** inspect order and move narrow exceptions earlier.
- **A negative rule matches unexpectedly:** confirm the attribute is present; missing values miss.
- **A browser rule is unsafe:** move trusted entitlement enforcement to the server.
- **A rollout reshuffles:** restore the original rollout attribute and normalization.

> [!WARNING] Targeting is not access control
> Context comes from the calling application. Continue enforcing permissions and
> entitlements in trusted application code even when a rule targets a role or
> plan.

Continue with [Percentage rollouts](/docs/flags/percentage-rollouts) and
[Design evaluation context](/docs/flags/evaluation-context).
