# SHiNE ESP32 Homeserver UI Spec

## Назначение

Этот документ описывает актуальный UI-прототип homeserver `SHiNE` для платы `Waveshare ESP32-S3-Touch-AMOLED-2.16`.
Актуальный основной Arduino-скетч лежит в `../main-device/shine_homeserver_main/`.

Документ является источником истины для Arduino-скетча:

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

## Текущий объём реализации

Текущая реализация является интерактивным прототипом экрана устройства, пригодным для ручной проверки на железе.

Что уже входит в прототип:

- локальный UI на тач-экране;
- хранение настроек и секретов во внутренней памяти `ESP32` через `NVS`;
- экранный UI устройства работает на английском языке, потому что кириллица на этом шрифтовом пути пока не поддерживается стабильно;
- экран пополнения с реальным `solana:` URI и рисованием QR-кода через `LVGL`;
- реальное подключение к `Wi-Fi` по сохранённым `SSID/паролю`;
- реальная проверка доступности `API`, `RPC` и `WS`-адресов;
- реальное чтение баланса кошелька из `Solana RPC`;
- проверка обязательных условий перед регистрацией;
- живая on-chain регистрация серверного `user_pda` в `shine_users` по нажатию кнопки на главном экране;
- живой экран заявок на подключение новых устройств через доверенную homeserver-сессию;
- PIN-блокировка (в текущей временной сборке вход по PIN отключён, устройство открывает `HOME` сразу после старта);
- базовые настройки, статус и главный экран;
- сохранение `PDA` и `tx signature` после успешной регистрации.
- создание и возобновление серверной сессии `SHiNE` через WebSocket с `sessionType = 100` и `clientPlatform = "ESP32"`.

Что пока считается именно прототипом, а не финальной интеграцией:

- пока реализован только сценарий заявок на подключение устройств через доверенную сессию;
- другие типы входящих запросов на подпись и произвольные approval-flow на этом устройстве ещё не подключены.

## Основная идея устройства

Устройство работает как отдельный homeserver:

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

`SD`-карта не нужна для постоянного хранения секрета в этом прототипе.
Основное сохранение идёт во внутреннюю flash-память через `NVS`.

## Данные, которые хранятся на устройстве

Прототип хранит:

- `PIN`;
- `Wi-Fi SSID`;
- `Wi-Fi password`;
- `login`;
- `session/homeserver name`;
- `master secret`;
- `wallet address`;
- `user pda address`;
- `registration signature`;
- `balance`;
- `server login` для первичной привязки;
- `resolved server api url` / `rpc url` / `ws url` после чтения PDA сервера;
- флаги:
  `wifiReady`, `serversReady`, `secretReady`, `registered`, `online`.

Для первой регистрации обычного `user PDA` устройство берёт `createdAtMs` из NTP прямо перед отправкой транзакции в Solana. При последующих обновлениях `user PDA` устройство так же берёт актуальный `updatedAtMs` из NTP перед отправкой update-транзакции. Дальше в `user PDA` сохраняется `accessServers`, где по умолчанию лежит `shineupme`.

## Правило серверной сессии SHiNE

При подключении к серверу `SHiNE` устройство должно авторизовываться как homeserver-сеанс:

- `sessionType = 100`
- `clientPlatform = "ESP32"`
- `clientInfo = "ESP32 homeserver:<homeserverName>"`

Это относится и к `CreateAuthSession`, и к `SessionLogin`.

## Правила готовности к регистрации

Кнопка регистрации доступна только если одновременно выполнены условия:

1. настроен и подтверждён `Wi-Fi`;
2. задан и подтверждён `SHiNE server login`;
3. задан логин;
4. сгенерирован или введён секрет;
5. баланс кошелька не меньше `0.20 SOL`;
6. устройство ещё не зарегистрировано.

Если хотя бы одно условие не выполнено, главный экран показывает, чего именно не хватает.

## Экранная модель

В прототипе используются следующие экраны:

1. `LOCK`
2. `HOME`
3. `STATUS`
4. `CONNECTION`
5. `WIFI_EDIT`
6. `SERVERS`
7. `ACCOUNT`
8. `WALLET`
9. `WALLET_QR`
10. `WALLET_SIGN_REQUEST`
11. `REQUESTS`
12. `REQUEST_DETAIL`
13. `SETTINGS`
14. `PIN_EDIT`
15. `TEXT_INPUT`
16. `CONFIRM`
17. `REGISTER_ACCOUNT_CONFIRM`
18. `REGISTER_ACCOUNT_RESULT`

