Skip to content

fix(payments,sub,api): webhook deduplication, HWID race guard, panic elimination, Hysteria2/Trojan/SS/gRPC/HTTPUpgrade/XHTTP support, Remnawave directives - #2

Open
reelsmaker2026 wants to merge 9 commits into
STEALTHNET-APP:mainfrom
reelsmaker2026:fix/payment-webhooks-and-api-panics
Open

reelsmaker2026 wants to merge 9 commits into
STEALTHNET-APP:mainfrom
reelsmaker2026:fix/payment-webhooks-and-api-panics

Conversation

@reelsmaker2026

@reelsmaker2026 reelsmaker2026 commented Sep 26, 2026 •

Copy link
Copy Markdown

Summary

This PR bundles a set of reliability fixes and subscription-format extensions developed in the reelsmaker2026 fork. All changes are backward-compatible and do not alter existing database schemas beyond an additive index.


Commits in this PR

SHA Scope Description
8c1f5ae fix(payments,api) Restore webhook deduplication, fix CryptoBot amounts, eliminate panics
805db28 feat(web) Dynamic theme auto-detection, cabinet help section, parity tests
a518f9b perf(api,worker) Delegate auth rate-limit expiry to worker, add window_start index
b9e05c8 fix(sub,web) Serialize device admission to prevent HWID race, polish checkout UX
82dbf1f feat(sub) Support Remnawave template directives (injectHosts, include-proxies)
3f80c42 fix(sub) Use serde_json Map entry on object value for template directives
43365dd feat(node) Pre-flight auto-download of missing Xray geodata assets
36be4b9 feat(sub) Support Hysteria2, Trojan, Shadowsocks in Clash and Sing-Box formats
9901a9c feat(sub) Support gRPC, HTTPUpgrade, XHTTP transports in Clash and Sing-Box

Total: 28 files changed, +1 120 / -102 lines


Changes

1 — Webhook deduplication & payment-provider fixes (8c1f5ae)

Files: crates/payments/src/providers/cryptobot.rs, crates/payments/src/providers/generic_http.rs, crates/api/src/pay_routes.rs, crates/api/src/catalog_routes.rs, crates/payments/tests/webhook_regression.rs

  • Restored idempotency guard in both the CryptoBot and generic HTTP payment providers. Duplicate webhook deliveries from payment gateways (common during retries) no longer result in double-crediting or duplicated subscription renewals.
  • Fixed CryptoBot amount parsing: amounts were being read as a string field and silently converted to zero when the gateway returned a numeric JSON value; now handled correctly for both representations.
  • Eliminated two API panics: unwrap() calls on Option in catalog_routes.rs and profile_workflow.rs replaced with proper ? propagation, preventing unhandled panics under edge-case inputs.
  • Added regression test suite (webhook_regression.rs, 183 lines): covers idempotent replay, correct amount extraction, and provider-level error paths.

2 — HWID race condition fix (b9e05c8)

Files: crates/api/src/sub_routes.rs, crates/sub/src/main.rs, web/app/app.js, web/app/customer-en.js, web/app/customer-ui.js

  • Serialized device admission with SELECT ... FOR UPDATE inside a transaction. Previously, concurrent subscription requests for the same client (e.g., two devices connecting at the same moment) could both pass the device-limit check before either inserted its row, resulting in over-limit device registration.
  • The fix: lock the client row first, then re-check used and known counts inside the same transaction — concurrent admissions are fully serialized without deadlock risk.
  • Polished the manual checkout UX: clearer messaging when a device limit is reached.

3 — Auth rate-limit performance (a518f9b)

Files: crates/api/src/cabinet.rs, crates/api/src/security.rs, crates/worker/src/main.rs, db/migrations/049_auth_limits_index.sql

  • Moved TTL-based expiry of auth-rate-limit windows from the API request path into the background worker, reducing per-request query latency.
  • Added window_start index (migration 049) to make expiry sweeps efficient even with large auth-attempt tables.

4 — Dynamic theme auto-detection & cabinet help section (805db28)

Files: web/theme.js, web/help.js, web/help-en.js, devtools/tests/help-parity.test.cjs, .gitignore, Makefile

  • Added OS-level dark/light theme auto-detection (prefers-color-scheme media query) in theme.js.
  • Added a cabinet help section with English copy (help-en.js).
  • Added 60-line parity test suite (help-parity.test.cjs) ensuring RU/EN help strings stay in sync.

5 — Remnawave template directives (82dbf1f + 3f80c42)

Files: crates/sub/src/policy.rs, crates/sub/Cargo.toml, web/subscription-studio.js

  • injectHosts: merges an operator-supplied hosts map into the outbound proxy objects in Sing-Box / Clash templates, without overwriting unrelated keys.
  • include-proxies: filters the generated proxy list down to a named subset, allowing per-user or per-plan subscription templates.
  • Fixed a follow-up bug (3f80c42) where the directive processor incorrectly inserted into a JSON array instead of the object's map entry, causing malformed output for nested object values.

6 — Pre-flight auto-download of Xray geodata assets (43365dd)

