feat(billing): Polar.sh Pro subscription integration
Some checks failed
CI / UI (push) Successful in 1m36s
CI / Backend (push) Successful in 59s
Release / Test backend (push) Successful in 39s
Release / Check ui (push) Successful in 33s
CI / Backend (pull_request) Successful in 44s
CI / UI (pull_request) Successful in 34s
Release / Docker / runner (push) Successful in 2m44s
Release / Docker / ui (push) Successful in 2m45s
Release / Docker / backend (push) Successful in 3m35s
Release / Docker / caddy (push) Successful in 1m8s
Release / Gitea Release (push) Failing after 2s

- Webhook handler verifies HMAC-SHA256 sig and updates user role on
  subscription.created / subscription.updated / subscription.revoked
- Audio endpoint gated: free users limited to 3 chapters/day via Valkey
  counter; returns 402 {error:'pro_required'} when limit reached
- Translation proxy endpoint enforces 402 for non-pro users
- AudioPlayer.svelte surfaces 402 via onProRequired callback + upgrade banner
- Chapter page shows lock icon + upgrade prompts for gated translation langs
- Profile page: subscription section shows Pro badge + manage link (active)
  or monthly/annual checkout buttons (free); isPro resolved fresh from DB
- i18n: 13 new profile_subscription_* keys across all 5 locales
This commit is contained in:
Admin
2026-03-29 13:21:23 +05:00
parent 83b3dccc41
commit 98631df47a
19 changed files with 539 additions and 13 deletions

2
ui/src/app.d.ts vendored
View File

@@ -6,9 +6,11 @@ declare global {
interface Locals {
sessionId: string;
user: { id: string; username: string; role: string; authSessionId: string } | null;
isPro: boolean;
}
interface PageData {
user?: { id: string; username: string; role: string; authSessionId: string } | null;
isPro?: boolean;
}
// interface PageState {}
// interface Platform {}