- заведён каталог web/ — Vue 3, роутер пятой версии, сборка Vite; собранное вшивается через go:embed и раздаётся корневым маршрутом: разметка на неизвестном пути вне корней сервиса, отказ контракта внутри корня - перечень корней сервиса стал единой точкой и порождает регистрацию маршрутов, а не описывает её; журнал раздачи пишет исход и длину пути, но не сам путь - шаг front зовёт Node контейнером docker — Biome, юнит-тесты Vue и сборка входят в гейт, а в Dockerfile появилась ступень приложения
57 lines
4.8 KiB
Markdown
57 lines
4.8 KiB
Markdown
## Why
|
||
|
||
Сервис отдаёт данные, но человеку их показать нечем: экранов нет вовсе, а
|
||
браузер, открывший адрес сервиса, получает поверхность хранилища вместо
|
||
приложения. Два основных сценария паспорта — «семейный архив» и «возвращение к
|
||
записи» — не работают ни один, и упираются они в одно: приложения не существует.
|
||
|
||
Каркас сам по себе экранов не приносит. Он приносит то, на чём они стоят:
|
||
собранное приложение, которое сервис отдаёт браузером, открывается по любому
|
||
своему адресу и показывает вошедшего, спросив об этом сервис.
|
||
|
||
## What Changes
|
||
|
||
- Сервис начинает отдавать браузеру **приложение**: разметку и её ресурсы. Они
|
||
лежат внутри самого бинарника, отдельного каталога рядом с ним не требуется, и
|
||
внешнего веб-сервера под них не заводится.
|
||
- Неизвестный адрес **вне корней сервиса** отдаёт разметку приложения, а не
|
||
отказ. Так обновление страницы посреди приложения открывает тот же экран, а не
|
||
ошибку. Корни перечислены поимённо, и адрес **внутри** корня в приложение не
|
||
проваливается никогда: отказ контракта остаётся отказом контракта.
|
||
- Разметка и её ресурсы отдаются **без сессии**: приложение само спрашивает
|
||
сервис, кто вошёл, и уводит ко входу, когда не вошёл никто. Требование сессии
|
||
на самой разметке отдавало бы отказ вместо экрана входа.
|
||
- Открытое приложение показывает **вошедшего** — то, что сервис ответил о нём, —
|
||
и это единственное, что оно сегодня показывает.
|
||
- В сборку приходит **шаг сборки приложения**: он входит в набор проверок и в
|
||
сборку образа. Спеками это не нормируется — у сборки другой потребитель, тот,
|
||
кто собирает.
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
- `webapp`: приложение в браузере — чем сервис его отдаёт, каким адресом оно
|
||
открывается, что делает обновление страницы посреди приложения и что человек
|
||
видит, открыв его.
|
||
|
||
### Modified Capabilities
|
||
- `access`: разметка приложения и её ресурсы пополняют перечень адресов,
|
||
открытых без сессии; сегодня в нём только проба здоровья и метрики.
|
||
|
||
## Impact
|
||
|
||
- новый каталог приложения: исходники, зависимости, настройка сборки;
|
||
- `internal/controller/http` — маршрут, отдающий разметку на неизвестном пути вне
|
||
корней, и раздача ресурсов приложения из бинарника;
|
||
- `Taskfile.yml` — шаг сборки приложения, его место в наборе проверок и в сборке
|
||
образа;
|
||
- `Dockerfile` — приложение собирается внутри образа, чтобы выкладка не зависела
|
||
от машины разработчика;
|
||
- `.gitignore` — каталог зависимостей и собранное приложение;
|
||
- новая внешняя зависимость сборки: Node и его установщик пакетов. На машину
|
||
разработчика они не ставятся — шаг сборки зовёт их контейнером, поэтому
|
||
требованием к машине становится docker, которым и так собирается образ;
|
||
- `docs/conventions/web-ui.md` и `docs/architecture.md` — правила кода
|
||
приложения перестают быть выведенными из выбора, а компонент и зависимость
|
||
сборки появляются в описании устройства.
|