Skip to content

Entitlements

An Entitlement is the central concept in MIDDAG Account. It is a unique record that means: "Someone has access to Product or Service Y." Every entitlement has a code, a lifecycle state, and links to all the downstream resources that access grants -- licenses, contracts, services, environments, invoices, and documents.

Before entitlements, answering "does Customer X have active support?" meant checking three or more systems. With entitlements, you look up one code and see everything: what was purchased, when it expires, what licenses or services are attached, and what the current status is.

The entitlement code

Every entitlement has a unique, immutable code in this format:

{CLASS}-{YEAR}{MONTH}{SEQ}

Example: PLG-2026040142 -- the 142nd Plugin entitlement created in April 2026.

The code is:

  • Unique -- generated atomically, no duplicates
  • Immutable -- once assigned, it never changes, even if the entitlement is suspended or cancelled
  • Human-readable -- the class prefix tells you what kind of access it represents, and the date tells you when it was created
  • Customer-facing -- customers see this code in the portal, in emails, and reference it when opening support tickets

This is your single identifier for any customer relationship question. "What's the status of PLG-2026040142?" gives you an instant, complete answer.

Lifecycle states

Every entitlement is in one of four states at any given time:

StateWhat it means
ActiveThe entitlement is in good standing. All downstream resources (licenses, services, environments) are live.
SuspendedTemporarily paused -- usually because of a failed payment or an admin hold. Can be reactivated.
ExpiredThe expiration date has passed. Downstream access is cut. Can be renewed with a new payment.
CancelledRevoked. Can only be reactivated through a deliberate win-back operation by an admin.

How transitions work

FromToWhat triggers itWho can do it
--ActiveCreated (auto-provisioning or manual)System / Admin
ActiveSuspendedPayment fails or admin places a holdSystem / Admin
ActiveExpiredExpiration date reachedCron (auto)
ActiveCancelledDirect cancellationAdmin
SuspendedActivePayment resolves or admin lifts holdSystem / Admin
SuspendedCancelledConfigurable timeout or admin decisionSystem / Admin
ExpiredActiveCustomer renews (new payment)System / Admin
ExpiredCancelledConfigurable timeoutSystem / Admin
CancelledActiveWin-back (reactivates the same code)Admin only

No transitions outside this table are allowed. An entitlement cannot jump from expired directly to suspended, for example.

Payment recovery

When a payment fails (detected via Stripe webhook), MIDDAG Account consults the Payment Recovery Policy to decide what happens:

  1. Stripe retries the payment on its normal schedule.
  2. If the policy says "suspend on first failure," the entitlement moves to suspended immediately. Otherwise, it waits until all retries are exhausted.
  3. If a retry succeeds, the entitlement is automatically reactivated.
  4. If all retries fail, the entitlement stays suspended for a configurable period before automatic cancellation.

Admins can manually cancel a suspended entitlement at any time, or wait for the automatic timeout.

Win-back

A cancelled entitlement can be brought back to life. Win-back reactivates the same entitlement with the same code -- it does not create a new one. This preserves the full history: orders, invoices, contracts, and service requests all remain linked. Win-back is an admin-only operation (a deliberate human decision).

Auto-creation from orders

The most common way an entitlement is created is automatically, after a customer completes a purchase:

Each line item in an order has a product meta field (_middag_entitlement_class) that tells the system which class of entitlement to create. If no class is specified, the default is ORD (general purchase).

The process is idempotent: if a webhook fires twice for the same order, the system checks whether an entitlement already exists for that order + line item combination and skips creation if it does.

After the entitlement is created, downstream resources are provisioned automatically based on the class:

  • PLG creates a License (with activation key and download access)
  • ENV creates an Environment (status: provisioning)
  • SVC creates a Service, a Contract (if ongoing), and a Credit Balance
  • ORD links to the Order and Invoice
  • AFL links to an Affiliate record
  • EDU links to the Order and enables educational downloads

Manual creation

Admins can also create entitlements manually from the WordPress admin. This is useful for:

  • Migrating existing customers from a legacy system
  • Granting complimentary access
  • Setting up entitlements for deals that did not go through the standard order pipeline

Manually created entitlements behave identically to auto-created ones. The only difference is the auto_created flag, which is false for manual creation.

Sovereign entitlements

An entitlement does not require an Organization. All relationships are optional -- an entitlement can exist completely standalone, without any customer record attached. This is what "sovereign" means in MIDDAG Account.

This flexibility supports scenarios beyond traditional B2B:

  • Gift cards and promotional access -- entitlements issued without a purchase or customer
  • Individual customers (B2C) -- a person, not a company, can hold entitlements directly
  • Migration imports -- entitlements imported from external systems where the organization mapping does not exist yet
  • Shared licenses -- entitlements that are not tied to a single organization

The entitlement is the sovereign entity of the system. Everything else connects to it optionally.

Parent-child entitlements

Entitlements can be organized in a hierarchy. A common example: a Service entitlement (SVC) acts as a master contract, with Environment (ENV) and Plugin (PLG) entitlements as children underneath it.

Rules:

  • Default maximum depth is 3 levels (configurable through the Policy Engine)
  • Cycle detection prevents entitlements from being linked in loops
  • Child entitlements can share the parent's credit balance (configurable per child)
  • Each entitlement has its own expiration date -- a child can outlive its parent
  • When a parent is cancelled or expires, children are unlinked (not cancelled). They become standalone and continue with their own lifecycle.

Downstream resources

Each entitlement connects to the resources that the access grants. Which resources depend on the entitlement class:

ResourceDescription
LicenseSoftware license with activation keys and sites
ContractService agreement with terms and SLA
ServiceOngoing or project-based work
EnvironmentManaged hosting installation
InvoiceFinancial record linked through the order
DocumentShared files, certificates, reports
DownloadDownloadable files (software, materials)
Credit BalanceConsumable credits for service-based entitlements
Service RequestSupport tickets tracked against the entitlement

When an entitlement is suspended, its downstream resources follow: licenses become inactive, environments are paused, service requests are frozen. When it is reactivated, downstream resources come back online.

What admins see

In the WordPress admin, the entitlement list shows:

  • Entitlement code (with class prefix)
  • Product name
  • Organization name (or "standalone" for sovereign entitlements)
  • Status (with color indicators: green for active, yellow for suspended, gray for expired, red for cancelled)
  • Expiration date
  • Creation method (auto or manual)

Clicking an entitlement opens its detail view with tabs for linked orders, licenses, contracts, services, environments, and the full status history.

Admins can filter by class, status, organization, or date range. The search supports looking up entitlements by their code directly -- type PLG-2026040142 and get an instant result.

Expiration automation

A daily cron job handles expiration automatically:

  1. Scans for active entitlements whose expires_at date has passed and transitions them to expired.
  2. Scans for expired entitlements that have exceeded the timeout configured in the Cancellation Policy and transitions them to cancelled.

No manual intervention is needed for routine expiration. Admins are notified of expiring entitlements through the dashboard and can take action (renew, extend) before the transition happens.