## Общие правила интерфейса

- Верхняя строка всегда показывает краткий статус устройства:
  `PIN`, `Wi-Fi`, `сервер`, `регистрация`.
- В правом верхнем углу рядом с батареей:
  - сначала процент заряда;
  - затем, если устройство реально заряжается, маленькая иконка молнии;
  - затем контур батареи;
  - затем индикатор `Wi-Fi`.
- Основной язык прототипа: английский.
- Для вывода текста в текущей временной сборке используется стандартный шрифт `Arduino_GFX`.
- Русские строки в UI устройства пока не использовать.
- Кнопки крупные, с тач-ориентированным размером.
- Опасные действия подтверждаются отдельным диалогом.
- После изменения данных конфигурация сразу сохраняется в `NVS`.

## Экран LOCK

Назначение:

- экран блокировки предусмотрен в UI, но в текущей временной сборке после запуска пропускается;
- вход по PIN временно отключён для отладки остальных экранов.

Отображается:

- заголовок `SHiNE Device`;
- статус `Устройство заблокировано`;
- поле ввода PIN в виде маски;
- кнопки цифровой клавиатуры;
- кнопки `Стереть` и `Открыть`.

Поведение:

- если PIN введён верно, открывается `HOME`;
- если PIN неверный, показывается ошибка `Неверный PIN`;
- в текущей временной сборке этот экран не показывается автоматически при старте.

## Экран HOME

Это основной экран устройства.

Показывает:

- крупный статус регистрации;
- имя логина;
- имя homeserver;
- строку `Wi-Fi: <SSID> connected|disconnected`;
- строку `SHiNE: <server address> connected|unavailable`;
- короткий статус баланса.

Особенности верхнего блока:

- зелёный/контурный статусный кружок аккаунта расположен слева от строки логина;
- блок `STATUS` поднят выше относительно предыдущей версии;
- если состояние хорошее, слово `connected` в строках `Wi-Fi` и `SHiNE` показывается зелёным.

В зоне кошелька:

- вместо старых двух кнопок `баланс` и `QR` показывается одна широкая кнопка;
- текст кнопки: `Wallet: <selected wallet name>`;
- доступные имена:
  - `ClientKey`
  - `RootKey`
  - либо сохранённое имя `custom`-кошелька;
- после старта устройства баланс активного выбранного кошелька пытается загрузиться автоматически, если уже есть секрет и `Wi-Fi`;
- нажатие на эту кнопку открывает экран `WALLET`.

Нижние кнопки:

- `Статус`
- `Подключение`
- `Аккаунт`
- `Wallet`
- `Запросы`
- `Настройки`

Дополнительная большая кнопка:

- `REGISTER ACCOUNT`
- либо жёлтая `ADD HOMESERVER`
- либо жёлтая `FIX HOMESERVER PASSWORD`

Если регистрация уже сделана:

- если пользователь создан, но в `PDA` ещё нет сессии текущего homeserver, показывается жёлтая кнопка `ADD HOMESERVER`;
- если в `PDA` есть homeserver с тем же именем, но с другим ключом, показывается жёлтая кнопка `FIX HOMESERVER PASSWORD`;
- если и пользователь, и homeserver-сессия уже корректны, вместо призыва к регистрации показывается статус `Homeserver активен`.
- две нижние кнопки внизу экрана не прилегают вплотную друг к другу, между ними есть небольшой зазор.

## Экран REGISTER_ACCOUNT_CONFIRM

Показывает предварительную проверку перед отправкой транзакции регистрации.

Отображается:

- повторный `login`;
- сообщение о том, что логин свободен или уже занят;
- баланс кошелька с проверкой порога `0.020 SOL`;
- имя homeserver;
- пометка, если используется стандартное значение `homeserver1`;
- отдельное предупреждение, если `Wi-Fi` не подключён.

Кнопки:

- `ЗАРЕГИСТРИРОВАТЬ В СИЯНИИ`
- `BACK`

Поведение:

- если `Wi-Fi` не подключён, на экране прямо показывается уведомление об этом и кнопка регистрации недоступна;
- если `login` уже занят в `shine_users`, регистрация недоступна;
- если баланс меньше `0.020 SOL`, на экране показывается соответствующая ошибка;
- если все проверки пройдены, кнопка регистрации активна и запускает on-chain регистрацию.

## Экран REGISTER_ACCOUNT_RESULT

Показывает результат отправки регистрации.

Отображается:

