40 Commits
Author SHA1 Message Date
mizorewwwandClaude Opus 5.5 a95535f437 Drop frontend gates that no longer protect anything
- The public form submits directly; the extra "confirm generating a link"
  dialog repeated guidance the form already shows, and creating a link never
  charges.
- queue_protocol is no longer sent, and the order check is reduced to
  "not a queue ticket and either paid or carrying a link" instead of
  re-validating every field and the Stripe URL the server just verified.
- Redemption status polling no longer stops after five minutes with a
  "continue" button; it keeps reading at a slower pace until the order
  settles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:40:33 +08:00
mizorewwwandClaude Opus 5.5 37e0b2720e Confirm public order payments with Stripe in the order lookup
The lookup used to read local records only, so a visitor who paid after the
queue stopped watching saw "expired, no payment recorded". For a created
order it now runs the same read-only Stripe completion check the payment
window uses, records a confirmed payment on the order (and frees its window)
when the order lock is free, and says whether Stripe could be reached. It
still never creates orders or joins the queue; the lookup limit drops to 6
requests per minute per IP because each one may call Stripe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:39:43 +08:00
mizorewwwandClaude Opus 5.5 9c41404b4f Relax limits that do not protect payments
- Replacement links after an operator-verified decline are no longer capped
  at three; each still needs the unpaid attestation and decline evidence.
- A payment node with a transport failure cools for 30 minutes, not 6 hours.
- Review orders keep being reconciled for 7 days instead of 24 hours.
- Recovery previews stay valid for an hour instead of 10 minutes.
- Code generation allows up to 2000 per batch and moves up to 1000 codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:38:46 +08:00
mizorewwwandClaude Opus 5.5 4b3c9802e3 Make the public queue clearer while waiting in the background
- Tab title shows queue position, then the payment countdown, so a
  backgrounded tab still tells people when to come back and pay.
- The ready-notification button moves above the payment warning, starts as
  enabled when permission was already granted, and is hidden where browsers
  cannot notify; phones vibrate when the link is ready.
- Waiting copy no longer says backgrounding is safe; it states the 90-second
  pause and 5-minute removal that the queue actually enforces.
- User-not-found, ineligible and expired-ticket errors say what happened,
  that nothing was charged, and what to do next; errors scroll into view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:29:11 +08:00
mizorewwwandClaude Opus 5.5 d19bc87eac Add a read-only payment status lookup for public orders
GET /api/manual-link/order?username= returns the newest public order that
this browser's cookie created for that X username: plan, link creation time
and a coarse state (paid, open, ended, not created). It reads local records
only, never joins the queue or creates orders, and never returns links, card
data or other browsers' orders. Paid state also uses the verification the
queue records for the last payment window. The public form and the payment
link card can run the lookup. Refs #6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:28:19 +08:00
mizorewwwandClaude Opus 5.5 eb67f9ec55 Show queue length and estimated wait before joining
Add a read-only GET /api/manual-link/queue that reports how many people are
waiting and the estimated wait for a newcomer, sharing the estimate used for
queued tickets. The public form and confirmation dialog show it so people
know the wait before they commit to keeping the page open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:26:50 +08:00
mizorewwwandClaude Opus 5.5 3ea0858f76 Recover live payment links on refresh and drop finished results
After a link was delivered the saved queue session stayed behind and
/queue/current returned finished tickets, so a refresh or later visit
replayed "付款链接已更新或失效". The page now saves the link's expiry and
forgets the session once it expires, is paid, or fails; the server only
recovers a finished ticket while its link is still live and answers 410
for ended links so the page returns to the clean form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:25:58 +08:00
mizorewwwandClaude Opus 5.5 8539669982 Accept any catalog plan in queue snapshots and saved sessions
Restoring the queue rejected anything other than 3 or 6 months, so a single
12-month ticket stopped the service from starting. Tickets are now checked
against 1..24 and the configured catalog, and invalid entries are skipped
with a log line. The page's saved queue session accepts the same range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:24:29 +08:00
mizorewwwandClaude Opus 5.5 2249b1fd1a Show final queue failures instead of reconnecting forever
Stored queue results never change, but terminal failures were saved as 502
and the page retried every 5xx, so users saw "reconnecting" indefinitely.
Pending and expired-link outcomes now answer 409, any other stored 5xx is
normalized to 422 (also for restored snapshots), lock failures are retried
by the worker, and the page reconnects only on network errors, 429, 502,
503 and 504.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:23:55 +08:00
mizorewwwandClaude Opus 5.5 e248d18b9a Explain queue waits and the three-minute payment window in public link guidance
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:19:48 +08:00
mizorewww 002e42d962 Restore queue positions after refresh and protect in-flight payments 2026-10-06 19:06:59 +08:00
mizorewww 3840bad7f0 Preserve payment queues across restarts and use three-minute windows 2026-10-06 17:31:42 +08:00
mizorewww 015f8021cf fix: reject legacy queue clients and validate payment results before rendering 2026-10-06 16:41:52 +08:00
mizorewww d8e75744ba fix: replace public gift plans immediately and renew expired links without manual gates 2026-10-06 16:35:43 +08:00
mizorewww cfb51cced6 fix: serialize checkout creation with a durable 15 minute payment window 2026-10-06 16:13:46 +08:00
mizorewww a5667bbbb2 fix: verify public checkout links and add a paced queue with Material status cards 2026-10-06 16:00:12 +08:00
mizorewww 7a5d4c8db0 feat: protect public submissions with Cloudflare Turnstile 2026-10-04 18:07:48 +08:00
mizorewww f7c21669bf feat: add isolated public Stripe checkout links in homepage FAQ 2026-10-04 17:56:52 +08:00
mizorewww 0a83e609e1 fix: prevent manual payment form fields from collapsing 2026-10-04 17:40:49 +08:00
mizorewww ef83f0e396 feat: generate manual Stripe payment links by username and duration 2026-10-04 17:34:32 +08:00
mizorewww a0599ec504 fix: cool authentication-challenged cards and guard operator recovery 2026-10-04 14:45:24 +08:00
mizorewww f355d1557d feat: split admin recovery panel into node and payment card cards
Move the Stripe node pool and per-card status out of the recovery card
into two dedicated panels with skeleton, empty, paused, and
failure-and-retry states. Translate backend card problem and block
reasons into Chinese, explain the rotation cadence and pair cooldowns,
warn when no card can currently pay, and drive the pause warning from
the real PaymentPaused flag instead of the site-wide switch.

