## Why the app side is already done

```ruby
def entitled? = active? || trialing?
```

That is the whole of it, in `app/models/subscription.rb`. The status enum already has `trialing`, so
a trial is not a special case anywhere in the gate, and `app/models/entitlement.rb` asks the same
question whether or not a trial is involved.

## What Stripe needs

Two settings, both on Stripe's side:

- A **trial period** on the price or passed into the checkout session.
- **Payment method collection** set so a card is not required to start.

Without a card, Stripe cannot charge when the trial ends. It sends
`customer.subscription.updated` with the status moving out of `trialing`, and the subscription is
canceled rather than billed. Your gate closes, which is the behavior you want.

## The event that matters most

`customer.subscription.updated` is what carries trial transitions, and it is easy to leave disabled
because it sounds generic. If it is not enabled on the endpoint, a trial that ended looks like an
active trial forever, and you give the product away indefinitely.

```bash
bin/kamal app exec --interactive --reuse 'bin/rails console'
```

```ruby
Subscription.where(status: "trialing").where("updated_at < ?", 30.days.ago).count
```

A number above zero on a 14 day trial is that bug.

## Card or no card

No card converts more people into trials and fewer trials into customers, because the end of the
trial is a decision rather than a default. With a card it is the reverse. Neither is wrong, but pick
deliberately and then measure it, rather than inheriting whichever one you configured first.

## Test the whole arc

Stripe test mode lets you advance a subscription's clock, which is the only honest way to test the
end of a trial. Without it you are asserting that a status change you never saw will do what you
expect. Run it once, watch the webhook arrive, and confirm the gate closes.