- текст успеха или ошибки;
- подробное сообщение;
- при успехе краткий `user_pda`;
- при успехе краткий `tx signature`.

Кнопки:

- `BACK HOME`
- `ACCOUNT`

Поведение:

- после успешной регистрации данные `user_pda` и `tx signature` сохраняются в `NVS`;
- при ошибке на экране показывается причина отказа;
- если ошибку вернул `sendTransaction`, экран старается показать не только общий текст, но и детали `RPC`/preflight/simulate-логов.

## Экран HOMESERVER_PDA_CONFIRM

Показывает, что именно не так с homeserver-секцией уже существующей пользовательской `PDA`.

Отображается:

- причина (`homeserver` отсутствует в `PDA` или ключ не совпадает с локальным секретом);
- `login`;
- имя `homeserver`;
- короткое пояснение, что именно будет сделано.

Кнопки:

- `ADD HOMESERVER` или `FIX HOMESERVER PASSWORD`
- `BACK`

Поведение:

- если `Wi-Fi` не подключён, действие недоступно;
- экран не создаёт нового пользователя, а запускает `update_user_pda`;
- при `ADD HOMESERVER` в блок `sessions` добавляется запись `session_type=100`;
- при `FIX HOMESERVER PASSWORD` обновляется публичный ключ уже существующей записи `homeserver`.

## Экран HOMESERVER_PDA_RESULT

Показывает результат обновления `sessions` в пользовательской `PDA`.

Отображается:

- успех или ошибка;
- короткое сообщение;
- при успехе краткий `tx signature`.

Кнопки:

- `BACK HOME`
- `ACCOUNT`

Поведение:

- при ошибке текст ошибки сохраняется в ту же USB/NVS-диагностику, что и регистрация;
- после успешного обновления выполняется повторная проверка `PDA`, и основной экран должен перейти в состояние `ok`.

## Экран STATUS

Показывает сводку:

- логин;
- homeserver;
- есть ли секрет;
- зарегистрировано ли устройство;
- подключён ли Wi-Fi;
- доступны ли серверы;
- хватает ли баланса;
- находится ли устройство онлайн;
- краткий отпечаток `PDA` или `tx`.

Кнопки:

- `Назад`
- `Обновить статус`

`Обновить статус` в прототипе не делает сеть, а просто перерисовывает текущие вычисленные состояния.

## Экран CONNECTION

Показывает:

- `Wi-Fi`: готов / не готов;
- `Серверы`: готовы / не готовы;
- `Онлайн`: да / нет.

Кнопки:

- `Wi-Fi`
- `Серверы`
- `Подключить`
- `Отключить`
- `Назад`

Поведение:

- `Подключить` переводит устройство в `online=true`, если `Wi-Fi` реально подключён и серверы реально проверены;
- `Отключить` переводит устройство в `online=false`.

## Экран WIFI_EDIT

Поля:

- `SSID`
- `Пароль`

Кнопки:

- `Изменить SSID`
- `Изменить пароль`
- `Проверить`
- `Сбросить`
- `Назад`

Поведение:

- `Проверить` делает реальную попытку подключения к `Wi-Fi`;
- `Сбросить` очищает обе строки и ставит `wifiReady=false`.

## Экран SERVERS

Поля:

- `API URL`
- `RPC URL`
- `WS URL`

Кнопки:

- `Изменить API`
- `Изменить RPC`
- `Изменить WS`
- `Проверить`
- `Тестовые`
- `Назад`

Поведение:

- `Тестовые` подставляет дефолтные тестовые значения;
- `Проверить` делает реальные сетевые проверки:
  - `API URL` должен отвечать по `HTTP/HTTPS`;
  - `RPC URL` должен отвечать на `Solana JSON-RPC`;
  - `WS URL` должен принимать `TCP/TLS`-соединение.

## Экран ACCOUNT

Показывает:

- логин;
- имя homeserver;
- статус секрета;
- короткий отпечаток секрета;
- статус регистрации;
- короткий отпечаток `PDA` или `tx`.

Кнопки:

- `Изменить логин`
- `Секрет`
- `Имя homeserver`
- `Сгенерировать`
- `Очистить`
- `Назад`

Поведение:

- `Сгенерировать` создаёт новый `master secret` и пересчитывает из него `device`-кошелёк;
- `Очистить` удаляет секрет, адрес кошелька, `PDA`, `tx`, регистрацию и онлайн-статус;
- логин приводится к нижнему регистру и trim.
- после успешной регистрации на экране сохраняются и отображаются краткие отпечатки `PDA` и `TX`.

