Files
transcriber/openspec/changes/archive/2026-08-15-spa-skeleton/proposal.md
T
av 663021f712 приложение собрано каркасом и вшито в бинарник
- заведён каталог web/ — Vue 3, роутер пятой версии, сборка Vite; собранное
  вшивается через go:embed и раздаётся корневым маршрутом: разметка на
  неизвестном пути вне корней сервиса, отказ контракта внутри корня
- перечень корней сервиса стал единой точкой и порождает регистрацию маршрутов,
  а не описывает её; журнал раздачи пишет исход и длину пути, но не сам путь
- шаг front зовёт Node контейнером docker — Biome, юнит-тесты Vue и сборка
  входят в гейт, а в Dockerfile появилась ступень приложения
2026-08-15 18:51:05 +03:00

57 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 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` — правила кода
приложения перестают быть выведенными из выбора, а компонент и зависимость
сборки появляются в описании устройства.