196 KiB
196 KiB
Changelog
3.36.1 (2026-03-20)
Bug Fixes
- handle duplicate admin roles in RBAC bootstrap (877b1cd)
- make migration 0042 idempotent for retry_count column (5faf701)
3.36.0 (2026-03-20)
New Features
- add media attachment support for admin ticket replies (69bb399)
- add multi-provider recovery, retry_count, amount verification, and indexes (3d78974)
- add partner → campaign edges to referral network graph (01132a7)
- add referral network graph visualization admin API (c08c903)
- add scoped referral network graph with scope selector API (df086b0)
- multi-select scope for referral network graph API (6a4ce3d)
Bug Fixes
- address review findings for guest purchase recovery (57c5c67)
- address review findings for multi-provider recovery (79c110f)
- allow repeated auto-assignment of promo groups on each purchase (4a002b7)
- correct revenue calculations in referral network (c8f4cca)
- improve referral network query correctness and cleanup (ac9fcd8)
- prevent duplicate promo groups during auto-assignment after purchase (da7a9cc)
- prevent guest purchases from getting stuck in PENDING/FAILED status (2781236)
- prevent premature commits in promocode promo group operations (8b26680)
- propagate exceptions from get_primary_user_promo_group (3ec9e71)
- use 'kassa_ai' base model name for guest metadata patch (182667e)
- use base model name for KassaAI guest metadata patch (b6d4373)
Performance
- add covering indexes for referral network queries (b5471b7)
3.35.0 (2026-03-18)
New Features
- add user_email to admin payments API response (7101555)
- include manual admin top-ups in sales statistics revenue (b80eeea)
- раздельные топики для админских уведомлений (e15b18f)
Bug Fixes
- fix Platega and CryptoBot webhook verification (b40a812)
- handle None autopay_days_before in autopayment processing (f1d4534)
- remove forced white background from custom email template overrides (cb61014)
- undefined currency variable in RioPay payment creation (5b33534)
3.34.1 (2026-03-18)
Bug Fixes
- add null check for subscription in execute_change_devices (5081deb)
- correct CryptoBot webhook signature verification and auto-fill topup amount from cart (d7ad9d7)
- correct RioPay API header case and remove undocumented fields (1a87d43)
- disable quick amount buttons in balance topup (d0eab3f)
- reset device limit to new tariff base on tariff switch (aec01ce)
- sync crypto link from happ.cryptoLink in webhook handlers (0ceff44)
Refactoring
- remove quick amount buttons feature entirely (136f29c)
Documentation
- add bot preview screenshot to README (d7931a2)
- add cabinet preview screenshot to README (b032c8f)
- add icons and list all 14+1 payment providers (1306c24)
- add Redis to tech stack (c14d7ab)
- add Redis to tech stack (e12cc9f)
- add WATA partnership block to payments section (31bdf8a)
- increase logo size to 800px (22e7f15)
- redesign README — concise feature showcase, link to docs (38deb70)
- replace header logo with new artwork (6888822)
- WATA partnership block with logo and table card (8d5a002)
3.34.0 (2026-03-18)
New Features
- добавлен SeverPay в админ-панель и настройки кабинета (06a00e3)
- добавлена интеграция SeverPay для пополнения баланса (abaf279)
- поиск платежей в админ-панели с фильтрами и статистикой (1804c28)
Bug Fixes
- remove contains_eager conflicting with selectinload on user relationship (fddf8ef)
- добавлен импорт MAX_ALL_TIME_DAYS в admin_payments routes (ad26832)
- добавлены RioPay и SeverPay в REAL_PAYMENT_METHODS (f967c29)
3.33.0 (2026-03-17)
New Features
- add SBP and Card sub-options for KassaAI payment method (5b722c5)
- add SBP and Card sub-options to kassa_ai payment method (04419fd)
- deep link авторизация в кабинете при блокировке oauth.telegram.org (322d457)
- добавлена поддержка RioPay в кабинете (3d1fbc7)
- добавлена поддержка RioPay для лендингов и подарков (04f4e6b)
Bug Fixes
- add back button to payment amount validation errors (20eff61)
- add sync_squads=True to admin tariff change handler (3f0b24c)
- deep link auth security and reliability fixes (099391e)
- enforce promo group authorization on country/server selection (641da94)
- merge phantom users into active accounts on /start (77f1a76)
- MissingGreenlet crash after subscription purchase in cabinet (a80a85c)
- MissingGreenlet crash after subscription purchase in cabinet (1cc687a)
- MissingGreenlet при изменении количества устройств на CLASSIC подписках (826accb)
- protect external squads from deletion during server sync (b563796)
- review findings — db.commit, isinstance guard, constants, ACTIVE check (72b5305)
- sub-method enabled check, guest payment provider, silent FSM return (603b9a1)
- subscription: remove stale extend promo state fields causing NameError (20a6fa1)
- swap Caddy auth headers — api_key to Authorization, caddy_token to X-Api-Key (038c34e)
- sync squads to Remnawave panel on tariff purchase/switch (c34fdd1)
- защита внешних сквадов от удаления при синхронизации серверов (f84885c)
- исправлен расчёт конверсии в статистике продаж (3089c17)
- исправлены проблемы RioPay интеграции после ревью (4abb8cb)
- миграция Tribute webhook с deprecated user_id на trb_user_id (9419941)
- скрыть плашку верификации email при выключенной верификации (4966e39)
Refactoring
- deduplicate KassaAI handlers with config dict and shared helpers (e4bb043)
- move KASSA_AI_SUB_METHODS to service layer, add early enabled checks (cda2392)
3.32.4 (2026-03-16)
Bug Fixes
- лог полного payload при ошибке PATCH /api/users для диагностики A039 (8d7f0ee)
- не пересылать activeInternalSquads в рутинных обновлениях RemnaWave (A039) (4aaf0dd)
- не пересылать externalSquadUuid в рутинных обновлениях RemnaWave (3d68db0)
- расширен лог PATCH /api/users payload для диагностики A039 (db2f0c9)
- режим «Контакт и тикеты» возвращает support_type='both' вместо 'tickets' (2f33e55)
- реферальный бонус инвайтера — сумма вместо максимума, защита флага первого пополнения (e1bcb1b)
- сохранение user_id до rollback чтобы избежать MissingGreenlet при lazy load (3f8e899)
- убрана отправка externalSquadUuid=null в RemnaWave API и исправлен ложный лог синхронизации рулетки (f80912e)
- уведомление об истечении подписки теперь учитывает autopay_enabled пользователя (c0b282a)
- устранена отправка externalSquadUuid=null в RemnaWave API (A039) и исправлен reduce_devices (e453521)
Refactoring
- централизация всех расчётов цен в PricingEngine (8d3cd50)
3.32.3 (2026-03-14)
Bug Fixes
- campaign registration, revenue calculation, backup restore, autopay errors, referral links (7648707)
- implement case-insensitive email checks in authentication and user retrieval (7e466ef)
- implement case-insensitive email checks in authentication and user retrieval (ebee834)
- payment: prioritize saved cart after topup over expired auto-extend (28321df)
- refresh CLASSIC_PERIOD_PRICES when admin changes PRICE_*_DAYS or SALES_MODE (6adf70b)
3.32.2 (2026-03-13)
Bug Fixes
- add nested selectinload and referrer eager loading to prevent MissingGreenlet (3306e02)
- add selectinload to user lock queries to prevent MissingGreenlet (5442f28)
- silence PARTICIPANT_ID_INVALID error in channel subscription check (14dceaa)
3.32.1 (2026-03-13)
Bug Fixes
- invalid ISO date format in node usage stats API call (69a38da)
- platega webhook ID fallback for SBP and card payments (aa3459b)
- resolve MissingGreenlet in switch_tariff endpoint (4d695be)
3.32.0 (2026-03-13)
New Features
- add _calculate_servers_price (fixed fallback) and _calculate_traffic_price (88369ee)
- add CLASSIC_PERIOD_PRICES to config (c3bb63f)
- add LIMITED subscription status and preserve extra devices on tariff switch (8f43452)
- add RenewalPricing dataclass and PricingEngine discount methods (83ca51c)
- implement calculate_renewal_price with tariff and classic modes (02e5401)
Bug Fixes
- add missing settings import in admin_users tariff switch (b2ee6c7)
- add per-category discounts and months multiplier to classic mode (1660b24)
- add period_days whitelist validation and type annotations (18e2e78)
- address 6-agent review findings for PricingEngine (c9f2dff)
- address review findings from 5-agent audit (08bea70)
- atomicity refactor, review fixes, and DELETED recovery logging (ba54819)
- change None assignment to [] + add "or []" guards at all 5 call sites. (a5fbd74)
- downgrade known-harmless RemnaWave 400s to warning level (0419781)
- guard rollback on commit flag, add flush to promo_offer_log (b7775b7)
- handle legacy telegram_id in YooKassa webhook recovery metadata (815a1d9)
- harden remnawave API error handling and YooKassa user cross-validation (585baaf)
- harden YooKassa webhook recovery user lookup (d35ee58)
- payment providers — lock_user_for_update + commit=False atomicity (b4ef52c)
- prevent balance loss on auto-purchase for DISABLED subscriptions and fix WATA expiration (266340a)
- pricing audit — display/charge parity, race conditions, balance locks (ae99358)
- resolve merge conflict with dev (accept calc_device_limit_on_tariff_switch) (ba049ca)
- user deletion FK error + connected_squads None TypeError (a5fbd74)
Refactoring
- add typed breakdowns + module-level singleton to PricingEngine (b551def)
- extract shared formatting helpers into app/utils/formatting.py (5e9a462)
- make finalize() accept both old and new pricing types (3efa24b)
- migrate admin user price calculation to PricingEngine (49c0f3f)
- migrate all callers to pricing_engine singleton + fix miniapp discount (e24b911)
- migrate bot renewal display to PricingEngine (ce82c2c)
- migrate bot renewal execute to PricingEngine (acf27a1)
- migrate cabinet renewal display + execute to PricingEngine (28fc36d)
- migrate cart auto-purchase to PricingEngine (fresh calc) (bd2e93a)
- migrate menu.py renewal pricing to PricingEngine (652b6da)
- migrate miniapp renewal display + execute to PricingEngine (cb43aca)
- migrate recurrent and monitoring services to PricingEngine (978f68e)
- migrate remaining callers to PricingEngine + cleanup dead CRUD (75dbd2b)
- migrate try_auto_extend_expired to PricingEngine (e6ebc67)
- remove dead pricing code and fix miniapp classic mode (c9a9816)
- unify first-purchase discount algorithm with PricingEngine (fe4e6ac)
3.31.0 (2026-03-12)
New Features
- add show_in_gift toggle for tariffs in admin panel (cb5126a)
- add sync-squads endpoint for bulk updating subscription squads in Remnawave (b1e2146)
- auto-sync squads to Remnawave when admin updates tariff (076290e)
- referral links now point to web cabinet instead of bot (12ae871)
Bug Fixes
- add post_update=True to User.referrals self-referential relationship (9957259)
- add Telegram Stars payment support for gift subscriptions (5424d8c)
- correct skipped_count in sync-squads circuit breaker and simplify ternary (8a362db)
- preserve purchased devices when admin changes user tariff (bf72f24)
- prevent account takeover via auto_login_token, ensure promo group on all purchase paths (b3f3eba)
- reactivate subscription after traffic top-up when status is EXPIRED (8b35428)
- update promo group via M2M table so admin changes persist (68bc8eb)
Refactoring
- remove estimated price from balance, simplify server sync, fix HTML injection (a798f11)
3.30.0 (2026-03-11)
New Features
- add gifts section to admin user detail API (bca8bab)
- add promo group and promo offer discounts to gift subscriptions (2fd0f6a)
Bug Fixes
- record transactions for free tariff switches and admin tariff changes (864a4ed)
- reset subscription for paid users, trial-to-paid tariff conversion, gift purchase MissingGreenlet (e67b8e4)
- use keyword args for Path.mkdir in asyncio.to_thread (2879996)
3.29.0 (2026-03-10)
New Features
- gift subscription code-only purchase + activation via deep link (5ffce17)
- prevent self-activation of gift codes (b30c73c)
Bug Fixes
- 3 bugs — notification type, referral with channel sub, BOT_USERNAME (3c96c2a)
- 3 critical issues from second-round review (a90d2d9)
- add minimum 8-char length check for gift token in bot deep link (8a8337f)
- address review findings from 6-agent audit (5c34656)
- code-only gifts skip fulfillment in gateway webhook + retry service (05bcac5)
- panel sync now updates end_date in both directions (def594b)
- pass full token to svc_activate instead of truncated prefix (38c6adf)
- refresh user subscription after gift activation in /start (363ccce)
- remove begin_nested that breaks activate_purchase transaction (0005d59)
- stars rate rounding + device/traffic purchase stats (641ff86)
- support prefix-based gift code lookup for activation (4fb72ae)
Refactoring
- deduplicate gift activation in start.py (769d3a0)
- rename GIFTCODE_ start parameter prefix to GIFT_ (42b6c80)
3.28.1 (2026-03-10)
Bug Fixes
- migrate pricing to days-based proration, fix promo revenue leaks, fix admin panel bugs (fcdeff1)
3.28.0 (2026-03-09)
New Features
- add cabinet gift subscription API routes and schemas (6a61b09)
- add cabinet menu layout editor with row arrangement, custom URL buttons, and drag-and-drop reordering (dd8d7f6)
- add CABINET_GIFT_ENABLED branding toggle (759bfe1)
- add open_in setting for custom buttons (external browser / webapp) (497a8ee)
- add source and buyer_user_id fields to GuestPurchase model (0936d4a)
- implement gateway payment for gifts, persist recipient warning (cd04f3b)
Bug Fixes
- enforce HTTPS for webapp mode, deduplicate keyboard builder, fix long line (69dbd6a)
- harden gift subscription feature after multi-agent review (6a4140e)
- loyalty tiers current status based on spending, not assigned group (b815abf)
- negate GIFT_PAYMENT amounts and remove dead code (f80b058)
- normalize threshold 0→NULL in create_promo_group for consistency (b9089e6)
- payment gateway issues — YooKassa polling, PAL24 card 500 (95a32e8)
- support Telegram OIDC id_token in account linking endpoint (680c22c)
3.27.0 (2026-03-09)
New Features
- auto-resume disabled daily subscriptions on balance topup (770b31d)
Bug Fixes
- add method query param to return_url and latest-payment endpoint (32d58b0)
- add table existence guards to migrations for optional payment tables (f4a7763)
- admin tariff server selection - 64-byte overflow and callback routing conflicts (536525c)
- align tariff pricing with calculate_renewal_price reference (6349b2f)
- conditional log messages and sanitize panel_error in user deletion (289cbe9)
- encode payment status in provider return URLs and wire failed_url (275f249)
- enforce tariff device_price and max_device_limit across all purchase paths (f9f07f3)
- keep DB session alive in Tribute payment notification handler (4186159)
- latest-payment endpoint returns all payments, not just pending (7a9264b)
- pass cabinet return_url to payment providers for top-up redirects (7ca9619)
- propagate tariff squad changes to existing subscriptions and fix user deletion from Remnawave (7ccfb66)
- renewal cost estimate double-counts servers and traffic in tariff mode (bfbefeb)
- resolve concurrent AsyncSession bug and sanitize error responses (4a5cacd)
- use parsed HTML length for Telegram caption limit checks (2649e12)
Refactoring
- move squad propagation to service layer with parallel Remnawave sync (79161ea)
3.26.0 (2026-03-08)
New Features
- add telegram gift notification with inline activation button (9ba61a0)
Bug Fixes
- auto-purchase classic extend missing device_limit and traffic_limit_gb (7dc5e4a)
- gift purchase notification and activation flow (330d1cb)
- multiple payment and notification bugs (f4eeb9a)
- quick topup buttons include device/server/traffic costs, broadcast button crash on media messages (5ebe107)
- remove is_active_paid_subscription guard from admin deactivation (1f664a9)
- respect send_before_menu flag for pinned messages during new user registration (20727b1)
3.25.0 (2026-03-07)
New Features
- add configurable animated background for landing pages (11d3e63)
- add landing page statistics endpoint with charts data (25478ce)
- add paginated purchases list endpoint for landing pages (0ba1127)
Bug Fixes
- add or [] guard to remaining connected_squads call site in fulfill_purchase (d9f9f3d)
- align context_vars and SAMPLE_CONTEXTS with actual runtime context keys (ab5313a)
- align subscription_renewed/activated context_vars with runtime keys (c507634)
- correct device_limit and connected_squads in guest purchase fulfillment (44d46fe)
- drop legacy prize_days column from contest_templates (5214f55)
- handle expired subscription in guest purchase fulfillment (9e78509)
- remaining context_vars/SAMPLE_CONTEXTS mismatches found by agents (d72ea6b)
- resolve alembic migration failures on fresh database install (bbd353f)
- resolve NameError in YooKassa successful payment processing (9d5329d)
- strip newlines from subject substitution, fix subscription notification context (c9ea2b1)
- substitute context variables in email template overrides (d52c87b)
- substitute sample context in admin test email for template overrides (351d714)
- support {total_amount} placeholder in cart notification templates (f4ab174)
- use --frozen instead of --locked in Dockerfile to avoid version mismatch (923b36a)
- use information_schema for constraint existence checks in migrations (fc65e2d)
- use pg_class lookup for constraint existence checks in migrations (ba335fe)
3.24.0 (2026-03-07)
New Features
- account linking and merge system for cabinet (dc7b8dc)
- account merge system — atomic user merge with full FK coverage (2664b49)
- add 'default' (no color) option for button styles (10538e7)
- add admin campaign chart data endpoint with deposits/spending split (fa7de58)
- add admin notifications for partner applications and withdrawals (cf7cc5a)
- add admin partner settings API (withdrawal toggle, requisites text, partner visibility) (6881d97)
- add admin sales statistics API with 6 analytics endpoints (58faf9e)
- add admin topic notifications for landing page purchases (dbb9757)
- add all remaining RemnaWave webhook events (node, service, crm, device) (1e37fd9)
- add button style and emoji support for cabinet mode (Bot API 9.4) (bf2b2f1)
- add cabinet admin API for pinned messages management (1a476c4)
- add campaign_id to ReferralEarning for campaign attribution (0c07812)
- add ChatTypeFilterMiddleware to ignore group/forum messages (25f014f)
- add close button to all webhook notifications (d9de15a)
- add daily deposits by payment method breakdown (d33c5d6)
- add daily device purchases chart to addons stats (2449a5c)
- add dedicated sales_stats RBAC permission section (8f29e2e)
- add desired commission percent to partner application (7ea8fbd)
- add discount system for landing pages (aa7d986)
- add external squad support for tariffs (c10d678)
- add GET /admin/rbac/users endpoint for listing all RBAC users (8b77cda)
- add granular user permissions (balance, subscription, promo_group, referral, send_offer) (60c4fe2)
- add landings to permission registry (c93dbec)
- add lite mode functionality with endpoints for retrieval and update (7b0403a)
- add LOG_COLORS env setting to toggle console ANSI colors (27309f5)
- add MULENPAY_WEBSITE_URL setting for post-payment redirect (fe5f5de)
- add multi-channel mandatory subscription system (8375d7e)
- add partner system and withdrawal management to cabinet (58bfaea)
- add per-button enable/disable toggle and custom labels per locale (68773b7)
- add per-channel disable settings and fix CHANNEL_REQUIRED_FOR_ALL bug (3642462)
- add per-section button style and emoji customization via admin API (a968791)
- add Persian (fa) locale with complete translations (29a3b39)
- add POST /auth/telegram/oidc endpoint for OIDC popup flow (3a400d9)
- add quick purchase email templates to admin panel (6970340)
- add RBAC + ABAC permission system for admin cabinet (3fee54f)
- add referral code tracking to all cabinet auth methods + email_templates migration (18c2477)
- add RemnaWave incoming webhooks for real-time subscription events (6d67cad)
- add required channels button to admin settings submenu in bot (3af07ff)
- add RESET_TRAFFIC_ON_TARIFF_SWITCH admin setting (4eaedd3)
- add resource_type and request body to audit log entries (388fc7e)
- add separate Freekassa SBP and card payment methods (0da0c55)
- add server-complete OAuth linking endpoint for Mini App flow (f867989)
- add startup warnings for missing HAPP_CRYPTOLINK_REDIRECT_TEMPLATE and MINIAPP_CUSTOM_URL (476b89f)
- add sub_options support for landing page payment methods (220196f)
- add Telegram account linking endpoint with security hardening (da40d56)
- add Telegram OIDC id_token validation and code exchange (2f0a9dc)
- add TELEGRAM_OIDC_* settings for new Telegram Login (833df51)
- add validation to animation config API (a15403b)
- add web admin button for admins in cabinet mode (9ac6da4)
- add web campaign links with bonus processing in auth flow (d955279)
- allow editing system roles (f6b6e22)
- allow tariff deletion with active subscriptions (ebd6bee)
- attribute campaign registrations to partner for referral earnings (767e965)
- blocked user detection during broadcasts, filter blocked from all notifications (10e231e)
- capture query params in audit log details for all requests (bea9da9)
- colored channel subscription buttons via Bot API 9.4 style (0b3b2e5)
- colored console logs via structlog + rich + FORCE_COLOR (bf64611)
- configurable Telegram Login Widget with admin settings (084a3cd)
- enforce 1-to-1 partner-campaign binding with partner info in campaigns (366df18)
- enhance sales stats with device purchases, per-tariff daily breakdown, and registration tracking (31c7e2e)
- expose oidc_enabled and oidc_client_id in telegram-widget config (000b0c0)
- expose payment sub-options with labels in public landing API (c53e9af)
- expose traffic_reset_mode in subscription response (59383bd)
- expose traffic_reset_mode in tariff API response (5d4a94b)
- guest purchase → cabinet account integration (f8edfd7)
- guest purchase delivery & activation system (776fc3a)
- handle errors.bandwidth_usage_threshold_reached_max_notifications webhook (8e85e24)
- handle service.subpage_config_changed webhook event (43a326a)
- include partner campaigns in /partner/status response (ea5d932)
- link campaign registrations to partner for referral earnings (c4dc43e)
- localization: add Persian (fa) locale support and wire it across app flows (cc54a7a)
- notify users on partner/withdrawal approve/reject (327d4f4)
- register TELEGRAM_OIDC category, hints in admin settings (3a36162)
- rename MAIN_MENU_MODE=text to cabinet with deep-linking to frontend sections (ad87c5f)
- replace pip with uv in Dockerfile (e23d69f)
- rework guide mode with Remnawave API integration (5a269b2)
- show all active webhook endpoints in startup log (9d71005)
- unified notification delivery for webhook events (email + WS support) (26637f0)
- webhook protection — prevent sync/monitoring from overwriting webhook data (184c52d)
- мультиязычные лендинги + гостевые платежи для всех провайдеров (6deab7d)
- публичные лендинг-страницы для быстрой покупки VPN-подписок (5e404cc)
Bug Fixes
- 3 user deletion bugs — type cast, inner savepoint, lazy load (af31c55)
- abs() for transaction amounts in admin notifications and subscription events (fd139b2)
- add /start burst rate-limit to prevent spam abuse (61a9722)
- add abs() to expenses query, display flip, contest stats, and recent payments (de6f806)
- add action buttons to webhook notifications and fix empty device names (7091eb9)
- add activate hint to gift pending activation email link (fa21549)
- add blocked_count column migration to universal_migration.py (b4b10c9)
- add diagnostic logging for device_limit sync to RemnaWave (97b3f89)
- add exc_info traceback to sync user error log (efdf2a3)
- add int32 overflow guards and strengthen auth validation (50a931e)
- add IntegrityError handling on link commit and format fixes (0c1dc58)
- add local traffic_used_gb reset in all tariff switch handlers (2cdbbc0)
- add Message-ID and Date headers to outgoing emails (de541ea)
- add Message-ID and Date headers to outgoing emails (e9b4d8e)
- add migration for partner system tables and columns (4645be5)
- add migration for partner system tables and columns (79ea398)
- add min_length to state field, use exc_info for referral warning (062c486)
- add missing broadcast_history columns and harden subscription logic (d4c4a8a)
- add missing CHANNEL_CHECK_NOT_SUBSCRIBED localization key (a47ef67)
- add missing mark_as_paid_subscription, fix operation order, remove dead code (5f2d855)
- add missing payment providers to payment_utils and fix {total_amount} formatting (bdb6161)
- add missing placeholders to Arabic SUBSCRIPTION_INFO template (fe54640)
- add missing subscription columns migration (b96e819)
- add naive datetime guards to fromisoformat() in Redis cache readers (1b3e6f2)
- add naive datetime guards to fromisoformat() in Redis cache readers (6fa4948)
- add naive datetime guards to parsers and fix test datetime literals (0946090)
- add passive_deletes to Subscription relationships to prevent NOT NULL violation on cascade delete (bfd66c4)
- add pending_activation to purchase stats and show total count (8510597)
- add promo code anti-abuse protections (97ec39a)
- add referral_code pattern validation, email login rate limiting, and Retry-After headers (5499ad6)
- add selectinload for campaign registrations in list query (4d74afd)
- add selectinload for subscription in campaign user list (eb9dba3)
- add startup warning for missing HAPP_CRYPTOLINK_REDIRECT_TEMPLATE in guide mode (1d43ae5)
- add X-CSRF-Token and X-Telegram-Init-Data to CORS allow_headers (77456ef)
- address code review findings for Telegram OIDC (da1cc4f)
- address code review issues in guide mode rework (fae6f71)
- address RBAC review findings (CRITICAL + HIGH) (1646f04)
- address remaining abs() issues from review (ff21b27)
- address review findings for guest purchase admin notifications (770f19e)
- address review findings from agent verification (cc5be70)
- address review issues in backup, updates, and webhook handlers (2094886)
- address security review findings (6feec1e)
- align RBAC route prefixes with frontend API paths (5a7dd3f)
- allow email change for unverified emails (93bb8e0)
- allow non-HTTP deep links in crypto link webhook updates (f779225)
- allow purchase when recalculated price is lower than cached (19dabf3)
- allow tariff switch when less than 1 day remains (67f3547)
- always include details in successful audit log entries (3dc0b93)
- AttributeError in withdrawal admin notification (send_to_admins → send_admin_notification) (c75ec0b)
- auth middleware catches all commit errors, not just connection errors (6409b0c)
- auto-convert naive datetimes to UTC-aware on model load (f7d33a7)
- auto-update permissions for system roles on bootstrap (eff74be)
- backup restore fails on FK constraints and transaction poisoning (ff1c872)
- build composite device name from platform + hwid short suffix (17ce640)
- callback routing safety and cache invalidation order (6a50013)
- campaign web link uses ?campaign= param, not ?start= (28f524b)
- cap expected_monthly_referrals to prevent int32 overflow (2ef6185)
- centralize balance deduction and fix unchecked return values (0466528)
- centralize has_had_paid_subscription into subtract_user_balance (e4a6aad)
- change CryptoBot URL priority to bot_invoice_url for Telegram opening (3193ffb)
- classic mode prices overridden by active tariff prices (628a99e)
- clean email verification and password fields from secondary user during merge (7b4e948)
- clean stale squad UUIDs from tariffs during server sync (fcaa9df)
- clear subscription data when user deleted from Remnawave panel (b0fd38d)
- close remaining daily subscription expire paths (618c936)
- code style and formatting from review (a539d69)
- complete datetime.utcnow() → datetime.now(UTC) migration (eb18994)
- complete FK migration — add 27 missing constraints, fix broadcast_history nullable (fe393d2)
- comprehensive security and quality fixes from 7-agent review (5c55662)
- comprehensive security hardening from 7-agent review (e96fe1e)
- connected_squads stores UUIDs, not int IDs — use get_server_ids_by_uuids (d7039d7)
- consume promo offer in miniapp tariff-mode renewal path (b8857e7)
- consume promo offer in tariff_purchase.py, fix negative transaction amount (c8ef808)
- correct broadcast button deep-links for cabinet mode (e5fa45f)
- correct cart notification after balance top-up (2fab50c)
- correct referral withdrawal balance formula and commission transaction type (83c6db4)
- correct subscription_service import in broadcast cleanup (6c4e035)
- count sales from completed payment transactions instead of subscription created_at (06c3996)
- critical OIDC fixes from 7-agent review (b78c01c)
- critical security and data integrity fixes for partner system (8899749)
- cross-validate Telegram identity on every authenticated request (973b3d3)
- CryptoBot guest payment — remove is_paid @property write, use correct status (6f871ed)
- daily tariff subscriptions stuck in expired/disabled with no resume path (80914c1)
- deadlock on user deletion + robust migration 0002 (b7b83ab)
- delete cross-referral earnings before bulk reassignment, clear secondary.referred_by_id (f204b67)
- delete subscription_servers before subscription to prevent FK violation (7d9ced8)
- device_limit fallback 1→0 для корректного отображения безлимита (3e26832)
- don't delete Heleket invoice message on status check (9943253)
- downgrade Telegram timeout errors to warning in monitoring service (e43a8d6)
- downgrade transient API errors (502/503/504) to warning level (ec8eaf5)
- eliminate deadlock by matching lock order with webhook (d651a6c)
- eliminate double panel API call on tariff change, harden cart notification (b2cf4aa)
- eliminate referral system inconsistencies (60c97f7)
- email verification bypass, ban-notifications size limit, referral balance API (256cbfc)
- empty JSONB values exported as None in backup (57aaca8)
- enforce user restrictions in cabinet API and fix poll history crash (faba3a8)
- expand backup coverage to all 68 models and harden restore (02e40bd)
- extend naive datetime guard to all model properties (bd11801)
- extract device name from nested hwidUserDevice object (79793c4)
- extract real client IP from X-Forwarded-For/X-Real-IP headers (af6686c)
- filter out traffic packages with zero price from purchase options (64a684c)
- flood control handling in pinned messages and XSS hardening in HTML sanitizer (454b831)
- force basicConfig to replace pre-existing handlers (7eb8d4e)
- freekassa OP-SP-7 error and missing telegram notification (200f91e)
- from redis.exceptions import NoScriptError (667291a)
- generate missing crypto link on the fly and skip unresolved templates (4c72058)
- grant legacy config-based admins full RBAC access (8893fc1)
- handle duplicate remnawave_uuid on email sync (eaeee7a)
- handle expired callback queries and harden middleware error handling (f52e6ae)
- handle expired ORM attributes in sync UUID mutation (9ae5d7b)
- handle naive datetime in raw SQL row comparison (payment/common) (38f3a9a)
- handle naive datetimes in Subscription properties (e512e5f)
- handle NULL used_promocodes for migrated users (cdcabee)
- handle nullable traffic_limit_gb and end_date in subscription model (e94b93d)
- handle photo message in ticket creation flow (e182280)
- handle RemnaWave API errors in traffic aggregation (ed4624c)
- handle StaleDataError in webhook user.deleted server counter decrement (c30c2fe)
- handle StaleDataError in webhook when user already deleted (d58a80f)
- handle tariff_extend callback without period (back button crash) (ba0a5e9)
- handle TelegramBadRequest in ticket edit_message_text calls (8e61fe4)
- handle time/date types in backup JSON serialization (27365b3)
- handle unique constraint conflicts during backup restore without clear_existing (5893874)
- handle YooKassa NotFoundError gracefully in get_payment_info (df5b1a0)
- harden account merge security and correctness (d855e9e)
- harden backup create/restore against serialization and constraint errors (fc42916)
- hide traffic topup button when tariff doesn't support it (399ca86)
- HTML parse fallback, email change race condition, username length limit (d05ff67)
- HTML-escape all externally-sourced text in guide messages (711ec34)
- ignore 'message is not modified' on privacy policy decline (be1da97)
- improve campaign notifications and ticket media in admin topics (a594a0f)
- improve campaign routes, schemas, and add database indexes (ded5c89)
- improve deduplication log message wording in monitoring service (2aead9a)
- include desired_commission_percent in admin notification (dc3d22f)
- initialize logger in bot_configuration.py (988d0e5)
- invalidate app config cache on local file saves (978726a)
- limit Rich traceback output to prevent console flood (11ef714)
- make migration 0002 robust with table existence checks (f076269)
- make migrations 0010/0011 idempotent, escape HTML in crash notification (a696896)
- make users.promo_group_id nullable — sync DB with model (e0f2243)
- medium-priority fixes for partner system (7c20fde)
- merge: validate before consuming token, add flush, defensive balance (bc1e6fb)
- migrate all remaining naive timestamp columns to timestamptz (708bb9e)
- migrate VK OAuth to VK ID OAuth 2.1 with PKCE (1dfa780)
- MissingGreenlet on campaign registrations access (018f18f)
- move PartnerStatus enum before User class to fix NameError (acc1323)
- NameError in set_user_devices_button — undefined action_text (1b8ef69)
- negative balance transfer, linking state validation, referrer migration (531d5cf)
- normalize transaction amount signs across all aggregations (4247981)
- nullify payment FK references before deleting transactions in user restoration (0b86f37)
- partner system — CRUD nullable fields, per-campaign stats, atomic unassign, diagnostic logging (ed3ae14)
- pass return_url to all payment providers for guest purchases (b85646a)
- payment race conditions, balance atomicity, renewal rollback safety (c5124b9)
- photo handling in QR messages (1afcd84)
- pre-existing bugs found during review (1bb939f)
- pre-validate CABINET_BUTTON_STYLE to prevent invalid values from suppressing per-section defaults (46c1a69)
- preserve connected_squads during subscription replacement cleanup (d86c29a)
- preserve payment initiation time in transaction created_at (90d9df8)
- preserve purchased traffic when extending same tariff (b167ed3)
- prevent 'caption is too long' error in logo mode (6e28a1a)
- prevent cascading greenlet errors after sync rollback (a1ffd5b)
- prevent concurrent device purchases exceeding max device limit (1cfede2)
- prevent daily subscriptions from being expired by middleware/CRUD/webhook (0ed6397)
- prevent fileConfig from destroying structlog handlers (e78b104)
- prevent infinite reuse of first_purchase_only promo code discounts (2cec8dc)
- prevent negative amounts in spent display and balance history (c30972f)
- prevent partner self-referral via own campaign link (115c0c8)
- prevent race condition expiring active daily subscriptions (bfef7cc)
- prevent self-referral loops, invalidate all sessions on merge (db61365)
- prevent squad drop on admin subscription type change, require subscription for wheel spins (59f0e42)
- prevent sync from overwriting end_date for non-ACTIVE panel users (49871f8)
- prevent sync from overwriting subscription URLs with empty strings (9c00479)
- promo code max_uses=0 conversion and trial UX after promo activation (1cae713)
- protect active paid subscriptions from being disabled in RemnaWave (1b6bbc7)
- protect server counter callers and fix tariff change detection (bee4aa4)
- RBAC API response format fixes and audit log user info (4598c27)
- RBAC audit log action filter and legacy admin level (c1da8a4)
- read discount overrides from landing model instead of response DTO (6d65e15)
- read OIDC enabled setting from DB in auth endpoint (2405dc5)
- reassign orphaned records on merge, eliminate TOCTOU race (d7a9d2b)
- redis cache uses sync client due to import shadowing (667291a)
- reject promo codes for days when user has no subscription or trial (e32e2f7)
- remove @username channel ID input, auto-prefix -100 for bare digits (a7db469)
- remove decorative cloudpayments sub-options (694aecc)
- remove DisplayNameRestrictionMiddleware (640da34)
- remove executable bit from email_service.py (372d628)
- remove gemini-effect and noise from allowed background types (731eb24)
- remove local UTC re-imports shadowing module-level import in purchase.py (e68760c)
- remove premature tariff_id assignment in _apply_extension_updates (b47678c)
- remove redundant trial inactivity monitoring checks (d712ab8)
- remove subscription connection links from guest purchase emails (9217352)
- remove unused PaymentService from MonitoringService init (491a7e1)
- renewals stats empty on all-time filter (e25fcfc)
- reorder button_click_logs migration to nullify before ALTER TYPE (df5415f)
- repair missing DB columns and make backup resilient to schema mismatches (c20355b)
- replace deprecated Query(regex=) with pattern= (871ceb8)
- reset QR photo when returning to referral (3ee108f)
- reset traffic purchases on expired subscription renewal + pricing fixes (dce9eaa)
- resolve deadlock on server_squads counter updates and add webhook notification toggles (57dc1ff)
- resolve exc_info for admin notifications, clean log formatting (11f8af0)
- resolve GROUP BY mismatch for daily_by_tariff query (e5f29eb)
- resolve HIGH-priority performance and security issues in partner system (fcf3a2c)
- resolve MissingGreenlet error when accessing subscription.tariff (a93a32f)
- resolve ruff lint errors (import sorting, unused variable) (b2d7abf)
- resolve sync 404 errors, user deletion FK constraint, and device limit not sent to RemnaWave (1ce9174)
- restore merge token on DB failure, fix partner_status priority (9582758)
- restore panel user discovery on admin tariff change, localize cart reminder (1256ddc)
- restore RemnaWave config management endpoints (6f473de)
- restore subscription_url and crypto_link after panel sync (26efb15)
- return zeroed stats dict when withdrawal is disabled (7883efc)
- review findings — exception chaining, redundant unquote, validator tightening (467dea1)
- safe HTML preview truncation and lazy-load subscription fallback (40d8a6d)
- second round review fixes for account merge (64ee045)
- security and architecture fixes for webhook handlers (dc1e96b)
- separate base and purchased traffic in renewal pricing (739ba29)
- show negative amounts for withdrawals in admin transaction list (5ee45f9)
- skip blocked users in trial notifications and broadcasts without DB status change (493f315)
- skip users with active subscriptions in admin inactive cleanup (e79f598)
- specify foreign_keys on User.admin_roles_rel to resolve ambiguous join (bc7d061)
- stack promo group + promo offer discounts in bot (matching cabinet) (628997f)
- stop CryptoBot webhook retry loop and save cabinet payments to DB (2cb6d73)
- suppress 'message is not modified' error in updates panel (3a680b4)
- suppress bot-blocked-by-user error in AuthMiddleware (fda9f3b)
- suppress expired callback query error in AuthMiddleware (2de4384)
- suppress startup log noise (~350 lines → ~30) (8a6650e)
- suppress web page preview when logo mode is disabled (1f4430f)
- sync subscription status from panel in user.modified webhook (5156d63)
- sync support mode from cabinet admin to SupportSettingsService (516be6e)
- sync SUPPORT_SYSTEM_MODE between SystemSettings and SupportSettings (0807a9f)
- sync traffic reset across all tariff switch code paths (d708365)
- sync uv.lock version with pyproject.toml 3.23.1 (8eb6a8c)
- sync uv.lock version with pyproject.toml 3.23.1 (bc52fd2)
- ticket creation crash and webhook PendingRollbackError (760c833)
- traceback in Telegram notifications + reduce log padding (909a403)
- transaction boundary and CORS in webapi (6495384)
- translate required channels handler to Russian, add localization keys (1bc9074)
- treat empty icon_url as None in payment method validation (ab981dc)
- unassign all campaigns when revoking partner status (d39063b)
- UnboundLocalError for get_logo_media in required_sub_channel_check (d3c14ac)
- UniqueViolation при мерже аккаунтов с общим OAuth/telegram/email ID (1c89bd8)
- uploaded backup restore button not triggering handler (ebe5083)
- use .is_(True) and add or 0 guards per code review (69b5ca0)
- use actual DB columns for subscription fallback query (f0e7f8e)
- use aiogram 3.x bot.download() instead of document.download() (205c8d9)
- use AwareDateTime TypeDecorator for all datetime columns (a7f3d65)
- use callback fallback when MINIAPP_CUSTOM_URL is not set (eaf3a07)
- use direct is_trial access, add missing error codes to promo APIs (69a9899)
- use event field directly as event_name (already includes scope prefix) (9aa22af)
- use float instead of int | float (PYI041) (310edae)
- use flush instead of commit in server counter functions (6cec024)
- use get_rendered_override for proper variable substitution in guest email overrides (c165cca)
- use SAVEPOINT instead of full rollback in sync user creation (2a90f87)
- use selection.period.days instead of selection.period_days (4541016)
- use short TTL fallback in restore_merge_token on parse error (0e8c61a)
- use sync context manager for structlog bound_contextvars (25e8c9f)
- use traffic topup config and add WATA 429 retry (b5998ea)
- validate payment sub-option suffix and harden payment method handling (5f01783)
- webhook notification 'My Subscription' button uses unregistered callback_data (1e2a7e3)
- webhook:close button not working due to channel check timeout (019fbc1)
- wrap user deletion steps in savepoints to prevent transaction cascade abort (a38dfcb)
- безопасность и качество кода лендингов — 16 исправлений (ef45095)
- гарантировать положительный доход от подписок и исправить общий доход (93a55df)
- дедупликация promocode_uses при мерже аккаунтов (00a7db2)
- добавить create_transaction для 6 потоков оплаты с баланса (374907b)
- добавить create_transaction и admin-уведомления для автопродлений (9f35088)
- добавить ON DELETE CASCADE/SET NULL на все FK к users.id (34c82c3)
- добавить пробелы в формат тарифов (1000 ГБ / 2 📱) (900be65)
- дубликаты системных ролей при переименовании и сброс permissions (7a7fb71)
- изолировать stored_amount от downstream consumers в create_transaction (b87535a)
- исправления системы реферальных конкурсов (6713b34)
- кнопка «Назад» в тарифах ведёт в админ панель, а не в настройки (04562fd)
- миграция 0016 падает если FK constraint отсутствует в БД (15fe45d)
- миграция 0021 — drop server_default перед сменой типа на JSON (3d3bb3b)
- передать явный диапазон дат для all_time_stats в дашборде (968d147)
- показывать кнопку покупки тарифа вместо ошибки для триальных подписок (acfa4b3)
- показывать только активные провайдеры на странице /profile/accounts (9d7a557)
- промокоды — конвертация триалов, race condition, savepoints (7fb839a)
- реактивация DISABLED подписок при покупке трафика для LIMITED пользователей (7d28f55)
- реактивация DISABLED подписок при покупке устройств и в REST API (b9e17be)
- синхронизация версии pyproject.toml с main и обновление uv в Dockerfile (b31a893)
- убрать WITHDRAWAL из автонегации, добавить abs() в агрегации, исправить all_time_stats (6da61d7)
- убрать избыточный минус в amount_kopeks для create_transaction (849b3a7)
- устранение race condition при покупке устройств через re-lock после коммита (a7a18dd)
- устранение race conditions и атомарность платёжной системы (4984f20)
- устранение каскадного PendingRollbackError при восстановлении бэкапа (8259278)
Performance
- cache logo file_id to avoid re-uploading on every message (142ff14)
Refactoring
- complete structlog migration with contextvars, kwargs, and logging hardening (1f0fef1)
- extract shared OAuth linking logic, add Literal types for providers (f7caf0d)
- improve log formatting — logger name prefix and table alignment (f637204)
- remove "both" mode from BOT_RUN_MODE, keep only polling and webhook (efa3a5d)
- remove Flask, use FastAPI exclusively for all webhooks (119f463)
- remove legacy app-config.json system (295d2e8)
- remove modem functionality from classic subscriptions (ee2e79d)
- remove smart auto-activation & activation prompt, fix production bugs (a3903a2)
- replace universal_migration.py with Alembic (b6c7f91)
- replace universal_migration.py with Alembic (784616b)
3.23.2 (2026-03-06)
Bug Fixes
- device_limit fallback 1→0 для корректного отображения безлимита (3e26832)
- sync uv.lock version with pyproject.toml 3.23.1 (8eb6a8c)
- sync uv.lock version with pyproject.toml 3.23.1 (bc52fd2)
- миграция 0016 падает если FK constraint отсутствует в БД (15fe45d)
3.23.1 (2026-03-06)
Bug Fixes
- complete FK migration — add 27 missing constraints, fix broadcast_history nullable (fe393d2)
- UniqueViolation при мерже аккаунтов с общим OAuth/telegram/email ID (1c89bd8)
- дедупликация promocode_uses при мерже аккаунтов (00a7db2)
- добавить ON DELETE CASCADE/SET NULL на все FK к users.id (34c82c3)
- дубликаты системных ролей при переименовании и сброс permissions (7a7fb71)
- исправления системы реферальных конкурсов (6713b34)
- кнопка «Назад» в тарифах ведёт в админ панель, а не в настройки (04562fd)
- промокоды — конвертация триалов, race condition, savepoints (7fb839a)
- устранение race conditions и атомарность платёжной системы (4984f20)
3.23.0 (2026-03-05)
New Features
- account linking and merge system for cabinet (dc7b8dc)
- account merge system — atomic user merge with full FK coverage (2664b49)
- add dedicated sales_stats RBAC permission section (8f29e2e)
- add server-complete OAuth linking endpoint for Mini App flow (f867989)
- add Telegram account linking endpoint with security hardening (da40d56)
Bug Fixes
- abs() for transaction amounts in admin notifications and subscription events (fd139b2)
- add abs() to expenses query, display flip, contest stats, and recent payments (de6f806)
- add IntegrityError handling on link commit and format fixes (0c1dc58)
- add missing mark_as_paid_subscription, fix operation order, remove dead code (5f2d855)
- auto-update permissions for system roles on bootstrap (eff74be)
- centralize balance deduction and fix unchecked return values (0466528)
- centralize has_had_paid_subscription into subtract_user_balance (e4a6aad)
- clean email verification and password fields from secondary user during merge (7b4e948)
- consume promo offer in miniapp tariff-mode renewal path (b8857e7)
- consume promo offer in tariff_purchase.py, fix negative transaction amount (c8ef808)
- delete cross-referral earnings before bulk reassignment, clear secondary.referred_by_id (f204b67)
- from redis.exceptions import NoScriptError (667291a)
- harden account merge security and correctness (d855e9e)
- merge: validate before consuming token, add flush, defensive balance (bc1e6fb)
- negative balance transfer, linking state validation, referrer migration (531d5cf)
- prevent concurrent device purchases exceeding max device limit (1cfede2)
- prevent infinite reuse of first_purchase_only promo code discounts (2cec8dc)
- prevent self-referral loops, invalidate all sessions on merge (db61365)
- reassign orphaned records on merge, eliminate TOCTOU race (d7a9d2b)
- redis cache uses sync client due to import shadowing (667291a)
- restore merge token on DB failure, fix partner_status priority (9582758)
- review findings — exception chaining, redundant unquote, validator tightening (467dea1)
- second round review fixes for account merge (64ee045)
- use short TTL fallback in restore_merge_token on parse error (0e8c61a)
- гарантировать положительный доход от подписок и исправить общий доход (93a55df)
- добавить create_transaction для 6 потоков оплаты с баланса (374907b)
- добавить create_transaction и admin-уведомления для автопродлений (9f35088)
- добавить пробелы в формат тарифов (1000 ГБ / 2 📱) (900be65)
- изолировать stored_amount от downstream consumers в create_transaction (b87535a)
- передать явный диапазон дат для all_time_stats в дашборде (968d147)
- показывать кнопку покупки тарифа вместо ошибки для триальных подписок (acfa4b3)
- показывать только активные провайдеры на странице /profile/accounts (9d7a557)
- реактивация DISABLED подписок при покупке трафика для LIMITED пользователей (7d28f55)
- реактивация DISABLED подписок при покупке устройств и в REST API (b9e17be)
- синхронизация версии pyproject.toml с main и обновление uv в Dockerfile (b31a893)
- убрать WITHDRAWAL из автонегации, добавить abs() в агрегации, исправить all_time_stats (6da61d7)
- убрать избыточный минус в amount_kopeks для create_transaction (849b3a7)
- устранение race condition при покупке устройств через re-lock после коммита (a7a18dd)
- устранение каскадного PendingRollbackError при восстановлении бэкапа (8259278)
Refactoring
- extract shared OAuth linking logic, add Literal types for providers (f7caf0d)
3.22.0 (2026-03-04)
New Features
- replace pip with uv in Dockerfile (e23d69f)
Bug Fixes
- add selectinload for campaign registrations in list query (4d74afd)
- backup restore fails on FK constraints and transaction poisoning (ff1c872)
- classic mode prices overridden by active tariff prices (628a99e)
- close remaining daily subscription expire paths (618c936)
- empty JSONB values exported as None in backup (57aaca8)
- handle duplicate remnawave_uuid on email sync (eaeee7a)
- MissingGreenlet on campaign registrations access (018f18f)
- prevent daily subscriptions from being expired by middleware/CRUD/webhook (0ed6397)
- reset traffic purchases on expired subscription renewal + pricing fixes (dce9eaa)
3.21.0 (2026-03-02)
New Features
- add admin campaign chart data endpoint with deposits/spending split (fa7de58)
- add admin sales statistics API with 6 analytics endpoints (58faf9e)
- add daily deposits by payment method breakdown (d33c5d6)
- add daily device purchases chart to addons stats (2449a5c)
- add desired commission percent to partner application (7ea8fbd)
- add RESET_TRAFFIC_ON_TARIFF_SWITCH admin setting (4eaedd3)
- enhance sales stats with device purchases, per-tariff daily breakdown, and registration tracking (31c7e2e)
Bug Fixes
- add exc_info traceback to sync user error log (efdf2a3)
- add local traffic_used_gb reset in all tariff switch handlers (2cdbbc0)
- add min_length to state field, use exc_info for referral warning (062c486)
- add missing subscription columns migration (b96e819)
- address review findings from agent verification (cc5be70)
- correct cart notification after balance top-up (2fab50c)
- correct referral withdrawal balance formula and commission transaction type (83c6db4)
- count sales from completed payment transactions instead of subscription created_at (06c3996)
- eliminate double panel API call on tariff change, harden cart notification (b2cf4aa)
- eliminate referral system inconsistencies (60c97f7)
- email verification bypass, ban-notifications size limit, referral balance API (256cbfc)
- enforce user restrictions in cabinet API and fix poll history crash (faba3a8)
- freekassa OP-SP-7 error and missing telegram notification (200f91e)
- generate missing crypto link on the fly and skip unresolved templates (4c72058)
- handle expired callback queries and harden middleware error handling (f52e6ae)
- handle expired ORM attributes in sync UUID mutation (9ae5d7b)
- handle NULL used_promocodes for migrated users (cdcabee)
- hide traffic topup button when tariff doesn't support it (399ca86)
- improve campaign routes, schemas, and add database indexes (ded5c89)
- include desired_commission_percent in admin notification (dc3d22f)
- migrate VK OAuth to VK ID OAuth 2.1 with PKCE (1dfa780)
- partner system — CRUD nullable fields, per-campaign stats, atomic unassign, diagnostic logging (ed3ae14)
- prevent squad drop on admin subscription type change, require subscription for wheel spins (59f0e42)
- prevent sync from overwriting subscription URLs with empty strings (9c00479)
- reject promo codes for days when user has no subscription or trial (e32e2f7)
- remove premature tariff_id assignment in _apply_extension_updates (b47678c)
- renewals stats empty on all-time filter (e25fcfc)
- resolve GROUP BY mismatch for daily_by_tariff query (e5f29eb)
- restore panel user discovery on admin tariff change, localize cart reminder (1256ddc)
- separate base and purchased traffic in renewal pricing (739ba29)
- sync traffic reset across all tariff switch code paths (d708365)
- use .is_(True) and add or 0 guards per code review (69b5ca0)
- use direct is_trial access, add missing error codes to promo APIs (69a9899)
- use float instead of int | float (PYI041) (310edae)
- use SAVEPOINT instead of full rollback in sync user creation (2a90f87)
3.20.1 (2026-02-25)
Bug Fixes
- make migrations 0010/0011 idempotent, escape HTML in crash notification (a696896)
- prevent race condition expiring active daily subscriptions (bfef7cc)
3.20.0 (2026-02-25)
New Features
- add separate Freekassa SBP and card payment methods (0da0c55)
- add validation to animation config API (a15403b)
Bug Fixes
- initialize logger in bot_configuration.py (988d0e5)
- remove gemini-effect and noise from allowed background types (731eb24)
- resolve ruff lint errors (import sorting, unused variable) (b2d7abf)
- resolve sync 404 errors, user deletion FK constraint, and device limit not sent to RemnaWave (1ce9174)
3.19.0 (2026-02-25)
New Features
- add granular user permissions (balance, subscription, promo_group, referral, send_offer) (60c4fe2)
- add per-channel disable settings and fix CHANNEL_REQUIRED_FOR_ALL bug (3642462)
- add RBAC + ABAC permission system for admin cabinet (3fee54f)
- add resource_type and request body to audit log entries (388fc7e)
- allow editing system roles (f6b6e22)
- capture query params in audit log details for all requests (bea9da9)
Bug Fixes
- address RBAC review findings (CRITICAL + HIGH) (1646f04)
- align RBAC route prefixes with frontend API paths (5a7dd3f)
- always include details in successful audit log entries (3dc0b93)
- extract real client IP from X-Forwarded-For/X-Real-IP headers (af6686c)
- grant legacy config-based admins full RBAC access (8893fc1)
- improve campaign notifications and ticket media in admin topics (a594a0f)
- RBAC API response format fixes and audit log user info (4598c27)
- RBAC audit log action filter and legacy admin level (c1da8a4)
- restore subscription_url and crypto_link after panel sync (26efb15)
- specify foreign_keys on User.admin_roles_rel to resolve ambiguous join (bc7d061)
- stack promo group + promo offer discounts in bot (matching cabinet) (628997f)
3.18.0 (2026-02-24)
New Features
- add ChatTypeFilterMiddleware to ignore group/forum messages (25f014f)
- add multi-channel mandatory subscription system (8375d7e)
- add required channels button to admin settings submenu in bot (3af07ff)
- colored channel subscription buttons via Bot API 9.4 style (0b3b2e5)
- rework guide mode with Remnawave API integration (5a269b2)
Bug Fixes
- add missing CHANNEL_CHECK_NOT_SUBSCRIBED localization key (a47ef67)
- address code review issues in guide mode rework (fae6f71)
- address security review findings (6feec1e)
- callback routing safety and cache invalidation order (6a50013)
- correct broadcast button deep-links for cabinet mode (e5fa45f)
- HTML-escape all externally-sourced text in guide messages (711ec34)
- improve deduplication log message wording in monitoring service (2aead9a)
- invalidate app config cache on local file saves (978726a)
- pre-existing bugs found during review (1bb939f)
- remove @username channel ID input, auto-prefix -100 for bare digits (a7db469)
- restore RemnaWave config management endpoints (6f473de)
- translate required channels handler to Russian, add localization keys (1bc9074)
Refactoring
- remove legacy app-config.json system (295d2e8)
3.17.1 (2026-02-23)
Bug Fixes
- add diagnostic logging for device_limit sync to RemnaWave (97b3f89)
- add int32 overflow guards and strengthen auth validation (50a931e)
- add missing broadcast_history columns and harden subscription logic (d4c4a8a)
- allow tariff switch when less than 1 day remains (67f3547)
- cap expected_monthly_referrals to prevent int32 overflow (2ef6185)
- cross-validate Telegram identity on every authenticated request (973b3d3)
- handle RemnaWave API errors in traffic aggregation (ed4624c)
- migrate all remaining naive timestamp columns to timestamptz (708bb9e)
- prevent partner self-referral via own campaign link (115c0c8)
- protect active paid subscriptions from being disabled in RemnaWave (1b6bbc7)
- repair missing DB columns and make backup resilient to schema mismatches (c20355b)
- show negative amounts for withdrawals in admin transaction list (5ee45f9)
- suppress web page preview when logo mode is disabled (1f4430f)
- uploaded backup restore button not triggering handler (ebe5083)
- use aiogram 3.x bot.download() instead of document.download() (205c8d9)
3.17.0 (2026-02-18)
New Features
- add referral code tracking to all cabinet auth methods + email_templates migration (18c2477)
Bug Fixes
- prevent 'caption is too long' error in logo mode (6e28a1a)
- skip blocked users in trial notifications and broadcasts without DB status change (493f315)
3.16.3 (2026-02-18)
Bug Fixes
- 3 user deletion bugs — type cast, inner savepoint, lazy load (af31c55)
- auth middleware catches all commit errors, not just connection errors (6409b0c)
- connected_squads stores UUIDs, not int IDs — use get_server_ids_by_uuids (d7039d7)
- deadlock on user deletion + robust migration 0002 (b7b83ab)
- eliminate deadlock by matching lock order with webhook (d651a6c)
- make migration 0002 robust with table existence checks (f076269)
- wrap user deletion steps in savepoints to prevent transaction cascade abort (a38dfcb)
3.16.2 (2026-02-18)
Bug Fixes
- auto-convert naive datetimes to UTC-aware on model load (f7d33a7)
- extend naive datetime guard to all model properties (bd11801)
- handle naive datetime in raw SQL row comparison (payment/common) (38f3a9a)
- handle naive datetimes in Subscription properties (e512e5f)
- use AwareDateTime TypeDecorator for all datetime columns (a7f3d65)
3.16.1 (2026-02-18)
Bug Fixes
- add migration for partner system tables and columns (4645be5)
- add migration for partner system tables and columns (79ea398)
3.16.0 (2026-02-18)
New Features
- add admin notifications for partner applications and withdrawals (cf7cc5a)
- add admin partner settings API (withdrawal toggle, requisites text, partner visibility) (6881d97)
- add campaign_id to ReferralEarning for campaign attribution (0c07812)
- add partner system and withdrawal management to cabinet (58bfaea)
- attribute campaign registrations to partner for referral earnings (767e965)
- blocked user detection during broadcasts, filter blocked from all notifications (10e231e)
- enforce 1-to-1 partner-campaign binding with partner info in campaigns (366df18)
- expose traffic_reset_mode in subscription response (59383bd)
- expose traffic_reset_mode in tariff API response (5d4a94b)
- include partner campaigns in /partner/status response (ea5d932)
- link campaign registrations to partner for referral earnings (c4dc43e)
- notify users on partner/withdrawal approve/reject (327d4f4)
Bug Fixes
- add blocked_count column migration to universal_migration.py (b4b10c9)
- add missing payment providers to payment_utils and fix {total_amount} formatting (bdb6161)
- add selectinload for subscription in campaign user list (eb9dba3)
- campaign web link uses ?campaign= param, not ?start= (28f524b)
- correct subscription_service import in broadcast cleanup (6c4e035)
- critical security and data integrity fixes for partner system (8899749)
- handle YooKassa NotFoundError gracefully in get_payment_info (df5b1a0)
- medium-priority fixes for partner system (7c20fde)
- move PartnerStatus enum before User class to fix NameError (acc1323)
- prevent fileConfig from destroying structlog handlers (e78b104)
- reorder button_click_logs migration to nullify before ALTER TYPE (df5415f)
- resolve HIGH-priority performance and security issues in partner system (fcf3a2c)
- return zeroed stats dict when withdrawal is disabled (7883efc)
- unassign all campaigns when revoking partner status (d39063b)
Refactoring
- replace universal_migration.py with Alembic (b6c7f91)
- replace universal_migration.py with Alembic (784616b)
3.15.1 (2026-02-17)
Bug Fixes
- add naive datetime guards to fromisoformat() in Redis cache readers (1b3e6f2)
- add naive datetime guards to fromisoformat() in Redis cache readers (6fa4948)
3.15.0 (2026-02-17)
New Features
- add LOG_COLORS env setting to toggle console ANSI colors (27309f5)
- add web campaign links with bonus processing in auth flow (d955279)
Bug Fixes
- AttributeError in withdrawal admin notification (send_to_admins → send_admin_notification) (c75ec0b)
- remove local UTC re-imports shadowing module-level import in purchase.py (e68760c)
3.14.1 (2026-02-17)
Bug Fixes
- add naive datetime guards to parsers and fix test datetime literals (0946090)
- address remaining abs() issues from review (ff21b27)
- complete datetime.utcnow() → datetime.now(UTC) migration (eb18994)
- normalize transaction amount signs across all aggregations (4247981)
- prevent negative amounts in spent display and balance history (c30972f)
3.14.0 (2026-02-16)
New Features
- show all active webhook endpoints in startup log (9d71005)
Bug Fixes
- force basicConfig to replace pre-existing handlers (7eb8d4e)
- NameError in set_user_devices_button — undefined action_text (1b8ef69)
- remove unused PaymentService from MonitoringService init (491a7e1)
- resolve MissingGreenlet error when accessing subscription.tariff (a93a32f)
- sync support mode from cabinet admin to SupportSettingsService (516be6e)
- sync SUPPORT_SYSTEM_MODE between SystemSettings and SupportSettings (0807a9f)
Refactoring
- improve log formatting — logger name prefix and table alignment (f637204)
3.13.0 (2026-02-16)
New Features
- colored console logs via structlog + rich + FORCE_COLOR (bf64611)
Bug Fixes
- limit Rich traceback output to prevent console flood (11ef714)
- resolve exc_info for admin notifications, clean log formatting (11f8af0)
- suppress startup log noise (~350 lines → ~30) (8a6650e)
- traceback in Telegram notifications + reduce log padding (909a403)
- use sync context manager for structlog bound_contextvars (25e8c9f)
Refactoring
- complete structlog migration with contextvars, kwargs, and logging hardening (1f0fef1)
3.12.1 (2026-02-16)
Bug Fixes
- add /start burst rate-limit to prevent spam abuse (61a9722)
- add promo code anti-abuse protections (97ec39a)
- handle TelegramBadRequest in ticket edit_message_text calls (8e61fe4)
- replace deprecated Query(regex=) with pattern= (871ceb8)
3.12.0 (2026-02-15)
New Features
- add 'default' (no color) option for button styles (10538e7)
- add button style and emoji support for cabinet mode (Bot API 9.4) (bf2b2f1)
- add per-button enable/disable toggle and custom labels per locale (68773b7)
- add per-section button style and emoji customization via admin API (a968791)
- add web admin button for admins in cabinet mode (9ac6da4)
- rename MAIN_MENU_MODE=text to cabinet with deep-linking to frontend sections (ad87c5f)
Bug Fixes
- daily tariff subscriptions stuck in expired/disabled with no resume path (80914c1)
- filter out traffic packages with zero price from purchase options (64a684c)
- handle photo message in ticket creation flow (e182280)
- handle tariff_extend callback without period (back button crash) (ba0a5e9)
- pre-validate CABINET_BUTTON_STYLE to prevent invalid values from suppressing per-section defaults (46c1a69)
- remove redundant trial inactivity monitoring checks (d712ab8)
- webhook notification 'My Subscription' button uses unregistered callback_data (1e2a7e3)
3.11.0 (2026-02-12)
New Features
- add cabinet admin API for pinned messages management (1a476c4)
- add startup warnings for missing HAPP_CRYPTOLINK_REDIRECT_TEMPLATE and MINIAPP_CUSTOM_URL (476b89f)
Bug Fixes
- add passive_deletes to Subscription relationships to prevent NOT NULL violation on cascade delete (bfd66c4)
- add startup warning for missing HAPP_CRYPTOLINK_REDIRECT_TEMPLATE in guide mode (1d43ae5)
- flood control handling in pinned messages and XSS hardening in HTML sanitizer (454b831)
- suppress expired callback query error in AuthMiddleware (2de4384)
- ticket creation crash and webhook PendingRollbackError (760c833)
3.10.3 (2026-02-12)
Bug Fixes
- handle unique constraint conflicts during backup restore without clear_existing (5893874)
- harden backup create/restore against serialization and constraint errors (fc42916)
- resolve deadlock on server_squads counter updates and add webhook notification toggles (57dc1ff)
3.10.2 (2026-02-12)
Bug Fixes
- allow email change for unverified emails (93bb8e0)
- clean stale squad UUIDs from tariffs during server sync (fcaa9df)
- delete subscription_servers before subscription to prevent FK violation (7d9ced8)
- handle StaleDataError in webhook user.deleted server counter decrement (c30c2fe)
- handle time/date types in backup JSON serialization (27365b3)
- HTML parse fallback, email change race condition, username length limit (d05ff67)
- payment race conditions, balance atomicity, renewal rollback safety (c5124b9)
- remove DisplayNameRestrictionMiddleware (640da34)
- suppress bot-blocked-by-user error in AuthMiddleware (fda9f3b)
- UnboundLocalError for get_logo_media in required_sub_channel_check (d3c14ac)
- use traffic topup config and add WATA 429 retry (b5998ea)
Refactoring
- remove modem functionality from classic subscriptions (ee2e79d)
3.10.1 (2026-02-11)
Bug Fixes
- address review issues in backup, updates, and webhook handlers (2094886)
- allow purchase when recalculated price is lower than cached (19dabf3)
- change CryptoBot URL priority to bot_invoice_url for Telegram opening (3193ffb)
- clear subscription data when user deleted from Remnawave panel (b0fd38d)
- downgrade Telegram timeout errors to warning in monitoring service (e43a8d6)
- expand backup coverage to all 68 models and harden restore (02e40bd)
- handle nullable traffic_limit_gb and end_date in subscription model (e94b93d)
- handle StaleDataError in webhook when user already deleted (d58a80f)
- ignore 'message is not modified' on privacy policy decline (be1da97)
- preserve purchased traffic when extending same tariff (b167ed3)
- prevent cascading greenlet errors after sync rollback (a1ffd5b)
- protect server counter callers and fix tariff change detection (bee4aa4)
- suppress 'message is not modified' error in updates panel (3a680b4)
- use callback fallback when MINIAPP_CUSTOM_URL is not set (eaf3a07)
- use flush instead of commit in server counter functions (6cec024)
3.10.0 (2026-02-10)
New Features
- add all remaining RemnaWave webhook events (node, service, crm, device) (1e37fd9)
- add close button to all webhook notifications (d9de15a)
- add MULENPAY_WEBSITE_URL setting for post-payment redirect (fe5f5de)
- add RemnaWave incoming webhooks for real-time subscription events (6d67cad)
- handle errors.bandwidth_usage_threshold_reached_max_notifications webhook (8e85e24)
- handle service.subpage_config_changed webhook event (43a326a)
- unified notification delivery for webhook events (email + WS support) (26637f0)
- webhook protection — prevent sync/monitoring from overwriting webhook data (184c52d)
Bug Fixes
- add action buttons to webhook notifications and fix empty device names (7091eb9)
- add missing placeholders to Arabic SUBSCRIPTION_INFO template (fe54640)
- allow non-HTTP deep links in crypto link webhook updates (f779225)
- build composite device name from platform + hwid short suffix (17ce640)
- downgrade transient API errors (502/503/504) to warning level (ec8eaf5)
- extract device name from nested hwidUserDevice object (79793c4)
- preserve payment initiation time in transaction created_at (90d9df8)
- security and architecture fixes for webhook handlers (dc1e96b)
- stop CryptoBot webhook retry loop and save cabinet payments to DB (2cb6d73)
- sync subscription status from panel in user.modified webhook (5156d63)
- use event field directly as event_name (already includes scope prefix) (9aa22af)
- webhook:close button not working due to channel check timeout (019fbc1)
3.9.1 (2026-02-10)
Bug Fixes
- don't delete Heleket invoice message on status check (9943253)
- safe HTML preview truncation and lazy-load subscription fallback (40d8a6d)
- use actual DB columns for subscription fallback query (f0e7f8e)
3.9.0 (2026-02-09)
New Features
- add lite mode functionality with endpoints for retrieval and update (7b0403a)
- add Persian (fa) locale with complete translations (29a3b39)
- allow tariff deletion with active subscriptions (ebd6bee)
- localization: add Persian (fa) locale support and wire it across app flows (cc54a7a)
Bug Fixes
- nullify payment FK references before deleting transactions in user restoration (0b86f37)
- prevent sync from overwriting end_date for non-ACTIVE panel users (49871f8)
- promo code max_uses=0 conversion and trial UX after promo activation (1cae713)
- skip users with active subscriptions in admin inactive cleanup (e79f598)
- use selection.period.days instead of selection.period_days (4541016)
Performance
- cache logo file_id to avoid re-uploading on every message (142ff14)
Refactoring
- remove "both" mode from BOT_RUN_MODE, keep only polling and webhook (efa3a5d)
- remove Flask, use FastAPI exclusively for all webhooks (119f463)
- remove smart auto-activation & activation prompt, fix production bugs (a3903a2)
3.8.0 (2026-02-08)
New Features
- add admin device management endpoints (c57de10)
- add admin traffic packages and device limit management (2f90f91)
- add admin updates endpoint for bot and cabinet releases (11b8ab1)
- add endpoint for updating user referral commission percent (da6f746)
- add enrichment data to CSV export (f2dbab6)
- add server-side sorting for enrichment columns (15c7cc2)
- add system info endpoint for admin dashboard (02c30f8)
- add traffic usage enrichment endpoint with devices, spending, dates, last node (5cf3f2f)
- admin panel enhancements & bug fixes (e6ebf81)
Bug Fixes
- add debug logging for bulk device response structure (46da31d)
- add email field to traffic table for OAuth/email users (94fcf20)
- add email/UUID fallback for OAuth user panel sync (165965d)
- add enrichment device mapping debug logs (5be82f2)
- include additional devices in tariff renewal price and display (17e9259)
- paginate bulk device endpoint to fetch all HWID devices (4648a82)
- read bot version from pyproject.toml when VERSION env is not set (9828ff0)
- revert device pagination, add raw user data field discovery (8f7fa76)
- use bulk device endpoint instead of per-user calls (5f219c3)
- use correct pagination params (start/size) for bulk HWID devices (17af51c)
- use per-user panel endpoints for reliable device counts and last node data (9d39901)
3.7.2 (2026-02-08)
Bug Fixes
- handle FK violation in create_yookassa_payment when user is deleted (55d281b)
- remove dots from Remnawave username sanitization (d6fa86b)
3.7.1 (2026-02-08)
Bug Fixes
- release-please config — remove blocked workflow files (d88ca98)
- remove workflow files and pyproject.toml from release-please extra-files (5070bb3)
- resolve HWID reset and webhook FK violation (5f3e426)
- resolve HWID reset context manager bug and webhook FK violation (a9eee19)
- resolve merge conflict in release-please config (0ef4f55)
- resolve multiple production errors and performance issues (071c23d)
3.7.0 (2026-02-07)
Features
- add admin traffic usage API (aa1cd38)
- add admin traffic usage API with per-node statistics (6c2c25d)
- add node/status filters and custom date range to traffic page (ad260d9)
- add node/status filters, custom date range, connected devices to traffic page (9ea533a)
- add node/status filters, date range, devices to traffic page (ad6522f)
- add risk columns to traffic CSV export (7c1a142)
- add tariff filter, fix traffic data aggregation (fa01819)
- node/status filters + custom date range for traffic page (a161e2f)
- tariff filter + fix traffic data aggregation (1021c2c)
- traffic filters, date range & risk columns in CSV export (4c40b5b)
Bug Fixes
- close unclosed HTML tags in version notification (0b61c7f)
- close unclosed HTML tags when truncating version notification (b674550)
- correct response parsing for non-legacy node-users endpoint (a076dfb)
- correct response parsing for non-legacy node-users endpoint (91ac90c)
- handle mixed types in traffic sort (eeed2d6)
- handle mixed types in traffic sort for string fields (a194be0)
- resolve 429 rate limiting on traffic page (b12544d)
- resolve 429 rate limiting on traffic page (924d6bc)
- use legacy per-node endpoint for traffic aggregation (cc1c8ba)
- use legacy per-node endpoint with correct response format (b707b79)
- use PaymentService for cabinet YooKassa payments (61bb8fc)
- use PaymentService for cabinet YooKassa payments to save local DB record (ff5bba3)
3.6.0 (2026-02-07)
Features
- add OAuth 2.0 authorization (Google, Yandex, Discord, VK) (97be4af)
- add panel info, node usage endpoints and campaign to user detail (287a43b)
- add panel info, node usage endpoints and campaign to user detail (0703212)
- add TRIAL_DISABLED_FOR setting to disable trial by user type (c4794db)
- add user_id filter to admin tickets endpoint (8886d0d)
- add user_id filter to admin tickets endpoint (d3819c4)
- block registration with disposable email addresses (9ca24ef)
- block registration with disposable email addresses (116c845)
- disable trial by user type (email/telegram/all) (4e7438b)
- migrate OAuth state storage from in-memory to Redis (e9b98b8)
- OAuth 2.0 authorization (Google, Yandex, Discord, VK) (3cbb9ef)
- return 30-day daily breakdown for node usage (7102c50)
- return 30-day daily breakdown for node usage (e4c65ca)
Bug Fixes
- increase OAuth HTTP timeout to 30s (333a3c5)
- parse bandwidth stats series format for node usage (557dbf3)
- parse bandwidth stats series format for node usage (462f7a9)
- pass tariff object instead of tariff_id to set_tariff_promo_groups (1ffb8a5)
- query per-node legacy endpoint for user traffic breakdown (b94e3ed)
- query per-node legacy endpoint for user traffic breakdown (51ca3e4)
- reduce node usage to 2 API calls to avoid 429 rate limit (c68c4e5)
- reduce node usage to 2 API calls to avoid 429 rate limit (f00a051)
- use accessible nodes API and fix date format for node usage (943e9a8)
- use accessible nodes API and fix date format for node usage (c4da591)
3.5.0 (2026-02-06)
Features
- add tariff reorder API endpoint (4c2e11e)
- pass platform-level fields from RemnaWave config to frontend (095bc00)
- serve original RemnaWave config from app-config endpoint (43762ce)
- tariff reorder API endpoint (085a617)
Bug Fixes
- enforce blacklist via middleware (561708b)
- enforce blacklist via middleware instead of per-handler checks (966a599)
- exclude signature field from Telegram initData HMAC validation (5b64046)
- improve button URL resolution and pass uiConfig to frontend (0ed98c3)
- restore unquote for user data parsing in telegram auth (c2cabbe)
Reverts
- remove signature pop from HMAC validation (4234769)