AudionAudion

Audion Sync Tools — журнал изменений

CHANGELOG_RU.md

Audion Sync Tools — журнал изменений

English · Руководство

Содержание

2.0.1 — 15 октября 2026

Пакеты шифрования PowerShell. Microsoft.PowerShell.SDK 7.6.6 приносит System.Security.Cryptography.Pkcs и .Xml 10.0.10 с известными уязвимостями; PowerShell программы (App\AudionPs.exe) теперь собирается с ними версии 10.0.13. Сам PowerShell остаётся 7.6.6, окно не меняется.

2.0.0 — 9 октября 2026

Новое окно. Окно переписано с WPF в PowerShell на C# и Avalonia; прежнее удалено целиком. Движок тот же: сценарии Engine\Scripts, Tunnel\ и врапперы Runs\, и кнопка по-прежнему зовёт то же, что зовётся из консоли. Start.exe запускает App\AudionSyncTools.exe; ключ --no-admin пропускает вопрос о правах администратора, -Root "папка данных" называет папку этого запуска, не меняя указатель программы.

Свой PowerShell 7. App\AudionPs.exe — PowerShell 7 внутри программы: на нём идут сценарии окна, все врапперы и шаги сборщика. На PowerShell системы остались рабочий процесс REVERSE SSH TUN и повторный запуск с правами администратора в четырёх сценариях установки.

Новый знак. «S» из двух встречных стрелок нарисована заново, вектором: морской синий и медь, прозрачный фон. Исходники - Assets\SyncTools.svg и Assets\SyncTools.png (1024), значок Assets\SyncTools.ico собран из картинки сценарием Engine\Launcher\Build-IconFromImage.ps1, шесть размеров от 16 до 256. Его несут Start.exe, App\AudionSyncTools.exe и App\AudionPs.exe.

Описание программы - парой в Docs. Docs\README_RU.md и Docs\README_EN.md, как у остальных программ: русский текст перенесён из корня как был, английский написан рядом. README.md в корне стал указателем на обе половины каждой пары.

Порядок восстановления - тоже парой. Docs\RESTORE.md стал Docs\RESTORE_RU.md, рядом лежит Docs\RESTORE_EN.md. В записях ниже прежнее имя оставлено как было.

Мастера стали сценариями. То, что раньше делал код окна, вынесено в Engine\Scripts и работает из консоли: Set-Targets.ps1 (АДРЕСА), New-ClientKey.ps1 (SSH-KEYGEN), Set-R2Credentials.ps1 (R2 CREDS), Set-RouterSecret.ps1 (ROUTER PASS), Build-Transport.ps1 (RCLONE.CONF), Manage-ClientKeys.ps1 (СПИСОК, SSH-COPY-ID, ОТОЗВАТЬ), Get-Clouds.ps1 (список облаков), Switch-Tunnel.ps1 и Get-TunnelState.ps1 (туннель до роутера BASE). Окно спрашивает формой, таблицей или выбором; в отдельной консоли открывается только то, что само ведёт разговор. Подсказки про SECOND VPS называют раздел SETUP: кнопка УСТАНОВИТЬ стоит там, а не в TUNNEL.

Задание кончается вместе со своим процессом. Команда, которая запустила помощника и ушла, держала задание «выполняется», пока жив помощник: окно ждало конца её вывода без предела, а СТОП не находил, что останавливать. Теперь последние строки ждутся три секунды после конца процесса, задание получает свой вердикт, и очередь идёт дальше; помощник не трогается. Шаг сборщика build_app проверяет, что новая App\ встала на место, и если нет — возвращает прежнюю: раньше занятый файл оставлял программу без App\ под словом «собрано».

Что прежнее окно делало само, без кнопки. Сверка нового окна с 1.19.2 по поведению нашла шесть таких мест; все на месте. Закрытие окна во время передачи спрашивает и на ПРЕРВАТЬ снимает задание с его процессами и очередь: rclone окно не переживает. Папка данных меняется одним шагом: облачная сессия прежней папки сохраняется в неё и уходит из окна раньше, чем меняется папка, панели открываются заново; пока идёт операция, папка не меняется. Маршруты машин читаются из открытого rclone.conf и тогда, когда подключены облака и рабочий конфиг зашифрован. COPY, MIRROR и BISYNC между двумя облаками одного вида идут на стороне облака — --server-side-across-configs. Папка данных без адресов получает их каркас из образца программы при старте, при выборе и перед мастером АДРЕСА: это делает Initialize-DataFolder.ps1, он же переносит запись SECOND VPS из ~\.ssh\config и рабочие файлы, оставшиеся в папке программы от версий до 1.15.0.

Действие идёт с тем, с чем начато. Пока действие считает или спрашивает — COPY считает, сколько поедет, F8 ждёт ответа, мастер показывает форму, — папка данных не меняется: окно отвечает «идёт операция: папку данных меняют после неё», как и во время передачи. COPY, сосчитанный в одной папке данных и подтверждённый после смены на другую, ушёл бы с путями первой и конфигом второй. Операция уходит по адресу, который назвал её вопрос, даже если панель за это время перешла в другое место — из окна поиска или после подключения OPENVPN: F5, F6, F2, F7, F8 и F3 берут место панели до вопроса. Проба сети, состояние и сводка, спрошенные у прежней папки данных, в новую не ложатся.

Проверка свежим взглядом, 8 октября. Программу прочли заново не по тому, с чем окно зовёт rclone, а по тому, что rclone после этого делает с файлами; спорное воспроизведено его же сборкой на временных папках, на своём sftp и на машинах — BASE и WORK. Номер тот же: из папки проекта 2.0.0 ещё не уходила. Десять абзацев ниже — что найдено и исправлено; за ними — что нашёл аудит этих правок.

F2 не переименовывает на занятое имя. rclone делал это молча: файл, лежавший под новым именем, удалялся, папки сливались. Окно сперва читает папку, куда идёт имя, и на занятое отказывает; не прочиталась папка — отказывает тоже. Каждое переименование идёт с --ignore-existing: файл, чьё имя заняли уже после вопроса, остаётся на месте рядом с занявшим, и задание кончается ошибкой, а не словом «готово». С папкой иначе — см. аудит ниже.

Смена одного регистра в имени больше не стоит файла. На машине с Windows по ssh rclone находил старое имя под новым, принимал источник за лишнюю копию и удалял его: name.txt → NAME.txt — файла нет, dir → DIR — папка пуста, а задание кончалось «готово». На диске этой машины папку с таким именем он не переименовывал вовсе. Теперь и там и там регистр меняется в два шага через временное имя; в R2 bucket и в облаках — одним, как раньше. СТОП между шагами второй шаг не начинает, и журнал называет, что осталось несделанным.

F8 на диске этой машины кладёт в Корзину Windows. Локальный диск чистился так же, как сервер, — насовсем, а вопрос говорил про «удалённые источники». Чего Корзина не примет, остаётся на месте, и задание об этом говорит. SHIFT+DEL и SHIFT+F8 удаляют мимо Корзины; вопрос и его бейдж это называют. На машине по ssh, на сервере и в R2 bucket Корзины нет: там всё как было, и вопрос прежний.

Папка внутри папки отклоняется до вопроса. F5, F6, COPY, MIRROR и BISYNC отказывают, когда приёмник лежит внутри источника, а зеркало — и когда источник лежит внутри приёмника. Сам rclone отклоняет только простой случай. Через junction и там, где одно место названо дважды — диск этой машины и она же по ssh, как открываются панели TUNNEL и REMOTE на BASE, — зеркало стирало соседние папки и сам источник. Копию папки в её же подпапку он не отклоняет вовсе и не останавливается: восемь тысяч уровней вложенности за пять минут. F5 и F6 в ту же папку, где стоят, тоже отклоняются.

Пара BISYNC остаётся той же парой при смене маршрута. rclone хранит состояние пары под именами её сторон, а имя машины менялось вместе с маршрутом. Пара, заведённая дома, издалека оказывалась новой: окно спрашивало про неё заново и шло с --resync — правка приёмника затиралась, удалённое в источнике возвращалось. Теперь у BISYNC машина зовётся одним именем при любом маршруте, а сам маршрут уходит rclone переменными процесса.

ЧЕРЕЗ MAIN VPS спрашивает и считает. Перегон между облаками стартовал с одного нажатия, а остановить его из окна нельзя: работа идёт на MAIN VPS сама. Теперь окно считает, сколько поедет, и спрашивает; вопрос говорит, что СТОП до неё не дотянется. Перегон на MAIN VPS идёт один: журнал и файл с номером процесса там одни на всех, и второй, начатый до конца первого, затирал оба. -Watch говорит «ИДЁТ», только когда записанный номер жив и это rclone.

Esc в поле ввода ничего не останавливает. Esc в строке быстрого фильтра или в поле масок снимал идущую передачу вместе с очередью. В поле ввода Esc теперь принадлежит полю; из панелей он по-прежнему СТОП.

Сценарий кончается своим кодом. Под окном и в шаге RESTORE кодом сценария становился код последней программы, которую он запускал сам. Сценарий, разобравшийся с отказом ssh или robocopy и кончившийся без своего exit, в окне был «код 3», а RESTORE на таком шаге проваливался целиком. Теперь код тот же, что у враппера: число собственного exit, а без него — ноль. Заодно Update-Tools.ps1 судит об установщике архиватора и редакторов по успеху вызова, а не по коду, оставшемуся от чего угодно до него.

Скачанное проверяется до запуска. Проверкой скачанного инструмента был его запуск — при том, что программа работает с правами администратора. Теперь до первого запуска сверяется, чьё оно: у клиента туннеля — подпись Cloudflare, у Windows Terminal и Microsoft Edit — подпись Microsoft; у rclone, micro и PeaZip, которых издатели не подписывают, — сумма SHA-256 из файла, который издатель кладёт рядом с выпуском. Подпись или сумма не сошлись — не ставится, прежняя копия остаётся. Файл сумм не скачался или нужной строки в нём нет — об этом сказано в журнале, и установка идёт дальше: сумма бережёт от архива, повреждённого в пути. Версии при этом по-прежнему свежие: что показывает SETTINGS и что ставит ОБНОВИТЬ, не изменилось.

КОПИРОВАТЬ у журнала берёт то, что в панели. Рядом с панелью велась вторая копия журнала, которую никто не обрезал: она росла всё время, пока окно открыто. В буфер идут строки панели — последние три тысячи; всё с начала дня лежит в файле logs.

Аудит этих правок, 8 октября. Правки проверил другой чат — по итоговому коду и опытами с настоящим rclone. Восемь находок и одно наблюдение за пределами правок; пять абзацев ниже — что исправлено, номер тот же.

Эта же машина дальним маршрутом — то же одно место. Свою машину под другим именем окно узнавало по адресу и только на прямом маршруте. Но кнопка ряда ROUTE ставит дальний маршрут и той машине, на которой запущена программа, а ноутбук вне дома приходит к себе через свой REVERSE SSH TUN — и зеркало папки в её родителя снова стирало соседей. Теперь машину на том конце спрашивают, не эта ли она: окно читает через неё собственный файл-метку, и только когда пути на обоих концах совпадают диск в диск. Машина не ответила — операция не начинается.

F2 перепроверяет имя перед запуском, а папку — после. Имя, свободное при нажатии F2, могли занять, пока задание ждало в очереди за долгой передачей. Папка читается ещё раз перед самым запуском, и на занятое имя задание не начинается. У папки, в отличие от файла, предохранителя на оставшийся миг нет: rclone переносит в занявшую имя папку то, чего в ней не было, одноимённое оставляет и кончает «готово». После переименования папки окно смотрит, не осталась ли она на месте, и говорит об этом ошибкой. Папку F2 ждёт столько же, сколько панель, — минуту, а не полминуты. Когда второй шаг смены регистра не выполнен или остановлен, журнал называет временное имя, под которым остался объект.

Панель не держит строки прежней папки. Диск этой машины до прихода списка новой папки показывал строки прежней, и F2, F8 и F5 в этот миг брали имя из старого списка и путь новой папки. Строки убираются сразу, как у машины по ssh. Вложенность папок окно спрашивает у диска не на своём потоке: сетевой диск, переставший отвечать, его больше не подвешивает.

Предупреждение rclone скрыто в одном задании, а не во всём журнале. Строка про ssh поверх адреса ожидаема только у BISYNC издалека, где окно само так делает; в любом другом задании она говорит об ошибке в рабочем rclone.conf и снова видна.

Сценарий смотрит на отказ программы, от которой зависит его доклад. Раз код сценария теперь его собственный, отказ icacls или git в окне больше не всплывает сам. Сценарий проверяет его там, где иначе доложил бы об успехе: права на ключ в EXPORT KEYS (отказ — ошибка сценария), в SSH-KEYGEN и при установке OpenSSH, правка core.sshCommand в IMPORT KEYS, удаление записи облака. Сумма PeaZip ищется по имени, которое файлу дал издатель, и тогда, когда архив пришёл запасной дорогой.

Первый запуск. Выпуск приходит без инструментов. Окно первого запуска спрашивает папку данных и скачивает недостающее, около 100 МБ: rclone, cloudflared, Windows Terminal, PeaZip, редакторы Microsoft Edit и micro. Оно возвращается при каждом старте, пока инструмента не хватает.

Маски. Кнопка со звёздочкой между панелями отмечает строки активной панели: свои маски через запятую, сохранённые наборы, время изменения и группы расширений с включением и исключением.

Поиск. Ctrl+F, Alt+F7 или лупа между панелями: от папки активной панели вглубь, на диске, на машине по ssh, в R2 bucket и в облаке. Ищет по части имени, расширению, маске, регулярному выражению, группам и времени. Найденное открывается в панели плоским списком либо переходом к файлу.

Клавиши. Добавлены Tab, Alt+← и Alt+→ (история панели), Alt+F1 и Alt+F2 (список источников), F (быстрый фильтр), Ctrl+A и * (отметки), Shift+Пробел (точный размер), Ctrl+R, Ctrl+U, Ctrl+Enter (терминал там, где стоит панель), Ctrl+Shift+N и Ctrl+Shift+P (имена и адреса в буфер), SHIFT+DEL и SHIFT+F8 (удалить мимо Корзины). Esc останавливает идущую операцию — из панелей; в поле ввода он принадлежит полю.

F3, F4 и архивы. F3 кладёт в буфер публичные ссылки на отмеченное в R2 bucket со своим сайтом. F4 открывает файл в редакторе, Shift+F4 создаёт новый; редактор выбирается в SETTINGS. Alt+F5 и Alt+F9 упаковывают и распаковывают архивы через PeaZip: ZIP, 7Z, SFX, TAR, TAR.GZ, TAR.ZSTD, TAR.LZ4, с паролем и проверкой архива. Редактор и архивы работают на дисках этой машины.

Индикаторы без красного. У кнопок обзаведения три значения: серый — этого нет, оранжевый — есть, но делом не подтверждено, зелёный — подтверждено чтением панели. Состояние отдают Get-SetupState.ps1 и Get-BeaconState.ps1 одной строкой JSON; читается оно при старте, после очереди заданий, после мастера и по кнопке СОСТОЯНИЕ. В журнале красным остаётся только то, что сломалось. Какой ключ здешний, индикаторы узнают по папке данных и профилю, а не по имени, которое помнит окно: свежая копия программы показывает ключ на месте сразу, как только указана папка данных.

