Documentation
Entitlements & Security
How entitlement resolution works, and security caveats to review before production.
Entitlements & Security
Entitlement resolver
resolve_entitlements(app_id, customer_id, now) returns an array of
EntitlementInfo:
interface EntitlementInfo {
identifier: string
is_active: boolean
will_renew: boolean
period_type: string
latest_purchase_date: string
expires_date: string
grace_period_expires_date: string | null
store: 'app_store' | 'play_store' | 'stripe'
product_identifier: string
}An entitlement is active when any linked subscription's
current_period_end > now or its grace_period_expires_at > now:
Security caveats
Apple JWS chain verification is rooted in Apple's Root CA - G3
apple_decode_jws_payload (in stackhouse/src/billing/validators.rs) does
real cryptographic signature verification: it checks the JWS signature
against the leaf certificate's public key (ES256/RS256), validates x5c
chain consistency, and then pins the root to Apple's published Root CA - G3.
A forged notification built with its own self-manufactured 3-cert chain
(fake leaf/intermediate/root, all internally consistent) whose root is not
Apple Root CA - G3 is rejected. The pinned root certificate is embedded in
stackhouse/src/billing/validators.rs.
Stripe signature verification
Uses the documented t=…,v1=… scheme with constant-time comparison and a
5-minute clock-skew tolerance.
Google Play validation
Requires you to mint the OAuth2 service-account token yourself; pass it
per-request or via STACKHOUSE_BILLING_GOOGLE_ACCESS_TOKEN.