Commit Graph
225 Commits
Author SHA1 Message Date
Dushnilin fd79c4e317 feat: поддержка HTTP/HTTPS прокси (#45), комплексная доработка деинсталляции и отката конфигурации (1.3.22) 2026-09-06 14:12:27 +03:00
Dushnilin 11925e7ec5 fix(updates): resolve tag commit SHA and format build fingerprints; fix telegram, watchdog and logs 2026-09-05 23:52:16 +03:00
Dushnilin 7cfd737d21 fix(watchdog): bind probe_wan to configured output_network_interface 2026-09-05 12:50:15 +03:00
Dushnilin a4a757223f fix(awg): support AmneziaWG 2.0/3.0/3.1, fix WARP generator safety & update release 1.3.20 2026-09-05 12:00:14 +03:00
Dushnilin dbe6eb013c fix(perf): eliminate 50k hosts DNS rules CPU lockup, optimize UI polling & memory limits 2026-09-05 00:14:51 +03:00
Dushnilin ae79195c17 fix: GOMEMLIMIT for all devices, cascade delete orphans, logread cleanup
- GOMEMLIMIT: remove 256MB RAM threshold cap. Now applies to ALL
  devices. Formula: min(35% RAM, 512MB). mem_scale respected.
  Fixes sing-box eating 500MB+ on 2GB routers with no limit.

- Cascade delete: when a routing section is deleted, child UCI entries
  (subscription_url, urltest, priority_group, priority_level,
  section_interface) are now removed. Prevents orphaned entries that
  corrupt config generation.

- Migration cleanup: orphan_section_interfaces now cleans ALL child
  types, not just section_interface.

- Watchdog logread: kill orphans in stop_runtime(), add SIGTERM/SIGINT
  handlers in uloop mode (previously only in fallback mode).
2026-09-04 20:25:54 +03:00
Dushnilin 529db5fc6c fix(watchdog,priority,dns_failover,providers): reduce CPU/memory footprint on low-end routers (1.3.20)
- priority.uc: replace 1s tight sleep loop with dynamic interval based on group config (5s default)
- dns_failover.uc: replace 1s sleep with min(active_interval, recovery_interval)
- watchdog.uc: cap pending_smart_domains at 500 entries, add 300s TTL expiry
- event_controller.uc: batch is_dns_working nslookup calls into single shell process
- byedpi/runtime.uc: add crash-loop backoff (up to 6x base delay after 5 rapid crashes)
- nfqueue/runtime.uc: same crash-loop backoff for nfqws supervisors
2026-09-04 19:44:20 +03:00
Dushnilin 69b6cf18ec fix(lifecycle): increase sing-box reload verification timeout to 60s for heavy rulesets (1.3.20) 2026-09-04 19:17:29 +03:00
Dushnilin 8e567bc190 fix(service): filter check commands from memory_rss_mb and apply GODEBUG madvdontneed (1.3.20) 2026-09-04 19:14:12 +03:00
Dushnilin 78bdd0b412 fix(core): optimize sing-box memory limits, eliminate SIGHUP memory thrashing, and harden zapret2 recovery (1.3.20) 2026-09-04 18:58:31 +03:00
Dushnilin 2f83954255 fix(updates): resolve service restart timeout and LuCI session drop on upgrade (1.3.20) 2026-09-04 17:15:52 +03:00
Dushnilin 0cfc351d5a fix: restore zapret2 worker startup, fast doctor check, and dnsmasq sync (1.3.20) 2026-09-04 16:47:08 +03:00
Dushnilin 6bedef4c77 fix: zapret2 daemon privileges and lua loader, dnsmasq reload auto-repair (1.3.20) 2026-09-04 14:45:01 +03:00
Dushnilin e901f9d41a fix: zapret2 startup, dnsmasq fakeip rebind protection, dns detour routes (1.3.19) 2026-09-04 13:56:48 +03:00
Dushnilin 196782b18d feat: variant badges, live RSS RAM tracking, sysctl network tuning, telegram updates (1.3.18) 2026-09-03 23:23:39 +03:00
Dushnilin 4c69a98c27 fix(singbox): fix Leadaxe (lx) version parsing regex and AWG startup on OpenWrt
- In action.uc: replace broken PCRE non-capturing regex in extract_sing_box_version_from_output with token-based field splitting. ucode POSIX regex engine threw 'Repetition not preceded by valid expression', crashing component_action during binary validation.
- In telegram.uc: replace non-capturing group (?:outbounds|server|servers) with standard capturing group for POSIX regex compatibility.
- In generator_outbounds.uc and servers.uc: enhance is_lx detection to check sing-box-version file in addition to sing-box-variant, ensuring AWG 2.0 root schema is generated even if variant file is desynced.
- In runtime.uc: add fallback recovery in sing_box_check retry loop for endpoints (auto-flattening amnezia sub-objects) and outbounds unknown fields.
2026-09-03 21:11:00 +03:00
Dushnilin 1c48422511 fix(luci): ensure Tachyon menu item reliably appears in LuCI
- Remove 'uci: { tachyon: true }' dependency from menu.d/luci-app-tachyon.json so LuCI does not hide the menu node if UCI config is uncommitted/reloading
- Add portable timeout normalization in install.sh ucode to handle Busybox timeout and systems without timeout applet
- Ensure luci_postinst is called directly in IPK postinst (build.sh) and after install in install.sh
- Restart uhttpd alongside rpcd and purge LuCI caches in post-install and uninstaller
- Fix uninstall.sh to remove packages individually with lock retry and omit non-existent luci-i18n-tachyon-en
- In install_ui_packages, verify that menu.d/luci-app-tachyon.json actually exists on disk before proceeding
2026-09-03 19:14:22 +03:00
Dushnilin abaa891dd3 fix(updates): resolve component update hang and multiple page reload loop
- action.uc: sweep stuck flock 1000 processes before tachyon restart, bound service restart with 25s timeout, and prevent worker lockup
- shell/index.ts: add 15-minute general hard timeout for non-Tachyon components to prevent infinite modal spin; allow same-version confirmation for both install and reinstall
- package.uc: remove disruptive uhttpd restart from luci_postinst to prevent active socket drops
- ui.uc: refresh stale PID state before checking value.running in action_ack so dead jobs can always be acknowledged
- initController.ts & sessionJobs.ts: persist handled job IDs across reloads in sessionStorage, eliminate redundant modal popups on page reload, and guard against concurrent reloads with safeReloadPage
- renderUpdateProgressModal.ts: record active job before reload and poll readiness with fast health check instead of blind 5s freeze
2026-09-03 07:36:30 +03:00
Dushnilin 36fe7ef312 fix(package): preserve managed sing-box on package upgrade 2026-09-03 07:22:05 +03:00
Dushnilin b3358f77a3 fix(stability): optimize Go memory tiers, prevent nftables degradation deadlock, harden NTP & process supervision
- singbox/runtime.uc: add dynamic 4-tier GOMEMLIMIT and GOGC limits based on RAM, enforce /etc/tachyon/mem_scale, and install managed init script across all binary variants
- service/event_controller.uc: guard probe_nftables() with recovery_bypass and native_internet_restored checks to prevent 5-minute network drop deadlock
- service/watchdog.uc: reduce Telegram worker heartbeat timeout from 900s to 300s and add nslookup fallback to Zero-RTT prefetcher
- diagnostics/runtime.uc & service/lifecycle.uc: use direct-IP NTP pool to eliminate circular DNS/TLS deadlocks, and step clock forward on cold boot if RTC desynced
- service/failover.uc & diagnostics/runtime.uc: flush conntrack states on proxy group switch so client connections immediately migrate
2026-09-03 06:13:30 +03:00
Dushnilin 9c80cb4442 fix(telegram): eliminate hang bugs, button payload limit, and sync reload lifecycle
- wrap /sw callback data in cb_data() to strictly enforce 64-byte limit and prevent BUTTON_DATA_INVALID API rejections
- sync telegram daemon in lifecycle reload() so LuCI Save & Apply starts/reloads bot automatically without router reboot
- cleanly stop telegram worker in stop_main() to prevent orphaned background polling processes
- reduce interactive curl timeout in tg_request_via from 35s to 12s, preventing 70s worker freeze on proxy stalls
- close open HTML tags on message truncation and add fallback to plain text if Telegram entity parsing fails
- reduce watchdog telegram worker restart cooldown from 3600s to 120s
- fix nftables check in /test to inspect TachyonTable instead of legacy ip tachyon
- add command aliases /server, /servers, /rules, /ai_doctor and fix integer division in /connections pagination
2026-09-03 05:00:40 +03:00
Dushnilin 8b3c3e365f feat(dns): upstream mode (sequential/parallel) & explicit fallback DNS servers, bump 1.3.13 2026-09-01 20:49:21 +03:00
Dushnilin 416a15a805 fix(parental): не устанавливать cron-джоб если нет расписаний с квотами (убирает cron.err spam) 2026-09-01 18:50:13 +03:00
Dushnilin 2d551bd2d1 fix(service): исправить fs.stat в lifecycle.uc, очистку кэша LuCI и перезапуск rpcd/uhttpd 2026-09-01 15:15:42 +03:00
Dushnilin c33018fe8f fix(service): подавлять конкурирующие службы Forkop/Podkop из ROM при старте 2026-09-01 12:44:29 +03:00
Dushnilin f553352e25 release: 1.3.9 - Оптимизация кодовой базы (Ponytail Audit), очистка мертвого кода и ускорение Telegram-бота
- Frontend: полное удаление неиспользуемого renderAdvancedSettings.ts (-1354 строки), очистка каталогов локализации от фантомных ключей, инкапсуляция внутренних экспортов в runtimeTags и singBoxVariant
- Backend: удаление неиспользуемого singbox/dns_prefetch.uc (-243 строки) и его вызова в lifecycle.uc, удаление устаревших заглушек Forkop-эпохи в service_check.uc
- Telegram Bot: внедрение in-memory кэша cb_map_cache для устранения избыточных дисковых чтений/записей JSON при рендеринге inline-кнопок
- Версия: bump версии до 1.3.9 в package.json и package-lock.json
2026-09-01 08:48:29 +03:00
Dushnilin 706b35328c feat(ruleset): auto-assign download_detour for remote rulesets & add watchdog self-heal for ruleset DNS stalls 2026-08-30 21:22:23 +03:00
Dushnilin dfb32722bf release: 1.3.8 - OpenWrt network interfaces for WARP generator, DoH doctor URL normalization & doctor lock fixes 2026-08-30 20:05:16 +03:00
Dushnilin 123f5e6ccf release: 1.3.7 - Telegram alert deduplication & rate limiting, DNS detour deadlock resolution, ucode fs.opendir fixes 2026-08-29 21:28:41 +03:00
Dushnilin 939d9418a2 release: 1.3.6 - Family Profiles, Mobile Responsiveness, Mixed Proxy fix & AI Doctor Fuzzer improvements 2026-08-29 13:57:17 +03:00
Dushnilin 404db8ae05 fix(dpi-bypass): TCP keepalive + conntrack tuning + nfqueue watchdog
- sysctl: tcp_keepalive=60/10/3, conntrack_established=600s (was 5 days)
- nfqws/nfqws2: --ctrack-timeouts=30,30,600,30,30,30,30,30 in default strategy
- watchdog: probe_nfqueue checks nfqws/nfqws2 process health every 300s
- watchdog: heal_nfqueue_stopped restarts tachyon if DPI bypass processes die

This eliminates the need for manual DNS flush + device restart when DPI
starts blocking connections. Dead connections are now detected in ~90s
instead of hours, and stale conntrack entries expire in 10 min instead
of 5 days.
2026-08-28 20:05:03 +03:00
Dushnilin 7ddb7f6d4d fix(warp): timeout при прокси, четная длина hex для awg_i1..i5, исправление выбора секции прокси (#43) 2026-08-27 13:06:31 +03:00
Dushnilin 9bc6fe28fd feat(failover): автоматическое переключение прокси-секций
- генератор: при section_failover_enabled catch-all указывает на селектор tachyon-failover со всеми секциями-кандидатами
- выбор по умолчанию переживает рестарты через /etc/tachyon/failover_section, устаревшее имя откатывается на первую секцию
- service/failover.uc: пробер каждой секции через Clash API delay, порог N подряд — переключение на живую, TG-уведомление
- watchdog: вызов проверки в slow-тире (модуль сам отключён при выключенной опции)
- настройки: флаг + порог во вкладке Advanced, RU-локализация
- тесты: генерация вкл/выкл/персист/устаревшее состояние + логика переключения со стабом Clash API
2026-08-26 14:15:23 +03:00
Dushnilin b12f2fbdee feat(parental): дневные квоты времени на устройства
- опция daily_quota_minutes у расписаний: лимит минут использования сети в сутки
- поминутный cron-тик: учёт активности через ip neigh, блок до полуночи при исчерпании
- nft-сеты tachyon_quota_block (MAC) и _ip (IPv4) с drop-правилами; самовосстановление после ребилдов таблицы
- сброс счётчиков после смены суток, TG-уведомление о блокировке
- validator: проверка диапазона 0..1440
- UI: поле и колонка квоты в Родительском контроле + RU-локализация
2026-08-26 14:00:40 +03:00
Dushnilin 2c6a1a7343 feat(tailscale): watchdog нативного режима и панель пиров тейлнета
- watchdog: проверка native-секции в slow-тире, авторестарт демона после 2 сбоев, TG-алерт раз в час
- AI Doctor: узел Tailscale (готов/не установлен/упал) только при настроенном native
- провайдер: режим peers — парсинг status --json через per-section socket
- RPC get_tailscale_status/get_tailscale_peers/tailscale_restart
- дашборд: карточка Tailscale (состояние, IP роутера, до 5 пиров с онлайн-статусом)
2026-08-26 13:43:23 +03:00
Dushnilin 7f0b085a07 feat(tailscale): нативный режим tailscaled и компонент Tailscale
- новый компонент Tailscale: установка пакета из фида, карточка в Обновлениях
- режим native для секций Tailscale: системный tailscaled вместо sing-box endpoint
- доступ к тейлнету с LAN без клиента: маршруты 100.64.0.0/10 и MagicDNS через dnsmasq
- masquerade и exit-node (opt-in) с обходом tproxy по зарезервированной маске
- validator: требование tailscaled и auth-key для native; bypass-правила в mangle
- тесты: генерация конфига, смоук рантайма с моками, обновлена сигнатура состояния
2026-08-26 11:30:52 +03:00
Dushnilin c3172dd82d refactor: remove hardcoded port 4534 — dynamic port from config
- Added get_mixed_port() to core/common.uc (reads sing-box config.json)
- agent_api.uc, api.uc: use common.get_mixed_port()
- warp_generator.uc: use config port instead of hardcoded fallback
- watchdog.uc: use mixed_ports_from_config() for Clash API calls
- runtime.uc: dynamic port in conflict checks and proxy probe
2026-08-25 15:46:03 +03:00
Dushnilin 1aa69d5e03 feat(telegram): full i18n — ~230 Russian strings replaced with t() calls
- Added ~120 new i18n keys to both en and ru sections
- Replaced all remaining hardcoded Russian strings in telegram.uc
- Menu, status, connections, diagnostics, help, subscriptions, quiet hours,
  test rule, export, MAC blocking, devices, watchdog/AI, QoS, section
  management, DNS presets, exec, daily digest, update notifications,
  blocked activity, all navigation buttons
- All keys verified present via runtime check
2026-08-25 15:45:44 +03:00
Dushnilin 2c21dd93c7 fix(telegram): move get_mixed_port() before mixed_port_alive()
ucode doesn't hoist functions — get_mixed_port() must be defined
before mixed_port_alive() which calls it.
2026-08-24 21:09:27 +03:00
Dushnilin 9a3bb6054b fix(telegram): read actual mixed-port from sing-box config
- Add get_mixed_port() helper that reads config.json
- Replace all hardcoded 4534 in telegram.uc with get_mixed_port()
- mixed_port_alive() now checks the real port
- diagnose() checks the real port for proxy health
- Clash API calls use the real port
- Route failure alerts use i18n, remove hardcoded port number
- Fixes LuCI 'Check connection to Telegram' showing false negatives
  when sing-box uses a non-default mixed-port (e.g. 1602)
2026-08-24 21:06:17 +03:00
Dushnilin b3a425e524 feat(telegram): i18n en/ru + /lang command
- Create i18n.uc with en/ru string tables (~125 keys)
- Add t() binding at module level, set per-session via UCI telegram.language
- Replace hardcoded Russian in main menu, status, speed, ping, test,
  connections, outbounds, sections, diagnostics, restart, language
- Add /lang command: language picker with UCI persistence
- Setting schema labels translated at display time via get_schema_label()
- 175 t() calls, 245 remaining raw Russian (deep UI only)
2026-08-24 20:36:30 +03:00
Dushnilin 9d0761c14e fix(warp): расширен диапазон IP для генерации WARP
- Добавлены недостающие /24 диапазоны: 162.159.195.0/24, 162.159.204.0/24,
  188.114.96.0/24, 188.114.97.0/24 (ранее было только 4 из 8 диапазонов)
- probe_ips: 9 → 17 IP (по два представителя на каждый /24 + 8.6.112.0)
- resolve_ips/resolve_ips_probe для API-запросов: 4 → 8 IP
- engage.cloudflareclient.com DNS-резолв продолжает добавлять
  динамические IP в пул автоматически
2026-08-24 17:02:39 +03:00
Dushnilin 4b80deed5f fix(service): экспорт write_text_file и mixed-вотч по конфигу
- helpers.uc определяла write_text_file, но не экспортировала:
  биндинг в telegram-воркере был null, write_heartbeat падал каждый
  цикл — «Worker loop error: left-hand side is not a function»
  каждые ~25с, heartbeat не писался, воркер зря перезапускался
- watchdog: mixed-порт теперь читается из сгенерённого конфига
  sing-box (inbounds[].type=mixed), а не хардкод 4534. Когда mixed
  выключен (Main.mixed_proxy_enabled=0) — вотч встаёт в сторону
  вместо бесконечных «Restarting sing-box» с пересозданием nftables
  каждые ~5 минут
- проверено на живом роутере: 0 рестартов и 0 ошибок воркера после
  деплоя, E2E зелёный
2026-08-24 13:56:29 +03:00
Dushnilin 890450d619 fix(singbox): mtproxy-инбаунд вместо shadowsocks — корень «decode psk» (#23)
В ветке mtproto тип инбаунда перезатирался на shadowsocks-2022,
и ee-секрет уходил в password: SS2022 парсит его как base64-PSK —
отсюда FATAL «decode psk: illegal base64 data at input byte 60»
у всех, у кого включён MTProto-сервер.

- mtproto снова эмитит type=mtproxy (как в схеме extended 2.6.x),
  юзер — {name, secret}, а не password (регрессия fe0099a3)
- конфиг с MTProto и AWG проверен `sing-box check` на реальном
  sing-box-extended 1.13.18-extended-2.6.5 — PASS
- warp-генератор: прямой префлайт-зонд с --resolve (DNS-отравление
  больше не даёт ложное «API недоступен»), живость 4534 — локальная
  по /proc/net/tcp вместо сквозного запроса через туннель
- багрепорт маскирует ai_doctor_api_key и tuic_password
2026-08-24 11:26:28 +03:00
Dushnilin 6bbc37cfdd fix(service): необъявленные вызовы в watchdog и telegram-воркере
- watchdog: command_output_from_args использовался без биндинга —
  «Graceful degradation: check_mixed_proxy_port failed: left-hand
  side is not a function» на каждом проходе
- telegram: write_heartbeat звал write_text_file из core.helpers,
  который не импортировался — «Worker loop error» каждый цикл,
  heartbeat не писалcя, воркер зря перезапускался по стейлу
- E2E: ноль «left-hand side» в логах OpenWrt-контейнера после фикса
2026-08-24 10:53:06 +03:00
Dushnilin c788c86184 fix(warp): префлайт-проверка Cloudflare вместо XHR timeout
На сетях, где api.cloudflareclient.com недоступен (типичный случай из
issue #39), генератор сжигал весь временной бюджет - фронтенд умирал по
XHR timeout через 30 секунд, не показывая причины.

- префлайт: одна проба (4с connect / 6с max) напрямую и через доступный
  транспорт; если Cloudflare недостижим - мгновенная понятная ошибка
  «Cloudflare API недоступен...» вместо минутного зависания
- бюджеты ужаты до 20с на call_api и 20с на всю регистрацию, чтобы
  худший случай укладывался в XHR-таймаут LuCI
- все ошибочные выходы теперь печатают JSON-конверт и exit(0): фронтенд
  парсит data.message и показывает настоящую причину (ненулевой код
  заставлял его писать безликое Unknown error)
2026-08-22 10:07:40 +03:00
Dushnilin e446b370e3 feat(watchdog): самолечение порта 4534 и живости телеграм-воркера
- новая slow-проверка (раз в 5 мин): sing-box запущен, но mixed-порт 4534
  не слушается две проверки подряд (~10 мин) -> один авторестарт ядра;
  если не помогло - уведомление админу не чаще раза в час, без циклов
  бесконечных рестартов
- проверка живости телеграм-воркера: бот включён, pid жив, но heartbeat
  старше 15 минут (зависший long-poll/мёртвый цикл) или pid отсутствует ->
  рестарт воркера через telegram_start с ограничением раз в час
- обе проверки добавлены в perform_slow_checks через safe_call
2026-08-22 10:07:19 +03:00
Dushnilin 28c5c19645 feat(telegram): бот выживает при мёртвом прокси и сам сообщает о проблемах
Корень «бот молчит»: get_proxy_args считал достаточным условием маршрутизации
через 4534 сам факт запущенного sing-box - если mixed-inbound не поднялся,
каждый запрос вечно падал, воркер уходил в бесконечный backoff (468 ретраев
подряд у пользователя), хотя api.telegram.org был доступен напрямую.

- mixed_port_alive(): TCP-проба слушается ли 4534 (netstat) с кэшем 30с;
  маршрут через прокси выдаётся только при живом порте
- tg_request разделён на tg_request_via + fallback-цепочку: прокси не ответил -
  повтор без прокси; отключается UCI telegram.bot_direct_fallback='0'
- алерт админу однократно за эпизод после 5 неудачных опросов подряд с
  указанием причины; сбрасывается при восстановлении опроса
- heartbeat /var/run/tachyon_telegram.heartbeat после каждого успешного
  цикла - основа для вотчдог-проверки живости (следующий коммит)
- ротация tmpfs-лога воркера: потолок 512KB, хвост 100KB, проверка раз в час
- /doctor в боте рендерит человекочитаемую сводку (проблемы/исправлено/
  запланировано) вместо сырого JSON
- config_version убран из человекочитаемого вывода конфига (внутренний
  маркер миграций)
2026-08-22 10:06:56 +03:00
Dushnilin 300ad50417 fix(security): защита CGI агента, права конфига и захват лока
- агентский CGI: /diagnose мог удалять nft-таблицы, переписывать resolv.conf
  и перезапускать sing-box с любого устройства LAN без токена; bearer-токен
  теперь передаётся через окружение вместо argv (виден в ps), тело запроса
  ограничено 64KB до чтения, wildcard Access-Control-Allow-Origin убран -
  произвольные сайты больше не могут читать состояние роутера кросс-доменно
  (включая DNS rebinding)
- agent_api: сравнение токена за константное время
- uci/migration: /etc/config/tachyon хранит Telegram bot token и ссылки на
  подписки; UCI не сохраняет 0600 при коммитах, поэтому режим ужесточается
  после каждого коммита этого конфига и после миграций
- build.yml: убран NODE_TLS_REJECT_UNAUTHORIZED=0 из шагов публикации релиза -
  проверка сертификатов не должна отключаться на раннере, заливающем релизы
- initd/state: устранено окно TOCTOU при захвате устаревшего reload-лока:
  два ожидающих могли оба выполнить rm+rmdir+mkdir и каждый считал лок своим;
  захват теперь атомарным переименованием, которое выигрывает ровно один
  претендент
2026-08-21 19:19:40 +03:00
Dushnilin 8996790f25 fix(core): хотфиксы issues #23, #32, #39, #41
- service_check: lan_interface() запрашивала несуществующий конфиг
  forkop/podkop, из-за чего все проверки сервисов смотрели в br-lan вместо
  настроенных LAN-интерфейсов - секции AWG/WireGuard всегда получали вердикт
  "не отвечает" при рабочем kernel-конфиге (#41, #32, #39)
- rag: у push() были перепутаны аргументы - коллекция эмбеддингов оставалась
  пустой для всех провайдеров OpenAI-формата; кэш эмбеддингов теперь
  инвалидируется по отпечатку индекса (mtime+size), null model_override
  обрабатывается корректно
- warp_generator: curl к Clash API без таймаута и матрица ретраев без общего
  дедлайна могли блокировать выполнение минутами и ловить XHR timeout LuCI
  (#39); добавлены -m 5 на локальные вызовы и бюджеты 40с/90с на весь цикл
- build.sh: релизные пакеты теперь содержат тот же состав файлов, что и
  сборка через OpenWrt Makefile (hotplug WAN-монитор, агентский CGI в
  /usr/lib/cgi-bin, defaults/config, профили servicecheck); конфиги с
  секретами ставятся с правами 0600; тест паритета инвентаря
- updates UI: после самообновления tachyon страница перезагружается только
  когда перезапущенный бэкенд снова отвечает на get_ui_state, вместо
  фиксированной задержки 8 секунд (#23)
2026-08-21 19:19:17 +03:00