Ошибка в обработчике окно не закрывает. Она целиком ложится в logs\gui-crash-<время>.log, в журнале остаётся одна строка с именем файла, окно работает дальше. Двадцать ошибок за минуту — программа закрывается, последний файл говорит почему. Ошибки фоновых задач, которых никто не ждал, пишутся в logs\gui-background-<дата>.log.

Сводка состояния — отдельным сценарием. СОСТОЯНИЕ и старт окна пишут в журнал сводку и отчёт о туннелях, как прежде; факты теперь отдаёт Get-StateSummary.ps1. Пропавший клиент туннеля виден и у опущенного туннеля: раньше проверка шла только у поднятого.

Наборы масок и пары BISYNC — в папке данных. Наборы лежат в config\mask-sets.json, пары — в config\bisync\pairs.json, а состояние rclone для каждой пары — рядом, в config\bisync\state. Раньше список пар жил в настройках окна, а состояние — в ._runtime программы: чистка уносила состояние и оставляла список, rclone отказывал с «must run --resync», и спросить заново окно не умело. Теперь пара считается знакомой, пока её состояние на месте. Пары из прежних настроек не переносятся: первый запуск каждой спросит заново, и журнал об этом говорит.

SETTINGS. Новый раздел на месте панелей: папка данных, инструменты и их версии (ПРОВЕРИТЬ ВЕРСИИ только спрашивает, ОБНОВИТЬ ведёт все шесть), редактор F4, размер и выбор шрифтов, прозрачность Windows 11, размеры в байтах, нижний ряд без подписей. Тем четыре: Audion Vault Dark, Audion Dark, Audion Code Dark, Audion Light.

Полоса между панелями. Туда переехали кнопка питания туннеля до роутера BASE, маршруты по машинам и закрепление раздела; рядом — маски, поиск, смена панелей местами, имена и полные адреса отмеченного в буфер.

Цвета строк. Читаются из config\colors\themes.json и config\mask-groups.json: группы масок, поиска и цветов — один список. Схемы Total Commander config\colors\*.ini и сценарий Update-AudionColors.ps1 из программы убраны.

Golden copy облаков берётся из той папки данных, с которой работает окно. После правки облака Manage-Clouds.ps1 выгружал на MAIN VPS конфиг из папки по указателю, даже когда ему назвали другую: -Root до выгрузки не доходил.

Проверки. Их 29, все идут под встроенным PowerShell через Tests\Run-Tests.ps1; имя, под которое не подошла ни одна проверка, теперь ошибка, а итог называет число прошедших. Новые: Test-NewWindow.ps1, Test-ClientKeys.ps1, Test-StateSummary.ps1, Test-DataFolder.ps1, Test-ScriptExit.ps1, Test-ToolTrust.ps1. Test-Cli.ps1 и Test-Prompts.ps1 читают новое окно. Test-Window.ps1, Test-Handlers.ps1 и Test-TransportRoutes.ps1 ушли вместе с прежним окном: логика, которую они проверяли, теперь на C#. Её поведение проверяет стенд Tests\Stand\Run-Stand.ps1: собранное окно без экрана и без мыши, с заглушками вместо PowerShell и rclone, восемнадцать проб — вопрос остаётся без ответа, папка данных меняется или панель уходит в другое место, и только потом вопрос получает ответ. Стенду нужен dotnet SDK, идёт он около двух минут и в общий прогон не входит.

Движок. Функции, на которых стоят сценарии, живут в Engine\BackupEngine.psm1 — без окна. Пять функций без вызовов удалены. Номер версии у окна один, config\version.json: проект сборки читает его оттуда, своего в нём нет.

Документы. README.md и оба руководства переписаны под новое окно.

Вживую не проверены: разговор с настоящим роутером, установка WireGuard, подъём и питание своего туннеля, вход в облако через браузер, SSH-COPY-ID и ОТОЗВАТЬ на настоящих машинах.

Окантовки контролов тише, цветные кнопки нижнего ряда без заливки, 10 октября. Рамки кнопок, переключателей, чекбоксов и полей — в покое, под указателем и у включённых — сохраняют 40% силы: много рамок рядом рябили. Рамки панелей, карточек, плашек и разделители прежние. У F5, F8, F11 и F12 нижнего ряда снята цветная заливка: кнопка стоит на фоне обычной кнопки, о ней говорит цвет окантовки. Номер тот же.

1.19.2 — 26 сентября 2026

Разгадана красная колонка SFTP в RESTORE MIRROR. Первый же MIRROR на BASE с 1.19.1 назвал причину: Invalid value when setting --s3-no-check-bucket from environment variable RCLONE_S3_NO_CHECK_BUCKET="". После каждого вызова rclone программа возвращала переменные окружения как были, и отсутствовавшие «возвращала» передачей $null в SetEnvironmentVariable. PowerShell превращает такой $null в пустую строку, а PowerShell 7, на котором живёт окно, пустую строку не удаляет, а хранит пустой переменной. Поэтому после первого rclone в окне всякий процесс, запущенный из него, — RESTORE, внешние окна, — получал RCLONE_S3_NO_CHECK_BUCKET="" и AWS_SHARED_CREDENTIALS_FILE="", и его rclone падал на старте. Отдельный запуск тех же проверок этих переменных не получал и проходил. Теперь удаление идёт через [NullString]::Value во всех 17 местах: возврат после rclone, пароль облаков RCLONE_CONFIG_PASS в окне и в Manage-Clouds.ps1, переменные облачных записей. Тем же объясняется давний случай, когда панель падала «на пустом типе» облака. Новый тест Tests\Test-EnvRestore.ps1 проверяет и код, и живой вызов под PowerShell 7.

1.19.1 — 26 сентября 2026

Проверка дорог называет причину. Таблица SSH/SFTP в конце RESTORE больше не пишет голое «FAILED / TIMEOUT»: под ней строки «Why:» — для каждого отказа последняя строка ошибки ssh или rclone, код выхода или «нет ответа за N с». Быстро упавшая проверка повторяется одна, прежде чем дорогу назвать мёртвой; прошла со второго раза — дорога OK, а первая причина остаётся в строке. Поводом стала колонка SFTP в MIRROR на LAPTOP 26.09.2026: все проверки падали разом, дороги при этом были живы, а причину таблица выбрасывала. Invoke-AbkHostScanBatch получил режим -Detailed (вывод, ошибки, код, таймаут); SSH-KEYSCAN зовёт его по-прежнему.

Окно не висит на cloudflared. Проба сети считает дорогу через cloudflared живой, только если открыт порт 443 ssh.audion.dev и есть вход в Cloudflare Access (cloudflared access token, в фоновом потоке пробы, предел 5 с). Нет входа — дорога молчит, окно берёт следующую, а в журнал уходит одна строка: как войти. Раньше cloudflared открывал браузер и ждал входа без предела времени, ssh ждал его, и окно вставало молча.

Сборка не открывает терминал. Установка Windows Terminal проверяла себя запуском wt.exe без аргументов, а это и есть «открыть окно»: при каждой сборке и каждом обновлении инструментов на экране всплывал пустой PowerShell. Теперь терминал проверяется по файлу и его версии, не запускаясь.

1.19.0 — 26 сентября 2026

RESTORE → «Начисто из DATA (MIRROR)». Прежний RESTORE только доливал: одинаковые ключи оставались, существующий ~/.ssh/config сохранялся, чужие строки administrators_authorized_keys жили дальше. 25.09.2026 BASE после такого RESTORE осталась на старом профиле из 8 хостов вместо 20, и половина дорог rclone не открывалась. MIRROR делает C: ровно таким, каким его описывает DATA: ~/.ssh собирается заново целиком, в файле ключей администраторов остаётся ровно CLIENTS, хост-ключи SSHD берутся из Tunnel\SSHD даже поверх других живых, убираются старый rclone.conf вне DATA, ярлыки REVERSE SSH TUN и задача Audion Backup Sync. Ничего не удаляется молча: всё убранное ложится в DATA\._runtime\mirror-<время> с закрытыми правами, там же журнал restore.log. Если импорт сорвался, прежний ~/.ssh возвращается. Человеческие шаги ждут без таймаутов: отклонённый UAC спрашивается снова, вход в Cloudflare Access проверяется и повторяется, пароль роутера сохраняется только после настоящего входа. Один ли пароль у всех роутеров — выбор владельца: он спрашивается один раз и лежит в DATA (targets.json, _routers.sharedPassword). Без него пароль одного роутера на другом не пробуется; ROUTER PASS в окне следует тому же выбору.

Проверка SFTP в RESTORE не переписывает rclone.conf. Разовый remote :sftp: определял оболочку той стороны и сохранял конфиг; семь проверок параллельно на Windows мешали друг другу, и 26.09.2026 все SFTP-строки таблицы упали при живых дорогах. Теперь тип оболочки задан явно.

SSH-KEYSCAN собирает всё, без чего чистый профиль не входит. MAIN VPS пишется ещё и под audion-vps — этим именем оба его маршрута сверяют ключ (HostKeyAlias). Роутер BASE теперь в плане сканирования: FILES ROUTER без его ключа не открывался. Запасной путь через ssh сверяет ключ под основным именем цели: Windows ssh-keyscan 9.5 не проходит KEX sntrup761 у MAIN VPS. -T сканера короче ожидания пакета: Windows-сканер держал соединение до -T, и LAPTOP с роутером гибли вместе с полученными ключами. DSA больше не принимается — из-за него прямое сканирование ложно кричало «HOST KEY CHANGED».

Адрес роутера — из данных. Check-Router, New-RouterPeer и ROUTER WEB брали зашитый 192.168.1.1, а дом давно в 192.168.10.x. Теперь адрес берётся из записи роутера в targets.json.

ROUTER PASS с двумя роутерами. Список роутеров приходил в выбор вложенным массивом: с одним роутером это не проявлялось, со вторым выбор не показывался, а сохранение падало на -Router. Окно при этом писало «пароль сохранён», хотя файла не было.

1.18.1 — 24 сентября 2026

Сборка через оркестратор находит PowerShell. Оркестратор вырезает шаг из builder_main.cmd и выполняет его без шапки файла, а PowerShell искала только шапка. 24.09.2026 все три шага установки — install_rclone, install_terminal, install_cloudflared — напечатали No PowerShell found, и программа осталась без rclone, терминала и клиента туннеля. Теперь эти шаги и tests ищут PowerShell сами, в том же порядке, что шапка. Из меню сборщик работал и прежде.

1.18.0 — 24 сентября 2026

F11 COPY спрашивает перед работой. Подтверждения здесь не было: COPY ничего не удаляет, и вопрос казался лишним. Но F11 стоит рядом с F12 и нажимается мимо — 24.09.2026 так уехало 16 754 файла, 4,6 ГБ, за 25 секунд, молча. Диалог называет обе стороны словами, состав области (вся папка или только отмеченное) и плашкой — сколько поедет: файлы и объём. Число считает сухой прогон rclone теми же ключами и фильтрами, что и сама передача, поэтому отвечает на заданный вопрос, а не на похожий. Когда приёмник уже свежий, плашка так и говорит: копировать нечего. Если счёт не удался, диалог остаётся с вопросом, но без числа.

1.17.0 — 20 сентября 2026

Переустановка Windows без объезда машин. SETUP → SSHD сохраняет хост-ключи службы в Tunnel\SSHD выбранной DATA вместе с манифестом, а SETUP → RESTORE возвращает их до установки и первого запуска sshd. У машины остаётся прежняя идентичность, и соседям не нужно доверять ей заново. RESTORE также импортирует ключи, чинит пути, возвращает ярлык включённого REVERSE SSH TUN и печатает таблицу SSH/SFTP. Живой ключ, отличный от сохранённого, не перезаписывается; повреждённая копия не применяется. Консольный ssh и ProxyJump получают UserKnownHostsFile с файлом из DATA. Порядок — Docs\RESTORE.md, консольная дверь — Tunnel\RemoteDesktop\restore-machine.cmd.

PRIVATE BACKUP не вытесняет более полный снимок. Перед удалением прежнего снимка сверяется его состав: снимок, в котором есть проект, отсутствующий в новом, остаётся, и программа называет, какой проект его держит. Удаление идёт по объектам, без запроса версионирования корзины. -Keep принимает значения от 1, -ProjectName понимает список через запятую. Зеркало MAIN VPS убирает из Snapshots только свои прежние снимки по имени, а не всё, в чём нет сегодняшней даты.

IMPORT KEYS. Файл, совпадающий с golden copy, пропускается; отказ по одному ключу сообщается строкой failed: и не останавливает остальные.

-NoPause у врапперов. Врапперы в Runs\ и Tunnel\ пропускают свою паузу, когда ключ передан: законченный фоновый запуск больше не ждёт клавиши. Без ключа пауза остаётся — окно, открытое двойным щелчком, не закрывается вместе с текстом ошибки.

Сборочная пара. cleanup_project.cmd возвращает папку программы к состоянию исходников: убирает скачанные Tools\rclone, Tools\terminal, Tunnel\Bin, журналы, ._runtime и состояние машины — config\profile.json и config\gui-settings.json. Start.exe, остальной config и папку данных рядом он не трогает; после чистки окно заново спрашивает DATA FOLDER. builder_main.cmd возвращает инструменты шагами install_rclone, install_terminal, install_cloudflared — тем же сценарием, что и кнопки UPDATE, — и несёт tests, verify, clean_cache. Клиент туннеля ставится без Install-TunnelClient.ps1: сборка только скачивает и ssh-профиль не правит.

Настройки терминала из config\terminal. После установки или обновления терминала недостающие файлы из config\terminal — маркер .portable и settings\settings.json — кладутся в Tools\terminal. Нажитые настройки не затираются; шаг идёт и тогда, когда версия терминала уже свежая.

1.16.0 — 20 сентября 2026

Сети BASE после переезда на 192.168.10.0/24. Прежняя 192.168.1.0/24 убрана из доверенных сетей правила Audion Remote Files (SSH 22) - и в SSHD, и в запасной установке OpenSSH: оба сценария ставят одно правило и теперь одним списком. Умолчание сетей мастера WG BASE-ROUTER при пустом routes.txt - 192.168.10.0/24, в окне и во враппере setup-base-vpn.cmd. На машинах правило обновляется следующим запуском setup-ssh-server.cmd.

PRIVATE BACKUP кладёт снимок в audion-backup/Projects. Путь в R2 по умолчанию сменился с builders на Projects; ключ -Remote по-прежнему задаёт свой.

1.15.3 — 15 сентября 2026

REVERSE SSH TUN после закрытия установочной консоли. GUI восстанавливает настроенный процесс напрямую и повторяет запуск после его неожиданного завершения с паузой 30 секунд. Регистрация ключа не повторяется. STOP и удаление учитываются; старые туннели LAPTOP не запускаются. Закрытие GUI завершает его процесс и дочерние SSH, не оставляя сирот. Ошибки запуска и ход OpenSSH сохраняются в журналах; зелёный индикатор требует подтверждения проброса сервером. Установление SSH ограничено 15 секундами на попытку.

1.15.2 — 15 сентября 2026

SSH-KEYSCAN не блокирует окно. Сканирование перенесено в отдельный сценарий, общий для GUI и Runs\ssh-keyscan.cmd. Хосты проверяются параллельно: до пяти секунд на прямой обход и ещё до пяти на доступ через настроенный SSH. STOP завершает рабочий процесс вместе с его потомками. Недоступные хосты сохраняют прежние ключи; изменившиеся принимаются только явно, через Ctrl или -Force.

