Роадмап: web-access переименована под приложение, которое ставится на телефон; заведена цель ready-notification — уведомление о готовности без открытого приложения. Беклог: десять задач. Многопользовательская цепочка (oidc-login, record-ownership, telegram-account-link), веб (json-api-for-spa, spa-skeleton, upload-and-status-screen, records-list-screen, installable-pwa), уведомления через apprise и ntfy, разведка выбора фреймворка. Очередь: долги, хранилище, вход, приложение. Решение сменилось с htmx на SPA, поэтому conventions/web-ui.md снята целиком и оставлена честной строкой до итога разведки. Открытые вопросы архитектуры, границы паспорта и триггеры метки ревью приведены в соответствие.
3.3 KiB
Веб-UI
Конвенция: как мы пишем код приложения. Это правила оформления кода (How), а не спецификация поведения — что именно приложение показывает и какие действия обязано поддерживать, живёт в спеке OpenSpec.
Фреймворк не выбран, и до выбора эта конвенция пуста. Здесь стоит только то,
что решено и от фреймворка не зависит; всё остальное появится по итогу разведки
spa-framework-choice, которая же заведёт запись в research/ и ADR.
Прежняя редакция описывала htmx с прямым запретом на шаг сборки и реактивные
фреймворки. Решение сменилось на SPA 2026-08-10, и та редакция снята целиком:
частичная подмена фрагментов, ветвление по HX-Request и деградация без JS к
SPA не относятся ни одним пунктом.
Логирование запросов — logging.md. Трансляция доменных ошибок наружу — errors.md.
Что решено
- Приложение — SPA, а не страницы, отрисованные сервером. Сервер отдаёт контракт данных, разметку собирает клиент.
- Приложение ставится на телефон и запускается с ярлыка: манифест, иконки, service worker.
- Статика вшивается в бинарник через
go:embedи раздаётся им же. Внешнего веб-сервера под статику не заводим, бинарник остаётся самодостаточным. - Шрифты и скрипты — со своего хоста, без внешних. Внешних ресурсов времени выполнения нет.
- Офлайн-чтения расшифровок и очереди отправки без сети не делаем — граница цели web-access. Без сети приложение показывает состояние, а не пустой экран.
- Web Push не делаем: уведомления идут через apprise и ntfy, цель ready-notification.
- Записи звука в приложении не делаем — файл выбирают системным диалогом.
Что не решено
Фреймворк, форма сборки, способ хранения состояния на клиенте, правила
разбиения на компоненты, обращение к API и показ ошибок. Всё это — предмет
spa-framework-choice; писать их наперёд, не зная фреймворка, значит написать
правила, которые придётся выбросить второй раз.