docs: drop the closed phase-14 hardening out of the plan
The plan holds only open work, but section A still retold what phase 14 implemented — security headers, the origin check, the __Host- cookie, the setup-token documentation — which the CHANGELOG and git history already describe in full. What is left of A is the two things deliberately *not* closed: the POST that carries neither Sec-Fetch-Site nor Origin, and the absence of session-bound CSRF tokens. The XSS note folds into the token item, which is the only place it was doing work; the "proxy must pass Host through" requirement is documented in the README and in the CHANGELOG, so it goes. Section A's numbered items are gone with it, so B-D renumber from 1. Nothing else in the file has been implemented: the README still says nothing about restarts signing the admin out or about the copytruncate rotation window, SELFPOST_HOSTNAME still falls back to localhost without a warning, and CI still runs only vet and unit tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+18
-28
@@ -11,20 +11,16 @@
|
|||||||
|
|
||||||
## Открытые вопросы — требует внимания и обсуждения (перед фиксацией v1.0)
|
## Открытые вопросы — требует внимания и обсуждения (перед фиксацией v1.0)
|
||||||
|
|
||||||
Базовый план 0→11 выполнен и **соответствует ТЗ** (все обязательные пункты 7.6
|
Ниже — то, что **выходит за букву ТЗ**, но заслуживает решения перед тем, как
|
||||||
подтверждены аудитом Фазы 11). Ниже — то, что **выходит за букву ТЗ**, но
|
считать v1.0 «финальным». Ничего из этого **не является дефектом
|
||||||
заслуживает решения перед тем, как считать v1.0 «финальным». Ничего из этого
|
соответствия**; это осознанные компромиссы и потенциальные улучшения. Каждый
|
||||||
**не является дефектом соответствия**; это осознанные компромиссы и
|
пункт — решение «делаем в v1.x / откладываем в 2.x / оставляем как есть»,
|
||||||
потенциальные улучшения. Каждый пункт — решение «делаем в v1.x / откладываем в
|
принимается пользователем.
|
||||||
2.x / оставляем как есть», принимается пользователем.
|
|
||||||
|
|
||||||
### A. Безопасность — hardening сверх обязательного 7.6
|
### A. Безопасность — принятые риски
|
||||||
|
|
||||||
Все четыре пункта раздела — security-заголовки, проверка origin, cookie
|
Hardening сверх обязательного 7.6 закрыт. Здесь остаётся только то, что закрыто
|
||||||
`__Host-` с обнаружением дублей и документация про `/data/setup-token` —
|
**сознательно не было**, чтобы это не потерялось:
|
||||||
**реализованы (Фаза 14)**; что именно сделано, см. [CHANGELOG.md](../CHANGELOG.md)
|
|
||||||
и `git log`. Здесь остаётся только то, что закрыто **сознательно не было**,
|
|
||||||
чтобы это не потерялось:
|
|
||||||
|
|
||||||
- **Принятый риск: `POST` без `Sec-Fetch-Site` и без `Origin` пропускается.**
|
- **Принятый риск: `POST` без `Sec-Fetch-Site` и без `Origin` пропускается.**
|
||||||
Клиент, не посылающий ни одного из двух — по-настоящему старый браузер или
|
Клиент, не посылающий ни одного из двух — по-настоящему старый браузер или
|
||||||
@@ -38,31 +34,25 @@
|
|||||||
закрывает соседний поддомен, но зависит от поведения браузера; токен — нет.
|
закрывает соседний поддомен, но зависит от поведения браузера; токен — нет.
|
||||||
Цена — скрытое поле примерно в двух десятках форм. Триггером вернуться к
|
Цена — скрытое поле примерно в двух десятках форм. Триггером вернуться к
|
||||||
вопросу считать появление требования «устойчиво независимо от браузера».
|
вопросу считать появление требования «устойчиво независимо от браузера».
|
||||||
- **XSS внутри самой панели** не закрывается ни проверкой origin, ни токенами:
|
От XSS внутри самой панели не спас бы и токен: код, исполняющийся в origin
|
||||||
код, исполняющийся в origin панели, отправит запрос сам. Против него
|
панели, отправит запрос сам — против этого работают автоэкранирование
|
||||||
работают автоэкранирование `html/template` (7.6.7) и CSP — поэтому шаблоны
|
`html/template` (7.6.7) и CSP, поэтому шаблоны не должны содержать
|
||||||
не должны содержать inline-скриптов и inline-стилей; это закреплено
|
inline-скриптов и inline-стилей.
|
||||||
тестом-стражем в [internal/web/templates_test.go](../internal/web/templates_test.go),
|
|
||||||
а не только договорённостью.
|
|
||||||
- **Требование к развёртыванию, появившееся вместе с проверкой origin:**
|
|
||||||
reverse-proxy обязан передавать исходный заголовок `Host`. Все четыре
|
|
||||||
поставляемых фрагмента это делают; чужой прокси, переписывающий `Host`,
|
|
||||||
превратит каждый `POST` в `403` (в лог пишутся обе сравниваемые стороны).
|
|
||||||
|
|
||||||
### B. Надёжность и эксплуатация
|
### B. Надёжность и эксплуатация
|
||||||
|
|
||||||
5. **Сессии только в памяти** — рестарт/редеплой разлогинивает админа (по ТЗ 9 допустимо). Плюс: absolute TTL 12ч без отдельного idle-timeout и без ротации токена при логине (session-fixation здесь неактуален, т.к. токен выдаётся только после аутентификации). Оставить; отметить поведение в README.
|
1. **Сессии только в памяти** — рестарт/редеплой разлогинивает админа (по ТЗ 9 допустимо). Плюс: absolute TTL 12ч без отдельного idle-timeout и без ротации токена при логине (session-fixation здесь неактуален, т.к. токен выдаётся только после аутентификации). Оставить; отметить поведение в README.
|
||||||
6. **Окно потери строк мониторингового лога при ротации** (`copytruncate`, Фаза 10) — несколько строк `mail.log` могут потеряться в момент ротации. Приемлемо для мониторинга; зафиксировать как известное свойство.
|
2. **Окно потери строк мониторингового лога при ротации** (`copytruncate`, Фаза 10) — несколько строк `mail.log` могут потеряться в момент ротации. Приемлемо для мониторинга; зафиксировать как известное свойство.
|
||||||
7. **Поведение при незаданном `SELFPOST_HOSTNAME`** — realm SASL и хост setup-ссылки падают в `localhost`. Для реального деплоя hostname обязателен. **Вопрос:** делать ли фатальную проверку «hostname обязателен» на старте (сейчас — мягкий fallback) — предложение: предупреждать громко в лог, но не падать.
|
3. **Поведение при незаданном `SELFPOST_HOSTNAME`** — realm SASL и хост setup-ссылки падают в `localhost`. Для реального деплоя hostname обязателен. **Вопрос:** делать ли фатальную проверку «hostname обязателен» на старте (сейчас — мягкий fallback) — предложение: предупреждать громко в лог, но не падать.
|
||||||
|
|
||||||
### C. CI и тесты
|
### C. CI и тесты
|
||||||
|
|
||||||
8. **Нет интеграционного/e2e-теста в CI.** Контейнерные e2e каждой фазы прогонялись вручную и задокументированы в git-истории, но не автоматизированы. Для v1.0 — вероятно, оставить ручными; для долгой поддержки — кандидат на smoke-тест (поднять контейнер, setup→login→add domain→auth SMTP) в CI.
|
4. **Нет интеграционного/e2e-теста в CI.** Контейнерные e2e каждой фазы прогонялись вручную и задокументированы в git-истории, но не автоматизированы. Для v1.0 — вероятно, оставить ручными; для долгой поддержки — кандидат на smoke-тест (поднять контейнер, setup→login→add domain→auth SMTP) в CI.
|
||||||
|
|
||||||
### D. Указатель на объём 2.x
|
### D. Указатель на объём 2.x
|
||||||
|
|
||||||
9. **Входящий релей и pluggable-антиспам** вынесены в опциональные фазы O1+ ниже (линия 2.x.x, вне v1.0, только по согласованию — ТЗ 12.6). Здесь перечислены лишь как напоминание, что это **сознательно отложенный объём**, а не забытый.
|
5. **Входящий релей и pluggable-антиспам** вынесены в опциональные фазы O1+ ниже (линия 2.x.x, вне v1.0, только по согласованию — ТЗ 12.6). Здесь перечислены лишь как напоминание, что это **сознательно отложенный объём**, а не забытый.
|
||||||
10. **2FA и несколько администраторов** — вне объёма v1.x (ТЗ этого не требует: один админ). Кандидаты на 2.x, если понадобятся.
|
6. **2FA и несколько администраторов** — вне объёма v1.x (ТЗ этого не требует: один админ). Кандидаты на 2.x, если понадобятся.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user