docs: заведён склад конвенций, первая — категории директорий приложения

- docs/conventions/ с индексом: чем конвенция отличается от ADR и drafts,
  статусы (рекомендуемая / обязательная), когда заводить
- app-directories.md: конфигурация / данные / кеш по принципу создания и
  ценности; из категорий выводится backup-targets
- раздел «Конвенции» в AGENTS.md со ссылкой на склад
This commit is contained in:
av
2026-07-25 13:52:00 +03:00
parent f505e9ebeb
commit d211052914
3 changed files with 125 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
# Категории директорий приложения
**Статус:** рекомендуемая.
Директории приложения внутри `base_dir` делим на три категории по
принципу создания и ценности содержимого:
- **конфигурация** — то, что восстанавливается прогоном плейбука, в том
числе секреты;
- **данные** — то, что генерирует приложение и что нужно бэкапить;
- **кеш** — то, что генерирует приложение и что не нужно бэкапить:
приложение перегенерирует заново.
Цель — упростить оперирование данными. Категория сразу отвечает на два
вопроса, которые иначе приходится выяснять по коду приложения: **кто
создаёт** содержимое и **что будет, если его потерять**.
## Категории
| Категория | Директория | Создаёт | Потеря содержимого | Бэкап |
| --- | --- | --- | --- | --- |
| Конфигурация | `config/` | плейбук | `inv pl -- <app>` восстанавливает | не нужен |
| Данные | `data/` | приложение | невосполнима | обязателен |
| Кеш | `cache/` | приложение | приложение перегенерирует | не нужен |
Тест на границе данных и кеша: что будет, если сделать `rm -rf` и
поднять приложение заново. Поднимется само и наверстает — кеш. Не
поднимется или поднимется пустым — данные.
Конфигурацию бэкапить не только не нужно, но и не стоит: там лежат
секреты, а бэкапы уезжают в облако. Источник истины для конфигурации —
репозиторий и vault, а не снапшот restic.
## Практика
- Переменные плейбука — `config_dir`, `data_dir`, `cache_dir` внутри
`base_dir`; директории создаются одной задачей `Create application
internal directories`.
- Файл `backup-targets` выводится из категорий механически: в него идут
данные, не идут конфигурация и кеш.
- Монтирование в контейнер: конфигурацию — `:ro`, где приложение это
позволяет. Данные и кеш — на запись.
- `docker-compose.yml` остаётся в корне `base_dir`: туда смотрит
`project_src` модуля `docker_compose_v2`.
Пример, где категории разведены полностью, — `playbook-gramps.yml`:
`data` (база), `media` (файлы), `cache` (миниатюры и кеш отчётов),
`backups` (дампы). В `backup-targets` попадают первые три без `cache`.
## Отступления, которые уже есть
Конвенция рекомендуемая, поэтому список честный, а не пустой.
- **`backups/`** — четвёртая директория рядом с тремя категориями.
Формально это производное от данных (дамп, который делает gobackup или
`pg_dump`), но именно она уезжает в restic, а сырые данные приложения —
не всегда. Держим отдельно и относим к данным.
- **`media/`** (gramps, outline) — это данные, просто вынесенные в
отдельную директорию: крупные файлы отделены от базы, чтобы их можно
было двигать между дисками независимо.
- **Конфигурация без `config/`** — она есть только у девяти плейбуков из
тридцати трёх, у остальных конфиги лежат прямо в `base_dir` рядом с
`docker-compose.yml`. Переезд по мере касания приложения, отдельной
кампанией не переписываем.
- **Легаси-раскладка `data/` под всё** — у части сервисов внутри `data/`
лежит и то, что по этой конвенции было бы кешем. Разделять имеет смысл
тогда, когда кеш заметен по объёму в бэкапе, а не ради самой схемы.
## Связано
- [ADR-2025-12-07](../adr/ADR-2025-12-07-app-data-on-separate-disk.md) —
почему всё это лежит на отдельном диске в `/mnt/applications`.
- `files/backups/backup-all.py` — оркестратор, читающий `backup-targets`.