TinyShip 2.9.0 Released
This release matches GitHub v2.9.0: AI credit billing, video task persistence, pending order resumption, and multi-channel admin refunds. The Cloudflare edition tinyship-cf is synchronized at 1.2.0 (aligning pending orders and refund flows, without #50 AI credit billing / video task tables).
Highlights
- AI credit billing: Chat charges per reply without exceeding balance; image/video generation holds credits upfront, confirming on success and idempotently refunding on failure (#50)
- Video task persistence: Added
ai_video_task(migration0008); credits refund at most once on failure or service restart; supports listing tasks for the current user (#50) - Pending orders: Users can "Pay now / Cancel"; admins can mark as paid or cancel; lazy expiration on listing (default 2h,
ORDER_PENDING_TTL) (#52) - Pending order resumption: "Pay now" calls
POST /api/payment/resumeto reuse the existing order instead of redirecting back to the pricing page (#54) - WeChat Pay: Integrated better-wechatpay with native refund support, revoking entitlements only after receiving
REFUND.SUCCESS(#53) - Multi-channel admin refunds: One-click full refunds for WeChat, Stripe, Alipay, PayPal, and Dodo; Creem records
transactionIdonly (no refund button); Waffo managed via dashboard (#53 #54)
Fixes
- Added missing baseline PostgreSQL migration
0000_optimal_mad_thinker.sqlso fresh databases can rundb:migrate(#51) - Aligned outdated unit tests to restore all green test suites for
pnpm test(#51)
Testing
- AI credits & video: SQLite / D1 / PostgreSQL integration tests + 3-framework E2E (with local mock AI)
- Pending orders, resumption, and multi-channel admin refunds: unit tests + E2E (including Stripe admin refund)
Upgrade
Run migrations after upgrading:
pnpm db:migrate # PostgreSQL
pnpm db:migrate:sqlite # SQLite / D1Note: Environments initialized with db:push that have an empty migration history table should not switch directly to running a full migrate, as this will attempt to recreate tables starting from 0000.