docs(archive): hot/warm/cold month snapshots; HTML /view removed.

Fixes EventHub/EventHubSpec#20

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-17 14:59:34 +03:00
parent f68f39f5f9
commit 14da77fd7e
5 changed files with 145 additions and 15 deletions
+18 -12
View File
@@ -266,6 +266,10 @@ Legacy: прямой `POST /v1/calendars/:id/specialists` **не использ
UI списка — Front#72. Kick-on-login / нативный клиент — по-прежнему future.
- **Не в фазе 2:** оплата услуги клиентом (B2C) — вне горизонта продукта.
#### Фаза 3 / архив (Spec#19, канон Spec#20)
- История календаря: hot = текущий месяц + будущее; warm = 3 закрытых месяца;
cold = gzip-файлы. Контракт: [`ARCHIVE.md`](ARCHIVE.md). Код: Back#76.
### 2.1.3. Share / приглашения (соредактор и заместитель)
Таблица `calendar_share` (`id`, `calendar_id`, `user_id`, `rights`: `read` | `write` | `admin`,
@@ -511,7 +515,9 @@ API:
- Полная репликация горячих таблиц между всеми узлами кластера (задача #14).
- Автоматическое обнаружение узлов через DNS-имя `eventhub-node` или статический список (задача #14).
- Периодическая очистка «мёртвых» узлов из схемы Mnesia (каждые 30 секунд) (задача #14).
- Архивирование исторических данных (старше 30 дней) в отдельные Mnesia-узлы с `disc_only_copies` (задача #15).
- Архив календаря (Фаза 3, [ARCHIVE.md](ARCHIVE.md), Spec#20): hot `disc_copies`
(текущий месяц + будущее) + `month_snapshot` `disc_only` (3 закрытых месяца) +
gzip-файлы старше. Не extra-node и не построчный `event_archive` (#15 отвергнут).
- Пагинация всех списков.
### 3.2. Надёжность
@@ -526,7 +532,8 @@ API:
- `EVENTHUB_ENV`: `dev` — допускаются documented fallbacks; `stage`/`prod` — fail-fast при слабых или отсутствующих `JWT_SECRET`, `ADMIN_JWT_SECRET` и паролях seed-админов (#25).
- Проверка прав доступа к календарям и событиям.
- Пароли хэшируются с использованием Argon2.
- Защита от несанкционированного просмотра архивных данных (только владелец календаря) (задача #15).
- Архив месяца: тот же ACL, что у живого календаря (`can_access`: owner | share).
Guest/public deep-archive чужой студии — не в волне 1 ([ARCHIVE.md](ARCHIVE.md)).
### 3.4. Наблюдаемость
- Логирование в JSON-формате.
@@ -555,12 +562,10 @@ API:
```
src/
├── core/ — бизнес-логика (core_user, core_event, core_booking, core_review, ...)
├── handlers/ — обработчики HTTP (handler_login, handler_calendar_view, ...)
├── infra/ — инфраструктура (infra_mnesia, infra_sup, cluster_discovery,
archive_manager, archive_controller, stats_collector,
│ migration_engine, ...)
├── archive/ — архивирование и рендеринг (archive_controller, archive_manager,
│ calendar_html_renderer, archive_fetcher)
├── handlers/ — обработчики HTTP (handler_login, handler_events, ...)
├── infra/ — infra_mnesia, infra_sup, month_archive_worker, stats_collector,
migration_engine, ...
├── logic/ — в т.ч. logic_month_archive (снимки месяца)
├── migrations/ — файлы миграций
└── eventhub_app.erl — точка входа приложения
```
@@ -682,7 +687,8 @@ src/
- `GET /v1/subscription` — подписка пользователя.
- `POST /v1/subscription``action=start_trial` | `activate` (+ `plan`, опционально
`payment_info`). Trial — только через `start_trial`, не через create commercial.
- `GET /v1/calendars/:calendar_id/view?month=YYYY-MM` — HTML-календарь (владелец), включая архив.
- `GET /v1/calendars/:calendar_id/events?from&to` — события диапазона: **hot** для живого окна;
archived month — из `month_snapshot` / файла, тот же JSON ([ARCHIVE.md](ARCHIVE.md), Back#76).
### WebSocket (порт 8081)
- `WS /ws` — пользовательский канал real-time (подписка на обновления событий календаря; детали — §2.11).
@@ -805,9 +811,9 @@ src/
хранение local disk `UPLOAD_DIR` (default `/app/data/uploads` на volume
`eventhub-data`); отдача `GET /v1/media/:kind/:owner/:file` (public).
Вложения к событию — пока не реализованы.
- Серверный рендеринг календаря работает только для владельца календаря.
- Автоматическое архивирование через `archive_controller` в локальном режиме использует
`slave:start`, который устарел; в production планируется `peer`.
- HTML `GET …/view` **удалён**; архив читается JSON-ом (Spec#20 / [ARCHIVE.md](ARCHIVE.md)).
- `archive_controller` + extra-node (`slave`/`peer`) **удалены**; архив — `month_snapshot`
на тех же нодах (Back#76, [ARCHIVE.md](ARCHIVE.md)).
## 9. ТРЕБОВАНИЯ К ОКРУЖЕНИЮ
- Erlang/OTP 28