Backup и recovery: проект механизмов
Статус: B1 реализован (2026-10-02, ADR 0054): ручная согласованная копия во встроенный vault на диске/NAS, проверка и восстановление в пустую цель через операторский CLI. B2 backend реализован (2026-10-02, ADR 0056): агент с расписанием, retention и prune, предупреждения, метрики, API /api/v1/backup, SDK и arkvoryctl backup. Установщики B2 реализованы (2026-10-02, ADR 0057): агент — третья служба systemd, WinSW и Compose, vault подключает arkvory configure --backup-vault <dir> --init-vault с проверкой и откатом. Консоль B2 реализована (2026-10-02): раздел «Резервные копии» с состоянием, предупреждениями, запуском копии и проверки, точками, заданиями и планом. Остальное в документе — проект следующих этапов. Правообладатель: Ian Panaev, бренд ProAnimaStudio.
Задача — получать самостоятельные проверяемые точки восстановления Arkvory без остановки обычной раздачи и приёма файлов, а восстанавливать их через понятный мастер даже при полной потере исходного сервера. Исходный масштаб: 4 ТБ, объекты десятков гигабайт и больше. Нельзя свести задачу к копированию каталога или запуску pg_dump: БД, неизменяемые blobs, конфигурация и автоочистка должны согласовать один состав копии.
Что уже есть и чего нет
Есть (B1): операторский CLI arkvory-backup (apps/backup, npm run backup -- …) с командами vault init, capture, list, verify [--deep], restore; durable capture jobs с idempotency key, lease и fencing generation; постоянные backup pins и барьер допуска unlink, которые соблюдают online GC и offline repair; логический экспорт всех таблиц Arkvory из одного snapshot T (реестр таблиц, NDJSON, SHA-256 и число строк); встроенный файловый vault с vault.json, дедупликацией blob по неизменяемому ID и атомарной публикацией точки; структурная и глубокая проверка; restore в пустую БД и пустой storage с версионированной нормализацией и отчётом. Миграция 25. Эксплуатация: CORE_RUNBOOK.
Есть (B2 backend, миграция 26): агент arkvory-backup agent с единственным активным экземпляром (lease, fencing, heartbeat с местом тома vault), ежедневное расписание в явном IANA-поясе с правилами перехода времени и одним догоняющим запуском, retention 7/4/6 с закреплением и защитой новейшей точки, forget и prune под эксклюзивной блокировкой vault, структурная проверка после каждой копии и еженедельная глубокая, каталог точек как кэш vault, предупреждения с машинными кодами, метрики и правила оповещения, API /api/v1/backup с системными правами backup.read/backup.manage, SDK client.backup и arkvoryctl backup, ограничение полосы копирования. Эксплуатация: CORE_RUNBOOK.
Есть (B2, установщики): служба агента arkvory-backup / Arkvorybackup / сервис Compose backup с автозапуском и восстановлением, как у worker, вне readiness API. Агент останавливается перед переключением релиза и запускается после API и worker; его отсутствие видно предупреждением установщика. arkvory configure --backup-vault <dir> [--init-vault] и --backup-vault-off проверяют каталог до изменений, выдают доступ учётной записи службы (drop-in systemd, ACL LocalService, bind mount Compose), перезапускают только агента и требуют его heartbeat с этим vault, при сбое восстанавливают прежнюю настройку (ADR 0057).
Есть (B2, консоль): раздел «Резервные копии» на RU/EN показывает состояние агента и vault, предупреждения и возраст последней точки, запускает копию и полную проверку с idempotency key, закрепляет точки, применяет retention только после предпросмотра и меняет план с CAS по ревизии. Права backup.read/backup.manage проверяет сервер; восстановление остаётся командой оператора (поведение консоли).
Есть (B3, шифрование): vault шифруется AES-256-GCM по умолчанию, ключи в слотах, recovery kit, проверка ключей и ротация доступа (ADR 0070). Нет: S3/restic, мастера восстановления в консоли, restore drill как отдельного статуса, controlled cutover, PITR и HA backup. Перед сменой схемы установщик сам снимает и проверяет точку (ADR 0059); ручной --backup-record для установок без vault по-прежнему проверяет только существование файла оператора. Восстановление ревизии asset в каталоге не заменяет восстановление потерянной площадки. Репликация также решает другую задачу.
Сценарии интерфейса: BACKUP_UX. Решение: ADR 0037. Работающий API — /api/v1/backup (ADR 0056, карта API); таблица кандидатов ниже остаётся проектом следующих этапов.
Продуктовый договор
- Обычные backups сохраняют опубликованное состояние на момент T, включая каталог, metadata, метки, манифесты/вложения, историю и необходимые им blobs. Новые публикации после T попадут в следующую копию.
- Незавершённые uploads, открытые TCP-сеансы и выполнявшиеся jobs не обещаем продолжить из disaster backup. Recovery явно отменяет их и приводит квоты к восстановленному набору; клиент получает необходимость начать новую загрузку. Это не штатное resume при кратком сетевом сбое.
- Скачивания и публикации продолжаются. Допустимы дополнительный I/O и временное удержание удаляемых bytes; UI показывает нагрузку и объём, удерживаемый backup. Нулевое влияние на latency не обещается.
- Копия завершена только после согласованного commit в backup vault. Результат проверки байтов и результат пробного восстановления имеют отдельные даты и статусы.
- Предыдущая исправная копия не удаляется из-за неудачного нового запуска, переполнения или сокращения retention. По умолчанию сохраняется минимум одна завершённая точка.
- Восстановление по умолчанию создаёт новый изолированный экземпляр. Автоматической перезаписи работающей БД, root или сетевого адреса нет. Переключение пользователей — отдельная операция после проверки.
- Можно открыть мастер восстановления с другого компьютера, имея адрес vault, доступ и recovery key. Исходные API, БД, DNS и пользовательская сессия Arkvory для этого не нужны.
Места хранения и движок
Первоначально проектируем два адаптера назначения: отдельный диск/смонтированный NAS и S3-совместимый vault. Один план относится к одному источнику и одному vault; несколько планов дают независимые копии с собственными датами и результатами. Копирование готовой точки во второй vault — последующее расширение; нельзя показывать его успешным по результату первого назначения.
B1 использует встроенный файловый vault (ADR 0054), шифрование добавлено поверх него без chunk store и дедупликации (ADR 0070); узкий порт vault оставлен для последующих адаптеров. Для шифрованного хранения с дедупликацией в следующих этапах рассматривается restic за узким адаптером, а не собственный формат шифрования и упаковки. Arkvory владеет согласованностью, manifest, правами, job state и UX. Выбор окончательно принимается после spike с Windows, Linux, NAS и выбранным S3. Версия binary и checksum будут закреплены; установщики должны поставлять компонент, лицензии и SBOM. Shell-команды пользователя и незакреплённый download latest запрещены.
Копии должны экономить передачу неизменившихся данных, при этом каждая видимая точка описывает полный восстанавливаемый набор. UI различает логический объём, прочитанные bytes, новые bytes назначения и фактически освобождённое место. Не складываем размеры точек для оценки занятого vault и не называем дедупликацию цепочкой SQL incremental dumps. Поведение restic и ограничения parent/file change detection: официальное описание backup.
Подключение проверяется службой на сервере-источнике, а не браузером администратора: identity назначения, запись/чтение временного объекта, достаточные права и возможности очистки, доступность после restart, доступное место, TLS и supported backend features. Для NAS запрещаем молча писать в локальную пустую папку при исчезнувшем mount: проверяем сохранённый vault ID и идентичность тома/mount перед каждым запуском. Нельзя разместить vault внутри source root или его алиаса/junction. Тот же физический диск помечается как отсутствие защиты от отказа диска; автоматическое определение домена отказа NAS/S3 не обещается.
Object Lock — отдельная проверенная возможность, а не универсальная галочка S3. Учитываем версии объектов, срок, права bypass, операции lock/index/pack движка, delete markers, стоимость и восстановление старых версий. Не объявляем vault неизменяемым, пока полный профиль write/check/prune/restore не прошёл приёмку. На неподдерживаемом backend показываем «защита от удаления не подтверждена». AWS: Object Lock. Для угрозы компрометации сервера нужен независимый домен администрирования и профиль, в котором credential источника не может уничтожить предыдущие копии.
Согласованная online-копия
Первый профиль — логический dump отдельной БД Arkvory и опубликованные blobs. Это самостоятельная переносимая точка; не PITR всего PostgreSQL. Для большой/нагруженной metadata DB последующий профиль — base backup + WAL и архив blobs с согласованным окном восстановления. Наличие WAL без соответствующих файлов не даёт PITR Arkvory. Выбор профиля зависит от измерений времени dump и MVCC pressure, а не только от 4 ТБ blob storage. PostgreSQL отдельно описывает область применения и ограничения pg_dump.
Предлагаемый порядок:
- Scheduler создаёт durable job с idempotency key и захватывает конечный lease/fencing epoch. Не более одного capture на source instance. Параллельная миграция схемы, offline repair или смена storage root запрещена; обычные API mutations разрешены.
- Coordinator кратко закрывает допуск нового физического удаления, дожидается уже допущенных unlink и фиксирует durable barrier
preparing. Барьер не блокирует download/upload/логические изменения. GC не может пройти между проверкой барьера и unlink: общий протокол admission + per-object guards обязателен для всех удаляющих инструментов. - Открывает REPEATABLE READ snapshot T. Из одного exported snapshot работают pg_dump и enumerator полного необходимого набора blobs. Enumerator читает keyset-порциями; пишет защищённый inventory и постоянные pins через отдельное writable-соединение. Pins относятся к immutable IDs, а не только к текущим asset pointers.
- После фиксации всех pins и durable inventory снимает широкий barrier. GC продолжает работу с остальными объектами; pins сохраняют точный набор T независимо от новых tombstones. Содержимое, которое не успело получить pin, нельзя считать защищённым grace-периодом.
- Завершает dump с тем же snapshot T, проверяет статус процесса и manifest. Затем закрывает экспортирующую транзакцию. Она живёт лишь во время dump/enumeration, не во время многочасового копирования 4 ТБ. Срок/размер/прогресс capture ограничены; превышение переводит job в ошибку и recovery очистки. Exported snapshot нельзя «возобновить» после потери его сессии. PostgreSQL: синхронизация snapshots.
- Передаёт в backup engine только указанные immutable blobs, готовый dump и versioned manifest/config. Потоковое чтение, ограниченные concurrency/cache/staging и rate. Никакого ZIP на 4 ТБ или копирования working PGDATA. Отсутствующий файл/неверный SHA — failure, а не успешная копия с warning.
- Engine завершает свой snapshot. Coordinator сверяет наличие полного набора, фиксирует внешнюю restore point и квитанцию, затем освобождает source pins. Manifest и inventory находятся в самой зашифрованной копии; каталог точек можно восстановить без исходной БД.
Реализация B1: миграция 25 (jobs/pins/barrier), протокол допуска unlink в online GC и offline repair и capability check по маркеру 18471/20 (ADR 0054). Вместо pg_dump таблицы выгружаются логически (NDJSON) из того же snapshot T; restore загружает только данные в известные таблицы и не исполняет SQL из копии. Текущие session pins читателей не заменяют durable backup pins. Старый runtime, не знающий backup protocol, нельзя запускать рядом: capture отказывает с upgrade_required, пока writer без маркера держит БД.
Отказы и продолжение
| Сбой | Требуемое поведение |
|---|---|
| Потеря snapshot до завершения capture | Старый capture не продолжается; новая точка T после reconciliation, старые pins снимаются только после fencing прежнего процесса. |
| Разрыв передачи после готового dump/inventory | Повтор с тем же job/manifest и ограниченным backoff; уже сохранённые chunks могут использоваться повторно. Точное resume с произвольного байта не обещается. |
| Crash между engine snapshot и SQL receipt | Reconciler находит snapshot по instance/job/manifest identity, проверяет и завершает тот же job без второй точки. |
| Истёк lease, старый агент ещё работает | Нельзя разрешить новый commit или снять pins по одному TTL. Сначала fence/остановка старого процесса и проверка внешнего результата. |
| Vault переполнен/недоступен | Сохраняются предыдущие копии; новый job не получает completed. Retry ограничен. Не удаляем последнюю копию ради нового запуска. |
| Недостаточно места на source из-за pins | Предупреждение/критическое событие и остановка нового capture по бюджету. Нужен явный cancel/reconcile, а не молчаливое удаление защищённых bytes. |
| Нажата «Пауза» | Разрешена на transfer с durable capture. Не удерживать экспортированный SQL snapshot ради долгой паузы. Есть предел времени удержания pins и видимый срок. |
| Нажата «Отменить» | Дождаться остановки дочернего процесса/передач, записать результат, освободить pins. Неподтверждённый исход — interrupted, не cancelled/success. |
Неизвестный исход сохраняется как отдельное состояние. Удаление «зависшего» job не должно обходить fences или освобождать его pins. При failover двух узлов источник определяется stable instance ID, а не hostname; пока fencing общей площадки не реализован, HA backup не заявляется.
Manifest и границы содержимого
Manifest version, backup job/point UUID, source instance ID, format/engine version, Arkvory release/commit, schema version, PostgreSQL major/client version, snapshot T, capture/completion timestamps, inventory hash/count/bytes, dump hash, config revision, platform/storage profile, encryption key ID без секрета, vault ID, исключённые ephemeral states и capability requirements.
Inventory — потоковый/порционный список immutable ID, size и SHA-256; полный список не помещается в одну UI/API JSON-страницу. Пути восстановления выводятся из проверенных IDs: запрещены traversal, absolute paths из произвольного manifest, symlink escape и распаковка поверх существующего root.
Сохраняем ACL/группы/пользователей как данные, но не активируем старые credentials автоматически. Dump сам содержит чувствительные hashes и отозванные состояния, поэтому всегда шифруется. Recovery нормализует upload/completion jobs, leases, gateway ownership, quotas, source backup jobs/pins и runtime sessions; живые source pins в SQL snapshot не должны заблокировать восстановленный сервис навечно. Эти преобразования версионированы и проверяются для каждой поддержанной схемы.
Сетевые адреса, локальные абсолютные пути, TLS private keys, SSH/GitHub secrets, пароли vault и DB connection strings не переносятся как готовая runtime-конфигурация. В manifest — безопасные параметры и ссылки на отдельно управляемые секреты; мастер заново связывает их с целевой установкой. Runtime/package provenance сохраняется; доверенный compatible installer нужен и в сценарии потери доступа к GitHub.
Шифрование и recovery kit
Реализовано (ADR 0070). Шифруются содержимое blob, inventory, таблицы, manifest и временные файлы prune (AES-256-GCM по 1 МиБ, ключ файла из мастер-ключа, vault, вида и имени); открыты vault.json, keys/*.json (мастер-ключ в обёртке под ключом слота) и COMMITTED. Ключи слотов — 32 случайных байта (AK1-… для службы, RK1-… для recovery kit), у ключа есть контрольная сумма; парольных фраз и KDF нет. Ниже — исходные требования; решение отличается: вместо restic и пароля — собственные слоты со случайными ключами, вместо шифрования всех исторических данных при ротации — отзыв слота без перешифрования (при компрометации ключа создаётся новый vault).
Backup engine шифрует содержимое и каталог. Пароль/key вводится или генерируется при настройке vault; исходный сервер хранит его в защищённом secret store/файле service identity. В API — только opaque secret reference. Маскированное поле не отправляет «••••» как новый пароль; поля отсутствуют при чтении.
Мастер выдаёт отдельный recovery kit: vault ID/адрес, engine/format, инструкция и recovery key в отдельно защищаемом экспорте. Не отправляем ключ в URL, audit, email или обычный manifest. Пользователь должен сохранить его вне source и подтвердить пробное открытие vault с kit. «Я сохранил» не заменяет проверку пригодности ключа. Потеря единственной копии ключа делает восстановление невозможным; UI объясняет это в соответствующем шаге.
Ротация доступа к vault и ротация encryption keys — разные операции. Сначала проверяется доступ новым recovery material к существующим точкам, затем отключается старый credential; физическое перешифрование всех historical bytes не обещается как мгновенная смена пароля. Проверяемое управление repository keys/check: restic repositories.
Расписание, retention и проверки
Предлагаемый стартовый шаблон: каждый день в 02:00 в явно выбранной IANA timezone, 7 ежедневных/4 еженедельных/6 ежемесячных точек, минимально 1 завершённая точка, один job на instance, ограниченный сетевой бюджет. Это редактируемый шаблон, не обещание RPO/SLA. UI показывает ближайшие 3 запуска в локальном времени и UTC; DST ambiguity разрешается правилом «один запуск на календарный слот». После downtime — один catch-up, а не очередь всех пропущенных суток. Повторное нажатие «Создать сейчас» имеет idempotency key.
Retain groups объединяются, поэтому значения 7/4/6 не обязаны давать ровно 17 разных точек. Preview показывает сохраняемые, удаляемые, закреплённые и заблокированные сроком точки. Manual pin действует сверх политики. Backup retention никак не меняет last-N билдов Arkvory. Удаление snapshot metadata и физический prune — разные операции; число потенциально освобождаемых bytes не выдаётся за результат. restic forget/prune.
Проверки: structural check при завершении; чтение/хеширование новых данных; расписание полной или порционной проверки всего vault с покрытием и датами; отдельный restore drill в чистую среду. restic check без чтения payload не доказывает целостность всех bytes. Статусы: «Завершена», «Проверено 100% / выборочно», «Пробное восстановление прошло» — разные поля. Ошибка проверки немедленно ухудшает состояние точки и не стирает историю последнего успеха.
Restore/drill закрепляет выбранную точку на весь job. Prune не конкурирует с restore, backup commit или глубокой проверкой: нужны per-vault очередь и совместимые engine locks, учитываемые также при запуске с другого узла. Снимать «старый» lock только по времени запрещено без подтверждения отсутствия владельца. Policy preview не является разрешением игнорировать актуальные pins и Object Lock при apply. Оценка экономии дедуплицированных данных до prune может быть неизвестна — UI обязан так и написать.
Бюджет backup отделён от квот хранения билдов. Ограничиваются сеть, параллельные чтения, cache/staging и при необходимости рабочее окно; исходные transfer-квоты не изменяются молча. Независимый лимит backup-процесса не является глобальным лимитом всех узлов и сетевых клиентов. Автоматическое снижение скорости по latency допускается только после измерений с hysteresis; в первой поставке — явные настройки и наблюдаемая нагрузка.
Предупреждаем об отсутствии первой копии, возрасте T последней завершённой точки, пропущенном расписании, отсутствии restore drill, повреждении, задержке очереди, месте source/vault, удержании pins, потере credentials и неподтверждённой защите от удаления. События имеют code, job/point ID, phase, severity, retryability и correlation ID без путей/секретов. Дедупликация повторов и recovery event обязательны. UI и системный журнал — первая поставка; webhooks/email только через отдельную настроенную интеграцию.
Восстановление
- Выбрать vault и точку; показать T, завершение, версии, состав, проверки, encryption key ID. Незавершённые точки недоступны для restore. Отдельный подтверждённый override повреждённой точки допускается только для будущего forensic export, не для запуска production.
- Выбрать новый сервер/root/volume. Preflight проверяет key, vault identity, совместимость Arkvory/schema/PostgreSQL, архив, свободное место с запасом, путь, права, порты, зависимости и отсутствие работающего экземпляра в target. План имеет hash/revision/expiry; изменение цели или копии делает его недействительным.
- Restore в отдельный staging/root и новую БД. Проверить все требуемые blobs, ссылки, каталог и квоты; применить версионированную нормализацию. Не использовать произвольный dump недоверенного superuser: импорт выполняет SQL-код, поэтому provenance и изоляция обязательны. Source продолжает работать; target не пишет во внешние системы.
- До первого запуска отключить retention/GC, backups, auto-update, исходящие интеграции и старые service credentials. Инвалидировать все сессии/transfer tokens, заменить bootstrap/health/DB secrets. Пароли и права пользователей требуют политики восстановления/повторного подтверждения; credentials, отозванные после T, не должны воскреснуть. На полностью утраченной площадке минимально безопасный default — новые credentials и controlled recovery admin.
- Выполнить
/health/ready, проверку worker, ACL, ссылок, скачивание и контрольные суммы, isolated upload/download; сформировать отчёт. Статус «Проверен, не опубликован» отделён от «Работает для клиентов». - Отдельное переключение: актуальная потеря данных относительно T, drain/fence старого writer, адрес/DNS/TLS/балансировщик, подтверждение имени цели, внешняя проверка. Online backup не означает restore с нулевым простоем или zero RPO. После новых записей на target простой возврат DNS на старый source небезопасен: нужен план reconciliation.
Restore drill никогда не переподключает production URL и не запускает расписания. Полный объём 4 ТБ нельзя восстановить мгновенно: UI показывает измеренный throughput, остаток bytes и диапазон ETA только после получения данных. Пользователь может закрыть UI; job принадлежит агенту на target. При недоступном source восстановление запускается из локального Remote Setup/Recovery entrypoint, не через потерянный API.
Восстановление поверх текущего экземпляра и выборочный импорт отдельных билдов — последующие явно отделённые сценарии. Сначала восстановить и проверить отдельно; destructive replace не является default или скрытой частью кнопки «Восстановить».
Архитектура и проект API
Domain: состояния, политика retention, оценка пригодности точки. Application: CaptureBackup, VerifyPoint, PlanRestore, RestoreToEmptyTarget и их узкие порты. Infrastructure: PostgreSQL snapshot/pins, vault/engine process adapters, journals и bounded transfers. API: авторизация, DTO, постановка команд. Web/CLI: SDK. Deploy: установка агента/зависимостей и bootstrap recovery при недоступном API; не импортирует другие apps.
При появлении исполнения нужен отдельный composition root apps/backup с явным allowlist application/domain/infrastructure и supervisor. Он изолирует dump/engine от transfer worker; это локальный сервис, не новый брокер или сетевой микросервис. Не добавлять пустые packages/интерфейсы до первого вертикального инкремента. Пути и секреты агента задаёт оператор установки; обычный repository key не может заставить сервер читать произвольный файл или запускать shell.
System-level права реализованы двумя именами: backup.read (состояние, план, задания, точки, preview retention) и backup.manage (план, запуск копии, проверка, retention, закрепление точек; включает read). Их имеют только администраторы учётных записей в сессии и файловый ключ владельца/bootstrap; персональные токены и управляемые сервисные ключи никогда (ADR 0056). Проектные имена backup.configure, backup.run, backup.verify, backup.delete, recovery.plan, recovery.execute, recovery.cutover не заведены и текущей авторизацией не поддержаны; репозиторный storage.manage не расширяется автоматически до backup всего instance. Начальный профиль — явно уполномоченный администратор; последующее делегирование не должно раскрыть содержимое чужих репозиториев или vault secrets.
| Предлагаемый endpoint | Назначение |
|---|---|
GET /api/v1/backup/capabilities | Поддержанные targets, checks, key management, ограничения и версия протокола. |
GET/POST /api/v1/backup/vaults, POST /{id}/probe | Конфигурация через secret references, capability/identity probe. |
GET/PUT /api/v1/backup/plans/{id} | CAS-настройки scope, schedule, budgets, retention; preview следующих запусков. |
POST /api/v1/backup/plans/{id}/runs | Идемпотентная постановка; 202 + durable job ID. |
GET /api/v1/backup/jobs, GET /{id}; POST /{id}/pause,resume,cancel | Пагинация, этапы, bytes, timestamps, допустимые команды, ошибки. |
GET /api/v1/backup/points, GET /{id} | Только доступные текущему principal точки; состав/check coverage/drill status. |
POST /api/v1/backup/points/{id}/verify | Асинхронная проверка с явно заданной глубиной. |
POST /api/v1/backup/retention/preview, POST /apply | План удаления, expectedRevision, pin/WORM checks; prune отдельно. |
POST /api/v1/recovery/plans, POST /api/v1/recovery/runs | Проверенный immutable plan → job на зарегистрированном target. |
GET /api/v1/recovery/jobs/{id}, POST /{id}/cutover | Отчёт и отдельное привилегированное переключение. |
Это кандидаты URI, не готовый контракт. Реализация должна синхронно добавить runtime validation, OpenAPI inventory, SDK и CLI. Все списки bounded/cursor-based; bytes — десятичные строки, timestamps — UTC, timezone — отдельное поле. Idempotency key связан с body/principal/target; stale plan/revision — conflict. Polling с backoff/Retry-After и snapshot revision обязателен до добавления SSE. Remote recovery agent принимает только типизированные команды с привязкой identity/nonce, а не исполнение произвольного кода через публичный API.
Порядок поставки и гейты
| Инкремент | Готовый вертикальный результат | Обязательная приёмка |
|---|---|---|
| B0 | Spike engine + capture/GC protocol; окончательный ADR | Протокол capture/GC и движок B1 решены ADR 0054; spike restic/S3 и переносимость ключей переходят в B3. |
| B1 ✔ | Ручная согласованная копия в local/NAS + CLI + отдельный агент | Выполнено 2026-10-02 (ADR 0054): гонки с публикациями, удалениями и GC; отказы на границах фаз; restore на чистую БД и API. |
| B2 ✔ | RU/EN UI, расписание, progress, budgets, retention и предупреждения | Выполнено 2026-10-02 (ADR 0056, 0057): CAS/ACL/idempotency, DST/downtime, lease/fencing, prune, crash; служба, vault и копия в native-install/containers; раздел консоли в browser-гейте. |
| B3 (частично) | S3 + независимый recovery kit + автономный recovery wizard | Выполнено 2026-10-07 (ADR 0070): шифрование vault, recovery kit, отказ при неверном key и подменённом manifest. S3 — ADR 0071 (proposed): S3 retries/permissions, S3-compatible contract suite. Открыто: автономный recovery wizard, потеря source, отключённый API. |
| B4 | Restore drill, controlled cutover и проверенный immutable/offsite profile | Старый writer fenced, secrets не воскрешают, нет исходящих side effects, отсутствие данных при сбое не скрыто. |
| B5 | Измерение 4 ТБ и профиль PITR/два узла | Согласованное окно WAL/blobs, RPO/RTO, capacity/I/O/p95 под реальной смешанной нагрузкой. |
Тесты входят в общий registry gates, verify/release и CI; не отдельные необязательные scripts. Новые Linux/Windows/S3 lanes не должны молча skip при отсутствующей инфраструктуре. Fault tests включают lease expiry со старым процессом, loss of mount, cancellation during commit, snapshot loss, missing blob, corrupted pack, last-good retention, schema incompatibility, восстановление revoked keys и недоступность исходного узла. Скорость и RPO/RTO публикуются только вместе с конфигурацией стенда и измерениями.
Решения, требующие уточнения площадки
Типы и домены отказа vault, лимит занимаемого места и бюджета I/O, целевые RPO/RTO, срок хранения, Object Lock/append-only backend, место recovery kit и ответственный за доступ. До ответов локальный/NAS и S3 рассматриваются как проектные профили; расписание/retention — редактируемые примеры. Ни одно производственное хранилище или правило удаления этим документом не настраивается.