This PR renames the links to the `zed.dev/settings` page to the
`zed.dev/account`.
Some of these spots will likely link out to a marketing page later.
Release Notes:
- N/A
This PR increases the frequency at which we poll for Stripe events.
This decreases the amount of time we have to wait in order for changes
in Stripe to be reflected in our system.
We now poll for events every 5 seconds, down from every 5 minutes.
In order to avoid needlessly over-fetching data from Stripe, we put a
cap on the number of pages consisting entirely of already-processed
events that we can see before stopping. This is set to 4, so once we've
seen 4 pages of processed events (400 events in total), we'll stop
fetching subsequent pages.
Release Notes:
- N/A
English is hard.
In US English the forms of "cancel" are as follows:
- `cancel`
- `cancels`
- `canceling`
- `canceled`
- `cancellation`
Note that `cancellation` _does_ use the double `l`, which all the rest
of the forms do not.
Release Notes:
- N/A
This PR updates collab to pick the `zed.dev` URL based on the current
environment rather than always using `https://zed.dev`.
This means that when developing locally we'll use
`http://localhost:3000` to be taken to the locally-running version of
`zed.dev`.
Release Notes:
- N/A
This PR updates the rate limits to adapt based on the user's current
plan.
For the free plan rate limits I just took one-tenth of the existing rate
limits (which are now the Pro limits). We can adjust, as needed.
Release Notes:
- N/A
---------
Co-authored-by: Max <max@zed.dev>
This PR adds a new `GET /billing/subscriptions` endpoint to collab for
retrieving the subscriptions to display on the account settings page.
Release Notes:
- N/A
This PR reworks how we process Stripe events for reconciliation
purposes.
The previous approach in #15480 turns out to not be workable, on account
of the Stripe event IDs not being strictly in order. This meant that we
couldn't reliably compare two arbitrary event IDs and determine which
one was more recent.
This new approach leans on the guidance that Stripe provides for
webhooks events:
> Webhook endpoints might occasionally receive the same event more than
once. You can guard against duplicated event receipts by logging the
[event IDs](https://docs.stripe.com/api/events/object#event_object-id)
you’ve processed, and then not processing already-logged events.
>
> https://docs.stripe.com/webhooks#handle-duplicate-events
We now record processed Stripe events in the `processed_stripe_events`
table and use this to filter out events that have already been
processed, so we do not process them again.
When retrieving events from the Stripe events API we now buffer the
unprocessed events so that we can sort them by their `created` timestamp
and process them in (roughly) the order they occurred.
Release Notes:
- N/A
This PR improves our Stripe event handling by keeping track of the last
event we've seen for each record.
The `billing_customers` and `billing_subscriptions` tables both have a
new `last_stripe_event_id` column. When we apply an event to one of
these records, we store the event ID that was applied.
Then, when we are going through events we can ignore any event that has
an ID that came before the `last_stripe_event_id` (based on the
lexicographical ordering of the IDs).
Release Notes:
- N/A
This PR lays the initial groundwork for using the Stripe events API to
reconcile the data in our system with what's in Stripe.
We're using the events API over webhooks so that we don't need to stand
up the associated infrastructure needed to handle webhooks effectively
(namely an asynchronous job queue).
Since we haven't configured the Stripe API keys yet, we won't actually
spawn the reconciliation background task yet, so this is currently a
no-op.
Release Notes:
- N/A
This PR adds a new `billing_customers` table to hold the billing
customers.
Previously we were storing both the `stripe_customer_id` and
`stripe_subscription_id` in the `billable_subscriptions` table. However,
this creates problems when we need to correlate subscription events back
to the subscription record, as we don't know the user that the Stripe
event corresponds to.
By moving the `stripe_customer_id` to a separate table we can create the
Stripe customer earlier in the flow—before we create the Stripe Checkout
session—and associate that customer with a user. This way when we
receive events down the line we can use the Stripe customer ID to
correlate it back to the user.
We're doing some destructive actions to the `billing_subscriptions`
table, but this is fine, as we haven't started using them yet.
Release Notes:
- N/A
This PR adds a new `POST /billing/subscriptions/manage` endpoint that
can be used to manage a billing subscription.
The endpoint accepts a `github_user_id` to identify the user, as well as
an optional `subscription_id` for managing a specific subscription. If
`subscription_id` is not provided, it try and use the active
subscription, if there is only one.
Right now the endpoint only supports cancelling an active subscription.
This is done by passing `"intent": "cancel"` in the request body.
The endpoint will return the URL to a Stripe customer portal session,
which the caller can redirect the user to.
Here's an example of how to call it:
```sh
curl -X POST "http://localhost:8080/billing/subscriptions/manage" \
-H "Authorization: <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"github_user_id": 12345, "intent": "cancel"}'
```
Release Notes:
- N/A
This PR adds a new `POST /billing/subscriptions` endpoint that can be
used to initiate a billing subscription.
The endpoint will use the provided `github_user_id` to look up a user,
generate a Stripe Checkout session, and then return the URL.
The caller would then redirect the user to the URL to initiate the
checkout flow.
Here's an example of how to call it:
```sh
curl -X POST "http://localhost:8080/billing/subscriptions" \
-H "Authorization: <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"github_user_id": 12345}'
```
Release Notes:
- N/A