entitlement-grant · git:20260913.51c1b6d · 2026-09-13 · sha256 662578bf33f27b38

entitlement-grant git:20260913.51c1b6dA

Immutable. This exact content never changes and is served at /api/v1/blob/662578bf33f27b38.

---
name: entitlement-grant
description: Use when verified purchases, subscriptions, durable unlocks, consumables, or time-limited access must be granted exactly once across retries, crashes, duplicate callbacks, and multiple devices.
---

# Entitlement grant

This skill owns verified purchase-event → durable entitlement state. Store UI and pricing belong elsewhere; `restore-purchase` owns user-initiated/current-entitlement reconstruction.

## Product classes

| Class | Durable state |
|---|---|
| non-consumable/durable-unlock | boolean/ownership keyed by product plus store identity |
| consumable | balance mutation keyed by a unique transaction/purchase token/event id |
| subscription/time-pass | entitlement interval/status keyed by the store's stable subscription identity/token |
| battle-track/season | ownership scoped to season/content identity |

## Idempotent transaction state machine

Use the immutable store transaction ID, purchase token, or equivalent verified event ID as the deduplication key; do not use UI callbacks or order display strings as the primary key.

A safe abstract flow is:

1. receive `pending`/purchased event and persist processing state;
2. verify authenticity/account/product and confirm it is grantable;
3. in one durable transaction, record the event ID and apply the entitlement/balance mutation if that event ID is not already committed;
4. only after durable grant, acknowledge / consume / finish according to product/store requirements;
5. if acknowledgement/consume/finish fails, retry that store-side completion **without granting again**;
6. emit UI refresh from durable entitlement state.

For stores that require consumption before re-purchase, preserve enough pending state that a crash cannot lose a consumed-but-not-accounted grant. Platform adapters may vary the exact store call sequence, but they must prove no crash window can duplicate or lose value.

`PENDING` or unverified purchases do not grant. Revocation/refund handling updates entitlement through an explicit policy rather than deleting unrelated story progress.

## Acceptance

Replay the same transaction/purchase token many times; kill after verification, after durable grant, and before/after acknowledge/consume/finish. The resulting durable entitlement or consumable delta is applied exactly once, and store completion can retry independently. Test pending→purchased and refund/revoke paths. Unrun sandbox/server cases stay `not-run`.