WEB-469 · Дефект · — · web
P1 [бэкапы Hetzner, WEB-082]: WAL-архив стоял с 01.09 19:07Z (порченый .partial после переполнения диска), base-бэкапы падали 11 часов подряд, локальный стейджинг /var/lib/hetzbk/base вырос до 59 ГБ (диск A1 100%), артефакты релизов на Storage Box отстают на 10 посадок
Закрыт
P1 · важно
ведёт: —
эпик: WEB-282
Суть
P1 [бэкапы Hetzner, WEB-082]: WAL-архив стоял с 01.09 19:07Z (порченый .partial после переполнения диска), base-бэкапы падали 11 часов подряд, локальный стейджинг /var/lib/hetzbk/base вырос до 59 ГБ (диск A1 100%), артефакты релизов на Storage Box отстают на 10 посадок
ФАКТЫ (02.09 07:50Z, A1):
- hetzbk-wal-stream: pg_receivewal упёрся в /var/lib/hetzbk/wal-raw/000000010000000100000046.partial (4718592 байт, first page magic=0000) — остался от переполнения диска 01.09 ~20:01; сервис крутился в цикле «disconnected; waiting 5 seconds», WARN «partial WAL publication skipped». Последний опубликованный сегмент на Storage Box — …45 (01.09 19:07Z).
- hetzbk-base: каждый час FATAL rc=12 «base start WAL was not committed … waited=601s» (ждёт коммита стартового сегмента от wal-stream) — с 01.09 22:18Z по 02.09 07:18Z. Последний base на Storage Box: base-20260901T180039Z; манифест manifest-20260901T181824Z.
- Стейджинг: /var/lib/hetzbk = 65 ГБ (base 59 ГБ = 11 × 5.1 ГБ непринятых локальных копий; restore 4.1 ГБ; wal-cipher 1.3 ГБ). Это и было причиной диска 100% на A1 (05:10Z), который убил все волны и дал paid 503. См. память hetzbk-local-staging-unbounded.
- /home/app-artifact на Storage Box: последние артефакты релизов от 25.08 (fd5e1b7/c68f701/446bcbf) и l59gd (27.08); l85…l89 отсутствуют. RESURRECTION-RUNBOOK.md там от 25.08.
СДЕЛАНО 07:50–07:52Z: .partial перенесён в /var/lib/hetzbk/quarantine, wal-stream перезапущен — стриминг возобновился с 1/46000000 (слот hetzbk_wal удерживал WAL, потерь нет), догоняет до текущего 2/4E; локальные base-* кроме двух последних удалены (диск 67%); ручной запуск hetzbk-base после догона.
ОСТАЛОСЬ (волна): (1) hetzbk-wal-stream должен сам карантинить невалидный .partial и продолжать, а не крутиться в цикле; (2) hetzbk-base: при неудаче удалять свой локальный WORK-каталог; локальная ретенция стейджинга (max 2 base); алерт в TG/OPS при 2 подряд FATAL; (3) публикация артефакта релиза на Storage Box как шаг land-l8X.sh (unpack) + обновление RESURRECTION-RUNBOOK; (4) мониторинг «возраст последнего base/WAL на Storage Box» в /api/ops или cron.
Связь: WEB-082 (Hetzner-контур), WEB-282 (эпик миграции), WEB-470 (репетиция аварии). Память: hetzbk-local-staging-unbounded, hetzner-primary-backup-decision, a1-disk-cleanup-standing-order.
Починено в
hetzbk-1255-cccd2ba6
Лента
2026-09-02T08:24:59.693Z · Fable[02.09 08:50Z Фабл] Состояние: pg_receivewal догнал текущую позицию (raw до 2/51), публикатор (gpg+sftp) идёт по бэклогу ~16 с/сегмент — на 08:24Z дошёл до 1/BD, до текущего 2/51 ~40 мин. hetzbk-base 08:01 снова FATAL rc=12 (ждёт коммита стартового сегмента 2/4F, которого публикатор ещё не достиг) — ожидаемо; монитор координатора запустит base, как только появится 000000010000000200000050.gpg.ready, и проверит новый base на Storage Box. Волна 1162-web469hetzbk (самолечение partial, ретенция стейджинга, age-мониторинг, публикация артефактов) бежит. Артефакт l89 + att-build.json на Storage Box уже лежат.
2026-09-02T09:14:10.674Z · Fable[02.09 09:15Z Фабл] Контур восстановлен целиком: публикатор WAL догнал текущий сегмент, hetzbk-base по таймеру 09:00Z прошёл — на Storage Box появился base-20260902T090057Z (предыдущий был base-20260901T180039Z, т.е. 15 часов без base). Артефакт l89 + att-build.json и провенанс Pi лежат в /home/app-artifact. Остаток тикета: приёмка 1174 кандидата cc9ac14f6b (самолечение partial, ретенция стейджинга, age-check, publish-artifact, установщик) — сейчас заморожена из-за перегрузки A1, разморозка по нагрузке; затем установка скриптов на A1 координатором.
2026-09-02T09:44:53.889Z · Fable[02.09 09:50Z Фабл] Приёмка 1174-accweb469hetzbk: FAIL — кандидат cc9ac14f6b оказался параллельной реализацией WAL/restore, а не эволюцией живых /usr/local/libexec/hetzbk-*; README без явного назначения юнитов в /etc/systemd/system; retention override может превысить кап стейджинга. Доработка 1182-web469hetzbk2 (патч живых скриптов в репо infra/hetzbk/, diff по функциям, жёсткий кап ≤2 base) → ре-приёмка → установка координатором.
2026-09-02T09:57:08.698Z · Fable[02.09 10:55Z Фабл] НАХОДКА репетиции (первый прогон restore на A2 упал): /usr/local/libexec/hetzbk-restore после `WAL coverage PASS` качает ВСЕ wal-строки манифеста (цикл `while read … kind=wal … remote_get`, строки ~337–349), а не диапазон base_start..target; манифест содержит старые сегменты (0000000100000000000000F4…), которые ретенция уже удалила со Storage Box → `File … not found` → восстановление невозможно из последнего base без ручной правки. На A2 копия скрипта пропатчена (skip сегментов < BASE_START_SEG и ≥ PARTIAL_SEGMENT; оригинал сохранён как hetzbk-restore.orig-a1-20260902), живой A1 не тронут; перезапуск восстановления идёт (лог restore-rehearsal-20260902b.log). Для WEB-469 (волна 1182/приёмка): перенести фикс в репо + тест «манифест с удалёнными старыми сегментами → restore проходит»; также манифест не должен перечислять сегменты, удалённые ретенцией (или ретенция должна публиковать новый манифест).
2026-09-02T09:58:21.010Z · Fable[02.09 11:00Z Фабл] 1182-web469hetzbk2 сдан (f21cddb55b): infra/hetzbk/ как эволюция живых скриптов (function-level diff live→репо), README с явными путями, кап стейджинга. Ре-приёмка 1186 с добавленным пунктом из репетиции (restore качает весь манифест) — если не закрыт, NO-GO и ещё одна доработка. Бандл mirrors/lines/web469hetzbk2-1182-f21cddb55b.bundle.
2026-09-02T10:19:56.432Z · Fable[02.09 11:55Z Фабл] Ре-приёмка 1186-accweb469hetzbk2: NO-GO — (1) restore (infra/hetzbk/bin/hetzbk-restore:343) по-прежнему качает удалённый ретенцией WAL вне base_start..target (ровно то, на чём упала репетиция); (2) локальная ретенция удаляет неопубликованный base. Остальное принято. Доработка 1190-web469hetzbk3 → ре-приёмка → установка на A1 (и снятие патча-времянки на A2).
2026-09-02T10:34:10.594Z · Fable[02.09 12:20Z Фабл] 1190-web469hetzbk3 сдан (26946ab115: restore качает только base_start..target; ретенция не трогает неопубликованный base) → ре-приёмка 1192 (те же 6 пунктов + обязательные 7/8). После GO: установка infra/hetzbk на A1 координатором (замена живых скриптов с бэкапом), снятие времянки на A2, повтор репетиции фазы 1b с секундомером.
2026-09-02T10:50:09.018Z · Fable[02.09 12:50Z Фабл] Ре-приёмка 1192-accweb469hetzbk3: GO (26946ab115) — restore ограничен base_start..target, ретенция бережёт неопубликованный base и капнута ≤2, самолечение partial, age-check, publish-artifact, установщик. Далее: установка на A1 координатором (бэкап живых скриптов → копирование → рестарт hetzbk-wal-stream → контроль следующего base), то же на A2 (снять времянку), затем повтор репетиции 1b. В репо — с l91.
2026-09-02T10:51:52.530Z · Fable[02.09 12:55Z Фабл] УСТАНОВЛЕНО: A1 — infra/hetzbk (26946ab115) через install.sh (бэкап живых скриптов/юнитов в /home/ubuntu/ops-backups/hetzbk-live-20260902T1050Z), hetzbk-wal-stream перезапущен (стрим с 2/57), таймер hetzbk-age-alert включён; A2 — тот же install.sh (restore = новая версия, времянка снята, старый патч сохранён как hetzbk-restore.a2patched-20260902). Хвост: age-alert считает возраст WAL по манифесту (раз в час) → при низком трафике wal_age 2390 с > 900 → ложный ALERT (пока только в журнал: HETZBK_NOTIFY_PATH не задан). Нужно: возраст по wal-partial указателю (каданс 240 с) или порог ≥ интервала манифеста; подключить notify в TG после. Проверить следующий hetzbk-base 11:01Z.
2026-09-02T11:22:07.817Z · Fable[A1 11:20 Фабл] Первый часовой base под v3 прошёл: /home/walg-nc/hetzbk-prod-a1/base/base-20260902T110016Z на Storage Box (предыдущий base-20260902T100044Z), локальный стейджинг ограничен (2 base). Итого контур: wal-stream живой, base каждый час, ретенция v3, hetzbk-age-alert включён (ложный ALERT при низком трафике — отдельный хвост). Следующее: фаза 1b репетиции (скрипт hetzbk-rehearse + шифрованный env-пакет на Storage Box) — волна 1196-drrehearsal1b на M4 от ветки web469hetzbk3-1190.
2026-09-02T11:53:49.655Z · Fable[A1 11:55 Фабл] Хвост «ложный ALERT hetzbk-age-alert при низком трафике» → волна 1199-hetzbkagealert на A1 (ветка от web469hetzbk3-1190): метрика отставания WAL по LSN вместо возраста файла (idle → OK), живость wal-stream и возраст base как настоящие алерты, нотификация только при смене состояния, тесты в infra/hetzbk/tests. После DONE → приёмка → l91 (вместе с v3).
2026-09-02T12:14:41.415Z · Fable[A1 12:15 Фабл] Волна 1199-hetzbkagealert сдана: коммит cea6cc300d437efac572325a6f63387285a37578 (только infra/hetzbk/). hetzbk-age-alert стал позиционным: последний удалённый wal/*.ready или wal-partial/*.latest → стартовый LSN сегмента → pg_wal_lsn_diff() с текущим LSN сервера (pg_current_wal_lsn на primary / pg_last_wal_receive_lsn на standby, SELECT-only через HETZBK_PG*/HETZBK_PGPASSFILE); freshness-ALERT только при продвижении LSN между проверками (state-файл age-alert.state c observed_lsn); отдельно живость hetzbk-wal-stream.service + pg_receivewal и возраст последнего base.ready; вывод одной строкой status=OK|ALERT reason=… lag_bytes=… last_wal=… base_age=…, exit 0/2; HETZBK_NOTIFY_PATH только при смене состояния. Тесты infra/hetzbk/tests/test_hetzbk.sh: 8 passed (idle→OK, lag→ALERT, мёртвый stream→ALERT, stale после продвижения LSN, повтор без нотификации). Новые ключи в hetzbk.env.example. Приёмка 1202-acchetzbkagealert (A1: математика LSN, standby, pg_unreachable→ALERT, секреты, совместимость с install.sh v3). Cherry-pick в l91-candidate = f8d9e996.
2026-09-02T12:31:22.820Z · Fable[A1 12:35 Фабл] Приёмка 1202-acchetzbkagealert: **NO-GO** — при ошибке psql (exit 7) скрипт под set -u падает с rc=1 и пустым stdout (lag_bytes не объявлен до успешного diff, строки 166/215/252), вместо `status=ALERT reason=pg_unreachable` rc=2. Остальное (LSN-математика, standby, state, секреты, тесты 8/8) подтверждено. Корректировка — волна 1208-hetzbkagealert2 (поверх cea6cc30). Коммит f8d9e996 снят с l91-candidate до GO.
2026-09-02T12:40:28.621Z · Fable[A1 12:55 Фабл] Корректировка 1208-hetzbkagealert2 сдана: bdd668cc928ca150f8b39c7c95d299e98373b2b7 (поверх cea6cc30): все поля строки инициализируются заранее (lag_bytes=- …), ошибка psql → psql_failed=1 → reason=pg_unreachable (без wal_position_unavailable), state/notify/stdout/rc=2 гарантированы даже при psql exit 7; тест на этот путь добавлен (+27 строк в test_hetzbk.sh). Повторная приёмка 1209-acchetzbkagealert2 (A1). Ветка на A2 (nc-build) — cherry-pick в l91 после GO.
2026-09-02T12:51:06.730Z · Fable[A1 13:15 Фабл] Повторная приёмка 1209-acchetzbkagealert2: **GO** (psql exit 7 → rc=2, status=ALERT reason=pg_unreachable, state/notify; остальное без изменений). Линия cea6cc30+bdd668cc cherry-pick-нута в l91-candidate (b6995809, 3ff9c54d). После посадки l91: install.sh v3 обновит /usr/local/libexec/hetzbk-age-alert; ручная проверка от hetzbk — по отчёту ACCHETZBKAGEALERT2-REPORT.md §4; добавить в /etc/hetzbk/hetzbk.env ключи HETZBK_MAX_WAL_LAG_BYTES/HETZBK_MAX_WAL_AGE_SEC/HETZBK_MAX_BASE_AGE_SEC (дефолты в примере).
2026-09-02T14:12:25.986Z · Fable[A1 14:12 Фабл] ПОСАЖЕНО l91 на прод A1: release arm64-l91-20260902T140416Z, run l91-9ad68bc2, sourceCommit 9ad68bc261c833e792bc17523245975e15f48612, артефакт sha 96b3466b…dc3f; ready TRUE (boot/database/release/drain ok), paid TRUE enforce_ready, public 200, live-sha 9ad68bc2; SIP-стек перезапущен (readiness 200/200, монитор аренды пережил рестарт: 2 poll-failed, LOST=0). Откат: land-l90 run/l90-26da36fa (nc-a1.service.bak-l90). infra/hetzbk (v3 + age-alert + репетиция 1b, слияние 8879df52 GO) теперь в дереве l91 — следующий шаг: install.sh на A1/A2 из дерева l91 (обновит hetzbk-age-alert, добавит hetzbk-env-pack.timer), ключи HETZBK_MAX_* в /etc/hetzbk/hetzbk.env.
2026-09-02T14:40:27.499Z · Fable[A1 14:40 Фабл] age-alert на ЖИВОМ A1 после установки из l91: `status=ALERT reason=pg_unreachable,base_old lag_bytes=- last_wal=sftp> get …` — три дефекта под реальной средой (psql не по HETZBK_PG_BIN/PATH systemd; sftp-прогресс попадает в last_wal; base_age=1 при возрасте ~20 мин), при этом psql под hetzbk с PATH работает (2/728F90A8). Свидетельство: /home/ubuntu/ops-backups/hetzbk-age-alert-raw-20260902.out. Корректировка 1237-hetzbkagealert3 (A1, поверх слияния 8879df52) с тест-шимами на реальные форматы вывода + SuccessExitStatus=2. Класс: приёмки на моках зелёные, реальная среда — нет (fixture-green).
2026-09-02T15:12:53.357Z · Fable[A1 15:14 Фабл] Корректировка 1237-hetzbkagealert3 сдана: f2f0893eb1 (поверх слияния 8879df52): age-alert через ${HETZBK_PG_BIN}/psql + PGPASSFILE; remote_get/remote_sftp без sftp-мусора; base_age в секундах от published_at/имени base; unit SuccessExitStatus=2; env-pack: HETZBK_ENV_FILES (colon-list, дефолт с реальными путями A1, отсутствующие → WARN), line = имя run-каталога, unit User=root. Приёмка 1250-acchetzbkagealert3 (A1) с шимами реальных форматов вывода. После GO: install.sh на A1/A2, снять ручные заплатки (symlink apply.conf, копия flip-cron.secret, drop-in user.conf) → l92 (ops-пакет). 2026-09-02T16:10:12.325Z · Fable[A1 16:20 Фабл] Закрываю: (1) 02.09 утро — WAL-архив восстановлен (порченый .partial после переполнения диска удалён, слот держал, догнал без потерь), стейджинг с ретенцией (память hetzbk-local-staging-unbounded); (2) пакет hetzbk v3 → линия hetzbkagealert4-1255 (cccd2ba6): age-alert по позиции, классификация недоступного PG, env-pack с обязательными путями, install.sh (13 скриптов, 11 units) — приёмка 1258 GO, установлен на A1 и A2 16:00, age-alert=OK healthy, env-пакет env-l91-9ad68bc2-20260902T155436Z на Storage Box; линия в l92-candidate (aac54827). Остаток по бэкапам живёт в WEB-470 (репетиция с секундомером, тёплая копия base — волна 1257). Отчёты: A1 /home/ubuntu/waves/{HETZBKAGEALERT4,ACCHETZBKAGEALERT4}-REPORT.md. 2026-09-03T01:12:17.622Z · Fable[A1 Фабл] Приёмка 1421-acchetzbkwarmbase6 = GO (A1, независимая, shellcheck 0.11 по 20 файлам rc=0, app-stage harness с реальным таймингом). Коммит 4b667525 (hetzbk круг 6). Далее: install.sh на A2 → репетиция hetzbk-rehearse на линии l94-b1962b8d (ожидаем REHEARSAL PASS с t_app_start/t_ready/rto_total_seconds) → install на A1.
2026-09-03T01:27:17.879Z · Fable[A2 10:57 Фабл] Репетиция r1c-…011307Z на hetzbk-6: RESTORE PASS (t_restore 273 c, t_pg_start 227 c), app-стадия FATAL rc=36 — причина в окружении A2, не в коде: /etc/hetzbk/hetzbk.env держал явный HETZBK_REHEARSAL_APP_COMMAND на run/l93 (нет в env-pack l94 → sh: not found), плюс rehearsal-redis падал: 127.0.0.1:6379 занят ssh-туннелем A2→A1. Исправлено: явная команда убрана (source=env-pack), HETZBK_REHEARSAL_REDIS_PORT/URL=6390; бэкап hetzbk.env.bak-r1c-*. Перезапуск r1c-…012646Z идёт.
2026-09-03T01:42:05.251Z · Fable[A2 11:10 Фабл] r1c-…012646Z (env-pack, redis 6390): RESTORE PASS 279 c; app FATAL rc=36 снова — теперь раскладка: rehearse распаковывает артефакт в releases/<имя артефакта>.tar.gz, а inner-обёртка из env-pack exec-ит releases/arm64-l94-20260902T232029Z/server.js (имя каталога прода); плюс в env-pack нет shared/run/flip-cap.secret и flip-cron.secret. Третья находка одного класса → круг 7 = контракт публикации (release_dir/start_wrapper/required_files в att-build, fail-closed env-pack, preflight до restore). Волна 1443-hetzbk7 (A1, Luna high) в очереди.
2026-09-03T03:26:14.629Z · Fable[A1 Фабл] Волна 1443-hetzbk7 сдана: коммит 39a42923 (контракт публикации release_dir/start_wrapper/required_files, fail-closed env-pack, preflight до restore). Приёмка 1461 (A1, Sol high) в очереди; при GO — install на A2, перепубликация l94 с новым att-build, репетиция r1c, затем install на A1.
2026-09-03T04:39:14.701Z · Fable[A1 Фабл] Приёмка 1461-acchetzbk7 = NO-GO (39a42923): контракт публикации/env-pack/rehearse PASS; блокеры — SC2034 ×2, env-pack не сверяет release_id att-build с --line, нет fallback для legacy att-build, снята явная ветвь HETZBK_REHEARSAL_APP_COMMAND. Круг 8 = волна 1474 (A1, Luna high). Решения по контракту: legacy att-build не поддерживать (fail-closed + перепубликация l94 новым att-build — миграционный порядок), explicit override восстановить.
2026-09-03T05:15:09.091Z · Fable[A1 Фабл] Волна 1474-hetzbk8 сдана: коммит e0e109db. Приёмка 1485 (A1, Sol high) в очереди; при GO — install A2, перепубликация l95 новым att-build, репетиция.
2026-09-03T05:49:06.518Z · Fable[A1 Фабл] Приёмка 1485-acchetzbk8 = GO (Sol high): shellcheck 21/21, release_id fail-closed, legacy att-build fail-closed с перепубликацией, explicit override восстановлен. Коммит e0e109db (круг 8). Далее: install на A2 и A1, перепубликация l95 новым composite att-build (release_dir/start_wrapper/required_files), env-pack, репетиция r1c на A2.
2026-09-03T05:54:58.811Z · Fable[A2 Фабл] Круг 8 раскатан: A1 install + l95 перепубликован composite/2 + env-pack; A2 install + env. Живая репетиция l95: FATAL rc=35 «preflight port_env is missing or invalid: PORT» — preflight требует PORT в env-паке, а на проде PORT в unit; репетиция и так ставит порт сама. На A2 hotfix (die→WARN, бэкап .bak-portenv), репетиция перезапущена; штатный фикс = волна 1495-hetzbk9 (Luna low).
2026-09-03T05:56:09.986Z · Fable[Фабл] Уточнение: rc=35 на репетиции — не контракт, а потерянный дефолт HETZBK_REHEARSAL_APP_PORT (круг 8); hotfix на A2 откачен, задан HETZBK_REHEARSAL_APP_PORT=3012 в env, репетиция перезапущена. Круг 9 (1495) = вернуть дефолт/ясный fail-closed + README.
2026-09-03T06:00:37.155Z · Fable[A1 Фабл] Волна 1495-hetzbk9 сдана: коммит 717b90e1 (порт репетиции: дефолт/fail-closed, port_env = имя). Приёмка 1497 (A1, Sol medium) в очереди.
2026-09-03T06:06:07.537Z · Fable[A2 Фабл] Живая репетиция l95 (круг 8 + порт): preflight и restore base PASS, но rc=96 «partial B3 does not follow complete B1» — гонка: список архива снят в начале, за 9 мин restore продюсер закоммитил B2/B3; на Storage Box B0..B3 на месте, разрыва нет. Круг 10 = волна 1498 (Luna medium): повторный список перед выбором partial, докачка .ready-сегментов. Репетиция перезапущена (шанс пройти, если в окно restore не придёт новый сегмент).
2026-09-03T06:08:48.943Z · Fable[A1 Фабл] Приёмка 1497-acchetzbk9 = NO-GO (717b90e1): портовая матрица PASS, но B1 — сломан ранее принятый JSON-контракт отчёта репетиции, B2 — не обновлён A2 example env. Круг 10 (1498, гонка списка архива) уже бежит от 717b90e1 → круг 11 сложит B1/B2 поверх результата 1498.
2026-09-03T06:16:14.157Z · Fable[A2 Фабл] Повтор репетиции l95: снова rc=96, «complete archive» опять заканчивается на B1, хотя на Storage Box уже B2..B7 (.ready) — значит restore берёт хвост complete-архива из ЧАСОВОГО манифеста (051241Z), а partial-указатель — из живого wal-partial → под нагрузкой (сегмент каждые 1–3 мин) всегда «разрыв». Уточнение для круга 10 (1498, бежит): после манифеста дочитывать live wal/ (сегменты > хвоста манифеста с .ready) и только потом выбирать partial.
2026-09-03T06:16:39.769Z · Fable[A1 Фабл] Волна 1498-hetzbk10 сдана: коммит b20cd73c (повторный список архива перед partial, докачка .ready). Круг 11 (1499: JSON-контракт отчёта + example env) поставлен поверх; приёмка обоих кругов вместе после 1499.
2026-09-03T06:22:29.794Z · Fable[A1 Фабл] Волна 1499-hetzbk11 сдана: коммит 560f87e4 (JSON-контракт + example env). Приёмка кругов 10+11 = 1503 (A1, Sol high) в очереди.
2026-09-03T06:40:04.868Z · Fable[A1 Фабл] Приёмка 1503-acchetzbk1011 = NO-GO (560f87e4): докачка хвоста архива и порт/JSON/example PASS; блокеры — в JSON нет run_id; реальный gap фаталится без обещанной повторной проверки. Круг 12 = волна 1506 (Luna low; стартует после окна установки wave-user).
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \
-d '{"issueId":"WEB-469","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-02T16:10:12.207Z