Bring the ASCII, Windows 95 and light themes up to date with the
webapp changes since the last theme refresh:
- Flatten/bevel the new Telegram notifications banner icon badge.
- Square off the premium-server and referral-tariff dropdown help
pills and bevel the standalone referral surfaces (win95).
- Fix the selected-language check vanishing on the highlighted row
(black on ASCII, inverted bitmap on win95).
- Square the login-screen language trigger and render flag emoji
monochrome in the ASCII console palette.
- Add a soft drop shadow to the banner on the light theme.
Bump assets_version for all three CSS themes and update the theme
config tests accordingly.
Add a broadcast audience for users who registered but never had any subscription or trial (no Subscription rows at all), backed by a new get_user_ids_without_any_subscription DAL helper and a 'never' target in the webapp broadcast route.
Add GET /api/admin/broadcast/audience-counts so the audience dropdown shows the recipient count next to each option, with graceful fallback when counts are unavailable.
On mobile the extend input/button and the reset-trial button rendered at 36px, which felt cramped for touch. Bump them to 46px in the max-width:640px block.
The toggle carried both .admin-btn and .admin-users-filter-toggle, which tied on specificity with the base button display rule and kept the button visible on desktop. Scope the show/hide rules to .admin-btn.admin-users-filter-toggle so it only appears on mobile.
CodeQL still traced taint through the previous helpers: the endpoint
regex fallback returned source-derived text and the payload dict keys
flowed verbatim into the log. Resolve both by sourcing every logged
token from literal lookup tables — endpoints map to constant path
labels and payload keys map through a field-name allow-list, with
unknown keys/paths collapsing to <field>/<other>. No source-derived
string (key, value or id) reaches the logger.
Rebuild logged endpoints from constant path templates and reduce every
payload leaf to a JSON type token, so user/squad UUIDs and PII (email,
telegramId) can never reach the dry-run log as clear text. Resolves
CodeQL py/clear-text-logging-sensitive-data findings.
CodeQL flagged clear-text logging of sensitive information in the panel
dry-run logger: it dumped the full request payload (which can include
proxy credentials like trojanPassword/ssPassword and PII such as email
and telegramId) and the raw endpoint (embedding user UUIDs).
Recursively redact values under sensitive keys before building the
payload preview, and mask opaque id-like segments in logged endpoints.
Add a once-a-day anonymous heartbeat (PostHog) so maintainers can see
active installs and version/OS breakdowns. Self-hosted friendly: opt out
via TELEMETRY_ENABLED in .env or the Admin -> System toggle (applied
without a restart), or by clearing the endpoint/key.
- Share version resolution in bot/utils/app_version.py so the admin
sidebar and the beacon report the same build version
- TelemetryWorker sends an opaque install id plus coarse facts only
(version, OS/arch, python, locale, enabled providers, user-count
range); never tokens, domains or user data
- Register the worker in main_worker.py behind a Redis single-flight lock
- Expose TELEMETRY_* settings and an Admin -> System manifest toggle
- Document the payload and opt-out in docs/configuration/telemetry.md
- Cover bucketing, payload shape and anonymity with tests