## Two questions, two places

**Which surfaces are paid?** One line per controller. Adding the include gates it; removing it
frees it.

**What does paid mean?** One line in `app/models/entitlement.rb`, which returns the strategy: a
subscription, a token balance, or nothing.

Keeping them apart is what makes each change cheap. A pricing experiment that moves a feature in or
out of the paid tier touches one controller and no billing code. A business model change touches one
model and no controllers.

## Tiers, if you need more than one

`Subscription` has a `tier` enum with `free` and `pro`. `entitled?` ignores it, because the shipped
gate is binary: you are in or you are not.

For a real tier split, the honest version is a second question rather than a cleverer version of the
first:

```ruby
Entitlement.for(Current.account).entitled?
Current.account.subscription&.pro?
```

Resist encoding tiers into `RequireEntitlement`. The moment the concern knows about plan names, every
controller that includes it is coupled to your pricing page, and pricing changes more often than
code.

## Do not confuse this with authorization

Entitlement asks whether the workspace may use the surface. Pundit asks whether this user may touch
this record. A gated controller still needs `authorize` and `policy_scope`, and the policies live in
`app/policies`. Skipping the second one means paying customers can read each other's data, which is
the worst version of this mistake.

## Check both paths

```bash
bin/rspec
```

Every gated controller wants two request specs: entitled gets 200, unentitled is redirected. The
example `Project` slice has both, and copying its spec file is faster than writing them.

## Changing a gate on a live app

Adding a gate to a feature people already use locks out existing users at the moment of deploy.
Usually worth announcing first, or grandfathering by giving existing accounts an active subscription
row before the deploy rather than after the complaints.