Права приватных SSH-ключей после переноса. IMPORT KEYS исправляет наследуемые и явные лишние разрешения, в том числе у уже существующих файлов. Неполный Export Keys дополняется серверными парами из Tunnel\SSH\servers; приватные ключи соседних машин из CLIENTS автоматически не добавляются. При установке REVERSE SSH TUN ошибка bad permissions запускает исправление ACL выбранного IdentityFile в данных или профиле и повторный вход. Содержимое ключа сохраняется; режимы проверки и снятия ACL не меняют. Установка клиента получает папку DATA из GUI явно и проверяет права используемых серверных ключей.

1.15.1 — 15 сентября 2026

Первый вход на VPS при установке REVERSE SSH TUN. Пустой known_hosts больше не оставляет установку без способа подтвердить отпечаток: OpenSSH предлагает сверить его в отдельном окне, затем установка повторяет вход в строгом режиме без диалога. Изменённый отпечаток не принимается. ОСМОТР, УДАЛЕНИЕ и запуск с перенаправленным вводом не спрашивают подтверждение. Ошибки всех маршрутов сохраняются в отдельном журнале установки; ошибка MAIN VPS больше не скрывает отказ SECOND VPS. SSH-KEYSCAN включает SECOND VPS с его SSH-портом. Добавлены проверки первого запуска и отказов на синтетических данных для PowerShell 5.1 и 7.

1.11.18 — 13 сентября 2026

Пароль роутера хранится переносимо, по имени роутера. Раньше он шифровался DPAPI — привязкой к учётной записи и машине, которая слетала при каждой переустановке Windows и не переезжала с набором: из всего набора только пароль роутера не переживал восстановление, а на портативном диске был мёртвым грузом. Теперь он ложится base64 в файл по имени роутера (router-base.secret, router-home.secret) — переживает переустановку и переезжает, как ключи и пароль облаков. Имя по роутеру, а не по адресу: у домашнего и деревенского роутеров один адрес 192.168.1.1, и файлы по адресу затирали бы друг друга; теперь разные роутеры — разные файлы, и пароли у них могут различаться. Сам файл бесполезен без доступа к роутеру — замок в правах папки и шифровании носителя. Скрипты роутера (new-router-peer, check-router, check-routes) получили ключ -Router. Прежний router_<адрес>.secret от DPAPI осиротеет — пароль вносят один раз кнопкой ROUTER PASS.

1.11.17 — 12 сентября 2026

Журнал не кричит об ожидаемом. Недоступная машина (панель ходит на BASE из другой сети) больше не роняет в журнал аварию [сбой] ... ErrorActionPreference Stop: Invoke-AbkRcloneCommand глушит исключение и отдаёт код возврата, как и обещает — окно живёт под Stop, а в PowerShell 7.4+ ненулевой выход rclone иначе всплывал в общий перехватчик. Теперь недоступность — одна понятная строка («BASE: не отвечает»), и не чаще раза в 15 минут, а не простыня от rclone. Убрана повторяющаяся заметка «идёт дольше пяти секунд, жду». Для устаревшего транспорта (в rclone.conf чужая буква диска, не находится known_hosts) — понятное «транспорт не собран, нажмите RCLONE.CONF».

1.11.16 — 11 сентября 2026

Проверка строк диалогов снова ловит непереведённое. В прошлой версии самой проверке досталась классическая ошибка PowerShell: $matches[1] -match перезаписывал автоматическую $matches, и остаток строки «метка: значение» терялся - тест переставал замечать непереведённую половину и молча засчитывал её. Группы теперь сохраняются в переменные до следующего поиска. Добавлена самопроверка: на синтетической «метка: остаток» с двумя заведомо непереведёнными половинами проверка обязана вернуть обе. Нашла перепроверка 1.11.15 (P3 в тесте, приложение не затронуто).

1.11.15 — 11 сентября 2026

Диалоги, собранные до перевода, дочитаны по-английски. Заголовок «Удалить …?» подставлял имя в шаблон раньше перевода, и готовая строка без {0} пары не находила; тело предупреждения о прерывании передачи собиралось интерполяцией и не переводилось вовсе. Оба теперь переводятся шаблоном с подстановкой после, а не до. Добавлена пара для кнопки ПРОДОЛЖИТЬ - она тоже оставалась русской. Test-Window теперь проверяет и -CancelText, ловит интерполяцию с кириллицей и русский шаблон -f, не завёрнутый в перевод. Нашла перепроверка ревью (остаток P3). Убран задвоенный заголовок 1.11.13 в журнале.

1.11.14 — 11 сентября 2026

Снятие ключа туннеля больше не может обнулить файл и отчитаться успехом. Сценарий снятия шёл без set -e, и после сбоя любой файловой операции - фильтра, подмены, прав - он всё равно печатал removed: пустой authorized_keys с ключами других машин выглядел как удачное снятие, а держатель наверху стирал состояние. Теперь снятие устроено как регистрация: копия до правки, сверка числа строк до подмены, а любой сбой обрывает сценарий до ответа - файл цел, состояние остаётся для повторной попытки. Сбой чтения и «ключа нет» теперь разные ответы. Нашло ревью 17967bb (P1); сценарий добавлен в Test-Beacon.

Диалоги окна дочитаны по-английски. Заголовки, кнопки и строки тела Show-AbkDialog окно переводит у себя, и два десятка кусков (метки СЕЙЧАС, ФАЙЛ, ПРИЁМНИК, РАВНЯЕМ и другие, кнопки, заголовки) не имели пары - English-окно показывало их по-русски. Остаток строки «метка: значение» теперь тоже переводится, недостающие пары добавлены. Test-Window проверяет строки всех диалогов, а не только вызовы Get-AbkText.

1.11.13 — 11 сентября 2026

Руководства рассказывают про учётную запись туннеля. Про tunnel знали только SKILL.md и журнал изменений, а кнопка с 1.11.12 умеет ответить, что на сервере её нет. Теперь в обоих руководствах сказано, что это за учётная запись, почему ключ туннеля живёт именно в ней и где взять её ограничения.

1.11.12 — 11 сентября 2026

Ключ REVERSE SSH TUN живёт в своей учётной записи. Раньше он прописывался рабочему пользователю на MAIN VPS и SECOND VPS. Ключ туннеля лежит на машине в чужой сети, и украденный доставал до всего, что доступно этому пользователю: файлов, групп, служебных сокетов. Теперь у туннеля своя учётная запись tunnel - без оболочки, с заблокированным паролем и пустым домом, где лежит только файл ключей. Что ей разрешено на стороне сервера, едет образцом Tunnel\RemoteDesktop\config\sshd-tunnel.sample.conf: обратный проброс на петле и ничего больше.

Учётная запись заводится на сервере руками, один раз. Пока её нет, подъём туннеля ничего не портит и говорит словами, чего не хватает.

1.11.11 — 11 сентября 2026

Английское окно: строки кода. 24 строки (25 вызовов), которые окно переводит вызовом Get-AbkText прямо в коде, не имели пары и в EN показывались по-русски: объяснения подключения облака, предупреждения SSH-KEYSCAN о смене ключа хоста, строки о туннеле до роутера BASE, число потоков. Пары заведены, а Tests\Test-Window.ps1 теперь проверяет и такие литералы. Находка N6 ревью 2035941.

Индикаторы обзаведения в руководствах. Таблицы говорили «зелёный, когда файл на месте», а окно красит жёлтым, пока дело не подтверждено: R2 CREDS - пока R2 bucket не прочитался в панели, SSH-KEYGEN и IMPORT KEYS - пока не прочиталась панель машины или VPS, SSH-KEYSCAN и RCLONE.CONF - пока не прочиталась удалённая панель, АДРЕСА - пока машина не ответила на пробу. В таблицах теперь два столбца: когда индикатор горит и после чего он зелёный. Находка N7.

Test-Prompts на чистой копии. Промпты называют Start.exe, а его собирают из исходников и в git не кладут, поэтому на чистой копии тест падал. Теперь для Start.exe достаточно сборщика Engine\Launcher\Build-StartExe.ps1. Находка N8.

1.11.10 — 11 сентября 2026

Пароль роутера - в той папке данных, с которой работают окно и враппер. Check-Router.ps1 и New-RouterPeer.ps1 принимали -Root с 1.11.4, но функции модуля RouterNdm.psm1 ключа не получали: пароль сохранялся и читался в папке из указателя config\profile.json или соседней, даже когда окно выбрало другую. Теперь -Root проходит через Save-RouterSecret, Get-RouterSecret и перенос прежнего файла - из этих сценариев, из Check-Routes.ps1 и из окна (ROUTER PASS, чтение пиров роутера). Находка N3 ревью 2035941.

Индикатор SETUP → TOOLS → ROUTER PASS видит сохранённый пароль. Окно звало внутреннюю функцию модуля, которую тот наружу не отдаёт: вызов падал, пустой catch оставлял индикатор серым. Теперь модуль отдаёт Test-RouterSecretStored. Находка N4.

Тесты. Tests\Test-Cli.ps1: каждый вызов функции, которая ищет папку данных, передаёт -Root - в сценариях, объявивших этот параметр, и в окне для функций пароля роутера; синтетический пароль ложится в папку из -Root и виден индикатору.

1.11.9 — 11 сентября 2026

REVERSE SSH TUN больше не снимает ключ соседа. Регистрация и удаление ключа туннеля на MAIN VPS и SECOND VPS искали метку audion-beacon-<имя> подстрокой: ключ машины lab уносил с собой ключ lab2, а проверка числа строк этого не замечала. Теперь строка узнаётся по комментарию ключа целиком. Находка N1 ревью 2035941 (P1, ошибка старше этого ревью).

Ключ туннеля ограничен своим портом. На VPS ключ писался как restrict,port-forwarding,command="/bin/false", и port-forwarding разрешал -L к любым адресам, видимым с VPS, и -R на любых портах. Теперь в строке стоят permitlisten и permitopen порта этого туннеля. Уже прописанные ключи получат ограничения при следующем подъёме: TUNNEL → LOCAL → REVERSE SSH TUN → ПОДНЯТЬ. Проброс unix-сокетов ключом не закрыть - это AllowStreamLocalForwarding в sshd самого VPS. Находка N5 (P2).

Проверка пароля ключа не виснет. Test-AbkKeyOpens звал ssh-keygen -y с закрытым вводом, а пароль ssh-keygen спрашивает у консоли: на ключе с паролем проверка ждала, пока процесс не снимут, - так висел Test-Beacon. Теперь пустой пароль передаётся явно (-P ""), учитывается код выхода, а на проверку отведено 15 секунд. Находка N2 (P2).

Тесты. Tests\Test-Beacon.ps1: пара с паролем распознаётся быстрее 10 секунд; настоящие сценарии регистрации и снятия ключа гоняются в Git Bash на синтетическом файле с ключами lab и lab2; строка ключа ограничена своим портом.

1.11.8 — 11 сентября 2026

Последние прежние имена. Setup-BaseVpn.ps1 называл мастер туннеля до роутера BASE «ROUTER-BASE WG» в справке, в шапке и в совете «туннель поднимается кнопкой…» - теперь WG BASE-ROUTER и путь TUNNEL → LOCAL → WG BASE-ROUTER. Заголовок журнала у R2 CREDS - «R2 CREDS» вместо «КЛЮЧИ R2». Подтверждение F12 SYNC → и заголовок его прогона звали кнопку прежним «ЗЕРКАЛО» - теперь «SYNC».

1.11.7 — 11 сентября 2026

Второй проход по словам: документы. README, SKILL, USER_GUIDE RU и EN, PROMPT RU и EN, CLAUDE и AGENTS, README доступа к машинам говорят теми же терминами, что окно и сценарии: golden copy, Export Keys, CLIENTS, публичный и приватный ключ, R2 bucket, jump host и ProxyJump, индикатор, rclone.conf, REVERSE SSH TUN.

Документы догнали окно. Таблица обзаведения описывает нынешние кнопки разделов SETUP и SSH KEYS и то, когда горит индикатор каждой; кнопок КЛЮЧИ R2 и СКЛАД, группы ИНСТРУМЕНТЫ и шага «SETUP → ЗАДАНИЯ: дальше зеркало само, каждую ночь» в окне давно нет. Промпты и SKILL называют у каждого шага раздел. Машины описаны в разделе REMOTE, кнопка пробы - PORT 22 TCP PING, мастер туннеля - WG BASE-ROUTER.

Исправленные неточности. Английское руководство утверждало, что окно не просит прав администратора, - оно просит их один раз. SKILL обещал, что пароль облаков приезжает с import-keys.cmd, а руководства - что rclone.conf едет в наборе ключей. SKILL числил 500/udp за маячками на SECOND VPS, убранными 09.09.2026. В PROMPT_EN шаг 5 повторялся обрывком, а абзац о маячке описывал прежний WG-туннель. Руководства говорили, что в clients лежат только публичные ключи, - там лежат пары.

Подсказка SETUP → TOOLS → ОБНОВИТЬ обещала зелёный индикатор, «когда все три на месте», а окно проверяет клиент туннеля и rclone; теперь сказано так.

1.11.6 — 11 сентября 2026

Второй проход по словам: сценарии, их справка, врапперы и тесты. Сообщения сценариев, справка Get-Help, строки rem во врапперах и заголовки тестов говорят теми же терминами, что окно: Export Keys, golden copy, CLIENTS, публичный и приватный ключ, R2 bucket, хост, Endpoint, SSHD. Внутренние комментарии кода этот проход не трогал.

Пароль облаков. Sync-CloudKeys и clouds-pull.cmd советовали на новой машине «сперва import-keys.cmd», но EXPORT KEYS и IMPORT KEYS Tunnel\clouds.key не переносят. Теперь сказано как есть: файл кладут в папку данных руками. Справка Manage-Clouds и шапка Clouds.ps1 больше не утверждают, что rclone.conf едет в наборе ключей.

Manage-Clouds без rclone отправлял к кнопке УСТАНОВИТЬ, которая ставит только cloudflared; теперь - к SETUP → TOOLS → ОБНОВИТЬ.

Старое имя программы. Export-AudionKeys, Import-AudionKeys, Sync-AudionBackup и Backup-AudionArchives печатали в шапке «AUDION BUILD BACKUP»; теперь «AUDION SYNC TOOLS» и имя кнопки.

Журнал окна красит вывод EXPORT KEYS и IMPORT KEYS по новым словам: «not in Export Keys» и «public key only» - предупреждением, метку export : - приглушённо.

1.11.5 — 11 сентября 2026

Второй проход по словам окна. Подсказки, подписи источников, диалоги и сообщения окна говорят теми же DevOps-терминами, что и кнопки: публичный и приватный ключ, CLIENTS, golden copy, Export Keys, R2 bucket, jump host и ProxyJump, индикатор, rclone.conf, публичные ссылки. Источники над панелями SSH KEYS зовутся GOLDEN COPY и EXPORT KEYS.

Английское окно больше не показывает русские подсказки. У 25 подсказок разметки и у кнопки F3 ССЫЛКА не было английской пары: маршруты, SSHD, DNS, облака, мастер туннеля до роутера BASE, RDP, ROUTER WEB, SOCKS, отметка по маске. Пары заведены, как и у подсказок источников LAPTOP и SECOND VPS, у заголовка диалога R2 CREDS и у запусков golden copy облаков. Пары, разошедшиеся с текстом (SSHD, BASE, маршруты), догнаны; 40 пар со старыми словами, которые никто уже не звал, убраны из словаря.

Подсказка SSHD говорит, что файл ключей сверяется с CLIENTS - так он работает с 1.10.8. Подсказка С MAIN VPS больше не обещает, что на новой машине хватит import-keys.cmd: пароль облаков Tunnel\clouds.key EXPORT KEYS не собирает, его переносят руками.

