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:
| State | What it means |
|---|---|
| Active | The entitlement is in good standing. All downstream resources (licenses, services, environments) are live. |
| Suspended | Temporarily paused -- usually because of a failed payment or an admin hold. Can be reactivated. |
| Expired | The expiration date has passed. Downstream access is cut. Can be renewed with a new payment. |
| Cancelled | Revoked. Can only be reactivated through a deliberate win-back operation by an admin. |
How transitions work
| From | To | What triggers it | Who can do it |
|---|---|---|---|
| -- | Active | Created (auto-provisioning or manual) | System / Admin |
| Active | Suspended | Payment fails or admin places a hold | System / Admin |
| Active | Expired | Expiration date reached | Cron (auto) |
| Active | Cancelled | Direct cancellation | Admin |
| Suspended | Active | Payment resolves or admin lifts hold | System / Admin |
| Suspended | Cancelled | Configurable timeout or admin decision | System / Admin |
| Expired | Active | Customer renews (new payment) | System / Admin |
| Expired | Cancelled | Configurable timeout | System / Admin |
| Cancelled | Active | Win-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:
- Stripe retries the payment on its normal schedule.
- If the policy says "suspend on first failure," the entitlement moves to
suspendedimmediately. Otherwise, it waits until all retries are exhausted. - If a retry succeeds, the entitlement is automatically reactivated.
- If all retries fail, the entitlement stays
suspendedfor 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:
| Resource | Description |
|---|---|
| License | Software license with activation keys and sites |
| Contract | Service agreement with terms and SLA |
| Service | Ongoing or project-based work |
| Environment | Managed hosting installation |
| Invoice | Financial record linked through the order |
| Document | Shared files, certificates, reports |
| Download | Downloadable files (software, materials) |
| Credit Balance | Consumable credits for service-based entitlements |
| Service Request | Support 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:
- Scans for active entitlements whose
expires_atdate has passed and transitions them toexpired. - 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.
Related pages
- Entitlement Classes -- the types of entitlements and what each one provisions
- Policies -- the rules that govern entitlement behavior
- Orders -- how purchases create entitlements
- Organizations -- the customer entity that (optionally) owns entitlements
- How Concepts Connect -- the full relationship diagram