diff --git a/docs/architecture.md b/docs/architecture.md index e7ddbf7..680037d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -245,9 +245,9 @@ сборкой Vite — 2026-08-11, [ADR](adr/ADR-2026-08-11-spa-on-vue.md), сравнение кандидатов в [research/spa-framework.md](research/spa-framework.md). Тем же решением Node - входит в гейт и слоем в сборку образа. Пишет это `spa-skeleton`; во что - обходится слой Node в образе, не замерялось. Не решено, брать ли готовый набор - компонентов. + входит в гейт и слоем в сборку образа; как именно он зовётся — решением + [ADR](adr/ADR-2026-08-15-node-in-container-not-on-machine.md) 2026-08-15. + Не решено, брать ли готовый набор компонентов. - **Уведомления.** Пользователь веба узнаёт о готовности только опросом карточки. Доставку решено брать внешнюю — apprise как отправитель, ntfy как канал; Web Push с VAPID отвергнут. Появляется внешняя зависимость, которой сегодня нет, и diff --git a/docs/conventions/web-ui.md b/docs/conventions/web-ui.md index 7eda56f..34a11ce 100644 --- a/docs/conventions/web-ui.md +++ b/docs/conventions/web-ui.md @@ -70,8 +70,8 @@ включаем: сборочная надстройка роутера пятой версии стоит 34 пакета в установке и на нашем числе маршрутов не окупается ([research/spa-framework.md](../research/spa-framework.md), «Vue»). Сколько - экранов и какие — не здесь: состав нормирует спека приложения, а до неё его - держит [spa-skeleton](../../tasks/items/spa-skeleton.md). + экранов и какие — не здесь: состав нормирует спека + [webapp](../../openspec/specs/webapp/spec.md). - **Адреса обычные, а не после решётки** (`createWebHistory`). Отсюда требование к серверу: неизвестный путь **вне корней сервиса** отдаёт `index.html`, а не `404`; путь внутри корня в приложение не проваливается никогда. Корней diff --git a/docs/research/spa-framework.md b/docs/research/spa-framework.md index 6c3a274..b816674 100644 --- a/docs/research/spa-framework.md +++ b/docs/research/spa-framework.md @@ -25,8 +25,8 @@ Nuxt, Next — не рассматривали: конвенция правил, и в сборке он у всех троих совпал до байта (883 Б), что и подтверждает одинаковость экрана. - **Четыре маршрута** — тот же экран плюс три заглушки и переходы между ними: - столько экранов заводит задача - [spa-skeleton](../../tasks/items/spa-skeleton.md). Роутеры + столько экранов предполагала задача `spa-skeleton`, сделанная 2026-08-15. + Роутеры `svelte-spa-router` 5.1.1, `vue-router` 5.2.0 и 4.6.4, `react-router` 8.3.0. - **Размеры** — `stat -c%s` и `gzip -9c | wc -c` по файлам `dist/`. Числа Vite в своём выводе печатает по другому уровню сжатия, поэтому в таблицах ниже стоят diff --git a/tasks/BACKLOG.md b/tasks/BACKLOG.md index ca4355b..44a2c3e 100644 --- a/tasks/BACKLOG.md +++ b/tasks/BACKLOG.md @@ -43,7 +43,6 @@ ## Очередь -- [✨ Собрать каркас приложения и раздать его из бинарника](items/spa-skeleton.md) — Экранов нет и собирать их нечем: ни сборки фронтенда, ни раздачи статики в проекте не существует. - [✨ Сделать экран загрузки записи и её состояния](items/upload-and-status-screen.md) — Первое, ради чего приложение открывают: отдать файл и увидеть, что с ним происходит. - [✨ Сделать экран списка своих записей и чтения текста](items/records-list-screen.md) — Расшифровка сегодня доходит одним сообщением и теряется в переписке; вернуться к ней через неделю нечем. - [✨ Дать владельцу править запись, возвращать её в работу и видеть её путь](items/audiorecord-actions.md) — С записью нельзя сделать ничего: заголовок ставит одна языковая модель, остановленную возвращает в работу только владелец сервиса в панели, а журнал событий пишется и не читается никем, кроме него же diff --git a/tasks/items/spa-skeleton.md b/tasks/items/spa-skeleton.md deleted file mode 100644 index 43fbf0a..0000000 --- a/tasks/items/spa-skeleton.md +++ /dev/null @@ -1,55 +0,0 @@ -# ✨ Собрать каркас приложения и раздать его из бинарника - -- **Тип:** feature -- **Категория:** Очередь — Каркас идёт сразу за контрактом: на нём стоят все экраны, а сам он ждёт готовой формы ответов -- **Зачем:** Экранов нет и собирать их нечем: ни сборки фронтенда, ни раздачи статики в проекте не существует. - -Каркас готовит экраны — загрузку, рубеж записи, чтение текста и список, — но сам -по себе пользователю ничего не даёт. Видимое от него одно: приложение -открывается и достаёт данные с живого сервера, а не отдаёт пустую страницу. - -Фреймворк выбран 2026-08-11 — Vue 3 с роутером пятой версии и сборкой Vite -([ADR](../../docs/adr/ADR-2026-08-11-spa-on-vue.md)); правила кода приложения -лежат в [conventions/web-ui.md](../../docs/conventions/web-ui.md). - -## Затрагивает - -- новый каталог фронтенда: исходники, зависимости, конфигурация сборки; -- роут, отдающий `index.html` на неизвестный путь вне корней сервиса — `/api/` - у хранилища, `/app/` у приложения, `/auth/` у входа, `/_/` у панели, плюс - `/health` и `/metrics`: адреса маршрутов обычные, а не после решётки; -- `Taskfile.yml` — шаг сборки статики и его место в `task gate` и `task image`; -- `Dockerfile` — сборка статики внутри образа, чтобы выкладка не зависела от - машины разработчика; -- раздача статики из бинарника через `go:embed` и роут под неё; -- `.gitignore` — каталог зависимостей и собранная статика; -- `docs/conventions/web-ui.md` — переписывается под выбранный фреймворк; -- `docs/architecture.md` — новый компонент и новая внешняя зависимость сборки. - -## Критерии приёмки - -- Статика собирается одной командой и вшивается в бинарник: запущенный бинарник - отдаёт приложение без каталога рядом. Оракул — сборка, запуск бинарника из - пустого каталога, запрос корня возвращает разметку приложения. -- Образ собирается на чистой машине без предустановленного окружения фронтенда. - Оракул — `task image` без локально установленных зависимостей фронтенда. -- Приложение показывает, кто вошёл, и обращается к API живого сервера. Оракул — - тест либо ручная проверка на запущенном сервере с сессией. -- Шаг сборки статики входит в `task gate` и краснеет при ошибке сборки. Оракул — - намеренно сломанный исходник роняет `task gate`. -- Обновление страницы на любом маршруте приложения открывает тот же экран, а - адрес внутри корня сервиса в приложение не проваливается. Оракул — тест на три - запроса: неизвестный путь вне корней отдаёт разметку, неизвестный путь внутри - `/api/` и внутри `/app/` отдаёт ошибку контракта. - -## Рамки - -Экранов, кроме заглушки с именем вошедшего, не делаем — это `upload-and-status-screen` -и `records-list-screen`. Установку на телефон не делаем — это `installable-pwa`. -Готовый набор компонентов не берём: он не выбран, а способен удвоить собранный -файл. - -Шаг сборки входит в гейт и в образ решением -[ADR](../../docs/adr/ADR-2026-08-11-spa-on-vue.md) 2026-08-11 — заново это -решение не принимается. Во что слой Node обходится образу по времени и по весу, -не замерялось: замер делает эта задача.