docs: plan specification retirement via D9 migration map
After the documentation pass, specification.md moves to archive once its content lives in product, architecture, development, and security docs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,12 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- docs: documentation plan now targets retiring `specification.md` after D9 —
|
||||||
|
migration map to `product.md`, `architecture.md`, `development.md`, and
|
||||||
|
expanded `security.md`; D9 added to the release gate.
|
||||||
|
|
||||||
## [0.4.0] - 2026-08-04
|
## [0.4.0] - 2026-08-04
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+99
-50
@@ -1,11 +1,22 @@
|
|||||||
# План документации SelfPost
|
# План документации SelfPost
|
||||||
|
|
||||||
**Зачем этот файл.** Документация — часть поставки (ТЗ раздел 11, пп. 5, 7, 9),
|
**Зачем этот файл.** Документация — часть поставки (deliverables v1.0, пп. 5, 7, 9
|
||||||
а не сопроводительный текст. Перед тегом релиза она обязана описывать **то, что
|
в [specification.md](specification.md)), а не сопроводительный текст. Перед тегом
|
||||||
делает код**, а не то, что задумывалось: расхождение здесь — такой же дефект,
|
релиза она обязана описывать **то, что делает код**, а не то, что задумывалось:
|
||||||
как несоответствие ТЗ, только обнаруживает его пользователь на своём проде.
|
расхождение здесь — такой же дефект, как несоответствие требованиям, только
|
||||||
План описывает, из чего состоит пакет, как он сверяется с кодом, что уже
|
обнаруживает его пользователь на своём проде. План описывает, из чего состоит
|
||||||
разошлось (первый проход выполнен, результаты ниже) и что с этим делать.
|
пакет, как он сверяется с кодом, что уже разошлось (первый проход выполнен,
|
||||||
|
результаты ниже) и что с этим делать.
|
||||||
|
|
||||||
|
**Цель после выполнения плана:** [specification.md](specification.md) (ТЗ v1.0)
|
||||||
|
**выводится из обращения** — не потому что требования исчезли, а потому что v1.0
|
||||||
|
реализован и каждый блок ТЗ получает постоянный дом: пользовательское — в
|
||||||
|
README, устройство — в `architecture.md`, продуктовые границы — в
|
||||||
|
`product.md`, обязательная безопасность — в `security.md`, процесс разработки —
|
||||||
|
в `development.md`. Живой `specification.md` после этого держит два риска:
|
||||||
|
дублирование с кодом и ложное ощущение «источника истины», который уже не
|
||||||
|
сверяют. Задача **D9** — миграция остатков и снятие файла; до её закрытия
|
||||||
|
ссылки на ТЗ в этом файле — исторические.
|
||||||
|
|
||||||
**Место в общем плане:** документационный проход идёт вместе с **D.5**
|
**Место в общем плане:** документационный проход идёт вместе с **D.5**
|
||||||
([implementation-plan.md](implementation-plan.md)) — до тега следующего релиза,
|
([implementation-plan.md](implementation-plan.md)) — до тега следующего релиза,
|
||||||
@@ -32,38 +43,49 @@
|
|||||||
|
|
||||||
### Рабочие документы проекта (не поставка, но обязаны быть верны)
|
### Рабочие документы проекта (не поставка, но обязаны быть верны)
|
||||||
|
|
||||||
[specification.md](specification.md) — ТЗ v1.0, источник истины по требованиям.
|
[specification.md](specification.md) — ТЗ v1.0; **на вывод после D9** (см. карту
|
||||||
|
миграции ниже). До закрытия D9 — ещё используется как историческая ссылка в
|
||||||
|
находках раздела 3.
|
||||||
[implementation-plan.md](implementation-plan.md) — открытые вопросы для v1.0/v1.x.
|
[implementation-plan.md](implementation-plan.md) — открытые вопросы для v1.0/v1.x.
|
||||||
[roadmap.md](roadmap.md) — линия 2.x.x.
|
[roadmap.md](roadmap.md) — линия 2.x.x.
|
||||||
[progress.md](progress.md) — живой трекер, читается первым после `/clear`.
|
[progress.md](progress.md) — живой трекер, читается первым после `/clear`.
|
||||||
[security.md](security.md) — принятые риски. Этот файл — план по документации.
|
[security.md](security.md) — обязательные требования безопасности + принятые
|
||||||
|
риски. Этот файл — план по документации.
|
||||||
|
|
||||||
**Новое: `docs/architecture.md` и `docs/development.md` — нужны, решение
|
**Новые `product.md`, `architecture.md`, `development.md` — решение принято.**
|
||||||
принято.** ТЗ их не требует (ТЗ 11 не относит их к обязательной поставке), но
|
В обязательную поставку пользователю (README) они не входят, но без них
|
||||||
без них понимание устройства и повторная сборка проекта держатся только на
|
понимание проекта держится на памяти сессии. Их содержимое **заменяет** живой
|
||||||
памяти и контексте текущей сессии — то есть не переживают её потерю ни для
|
`specification.md` для всех будущих проходов — задачи **D8** и **D9**.
|
||||||
будущего контрибьютора, ни для будущего прохода без доступа к истории чата.
|
|
||||||
Обе — рабочие документы проекта (не часть поставки пользователю, не
|
|
||||||
упоминаются в README как обязательные), задача заведена в разделе 4 (**D8**).
|
|
||||||
|
|
||||||
- `docs/architecture.md` — компоненты контейнера (`supervisord`,
|
- `docs/product.md` — из ТЗ §1–3 и §4.1: зачем SelfPost, инфраструктурные
|
||||||
`postfix`, `opendkim`, `panel`, milter-цепочка) и как они связаны; путь
|
предпосылки, out of scope, мультидоменная модель «домен ↔ приложения ↔
|
||||||
письма через тракт (SMTP submission → milter'ы → OpenDKIM → доставка);
|
режим From». Границы продукта, меняющиеся только явным решением.
|
||||||
что читает/пишет `/data` и в каком формате; где проходит граница
|
- `docs/architecture.md` — as-built по коду: `supervisord`, `postfix`,
|
||||||
привилегий (root vs непривилегированный uid панели) и почему —
|
`opendkim`, panel (HTTP + journal-milter + log-tailer); порядок старта;
|
||||||
источник истины: код (`build/supervisord.conf`, `internal/`), а не
|
milter-цепочка; Postfix/SASL/TLS; журнал отправки и L1/L2 rate-limit;
|
||||||
ТЗ, план сверки — тот же метод из раздела 2.
|
бэкап/restore; персистентность `/data`. Источник истины — код, не ТЗ.
|
||||||
- `docs/development.md` — как собрать и прогнать тесты локально (Go
|
- `docs/development.md` — Go локально, `go test`/`go vet`, `make e2e`, когда
|
||||||
локально, без Docker — см. память проекта), когда нужен полный
|
нужен полный контейнер на dev-сервере, ручная проверка на
|
||||||
контейнерный цикл на dev-сервере (сборка образа, milter/почтовые
|
`selfpost.mixfed.ru`, протокол коммитов/CHANGELOG, правила для агента
|
||||||
изменения) и почему локальной сборки недостаточно, порядок ручной
|
(бывшее ТЗ §12). В `progress.md` — текущее состояние, не процедура.
|
||||||
проверки на `selfpost.mixfed.ru` перед мёржем. Заменяет часть, что
|
|
||||||
раньше держалась только в памяти проекта и `progress.md` — там
|
### Карта миграции из `specification.md`
|
||||||
остаётся текущее состояние и следующий шаг, а не воспроизводимая
|
|
||||||
процедура.
|
| Блок ТЗ | Новый дом | Задача |
|
||||||
|
|---|---|---|
|
||||||
|
| §1–3, §4.1 | `product.md` | D9 |
|
||||||
|
| §4, §5–7 (техника), §9 | `architecture.md` | D8 |
|
||||||
|
| §7.6 | `security.md` («Обязательные требования») | D9 |
|
||||||
|
| §8 | README (таблица env) | D2 |
|
||||||
|
| §9 (путь `tar` для пользователя) | README | D3 |
|
||||||
|
| §10–11 | README + таблица «Поставка» выше | D1–D4 |
|
||||||
|
| §12 | `development.md` | D8 |
|
||||||
|
|
||||||
|
После D9: `specification.md` → `docs/archive/specification-v1.0.md` (снимок,
|
||||||
|
не правится); в `docs/` живых ссылок на него нет.
|
||||||
|
|
||||||
**Границы (без изменений):** отдельные `CONTRIBUTING.md`, man-страницы и сайт
|
**Границы (без изменений):** отдельные `CONTRIBUTING.md`, man-страницы и сайт
|
||||||
документации ТЗ по-прежнему не требует и в объём v1.x не входят.
|
документации в объём v1.x не входят.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -82,11 +104,16 @@
|
|||||||
| Сессии, вход, смена пароля | [internal/store/sessions.go](../internal/store/sessions.go), [internal/web/session.go](../internal/web/session.go), [internal/web/handlers_account.go](../internal/web/handlers_account.go) |
|
| Сессии, вход, смена пароля | [internal/store/sessions.go](../internal/store/sessions.go), [internal/web/session.go](../internal/web/session.go), [internal/web/handlers_account.go](../internal/web/handlers_account.go) |
|
||||||
| Ротация лога, периодический reload, интервалы | [build/logrotate-mail.conf](../build/logrotate-mail.conf), [build/logrotate-loop.sh](../build/logrotate-loop.sh), [build/postfix-cert-reload.sh](../build/postfix-cert-reload.sh) |
|
| Ротация лога, периодический reload, интервалы | [build/logrotate-mail.conf](../build/logrotate-mail.conf), [build/logrotate-loop.sh](../build/logrotate-loop.sh), [build/postfix-cert-reload.sh](../build/postfix-cert-reload.sh) |
|
||||||
| Деплой: тег образа, порты, монтирования, capabilities | [deploy/docker-compose.yml](../deploy/docker-compose.yml), [build/Dockerfile](../build/Dockerfile) |
|
| Деплой: тег образа, порты, монтирования, capabilities | [deploy/docker-compose.yml](../deploy/docker-compose.yml), [build/Dockerfile](../build/Dockerfile) |
|
||||||
| Требования, а не реализация (что вообще должно быть описано) | [specification.md](specification.md) разделы 9, 10, 11 |
|
| Обязательное содержание README (чеклист поставки) | таблица «Поставка» в §1 этого файла (бывшее ТЗ §10–11) |
|
||||||
|
| Границы продукта, out of scope | [product.md](product.md) *(после D9)* |
|
||||||
|
| As-built устройство (не пользовательский текст) | [architecture.md](architecture.md) *(после D8)* |
|
||||||
|
| Обязательные требования безопасности | [security.md](security.md) *(после D9)* |
|
||||||
|
|
||||||
Порядок прохода: сначала перечислить фактическое (env-ключи, маршруты,
|
Порядок прохода: сначала перечислить фактическое (env-ключи, маршруты,
|
||||||
`postconf`-настройки), потом искать каждый пункт в README — так находится и
|
`postconf`-настройки), потом искать каждый пункт в README / `architecture.md` —
|
||||||
неверное, и **отсутствующее**.
|
так находится и неверное, и **отсутствующее**. До закрытия D9 для чеклиста
|
||||||
|
README допустима сверка с `specification.md` §10–11; после D9 — только с §1
|
||||||
|
этого файла.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -230,7 +257,8 @@ DNS-карточка домена); прогрев IP; смысл фиксиро
|
|||||||
«на живом контейнере так делать не надо, потому что SQLite в WAL». Заодно
|
«на живом контейнере так делать не надо, потому что SQLite в WAL». Заодно
|
||||||
упомянуть, что `manifest.json` после успешного восстановления потребляется.
|
упомянуть, что `manifest.json` после успешного восстановления потребляется.
|
||||||
|
|
||||||
**D4. Точечные правки.** Находки 5, 7, 8, 11: баннер статуса и ссылки; комментарий
|
**D4. Точечные правки.** Находки 5, 7, 8, 11: баннер статуса и ссылки (убрать
|
||||||
|
ссылку на `specification.md` — после D9 продукт в `product.md`); комментарий
|
||||||
в шапке compose про `.env`; строка про 587; бамп тега образа (делается в
|
в шапке compose про `.env`; строка про 587; бамп тега образа (делается в
|
||||||
релизном коммите, не раньше).
|
релизном коммите, не раньше).
|
||||||
|
|
||||||
@@ -245,17 +273,36 @@ DNS-карточка домена); прогрев IP; смысл фиксиро
|
|||||||
|
|
||||||
**D7. Регресс-защита (см. раздел 5).**
|
**D7. Регресс-защита (см. раздел 5).**
|
||||||
|
|
||||||
**D8. Новые документы: `docs/architecture.md` и `docs/development.md`.**
|
**D8. Новые документы: `architecture.md` и `development.md`.** Пишутся с нуля и
|
||||||
Пишутся с нуля (в разделе 3 их нет — это не расхождение с кодом, а
|
перенимают техническую часть ТЗ (§4–7, §9, §12) в форму as-built / процесса.
|
||||||
отсутствовавший артефакт). `architecture.md` сверяется тем же методом, что и
|
`architecture.md` сверяется методом из раздела 2 — по коду, не по памяти.
|
||||||
остальное (раздел 2): по факту компоновки образа и кода, не по памяти.
|
`development.md` фиксирует воспроизводимый процесс (Go локально / e2e /
|
||||||
`development.md` фиксирует уже существующий, но нигде не описанный процесс
|
dev-сервер).
|
||||||
(Go локально / полный цикл на dev-сервере для Docker-зависимых изменений).
|
|
||||||
*Готово, когда:* `architecture.md` перечисляет все managed-процессы из
|
*Готово, когда:* `architecture.md` перечисляет все managed-процессы из
|
||||||
[build/supervisord.conf](../build/supervisord.conf) и путь письма через
|
[build/supervisord.conf](../build/supervisord.conf) и путь письма через
|
||||||
milter-цепочку без противоречий коду; `development.md` позволяет с нуля
|
milter-цепочку без противоречий коду; `development.md` позволяет с нуля
|
||||||
повторить локальную сборку + прогон тестов и понять, когда нужен
|
повторить локальную сборку + прогон тестов и понять, когда нужен dev-сервер,
|
||||||
dev-сервер, не заглядывая в память проекта.
|
не заглядывая в память проекта и не открывая `specification.md`.
|
||||||
|
|
||||||
|
**D9. Вывод `specification.md` из обращения (после D1–D8).** Закрывает цель
|
||||||
|
плана: живой ТЗ больше не нужен.
|
||||||
|
1. Создать `docs/product.md` — §1–3, §4.1 (см. карту миграции в §1).
|
||||||
|
2. Дополнить [security.md](security.md) разделом «Обязательные требования» —
|
||||||
|
самодостаточный чеклист из бывшего §7.6 (setup-link, SASL, сессии,
|
||||||
|
rate-limit логина, `html/template`, не-root и т.д.), без отсылки «см. ТЗ».
|
||||||
|
3. Убедиться, что D1–D4 и D8 покрыли всё из §8–11, что должно жить в README /
|
||||||
|
`architecture.md` (пройти карту миграции построчно).
|
||||||
|
4. Перенести `specification.md` → `docs/archive/specification-v1.0.md` без
|
||||||
|
правок текста; в начале архива — одна строка: «исторический снимок v1.0,
|
||||||
|
не источник истины».
|
||||||
|
5. Обновить ссылки во всём репозитории: `progress.md` (убрать «ТЗ:
|
||||||
|
specification.md», заменить на `product.md` + `architecture.md`),
|
||||||
|
`implementation-plan.md` и `roadmap.md` («Основа» → `product.md`),
|
||||||
|
`security.md`, `README.md` (баннер D4 — не на ТЗ). `rg specification\.md`
|
||||||
|
по репо — только архив и CHANGELOG/история.
|
||||||
|
*Готово, когда:* в `docs/` нет `specification.md`; новый агент после `/clear`
|
||||||
|
может понять продукт, устройство, безопасность и процесс разработки, не
|
||||||
|
открывая архив.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -270,16 +317,18 @@ dev-сервер, не заглядывая в память проекта.
|
|||||||
новом недокументированном ключе. Ловит самый частый класс расхождений
|
новом недокументированном ключе. Ловит самый частый класс расхождений
|
||||||
(находка 3) без ручного прохода. Границу «внутренних» ключей задать явным
|
(находка 3) без ручного прохода. Границу «внутренних» ключей задать явным
|
||||||
списком-исключением в самом тесте.
|
списком-исключением в самом тесте.
|
||||||
3. **Перед каждым тегом** — короткий проход по разделу 2 этого файла (семь
|
3. **Перед каждым тегом** — короткий проход по разделу 2 (источники истины в
|
||||||
источников истины), а не полная ревизия текста.
|
коде + README + `architecture.md` + `product.md`), а не полная ревизия текста
|
||||||
|
и не сверка с архивным ТЗ.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Гейт релиза
|
## 6. Гейт релиза
|
||||||
|
|
||||||
Документационный проход — часть того же гейта, что e2e (C.4) и ревизия
|
Документационный проход — часть того же гейта, что e2e (C.4) и ревизия
|
||||||
безопасности (D.5): **D1–D6 закрыты до тега**. D7 и D8 — желательны, но тег не
|
безопасности (D.5): **D1–D6 и D9 закрыты до тега**. D7 желателен, но тег не
|
||||||
блокируют: D8 не покрывает пробел против ТЗ (архитектура/разработка не входят
|
блокирует. **D8** — обязателен до D9 (архитектура должна существовать до
|
||||||
в обязательную поставку), поэтому может тянуться в фон после релиза. Находки,
|
миграции); D8 один тег не блокирует, если D9 отложен, но **полное закрытие
|
||||||
обнаруженные позже, дописываются сюда, а не исправляются молча: этот файл —
|
плана (= вывод specification) — только D1–D9 вместе**. Находки, обнаруженные
|
||||||
журнал состояния документации, а не одноразовый список дел.
|
позже, дописываются сюда, а не исправляются молча: этот файл — журнал
|
||||||
|
состояния документации, а не одноразовый список дел.
|
||||||
|
|||||||
Reference in New Issue
Block a user