diff --git a/docs/_resources/Архитектура - общая схема.png b/docs/_resources/Архитектура - общая схема.png
new file mode 100644
index 0000000..7b93035
Binary files /dev/null and b/docs/_resources/Архитектура - общая схема.png differ
diff --git a/docs/_resources/Архитектура - основной процесс.png b/docs/_resources/Архитектура - основной процесс.png
new file mode 100644
index 0000000..f1f14e4
Binary files /dev/null and b/docs/_resources/Архитектура - основной процесс.png differ
diff --git a/docs/_resources/Архитектура.svg b/docs/_resources/Архитектура.svg
new file mode 100644
index 0000000..3fc7e39
--- /dev/null
+++ b/docs/_resources/Архитектура.svg
@@ -0,0 +1,1430 @@
+
+
diff --git a/docs/_resources/Папка в почте с уведомлениями из Redmine.png b/docs/_resources/Папка в почте с уведомлениями из Redmine.png
new file mode 100644
index 0000000..a0092a5
Binary files /dev/null and b/docs/_resources/Папка в почте с уведомлениями из Redmine.png differ
diff --git a/docs/_resources/Преднастроенный фильтр в Redmine.png b/docs/_resources/Преднастроенный фильтр в Redmine.png
new file mode 100644
index 0000000..bb17895
Binary files /dev/null and b/docs/_resources/Преднастроенный фильтр в Redmine.png differ
diff --git a/docs/_resources/Преобразования задач.png b/docs/_resources/Преобразования задач.png
new file mode 100644
index 0000000..1f0e61c
Binary files /dev/null and b/docs/_resources/Преобразования задач.png differ
diff --git a/docs/_resources/Преобразования задач.svg b/docs/_resources/Преобразования задач.svg
new file mode 100644
index 0000000..2c6762e
--- /dev/null
+++ b/docs/_resources/Преобразования задач.svg
@@ -0,0 +1,252 @@
+
+
diff --git a/docs/_resources/Сохранение в CouchDB.png b/docs/_resources/Сохранение в CouchDB.png
new file mode 100644
index 0000000..fc30a36
Binary files /dev/null and b/docs/_resources/Сохранение в CouchDB.png differ
diff --git a/docs/_resources/Сохранение в CouchDB.svg b/docs/_resources/Сохранение в CouchDB.svg
new file mode 100644
index 0000000..c74878a
--- /dev/null
+++ b/docs/_resources/Сохранение в CouchDB.svg
@@ -0,0 +1,462 @@
+
+
diff --git a/docs/Архитектура.md b/docs/Архитектура.md
new file mode 100644
index 0000000..6338b05
--- /dev/null
+++ b/docs/Архитектура.md
@@ -0,0 +1,52 @@
+# Общая структура
+
+
+
+Основной код приложения написан на TypeScript и фреймворке NestJS (это такой Angular для backend-а)
+
+Монолитное приложение включает в своём составе:
+
+- основная функциональность
+- кеш и промежуточный коллектор для данных на couchdb
+- http api для внешних интеграций
+- webhook-и и websocket-ы
+- telegram-бот - есть возможность для реализации новых интеграций с другими чат-ботами
+- cron-task-и для выполнения повторяющихся задач
+- frontend server-side на простой шаблонизации
+- frontend на react
+- специальный плагин для lowcode платформы n8n
+
+# Основной процесс
+
+
+
+Двигателем приложения служит redmine-issue-event-emitter - это основной процесс поступления данных в Pinkmine.
+
+1. Подписка на источники событий - по email, через cron-таски, через rss. Позволяет обнаруживать факты изменений в задачах в redmine. ([подробнее](Как%20это%20работает/Как%20работают%20стратегии%20синхронизации%20redmine%20и%20pinkmine.md))
+2. Redmine Issue Event Emitter - это очередь для синхронизации данных из redmine. На выход кладётся номер задачи, на выходе данные полученные с помощью redmine api. Очередь обеспечивает бережное отношение к боевому redmine, так как позволяет выполнять выгрузки не выходя за выставленный лимит обращений. ([подробнее про работу очереди](Как%20это%20работает/Как%20работает%20очередь%20загрузки%20задач.md) и [подробнее про загрузку задач из redmine](Как%20это%20работает/Как%20происходит%20загрузка%20задачи%20из%20Redmine.md))
+3. Преобразование задачи - это набор вспомогательных обработчиков. Позволяет при получении данных произвести попутно полезные изменения, например, привести текстовые теги к массиву, определить текущего ответственного за задачу, обнаружить в описании или в комментариях ссылки на gitlab на MR-ы, в т.ч. можно реализовать специализированный обработчик. ([подбронее](./Как%20это%20работает/Как%20происходит%20преобразование%20задачи.md))
+4. Сохранение задачи в кеш в CouchDB ([подробнее](./Как%20это%20работает/Сохранение%20задачи%20в%20кеш%20CouchDB.md))
+5. Анализ изменений в задаче - это сравнение предыдущего состояния задачи с новым. Позволяет организовать процессы связанные с жизненным циклом самой задачи и, например, разослать уведомления с учётом происходящих изменений ([подробнее](./Как%20это%20работает/Анализ%20изменений%20в%20задаче.md))
+6. Сохранение событий изменения в журнал - вспомогательная коллекция данных ([подробнее](./Как%20это%20работает/Анализ%20изменений%20в%20задаче.md))
+
+# Точки расширения
+
+Платформа Pinkmine предполагает в т.ч. реализацию конкретных задач в рамках основного кода. Допускается реализация специализированных внутренних сервисов.
+
+В рамках ядра redmine-issue-event-emitter:
+
+- новые стратегии получения задач из Redmine
+- специализированные обработчики задач для отдельных проектов
+- интеграция событий в новые процессы - чат-боты или простая передача данных с помощью webhook-ов и websocket-ов
+
+В рамках расширенной платформы pinkmine:
+
+Благодаря CouchDB стало возможным предоставить api для поиска задач с более гибкими условиями для выборки чем во встроенном в redmine api. Можно использовать в выборках комбинированные выражения через "и"/"или". Богатый набор операторов - "есть значение", "нет значения", "больше", "меньше", "равно", "поиск по регулярному выражению". Для поиска можно пользоваться расширенными данными.
+
+CouchDB позволяет выгружать для работы и анализа больший объём данных чем основной api redmine.
+
+Webhook-и и websocket-ы могут сделать api ещё более гибким.
+
+В рамках реализованного telegram chat бота можно дописывать логику работы под узкоспециализированные задачи.
+
+С помощью фреймворка NestJS можно сделать сервисы для решения узких задач. Например, сделать cron-task-у с аналитической выгрузкой с сохранением промежуточных результатов во вспомогательную коллекцию в CouchDB и предостатить уже к ней доступ через http api и сделать человеко-читаемое представление с помощью шаблона.
diff --git a/docs/Как это работает/Анализ изменений в задаче.md b/docs/Как это работает/Анализ изменений в задаче.md
new file mode 100644
index 0000000..4715832
--- /dev/null
+++ b/docs/Как это работает/Анализ изменений в задаче.md
@@ -0,0 +1,64 @@
+Как было описано в документе [Сохранение задачи в кеш CouchDB](./Сохранение%20задачи%20в%20кеш%20CouchDB.md) специфика работы с данными из issue такова что есть два состояния - предыдущее и текущее состояние.
+
+Значит есть возможность сравнения двух состояний и построение дополнительной логики на основе сравнения.
+
+Это позволило реализовать рассылку уведомлений при обнаружении в задачах изменений.
+
+Функции сохранения данных в CouchDB с вычислением изменений реализована в `libs/event-emitter/src/issue-cache-writer/redmine-issues-cache-writer.service.ts`.
+
+Затем с помощью пайплайнов rxjs реализован дополнительный анализ изменений:
+
+1. `src/notifications/personal-notifications.service.ts` - поиск упоминаний пользователей redmine в комментариях для пересылки личных уведомлений в чат-бот
+2. `src/notifications/status-change-notifications.service.ts` - поиск изменений статусов для рассылки уведомлений согласно изменениям ответственного за дальнейшую работу над задачей
+3. `src/changes-cache-writer/changes-cache-writer.service.ts` - сохранение изменений в дополнительный журнал активностей в коллекцию в CouchDB
+
+Сам пайплайн rxjs определяется в инициализирующей функции в `src/app.module.ts`.
+
+Для правильности работы функций анализа нужно выполнить правильно конфигугирование.
+
+Статусы используемые в вашем экземпляре redmine определяются в конфигурационном файле `configs/redmine-statuses-config.jsonc`. Они имеет следующий вид:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "New"
+ },
+ {
+ "id": 2,
+ "name": "In Progress"
+ },
+ {
+ "id": 3,
+ "name": "Closed",
+ "is_closed": true
+ }
+ // ...
+]
+```
+
+Идентификаторы и name должны соответствовать статусам настроенным в основном redmine.
+
+Правила для определения изменений в статусах определяются с помощью конфигурационного файла `configs/redmine-status-changes-config.jsonc`. Он имеет следующий вид:
+
+```json
+[
+ {
+ "default": false,
+ "from": "New",
+ "to": "In Progress",
+ "messages": [
+ {
+ "recipient": "",
+ // Handlebars - template engine
+ "changes_message": "{{qa.name}} got issue #{{issue_id}} after development {{dev.name}}",
+ "notification_message": "{{ issue_tracker }} #{{ issue_id }} {{ issue_subject }}:\n{{dev.name}} finished development. You can test issue.\n\n{{journal_note}}"
+ }
+ // ...
+ ]
+ }
+ // ...
+]
+```
+
+Это набор правил для формирования уведомлений и сообщений для журнала изменений. Поля "from" и "to" - указывают на возможные статусы задачи. "messages" - это набор сообщений. Тут можно определить варианты сообщений для различных получателей задаваемых полем "recipient", а тексты сообщений с помощью шаблонизатора [Handlebars](https://handlebarsjs.com).
\ No newline at end of file
diff --git a/docs/Как это работает/Как происходит загрузка задачи из Redmine.md b/docs/Как это работает/Как происходит загрузка задачи из Redmine.md
new file mode 100644
index 0000000..aec8ab9
--- /dev/null
+++ b/docs/Как это работает/Как происходит загрузка задачи из Redmine.md
@@ -0,0 +1,6 @@
+Это обращение к стандартной функции через http api по следующему шаблону:
+
+`/issues/.json?include=children,journals,relations`
+
+Подробное описание параметров api можно найти в официальной фокументации на странице [Rest_Issues](https://www.redmine.org/projects/redmine/wiki/Rest_Issues)
+
diff --git a/docs/Как это работает/Как происходит преобразование задачи.md b/docs/Как это работает/Как происходит преобразование задачи.md
new file mode 100644
index 0000000..8e55f51
--- /dev/null
+++ b/docs/Как это работает/Как происходит преобразование задачи.md
@@ -0,0 +1,41 @@
+Для разрешения некоторых проблем напрашивалось попутно после получения данных об issue из redmine делать преобразования
+
+Примеры:
+
+1. Преобразовать дату+вермя из текстового формата в числовой для возможности фильтрации данных с помощью сравнивающих операторов - больше и меньше.
+2. Привести текстовое значение тегов к массиву для фильтрации данных с помощью оператора "$in".
+3. Можно извлечь из описания и комментариев ссылки на MR-ы в gitlab-е.
+4. Определить текущего ответственного за задачу по правилам соответствия статусу одному из полей - "Назначено", "Code Reviewer", "Quality Assurance".
+
+Через конфигурационный файл уже не решить настройку, т.к. за преобразования задач отвечают функции - а если точнее то классы с реализацией интерфейса `IssueEnhancerInterface`. Это делается в коде проекта Pinkmine. Примеры реализаций в файлах:
+
+- `libs/event-emitter/src/issue-enhancers/timestamps-enhancer.ts` - преобразует дату+время из текстового формата в числовой
+- `libs/event-emitter/src/issue-enhancers` - в папке ещё несколько универсальных примеров (не зависящих от экземпляра redmine)
+- `src/issue-enhancers` - в папке лежат дополнительные примеры с функциями уже привязанными к рабочему redmine и специфичные для рабочих проектов
+
+Чтобы эти функции отрабатывали налету после получения данных из redmine и перед сохранением в кеш, то нужно при начальной инициализации приложения (`src/app.module.ts` > `AppModule.onModuleInit`) указать набор реализаций `IssueEnhancerInterface`. Упрощённый код, отражающий суть:
+
+```ts
+export class AppModule {
+ // ...
+ onModuleInit() {
+ // ...
+ this.enhancerService.addEnhancer([
+ this.timestampEnhancer,
+ this.customFieldsEnhancer,
+ this.currentUserEnhancer,
+ this.issueUrlEnhancer,
+ this.categoryMergeToTagsEnhancer,
+ this.calendarEnhancer,
+ ]);
+ // ...
+ }
+ // ...
+}
+```
+
+Схематически процесс можно проиллюстрировать так:
+
+
+
+Выполнение преобразований данных до сохранения в кеш в CouchDB позволяет в последствии использовать дополнительные данные для выборки задач
\ No newline at end of file
diff --git a/docs/Как это работает/Как работает очередь загрузки задач.md b/docs/Как это работает/Как работает очередь загрузки задач.md
new file mode 100644
index 0000000..9fb8324
--- /dev/null
+++ b/docs/Как это работает/Как работает очередь загрузки задач.md
@@ -0,0 +1,22 @@
+Это стандартный паттерн:
+
+1. берём максимум N номеров задач раз в M секунд,
+2. передаём их в функцию для синхронизаицации
+ 1. выгружаем данные о задаче из redmine api
+ 2. пишем полученные данные во внутренний кеш
+
+Очередь нужна для бережного отношения к боевому redmine, потому что не загрузит CPU на сервере сотнями одновременных параллельных запросов.
+
+Настройка очереди производится в конфигурационном файле `configs/issue-event-emitter-config.jsonc` в секции `issueChangesQueue`:
+
+```json
+{
+ // ...
+ "issueChangesQueue": {
+ "updateInterval": 5000, // 5 sec
+ "itemsLimit": 3
+ }
+ // ...
+}
+```
+
diff --git a/docs/Как это работает/Как работают стратегии синхронизации redmine и pinkmine.md b/docs/Как это работает/Как работают стратегии синхронизации redmine и pinkmine.md
new file mode 100644
index 0000000..5d4c0d7
--- /dev/null
+++ b/docs/Как это работает/Как работают стратегии синхронизации redmine и pinkmine.md
@@ -0,0 +1,106 @@
+# Стратегия по email
+
+
+
+1. В задаче в redmine делается любое изменение - смена статуса, обновление описания, добавление нового комментария.
+2. Redmine отправляет сообщение о факте обновления задачи по email
+3. Pinkmine читает новые письма протоколу imap, находит в заголовках номер задачи с помощью регулярного выражения
+4. Pinkmine помещает номер задачи в очередь для выполнения обновления
+
+Параметры работы стратегии задаются в конфигурационном файле `configs/issue-event-emitter-config.jsonc` в секции `mailListener`:
+
+```json
+{
+
+ // ...
+
+ "mailListener": {
+
+ // регулярное выражение для определения номера задачи в заголовке письма:
+ "issueNumberParser": "\\b(?<=#)\\d+\\b",
+
+ // параметры для доступа к почте через протокол imap:
+ "imapSimpleConfig": {
+ "imap": {
+ "user": "",
+ "password": "",
+ "host": "",
+ "port": 143,
+ // tls: true,
+ "autotls": "always",
+ "authTimeout": 5000
+ }
+ },
+
+ // интервал через который происходит проверка почты:
+ "updateInterval": 180000, // 3 min
+
+ // имя папки в которой следует искать входящие письма
+ "boxName": "INBOX"
+ },
+
+ // ...
+
+}
+```
+
+# Стратегия через cron-таски
+
+
+
+1. Pinkmine загружает данные из преднастроенных query-запросов в redmine в формате csv. Выбирает данные по двум полям - id задачи и "обновлено" (дата+время обновления задачи)
+2. Pinkmine проверяет какие задачи в своём кеше (CouchDB) уже успели устареть
+3. Номера устаревших задач кладёт в очередь для дальнейшего обновления
+
+Параметры работы стратегии задаются в конфигурационном файле `configs/issue-event-emitter-config.jsonc` в секциях `csvListener` и `rootIssueListener`:
+
+```json
+{
+
+ // ...
+
+ // таски для синхронизации по преднастроенным запросам:
+ "csvListener": {
+ "tasks": [
+ {
+ // расписание для выполнения задачи (синтаксис crontab)
+ "schedule": "* * * * *",
+
+ // поле в csv-файле с датой и временем обновления задачи
+ "updatedAtFieldName": "Обновлено",
+
+ // формат даты и времени
+ "dateTimeFormat": "dd.MM.yyyy HH:mm",
+
+ // ссылки на предстароенные запросы выборки задач в формате csv
+ "csvLinks": [
+ "https:///projects/proj/issues.csv?utf8=%E2%9C%93&query_id=2"
+ ]
+ }
+ ]
+ },
+
+ // таски для синхронизации корневых и суммирующих задач:
+ "rootIssueListener": {
+ "tasks": [
+ {
+ // расписание для выполнения задачи (синтаксис crontab)
+ "schedule": "15 6,12 * * *",
+
+ // номера задач
+ "rootIssues": [
+ 1,
+ 3,
+ 7,
+ 11
+ ]
+ }
+ ]
+ },
+
+ // ...
+
+}
+```
+
+Эта стратегия позволяет догружать данные, которые не пришли по email рассылке: закрытые задачи, shady-mode, изменение структуры дерева при смене привязки к родительской задаче и т.п.
\ No newline at end of file
diff --git a/docs/Как это работает/Сохранение задачи в кеш CouchDB.md b/docs/Как это работает/Сохранение задачи в кеш CouchDB.md
new file mode 100644
index 0000000..7b1cde8
--- /dev/null
+++ b/docs/Как это работает/Сохранение задачи в кеш CouchDB.md
@@ -0,0 +1,32 @@
+CouchDB - это nosql субд. Основная концепция CouchDB - это коллекции данных (json) с возможностью гибкого поиска по ним.
+
+Важная особенность CouchDB - это отсутствие механизма транзакций. Гарантия согласованности записи обеспечивается с помощью контроля ревизии.
+
+Документы в CouchDB имеют версионирование, аналогичное тому, как это было бы в обычной системе контроля версий, такой как Subversion. Если вы хотите изменить значение в документе, вы создаете полностью новую версию этого документа и сохраняете ее поверх старой. После выполнения этого вы получите две версии одного и того же документа, одну старую и одну новую.
+
+Как это обеспечивает улучшение по сравнению с блокировками? Рассмотрим набор запросов, желающих получить доступ к документу. Первый запрос считывает документ. Пока он обрабатывается, второй запрос изменяет документ. Поскольку второй запрос включает совершенно новую версию документа, CouchDB может просто добавить его в базу данных, не дожидаясь завершения запроса на чтение.
+
+Когда третий запрос захочет прочитать тот же документ, CouchDB укажет ему на новую версию, которая только что была написана. В течение всего этого процесса первый запрос все еще может читать исходную версию.
+
+Запрос на чтение всегда будет отображать самый последний снимок вашей базы данных на момент начала запроса.
+
+
+
+Redmine Issue Event Emitter всегда для записи нового состояния задачи должен прочитать предыдущее состояние. Это обязательно нужно для корректного определения последней ревизии. Одновременно для дальнейшего анализа станет доступно два состояния - предыдущее и текущее. Благодаря этой особенности работы с CouchDB можно проводить дополнительный [анализ произошедших в задаче изменений](./Анализ%20изменений%20в%20задаче.md).
+
+Настройка доступа к CouchDB делается в конфигурационном файле `configs/issue-event-emitter-config.jsonc` в секции `couchDb`:
+
+```json
+{
+ // ...
+ "couchDb": {
+ "url": "http://admin:password@localhost:5984",
+ "dbs": {
+ "users": "redmine_users",
+ "issues": "redmine_issues",
+ "dashboards": "dashboards"
+ }
+ }
+ // ...
+}
+```
\ No newline at end of file