67 Commits
Author SHA1 Message Date
mizorewwwandClaude Opus 5.5 08f2a718e5 Carry the v1 public queue snapshot into v2 so waiting users keep their places
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:41:59 +08:00
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 4310a225e1 Split redemption messages and database setup out of large functions
redeemMessage replaces a chain of overriding assignments in the redemption
worker, and openSiteDB moves schema setup and migrations out of Run. An order
whose checkout creation did not finish now invites the customer to recheck
and continue, matching the retry on the next explicit request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:37:53 +08:00
mizorewwwandClaude Opus 5.5 2d6c3ae625 Validate usernames and link cookies in one place
checkout.NormalizeUsername and checkout.ValidOwner replace the regular
expressions compiled inline in eight handlers and checkout entry points, and
the two public link entry points share one setup helper. A public link
request without the browser cookie now gets one instead of a 400 asking the
visitor to refresh. The public path no longer threads an unused
verified-unpaid flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:37:18 +08:00
mizorewwwandClaude Opus 5.5 acc9c53710 Return link outcomes as values and share one order lock helper
- createLink returns a linkOutcome instead of writing HTTP headers that the
  queue worker parsed back (Retry-After, X-Checkout-Wait-Seconds,
  X-Checkout-Requeue); the fake ResponseWriter is gone and the failure
  reason table is merged into the single error switch.
- tryLock/waitLock replace five copies of the worker slot plus checkout.lock
  dance (manual links, window holder, redemption, recovery, reconcile).
- A finished ticket replays its stored link until the payment window ends
  instead of re-verifying against Stripe after 15 seconds; expired links get
  410 and the order lookup reports payment.
- Queue tickets serialize directly (key v2), are saved on every structural
  change instead of a dirty/10-second checkpoint, and a damaged snapshot or
  ticket is dropped instead of refusing to start.
- The wait estimate is the creation window plus one payment window and build
  time per person ahead; the moving average is gone.
- Redemption waits up to 30 seconds for another order instead of failing
  with 503, the HTTP write timeout covers the 110-second link creation, and a
  full rate-limit table resets instead of rejecting everyone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:36:14 +08:00
mizorewwwandClaude Opus 5.5 fce2ca7c93 Drop upgrade-era compatibility and the permanent creation retry budget
- The active payment window no longer accepts the old 15-minute format or
  scans every order to bootstrap itself; a missing reservation means no window.
- Public link requests no longer need queue_protocol, unknown JSON fields are
  ignored, and an empty cancel beacon is no longer treated as leaving.
- Checkout creation never charges, so a saved-card order whose creation failed
  is retried on the next explicit request instead of being blocked forever;
  creation still uses the safe retry helper within one request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:32:41 +08:00
mizorewwwandClaude Opus 5.5 6d94885342 Remove unreachable card selection and recovery helpers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:31:43 +08:00
mizorewwwandClaude Opus 5.5 4dad582640 Trim the test suite to the payment-safety core
Keep only tests that guard against double charges, payment spacing, decline
handling, public link isolation, the payment window, queue ordering and
ownership, and the redemption resume path (about 20% of the former size).
checkFixture moves into the queue tests now that check_test.go is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:31:06 +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 64c54480cb Stop logging queue-head rate waits as manual link failures
Waiting for the active payment window is the normal state at the head of
the public queue and produced thousands of "manual link failed" lines.
Real failures are still logged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:24:00 +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 21ce3a1516 Release declined payment windows and requeue retries behind waiting users 2026-10-06 19:25:07 +08:00
mizorewww 93aac0a835 Recognize declined public payments when Stripe omits private amounts 2026-10-06 19:10:42 +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 5080d43d2b fix: reuse verified public checkout links across browsers for 15 minutes 2026-10-06 16:03:47 +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 50f0406d3a fix: recover unpublished public checkout attempts and clarify conflicts 2026-10-05 18:07:26 +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 4cb9119dbf feat: cool declined exits before cards and expose payment status
Route X account and eligibility checks directly while regional pricing
and checkout creation share the configured proxy exit, keeping quoted
currency and amounts consistent for the customer.

A decline now cools the card×node pair and the exit's shared IP for 30
minutes first; only a card declined through two distinct nodes enters a
whole-card cooldown, and do_not_try_again blocks just that card. Card
and rotation status stay readable with no cards configured and no longer
report expired cooldowns as blocks. Links-only recovery works without a
payment card, and the recovery status endpoint reports the
payment-protection pause.
2026-10-04 14:27:26 +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 b0ce2a249c feat: make the Stripe catalog operator-configurable
Move the hardcoded merchant account, product IDs, amounts and
currency into an encrypted catalog vault record read per checkout
flow. The setup wizard offers the X Premium defaults (X's public
gifting identifiers) or a fully custom catalog, put --name catalog
updates it, and status validates it. Tests use fake catalog
fixtures instead of real identifiers.
2026-10-03 12:48:46 +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 a8e7565448 fix(proxy): ignore services, endpoints and experimental sections
A pasted sing-box config carrying services (api/ssm-api), endpoints
(wireguard/tailscale), or experimental controllers (clash/v2ray/debug)
could bind non-loopback listeners or alter host networking once the
full include registries are enabled. Strip those sections so the
proxy record can only forward traffic; outbounds, route and dns still
pass through. Align the README outbound list (dns outbound was
removed in sing-box 1.12) and document the stripped sections.
2026-10-03 12:09:37 +08:00
mizorewww a15e6b5537 feat(proxy): accept any sing-box outbound including direct
Register the full sing-box include registries instead of the
anytls-only outbound registry so the vault proxy record may use any
core outbound type (direct, socks, http, shadowsocks, vmess, vless,
trojan, anytls, shadowtls, snell, ssh, tor, block, dns, selector or
urltest) plus route and dns sections. Reject configs without
outbounds early. The forced loopback mixed inbound and disabled log
are unchanged.
2026-10-03 11:54:31 +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 ab1096455c fix: retry transient X query failures and preserve encrypted diagnostics 2026-10-03 10:53:39 +08:00