Новый тест. Tests\Test-Window.ps1 проверяет, что у каждой русской строки разметки окна и диалога есть пара в словаре.

1.11.4 — 11 сентября 2026

SSHD, NDMS API, ДИАГНОСТИКА и ROUTER WG PEER снова запускаются из окна. Окно передаёт каждому врапперу папку данных ключом -Root, а Setup-SshServer.ps1, Check-Router.ps1, Check-Routes.ps1 и New-RouterPeer.ps1 такого параметра не знали и падали на привязке: «A parameter cannot be found that matches parameter name 'Root'». Теперь принимают; SSHD передаёт папку и в окно с правами администратора, ROUTER WG PEER берёт из неё данные. В Setup-SshServer.ps1 переменная $Root называла папку сценария и затёрла бы параметр - SSHD искал бы CLIENTS не там; она переименована в $Here.

Тест соответствия окна и консоли. Tests\Test-Cli.ps1 собирает ключи у каждого вызова сценария в окне - явные, из переменных, из врапперов и -Root - и сверяет с param() сценария; заодно проверяет, что -Root не затирается в теле.

1.11.3 — 11 сентября 2026

1.11.3 — 11 сентября 2026

Ряды TUNNEL и REMOTE помещаются в строку. Поля кнопок по бокам - 6 px вместо 8, промежуток между группами - 10 px вместо 14. При ширине окна 1520 (экран 1920 при масштабе 125%) оба ряда встают в одну строку; слова и подписи прежние.

1.11.2 — 11 сентября 2026

NET и TOOLS. Подписи групп СЕТЬ и ИНСТРУМЕНТЫ стали NET и TOOLS - в ряду TUNNEL и в SETUP: ряд TUNNEL не помещался.

1.11.1 — 11 сентября 2026

Подписи групп - одним словом. ЭТА МАШИНА стала LOCAL: в рядах TUNNEL и SSH KEYS, над файловыми панелями вместо «этот ПК» и в диалогах. ЧЕМ ОТКРЫВАТЬ стало ОТКРЫТИЕ, ОТКРЫТЬ ПАПКУ - ПАПКА. В окне шириной 1920 длинные подписи роняли кнопки на вторую строку.

Ряд REMOTE переносит группы целиком, как TUNNEL и SSH KEYS: SOCKS больше не уезжает один под роутеры.

1.11.0 — 11 сентября 2026

Кнопки зовутся DevOps-терминами, под кнопками подписи. Имена кнопок - имена программ, команд и файлов, которые за ними стоят: SSH-KEYGEN, SSH-COPY-ID, SSH-KEYSCAN, IMPORT KEYS, EXPORT KEYS, R2 CREDS, CLOUDFLARED, RCLONE.CONF, PORT 22 TCP PING, ROUTER PASS, NDMS API, ROUTER WG PEER, RDP, ROUTER WEB, SOCKS, SYNC ALL, SYNC SELECTED, DRY RUN, RELEASE, PRIVATE BACKUP, F11 COPY →, F12 SYNC →, BISYNC ⇄. Группы - AUTHORIZED_KEYS, EXTERNAL, МАРШРУТ; раздел TRANSPORT стал REMOTE. Под кнопками - подпись в две-три слова на языке окна, с направлением: «ключи → Tunnel\Export», «R2 → шесть папок». Кнопки стали на 6 px выше; у кнопок машин над файловыми панелями подписей нет. Ряд TUNNEL переносит группы целиком, как SSH KEYS: в узком окне СЕТЬ и ИНСТРУМЕНТЫ идут первой строкой, ЭТА МАШИНА второй - прежде середина ряда складывалась в столбик по кнопке в строке.

REVERSE SSH TUN. Бывший SSH BEACON. В подписи кнопки - VPS, через который канал держится сейчас: REVERSE SSH TUN · SECOND VPS или · MAIN VPS. Врапперы названы по VPS: reverse-ssh-second-vps.cmd, reverse-ssh-main-vps.cmd, reverse-ssh-check.cmd, reverse-ssh-remove.cmd.

REMOVE TASK - одна кнопка. Старое задание Планировщика удаляет кнопка в SETUP, и видна она только на машине, где задание осталось. Кнопка ОТМЕНИТЬ в STORAGE убрана.

Тест окна проверяет, что у каждой подписи под кнопкой есть перевод; тест туннеля - что VPS в подписи определяется по имени хоста.

1.10.8 — 11 сентября 2026

SSHD не даёт файлу ключей отстать. Файл C:\ProgramData\ssh\administrators_authorized_keys раньше только дописывался: ключ машины, заменённый в складе, оставался прописанным, а новый не попадал, пока кнопку не нажимали снова. Теперь setup-ssh-server.cmd заменяет строку машины из Tunnel\SSH\clients, если в ней другой ключ, дописывает недостающие половины и схлопывает повторы. Строки машин, которых в складе нет, остаются и называются по подписи: их приносит РАЗДАТЬ КЛЮЧИ с соседних машин. Пустой склад файл не трогает. Файл читается и пишется как UTF-8 без BOM. Проверка — новый Tests\Test-SshServerKeys.ps1.

1.10.7 — 11 сентября 2026

Пароль роутера — в папке данных. Рабочий файл router_*.secret лежит в Tunnel\RemoteDesktop\config папки данных, а не рядом со сценариями в программе: это секрет этой машины, а папка программы уезжает копией на соседние машины. Кнопки NDMS, РОУТЕР, КОНФИГ и check-routes.cmd берут его оттуда. Файл из папки программы переносится при первом обращении, если в данных его ещё нет. В различия машины пароль больше не входит.

1.10.6 — 11 сентября 2026

Где Windows хранит ключи машин. Подсказка кнопки SSHD, руководство, SKILL.md и промпты называют файл: C:\ProgramData\ssh\administrators_authorized_keys. У учётной записи из группы администраторов sshd на Windows читает ключи только оттуда, а .ssh\authorized_keys не смотрит. Программа и раньше писала туда; тексты говорили только «authorized_keys».

1.10.5 — 11 сентября 2026

Резерв забирает машина. Подсказка кнопки СНЯТЬ РАСПИСАНИЕ и SKILL.md говорили, что MAIN VPS сам приходит за данными. Это не так: ночной резерв MAIN VPS кладёт в R2, а каждая машина забирает его сама — кнопкой ОБНОВИТЬ ВСЁ или sync-backup.cmd, как ноутбук. К машинам MAIN VPS не ходит, и BASE здесь не исключение.

1.10.4 — 11 сентября 2026

Папки зеркала без имён провайдеров. Юниты, скрипты и документы MAIN VPS лежат в MAIN VPS Backup, плечи SECOND VPS — в SECOND VPS Tunnel Config: так их называют образец config\mirror.sample.json и руководство. Имя провайдера в названии папки устаревает при первом же переезде. На машине с прежним планом зеркала папки переименовываются вместе с записями folder в config\mirror.json, иначе следующее обновление начнёт их заново рядом со старыми.

1.10.3 — 10 сентября 2026

Только MAIN VPS и SECOND VPS. На всех языках и во всех текстах: в окне, словаре, подсказках, сценариях, образцах и документации. Описательные названия заменены именами. Кнопки и подписи: маршруты SSH MAIN VPS и SSH MAIN VPS CF, источник MAIN VPS, подписи панелей BASE · MAIN VPS и BASE · MAIN VPS CF, в разделе CLOUDS — ЧЕРЕЗ MAIN VPS, НА MAIN VPS и С MAIN VPS.

Маршруты. Выбор пути к машине везде называется маршрутом: подписи, подсказки, журнал окна, check-routes.cmd и документация.

У роутеров — WG-сервер и WG-клиент. Другими словами роутеры в текстах не описываются.

Маячок везде SSH BEACON. Остатки прежнего имени в описании врапперов ssh-beacon-* и в комментариях заменены.

Термины заменены в 59 файлах программы и документации. Старые записи журнала не переписаны: это история.

1.10.2 — 10 сентября 2026

Туннеля «WG SECOND VPS» нет и в текстах. WG-туннель машины до второго сервера убран из программы 09.09.2026, но хвосты от него остались, а обезличивание дало им новое имя — «WG SECOND VPS». Теперь ушли: упоминание этого туннеля в подсказке кнопки установки WireGuard, подсказка панели WORK об адресе в туннеле, подсказки «до LAPTOP — только точка сбора» (к лэптопу издалека не ходят), 30 переводов удалённого мастера и старых подсказок, неиспользуемая проверка живости этого туннеля, отсев адресов 10.13.* в мастере туннеля до роутера и пояснение «туннель и есть дорога» в заготовке транспорта.

Правило брандмауэра без погашенной подсети. setup-ssh-server.cmd больше не пускает к порту 22 подсеть 10.13.0.0/24. Правило пересоздаётся при каждом запуске, поэтому на машине оно обновится при следующей настройке приёма файлов.

check-routes.cmd проверяет единственный туннель машины. Раздел туннелей искал службы home и laptop, и только у WireGuard. Теперь это один туннель — WG BASE-ROUTER — под любым из его имён (router-base-wg, base, home), у WireGuard и у AmneziaWG, а рукопожатие спрашивается у того клиента, который ответит. Подсказка кнопки ДИАГНОСТИКА и SKILL.md говорят о том же.

1.10.1 — 10 сентября 2026

Повторная проверка 1.10.0 подтвердила исправление четырёх регрессий и нашла ещё пять мест; все подтвердились и исправлены.

Ключ SSH BEACON — без пароля и под PowerShell 7. Сценарий маячка создавал ключ своим вызовом ssh-keygen -N '""', а врапперы предпочитают pwsh: там две кавычки становятся паролем. Ключ создавался с кодом ноль, и держатель с BatchMode не мог его открыть. Теперь пары ключей создаёт одна функция — New-AbkKeyPair в новом Engine\KeyPair.ps1, её зовут и окно, и маячок, — и пара проверяется сразу. Если ключ маячка уже закрыт паролем, установка говорит об этом и останавливается: ключи правит владелец.

Снятие и осмотр маячка — на его сервере. Оба шли на плечи по умолчанию, к MAIN VPS. Маячок, заведённый через SECOND VPS, снимался «успешно»: там его ключа не было, сервер отвечал «ok», а ключ оставался на SECOND VPS. Теперь плечи берутся из состояния, состояние помнит, где ключ прописывался, каждое плечо спрашивается отдельно, и «ключа не было» с другого сервера успехом не считается. Не ответило место регистрации — снятие завершается ошибкой и оставляет состояние для повтора.

Порт SECOND VPS доходит до подключения. Мастер АДРЕСА записывал порт, но резолвер его не отдавал: клиент туннеля писал блок без Port, проба окна и check-routes стучались на 22, файлы и рабочий стол через второй сервер шли без -p. Теперь порт у всех, и перенос из ~\.ssh\config забирает его тоже.

Имена второго сервера — в мастере АДРЕСА. Под таблицей три поля: имя хоста в ~\.ssh\config, имя поверх cloudflared и имя ключа. Имена с пробелами и знаками не пишутся.

Include в ssh config. Проверка имени искала строку Host только в основном файле, и сборка кнопкой ТРАНСПОРТ заменяла рабочий раздел второго сервера меткой, если хост описан во включённом файле. Теперь разбор раскрывает Include, проверка спрашивает и сам ssh -G, два имени проверяются отдельно, а метка, которой нечем заполниться, не затирает рабочую строку: строка берётся из прежнего транспорта, и окно говорит, что оставлено.

Точка SSH BEACON — только свой канал. Индикатор засчитывал любой ssh с тем же номером порта. Теперь канал — это ssh, запущенный держателем этой машины, с её ключом и её портом, проживший дольше двадцати секунд; моложе — «поднимается».

Проверки: новый Test-Beacon — пара без пароля и распознавание запароленной, остановка канала, выбор плеч, решение о снятии, свой индикатор; Test-Targets — Include, порт, имена; Test-Transport — рабочие строки переживают пересборку.

1.10.0 — 10 сентября 2026

Второй сервер переносится сам. Машина, настроенная до записи second, держит второй сервер только в ~\.ssh\config — так его прописывал клиент туннеля. 1.9.0 такую машину не узнавал: отдавал образцовые имена, и первая же сборка кнопкой ТРАНСПОРТ уводила панель второго сервера на хост second-vps, которого нет нигде, с отчётом «собран». Теперь окно при запуске находит второй сервер в блоке клиента туннеля — хост, который не главный, и его вариант поверх cloudflared рядом — и переносит запись в targets.json. Машине без второго сервера заводится пустая запись из образца. Мастер ТРАНСПОРТ подставляет имя второго сервера, только если оно описано в ~\.ssh\config, а иначе оставляет метку незаполненной и говорит, что сделать.

Адрес второго сервера — кнопкой АДРЕСА. Строка SECOND VPS стоит в таблице рядом с машинами и пишет в targets.json поле host. После записи окно сверяется с ~\.ssh\config: имени нет — зовёт УСТАНОВИТЬ в разделе TUNNEL, адрес другой — говорит, где его поправить.

Кнопка SSH BEACON. Обратный проброс ssh — основной способ позвать машину снаружи — жил только в консоли. Кнопка в ряду «эта машина» раздела TUNNEL поднимает его через SECOND VPS или только через MAIN VPS, осматривает и снимает; каждое действие — прежний враппер ssh-beacon-*.cmd. Точка горит зелёным, пока ssh держит проброс. В текстах сценария проброс снова зовётся SSH BEACON, как кнопка и врапперы: SSH SERVER осталось именем дороги.

Снятие маячка больше не оставляет ssh. В PowerShell 5.1 единственный держатель канала приходил из функции одиночной записью без Count, и проверка пропускала поиск его ssh: держатель останавливался, ssh продолжал держать порт на сервере, а сценарий отчитывался «канал опущен». Теперь список держателей всегда массив, снятие ждёт ухода и держателей, и их ssh, а отказ остановить ssh делает снятие ошибкой. Установка не поднимает второго держателя рядом с не остановившимся прежним.

Проверки говорят правду. Test-Cli сравнивал полный путь враппера с маской *\Tools\*, а проект лежит в E:\TOOLS: отсеивались все врапперы, и строка «у каждого враппера есть кнопка» горела зелёным, не проверив ни одного. Путь теперь относительный, число проверенных печатается, а сверка знает, что окно зовёт сценарии и напрямую. Test-Targets брал рабочий targets.json, которого в исходниках нет, и на чистой копии падал первой строкой; теперь он строится из образца и проверяет перенос второго сервера на синтетическом ssh config.

Документы. README описывает профиль машины как он есть — это сама папка данных — и больше не зовёт к шагу SCHEDULE: заданий программа не заводит. SKILL.md и руководства больше не описывают WG-маячок и его ключ, а подсказка кнопки ОТМЕНИТЬ не ссылается на исчезнувшую кнопку.

1.9.0 — 10 сентября 2026

Второй сервер — из targets.json. Адрес точки сбора, имена её хостов в ~\.ssh\config, ключ и учётная запись больше не зашиты в коде. Окно, клиент туннеля, рабочий стол, файлы, проверка дорог, маяк и импорт ключей берут их из записи second в targets.json — через общий Engine\Targets.ps1. В образце стоят нейтральные second-vps, second-vps-cf и second_vps_ed25519, адреса нет: без него точка не пробуется, а клиент туннеля оставляет прежнюю запись второго сервера в ~\.ssh\config как была и говорит об этом.