## Экран WALLET

Показывает:

- кнопку `Wallet: <selected wallet name>`;
- строку текущего статуса/баланса активного кошелька;
- сокращённый публичный ключ активного кошелька.

Кнопки:

- `Wallet: <selected wallet name>`
- `SHOW BALANCE`
- `SHOW WALLET QR`

Поведение:

- верхняя кнопка открывает экран выбора кошелька `WALLET_SELECT`;
- `Показать баланс кошелька` читает реальный баланс именно активного выбранного кошелька из `Solana RPC`;
- `Показать QR-код кошелька` открывает экран `WALLET_QR`;
- этот экран не меняет логику Solana-регистрации пользователя: on-chain регистрация и проверки `PDA` по-прежнему завязаны на `client key`.

## Экран WALLET_SELECT

Показывает:

- строку `Current: <selected wallet name>`;
- три кнопки выбора:
  - `ClientKey`
  - `RootKey`
  - `Custom` или `Custom: <имя>`;
- у текущего выбора видна галочка.

Поведение:

- `ClientKey` активирует кошелёк, выведенный из suffix `client.key`;
- `RootKey` активирует кошелёк, выведенный из suffix `root.key`;
- `Custom` использует derivation:
  `sha256(base64(secret32) + "|wallet." + customName)`;
- если имя `custom`-кошелька ещё не задано, нажатие `Custom` открывает экран текстового ввода;
- если `custom` уже выбран, повторное нажатие на него открывает экран редактирования имени;
- после выбора кошелька устройство возвращается на экран `WALLET`.

## Экран WALLET_QR

Экран показывает:

- крупный реальный `QR` для строки `solana:<wallet_address>`;
- снизу крупный текст самого адреса кошелька.

Поведение:

- отдельная текстовая подсказка возврата не показывается;
- возврат на главный экран выполняется обычным тапом по экрану.

Показывает:

- QR-код для строки вида:
  `solana:<wallet>`;
- мелкую подпись с полным адресом кошелька под QR.

Поведение:

- QR должен быть сканируемым, а не декоративным;
- адрес кошелька берётся из текущего активного выбранного кошелька;
- нажатие в любую точку экрана возвращает пользователя на `WALLET`.

## Экран WALLET_SIGN_REQUEST

Экран показывается, когда браузерное wallet-расширение присылает на ESP32 запрос `sign_transaction`.

Показывает:

- заголовок `SIGN REQUEST`;
- вопрос о подписи транзакции текущим активным кошельком;
- сокращённый публичный ключ кошелька;
- комментарий, присланный полем `comment`;
- две кнопки:
  - `REJECT`
  - `APPROVE`

Поведение:

- если пользователь нажимает `APPROVE`, ESP32 подписывает транзакцию текущим активным кошельком и отправляет ответ в расширение;
- если пользователь нажимает `REJECT`, ESP32 отправляет отказ `rejected_by_user`;
- пока запрос активен, свайпом этот экран не закрывается;
- после ответа расширению устройство возвращается на предыдущий экран.

## Экран REQUESTS

Экран доступен только если homeserver уже авторизован в SHiNE.

Показывает:

- слева сверху кнопку `REFRESH`;
- заголовок `REQUESTS:` немного правее стандартного левого положения;
- справа сверху только большую цифру числа активных заявок;
- ниже прокручиваемый список активных pairing-заявок;
- на экране одновременно видны примерно две плитки.

Каждая плитка показывает:

- код подключения из `10` цифр в виде `5` пар: `XX XX XX XX XX`;
- строку `Session: <platform/name>`;
- строку `Kind: Client session` или `Kind: Wallet session`.

Поведение:

- список берётся из живой операции `ListTrustedDeviceLoginRequests`;
- если заявок нет, экран показывает `No active requests`;
- отдельная строка вида `Active requests: N` на этом экране не показывается;
- вертикальный скролл позволяет просматривать все активные заявки;
- нажатие по плитке открывает `REQUEST_DETAIL`;
- свайп вправо возвращает в `SETTINGS`.

## Экран REQUEST_DETAIL

Показывает детали выбранной pairing-заявки:

- вопрос `Connect session ...?`;
- код подключения `XX XX XX XX XX`;
- строку `Session: <platform/name>`;
- строку `Kind: Client session` или `Kind: Wallet session`;
- пояснение:
  - для client session: `Only client key will be transferred. No additional keys will be sent.`
  - для wallet session: `No keys will be transferred.`

Кнопки:

- `YES`
- `NO`

