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

4.8 KiB
Raw Blame History

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 — правила кода приложения перестают быть выведенными из выбора, а компонент и зависимость сборки появляются в описании устройства.