Разделы транспорта second и second-cf. В заготовке они сменили прежние имена, а имена хостов подставляет мастер ТРАНСПОРТ. На машине, где транспорт собран прежней версией, панель второго сервера оживёт после повторной сборки кнопкой ТРАНСПОРТ.

Серверы в текстах — MAIN VPS и SECOND VPS. Подписи, подсказки и документы больше не называют провайдеров, город и страну второго сервера. Из подсказки клиента туннеля ушёл идентификатор туннеля Cloudflare.

План зеркала у каждого свой. config\mirror.json вышел из истории, в сборку едет config\mirror.sample.json: зеркало берёт образец, пока своего списка нет. Сам план стал различием машины — он складывается в папку данных и возвращается оттуда в свежую распаковку.

Места и адреса — тоже из данных. Тексты зовут места по машинам — BASE и HOME, а не бытовыми словами. Прямые обёртки рабочего стола connect-*-lan.cmd, проверка дорог и мастер туннеля до роутера берут адреса стационара и роутера из targets.json, а не из кода; умолчание сетей туннеля — одна 192.168.1.0/24, свои живут в routes.txt. Подсказки для машин парка переехали из программы в папку данных. install-wireguard.cmd снова работает: он звал сценарий, которого уже не было. README удалённого доступа описывает то, что есть сейчас, и прямо говорит, что рабочий стол по RDP ещё не проверялся.

Проверки: Test-Targets — второй сервер в образце заведён без адреса и с нейтральными именами; Test-Transport — разделы second и second-cf собираются; Test-Machine — различий машины шесть.

1.8.0 — 10 сентября 2026

Настройки окна — снова часть программы. config\gui-settings.json — тема, язык, терминал, корень архива, пары СИНХРО, выбранные дороги — числился среди различий машины: окно после каждой записи копировало его в папку данных и возвращало оттуда в свежую распаковку. Теперь файл живёт только в папке программы. Сборка, распакованная без него, встаёт с настройками по умолчанию.

Путь к папке данных в настройках больше не пишется. Поле DataRoot повторяло указатель config\profile.json, и окно его только записывало: путь к данным берётся из указателя или из поиска рядом с программой. Копия устаревала при первом же переносе — в комплекте ноутбука она показывала E:\TOOLS\Audion Backup, когда папка давно звалась Audion Backup Laptop. У пути к данным теперь один хозяин.

Tests\Test-Machine.ps1 проверяет обе стороны: различий машины пять, настройки окна в данные не уходят, а копия от прежних версий, оставшаяся в данных, в программу не возвращается.

1.7.0 — 8 сентября 2026

Программа переименована: Audion Sync Tools. Прежнее имя описывало то, чем она начиналась, — снимок Build-стека. Сейчас это двухпанельный диспетчер всего хозяйства: машины, роутеры, серверы, корзины R2, облака, терминалы, туннели, пробросы, зеркала; бэкап — одна из десяти его работ. Имя встаёт в семью Disk Tools, DevOps Tools, Get Tools, и оба слова понятны без перевода.

Папка теперь E:\TOOLS\Audion Sync Tools, знак — «S» из двух встречных стрелок (Assets\SyncTools.ico, шесть размеров от 16 до 256). Внутри имя заменено везде, включая пути транспорта; проверено делом — после переезда читаются и машины, и облако.

Свой ключ приложения для облака — своим действием. clouds-key.cmd меняет client_id и client_secret у заведённого облака, не трогая ни имени, ни прочих настроек, а clouds-reconnect.cmd обновляет пропуск — тот, по которому rclone ходит вместо человека. Пересоздавать облако ради смены ключа больше не нужно; в окне это кнопки ВОЙТИ ЗАНОВО и лента CLOUDS.

Хвост client_id проверяется сразу: он обязан кончаться на .apps.googleusercontent.com. Обрезанный при вставке ключ выглядит как рабочий, но Google отвечает на него «клиент не найден», и разбирательство занимает час — теперь сценарий говорит об этом до записи.

Копирование и перенос спрашивают перед делом. На своём диске это формальность, а здесь на другом конце чужая машина, сервер или облако: промах по клавише стоит дорого, а отменить нечем. Теперь F5 и F6 показывают, что берут, откуда и куда, сколько объектов и первые имена; для переноса добавляют, что в источнике их не останется; если в приёмнике есть совпадающие имена — называют их и предупреждают о перезаписи; а когда оба конца — одно облако, говорят, что файлы переложит сам провайдер, минуя эту машину.

Спрашивают и остальные действия, которые пишут наружу. Снимок Build-стека в корзину — с напоминанием, что старые снимки вытесняются, и подсказкой про кнопку ПЛАН. Обновление всех зеркал — с напоминанием, что местная копия равняется по серверу. Удаление, зеркало и синхронизация спрашивали и раньше; переименование и создание папки спрашивают имя, чего достаточно.

Ключи облаков переживают переустановку Windows. DPAPI запечатывает на этого пользователя и эту систему: переставили Windows — и заново проходи вход во все облака. Токены при этом ни при чём, они к машине не привязаны — привязан только замок. Поэтому эталон конфига теперь кладётся туда, где ничего не переустанавливают: clouds-push.cmd отправляет его на сервер в ~/.audion/clouds.conf с правами 600, а clouds-pull.cmd забирает на любую машину. Пароль от конфига на сервер не уезжает: он ложится в склад ключей, в папку данных, и переезжает комплектом (export-keys.cmd / import-keys.cmd). Сервер держит замок, склад — ключ от него; порознь ни то, ни другое не открывается. Порядок для новой машины: импорт ключей, потом clouds-pull.cmd — и ни одного повторного входа.

Копия между двумя аккаунтами одного облака идёт внутри провайдера. Когда обе стороны — один и тот же тип (два Google Drive, два Dropbox), окно добавляет --server-side-across-configs, и данные вообще не проходят через машину: провайдер перекладывает файлы у себя. Между разными облаками такого протокола нет, поэтому флаг ставится только на совпадающий тип — команда должна честно описывать то, что произойдёт.

Перегон между разными облаками можно поручить серверу. ЧЕРЕЗ СЕРВЕР в разделе CLOUDS (и clouds-send.cmd из консоли) берёт левую панель как источник, правую как приёмник и запускает rclone на сервере: у него канал дата-центра, а не домашний. Ключи уходят туда переменными внутри сценария, который выполняется через ssh … bash -s, — на диск сервера не ложится ничего, в списке процессов виден только bash. Проверено делом: после прогона ~/.config/rclone на сервере остаётся пустым.

Проверка облаков считает место и подводит итог. clouds-check.cmd и кнопка ПРОВЕРИТЬ теперь по каждому облаку говорят не только «отвечает», но и сколько там свободно, а в конце — сколько свободно по всем сразу. Где у облака квоты нет как понятия, место не пишется.

Мастер спрашивает свой ключ приложения. Без него rclone ходит общим ключом — тем же, каким ходят все его пользователи: квота одна на всех, скорость ниже, в час пик отказы. Свой ключ принимают Google Drive, Dropbox, OneDrive, Яндекс.Диск, pCloud и Box; MEGA и Proton Drive такого не дают вовсе, у них вход логином и паролем. Дело добровольное: пропустил вопрос — работает и на общем.

Облака работают всеми кнопками, а не только копированием. rclone умеет описывать remote переменными окружения, и это решило задачу целиком: конфиг у всех вызовов остаётся обычный, машины и корзины на месте, а облака добавляются поверх. Поэтому им доступно всё то же, что и машинам, — F5, F6, F8, F2, F7, F11 «обновить», F12 «зеркало», синхронизация, свободное место под панелью и отметки по маске. Сами операции про облака ничего не знают и знать не должны. Ключи при этом не попадают ни в командную строку, ни во временные файлы: их видит только rclone, запущенный отсюда.

Появился раздел CLOUDS. Облака стоят источниками над панелями рядом с машинами: Google Drive, Dropbox, OneDrive, Яндекс.Диск, pCloud, Box, MEGA, Proton Drive — какие заведёте. Файл идёт из облака в облако или на машину обычным копированием, теми же кнопками, что и всё остальное; никакого особого режима переноса нет.

Ключи облаков лежат отдельно и зашифрованными. В общем rclone.conf им не место: тот файл открыт и ездит между машинами в комплекте ключей. Облака живут в своём config\rclone\clouds.conf, зашифрованном самим rclone, а пароль от него — в clouds.key, запечатанном средствами Windows на этого пользователя и эту машину: перенесённый файл не откроется. Пароль нигде не показывается и в командную строку не попадает — rclone получает его переменной окружения на время вызова.

Вход в облако делает человек, а не программа. Кнопка ПОДКЛЮЧИТЬ открывает консоль rclone: где у облака есть OAuth — откроется браузер, где нет — rclone спросит логин и пароль сам. Программа в этом разговоре не участвует, ей достаётся только выданный ключ доступа. Из консоли то же делают врапперы: clouds-add.cmd, clouds-remove.cmd, clouds-check.cmd, clouds-keys.cmd, а clouds.cmd показывает список.

Отметки по маске. В шапке каждой панели встала кнопка с воронкой: маска вида *.zip, 2026-*, несколько через пробел, пустая строка снимает все отметки. Кнопки шапки заодно уменьшены на четверть — они служебные.

Ряд наверху разделён на три блока. ПУТЬ, РЕЖИМЫ и ПОТОКИ стоят в своих рамках: на общей подложке разделы читались как обычные управляющие кнопки. Блок пути переносит кнопки внутри себя, а не обрезает их на узком окне.

Кнопка ДОМ стала LAN. Она не туннель и не машина, а способ идти по местному адресу без посредников — и слово об этом говорит прямо.

Доска дорог разложена по столбцам. У каждой дороги свой столбец: одна и та же дорога стоит у всех машин на одном месте, пустая клетка значит, что такой дороги у машины нет. Раньше строка росла свободно, и пятая дорога лэптопа обрезалась краем окна.

Под панелью видно, сколько там осталось места. На серверах это главное число: влезет ли то, что собираешься класть. Считается для открытой папки, а не для машины целиком — у машины с дисками C: и S: числа разные, и одно на двоих врало бы. В корне, где стоит список дисков, не пишется ничего: у каждого своё. Ответ по ssh идёт секунду-другую и потому берётся отдельным процессом и запоминается на пять минут — окно не ждёт. У корзин R2 места не показываем: там оно не кончается, там счёт за хранимое.

Точки доступа ушли из файловых панелей. Источник, до которого сейчас не достать, всё равно виден и открывается попыткой — она и скажет правду вернее пробы, снятой минуту назад. Точки остались там, где решают: у машин и роутеров в ряду терминалов.

Кнопки машин собираются из файла целей. Их было восемь, по кнопке в разметке на каждую машину, и девятая потребовала бы правки в трёх местах. Теперь набор задаёт targets.json: ключ с приставкой router- уходит в группу роутеров, остальные — в группу машин, порядок как в файле. Подсказка над кнопкой собирается оттуда же — описание цели, совет на случай молчания, оговорка про вход по паролю. Мастер АДРЕСА тоже перестал держать список машин в себе.

SECOND VPS появился в панелях. Точка сбора открывается как обычный источник — рядом с машинами и корзинами, — и файл кладётся на неё перетаскиванием, как куда угодно ещё. Из дома дорога до неё прямая, без VPN; где её ssh режут, работает запасная поверх cloudflared. Учётная запись и ключ не переписаны в конфиг rclone: имя хоста second-vps уже описано в ~\.ssh\config, оттуда ssh их и берёт.

У ssh-маячка теперь два плеча на выбор. ssh-beacon-fast.cmd поднимает его через SECOND VPS — она отвечает примерно на сорок миллисекунд быстрее и из дома достижима без VPN, но стоит внутри страны. ssh-beacon-private.cmd — через MAIN VPS: дольше ставится, зато трафик не заходит на узел внутри страны. Осмотр и снятие — ssh-beacon-check.cmd и ssh-beacon-remove.cmd.

Число потоков задаётся в окне. rclone делит один файл на потоки только начиная с 256 МБ, а на широком канале выигрыш заметен куда раньше: на двух гигабайтах до BASE один поток дал 167 МБ/с, восемь — 180. Порог опущен до шестнадцати мегабайт, а число потоков выбирается спиннером в ряду режимов — 1, 2, 4, 8, 16, 32, по умолчанию восемь. Значение запоминается между запусками.

Окно стало ниже на этаж. Ряды разъехались по смыслу. Дорога и потоки — настройки всего окна, и они встали рядом с режимами: слева путь, справа потоки. Терминалы машин и роутеров, пробросы рабочего стола, веб-морды и прокси, выбор программы терминала — это ежедневная работа, и она собралась в новом разделе TRANSPORT. В TUNNEL осталось то, чем связь устроена: клиент туннеля, маячок, маршруты, ключи роутера — там её ставят и чинят, в транспорте ею пользуются.

SERVER MIRROR и R2 BACKUP слились в STORAGE. Оба раздела про одно и то же — где лежат копии. Теперь в панелях разом видны и ночные снимки, и папка данных, и корзины audion-backup, audion-releases, audion-share, и сам сервер: файл из корзины на сервер и обратно идёт без переключения раздела. Кнопки заливки в R2 встали в ту же ленту, справа.

Туннели живут на том клиенте, который на машине уже есть. На машинах стоит Red Shield VPN, а он работает на AmneziaWG. Драйвер в системе один на всех, и занявший первым решает за остальных: версия Amnezia умеет и обфускацию, и обычный WireGuard, обычная — только обычный. Отсюда и наблюдалось, что VPN не соединялся, пока наши туннели стояли на классическом клиенте. Теперь туннель ставится на том, что уже установлено: не потому, что он лучше, а чтобы не отбирать у человека его VPN. Свой клиент программа не ставит и чужой не трогает.

Программа перестала показывать небылицы. Состояние туннеля спрашивалось у wg.exe, а туннели стоят на AmneziaWG — и обычному клиенту они не отвечают вовсе: wg show interfaces возвращал пустоту при работающем туннеле. Теперь опрашиваются все клиенты, какие на машине есть, и ответы складываются.

Час, на который всё было мертво. Возраст рукопожатия считался через Get-Date -UFormat %s, а он отдаёт местное время под видом всемирного. Разница ровно на часовой пояс: свежее рукопожатие показывалось шестичасовым, и живой туннель выглядел мёртвым.

Адреса называет тот, кто их раздаёт. Окно маячка показывало занятые адреса и предлагало свободный, считая их по своим файлам — по целям и по конфигам рядом. Выходила выдумка: в списке значились адреса, которых на сервере нет вовсе, а свободным назывался давно занятый. Теперь окно спрашивает точку сбора, а мастер выписки пира — роутер; молчат — так и говорим, вместо того чтобы подставить догадку. Поле ввода адреса убрано: его назначает тот, кто раздаёт.

Свой конфиг ищется раньше выписанных. Сценарий, не найдя своего, брал самый свежий из выписанных мастером — чей бы он ни был. Так на домашнюю машину попал конфиг рабочей: с её ключом и её адресом, который роутер этому ключу не разрешает. Пакеты отбрасывались молча, на любом клиенте, и выглядело это как «поднял и тишина».

Папка данных зовётся по машине. Audion Backup Laptop, Audion Backup Work — имя видно снаружи, и слоя Machines\<имя> внутри больше нет: папка сама себе профиль. Профиль прежних схем поднимается в корень при первом же открытии. При первом запуске папку указывает человек — в ней ключи, адреса и пароль роутера, и садиться в неё по догадке программа не будет, даже когда папка рядом одна.

