Backend:
- constants.uc: add TACHYON_COMMIT_SHA constant (placeholder __COMPILED_COMMIT_SHA__)
- build.sh: capture git rev-parse HEAD and sed-replace commit SHA placeholder
- Makefile: same commit SHA sed replacement for OpenWrt builds
- action.uc: modify check_tachyon() to compare installed commit SHA with
target_commitish from GitHub release, new status 'outdated_same_release'
- action.uc: reuse release_json for both version and commit SHA extraction
- updater.uc: add release_commit_sha helper to extract target_commitish
- updates.uc: extend cacheable status to include outdated_same_release
Frontend:
- main.js: handle outdated_same_release status in renderComponentCard
- main.js: include outdated_same_release in shouldShowInstallAfterCheck
- main.js: include outdated_same_release in applyCachedCheckResults
i18n:
- Add 'Update is available for current release' and 'Update is available
for current release:' to .pot and .ru.po files
78 tests pass.
generator.uc: try/catch around hosts cache file read with guaranteed close
hosts.uc: try/catch around parse_hosts_file with guaranteed close
migration.uc: try/catch around remove_cache_path, checked unlink in remove_legacy
runtime.uc: cleanup stale temp config files on init_config startup
lifecycle.uc: log warning on nft table delete failure in stop_main
migration.uc:
- try/catch around migration.run() with error logging
- try/catch around apply_operations() with error logging
- Error checking for UCI cursor operations in apply_operations
- Checked fs.writefile return values in ensure_runtime_cache_format
updates.uc:
- Write pending marker on lock acquisition failure for next retry
- watchdog: fix 'left-hand side is not a function' tick crashes
- safe_call: replace String(e)/instanceof Error with as_string(e)
- ai_heal_empty_sections: list_option/read_json_file -> common.*
- read_dns_recovery_state/ai_heal_dns_loop: read_json_file -> common.*
- common.is_connections_action -> connections.is_connections_action
(add missing 'config.connections' module import)
- wrap check_singbox_process/check_auto_resume_pause/ai_full_health_audit
in safe_call to prevent uncaught exceptions in tick loop
- state: SIGHUP race condition: fall back to sing-box start instead of
exit(1) when process dies between config generation and signal delivery
- telegram: fix String(e)/instanceof Error crash in update catch block
On some OpenWrt builds (e.g., FriendlyWRT with ip-full conflict), apk
reports '1 error' even though the package installed successfully
(pre/post scripts ran). The install script now checks if the package
is actually installed after apk returns non-zero, and continues if so.
Ключевые изменения:
1. core/helpers.uc: file_is_usable(path, min_bytes) + file_size_value(path)
для единообразной проверки файлов (минимальный размер порог).
2. singbox/dns.uc: WAN fallback DNS серверы (fallback_wan_main) теперь
используют прямой UDP без detour — исправлена петля когда
DNS шёл через мёртвую прокси-секцию.
Health probes для ВСЕХ DNS серверов (включая DoH) идут direct —
failover может определить доступность DNS серверов.
3. watchdog.uc: ai_heal_empty_sections() — автообнаружение пустых
proxy-секций с подписками → запуск subscription_update_async.
ai_heal_dns_loop() — при обнаружении DNS-петли (dead proxy +
dead DNS) → временно отключает DNS detour → загружает подписку →
восстанавливает настройки.
4. Единая file_is_usable: nft/apply.uc, generator_routes.uc,
components/{updates,action}.uc, config/validator.uc,
subscription/cache.uc — все используют helpers.file_is_usable.
5. Тест tests/file_usable.sh для проверки helpers CLI.
6. Исправлен components_updater_job.sh mock lib — добавлен core/helpers.uc
- generator_routes.uc: ensure_custom_ruleset() returns null and local
file references with size <100 bytes are skipped (previously would
silently reference a nonexistent/broken path, leaving sing-box with
no domain matchers)
- generator_routes.uc: ruleset/rule_sets_with_subnets loops guard
against null ensured result before accessing .tag/.kind
- nft/apply.uc: community-subnets .lst files with size <50 bytes are
skipped before handing data to nftables
Tiny or zero-byte .srs files can appear after interrupted downloads or
failed remote fetches. If such a file is picked as a local ruleset, the
section silently loses its domain matchers. Raise the size threshold to
100 bytes so damaged snapshots fall back to the remote rule_set URL.
- updates.uc: cache downloaded built-in subnet lists (telegram, meta, twitter, etc.) to community-subnets-<service>.lst.
- generator_routes.uc: dynamically load community list IP CIDRs from cached subnet files for all community lists into sing-box route rules. Zero hardcoded IP arrays.
- nft/apply.uc: add 'awg' and 'warp' to action_captures_traffic so nftables
creates priority sets for AmneziaWG / Cloudflare WARP sections.
- nft/apply.uc: insert flowtable bypass in fw4 forward for marked TPROXY packets
so OpenWrt flow offloading doesn't hijack proxied connections.
- singbox/generator_routes.uc: include official Telegram IP CIDRs in route rules
for telegram community list so direct IP connections match sing-box rules.
- nft/apply.uc: nft_add_community_subnet_file_for_section now populates
common_set (tachyon_subnets / tachyon_rule_<Section>_subnets) when section
is not a priority rule section. Previously, community subnets for normal
proxy/VPN sections were skipped completely.
- updates.uc: fix typo SUBNETS_TELERAM -> SUBNETS_TELEGRAM in BUILTIN_SUBNET_URLS
- bump version 1.2.31 -> 1.2.32