Поведение:

- `YES` подтверждает заявку:
  - для client session устройство передаёт только `client key`;
  - для wallet session устройство выпускает отдельную `wallet-session` без передачи ключей;
- `NO` отклоняет заявку;
- после любого решения устройство возвращается в список `REQUESTS` и обновляет его;
- свайп вправо возвращает в `REQUESTS`.

## Экран SETTINGS

Показывает вертикальное меню крупных пунктов.

Если homeserver ещё не авторизован в SHiNE:

- `1. Wi-Fi`
- `2. Server`
- `3. Account`

Если homeserver уже авторизован:

- `1. Device requests`
- `2. Wi-Fi`
- `3. Server`
- `4. Account`

Поведение:

- одновременно видны только две карточки;
- список листается свайпом вверх/вниз;
- свайп вправо возвращает на `HOME`;
- пункт `Device requests` должен быть первым и появляется только для авторизованного homeserver.

## Экран PIN_EDIT

Используется для ввода нового PIN.

Правила:

- допустимы только цифры;
- длина PIN: 4..8 символов;
- после сохранения новый PIN немедленно пишется в `NVS`.

## Экран TEXT_INPUT

Это общий экран редактирования текстовых полей.

Используется для:

- `SSID`
- `Пароль Wi-Fi`
- `Логин`
- `Имя homeserver`
- `API URL`
- `RPC URL`
- `WS URL`

Состав экрана:

- заголовок поля;
- текущее значение;
- программная клавиатура;
- кнопки `Стереть`, `OK`, `Отмена`.

## Экран CONFIRM

Это модальный экран подтверждения.

Используется для:

- регистрации;
- очистки секрета;
- полного сброса.

Кнопки:

- `Подтвердить`
- `Отмена`

## Сценарий первой настройки

Ожидаемый путь пользователя:

1. открыть устройство сразу после старта; экран PIN временно не требуется;
2. открыть `Подключение -> Wi-Fi`;
3. ввести `SSID` и пароль, нажать `Проверить`;
4. открыть `Подключение -> Серверы`;
5. проверить или задать `SHiNE server login` (по умолчанию `shineupme`);
6. открыть `Аккаунт`;
7. ввести логин;
8. задать имя homeserver;
9. сгенерировать секрет;
10. открыть `Кошелёк`;
11. при необходимости пополнить баланс;
12. вернуться на `HOME`;
13. нажать `REGISTER ACCOUNT`;
14. на экране проверки ещё раз увидеть `login`, статус свободного `PDA`, баланс, `homeserver1`, серверный login и при необходимости сообщение о неподключённом `Wi-Fi`;
15. нажать `ЗАРЕГИСТРИРОВАТЬ В СИЯНИИ`;
16. после завершения увидеть либо экран успеха с `user_pda` и `tx signature`, либо подробную ошибку;
17. после успешной регистрации увидеть статус `Homeserver активен`.

Примечание:

- устройство реально отправляет `create_user_pda` в `shine_users`, а после подтверждения сохраняет `PDA` и `tx signature`;
- при первой регистрации для обычного `user PDA` не заполняется `serverAddress`, а `accessServers` получает `shineupme` или другой выбранный `SHiNE server login`.

## Сценарий входящего запроса

1. открыть `Запросы`;
2. выбрать один из запросов;
3. прочитать детали;
4. нажать `Разрешить` или `Отклонить`;
5. убедиться, что статус запроса изменился.

## Временный режим текста

В текущей диагностической версии:

- строковые литералы экранного UI должны оставаться английскими ASCII-совместимыми;
- возвращение кириллицы допустимо только после отдельной доработки шрифтов и реальной проверки на устройстве;
- рендер выполняется стандартным шрифтом `Arduino_GFX`;
- это обходной режим, пока `U8g2`-шрифты на устройстве не начнут рисоваться стабильно.

## Критерии ручной проверки

Минимально нужно проверить:

1. устройство загружается и сразу открывает `HOME`; экран блокировки временно отключён;
2. весь экранный текст отображается читаемо на английском без замены символов;
3. ввод по экранной клавиатуре работает;
4. после перезагрузки сохранённые поля остаются в памяти;
5. секрет и адрес кошелька сохраняются на устройстве;
6. экран `QR и URI` рисует читаемый QR-код;
7. регистрация блокируется, пока условия не выполнены;
8. после выполнения условий регистрация становится доступной;
9. список запросов и экран подтверждения работают;
10. полный сброс действительно очищает сохранённое состояние.