Кнопка ПОДНЯТЬ ВСЕГДА. Клиент заводит службу с ручным запуском, и для машины, которая ходит по чужим сетям, это верно: включил компьютер на работе — туннель не мешает тамошнему VPN, пока сам не понадобится. Но есть машины, до которых рукой не дотянуться: машина HOME перезагрузилась, и связи с ней нет до следующего приезда. Для них второе действие подъёма переводит службу на автозапуск. Обычное ПОДНЯТЬ возвращает ручной — режим переключается тем же нажатием, без снятия туннеля.

Маячок берёт имя у машины, а адрес у сервера. В параметрах стояло имя laptop и адрес 10.13.0.2, а второй машине полагалось вписать своё руками. Про это забывали: машины выписывались под одним именем и отбирали друг у друга адрес, а после переименования на сервере оставался пир под прежним. Теперь имя берётся у машины, а свой пир узнаётся по ключу и сохраняет прежнее место — ключ переживает и переустановку системы, и переименование.

Снятие пира убирает его целиком. Из конфига сервера вырезалась одна строка с ключом, а [Peer], имя и AllowedIPs оставались лежать. Пир без ключа не работает, но адрес держит — и следующая установка брала адрес дальше. За пару «поставил — снял» маячок уезжал с .2 на .5, а на сервере копились огрызки, которых нет в работающем туннеле.

Клиент берётся своей разрядности. Red Shield кладёт рядом сборки под amd64 и arm64, и запуск чужой — не тихая ошибка: Windows показывает модальное окно «Несоответствие типа компьютера», которое не поймать ни try, ни catch. А состояние опрашивается по таймеру, так что окно всплывало снова и снова поверх работы.

Инвентарь показывает матрицу. Кто куда ходит — таблицей: ключи по строкам, машины по столбцам, в клетке плюс, точка или вопрос, если машина не ответила. Строчками через запятую было видно, кто где прописан, но не видно дыр.

Кнопки роутера спрашивают, с каким говорить. Роутер будет не один: роутер BASE есть, HOME появится, WORK заведётся позже. В списке показываются только те, у кого вписан адрес, — пока роутер один, вопроса нет.

Ставит клиент только кнопка WIREGUARD, и она сперва смотрит. Сценарий маячка, не найдя WireGuard, тянул его через winget сам — и поставил на машину, где давно стоял AmneziaWG и где обычный клиент не нужен ни для чего. Теперь кнопка говорит, какой клиент есть и почему второго не нужно, а ставит, только если нет ни одного.

Врапперы уехали в Runs. Корень программы очистился: там остались документы, папки и Start.exe.

Ряд настройки разложен по ширине. ШАГИ слева, ИНСТРУМЕНТЫ посередине, ЗАДАНИЯ справа — одной строкой. Двумя полосами ряд читался хуже: верхняя жалась к левому краю, нижняя комом к правому, а середина пустовала. Группа ПАРК опустела раньше — её кнопки уехали в раздел ключей — и убрана вместе с чертой, которая их разделяла.

Подписи кнопок больше не выглядят обрезанными. Многоточие на конце — ТЕРМИНАЛ…, АДРЕСА…, КОНФИГ… — означало «откроет окно выбора», а читалось как текст, которому не хватило места. Что кнопка спросит, сказано в подсказке: там для этого есть строка целиком.

Подпись терминала переводится целиком. Она собирается в коде, и на английский уходило только значение на конце: выходила смесь — ТЕРМИНАЛ: own. Теперь переводится вся строка, и при смене языка подпись пересобирается: обход дерева ставил вместо неё исходное слово из разметки, теряя выбранную программу.

Ряд туннеля тоже в одну строку. СЕТЬ слева, ИНСТРУМЕНТЫ посередине, ЭТА МАШИНА справа. Инструменты стояли вторым ярусом и читались как отдельный ряд. Середина — панель с переносом: при ширине окна примерно от 1400 точек всё стоит в строку, а если сузить сильнее, кнопки уходят вниз, а не срезаются по краю.

Язык окна берётся из настроек с самого начала. В коде стояло жёсткое en, и при русском окне переменная языка так и оставалась английской: разметку возвращал обход дерева, а всё, что собирается кодом — подписи и строки журнала, — шло через словарь и выходило по-английски. На кнопке это выглядело как TERMINAL: own.

Снятие маячка не просит прав, когда снимать нечего. Службы уже нет — остаётся убрать пир на точке сбора, а это разговор по ssh. Права здесь не просто лишние: повышенный процесс до сервера не дошёл, хотя из обычного окна ключ работает.

Отказ ssh называет причину. Сказанное в поток ошибок выбрасывалось, и оставалось «проверь ключ SECOND VPS» — гадай, права ли на файле, чужой ли ключ, молчит ли сервер. Теперь причина печатается словами: connect to host ... port 22: Connection timed out — видно, что дело в сети, а не в ключе.

Фон файловых панелей посветлел — 26 33 38 вместо почти чёрного. Рамки, лента, блок терминала и подвал остались прежними.

Кнопка DNS: кто разрешает имена и кому их доверить. Так выглядит обрыв, которого нет: адреса пингуются, маршрут на месте, а ни один сайт не открывается. Разгадка обычно одна - на адаптерах прописан локальный резолвер, а тот не работает: ControlD, YogaDNS, AdGuard, dnscrypt ставят себя на 127.0.0.1 и разрешают имена сами, шифрованным каналом.

Кнопка сперва показывает: какие адреса стоят на адаптерах, что предлагает роутер по DHCP (это лежит в реестре рядом с заданным вручную и никуда не девается), кто держит 53-й порт и кто в итоге спрашивает наружу - последнее звено находится через служебное имя Google, а обратная запись называет хозяина: dns.google, one.one.one.one, узел провайдера.

Потом даёт выбрать: оставить как есть, вернуться к роутеру или назвать известного - Cloudflare, Google, Quad9, Яндекс, AdGuard. Выбранного сперва спрашивают именем и прописывают, только если он ответил: молчащий резолвер оставил бы машину без имён, и чинить пришлось бы вслепую. Лежачую службу локального резолвера кнопка поднимает сама. Адаптеры туннелей не трогает.

Та же кнопка смотрит службу NlaSvc - ту, что решает, есть ли выход наружу, и рисует значок в трее. Когда она лежит, выходит «интернет как бы есть, но»: сайты открываются, а Windows показывает глобус, профиль сети висит на LocalNetwork, и брандмауэр берёт профиль наугад. Кнопка возвращает службе автозапуск - штатное для Windows значение - и поднимает её.

Приватный ключ закрыт везде, где лежит. Защищался только файл .key, а тот же ключ стоит строкой PrivateKey внутри .conf - и конфиги писались с правами, унаследованными от места. На E:\TOOLS это «Пользователи» с чтением и «Прошедшие проверку» с изменением: сосед по системе мог прочитать ключ и подменить конфиг, а подмена вступила бы в силу при следующем подъёме туннеля.

Теперь права ставит одна процедура - Engine\Secrets.ps1. Она закрывает файл или каталог до трёх субъектов (владелец, администраторы, система) и проверяет результат: сказанное «защищено» должно быть проверенным. Установщик маячка закрывает склад ключей целиком при каждом запуске - права приезжают от места, и после переезда папки данных склад открывается заново. Мастер туннеля до роутера и выписка пира закрывают свои конфиги сразу после записи.

Ключ -AtBoot переживает подъём прав. В повышенный процесс передавались имя, адрес и снятие, но не автозапуск: запуск из обычной консоли с -AtBoot проходил UAC и попадал в ветку ручного старта. Человек просил «поднимайся при загрузке», а машина после перезагрузки молчала.

Осмотр перестал двигать файлы. Ключ -Check обещает «только посмотреть», а на деле создавал каталоги и переносил старый конфиг в папку данных, попутно правя ему права. Если служба ждала файл по прежнему пути, следующий её запуск мог не состояться. Теперь переезд и создание каталогов - только когда мы правда ставим.

DNS «сам роутер» - каждому адаптеру свой. Первый найденный шлюз назначался всем адаптерам разом. При одновременных Ethernet и Wi-Fi из разных сетей один получал шлюз чужого сегмента, а с отключением того подключения оставался и без имён. Теперь адрес берётся по интерфейсу, каждый шлюз проверяется отдельно, и адаптер без своего шлюза не трогается вовсе.

Проверка кодировок не смотрит в ._runtime. Там распакованные инструменты, рабочие копии и материалы разборов - требовать от них BOM и CRLF нечего.

Маячок без туннеля: обратный проброс на зарубежный сервер. Прежний маячок поднимал в системе адаптер и службу WireGuard - забирал маршруты, ставил свой DNS, спорил с купленным VPN за общий драйвер и падал при загрузке, пока сеть не готова. Новый не делает ничего из этого: машина сама держит одно исходящее соединение и просит сервер открыть у себя порт на localhost. Кто вошёл на сервер - через этот порт попадает на машину. Ни адаптера, ни маршрутов, ни драйвера.

Это вторая дорога рядом с прежней, а не вместо неё: оба маячка ставятся и снимаются по отдельности. WireGuard даёт машину целиком - любой порт, файлы, рабочий стол; проброс даёт двадцать второй порт и всё, что умеет через него ssh. Зато проброс - это TCP, и он проходит из-под чужого VPN и мобильного оператора, где UDP не возвращается вовсе.

Плечи перебираются сами: сперва прямой адрес сервера, при обрыве - тот же сервер поверх cloudflared. Выбор не спрашивается, потому что сеть под ногами меняется: то, что не прошло минуту назад, может оказаться единственным работающим. -Check показывает порядок плеч и какое держит канал сейчас, а держатель пишет журнал в logs\ssh-beacon-<машина>.log - он живёт в задаче, без окна, и раньше всё сказанное уходило в пустоту.

Ключ маячка отдельный от машинного, на сервере прописан с ограничением restrict,port-forwarding,command="/bin/false" - оболочку им не получить. Правка authorized_keys идёт с копией файла и сверкой числа строк: там живут и ключи владельца.

Дорога МАЯЧОК в окне. Четвёртая кнопка пути, между CF и SECOND VPS. Она ведёт на ту же машину, но не зависит от того, достанет ли до неё кто-то снаружи: канал держит она сама. Для машины за чужим NAT это единственная дорога вообще, поэтому автомат ставит её перед точкой сбора.

Сервер перестал держать порт за мёртвой сессией. sshd замечает обрыв не сразу, и проброшенный порт остаётся занятым - новое соединение получает remote port forwarding failed, маячок не поднимается. Вылечено с двух концов: на сервере включены ClientAliveInterval 30 и ClientAliveCountMax 3, а держатель, увидев занятый порт, ждёт минуту вместо того, чтобы долбиться.

Маячок больше не уносит с сервера чужой пир. Блок сносился при совпадении любого из трёх признаков - ключа, имени или адреса. Ключ - это личность пира, а имя и адрес могут принадлежать другой машине: явный -Address, совпавший с чужим пиром, молча удалял его с сервера. Теперь свой блок ищется по ключу, а совпадение имени или адреса при чужом ключе - конфликт: установка останавливается и говорит, чьё место занято. Настоять можно ключом -Force - тогда перебивающий блок уходит осознанно, а не украдкой.

Адрес и запись пира - одна транзакция под замком сервера. Прежде это были два разговора: сперва «какой адрес свободен», потом «запиши меня». Между ними помещался второй установщик - оба получали один и тот же адрес, и второй затирал первого. Теперь выбор и запись идут одной командой под flock, а временные файлы уникальны: общие /tmp/wg2.new и /tmp/wg2.strip тоже сталкивались при одновременной работе.

Отказ сервера перестал выглядеть успехом. Команды заканчивались безусловным echo ok, оболочка не прерывалась на ошибке, а в синхронизации итоговый код перезаписывался успешной уборкой за собой. Установка шла дальше и поднимала службу на пир, которого на сервере нет. Теперь каждый шаг под set -e, ответ проверяется вместе с кодом возврата, а при отказе локальная служба не трогается вовсе.

Проверено стендом, а не обещанием. Настоящие куски команд вырезаны из сценария и прогнаны на подставном конфиге с тремя пирами: чужой адрес и чужое имя дают конфликт и никого не трогают; с -Force перебивающий блок уходит и дублей адреса не остаётся; свой ключ переписывает свой же блок; незнакомый ключ не трогает никого.

Файловый клиент перестал верить любому, кто ответил. WinSCP получал -hostkey=* - то есть принимал ключ любого узла. В чужой сети с тем же частным адресом (192.168.1.x встречается везде) на 22-й порт отвечает соседская машина, и файлы уехали бы к ней; туннель до сервера тут не спасает, он проверяет сервер, а не машину на том конце. Теперь отпечаток берётся из своего списка ключей хостов и передаётся клиенту; записи нет - подключение не открывается вовсе, с подсказкой снять ключи кнопкой. Штатный sftp тоже получил свой список вместо одноразового файла: accept-new в пустой файл - это «верю первому, кто ответил».

Ключи хостов обновляются по узлу. Файл переписывался целиком тем, что удалось снять сейчас: ответила одна BASE - записи остальных машин исчезали. Теперь недоступная машина сохраняет прежние ключи, а в обход добавлены HOME и WORK, которых там не было вовсе, и учитывается порт.

Смена ключа хоста больше не проходит молча. Так выглядит и переустановка системы, и подмена узла - разница только в том, знает ли об этом человек. Кнопка оставляет прежнюю запись и говорит, у каких машин ключ не тот; принять новый можно тем же нажатием с зажатым Ctrl.

Неоднозначная папка данных останавливает работу. Рядом лежат комплекты всех машин, и при отсутствии указателя бралась первая по алфавиту - установщик туннеля брал из чужого комплекта ключи и конфиги, а правки уходили не туда. Теперь поиск прекращается с вопросом, а выбранную папку окно передаёт сценариям ключом -Root - и через подъём прав, и в задачу маячка.

Прежний снимок сервера уходит только после проверки нового. Совпавшая контрольная сумма говорит, что скачанные байты равны исходным, - но не что исходные годятся. Сервер мог выгрузить обрезанный архив вместе с его правильной суммой, а прежний, рабочий, к этому времени уже стёрт. Теперь новый снимок сперва открывают и перечисляют - читая, ничего не распаковывая, - и лишь потом убирают старые. Не открылся - прежние остаются на месте, а окно говорит об этом.

Выбор проекта ограничивает и передачу. -ProjectName фильтровал список на экране, а rclone sync получал папку целиком: при нескольких проектах рядом уезжали и чужие архивы. Хуже того, сверка потом сравнивала полный удалённый каталог с выбранной частью локального и объявляла ошибку - когда лишнее уже отправлено. Теперь и передача, и сверка держатся одной области.

Файловый враппер роутера снова работает. Он звал цель router, а в targets.json живут router-base, router-home и router-work - вход кончался «цель не описана». Имя оставлено как привычное короткое: оно разворачивается в роутер BASE, а список допустимых целей приведён к тому, что действительно есть.

Проброс порта: рабочий стол и всё остальное без туннеля. Файлы возит окно, команды выполняет терминал, а рабочий стол, веб-морда роутера или сетевая папка теперь переносятся по уже поднятому ssh. Адрес разрешается на той стороне, поэтому через одну машину видно всё, что видит она - её саму, роутер, принтер, соседний компьютер.

В системе при этом не меняется ничего: ни адаптера, ни маршрутов, ни своего DNS, и чужому VPN спорить не с чем. Закрыли окно рабочего стола - проброс снят.

