Changelog
All notable changes to Generous.nz are recorded here, grouped by version. Every deployed build has a version number, a git tag, and an entry below.
Versioning scheme
Versions follow MAJOR.MINOR.PATCH:
- 0.x — pre-launch. Minor bumps mark a completed build phase or major feature set; patches are bug fixes on the current build.
- 1.0.0 — first public launch.
- 1.x+ — post-launch: minor = new features, patch = fixes, major = breaking changes or significant re-architecture.
Each version is tagged in git (v0.2.0) and the current version is kept in
package.json. See docs/version-control.md for how to cut a release.
[0.9.189] — 2026-08-26
Fixed
- Purchase history now survives item deletion. Verified at the database
level:
Order→Product/FundraiserandDonation→FundraiseruseON DELETE RESTRICT, so hard-deleting a product or fundraiser with orders fails instead of wiping them, and the app's own remove/delete flows were already soft (statusREMOVED/ARCHIVED). The one cascade that could erase sold vouchers —VoucherCode.wholesaleProductId→CASCADE— is nowSET NULL, so purchasers keep their vouchers in "My purchases" even if a wholesale product is hard-deleted. Wholesaler voucher lists/export handle removed products gracefully.
[0.9.188] — 2026-08-26
Changed
docs/bulk-test-runbook.mdupdated: disputes/refunds/payouts on seller accounts are now covered by the daily reconciliation job (v0.9.187); only recurring-donation renewals still need the seller webhook secret.
[0.9.187] — 2026-08-26
Added
- Daily connected-account reconciliation (
lib/payments/stripe-sync.ts, wired into/api/cron/reconcilewhich the daily app cron already calls). With the direct-charge model, Stripe sends dispute, refund and payout events to the seller's own account rather than the platform webhook — this job now polls every connected account over a rolling lookback (default 7 days,RECONCILE_LOOKBACK_DAYS) and replays the same logic the webhook would have run: mark orders/donations disputed or refunded, hold/cancel/restore commission, apply fee credits, notify sellers, raise moderation flags, and keep payout history current. Everything is idempotent, so missed webhooks self-heal on the next run, and seller-initiated refunds (which the webhook never saw) are now captured too.
[0.9.186] — 2026-08-26
Changed
docs/bulk-test-runbook.mdcorrected after the second full test run: Step 3 now makes clear thatcreate-checkouts-2.jsis only for re-creating wholesale checkouts that failed in the main script (running it otherwise duplicates orders), and stalecheckouts2.jsonshould be deleted before a fresh run..attach-shared-account.js(server helper, not app code) was also fixed to recreate a plain index so re-runs work.
[0.9.185] — 2026-08-26
Added
docs/bulk-test-runbook.md: the full automated test runbook for Stripe test mode. Saying "run testing" in a future conversation executes Steps 0–6 (test-mode check, seed data, shared test account attach, checkout creation, automated card payments, database/email verification, cleanup) and reports results per scenario.
[0.9.184] — 2026-08-26
Fixed
- Voucher gift purchases now actually email the recipient. The order API accepted the gift name/email/message but never saved them on the order, so the "You've received a voucher" email to the gift recipient never fired. Gift details are now stored in the order metadata and used by the voucher delivery flow.
[0.9.183] — 2026-08-26
Fixed
- Orders and donations no longer depend on the seller's own Stripe webhooks
to finalise. With the direct-charge model, Stripe delivers payment events to
the connected seller account rather than the platform, which left paid
orders stuck on "pending". The checkout success pages now retrieve the
Stripe session on the seller's account and finalise the order/donation
immediately (idempotent; the webhook path still runs as a backstop). The
finalise logic was extracted to
lib/payments/finalise-checkout.tsand is shared by both paths, so receipts, WhooHoo emails, voucher assignment, stock, settlements and goal celebrations behave identically. - Donation checkouts now carry the session id in the success URL so the fundraiser page can finalise a just-completed donation the same way.
[0.9.182] — 2026-08-26
Fixed
- Wholesaler platform-fee direct debits now supply the
return_urlStripe requires at PaymentIntent confirmation (Stripe was rejecting off-session card debits without it, which showed up as payment failures in the Stripe dashboard). If a bank still asks for cardholder authentication, the invoice is marked failed with a clear reason and the business is emailed a link to their Billing settings, instead of the debit silently hanging.