Refresh the preview mock with realistic rotation values, real reason
strings, and a PREVIEW_NETWORK=direct switch; rebuild the assets.
2026-10-04 14:27:36 +08:00
mizorewww 83ac3f00ae feat: add card rotation, customer lookup, and concurrent eligibility checks
Add encrypted card pool management, persisted card and outbound rotation, and per-card decline cooldowns. Improve customer and redemption-code lookup, recovery controls, and filtering; rebuild frontend assets and refresh mock screenshots.

Give read-only eligibility checks four independent slots so payment processing no longer blocks them. Cover concurrency, slot cleanup, card rotation, and lookup behavior with tests.
2026-10-04 11:44:38 +08:00
mizorewww 92f09423c3 feat: add payment node cooldown and safe network retries 2026-10-04 01:50:08 +08:00
mizorewww 7493a72941 feat: add order recovery and per-order payment proxy pools
Add customer code lookup, single-order and batch recovery, and verified replacement checkout links with preserved payment evidence.

Add payment pause controls, persisted per-order outbound selection, proxy diagnostics, admin status, documentation, tests, and rebuilt frontend assets.
2026-10-03 21:59:14 +08:00
mizorewww 56c606ca40 feat: add pre-redemption eligibility check
POST /api/check runs the read-only X gifting-eligibility query for
a username under the shared work semaphore with its own 8/min rate
bucket, so visitors can verify their account before redeeming. The
redeem page gains an advisory check button with loading and result
states.
2026-10-03 17:29:32 +08:00
mizorewww a9589a3867 feat: extend filter expressions with NOT, inequality, and more fields
Add stackable complement operators (not/!/非), per-condition
inequality (status!=active, clickable = / ≠ toggle on canvas
tokens), and months/username conditions with - for empty values.
The palette gains duration and account groups, and full-width
operator punctuation is normalized.
2026-10-03 17:29:31 +08:00
mizorewww 99876953f9 feat: rebuild the filter as a palette token builder
The expression renders as deletable rounded-rectangle tokens on a
canvas, composed from a guarded palette of status/folder/logic
buttons, with a raw-text mode for power users. Guards prevent
invalid sequences, mid-deletions explain what broke and how to
repair it, full-width punctuation is normalized, and all actions
are announced to screen readers.
2026-10-03 16:55:57 +08:00
mizorewww a4f37555d6 feat: add client-side expression filter to the codes table
Compose folder and status conditions with and/or/parentheses in the
admin UI (typed or assembled from helper chips). In filter mode all
pages are fetched and matched client-side with local pagination, so
no backend changes are needed. Invalid expressions show precise
Chinese errors without fetching.
2026-10-03 14:16:48 +08:00
mizorewww f5f80b7d42 feat: add copyright and GitHub link footer to both pages 2026-10-03 13:13:13 +08:00
mizorewww 1a0aaa3dc6 feat: redesign stats dashboard charts for readability
Replace the cramped 90-bar grouped activity chart with three
single-series small-multiple strips (created, redeemed, succeeded),
give plan and review-stage bars proper height with legends and
percentage labels, and lay the summary cards out 3x2 on desktop.
2026-10-03 12:48:45 +08:00
mizorewww a31de399ad feat: add admin statistics dashboard and polling resume
Add GET /api/admin/stats aggregating code counts, redemption and
success rates, per-plan totals, a 30-day activity series, and review
stage distribution. Render a collapsible stats panel with summary
cards and an accessible SVG bar chart on the admin page, show total
count and pages in pagination, and let users resume status polling
after the 5-minute timeout without re-redeeming.
2026-10-03 11:38:34 +08:00
mizorewww 7162039c6d feat: resume unsubmitted review orders through explicit user action 2026-10-03 10:53:39 +08:00
mizorewww cf2a058e77 fix: reserve batch navigation height to prevent loading layout shifts 2026-10-02 19:28:36 +08:00
mizorewww ba162cb7d1 fix: use batch folders and explicit icon actions with row copying 2026-10-02 19:26:31 +08:00
mizorewww c06fbe466d feat: manage redemption folders from the admin dashboard 2026-10-02 19:15:18 +08:00
mizorewww 07820c8f48 feat: copy newly generated redemption codes with one click 2026-10-02 19:07:26 +08:00
mizorewww abba32850c fix: keep card position stable when switching appearance 2026-10-02 19:06:22 +08:00
mizorewww 2cc8d8acde fix: centralize theme colors and use neutral gray surfaces 2026-10-02 19:04:08 +08:00
mizorewww b4b9d2a36d feat: migrate redemption and admin UI to themed React and MUI 2026-10-02 19:02:21 +08:00