diff --git a/EventHubBackSpec.md b/EventHubBackSpec.md index 4e57c0c..4f1277d 100644 --- a/EventHubBackSpec.md +++ b/EventHubBackSpec.md @@ -173,7 +173,8 @@ EventHub — платформа для управления событиями - Поддержка 100 000+ пользователей. - Горизонтальное масштабирование добавлением новых узлов. - Все персистентные таблицы хранятся в `disc_copies` на каждом узле (задача #13). -- Сессионные таблицы (`session`, `admin_session`) оставлены в `ram_copies` для скорости. +- Сессионные таблицы: `auth_session` (единая модель refresh JWT) хранится в `disc_copies` для кластерной устойчивости. +- Legacy-таблицы `session` и `admin_session` (`ram_copies`) сохранены для пользовательского `/v1/refresh` до фазы 2. - Индексы созданы для часто запрашиваемых полей (calendar_id, start_time, event_type, status и др.) (задача #13). - Полная репликация горячих таблиц между всеми узлами кластера (задача #14). - Автоматическое обнаружение узлов через DNS-имя `eventhub-node` или статический список (задача #14). @@ -263,6 +264,7 @@ src/ - `GET /v1/admin/health` — состояние сервера. - `GET /v1/admin/stats` — статистика. - `POST /v1/admin/login` — вход администратора. +- `POST /v1/admin/refresh` — обновление пары access/refresh JWT администратора. - `GET /v1/admin/users`, `GET /v1/admin/users/:id` — пользователи. - `GET /v1/admin/reports`, `GET /v1/admin/reports/:id` — жалобы. - `DELETE /v1/admin/reviews/:id` — удалить отзыв. @@ -276,9 +278,50 @@ src/ - `GET /v1/admin/audit` — аудит. ## 6.1. Аутентификация и авторизация -- Пользователи и администраторы используют разные эндпоинты и JWT-токены. -- Access-токен имеет срок жизни 1 час, refresh-токен — 30 дней. -- Все защищённые эндпоинты требуют заголовок `Authorization: Bearer `. + +### Общие принципы +- Пользователи и администраторы используют разные эндпоинты и JWT-секреты. +- Access-токен — короткоживущий stateless JWT (HS256). +- Refresh-токен — 30 дней; для admin API реализован как подписанный JWT (фаза 1, #23). +- Все защищённые эндпоинты требуют заголовок `Authorization: Bearer `. + +### Единая session-модель (`auth_session`, фаза 1 — admin) + +Таблица Mnesia `auth_session` (`disc_copies`): +| Поле | Описание | +|------|----------| +| `session_id` | Первичный ключ сессии устройства | +| `family_id` | Семейство ротаций одной сессии | +| `subject_id` | ID пользователя или администратора | +| `subject_type` | `user` \| `admin` | +| `client_type` | `admin` \| `web` \| `mobile` | +| `current_jti` | Актуальный jti refresh JWT | +| `expires_at` | Срок жизни сессии (30 дней) | +| `revoked` | Флаг отзыва | + +**Refresh JWT (admin)** — claims: +- `typ=refresh`, `aud=admin`, `sub=` +- `sid=`, `fid=`, `jti=` +- `client=admin`, `exp`, `iat` + +**Поток login admin** (`POST /v1/admin/login`): +1. Проверка email/password. +2. Создание записи `auth_session`. +3. Ответ: `{ token, refresh_token, user }`. + +**Поток refresh admin** (`POST /v1/admin/refresh`): +1. Верификация подписи и срока refresh JWT. +2. Сверка `jti` из JWT с `current_jti` в Mnesia. +3. При совпадении — ротация: новый `jti`, новая пара токенов. +4. При несовпадении (reuse) — `revoke_family`, ответ 401. + +**Фазы внедрения:** +- Фаза 1 (#23): admin API — реализовано. +- Фаза 2: user `/v1/refresh` на той же модели. +- Фаза 3: client web + mobile (тот же контракт `{token, refresh_token}`). + +### Legacy user refresh (до фазы 2) +- `POST /v1/login` + `POST /v1/refresh` используют opaque refresh-токен в таблице `session` (`ram_copies`). ## 7. ВЕРСИОНИРОВАНИЕ И СТАТУС Текущая версия: 1.5 (MVP, альфа). Включает: diff --git a/README.md b/README.md index 98313c1..7952f4f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # **Техническое задание EventHub** ## 1. [EventHub Backend — Техническое задание](EventHubBackSpec.md) ## 2. [EventHub Admin UI — Техническое задание](EventHubFrontAdminSpec.md) +## 3. [Правила работы (workflow)](WORKFLOW.md) # **Репозитории разработки EventHub** ## 1. [EventHub Backend](https://git.sabilin.com/EventHub/EventHubBack) diff --git a/WORKFLOW.md b/WORKFLOW.md new file mode 100644 index 0000000..f987596 --- /dev/null +++ b/WORKFLOW.md @@ -0,0 +1,108 @@ +# EventHub — правила работы + +Живой документ процесса разработки. Дополняется по мере появления новых договорённостей. + +**Репозитории:** `EventHubBack`, `EventHubFrontAdmin`, `EventHubSpec` +**Трекер:** https://git.sabilin.com/EventHub +**Cursor skill для задач:** `eventhub-gitea` + +--- + +## 1. Задачи (Gitea) + +### Язык +Все задачи, комментарии и описания — **на русском**. +Исключение: имена файлов, пути API, идентификаторы в backticks. + +### Жизненный цикл + +| Этап | Действие | +|------|----------| +| Старт | Прочитать issue → назначить на себя → комментарий «Беру в работу» | +| План | **Предложить 1–3 варианта решения с trade-offs → ждать утверждения** | +| Работа | После утверждения — код в репозитории-владельце; коммиты с `Refs EventHub/#N` | +| Финиш | Тесты зелёные → комментарий с итогом → закрыть issue | + +### Метки (единый набор во всех репо) + +| Метка | Назначение | +|-------|------------| +| Bug | Дефект | +| Task | Техническая задача | +| Story | Пользовательская история | +| Epic | Крупная инициатива | +| Future | Отложено | + +Синхронизация меток: `~/.cursor/skills/eventhub-gitea/scripts/sync-labels.ps1` + +### Приоритеты +`P0` → `P1` → `P2` (указывается в заголовке задачи). + +--- + +## 2. Тестирование (обязательный gate) + +**Нельзя** закрывать задачу и **нельзя** обновлять спеку, пока: + +- пройдены релевантные тесты репозитория; +- выполнена ручная проверка, если автотестов нет; +- нет известных регрессий в затронутой области. + +| Репозиторий | Минимум | +|-------------|---------| +| EventHubBack | `make test` / `make eunit` / целевые API-тесты | +| EventHubFrontAdmin | `npm run lint`, `npm run build` | +| EventHubSpec | ревью текста, ссылки на код | + +--- + +## 3. Спецификация (после успешных тестов) + +Если изменение затрагивает **поведение, API, модель данных или роли**: + +1. Обновить соответствующий файл в `EventHubSpec/`: + - backend → `EventHubBackSpec.md` + - admin → `EventHubFrontAdminSpec.md` +2. В комментарии к issue указать: «Спека обновлена: …» +3. Спека описывает **фактическую** реализацию, не планы. + +Что синхронизировать: +- endpoint-ы (путь, метод, auth); +- форматы запросов/ответов; +- поля records/таблиц; +- роли и права; +- ограничения и допущения. + +Чистый рефакторинг без смены контракта — обновление спеки не обязательно (написать в issue). + +--- + +## 4. Расширение правил + +При появлении новой договорённости в работе: + +1. Добавить пункт в этот файл (раздел «Правила» ниже). +2. При необходимости — задача `Task` в `EventHubSpec` на согласование. +3. Для Cursor — обновить skill `eventhub-workflow`. + +--- + +## Правила (накопительный список) + +- Задачи в Gitea вести через skill `eventhub-gitea`; тексты на русском. +- **Перед реализацией** — предложить оптимальные варианты решения; кодить только после утверждения варианта пользователем. +- Перед закрытием issue — успешные тесты изменённого кода. +- После успешных тестов — обновить спеку, если менялся внешний контракт. +- Одна задача — один логический объём работы. +- Код фичи — в репозитории-владельце; `EventHubSpec` — для документации и процесса. +- Метки во всех репозиториях держать одинаковыми (`sync-labels.ps1`). +- Секреты и токены не коммитить; Gitea token — только в env / `~/.cursor/secrets/`. + +--- + +## История + +| Дата | Изменение | +|------|-----------| +| 2026-07-07 | Правило: варианты решения и утверждение перед реализацией | +| 2026-07-07 | Первая версия: Gitea workflow, gate тестирования, sync спеки |