Как Robo-8 v2 планировали, проектировали и собирали
Рассказ мастера о Robo-8 v2: ограничения, архитектурные решения, направление дизайна и то, как это проверяли.
Начать с ограничений
Я начал не с функций, а с четырёх условий, которым приложение должно соответствовать. Оно должно работать без сервера. Любое использование облака необязательно и бесплатно для пробы. Ключ не должен жить ни в APK, ни в веб-хранилище. И оно должно работать на Android 6 и новее. Всё остальное могло подстраиваться под эти условия.
Одно допущение, которое нельзя было обойти
Исходного материала для подписи v1 не было. Это важнее, чем кажется: Android не обновит приложение, подписанное другим ключом. Поэтому v2 стал отдельным пакетом, который ставится рядом с v1. Я записал это как допущение и не стал выдавать за обновление.
Архитектура: WebView и очень маленький нативный мост
Я взвесил три варианта. Страница на сервере перестаёт работать без сети. Полноценная среда с агентным интерфейсом тянет платный маршрутизатор и сервер, что нарушает правило «только бесплатное». Выбранный вариант упаковывает HTML, CSS, JavaScript и шрифты внутрь приложения и загружает их в WebView с источника, существующего только внутри приложения, а крошечный нативный слой делает две вещи: выполняет HTTPS-запрос к NVIDIA и принимает ключ. Раз запрос нативный, браузер никогда не видит ключ, а проблема CORS исчезает.
Ключ никогда не попадает на страницу
Ключ вводится в собственном окне Android, которое блокирует снимки экрана, хранится в памяти процесса на время сеанса и стирается при отключении. WebView не может его прочитать. Запрос содержит только набранное вами сообщение и фиксированный промпт, с ограничением размера тела, сроками на соединение и чтение и без перехода по перенаправлениям. Истории чата, которая могла бы утечь, нет: она не хранится.
Дизайн: маленький живой предмет, а не панель
Направление, которое я записал, это игривый прибор: телефон на столе вечерним светом должен казаться маленьким живым существом. Отсюда глубокая морская поверхность, бледно-мятные глаза, один киноварный акцент, шрифт цвета раковины и один фирменный приём: асимметричные округлые глаза в физическом отверстии лица. Space Grotesk и IBM Plex Mono встроены локально. Я исключил градиенты, стекло, вложенные карточки и декоративные циклы. Движение есть только чтобы показать взгляд, моргание, касание, мысль или дыхание, а режим «Уменьшить движение» отключает фоновую анимацию. Первый экран это робот; инструменты и разговор ниже.
Своё лицо, заимствованы только принципы
Публичное описание выражений, характера и фонового поведения EMO было источником вдохновения. Ни графику, ни прошивку, ни анимацию оттуда я не копировал. У двух проектов под лицензией MIT я взял идеи, а не рабочий код: способ отображать сгенерированные компоненты интерфейса по списку разрешённых, и привычку держать ключи временными. Оба указаны в уведомлениях.
Безопасность по построению там, где это удалось
Сгенерированные ответы не могут выполнять код. Отрисовка принимает только фиксированные схемы компонентов и выводит текст через textContent, поэтому враждебный ответ остаётся просто текстом. У сетевых вызовов есть ограничения. Скрытые анимации ставятся на паузу. Эти случаи сбоев я перечислил до написания кода, а затем написал для них тесты.
Проверка и то, что она не покрыла
Проверки я планировал как способы показать, что дизайн ошибочен: отрисовка при 320 и 390 пикселях, все взаимодействия без сети, имитация облачных ошибок, проверка подписи и манифеста APK, установка и запуск. В записи значатся 11 проверок движка и 34 проверки интерфейса в браузере, а также установка и запуск на эмуляторе Android 6. Первый запуск на эмуляторе выявил настоящую ошибку: встроенный WebView оказался слишком старым для современного JavaScript, поэтому я перевёл код под старый Chrome и добавил запасные варианты CSS, затем переустановил и проверил снова. Чего не проверяли: настоящий телефон, новые версии Android, поведение батареи у производителей, подпись для выпуска и авторизованный ответ NVIDIA, потому что ключа не было. Я говорю об этом и на странице приложения.
Что я сделал бы дальше
Проверить на настоящем устройстве, провести один авторизованный облачный сеанс с пробным ключом и решить, стоит ли вернуть камеру и речь из v1 за явным разрешением. До тех пор v2 это спокойный компаньон без сети с необязательным «мозгом».
Версия 3: датчики, память и то, что я не смог проверить
В v3 я развил дизайн v2, добавив органы чувств. Компаньон теперь реагирует на то, что его поднимают, трясут, крутят, наклоняют и роняют, на свет и темноту, на хлопки и поглаживания, помнит серии дней и этапы и сам совершает мелкие действия в простое. Микрофон по умолчанию выключен, потому что функция прослушивания должна включаться по желанию. Я также дал приложению нейтральное имя пакета, com.jackgross.robo8, чтобы идентификатор не нёс ничего, кроме самого проекта. В ходе сборки нашлась настоящая ошибка: нативные события датчиков срабатывали до загрузки JavaScript страницы, и ранние реакции терялись. Её исправили, и здесь размещена исправленная сборка. Что проверено, по сообщению проекта: установка и запуск на эмуляторе Android 6, живая проверка реакций на батарею, сон при свете и темноте, положение лицом вниз, пробуждение и танец в простое, 97 проверок движка и 27 из 27 проверок в браузере. Что нет: датчики, микрофон и вибрация на настоящем телефоне и авторизованный ответ NVIDIA. Считайте пороги датчиков недоказанными, пока не будет запуска на телефоне.