Появились сценарий Tunnel\RemoteDesktop\Open-Forward.ps1, четыре враппера и группа ДОСТУП в ряду TUNNEL: РАБОЧИЙ СТОЛ, ВЕБ РОУТЕРА, ПРОКСИ. Последний открывает браузеру домашнюю сеть целиком через SOCKS5.

Туннель остаётся нужен ровно для одного случая - когда сеть нужна вся и сразу, включая то, чего заранее не назвали. Для одного порта проброс дешевле.

Туннель не поднимается поверх адресов той сети, где машина стоит. Он забирает себе всё, что перечислено в его AllowedIPs; если такой адрес уже принадлежит местной сети, он для машины пропадает - пакеты уходят в туннель, а не к соседу. Так бывает в сети, где занят весь 192.168.0.0/16: путь до сети BASE отнял бы у неё адреса разом.

Но пересечение диапазонов - ещё не конфликт: отнять можно только занятое. Если в большой сети нужные адреса свободны, туннель там работает.

Поэтому проверка идёт в два шага: арифметика - попадает ли адрес в местную сеть, - и живая проба, отвечает ли по нему кто-нибудь здесь и сейчас. Кнопка питания перед подъёмом называет только настоящие столкновения. Дома это значит «туннель не нужен, адреса и так рядом», в чужой сети - «он отнимет у неё эти адреса». Поднять вопреки можно нажатием с Ctrl. Опускание не проверяется: снимать туннель безопасно всегда.

Разбор сетей вынесен в Engine\Routes.ps1: он читает AllowedIPs из конфига, берёт живые адреса машины с масками и считает пересечение по меньшему префиксу.

1.6.1 — 7 сентября 2026

Туннель находится и под прежним именем. Имя менялось дважды: home, base, теперь router-base-wg. Мастер снимает прежние при установке, но пока его не запускали, служба живёт под старым и работает — а программа искала только новое и показывала «не заведён» при поднятом туннеле: точка серая, выключить нечем. Теперь служба ищется по всем трём именам, а мастер показывает плашкой, под каким она найдена.

Отказ в правах узнаётся делом, а не словами. Windows на попытку остановить чужую службу отвечает Cannot open 'WireGuardTunnel$base' service on computer '.' — ни «прав», ни «доступа» в этой строке нет, и проверка по словам молчала: диалог с предложением выдать право не появлялся, оставалось сухое «не вышло». Признак теперь другой: служба есть, переключение не прошло, таймаута не было — значит предлагаем права.

1.6.0 — 7 сентября 2026

Туннель включается и выключается кнопкой. Рядом с ROUTER-BASE WG и BEACON стоит кнопка питания: ▶ поднять, ■ опустить. Мастер остался тем, чем был — ставит туннель и сносит его насовсем; кнопка только поднимает и опускает службу, конфиг и ключи остаются на месте.

Это нужно потому, что поднятый туннель забирает себе перечисленные сети и мешает обычной сетевой работе: другому VPN, рабочей сети, принтерам. Выключать его приходится часто, а раньше для этого надо было открывать приложение WireGuard или лезть в сетевые настройки Windows.

Чтобы переключение было мгновенным, а не через запрос прав на каждое нажатие, установка туннеля сразу выдаёт этой учётной записи право пускать и останавливать именно эту службу — и ничего больше: ни установки, ни удаления, ни смены настроек. На туннелях, заведённых раньше, право выдаётся по первому отказу, с согласия и один раз.

1.5.1 — 7 сентября 2026

Указанная Machines не порождает Machines\Machines. В выборе папки легко зайти на шаг глубже: окно показывает дерево, и Machines выглядит не хуже родителя. Путь тогда складывался дважды, и программа об этом молчала. Теперь любая из этих папок приводится к папке данных — сама Machines, профиль внутри неё и уже сложившаяся двойная вложенность; в журнале сказано, что указано и что взято.

1.5.0 — 7 сентября 2026

Программа больше не хранит своего. У неё остался один файл — config\profile.json с двумя строками: где папка данных и как зовётся профиль этой машины. Всё остальное — адреса, ключи корзины, отпечатки хостов, пароль роутера, настройки окна — живёт в Audion Backup\Machines\<Имя>. Программу можно снести, пересобрать и распаковать заново: она прочитает указатель и найдёт своё.

Профиль называет человек. Кнопка ДАННЫЕ спрашивает папку, следом — профиль: списком того, что уже лежит в Machines, плюс поле для нового имени. Имя не выводится из имени компьютера: на работе его не переделать, а папку данных носят между машинами — «угаданное» имя завело бы там пустой профиль вместо принесённого.

Адреса вписываются одной таблицей. Раньше мастер спрашивал одну машину за нажатие и закрывался; про то, что кнопку надо нажать ещё четыре раза, не говорилось нигде. Отсюда и выходило: адрес появился у одной машины, транспорт собрался с восемью незаполненными метками, а окно отчиталось об успехе. Теперь все машины сразу: адрес, учётная запись, порт, и рядом сказано, что молчит и почему это не ошибка записи.

Журнал окна ложится файлом — logs\gui-ГГГГММДД.log, строка со временем. Раньше в файл попадали только падения, и разбирать чужую машину было нечем: панель показывает всё, а прислать оттуда нечего.

Каркас адресов приезжает со сборкой. targets.json — не только данные, в нём заведены сами машины; запись адреса правит текст готового файла и на отсутствующем молча отвечала «не удалось». Теперь рядом едет targets.sample.json, и программа разворачивает его при первом запуске.

1.4.0 — 7 сентября 2026

Различия машины живут в данных. Рядом с программой, в Audion Backup\Machine, лежит её слой: настройки окна, транспорт rclone, ключи корзины, отпечатки хостов, адреса машин и пароль роутера. При запуске программа берёт оттуда то, чего у неё нет; при каждой записи складывает туда свежее. Распаковка новой сборки поверх удалённой старой больше ничего не уносит — раньше уносила всё перечисленное, и возвращать приходилось руками.

Возврат берёт только отсутствующее: то, с чем человек работает сейчас, важнее сохранённого. Версия сборки, темы и шаблон конфига в слой не идут — они у всех одинаковые и приезжают с программой. Кнопка СПИСОК показывает слой целиком: что где лежит и чего где нет.

Адреса туннеля набираются окошками. В мастере ROUTER-BASE WG на каждый адрес своя строка: четыре окошка под числа с переходом по точке и по третьей цифре, размер сети — кнопками словами (ОДИН АДРЕС, 254 АДРЕСА, 65 ТЫСЯЧ, 16 МЛН), ЕЩЁ АДРЕС добавляет строку, крестик убирает. Итоговая запись собирается плашкой сверху по мере ввода, рядом показана сеть самой машины — видно, задевает ли список её.

Сплит-туннелинг настраивается там же. Туннель и раньше вёл в себя только перечисленные сети, но список был зашит в коде: целая подсеть пересекалась с местной сетью и забирала принтеры. Теперь список лежит в Audion Backup\Tunnel\WG\routes.txt и правится кнопкой; узкие адреса пишутся как 192.168.1.10/32. Перед подъёмом сценарий предупреждает, если адрес самой машины попадает в заворачиваемую сеть.

Туннели снимаются кнопкой. У мастеров ROUTER-BASE WG и BEACON три действия: ПОДНЯТЬ, ПРОВЕРИТЬ, СНЯТЬ. Состояние показано плашками — служба, адрес в туннеле, найденный конфиг.

Исправлено. Плашки состояния роняли диалог: своя переменная совпала с именем параметра, объявленного с проверкой значений. Обработчики, созданные через GetNewClosure, не знали функций окна и падали при нажатии. Кнопка ОТМЕНА оставалась русской при английском языке. Обе ошибки теперь ловит Test-Handlers по дереву разбора, слой проверяет Test-Machine на песочнице.

1.3.0 — 6 сентября 2026

Цвета берутся из темы Total Commander целиком. Цвета имён, порядок правил и маски типов читаются из config\colors; своего списка расширений в программе больше нет. Тёмная сторона берёт парные значения ColorFilterNColorDark, светлая — обычные. Возраст считается календарными сутками, как в TC.

Две темы — тёмная и светлая, кнопка в шапке. Выбор запоминается; журнал, строка пробы и панели перекрашиваются вместе с темой.

Сортировка по колонкам — щелчок по заголовку, повторный переворачивает порядок. Папки сверху, курсор держится за имя.

Колонка «Изменён» — единый вид дд.ММ.гггг ЧЧ:мм для всех строк.

Мелочи. Из списка дисков убран служебный Temp: самого PowerShell. Щелчок по букве диска в дорожке пути ведёт в корень, а не в папку программы. Справка rclone больше не попадает в журнал.

Лента разделов в два яруса. Наверху по центру — сами разделы под подписью РЕЖИМЫ, ниже отдельным блоком — ДОСТУП с машинами слева и ПУТЬ с дорогами справа. Группы кнопок подписаны в каждом разделе: СЕТЬ, ЭТА МАШИНА и ИНСТРУМЕНТЫ в туннеле, ИСТОЧНИК и ЗАЛИВКА В R2 в корзине, РАСКЛАДКА КЛЮЧЕЙ и ОТКРЫТЬ ПАПКУ в ключах, ЗЕРКАЛО СЕРВЕРА, ПЛАНИРОВЩИК и ОБЪЕКТЫ ЗЕРКАЛА в зеркале.

Задание планировщика снимается кнопкой. Рядом с РАСПИСАНИЕ встала ОТМЕНИТЬ: ежедневное задание уходит, зеркало остаётся на месте. Если задания не было, окно так и говорит.

Отметки в панели. Кнопки ВСЕ и НИ ОДНОГО берут строки активной панели и пишут в журнал, сколько строк отмечено и в какой панели.

Фонов стало два. Под файлами, журналом и терминалом — один тон, у самих блоков — он же, а подложка окна светлее: блоки видно как блоки, а не по одним окантовкам. РЕЖИМЫ стали таким же блоком во всю ширину. Строку заголовка это не затронуло.

Курсор тёмно-морской. Строка под курсором красится #004360, текст на ней светлый. Из темы Total Commander цвет курсора не берётся: там он голубой и возвращался бы при каждой смене темы.

Отметки доходят до экрана. Строки панели проходили через сортировку, а Sort-Object заворачивает каждую в PSObject — WPF терял в ней источник уведомлений, и галочка, поставленная пробелом или кнопкой ВСЕ, появлялась только при следующей пересборке списка. Теперь обёртки разворачиваются, и отметка видна сразу. Пробел, кроме того, ставит галочку той строке, что подсвечена, а не той, где курсор оставила клавиатура.

Точка доступности у источников. У каждой кнопки источника — зелёная точка, если туда сейчас можно попасть: у машин это последняя проба или живая обходная дорога, у папок — их наличие, у корзин — ключи и дорога наружу. Недостижимое гаснет до трети яркости. Пока пробы не было, всё показано живым. Что не влезает по ширине, уходит второй строкой — вбок ряд больше не прокручивается.

Два языка. Кнопка в шапке переключает русский и английский; по умолчанию английский. Переводятся подписи, подсказки, сообщения журнала, диалоги и строка пробы — окно при этом не пересоздаётся. Словарь лежит парами в Engine\Lang.psd1: ключи хэша PowerShell не различают регистр, а «ДОМ» на кнопке и «дом» в строке пробы — разные слова с разным переводом. Скрипты движка переведены на английский целиком, без переключения: их вывод и так читают в журнале.

Мастера вместо блокнота. Раздел SETUP теперь умеет заводить то, что раньше правили руками:

targets.json, сохраняя порядок ключей и пояснения; сразу после записи стучится в порт. Нажатие на серую кнопку машины ведёт туда же.

адреса, учётные записи и ключи подставляются из targets.json и склада, спрашивается только идентификатор учётной записи Cloudflare. Что не подставилось — остаётся в файле меткой {{…}}, и окно называет её вслух.

в профиль и в склад, открытая показывается и копируется в буфер. Если пара уже есть, новая не делается — старая перестала бы пускать на машины.

ключ -Root при запуске по-прежнему сильнее запомненного.

Ещё два теста. Tests\Test-Targets.ps1 следит, что правка адреса меняет одну цель и не трогает соседние, пояснения и BOM. Tests\Test-Transport.ps1 собирает транспорт из заготовки во временную папку и проверяет подстановку, состав секций и то, что незаполненные метки честно названы.

Мастер обзаведения — раздел SETUP. Четыре секции с разделителями: КЛЮЧИ, МАШИНЫ, ИНСТРУМЕНТЫ, ДАННЫЕ. У каждой кнопки точка: зелёная, когда дело сделано, серая — когда до него ещё не дошли. Кнопки зовут уже написанное; своё в разделе — только АДРЕСА…, открывающая targets.json.

Ключи к корзине вводятся полями. Кнопка КЛЮЧИ R2… спрашивает пару «идентификатор и секрет» и кладёт её файлом r2.credentials туда, где её ищет rclone, после чего сразу спрашивает у корзины список бакетов. Значения в журнал не попадают. Диалог научился нескольким полям сразу.

Диалоги живут в теме окна. Своя копия палитры в Dialog.xaml осталась заводской, а живое окно перед показом кладёт туда свои кисти; заголовок диалога тёмный ровно тогда, когда тёмное окно.

SERVER среди машин. Зарубежный сервер стоит в ряду ДОСТУП и в панелях разделов TUNNEL и R2 BACKUP: файлы возятся между корзиной и сервером напрямую, без scp и без консоли. Дорога — родной sftp самого rclone по ключу audion_vps_root_ed25519; запасная, поверх cloudflared, осталась на внешнем ssh. У цели появилось поле sshHost: у сервера нет домашнего адреса, и окно зовёт готовый хост из ~\.ssh\config.

Свой список ключей хостов. config\rclone\known_hosts знает BASE, LAPTOP и SERVER; все панели сверяются с ним, путей в профиль пользователя больше нет. Кнопка КЛЮЧИ ХОСТОВ снимает ключи заново: домашние машины отвечают на ssh-keyscan, у сервера он молчит — там окно спрашивает сам хост по уже поднятому соединению. Файл ~\.ssh\known_hosts не трогается: им пользуются ssh и Tabby.

Первый тест. Tests\Test-Window.ps1 проверяет окно, не запуская его: разбор разметки и модуля, полноту списка загрузки, ряды и переключатели разделов, знание тем о кистях. Написан после того, как раздел SETUP не открылся из-за имени, забытого в списке загрузки.

Ключи R2 зовутся r2.credentials. Точка вместо подчёркивания — так этот файл называется в самой экосистеме AWS, в складе ключей и у публикатора. Старого имени не осталось ни в программе, ни в данных, ни на серверах.

Машины переехали в ленту. Кнопки BASE, LAPTOP, HOME, WORK, ROUTER-BASE, ROUTER-HOME и ROUTER-WORK стоят посередине ленты разделов и видны из любого раздела: консоль нужна не только в TUNNEL. Ряд кнопок раздела разгрузился и разошёлся по ширине окна тремя группами. Три новые точки заведены заранее с пустыми адресами — кружок серый, нажатие говорит, что вписать адрес нужно в targets.json.

Одна кнопка на три инструмента. ОБНОВИТЬ ведёт клиент туннеля, rclone и портативный терминал; кнопка ИНСТРУМЕНТЫ убрана как лишняя. Версии спрашиваются до закачки, поэтому свежее не тянется повторно, а -Force перекачивает принудительно. У закачки виден вес, скорость и остаток; шаги подписаны. Настоящий выпуск терминала пишется рядом в .version: в самом wt.exe Microsoft оставляет номер базовой ветки.