Files: crates/node/src/engine_update.rs, crates/node/src/main.rs

  • Added a pre-flight check that automatically downloads missing Xray geodata files (geoip.dat, geosite.dat) before the node engine starts, eliminating a common manual setup step and preventing startup failures on fresh nodes.

7 — Protocol support: Hysteria2, Trojan, Shadowsocks (36be4b9)

Files: crates/sub/src/formats.rs

Extended the Clash and Sing-Box subscription serializers to emit correct proxy objects for:

Protocol Clash output Sing-Box output
Hysteria2 hysteria2 proxy type with up/down bandwidth, obfs, pinned cert hysteria2 outbound
Trojan trojan proxy type with TLS settings trojan outbound
Shadowsocks ss proxy type with cipher and password shadowsocks outbound

Previously these protocols were silently omitted from generated subscription links, causing clients to show empty proxy lists when the node operator used them.

8 — Transport support: gRPC, HTTPUpgrade, XHTTP (9901a9c)

Files: crates/sub/src/formats.rs

Added transport-layer mapping inside the Clash / Sing-Box serializers:

Transport Clash Sing-Box
gRPC grpc-opts with grpc-service-name grpc transport with service_name
HTTPUpgrade http-opts with upgrade headers httpupgrade transport
XHTTP network: xhttp with path/host xhttp transport

These transports are increasingly common in censorship-resilient deployments; without them, subscription links generated by the panel were unusable for nodes configured with non-WebSocket transports.


Testing

  • crates/payments/tests/webhook_regression.rs — 183-line regression suite covering webhook replay, amount parsing, and provider errors (new)
  • devtools/tests/help-parity.test.cjs — 60-line parity tests for RU/EN help strings (new)
  • Existing unit and integration tests pass unchanged

Migration

Only one additive migration is included:

-- db/migrations/049_auth_limits_index.sql
CREATE INDEX IF NOT EXISTS auth_rate_limits_window_start_idx
    ON auth_rate_limits (window_start);

No existing columns are altered, no data is touched.


Checklist

  • All changes compile with cargo check --workspace
  • Webhook regression tests added and passing
  • No unwrap() on Option/Result in hot paths
  • Database migration is additive-only
  • No breaking changes to existing API contracts
  • Backward-compatible subscription output (new protocols appended, existing unchanged)

🇷🇺 Описание изменений (на русском языке)

Данный PR объединяет набор исправлений надёжности и расширений форматов подписок, разработанных в форке reelsmaker2026. Все изменения обратно совместимы и не затрагивают схему БД за исключением одного дополнительного индекса.

Содержимое PR:

  1. Дедупликация вебхуков и фиксы платежей (8c1f5ae):

    • Восстановлена идемпотентность обработки вебхуков в провайдерах CryptoBot и Generic HTTP (повторные запросы от платежных шлюзов больше не приводят к двойному зачислению средств или продлению подписки).
    • Исправлен парсинг суммы CryptoBot: корректно обрабатываются как числовые, так и строковые представления JSON.
    • Устранены две паники API (unwrap() в catalog_routes.rs и profile_workflow.rs заменены на безопасный оператор ?).
    • Добавлен набор регрессионных тестов (webhook_regression.rs, 183 строки).
  2. Устранение race condition при регистрации HWID (b9e05c8):

    • Авторизация устройств теперь сериализуется с помощью SELECT ... FOR UPDATE внутри транзакции. Исключена ситуация, когда параллельные запросы с разных устройств одновременно проходили проверку лимита до записи в базу.
  3. Оптимизация проверки лимитов авторизации (a518f9b):

    • Очистка истекших окон auth rate-limit вынесена из критического пути API-запросов в фоновый worker.
    • Добавлен индекс window_start (миграция 049) для быстрого удаления устаревших записей.
  4. Автоопределение темы и справка в кабинете (805db28):

    • Реализовано автоопределение системной темы (тёмная/светлая через prefers-color-scheme).
    • Добавлен раздел помощи в кабинете пользователя с англоязычной локализацией и тестами паритета RU/EN строк.
  5. Шаблонные директивы совместимости с Remnawave (82dbf1f + 3f80c42):

    • Поддержка директив injectHosts (подмешивание карты хостов оператора в исходящие прокси) и include-proxies (фильтрация списка прокси). Исправлена вставка в мапу JSON-объекта.
  6. Автозагрузка геобаз Xray перед запуском (43365dd):

    • Добавлена автоматическая предстартовая проверка и скачивание отсутствующих файлов geoip.dat и geosite.dat.
  7. Поддержка протоколов подписок: Hysteria2, Trojan, Shadowsocks (36be4b9):

    • В сериализаторы Clash и Sing-Box добавлена генерация корректных конфигураций для Hysteria 2 (с bandwidth, obfs), Trojan (с TLS) и Shadowsocks.
  8. Поддержка транспортов: gRPC, HTTPUpgrade, XHTTP (9901a9c):

    • Добавлен маппинг транспортов gRPC, HTTPUpgrade и XHTTP в форматах Clash и Sing-Box для надёжной работы в условиях блокировок.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant