Skip to content

Консоль: сценарии и правила интерфейса ​

Веб-интерфейс репозиториев и сервисного доступа: WEB_ADMINISTRATION.

Основной путь ​

Подключение → каталог → скачать или открыть свойства. Скачивание доступно непосредственно в строке каталога; получение метаданных не является дополнительным условием для скачивания. В строке видны имя, размер, время публикации, стадии продвижения (акцентные фишки) и текущие метки, а также действия. Всё это приходит одним запросом поиска, без отдельного запроса на строку. ID занимает последнюю строку на широком экране и доступен в свойствах на любом экране. Подписи «Размер», «Опубликован», «Стадии», «Метки» доступны программам чтения с экрана.

На каждом экране один заголовок страницы. Кнопка загрузки в заголовке показывается у каталога, пакетов и истории. В редакторе показывается имя выбранного файла, отдельно от технического идентификатора. Имена, пути и другие пользовательские данные выводятся через textContent.

Решения по экранам ​

СценарийПоведение
ПодключениеДля людей основной путь — имя и пароль; ключ сервиса или автоматизации вводится в свёрнутом блоке «Подключиться ключом сервиса или автоматизации». Репозиторий выбирается автоматически после входа. Значок показывает «Подключено» после любого успешного входа (пароль или ключ), даже если у администратора нет репозитория. «Отключиться» видна только при активном подключении. После первого входа карточка сворачивается.
Ошибки входаТекст выбирается по причине ответа, а не по маршруту: invalid_credentials — «Неверное имя пользователя или пароль», current_password_invalid — «Текущий пароль указан неверно» с отметкой поля, сеанс остаётся. 401 о самой сессии завершает её: консоль очищает приватные данные, раскрывает карточку, фокусирует имя и сообщает «Сеанс истёк» (session_expired) или «Сеанс завершён» (отзыв, выход в другом месте, смена пароля). Для ключа: истёкший — «Срок ключа истёк», недействительный или отозванный — «Ключ недействителен»; без учётных данных — просьба войти.
СсылкиКаждый раздел имеет адрес #/catalog, #/packages, #/history, #/upload, #/downloads, #/administration, #/repositories, #/services, #/updates, #/backups, #/onboarding, #/help; открытый артефакт — #/artifact/{repository}/{id}. Навигация добавляет запись истории, кнопка «Назад» возвращает предыдущий раздел. Ссылка, открытая до входа, запоминается и восстанавливается после подключения; неизвестный или недоступный раздел ведёт в каталог с сообщением. В адресе нет токенов, паролей, поисковых запросов и черновиков. Старые #onboarding и #help поддерживаются.
ПодтвержденияОтключение пользователя, удаление из группы и снятие доступа группы к репозиторию спрашивают в модальном окне с именами затронутых объектов. Фокус ставится на «Отмена»; Escape и выход из сеанса отменяют действие. Включение пользователя, добавление и выдача доступа подтверждения не требуют.
РазмерыБайты показываются через formatBytes/параметры размера message: использование хранилища, квота, кандидаты автоочистки, освобождённое место и записанные байты скачивания. Квота вводится в ГиБ (до трёх знаков после точки или запятой); API получает точное число байт, а неизменённое значение сохраняется без округления.
Справка и сервисыПодсказка «API и CLI» меняется при подключении и отключении. Пустой список «Сервисного доступа» для ключа владельца из файла объясняет, что ключ предназначен для настройки, и предлагает создать сервисную учётную запись; делегированный доступ просит обратиться к владельцу сервера.
НавигацияНа широком экране постоянная боковая панель. До 760 px — кнопка «Разделы» с aria-expanded/aria-controls и сеткой разделов. Выбор закрывает меню и фокусирует заголовок. Escape закрывает меню и возвращает фокус на кнопку.
КаталогПоиск, фильтр по метке и сброс. Пустой репозиторий отличается от отсутствия совпадений. Пока запрос выполняется, поиск и следующая страница недоступны, область помечена aria-busy. Устаревший ответ не меняет каталог другого подключения.
СвойстваИмя файла над формой; ID под раскрытием. Метки, коллекции и JSON остаются редактируемыми при переходах между экранами и смене языка/темы. Сохранение по-прежнему проверяет ревизию на сервере.
Сводка артефактаРазмер в двоичных единицах с локализованными цифрами, время загрузки и SHA-256 с кнопкой копирования. Ошибка буфера обмена сообщается отдельно, значение остаётся доступным для выделения.
ПродвижениеСтадии — фишки с кнопкой снятия (подтверждение, aria-label со стадией), форма добавления проверяет имя до запроса. Форма продвижения показывает только репозитории с правом artifact.promote; перенос (move) требует подтверждения и возвращает в каталог. История — по возрастанию, «Показать ещё» догружает страницы. Элементы скрыты без соответствующих операций.
ПакетыКолонка «Стадии» заполняется одним запросом stages?ids= на страницу; без права artifact.list остаётся пустой.
ЗагрузкаВо время передачи блокируются параметры подключения, вход и смена пароля; пауза, навигация, тема и язык остаются доступны.
СкачиванияНастройки параллелизма/задержек под раскрытием. Видны применимые действия очистки; пустая очередь показывает переход в каталог вместо пустой таблицы. Пауза пустой очереди разрешена, чтобы следующие файлы сначала встали в ожидание. Пауза всей очереди отмечена отдельным сообщением.
ПользователиСписки учётных записей и групп разделены. Создание, смена пароля, состав группы и выдача прав — отдельные раскрываемые формы. При открытии раздела данные обновляются.
Результаты операцийГлобальный результат расположен перед содержимым; на широком экране остаётся видимым при прокрутке. Переход между экранами убирает старый результат; новое сообщение снова отображается. Локальные результаты передачи остаются в своём разделе.

Обратная связь об ошибках ​

Контракт ошибок — ADR 0051. Консоль никогда не разбирает текст ошибки: errorKey берёт сообщение по паре code/reason, затем по code, затем по HTTP-статусу для ответов прокси без конверта Arkvory, затем общее «Не удалось выполнить операцию». Неизвестная будущая причина читается как её код.

СитуацияСообщение
capacity_exceededПо виду лимита: квота репозитория, диск сервера, учётные записи, группы, участники, правила доступа, ключи, токены, делегирования, каталог, очередь
conflict/upload_expired«Срок загрузки истёк… Начните новую загрузку»; upload_state — загрузка уже опубликована или отменена
conflict/revision_mismatchОбъект изменён: обновите и повторите; version_exists, already_exists, stage_limit, idempotency_mismatch — отдельные тексты
forbiddenПо причине: токен только для чтения, нужен вход по паролю, только администратор, ключ отозван, регистрация выключена, адрес консоли не разрешён
rate_limitedlogin_attempts — о попытках входа; регистрация и текущий пароль — свои тексты; иначе «Слишком много запросов»
read_onlyАдрес только раздаёт файлы, изменения — через основной адрес
internal«Непредвиденная ошибка сервера. Сообщите администратору идентификатор запроса»
Сеть / таймаут / 502, 504Раздельно: нет ответа (проверьте сеть), сервер отвечал слишком долго, прокси перед Arkvory не получил ответа
invalid_input с details«Проверьте выделенные поля»; 413/415/битый JSON и неизвестный маршрут или метод — отдельные тексты

Под сообщением — тихая строка .error-ref: «Повторите через N с», если сервер прислал Retry-After, и «ID запроса» с моноширинным значением, которое выделяется целиком одним щелчком и доступно с клавиатуры. Строка одинакова для общей строки состояния (#request-id), панелей (вложения, хранение, очистка, удаление, справка, обновления), ManagementTask, строк очереди скачиваний и состояния передачи; её создаёт единственный showFailure. Любое новое сообщение того же узла убирает строку, пустой узел скрывает её через CSS; повторная отрисовка строки скачивания не пересоздаёт её, поэтому выделение не теряется. Для локальных ошибок консоли строки нет.

Поля из details сервера или локальной проверки отмечаются aria-invalid="true", получают сообщение #<id>-error через aria-describedby («Обязательное поле», «Неверный формат», «Проверьте значение»…) и фокус на первом из них; свёрнутый раздел с полем раскрывается, правка значения снимает отметку. Карта «поле запроса → элемент» есть у входа и регистрации, смены своего пароля, создания пользователя и группы, сброса пароля, меток/метаданных/коллекций, политики хранения (квота, пороги, интервалы), имени стадии и формы продвижения. Для invalid_credentials поля не отмечаются: сервер намеренно не сообщает, что именно неверно.

Вёрстка и доступность ​

  • Цвета, размеры текста, отступы, радиусы, размеры контролов и слои задаются в tokens.css. Компоненты используют семантические токены обеих тем.
  • Минимальная ширина каталога снята: имя и действия доступны на телефоне без горизонтальной прокрутки. Более широкие таблицы прокручиваются внутри именованной области, доступной с клавиатуры; заголовки столбцов имеют scope="col".
  • Checkbox имеет собственный размер и выравнивание, не наследует геометрию текстового поля.
  • Кнопки строк описаны именем соответствующего файла. Нативные details/summary сохраняют управление с клавиатуры и состояние раскрытия при смене языка.
  • Интерфейс не показывает фиксированное число серверов: консоль не располагает данными, подтверждающими топологию развёртывания.
  • В настройках браузера сохраняются только язык и тема. Эти изменения не добавляют сохранение токенов, очередей или содержимого форм.
  • На телефоне (375–390 px) поля входа и кнопки выстраиваются в колонку, каждая кнопка занимает строку; подписи переносятся только между словами. Боковая полоса на широком экране прокручивается только по вертикали и не получает горизонтальную полосу прокрутки при короткой высоте окна.

Плотная раскладка для мыши, подробности в дизайн-системе:

  • Шапка. Заголовок экрана, «Загрузить файл» и настройки стоят в одной строке шапки.
  • Подключение. Карточка подключения после входа сворачивается в одну строку.
  • Каталог. Счётчик и подсказка стоят в строке поиска. Строка артефакта двухуровневая: имя со стадиями и метками, затем размер, время публикации и ID.
  • Пакеты. Фильтры пакетов занимают одну строку.
  • Репозитории. Репозитории идут списком строк, права раскрываются фишками.
  • Онбординг и справка. Без дублирующих заголовков и подзаголовков.

Поясняющие абзацы перенесены в подсказки «?». На сенсорных экранах цели снова 44 px.

Язык интерфейса ​

Пользовательские тексты избегают внутреннего жаргона; точная техническая формулировка остаётся в подсказке рядом. Примеры замен: «Ревизия метаданных: N» → «Свойства открыты · версия N»; «Ожидаемая ревизия» → «Текущая версия ссылки» с пояснением о защите от одновременных изменений; «ожидают GC» → «ожидают очистки»; «gateways и workers» → «все серверы Arkvory, включая серверы чтения и фоновые обработчики»; «только bootstrap» → «только владелец сервера (учётная запись первичной настройки)»; «Ключ повторного запроса» → «Ключ защиты от повторов» с подсказкой про Idempotency-Key; «билды» → «сборки». Счётчики изменений файлов, вложений и политик называются версиями. Справочник API и примеры CLI сохраняют технические имена.

Резервные копии ​

Раздел «Резервные копии / Backups» (#/backups) построен на /api/v1/backup через SDK client.backup (ADR 0056, продуктовый замысел — BACKUP_UX). Он виден, только если operation discovery (/api/v1/operations?surface=administration) перечисляет операции с backup.read, — тот же источник, что у других административных экранов: администраторам учётных записей и ключу владельца из файла. Сервисные ключи, ключи репозиториев и персональные токены раздела не видят, ссылка на него ведёт в каталог с «Раздел недоступен». Каждое действие показывается по своей операции backup.manage (шлюз чтения изменений не перечисляет); решение всё равно принимает сервер. Каждый вход создаёт новую сессию раздела с клиентом своего ключа: выход и смена ключа отменяют её запросы и очищают данные.

БлокПоведение
СостояниеФишка из предупреждений: «Копии в порядке» только без предупреждений, любое critical — «Требуется вмешательство»; текст и точка, не только цвет. Возраст последней копии отсчитывается от снимка T, точное местное время — при наведении. Следующий запуск — местное время и отдельной строкой UTC, «Просрочен», если nextRunAt уже прошёл. Агент — в сети/не в сети, последний сигнал, версия. Хранилище копий — свободно из всего в двоичных единицах, «Неизвестно», пока агент не в сети.
ПредупрежденияСтрока на код: уровень («Внимание»/«Критично») и сообщение; действие оператора — в подсказке «Что делать» (ARKVORY_BACKUP_VAULT агенту или arkvory configure --backup-vault, когда установщики его поддержат; запуск службы arkvory-backup и т. д.). Пути файловой системы не показываются нигде: API их не возвращает.
Создать копию сейчасОдин щелчок — одно задание (SDK присылает новый Idempotency-Key, ответ 202). Кнопка недоступна, пока копия в очереди или выполняется. Выполняющееся задание показано в сводке: вид, этап (live region объявляет смену этапа, а не байты), прогресс — только при известном общем объёме.
ТочкиНовые первыми, по 20, «Ещё»: T, завершение, объём и новые байты, файлы, проверка (не проверена / структура / полностью / ошибка с кодом), закрепление, «Проверить полностью» и «Закрепить/Открепить». Кнопки строки описаны временем T через aria-describedby.
Хранение«Применить хранение» сначала читает preview и показывает в общем окне подтверждения списки «Удаляются» и «Остаются» с причинами (день, неделя, месяц, закреплена, новейшая). Фокус на «Отмена»; отмена ничего не ставит в очередь. Подсказка объясняет, что хранится одна точка на местный день, поэтому нужную точку закрепляют.
ЗаданияНовые первыми, «Ещё»: вид, состояние, этап, начало и конец, код ошибки, полоса по байтам для открытого задания.
ПланФлажок, местное время, IANA-пояс с поиском по datalist из Intl.supportedValuesOf('timeZone'), текущее смещение от UTC, хранение дни/недели/месяцы. Пояс браузера только предлагается кнопкой и не меняет сохранённый план. Сохранение — CAS по expectedRevision: 409 revision_mismatch перечитывает план, показывает версию, сохранённую другими, и просит проверить; details отмечают поля. Имя пояса проверяет сервер.
ВосстановлениеОдна строка «выполняет оператор на сервере — в пустую цель» с подсказкой команды npm run backup -- restore … и ссылкой на CORE_RUNBOOK. Кнопки восстановления в консоли нет.

Опрос: статус и первая страница заданий каждые 5 с, только пока есть задание в очереди или в работе и экран видим. Переход на другой экран и скрытая вкладка останавливают его сразу; возвращение на экран перечитывает данные, видимая снова вкладка продолжает опрос. После ошибки интервал растёт: 10, 20, 40, не более 60 с. Завершившееся задание перечитывает точки. Строки обновляются на месте по ID, предупреждения пересоздаются только при смене набора кодов, поэтому фокус и открытая подсказка переживают опрос. Форму плана заполняют только явная загрузка, сохранение и конфликт; фоновое обновление её не трогает.

Вёрстка плотная; до 760 px строки обеих таблиц становятся карточками с подписями значений, поэтому на 320–1440 px нет горизонтальной прокрутки. Обе темы, RU/EN; на сенсорных экранах цели 44 px через токены. Чистые правила экрана (фишка состояния, «просрочен», смещение пояса, процент без потери точности больших чисел, интервал опроса, относительный возраст) — в backup-model.ts и relative-time.ts, их проверяет tests/web-backups.test.mjs.

Приёмка ​

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

Активная загрузка, как и очередь скачивания, защищена нативным beforeunload: браузер предупреждает перед уходом со страницы. После завершения блокировка снимается. Явная пауза отображается информационным сообщением, сохраняет ID загрузки и разрешает продолжение; она не считается ошибкой передачи. Блокировка полей вынесена в upload-controls.ts, основной контроллер укладывается в общий лимит 500 строк кода без исключения.

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

tests/browser/session.mjs (через console.mjs) открывает консоль по ссылке на артефакт без входа, проверяет порядок форм, скрытую кнопку «Отключиться», неверный пароль, значок после входа по паролю, восстановление ссылки, «Назад», неизвестный и запрещённый разделы, подсказку справки, завершённый сеанс (сессия отзывается через API — «Сеанс завершён») и пустой список сервисов для ключа владельца. tests/browser/errors.mjs на отдельном сервере проверяет отметку поля по details сервера с фокусом, aria-describedby и переводом RU/EN, ID запроса, неверный текущий пароль без выхода и истёкший сеанс на той же форме, а также «Повторите через N с» после исчерпания попыток входа. build-details.mjs проверяет ID запроса в панели вложений при конфликте версии. На 375 и 390 px в RU/EN каждое слово подписи кнопки проверяется через Range.getClientRects(); боковая полоса проверяется в отдельном браузере с видимыми полосами прокрутки при высоте 420–600 px. Там же проверяются три подтверждения в разделе пользователей. build-details.mjs открывает ссылку #/artifact/... во второй вкладке с ключом читателя.

Эти регрессии проверяет tests/browser/usability.mjs через вход console.mjs: клавиатурный переход по логотипу, сохранение файла и подключения, отмена picker с последующим успешным скачиванием, запоздавшая сетевая ошибка, число HTTP-запросов и очистка при RU/EN. Для проверки сетевого отказа один запрос поиска задерживается и прерывается в браузере; остальные операции используют реальный API.

tests/browser/backups.mjs (в console.mjs перед density и проверкой ошибок) работает с реальными API, PostgreSQL, временным vault, копией через композицию CLI и агентом в процессе теста, как tests/integration/backup-agent.test.mjs. Проверяются ссылка #/backups до входа, исходные предупреждения о хранилище и агенте с подсказками, сохранение плана, конфликт версий и поле, отклонённое сервером (RU/EN), очередь «Создать копию сейчас» без агента, опрос и его остановка на другом экране и в скрытой вкладке, отказ vault_missing агента без хранилища, закрепление, копия агентом с сохранением фокуса в строке, окно хранения с отменой и подтверждением, полная проверка, отсутствие путей, 320/390/768/1024/1440 px × RU/EN × обе темы, цели 44 px при касании и скрытый раздел для ключа читателя.

tests/browser/density.mjs проверяет в контексте без касаний: указатель точный, заголовок в шапке, поля не выше 34 px, строка каталога не выше 64 px, все видимые экраны при 1024 и 1440 px на RU и EN без горизонтальной прокрутки. tests/browser/console.mjs работает с реальными PostgreSQL, API и OPFS. Проверяет поиск/сброс, скачивание из каталога, ошибку JSON и сохранение метаданных, привязку пути и чтение истории, создание пользователя, загрузку файла, блокировку входа во время передачи, сохранение полей при переключениях и выход. Для проверки активной загрузки задерживается реальный HTTP-запрос; ответ не подменяется. Только системный save picker заменяется выдачей настоящего OPFS handle.

Матрица layout: семь экранов × 320/390/768/1440 CSS px × RU/EN × light/dark. Проверяются отсутствие горизонтального переполнения страницы, фокус заголовка и работа мобильного меню с Escape. Снимки для ручного просмотра сохраняются в игнорируемом test-results/. Отдельный tests/browser/downloads.mjs проверяет скачивание 17 MiB, паузу на границе 8 MiB, докачку, SHA-256 и изоляцию временных файлов вкладок.

Запуск на выделенной тестовой БД:

powershell
# ARKVORY_TEST_DATABASE_URL — из .env.test или окружения, не production.
# Playwright зафиксирован в devDependencies; по умолчанию используется pinned Chromium.
$env:ARKVORY_BROWSER_CHANNEL = 'msedge'
npm run gate -- browser

Браузерные сценарии запускаются последовательно: fixture использует эксклюзивный профиль API на тестовой БД. Проверено локально на Windows, Node 24.13, PostgreSQL 18.4, headless Edge. Основные проверки дополнены тестами полноты RU/EN и контраста текстовых пар. Это не сертификация WCAG: проверка screen reader, Safari/Firefox и пользовательское исследование ещё не проводились. Ограничения save picker/OPFS и времени жизни очереди описаны в DOWNLOAD_QUEUE.

Карточка сборки дополнена редактором metadata ключ/значение (JSON в disclosure), свободными метками с переключаемыми подсказками и блоком вложений. Права приходят через operation discovery; read-only скрывает mutations. Реальные сценарии паузы/продолжения, конфликта, unlink/restore и просмотра reader проверяются tests/browser/build-details.mjs. Подробности.

Каталог ищет имя и актуальные значения metadata; точная пара ключ/значение находится под раскрытием и участвует в общем сбросе фильтров. Экран скачиваний предлагает восстановить очередь после reload. Записи восстанавливаются на паузе в порядке создания, только после проверки identity; продолжение требует повторного выбора назначения. Общая кнопка продолжения не запускает записи без выбранного файла. Границы восстановления.

Arkvory · ProAnimaStudio