Files
firefrost-services/services
Claude 9777a7af9d feat(arbiter): Task #126 lifecycle handlers — We Don't Kick People Out
Implements the Firefrost core policy that Awakened ($1) is lifetime access.
Paying customers are never removed from access — only demoted to Awakened
when a paid subscription ends. Hard bans reserved for actionable violations
(chargebacks and refunds).

Changes:
- customer.subscription.deleted: demote to Awakened instead of grace period
  * Uses existing 'lifetime' status + is_lifetime=TRUE (no schema changes,
    no touches to other filters in servers.js/roles.js/financials.js)
  * Calls downgradeToAwakened() to strip tier role and assign Awakened
  * Audit log entry tagged with policy
- New charge.refunded handler: hard ban with Trinity appeal eligibility
  * Mirrors charge.dispute.created pattern
  * appeal_eligible: true flag in banned_users.notes
  * removeAllRoles() (NOT demote — refund is a hard ban)
- Added downgradeToAwakened to stripe.js imports

Left unchanged (intentionally):
- invoice.payment_failed: marks past_due, trust Stripe's retry logic
- invoice.payment_succeeded: clears grace period (harmless legacy field reset)
- charge.dispute.created: already correct under new policy
- checkout.session.completed: syncRole already handles Model A (Awakened
  automatically assigned on any first purchase via tier role replacement)

Co-authored with Michael (The Wizard)
Task #126 — Soft launch blocker
2026-04-11 23:04:30 +00:00
..