Проба показывает время. Вместо галочек — миллисекунды каждой дороги, а рядом задержка самого окна: видно, кто тормозит, сеть или программа. Замер вынесен из потока окна, иначе мерялась очередь диспетчера и все дороги выходили одинаковыми.

Панели. Добавлены источники R2 MEDIA и R2 VAULT. Шапка панели начинается с кнопок хода, источники следом. Исправлены четыре падения: список из одного объекта, пустая корзина, сторож исключений и статус, который навсегда оставался «читаю…».

Туннели. Точка показывает живость канала, а не только службу Windows. Маячок лэптопа чинился: в скрипте оставался порт 8444, тогда как сервер слушает 500.

Своё имя на панели задач — окно больше не выглядит как PowerShell.

1.2.0 — 5 сентября 2026

Синхронизация папок. Правее файловых операций три кнопки:

устаревшее; ничего не удаляет;

удаляется, поэтому спрашивается подтверждение с направлением и составом, а предохранитель отменяет операцию, если под удаление уходит больше 200 файлов;

Направление задаёт активная панель: источник — та, где курсор. Работают эти кнопки не с именами папок, а с тем, что открыто: сравниваются два каталога из дорожек пути, со всем вложенным на любую глубину.

Область задают галочки. Ничего не отмечено — равняется открытая папка целиком. Отмечено — только отмеченные ветки: они уходят в фильтры --include, а rclone применяет фильтры и к удалению, поэтому соседние папки приёмника остаются нетронутыми. Проверено на песочнице: зеркало по двум веткам из четырёх обновило только их, две другие не тронуло. Подсветка строки, в отличие от F5, областью не считается: зеркало удаляет, и выбор должен быть намеренным. СИНХРО отметки не принимает и говорит об этом — он помнит состояние пары папок, и смена области потребовала бы нового разбора с нуля.

Кнопка ДОРОГИ и враппер check-routes.cmd. Проходит все четыре дороги до BASE и говорит, какие живут: кто ответил, за сколько и что сказала та сторона, плюс читает каталог по каждой живой. С ключом -Speed заодно меряет скорость. Отчёт ложится в logs outes-<дата>.log: его можно показать позже, когда связь вернётся. Ничего не меняет — только читает, и потому годится как первое, что запускаешь в незнакомой сети.

Дорогу можно выбрать руками. Справа в ленте разделов, за разделителем: ПУТЬ — АВТО, ДОМ, СЕРВЕР, CF, SECOND VPS. АВТО слушает пробу, остальные держат выбранное, даже если проба против: человек знает про сеть больше, чем стук в порт. Переключение сразу перечитывает панели машин.

Строка пробы говорит словами и переехала в середину шапки — она про всю программу, а не про раздел. Было «отвечают 3 из 6», стало «дом ✗ · сервер ✓ · cloudflare ✓ · SECOND VPS ✓ · путь: СЕРВЕР (по пробе)» — видно, что именно доступно и какой дорогой пойдёт окно. Оговорка: галочка означает, что порт открыт, а не что протокол пройдёт: SECOND VPS рвут уже после установления соединения, и проба такого не видит.

Дорога видна на кнопке. Подпись источника называет и машину, и путь к ней: BASE — напрямую из дома, BASE · CF — через зарубежный сервер поверх cloudflared, BASE · СЕРВЕР — тот же сервер по имени, BASE · SECOND VPS — через точку сбора. Иначе непонятно, почему одно и то же имя отвечает то мгновенно, то через минуту.

Четыре дороги к домашним машинам. Панели идут первой доступной: дома напрямую, из чужой сети — прыжком через зарубежный сервер по имени, затем через него же поверх cloudflared, и последней остаётся SECOND VPS. Скорость передачи у дальних дорог одинакова (замер дал 1,65 МиБ/с и там, и там), но сессия по прямому имени встаёт вдвое быстрее — 1,7 секунды против 2,8. Риска в этом нет: проба щупает сам адрес, и когда его заблокируют, окно уйдёт на cloudflared, где блокировать нечего. Выбор делает проба: она щупает домашние адреса и сервер, а результат виден в ленте режимов — там же, где переключаются разделы. Раньше строка пробы стояла в ряду кнопок и наезжала на крайние.

Кнопки РОУТЕР и КОНФИГ. Разговор с домашним роутером по его собственному API теперь есть и в окне: РОУТЕР показывает модель, прошивку и пиров с рукопожатиями, КОНФИГ… выписывает этой машине конфиг WireGuard — спрашивает имя своим окном и сначала показывает команды, которые уйдут в роутер.

Пустые папки теперь переносятся. Для rclone существуют только файлы: каталог без единого файла он не создаёт в приёмнике и молча оставляет как есть — зеркало заканчивалось за секунду с 0 B / 0 B, а в приёмнике недоставало папок. Все передачи, включая очередь F5/F6, идут с --create-empty-src-dirs. Пустые файлы, скрытые и системные переносились и раньше — но атрибуты «скрытый» и «системный» не сохраняются, в приёмнике файл становится обычным.

Времена файлов переносятся. Ко всем передачам добавлен --metadata: копия помнит, когда файл создан, изменён и когда его открывали. Без него сохранялось только время изменения, а «создан» у копии значилось сегодняшним числом. Оговорка касается машин по ssh: бэкенд sftp у rclone метаданных не умеет вовсе — туда доезжает лишь время изменения. Полностью времена сохраняются между дисками, подключёнными к этой машине.

Время каталогов на машины по ssh больше не ставится. rclone обновляет время папки после копирования, а OpenSSH под Windows отвечает на это отказом — похоже, пока в папку ещё пишутся файлы. Для rclone это ошибка ввода-вывода, и дальше он отказывается удалять лишнее: зеркало доносило файлы, но оставалось недоделанным и заканчивалось кодом 1. Теперь, когда одна из сторон — машина по ssh, добавляется --no-update-dir-modtime. Времена файлов переносятся как прежде; время папки на той стороне всё равно поставить нечем.

Повторы с паузой. rclone повторяет неудачную операцию трижды, но все три попытки укладывает в одну секунду — а типичная причина отказа как раз временная: свежескопированные файлы ещё держит индексатор или антивирус, и только что опустевшая папка не удаляется с «permission denied». Между попытками теперь пять секунд, а удаление на машине по ssh пробует шесть раз — вместе это даёт папке полминуты, чтобы освободиться.

Конфиг выписывается сам. Раньше клиента WireGuard заводили руками в веб-интерфейсе роутера, а его файл несли с собой. Теперь это делает new-router-peer.cmd: ключевая пара рождается на машине (роутер видит только открытую половину), в роутере заводится пир со свободным адресом из его подсети, обратно забираются открытый ключ сервера, порт и доменное имя — и из всего этого собирается готовый .conf. Тот же враппер с -Remove снимает пира, с -WhatIf показывает команды не отправляя.

Разговор с роутером ведёт RouterNdm.psm1: NDMS здоровается отказом с realm и challenge, пароль по проводу не идёт — сверяется отпечаток. Пароль можно сохранить ключом -Remember: он ложится зашифрованным средствами Windows, под эту учётную запись и эту машину, и дальше не спрашивается.

Кнопка WIREGUARD. Ставит на эту машину сам WireGuard — программу, без которой не поднять ни путь домой, ни маячок. Раньше он ставился побочно, внутри первого запуска пути домой; теперь это отдельное действие со своим враппером install-wireguard.cmd и своей точкой: зелёная — программа на месте, красная — нет. Портативным WireGuard не бывает: туннель держит служба Windows, а сетевой адаптер — драйвер, поэтому установщик и права администратора.

Ряд кнопок стоит на разделителе панелей. Раньше он держался центра окна и строка состояния налезала на кнопки: во время передачи поверх F11 и F12 шли проценты и скорость. Теперь середина ряда совпадает с разделителем файловых панелей и пересчитывается, когда разделитель тащат мышью, а состояние живёт в своей колонке справа и при нехватке места обрезается многоточием.

Видно, какая панель активна. Направление задаёт та панель, где стоит курсор, а понять это было неоткуда. Теперь её рамка подсвечена морским, и активной панель становится от любого касания: щелчка по списку, по кнопке источника, по дорожке пути или по пустому месту.

Диалоги стали своими. Системный MessageBox рисует Windows, и тёмным он не бывает: посреди тёмного окна вспыхивало белое. Подтверждения и ввод имени теперь идут в своём окне в цветах программы — заодно ушёл InputBox из VisualBasic, который выглядел вовсе чужим. Заголовок самого окна тоже потемнел: его рисует не приложение, а система, и просит об этом атрибут DWM.

Панель не пересобирается зря. Автообновление раз в две секунды заменяло список целиком: слетали галочки, курсор и прокрутка, а копирование после этого жаловалось «нет объектов для копирования». Теперь панель сверяет состав с прежним и не трогает список, пока ничего не изменилось; когда изменилось — переносит отметки по именам.

Песочные часы остались только у удалённых источников. Чтение локального каталога занимает доли миллисекунды, а курсор ожидания мигал при каждом автообновлении и выглядел как тяжёлая работа.

1.1.0 — 5 сентября 2026

Окно стало файловым менеджером. Две панели видны всегда, а лента режимов сверху меняет только то, что в них открыто и какой ряд кнопок показан. Так кнопка перестаёт быть заклинанием: нажимая «разложить ключи», видно слева эталон, справа профиль, а после прогона — что там изменилось.

Один транспорт на всё. Локальный диск, машина по ssh и корзина R2 читаются одним rclone, поэтому копировать можно между любыми двумя сторонами. Замер на живом: 2 ГБ на стационар ушли за 11,6 с (176 МБ/с), обратно за 10,1 с (203 МБ/с) — около двух третей от SMB, зато с докачкой, повтором при обрыве и сверкой. Копирование идёт через ту машину, где открыто окно; дома это домашняя сеть через роутер, SECOND VPS не участвует.

Очередь. F5 и F6 кладут отмеченное в очередь, а не запускают операцию сразу. Приёмник запоминается в момент добавления — можно набрать объекты в разных папках и разных источниках, и всё уедет в одно место. Задачи идут по одной: параллельные передачи поделили бы канал и перемешали вывод.

Клавиши как в файловом менеджере: пробел отмечает строку и ведёт курсор ниже, Enter входит в папку, Backspace поднимает на уровень, F2/F5/F6/F7/F8 — переименовать, копировать, перенести, создать папку, удалить.

Видно, что происходит. Полоса выполнения внизу, проценты в заголовке окна и в панели задач, скорость и оставшееся время в строке состояния, строка rclone в терминале раз в пять секунд. Панели перечитываются сами: локальные раз в две секунды, удалённые — после операции, кнопкой и при возврате в окно.

Сироты больше не живут дольше окна. Осиротевший rclone от прошлого запуска продолжал качать молча — удалённая руками папка появлялась снова. Теперь процессы этой копии программы снимаются при закрытии окна, по кнопке СТОП, а при старте окно предупреждает, если такой процесс уже висит.

Раскраска строк взята из темы Total Commander: цвета читаются из config\colors\AudionDark.ini (там они в десятичном BGR), расширения расписаны в программе — в теме их нет, там ссылки на поисковые шаблоны TC. Папки жёлтые, как в проводнике.

Мелочи, которые чинились по ходу. Корень диска пишется с косой чертой: «E:» Windows понимает как текущую папку на этом диске, и вход на диск уводил в каталог программы. У ssh корень «/» — не то же, что пустой путь: первый показывает диски машины, второй — домашнюю папку. Прогресс rclone печатается только с --stats-log-level NOTICE, иначе его не видно вовсе. Полосы прокрутки и полоса выполнения нарисованы свои — системные светлые в тёмном окне выглядят заплатой.

1.0.0 — 5 сентября 2026

Первая сборка. Проект собран из того, что годом раньше расползлось по двум чужим папкам: сценарии зеркала лежали вперемешку с самими зеркалами, снимок приватных архивов делал публикатор, а ключи к корзине зеркало занимало у соседа.

Программа отделена от данных. Audion Sync Tools держит окно, сценарии, клиент туннеля, доступ к машинам, свой rclone и свои ключи к корзине. Соседняя Audion Backup осталась хранилищем: снимки, шесть зеркал, склад ключей, токены — и ни одного исполняемого файла. Путь к данным считается от расположения программы и задаётся ключом -Root; буква диска не зашита нигде, поэтому на машине, где инструменты живут на другом диске, править нечего.

Своё, а не соседское. Раньше Sync-AudionBackup.ps1 брал rclone.exe и ключи R2 у публикатора — «чтобы не держать вторую копию тех же ключей». Цена экономии: без публикатора рядом зеркало не поднималось вовсе, а подниматься оно должно на пустой машине первым. Теперь у программы свой бинарник в Tools\rclone и свои ключи в config\rclone, а Engine\BackupRclone.psm1 знает о них ровно три вещи: где искать, чем настраивать, как звать.

Снимок Build-стека переехал из публикатора. backup.cmd и Backup-AudionArchives.ps1 теперь здесь; в публикаторе (версия 1.8.0) кнопка «БЭКАП» убрана. Роли разведены по направлению действия: публикатор занимается тем, что уходит наружу, а всё, что кладёт и забирает копии, собрано в одном месте. Сама операция не изменилась ни на строку.

Окно. Три трети с перетаскиваемыми полосами: слева папки зеркала и состояние, посередине машины, справа терминал во всю высоту. Кнопки не делают работу сами — каждая зовёт тот же сценарий, что и человек из консоли, поэтому окно и врапперы не расходятся. Подписи английские, подсказки русские, задержка подсказки 1500 мс — как у оркестратора, у которого взят каркас; механика дочернего процесса взята у публикатора.

Точки состояния. У кнопок машин четыре значения и ни одного «наверное»: зелёная — проверено и отвечает, жёлтая — заведено, но не поднято, красная — проверено и молчит, серая — проверять нечего. Службы читаются сами раз в тридцать секунд, сеть пробуется кнопкой и один раз при открытии. Пробы уходят разом и ждутся таймером окна: шесть подключений подряд заморозили бы окно на три секунды. Адреса берутся из того же targets.json, что читают врапперы, — второго списка адресов в программе нет.

Бейджи в шапке показывают папку данных и корень выпуска. Второй желтеет, если в выбранной папке нет приватных архивов: BACKUP на такой откажется, и увидеть это лучше до нажатия. Длинные пути режутся с головы — различает их хвост.

Ключи. export-keys.cmd собирает ключи машины в Tunnel\Export, import-keys.cmd раскладывает их по трём местам, где их ищут программы: профиль, config\rclone, core.sshCommand зеркал. Ключом считается файл с парным .pub — так переносятся любые имена. Приватным копиям сразу сводятся права: ключ, доступный кому-то кроме владельца, ssh молча отвергает, и это самая частая причина того, что на новой машине «ничего не работает». Права чинятся и в источнике: маршруты, написанные установщиком туннеля, ссылаются в склад.

Пути чинятся сами. Импорт переписывает в ~\.ssh\config только те пути, которые никуда не ведут, и не трогает рабочие строки. На переезде программы это сработало на первом же прогоне: ProxyCommand показывал на прежнее место cloudflared, и был исправлен без единой правки руками.

Значок и запуск. Start.exe собирается компилятором из состава Windows (Engine\Launcher), рядом лежит Build-Icon.ps1. Каждый кадр значка рисуется в своих пикселях, а не ужимается из большого: в шестнадцати точках ореол превращается в грязь. Свечение остаётся только у кадров от 64 и выше.

All projects