Licensing Operations
This runbook covers day-to-day operations for acetab Pro access while Paddle is being finalized and after paid checkout goes live.
Architecture Summary
- License verification remains server-side at
/api/license/validate. - Promo issuance/redemption uses D1-backed APIs under
/api/admin/promo/*and/api/promo/redeem. - Admin access is expected to be protected by Cloudflare Access policy for
/api/admin/*and/admin/*. - The extension syncs entitlement via
extension/src/services/licenseEntitlement.ts(new tab, Options, and background). Turning onPRO_FREE_MODE_*in Cloudflare alone is not enough for users who never open Settings: the client must call/api/license/validateso localisPremiumupdates.
Environment Variables
Set these in Cloudflare Pages project environment:
ADMIN_ALLOWED_EMAILS— comma-separated admin emails permitted for admin APIs.ADMIN_ALLOW_DEV—trueonly for local/testing without Access identity headers.PRO_FREE_MODE_ENABLED— enables temporary global Pro access.PRO_FREE_MODE_UNTIL— optional ISO timestamp cutoff for the free window. Leave empty (or omit) for “until disabled manually.”
Pre-Paddle Hybrid Operations
1) Temporary Global Free Window
- Set
PRO_FREE_MODE_ENABLED=truein the Cloudflare Pages production environment (and deploy). Repository defaults inwebsite/wrangler.tomlare for local/preview only. - Optionally set
PRO_FREE_MODE_UNTILto a fixed date/time; omit it to run until you flip the flag. - Ship an extension build that includes automatic entitlement sync (
extension/src/services/licenseEntitlement.ts). - Monitor API logs for
license.free_mode_validateevents. - Disable by setting
PRO_FREE_MODE_ENABLED=falsewhen Paddle goes live (or when the campaign ends).
2) Invite / Promo Codes for Early Adopters
- Create campaign with
grant_type:trialwithdefault_duration_dayslifetime(stored as non-expiring premium license)
- Generate codes in batches from admin UI (
/admin/licensing). - Share plaintext codes through trusted channels only.
- Redeemers call
/api/promo/redeem(or use Settings → License → Redeem promo code in the extension) and receive a full license key.
Abuse Response
If abuse is detected:
- Pause campaign (
status=paused) or setdisabled_atfor compromised codes. - Revoke affected licenses via
/api/admin/licenses/revoke. - Issue replacement codes in a new campaign.
- Review
admin_audit_logandpromo_redemptionsfor scope.
Paddle Cutover Checklist
When Paddle is ready:
- Keep promo schema and endpoints (for support grants and comps).
- Verify webhook env vars and route are production-ready.
- Disable global free mode:
PRO_FREE_MODE_ENABLED=false
- Keep invite campaigns active only where intended.
- Confirm paid transactions create or upgrade licenses:
- Webhook upgrades existing promo/trial license by email where applicable.
- Update pricing/legal copy to clarify paid availability and invite policy.
Recovery Checklist
- If license validation fails unexpectedly:
- check D1 connectivity,
- verify migration
0004_promo_licensing.sqlapplied, - verify env vars are present in production environment.
- If admin endpoints return
401:- confirm Cloudflare Access policy and user email allowlist.