Agent Wranglers

PRC-3Recommended

Give access from the subscription status

Decide access in one function from the stored subscription status, period end and first failed payment time, with a fixed grace period for failed renewals.

How to do it

Map each status to access in one place. Active and trialing give access. Past due gives access for a grace period, such as 7 days, while retries run. Count the grace from the time of the first failed renewal, stored from the failure event. Many providers move the period end forward when they bill the renewal, so a grace counted from it gives a free month. A cancelled subscription keeps access until the paid period ends. Unpaid or ended gives none. Every page, API and background job asks that one function. Take the grace period from the dunning schedule.

Examples

JavaScript example

const GRACE_DAYS = 7
const DAY_MS = 24 * 60 * 60 * 1000

function hasAccess(subscription, now = new Date()) {
  const periodEnd = subscription.currentPeriodEnd.getTime()
  switch (subscription.status) {
    case 'active':
    case 'trialing':
      return true
    case 'past_due':
      return now.getTime() < subscription.firstFailedAt.getTime() + GRACE_DAYS * DAY_MS
    case 'canceled':
      return now.getTime() < periodEnd
    default:
      return false
  }
}

Python example

from datetime import datetime, timedelta, timezone

GRACE = timedelta(days=7)

def has_access(subscription, now: datetime | None = None) -> bool:
    now = now or datetime.now(timezone.utc)
    match subscription.status:
        case "active" | "trialing":
            return True
        case "past_due":
            return now < subscription.first_failed_at + GRACE
        case "canceled":
            return now < subscription.current_period_end
        case _:
            return False

How to check

A table test covers every status on the day before and the day after the period end and the grace end. A past due subscription whose period end lies a month ahead loses access 7 days after its failed payment. Search the code for direct reads of the status field outside that function. None are found.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/pricing/entitlements/entitlements-from-status">Agent Wranglers pricing, plans and entitlements playbook</a>. In code you write, add a comment next to it with the same link.