Paid episodes:
- server/services/cashu.ts: self-custodied Cashu wallet against a configured
mint (NUT-04 mint quote -> bolt11 invoice -> mint/store proofs -> LNURL-pay
payout on withdraw). Buyers pay a plain Lightning invoice, no Cashu wallet
needed on their end.
- routes/marketplace.ts: purchase/confirm flow, download-url paywall gate,
reseller certification/revocation, earnings ledger + withdraw.
- services/marketplace.ts: producer + certified-reseller source resolution,
with a naive per-seller sales-count reputation signal.
Discovery:
- services/rss.ts: <podsteadr:source> RSS tag on priced episodes (producer +
resellers, price, sales count, url) so pricing/sources are discoverable
straight from the feed, not just a separate API call. Locked episodes point
their <enclosure> at an info page instead of the raw file.
- routes/feeds.ts: /catalog.opml lists every podcast this instance hosts, for
peer podsteadr servers or any OPML-aware crawler to discover without a
central directory.
Frontend: episode wizard price/reseller controls, sources display, earnings
dashboard.
Also fixes CORS and a container-image reference:
- app.ts: register @fastify/cors, open on the catalog/feed/sources endpoints
(already deliberately public/crawlable) and on purchase/confirm (already
accept stateless NIP-98 header auth for exactly this case). Credentials
stay off, so the session cookie never crosses origins — cookie-authed
admin routes stay same-origin-only. Needed so external clients like
podsteadr-player can browse/buy/play from a different origin.
- docker-compose.yml: fully qualify the mediamtx image reference
(docker.io/bluenviron/mediamtx:1.19.2) — some Podman hosts have no
unqualified-search registry configured and fail to resolve short names.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>