Add a new provider module for LAVA Business (api.lava.ru):
- invoice creation via POST /business/invoice/create signed with
HMAC-SHA256 over the raw request body in the Signature header
- webhook handling with Authorization-header signature verification
that accepts both raw-body and sorted-keys JSON canonicalizations
(legacy PHP SDK shops sign the latter), plus amount cross-check
before finalizing a successful payment
- pending invoice reuse through /business/invoice/status
- Telegram pay_lava callback flow and Web App payment creation
- admin settings manifest fields, presentation overrides, and
RUB-only currency support declared on the provider SPEC
Register the SPEC in the provider registry and wire the provider into
the payment method order, success-email labels, and locale override
prefixes.
Stamp official Docker builds with a low-cardinality provenance marker and report build_provenance/image_modified in anonymous telemetry. Local and fork builds default to custom, while official GitHub/GitLab release paths mark images as official.
Emoji logos were removed long ago; the only remaining trace was a
purge of stale data/webapp-emoji cache files on theme save. Remove
the purge, the WEBAPP_EMOJI_CACHE_DIR constant and the emoji part of
the prune test.
Add GET /api/admin/health powered by a config health service that
detects common deployment mistakes: missing or read-only data volume,
broken tariffs/locale-override/guides JSON files, payment providers
enabled without credentials, webhook providers without
WEBHOOK_BASE_URL, no enabled payment methods, missing or non-https
mini app URL, missing Redis, partially configured SMTP, untrusted
reverse proxy, invalid bot token, missing/mismatched/failing Telegram
webhook and unreachable Remnawave panel. Network checks (Telegram,
panel) are cached for two minutes; ?refresh=1 forces a re-check.
The admin UI shows the alerts as a banner on the dashboard with
per-section navigation chips and a manual re-check button, and as a
filtered banner inside each affected section. Alerts are localized
via admin_health_* keys with built-in Russian fallbacks.
PAYMENT_REQUEST_TIMEOUT_SECONDS was read once in each provider's
__init__ and baked into the aiohttp session, so admin overrides
(applied in-process) only took effect after a container restart.
Providers now hand HttpClientMixin a timeout source callable; the
mixin builds the session with the current value and swaps in a fresh
session when the value changes, closing the replaced one only after
any in-flight request on it is bound by its own total timeout.
Also:
- check the Heleket payment-info success flag before reading the
payload so a non-dict provider response cannot raise in the
pending-payment reuse path
- add PAYMENT_REQUEST_TIMEOUT_SECONDS to the FreeKassa settings stub
in test_security.py (fixes three tests broken by the new field)
The lazy-loaded admin CSS/JS resolved to bare runtime names served
no-store, the same scheme that left the main bundle vulnerable to stale
CSS in iOS WebViews after a deploy. The original reason for keeping them
bare (hashed admin files could 404 when nginx fronts aiohttp) no longer
holds: the backend image now carries the same deterministically hashed
assets nginx serves, and the App.svelte loader already falls back to the
bare name if a hashed asset ever 404s.
Resolve the admin assets through the same hashed/version-stable path as
the main bundle so they are emitted as immutable, cache-busting URLs.
Also drop the inert <meta http-equiv="Cache-Control/Pragma/Expires">
tags from the shell: browsers ignore http-equiv caching directives for
the document and use the real HTTP headers, which are already set.
The once-per-version Clear-Site-Data: "cache" header on the index
navigation raced the page's own CSS/JS subresource loads in the
Telegram WebView, intermittently evicting or aborting the main
stylesheet so the mini app rendered half-styled on mobile.
It also could not fix stale HTML: it only fires when the document
actually reaches the backend, never when the WebView serves a cached
page. The no-store HTML plus immutable content-hashed asset filenames
already guarantee freshness without clearing the cache, so remove the
reset header, its helpers, constants, and tests.