AlpineClubBookingsNZ v0.10.1
Tag: v0.10.1 · Previous: v0.10.0 (2026-07-07) · Merge commit: 331cb7e27.
What this release is
A patch release: four payment/booking-recovery hardening fixes and one operator
cleanup script on top of v0.10.0. No new features, and no behaviour changes
outside the raced/edge shapes the fixes close.
No database migrations, no schema changes, no post-upgrade actions.
docs/BLUE_GREEN_MIGRATION_SAFETY.tsv gains no rows and either app color can
serve throughout the deploy. The standard procedure still applies: back up the
database before deploying (docs/UPGRADING.md, "v0.10.0 → v0.10.1").
Changes
- Quote re-send vs concurrent decline race closed — an admin re-sending a
booking-request quote while the member declines can no longer resurrect a
DECLINED/CANCELLEDrequest or send its quote email; the losing re-send
rolls back with a 409. (#1508, issue #1504) - Recovery replays converged with their inline Stripe bodies — the
refund-request and booking-modification recovery replays previously sent a
differentreasonunder the same idempotency key, so Stripe rejected the
replay withidempotency_errorand recovery retried to exhaustion instead of
converging (safe-failing; never a double refund). Shared per-path body
builders now guarantee byte-identical replays. (#1509, issue #1507) - Refund-appeal allocation plan frozen — the approve route computes the
per-transaction Stripe refund allocation once, uses it inline, and persists
the same slices to the recovery operation on inline failure, so a replay
re-requests exactly the original slices under the original idempotency keys.
Supersedes the completed-refund remainder heuristic; in the exotic mixed
Stripe + Internet-Banking appeal shape the route now refunds the plannable
Stripe portion inline and logs any shortfall (net Stripe money unchanged; the
IB portion still settles via credit note). (#1513, issue #1510) - Aggregate per-invoice cap on never-settled Internet-Banking credit mint —
multiple never-settled IB payments matched to a single invoice can no longer
collectively mint account credit above that invoice's cash. No current app
flow produces the aggregate shape, so real-flow mint amounts are unchanged.
(#1512, issue #1505) - New operator script
npm run payments:backfill-cancel-flattened— a
one-off, idempotent, dry-run-by-default backfill restoring the stored
Payment.statuson rows the pre-#1489 cancel defect flattened toFAILED
on cancelled bookings. The read path already compensates, so this is
cosmetic-only for stored rows; it makes no Xero and no Stripe calls. See
"Backfill cancel-flattened payment statuses" indocs/MAINTENANCE.md.
(#1511, issue #1506)
Optional post-upgrade cleanup
If your fork ever ran a pre-v0.10.0 build, booking cancellations may have
flattened captured (PARTIALLY_)REFUNDED payments' stored status to
FAILED. You can restore the stored rows with
npm run payments:backfill-cancel-flattened — dry-run first, review the
report, then re-run with --apply. Detail in docs/MAINTENANCE.md.
Validation evidence
- Release PR #1514 CI fully green at head
f9c396c75(tree identical to the
merge commit):verify(lint, typecheck, tests, build), Playwright E2E,
Migration drift check, Static analysis gate, CodeQL, dependency-review,
gitleaks (full-repo + PR-diff), docker-image-security. - Local on the release branch:
npm run lint0 errors (5 pre-existing
warnings, unchanged from the v0.10.0 cut);npm run typecheckpass (banner
alpine-club-bookings-nz@0.10.1). npm run db:check-driftnot run — no schema change in this release
(git diff v0.10.0..v0.10.1 -- prisma/is empty).- An independent review agent verified changelog completeness (all 5
first-parent merges sincev0.10.0covered, no direct commits), the
no-migrations claim, the version bump, and the UPGRADING/MAINTENANCE
cross-references before merge.
Images
Published by main CI for the merge commit:
ghcr.io/thatskiff33/alpineclubbookingsnz-app:331cb7e2784fedc862e6feca712d7ba3dcf13193ghcr.io/thatskiff33/alpineclubbookingsnz-migrate:331cb7e2784fedc862e6feca712d7ba3dcf13193
Maintainability follow-ups (non-blocking)
Unchanged from v0.10.0 — the current known-hotspots list in
docs/MAINTENANCE.md (large-file split queue headed by
src/lib/xero-operation-outbox.ts, queued for PR-b of #1272's replay-stack
co-location).