Один бинарь на stdlib, ноль зависимостей: подкоманды serve, vapid, version; статика из embed с ETag и Cache-Control: no-cache; /healthz; заголовки безопасности ADR-021 на всех ответах, включая ошибки; лимит тела 32 КиБ. Путь в логе — в percent-форме: подделать строку журнала запросом нельзя. Ни IP, ни ника, ни query в логах нет. Клиент — знак «Скобы» и слово bare: без script-тегов, inline-стилей и внешних ресурсов. ADR-025: go:embed не выходит за каталог пакета, поэтому объявление статики живёт в корне модуля, а клиент остаётся в web/. ADR-026: 413 отдаётся кодом too_large, неподдерживаемый метод — 404; оба добавлены в перечень protocol.md. Сервер: пользователь bare, /opt/bare, /var/lib/bare, /etc/bare/env 0600, systemd-юнит, nginx с сертификатом certbot (плагин nginx, как у соседей). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DbCjVfTFq4ZFG8juD45YJ
18 lines
1.9 KiB
Markdown
18 lines
1.9 KiB
Markdown
# ADR-025: Встраивание статики объявляется в корне модуля
|
||
|
||
## Контекст
|
||
|
||
ADR-022 требует один артефакт деплоя: клиентская статика вкомпилирована в бинарь. Раскладка в `docs/plan.md` кладёт отдачу статики в `internal/web/`, а сам клиент — в `web/` в корне. Директива `//go:embed` встраивает только файлы каталога своего пакета и ниже: из `internal/web/` до корневого `web/` не дотянуться. Варианты — перенести клиент внутрь `internal/web/`, продублировать файлы или объявить встраивание в корне.
|
||
|
||
## Решение
|
||
|
||
Клиент остаётся в `web/` в корне: путь в репозитории совпадает с путём в URL, и его видно первым в дереве. Встраивание объявляется рядом — файл `embed.go` в корне модуля, `package bare`, `//go:embed web` и `var Web embed.FS`. Логики в пакете нет, только объявление.
|
||
|
||
`internal/web/` получает подкаталог через `fs.Sub(bare.Web, "web")` и отвечает за отдачу: ETag, `Cache-Control`, `Content-Type`, 304, `Service-Worker-Allowed`.
|
||
|
||
## Следствия
|
||
|
||
- В корне модуля появляется пакет `bare` из одного файла — он не растёт: всё, что не объявление `embed.FS`, идёт в `internal/`.
|
||
- `internal/web/` импортирует корневой пакет; обратной зависимости нет и не будет.
|
||
- Раскладка в `docs/plan.md` дополнена строкой `embed.go`; в остальном не меняется.
|