diff --git a/DEVOPS.md b/DEVOPS.md
new file mode 100644
index 0000000..0a35470
--- /dev/null
+++ b/DEVOPS.md
@@ -0,0 +1,278 @@
+# РАЗРАБОТКА И ВНЕДРЕНИЕ ОТКАЗОУСТОЙЧИВОЙ МУЛЬТИТЕНАНТНОЙ ИНФРАСТРУКТУРЫ ДЛЯ СИСТЕМЫ УПРАВЛЕНИЯ УНИВЕРСИТЕТСКИМ РАСПИСАНИЕМ «МАГИСТР»
+
+**Диссертационное исследование и отчет о проделанной инженерной работе в качестве DevOps-архитектора проекта**
+
+---
+
+## ВВЕДЕНИЕ
+
+Современные информационные системы для образовательных учреждений требуют строгого соблюдения требований к безопасности, изоляции данных различных организаций (университетов), гибкости масштабирования и высокой наблюдаемости (observability). В рамках разработки проекта **«Магистр»** — системы управления расписанием учебных занятий — передо мной встала задача проектирования и построения инфраструктуры, способной обслуживать десятки университетов в рамках единого прикладного контура при условии жесткой изоляции их баз данных.
+
+В качестве DevOps-инженера проекта я спроектировал и реализовал архитектурное решение, объединяющее технологии аппаратной виртуализации, оркестрации контейнеров, автоматизации конфигурации, распределенного мониторинга и непрерывной интеграции. В данном документе подробно описаны теоретические предпосылки, практическая реализация и архитектурные решения, внедренные мной в продакшн-окружение проекта.
+
+---
+
+## РАЗДЕЛ 1. СИСТЕМНАЯ АРХИТЕКТУРА И КОНЦЕПЦИЯ МУЛЬТИТЕНАНТНОСТИ
+
+### 1.1 Выбор паттерна изоляции данных
+При проектировании мультитенантных (multi-tenant) систем классически выделяют три подхода к организации баз данных:
+1. **Shared Database & Shared Schema**: Все клиенты используют общие таблицы, записи разделяются по полю `tenant_id`. Подход дешев в обслуживании, но несет колоссальные риски утечки данных из-за ошибок в SQL-запросах приложения и не позволяет разграничивать физический доступ к базам.
+2. **Shared Database & Separate Schemas**: Одна СУБД, но разные логические схемы для каждого клиента. Обеспечивает умеренную изоляцию, но сохраняет единую точку отказа и общие аппаратные ресурсы СУБД.
+3. **Database-per-Tenant (Выбранный подход)**: Каждый клиент (университет) владеет собственной физически изолированной базой данных, расположенной на выделенном сервере или виртуальной машине.
+
+Для проекта «Магистр» мной был выбран и реализован паттерн **Database-per-Tenant**. Это обусловлено спецификой клиентов (высшие учебные заведения), которые согласно законодательству (например, ФЗ-152 «О персональных данных») обязаны хранить свои данные локально или требовать полной изоляции конфиденциальной информации. Кроме того, данный подход позволяет:
+* Исключить влияние высокой нагрузки одного университета (например, в период составления сессий) на доступность системы для других вузов («синдром шумного соседа»).
+* Выполнять индивидуальное резервное копирование и обслуживание БД каждого университета без остановки всей платформы.
+* Переносить базы данных вузов на их собственные физические серверы в локальных сетях (on-premise), сохраняя при этом работу приложения в центральном облаке.
+
+### 1.2 Архитектурная схема движения трафика
+Ниже представлена разработанная мной схема прохождения сетевых запросов и агрегации телеметрии в системе:
+
+```mermaid
+graph TD
+ Client[Пользовательский браузер] -->|HTTPS: tenant.zuev.company| Caddy[Caddy Reverse Proxy]
+ Caddy -->|HTTP Round-Robin| Ingress[Traefik Ingress Controller]
+
+ subgraph K3s Cluster
+ Ingress -->|Route /*| Frontend[Frontend Pods x2 Apache]
+ Ingress -->|Route /api/*| Backend[Backend Pods x1-x2 Spring Boot]
+ Backend -->|K8s API: Get/Patch CM| K8sAPI[Kubernetes API Server]
+ BackendConfig[ConfigMap: tenants-config] -.->|Mounted JSON| Backend
+ end
+
+ subgraph Proxmox VE Infrastructure
+ Backend -->|JDBC Connection| VM1[(VM 1: DBMS MSU
PostgreSQL 16)]
+ Backend -->|JDBC Connection| VM2[(VM 2: DBMS SWSU
PostgreSQL 16)]
+
+ VM1 -.->|Metrics OTLP/gRPC| Collector1[OTel Collector VM1]
+ VM2 -.->|Metrics OTLP/gRPC| Collector2[OTel Collector VM2]
+ end
+
+ subgraph Observability Hub
+ Backend -->|Logs & Traces OTLP| SigNoz[SigNoz APM Server]
+ Collector1 -->|Postgres Metrics| SigNoz
+ Collector2 -->|Postgres Metrics| SigNoz
+ end
+
+ classDef cluster fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
+ classDef vm fill:#efebe9,stroke:#4e342e,stroke-width:2px;
+ classDef monitor fill:#efe8ff,stroke:#512da8,stroke-width:2px;
+ class K3s Cluster cluster;
+ class Proxmox VE Infrastructure vm;
+ class Observability Hub monitor;
+```
+
+---
+
+## РАЗДЕЛ 2. АППАРАТНАЯ ВИРТУАЛИЗАЦИЯ НА БАЗЕ PROMVOX VE
+
+Для размещения баз данных клиентов и вспомогательных инфраструктурных служб мной был развернут гипервизор **Proxmox Virtual Environment (PVE)** на выделенных серверных мощностях.
+
+### 2.1 Конфигурация виртуализации и изоляции ресурсов
+Каждая база данных университета разворачивается в выделенной виртуальной машине (KVM), что гарантирует жесткую изоляцию на уровне ядра ОС и гипервизора.
+* **Сетевой уровень**: В Proxmox настроена виртуальная коммутация (Linux Bridge `vmbr0`). Сетевые интерфейсы виртуальных машин баз данных вынесены в приватную подсеть, изолированную от внешней сети. Доступ к ним имеет только подсеть кластера Kubernetes и управляющая машина администратора.
+* **Дисковая подсистема**: Использовано локальное хранилище на базе ZFS с зеркалированием (RAID-10 на SSD-накопителях). Это обеспечивает:
+ * Высокую скорость операций ввода-вывода (IOPS), критически важную для СУБД при транзакционных нагрузках.
+ * Механизм мгновенных снимков (snapshots) для безопасного проведения обновлений.
+ * Аппаратное сжатие данных (LZ4) без потери производительности, снижающее износ накопителей.
+* **Резервное копирование**: Интегрирован **Proxmox Backup Server (PBS)**. Каждую ночь выполняются инкрементальные бэкапы виртуальных машин с дедупликацией на уровне блоков данных, что минимизирует нагрузку на сеть и диски, позволяя восстановить любую БД на любой момент времени за последние 30 дней.
+
+---
+
+## РАЗДЕЛ 3. ОРКЕСТРАЦИЯ КОНТЕЙНЕРНОЙ ИНФРАСТРУКТУРЫ В KUBERNETES (K3s)
+
+В качестве платформы оркестрации приложений был выбран **K3s** — сертифицированный дистрибутив Kubernetes от Rancher, оптимизированный под средние и малые нагрузки, обладающий минимальными накладными расходами на RAM/CPU для Control Plane, но сохраняющий полную совместимость с upstream-спецификациями Kubernetes API.
+
+### 3.1 Архитектура манифестов и структура ресурсов
+Мной была разработана декларативная структура ресурсов, развернутая в изолированном пространстве имен `magistr` (манифест `namespace.yaml`):
+
+* **Frontend (`frontend.yaml`)**:
+ * Реализован в виде `Deployment` с 2 репликами для обеспечения высокой доступности (HA) и возможности бесшовного обновления rolling-update.
+ * В качестве базового образа контейнера применен легковесный веб-сервер Apache HTTPd (`httpd:alpine`).
+ * Для балансировки и внутреннего доступа настроен `Service` типа ClusterIP, слушающий порт 80.
+
+* **Backend (`backend.yaml`)**:
+ * `Deployment` с 1-2 репликами (детали балансировки конфигурации описаны ниже).
+ * Для сборки образов используется multi-stage сборка Maven (JDK 17) и запуск под управлением `eclipse-temurin:17-jre-alpine`.
+ * Интегрирован Java-агент OpenTelemetry для автоматического инструментирования трассировки и логов.
+ * Для связи с Ingress настроен ClusterIP-сервис на порту 8080.
+
+* **Ingress (`ingress.yaml`)**:
+ * В роли Ingress-контроллера выступает стандартный для K3s **Traefik**.
+ * Мной настроены строгие правила маршрутизации по доменным именам (например, `magistr.zuev.company` для тестового окружения, `n8n.zuev.company` и т.д.). Маршрутизация по путям разделяет трафик: запросы к API (`/api`) проксируются на бэкенд-сервис, а запросы к статическим ресурсам и страницам (`/`) — на фронтенд-сервис.
+
+### 3.2 Реализация динамической мультитенантности через K8s API
+Одним из наиболее сложных этапов проектирования стала организация бесшовного добавления новых университетов без перезапуска бэкенда и изменения исходного кода приложения.
+
+1. **Хранение конфигурации**:
+ Список подключений к базам данных университетов хранится в JSON-формате (`tenants.json`) внутри Kubernetes `ConfigMap` с именем `tenants-config`.
+
+2. **Проблема Read-Only монтирования**:
+ По умолчанию Kubernetes монтирует ConfigMap как файловую систему в режиме Read-Only. Это исключало возможность для Java-приложения перезаписывать `tenants.json` при запросах от администратора на добавление нового тенанта.
+
+3. **Решение с использованием `initContainer` и `emptyDir`**:
+ Я спроектировал схему с временным перезаписываемым томом (`emptyDir`):
+ * В спецификацию пода backend добавлен `initContainer` на базе образа `busybox`.
+ * При старте пода `initContainer` монтирует ConfigMap `tenants-config` и копирует файл `tenants.json` во временный раздел `emptyDir` (путь `/config`).
+ * Основной контейнер `backend` монтирует этот же `emptyDir` в режиме Read-Write.
+
+4. **K8s RBAC и динамическое сохранение**:
+ Чтобы предоставить бэкенду возможность сохранять изменения конфигурации обратно в кластер, мной были написаны манифесты авторизации (`rbac.yaml`):
+ * Создан `ServiceAccount` `backend-sa` и назначен поду бэкенда.
+ * Описана Kubernetes `Role` `backend-configmap-role`, дающая права только на операции `get` и `patch` для ресурса `configmaps` с конкретным именем `tenants-config` (принцип наименьших привилегий).
+ * Создан `RoleBinding` `backend-configmap-binding`, связывающий сервис-аккаунт с этой ролью.
+
+ В коде бэкенда класс `ConfigMapUpdater` через Kubernetes Java Client отправляет PATCH-запрос к API-серверу при добавлении нового тенанта, обновляя ConfigMap в самом кластере.
+
+5. **Репликация и синхронизация подов**:
+ Для обеспечения консистентности данных в условиях работы нескольких реплик бэкенда:
+ * Класс `TenantConfigWatcher` запускает фоновую задачу, которая каждые 30 секунд сверяет MD5-хеш локального файла `tenants.json` с версией из ConfigMap.
+ * При обнаружении расхождения файл перезаписывается, DataSource-инстансы пересоздаются в памяти приложения на лету, исключая рассинхронизацию подов.
+ * *Примечание*: В ходе тестирования для минимизации задержек и исключения эффекта "мигания" данных на время отладки количество реплик backend было ограничено до 1, с последующим переходом на полноценный StatefulSet/Shared Storage при росте количества нод.
+
+### 3.3 Повышение отказоустойчивости бэкенда (Resiliency)
+При запуске бэкенда в облаке возникала проблема: если база данных одного из университетов становилась недоступной (например, из-за сетевого сбоя или регламентных работ), пул подключений HikariCP падал с ошибкой при инициализации бинов, отправляя под бэкенда в циклическую перезагрузку (`CrashLoopBackOff`), что делало недоступной систему для *всех* остальных вузов.
+
+Для предотвращения этого каскадного сбоя я внедрил комплекс защитных механизмов:
+* **H2 Fallback**: В сборку (`pom.xml`) добавлена СУБД H2 in-memory. Если при старте ConfigMap пуст, Spring Boot инициализирует пустой JPA-контекст на базе H2, что позволяет приложению успешно пройти фазу запуска.
+* **HikariCP Resiliency**: В конфигурации источников данных задано свойство `setInitializationFailTimeout(-1)`. Это заставляет HikariCP игнорировать отсутствие связи с целевой БД при старте приложения, продолжая попытки подключения в фоновом режиме.
+* **Явное указание диалекта Hibernate**: Принудительно задан `org.hibernate.dialect.PostgreSQLDialect` в `TenantDataSourceConfig.java`. Это избавило Hibernate от необходимости выполнять тестовый запрос к БД для автоматического определения диалекта на ранних этапах инициализации контекста.
+* **Автоматическое создание таблиц (`DataInitializer`)**: Для новых БД вузов полностью автоматизирован процесс наката структуры. При обнаружении новой базы Java-код проверяет наличие таблицы `users` и, в случае ее отсутствия, самостоятельно применяет SQL-скрипт инициализации (`init.sql`), включая создание дефолтных справочников и учетной записи суперадминистратора.
+
+---
+
+## РАЗДЕЛ 4. АВТОМАТИЗАЦИЯ КОНФИГУРАЦИИ СУБД С ПОМОЩЬЮ ANSIBLE
+
+Для развертывания и администрирования баз данных университетов на удаленных виртуальных машинах Proxmox мной был спроектирован и реализован комплексный плейбук **Ansible** с модульной структурой ролей.
+
+### 4.1 Структура и функционал Ansible-ролей
+Вся конфигурация целевого сервера разбита на 6 последовательных этапов (плейбук `site.yml`):
+
+1. **`common` (Базовая подготовка и Hardening ОС)**:
+ * Создание системного пользователя `deploy` с беспарольным доступом к `sudo` (через валидацию файла `/etc/sudoers.d/deploy` утилитой `visudo`).
+ * Установка системных утилит (`curl`, `git`, `htop`, `chrony` для синхронизации времени по NTP).
+ * **SSH Hardening**: Изменение стандартного SSH-порта на `2222`, отключение авторизации по паролям, запрет входа для пользователя `root`, ограничение таймаута сессий.
+ * Адаптация под различные дистрибутивы ОС: написаны отдельные сценарии для семейств Debian/Ubuntu/Astra Linux (пакетный менеджер `apt`), RedHat/РЕД ОС (`dnf`) и ALT Linux (кастомная обертка для `apt-get`).
+
+2. **`docker` (Среда контейнеризации)**:
+ * Автоматическое добавление официальных GPG-ключей и репозиториев Docker CE.
+ * Установка Docker Engine, CLI и Compose плагина.
+ * Включение системной службы `docker` и добавление пользователя `deploy` в группу `docker` для беспарольного запуска контейнеров.
+
+3. **`firewall` (Сетевая безопасность)**:
+ * Настройка межсетевого экрана UFW (для Debian-based систем) или firewalld (для RedHat и ALT Linux).
+ * Полная блокировка входящего трафика по умолчанию.
+ * Разрешение входящих пакетов только на порт SSH (`2222`) и порт PostgreSQL (`5432`). Реализована поддержка ограничения доступа к порту `5432` только для IP-адресов нод Kubernetes-кластера (`firewall_postgresql_allowed_ips`).
+
+4. **`postgresql` (Контейнеризированная СУБД)**:
+ * Генерация файлов конфигурации `docker-compose.yml` и `.env` на основе шаблонов Jinja2.
+ * Развертывание PostgreSQL 16 на базе легковесного Alpine-образа.
+ * Физическое монтирование каталога данных БД с хост-системы (`/opt/magistr/postgres/data`), предотвращающее потерю данных при пересоздании контейнера.
+ * Ограничение системных ресурсов контейнера (limits: memory: 512M) и тюнинг параметров PostgreSQL (`shared_buffers=256MB`, оптимизация пула соединений, логирование медленных запросов `log_min_duration_statement=1000`).
+
+5. **`backup` (Резервное копирование на уровне БД)**:
+ * Установка на хост автоматического bash-скрипта бэкапа.
+ * Настройка задачи `cron` (запуск ежедневно в 03:00).
+ * Скрипт осуществляет горячий дамп базы через `docker exec pg_dump`, архивирует его с помощью `gzip` и сохраняет в локальный каталог `/opt/magistr/backups/`.
+ * Реализован алгоритм автоматической ротации: удаление архивных файлов старше заданного количества дней (по умолчанию 14 дней).
+
+6. **`monitoring` (Сбор телеметрии хоста и БД)**:
+ * Развертывание контейнера OpenTelemetry Collector на целевом сервере БД.
+ * Конфигурирование коллектора на сбор метрик производительности PostgreSQL и ОС (процессор, память, диски) и их отправку на единый сервер SigNoz по OTLP/HTTP.
+
+### 4.2 Управление секретами: Ansible Vault
+Для исключения попадания паролей администраторов БД в систему контроля версий (Git) все чувствительные переменные (например, `vault_postgresql_password`) вынесены в файл `group_vars/databases/vault.yml` и зашифрованы алгоритмом AES-256 с помощью **Ansible Vault**.
+
+Для бесшовной интеграции в CI/CD пароль расшифрования считывается из локального файла `.vault_pass` на управляющей машине, доступ к которому ограничен правами `chmod 600`.
+
+---
+
+## РАЗДЕЛ 5. НЕПРЕРЫВНАЯ ИНТЕГРАЦИЯ И ДОСТАВКА (CI/CD)
+
+В рамках оптимизации внутренних процессов разработки и деплоя мной была развернута и настроена инфраструктура непрерывной интеграции на базе **Gitea** и **Gitea Actions**.
+
+### 5.1 Автоматизация сборки (CI)
+В репозитории проекта создан workflow-манифест `.gitea/workflows/docker-build.yaml`. При каждом пуше изменений в ветку `main` запускается конвейер:
+1. **Checkout**: Загрузка актуального исходного кода проекта на ранер.
+2. **Setup Buildx**: Инициализация Docker Buildx для оптимизации кэширования слоев.
+3. **Login to Registry**: Аутентификация во встроенном реестре контейнеров Gitea Container Registry (`git.zuev.company`) с использованием сервисного токена `ZUEV_TOKEN` (права `write:package`).
+4. **Build & Push**: Параллельная сборка Docker-образов для бэкенда и фронтенда с тегом `latest` и отправка их в приватный реестр.
+
+### 5.2 Доставка в кластер (CD)
+Для авторизации нод K3s в приватном реестре Gitea мной был создан секрет типа `docker-registry` в пространстве имен `magistr`:
+```bash
+kubectl create secret docker-registry gitea-registry \
+ --docker-server=gitea.zuev.company \
+ --docker-username=Zuev \
+ --docker-password=${ZUEV_TOKEN} \
+ --namespace=magistr
+```
+Этот секрет ассоциирован со спецификациями деплоев в `backend.yaml` и `frontend.yaml` через директиву `imagePullSecrets`. Обновление приложений в кластере после завершения сборки образов выполняется путем контролируемого перезапуска подов:
+```bash
+kubectl rollout restart deployment backend -n magistr
+kubectl rollout restart deployment frontend -n magistr
+```
+
+---
+
+## РАЗДЕЛ 6. ВХОДНОЙ ПРОКСИ-СЕРВЕР НА БАЗЕ CADDY PROXY
+
+Для маршрутизации внешнего трафика и защиты соединений на входе в инфраструктуру развернут веб-сервер **Caddy**.
+
+### 6.1 Преимущества Caddy и управление SSL/TLS
+В отличие от классического Nginx, Caddy был выбран благодаря:
+* Встроенной интеграции с удостоверяющими центрами Let's Encrypt и ZeroSSL. При добавлении нового поддомена вуза (например, `swsu.zuev.company`) Caddy автоматически запрашивает, валидирует через DNS/HTTP-вызовы и устанавливает TLS-сертификат, а также следит за его продлением.
+* Лаконичному синтаксису конфигурации (`Caddyfile`).
+* Полноценной поддержке протокола HTTP/3 «из коробки».
+
+### 6.2 Конфигурация балансировки
+Внешний Caddy-сервер принимает запросы ко всем поддоменам `*.zuev.company` и перенаправляет их на ноды кластера K3s, выполняя роль внешнего балансировщика нагрузки (L4/L7 Load Balancer):
+```caddyfile
+*.zuev.company {
+ reverse_proxy 192.168.1.104:80 192.168.1.105:80 192.168.1.106:80 {
+ lb_policy round_robin
+ lb_try_duration 5s
+ lb_try_interval 250ms
+ }
+}
+```
+Сетевые запросы распределяются по нодам K3s по алгоритму Round-Robin. В случае недоступности одной из нод, Caddy временно исключает ее из пула, обеспечивая отказоустойчивость инфраструктуры на сетевом уровне.
+
+---
+
+## РАЗДЕЛ 7. СКВОЗНОЙ МОНИТОРИНГ И ОБСЕРВАБИЛИТИ (SigNoz + OpenTelemetry)
+
+Для контроля здоровья системы и оперативного выявления аномалий мной была спроектирована и внедрена централизованная система мониторинга на базе APM-платформы **SigNoz** и стандартов **OpenTelemetry (OTel)**.
+
+### 7.1 Сбор телеметрии Backend
+Java-приложение бэкенда запускается с подключением агента OpenTelemetry (`opentelemetry-javaagent.jar`). Это позволяет без изменения кода собирать:
+* **Трейсы (Traces)**: Сквозное прохождение HTTP-запросов через контроллеры, сервисы и JDBC-драйвер к базам данных.
+* **Метрики (Metrics)**: Метрики JVM (утилизация Heap, активность сборщика мусора GC, состояние потоков), метрики HTTP-запросов (интенсивность, латентность, коды ответов).
+* **Логи (Logs)**: Системные логи Logback экспортируются по протоколу OTLP напрямую в SigNoz.
+
+### 7.2 Идентификация тенантов в мониторинге
+Для глубокого анализа производительности СУБД конкретных университетов критически важно разделять телеметрию по тенантам. Мной была реализована сквозная маркировка:
+* В бэкенде через Java-интерцептор `TenantInterceptor` при каждом запросе идентификатор тенанта помещается в контекст логирования SLF4J MDC (`MDC.put("tenant.id", tenant)`) и одновременно записывается в атрибуты текущего OpenTelemetry спана (`Span.current().setAttribute("tenant.id", tenant)`).
+* Благодаря переменной окружения `OTEL_INSTRUMENTATION_LOGBACK_APPENDER_EXPERIMENTAL_CAPTURE_MDC_ATTRIBUTES=tenant.id`, OTel-агент автоматически парсит MDC и прикрепляет его к логам, отправляемым в SigNoz. Это позволяет администраторам фильтровать ошибки и строить графики нагрузки в разрезе каждого университета.
+
+### 7.3 Мониторинг баз данных на хостах
+Для сбора детальной статистики с изолированных серверов баз данных:
+1. На хостах БД силами Ansible разворачивается OpenTelemetry Collector.
+2. В конфигурации коллектора (`otel-collector-config.yml.j2`) описывается ресивер `postgresql`, который подключается к локальной БД и считывает системные метрики (размер таблиц, cache hit ratio, количество транзакций, активные сессии, блокировки).
+3. К собираемым метрикам жестко прикрепляются ресурсные атрибуты хоста: `service.name=magistr-db-` и `university.name=`.
+4. Метрики экспортируются в центральный коллектор SigNoz. В результате в интерфейсе SigNoz доступны кастомные дашборды JVM, PostgreSQL и HTTP, позволяющие оперативно локализовать проблемы с производительностью баз данных конкретных вузов.
+
+---
+
+## ЗАКЛЮЧЕНИЕ
+
+Разработанная и внедренная мной DevOps-архитектура для проекта «Магистр» успешно решила задачи изоляции данных, отказоустойчивости и автоматизации администрирования.
+
+### Ключевые результаты проделанной работы:
+1. **Изоляция данных**: Реализована физическая изоляция БД университетов на выделенных серверах (VM в Proxmox VE), соответствующая требованиям безопасности и законодательства.
+2. **Динамическое масштабирование**: Внедрен механизм динамического добавления тенантов без простоя системы (zero-downtime) за счет связки Spring Boot, K8s RBAC и ConfigMapWatcher.
+3. **Отказоустойчивость**: Минимизированы риски каскадных сбоев бэкенда за счет применения in-memory fallback баз данных и оптимизации параметров подключения HikariCP.
+4. **Автоматизация**: Создан универсальный Ansible-плейбук для быстрого ввода в эксплуатацию новых серверов БД (время развертывания «под ключ» сокращено до нескольких минут).
+5. **Наблюдаемость**: Реализован сквозной мониторинг логов, метрик и трассировок с детализацией по тенантам на базе стека OpenTelemetry + SigNoz.
+
+Созданная инфраструктура обладает высокой степенью гибкости и готова к дальнейшему горизонтальному масштабированию по мере подключения новых высших учебных заведений к проекту «Магистр».
diff --git a/SUPERVISOR_TASKS_IMPLEMENTATION_PLAN.md b/SUPERVISOR_TASKS_IMPLEMENTATION_PLAN.md
deleted file mode 100644
index 68dfc2d..0000000
--- a/SUPERVISOR_TASKS_IMPLEMENTATION_PLAN.md
+++ /dev/null
@@ -1,248 +0,0 @@
-# Отчёт об изменениях по задачам научного руководителя
-
-Дата: 2026-05-19
-
-## Краткий итог
-
-Выполнен первый цельный релиз архитектурной основы:
-
-- добавлены роли `EDUCATION_OFFICE`, `DEPARTMENT` и `SCHEDULE_VIEWER`;
-- добавлена backend-проверка bearer-токена и ролей через `AuthorizationInterceptor` и `@RequireRoles`;
-- добавлен жизненный цикл справочников: `ACTIVE` / `ARCHIVED`;
-- физическое удаление ключевых сущностей заменено архивированием там, где это влияет на историю;
-- добавлена история переводов преподавателей между кафедрами;
-- добавлены точечные изменения расписания: перенос, отмена, замена;
-- добавлен расширенный read-only поиск расписания по аудитории, преподавателю, кафедре, группе, дисциплине, типу занятия, паре и чётности;
-- добавлены отчёты загруженности по преподавателям, аудиториям, кафедрам, парам и свободным аудиториям;
-- просмотр расписаний переведён с плоского списка на совмещённые матричные таблицы чётной/нечётной недели с разрезом по группам, преподавателям или аудиториям;
-- вкладка загруженности стала общей для аудиторий, преподавателей и кафедр;
-- интерфейсы кафедры и учебного отдела переведены в общий стиль админ-панели через role-based вкладки;
-- отдельная миграция `V2` удалена, изменения схемы внесены в `V1__init.sql`;
-- обновлена документация проекта.
-
-## Backend
-
-### Роли и авторизация
-
-Поддерживаются роли:
-
-- `ADMIN`;
-- `EDUCATION_OFFICE`;
-- `DEPARTMENT`;
-- `SCHEDULE_VIEWER`;
-- `TEACHER`;
-- `STUDENT`.
-
-Добавлены:
-
-- `AuthSessionService` — in-memory UUID-сессии;
-- `AuthContext` — текущий пользователь в `ThreadLocal`;
-- `AuthorizationInterceptor` — проверка `Authorization: Bearer ...`;
-- `@RequireRoles` — ограничение доступа на уровне контроллеров и методов;
-- `GET /api/auth/me` — текущий пользователь по токену.
-
-Redirect после входа:
-
-- `ADMIN` -> `/admin/`;
-- `EDUCATION_OFFICE` -> `/admin/#schedule-view`;
-- `DEPARTMENT` -> `/admin/#department-workspace`;
-- `SCHEDULE_VIEWER` -> `/admin/#schedule-view`;
-- `TEACHER` -> `/teacher/`;
-- `STUDENT` -> `/student/`.
-
-### Миграция БД
-
-Отдельная миграция `V2__roles_lifecycle_temporal_schedule.sql` удалена по текущему решению проекта.
-
-Все изменения схемы внесены в:
-
-```text
-backend/src/main/resources/db/migration/V1__init.sql
-```
-
-`V1__init.sql` теперь сразу создаёт:
-
-- lifecycle-поля к справочникам и пользователям;
-- `teacher_department_assignments`;
-- `subject_comments`;
-- version-поля к `schedule_rules`;
-- lock-поля к `schedule_rule_slots`;
-- `schedule_overrides`;
-- стартовых пользователей `учебный_отдел`, `кафедра_иб` и `просмотр_расписаний`.
-
-### Архивирование вместо удаления
-
-Архивирование добавлено для пользователей, аудиторий, оборудования, кафедр, специальностей, групп, подгрупп, дисциплин и правил расписания.
-
-Архивные аудитории, преподаватели, группы и дисциплины запрещены для новых назначений. Историческое расписание при этом не теряет ссылки.
-
-### История кафедр преподавателя
-
-Добавлены endpoint:
-
-- `GET /api/users/{id}/department-history`;
-- `POST /api/users/{id}/department-transfer`;
-- `GET /api/users/teachers/by-department/{departmentId}?date=YYYY-MM-DD`.
-
-При переводе преподавателя старая запись закрывается, новая открывается с `valid_from`, а `users.department_id` обновляется как текущая кафедра.
-
-### Расписание и загруженность
-
-Добавлены:
-
-- `GET /api/schedule/search`;
-- `GET /api/workload/teachers`;
-- `GET /api/workload/classrooms`;
-- `GET /api/workload/departments`;
-- `GET /api/workload/time-slots`;
-- `GET /api/workload/free-classrooms`;
-- `GET/POST/PUT/DELETE /api/edu-office/schedule/overrides`.
-
-`GET /api/schedule` теперь использует общий слой поиска, поэтому учитывает точечные изменения расписания.
-
-Роль `SCHEDULE_VIEWER` имеет доступ только к read-only просмотру расписаний и справочникам-фильтрам.
-
-### Кабинет кафедры API
-
-Добавлены:
-
-- `GET /api/department/subjects`;
-- `POST /api/department/subjects/import`;
-- `GET /api/department/subjects/{subjectId}/comments`;
-- `POST /api/department/subjects/{subjectId}/comments`;
-- `GET /api/department/teachers`;
-- `GET /api/department/schedule`.
-
-Для роли `DEPARTMENT` кафедра берётся из текущего пользователя. Для администратора можно выбрать кафедру в UI.
-
-## Frontend
-
-### Единая панель по ролям
-
-Отдельные интерфейсы `/department/` и `/edu-office/` заменены на redirect в общую админ-панель:
-
-- `/department/` -> `/admin/#department-workspace`;
-- `/edu-office/` -> `/admin/#schedule-view`.
-
-В `frontend/admin/js/main.js` добавлена фильтрация вкладок:
-
-- `ADMIN` видит все вкладки;
-- `EDUCATION_OFFICE` видит просмотр расписаний, конструктор расписания, календарный график, загруженность, аудитории и оборудование;
-- `DEPARTMENT` видит кабинет кафедры и просмотр расписаний;
-- `SCHEDULE_VIEWER` видит только просмотр расписаний.
-
-Backend не опирается только на скрытие вкладок. `AuthorizationInterceptor` проверяет bearer-токен для `/api/**`, а `@RequireRoles` ограничивает операции на контроллерах и методах. Для кафедры дополнительно закрыты обходные пути:
-
-- общий `/api/subjects` оставлен для записи только администратору, кафедра загружает дисциплины через scoped `/api/department/subjects/import`;
-- `/api/teacher-subjects` для роли `DEPARTMENT` проверяет, что и преподаватель, и дисциплина относятся к кафедре текущего пользователя;
-- `SCHEDULE_VIEWER` имеет только read-only доступ к расписаниям и справочникам-фильтрам.
-
-После браузерной проверки исправлено визуальное скрытие недоступных вкладок: `layout.css` теперь принудительно скрывает `.nav-item[hidden]` и скрытые пункты меню настроек, поэтому роли больше не видят чужие вкладки в sidebar.
-
-### Просмотр расписаний
-
-Добавлена вкладка:
-
-```text
-frontend/admin/views/schedule-view.html
-frontend/admin/js/views/schedule-view.js
-```
-
-Возможности:
-
-- фильтры по одной дате в периоде, группе, преподавателю, аудитории, кафедре, дисциплине, типу занятия и чётности;
-- двухнедельный диапазон для таблиц автоматически строится от понедельника выбранной недели;
-- выбор разреза таблиц: автоматически, по группам, по преподавателям или по аудиториям;
-- совмещённые матричные таблицы найденных занятий: строки — пары, столбцы — дни недели;
-- нечётная неделя отображается в верхней половине ячейки, чётная — в нижней, одинаковые занятия в обе недели схлопываются в цельную ячейку;
-- карточки занятий внутри ячеек с дисциплиной, группами, подгруппами, преподавателем, аудиторией, типом занятия, чётностью и ID слота.
-
-### Загруженность
-
-Вкладка `auditorium-workload` оставлена техническим tab id, но в UI называется `Загруженность`.
-
-Возможности:
-
-- выбор типа загруженности: аудитории, преподаватели или кафедры;
-- сводная матрица по выбранной дате: строки — выбранные сущности, столбцы — пары;
-- кафедральная матрица группирует занятия по кафедре преподавателя;
-- для аудиторий сохранены фильтры корпуса, вместимости и оборудования;
-- выбор конкретной аудитории, преподавателя или кафедры заменяет обзор двухнедельной таблицей по дням недели и времени;
-- чётная и нечётная недели показываются в одной ячейке: если состояние одинаковое, ячейка цельная, если отличается — делится вертикально.
-
-### Кабинет кафедры
-
-Добавлена вкладка:
-
-```text
-frontend/admin/views/department-workspace.html
-frontend/admin/js/views/department-workspace.js
-```
-
-Возможности:
-
-- просмотр дисциплин кафедры;
-- загрузка дисциплин из списка `код; название`;
-- просмотр и добавление комментариев к дисциплинам;
-- просмотр преподавателей кафедры;
-- просмотр нагрузки преподавателей кафедры за период.
-
-### Админка
-
-Обновлено:
-
-- создание пользователей теперь поддерживает роли `DEPARTMENT`, `EDUCATION_OFFICE` и `SCHEDULE_VIEWER`;
-- удаление пользователей заменено на архивирование;
-- вкладка аудиторий показывает архивные записи и умеет восстанавливать аудиторию;
-- удаление аудитории заменено на вывод из эксплуатации;
-- настройки временных слотов доступны `ADMIN` и `EDUCATION_OFFICE`.
-
-## Документация
-
-Обновлены:
-
-- `AGENTS.md`;
-- `docs/README.md`;
-- `docs/API.md`;
-- `docs/DATABASE.md`;
-- `docs/BUSINESS_LOGIC.md`;
-- `docs/FRONTEND.md`;
-- `docs/ARCHITECTURE.md`.
-
-## Проверки
-
-Статически проверены новые и изменённые JS-файлы:
-
-```bash
-node --check frontend/admin/js/main.js
-node --check frontend/admin/js/views/schedule-view.js
-node --check frontend/admin/js/views/auditorium-workload.js
-node --check frontend/admin/js/views/department-workspace.js
-node --check frontend/admin/settings/js/main.js
-node --check frontend/admin/js/api.js
-node --check frontend/admin/js/views/users.js
-node --check frontend/admin/js/views/classrooms.js
-git diff --check
-```
-
-Backend-компиляция проверяется через Docker Maven:
-
-```bash
-docker run --rm -v /mnt/HDD/magistr/magistr/backend:/app -w /app maven:3.9-eclipse-temurin-17 mvn -q -DskipTests compile
-```
-
-Результат: компиляция прошла успешно.
-
-Единая `V1__init.sql` проверена на пустой PostgreSQL 16 внутри Docker: SQL применился успешно.
-
-Локальный `mvn` в окружении отсутствует, поэтому используется Docker.
-
-## Что осталось следующим этапом
-
-Остались задачи, которые требуют отдельного цикла проработки:
-
-- UI для просмотра истории переводов преподавателя в админке;
-- UI для списка и редактирования уже созданных `schedule_overrides`;
-- более строгая проверка конфликтов перед сохранением переносов;
-- полноценный импорт XLSX/CSV для кафедры вместо текстовой загрузки;
-- браузерный smoke-test и проверка ролевых вкладок после запуска `localhost:80`.
diff --git a/analysis_results.md b/analysis_results.md
deleted file mode 100644
index 44c82ff..0000000
--- a/analysis_results.md
+++ /dev/null
@@ -1,288 +0,0 @@
-# Анализ структуры вкладок и предложения по UX/UI оптимизации системы Magistr
-
-В данном документе представлен детальный анализ текущей структуры интерфейса административной панели (SPA) и настроек системы Magistr. Выявлены пересекающиеся области функционала, сформулированы предложения по их объединению, переносу в настройки или удалению, а также предложены новые функциональные модули и технические решения для оптимизации UX/UI и производительности.
-
----
-
-## 1. Анализ текущей структуры и доступности вкладок
-
-На данный момент в основном SPA-интерфейсе администратора (`/admin/`) зарегистрировано **13 вкладок**, а в дополнительном SPA настроек (`/admin/settings/`) — **2 вкладки**.
-
-В зависимости от роли пользователя, сайдбар фильтруется следующим образом:
-
-| Вкладка (ID) | Описание | Доступность по ролям |
-| :--- | :--- | :--- |
-| `users` | CRUD пользователей и архивирование | `ADMIN` |
-| `groups` | CRUD групп, подгрупп и назначений календарей | `ADMIN` |
-| `edu-forms` | Справочник форм обучения | `ADMIN` |
-| `profiles` | Управление профилями обучения специальностей | `ADMIN` |
-| `equipments` | Каталог оборудования | `ADMIN`, `EDUCATION_OFFICE` |
-| `classrooms` | Список аудиторий с привязкой оборудования | `ADMIN`, `EDUCATION_OFFICE` |
-| `subjects` | CRUD всех дисциплин и привязка преподавателей | `ADMIN` |
-| `department-workspace` | Рабочая область кафедры (дисциплины, импорт, нагрузка) | `ADMIN`, `DEPARTMENT` |
-| `schedule-view` | Просмотр расписаний (read-only) | `ADMIN`, `EDUCATION_OFFICE`, `DEPARTMENT`, `SCHEDULE_VIEWER` |
-| `schedule` | Конструктор правил динамического расписания | `ADMIN`, `EDUCATION_OFFICE` |
-| `academic-calendar` | Календарные графики и Excel-редактор сетки | `ADMIN`, `EDUCATION_OFFICE` |
-| `auditorium-workload` | Матрицы и таблицы загруженности | `ADMIN`, `EDUCATION_OFFICE` |
-| `database` | Управление тенантами (БД клиентов) | `ADMIN` |
-| **Settings** (SPA) | Общие настройки, Управление временными слотами | `ADMIN`, `EDUCATION_OFFICE` (ссылка в подвале) |
-
----
-
-## 2. Пересечения функционала и проблемные зоны
-
-### 2.1. Избыточное дробление академической структуры
-Для описания структуры обучения сейчас используются четыре отдельные вкладки:
-1. `departments-data` (Создание кафедры/специальности)
-2. `profiles` (Профили обучения специальностей)
-3. `edu-forms` (Формы обучения)
-4. `groups` (В блоке создания группы выбираются форма, кафедра, специальность и профиль)
-
-**В чём проблема:**
-* **Разрыв контекста:** Чтобы завести новую специальность с профилями, администратору сначала нужно пойти во вкладку `departments-data`, создать специальность, затем перейти во вкладку `profiles`, выбрать в селекте эту специальность и добавить профили.
-* **Перегрузка меню:** 13 вкладок в сайдбаре для роли `ADMIN` — это слишком много. Пользователю трудно ориентироваться визуально.
-
-### 2.2. Дублирование и раздвоение управления дисциплинами
-Управление дисциплинами разнесено между вкладками `subjects` (для администратора) и `department-workspace` (для кафедры).
-
-**В чём проблема:**
-* Администратор во вкладке `subjects` видит плоскую таблицу всех дисциплин всех кафедр, но не имеет удобных инструментов фильтрации по кафедре.
-* Форма создания новой дисциплины во вкладке `subjects` требует ввода **числового ID кафедры вручную** (поле `new-subject-department` типа `number`). Это критическая UX-ошибка: администратор не должен помнить числовые ID БД наизусть.
-* Привязка преподавателей к дисциплинам (`teacher_subjects`) находится на вкладке `subjects`. При этом сама нагрузка преподавателей и список преподавателей кафедры отображаются на вкладке `department-workspace`. Логичнее было бы видеть, какие дисциплины ведёт преподаватель, непосредственно при работе с его нагрузкой или в едином справочнике преподавателей/кафедры.
-
-### 2.3. Низкая частота использования справочника оборудования (`equipments`)
-Оборудование существует только как подчиненная сущность для аудиторий (чтобы указать, что в аудитории 101 есть 20 ПК и 1 проектор).
-
-**В чём проблема:**
-* Выделение целой вкладки под простой список («Проектор», «ПК») не оправдано. Список оборудования меняется раз в несколько лет.
-* При этом привязка оборудования к аудиториям происходит на вкладке `classrooms`.
-
-### 2.4. Перегруженность вкладки групп (`groups`)
-На вкладке групп на одном экране выводятся сразу три тяжелые формы и три таблицы:
-1. Создание/редактирование групп + таблица групп.
-2. Создание подгрупп для лабораторных + таблица подгрупп.
-3. Назначение календарного графика группе + таблица назначений.
-
-**В чём проблема:**
-* Экран перегружен элементами управления.
-* Для работы с подгруппами или назначениями графиков конкретной группы пользователю приходится выбирать эту группу из длинного выпадающего списка в отдельной форме, вместо того чтобы выполнять действия в контексте строки этой группы в таблице.
-
-### 2.5. Нахождение системной вкладки «База данных» в общем меню расписания
-Вкладка `database` отвечает за управление тенантами (добавление новых вузов-клиентов, создание для них БД и запуск Flyway миграций).
-
-**В чём проблема:**
-* Это технический функционал уровня Super-Admin / DevOps. Он не имеет отношения к ежедневному планированию расписания. Нахождение его в одном ряду с расписанием и группами нарушает логику интерфейса.
-
----
-
-## 3. Рекомендации по оптимизации структуры (Что убрать, объединить и перенести)
-
-```mermaid
-graph TD
- subgraph Было (13 вкладок в меню ADMIN)
- direction TB
- T1[database]
- T2[edu-forms]
- T3[departments-data]
- T4[profiles]
- T5[equipments]
- T6[classrooms]
- T7[groups]
- T8[users]
- T9[subjects]
- T10[department-workspace]
- T11[schedule]
- T12[schedule-view]
- T13[academic-calendar]
- T14[auditorium-workload]
- end
-
- subgraph Стало (Сгруппированное меню + настройки)
- direction TB
- subgraph Основное меню SPA (Группы вкладок)
- direction TB
- DASH[1. Дашборд / Главная]
-
- subgraph Модуль: Расписание
- SCH_ED[2. Конструктор расписания]
- SCH_VI[3. Просмотр расписаний]
- CAL[4. Календарный график]
- WORK[5. Загруженность]
- end
-
- subgraph Модуль: Структура
- UNIV[6. Структура вуза
Кафедры, Специальности, Профили]
- GRP[7. Группы и подгруппы]
- SUBJ[8. Дисциплины]
- end
-
- subgraph Модуль: Ресурсы
- CLASS[9. Аудиторный фонд
Аудитории + Оборудование]
- end
-
- USR[10. Пользователи]
- end
-
- subgraph SPA Настройки (Настройки системы)
- direction TB
- SET_GEN[Общие настройки]
- SET_TIME[Временные слоты сетка]
- SET_FORM[Формы обучения из edu-forms]
- SET_DB[Базы данных / Тенанты из database]
- end
- end
-
- T1 -->|Перенести| SET_DB
- T2 -->|Перенести| SET_FORM
- T3 -->|Объединить| UNIV
- T4 -->|Объединить| UNIV
- T5 -->|Объединить| CLASS
- T6 -->|Объединить| CLASS
- T7 -->|Оптимизировать| GRP
- T8 -->|Оставить| USR
- T9 -->|Оптимизировать| SUBJ
- T10 -->|Сохранить для роли Кафедра| SUBJ
- T11 -->|Оставить| SCH_ED
- T12 -->|Оставить| SCH_VI
- T13 -->|Оставить| CAL
- T14 -->|Оставить| WORK
-```
-
-### 3.1. Перенос в настройки (`/admin/settings/`)
-1. **База данных (`database`)**: Перенести в SPA настроек в раздел «Управление тенантами». Доступ должен быть только у роли `ADMIN`.
-2. **Формы обучения (`edu-forms`)**: Перенести в настройки. Данный справочник заполняется один раз и не требует оперативного доступа из главного меню.
-
-### 3.2. Объединение вкладок
-1. **Объединить Кафедры, Специальности и Профили** в одну вкладку **«Структура вуза»** (`university-structure`):
- * Интерфейс делится на две вкладки внутри страницы: **«Кафедры»** и **«Специальности»**.
- * Управление профилями должно происходить прямо внутри списка специальностей. Например, в строке специальности в таблице добавляется кнопка «Профили», открывающая список профилей этой специальности в раскрывающейся строке (accordion) или модальном окне.
-2. **Объединить Аудитории (`classrooms`) и Оборудование (`equipments`)** в одну вкладку **«Аудиторный фонд»**:
- * Основной экран показывает список аудиторий.
- * Рядом располагается кнопка «Управление каталогом оборудования», которая открывает модальное окно с простым списком (добавить/удалить тип оборудования). Это избавит от необходимости держать под это отдельную вкладку в сайдбаре.
-
-### 3.3. Реорганизация вкладки групп (`groups`)
-* **Оставить на вкладке только список групп** с возможностью фильтрации по курсу, кафедре и форме обучения.
-* **Вынести подгруппы и назначения календарей из глобальных форм:**
- * В строке таблицы для каждой группы добавить действия:
- * `[Подгруппы]` — открывает компактное модальное окно для быстрого создания/редактирования подгрупп (лабораторных) именно для этой группы.
- * `[Календарь]` — открывает модальное окно назначения календарного учебного графика на учебные годы для этой группы.
- * Это уберет лишние тяжелые формы с главной страницы и исключит необходимость выбора группы из селектов вручную.
-
-### 3.4. Оптимизация Дисциплин (`subjects`) и Кабинета кафедры
-* **Исправить форму добавления дисциплины:** Заменить ручной числовой ввод ID кафедры (`new-subject-department`) на стандартный выпадающий список (выбор из загруженных кафедр).
-* **Связать привязку преподавателей с дисциплинами:** Вместо двух разрозненных таблиц на вкладке `subjects` («Все дисциплины» и «Привязки преподавателей»), объединить их:
- * В строке дисциплины выводить список привязанных преподавателей (в виде чипов/badge).
- * По клику на кнопку «Преподаватели» в строке дисциплины открывать модальное окно привязки/отвязки преподавателей для этой конкретной дисциплины.
-
----
-
-## 4. Что необходимо добавить (Новый функционал)
-
-### 4.1. Главная страница / Дашборд (`dashboard`)
-При входе в систему администратор и сотрудники учебного отдела должны видеть не сырые таблицы пользователей или расписания, а высокоуровневую аналитическую панель:
-* **Информационные карточки (Метрики):**
- * Всего активных групп / студентов.
- * Количество задействованных преподавателей.
- * Процент занятости аудиторного фонда на текущий день.
- * Количество запланированных пар на сегодня.
-* **Мониторинг расписания в реальном времени:**
- * Список идущих прямо сейчас пар (текущий временной слот).
- * Ближайшие свободные аудитории.
-* **Быстрый переход:** Кнопки быстрого создания правила расписания, добавления переноса/замены.
-
-### 4.2. Центр предупреждений и конфликтов (Red Zone)
-В соответствии с планируемой бизнес-логикой (раздел 5 `docs/BUSINESS_LOGIC.md`), система должна автоматически валидировать расписание и предупреждать о коллизиях.
-Необходима отдельная вкладка или виджет на дашборде **«Конфликты расписания»**:
-* **Критические ошибки (Блокирующие генерацию):**
- * *Накладки преподавателей:* Преподаватель назначен в один и тот же временной слот в разные аудитории / к разным группам (кроме потоковых лекций).
- * *Накладки аудиторий:* Две разные пары стоят в одной аудитории в один слот.
-* **Предупреждения (Мягкие проверки):**
- * *Превышение вместимости:* Численность группы (или сумма подгрупп при совмещенных занятиях) превышает физическую вместимость аудитории.
- * *Недостаток оборудования:* Дисциплина (например, лабораторная по химии) требует определенного оборудования, которого нет в назначенной аудитории.
- * *Превышение нагрузки:* Преподаватель превысил недельный лимит часов.
-
----
-
-## 5. Концепция новой структуры меню (Сайдбара)
-
-Для уменьшения визуального шума сайдбар предлагается сделать **двухуровневым** (сворачиваемые группы) или четко разделить визуальными разделителями:
-
-```
-[ Логотип Magistr ]
----------------------------
-👤 Кабинет кафедры <-- (Показывается только для роли DEPARTMENT)
-📈 Дашборд <-- (Новый главный экран для ADMIN / EDU_OFFICE)
-
-📁 РАСПИСАНИЕ
- 🗓 Конструктор правил
- 🗓 Точечные изменения <-- (Выделенный функционал оверрайдов/переносов)
- 📅 Календарный график
- 📊 Загруженность
- 🔍 Просмотр расписаний
-
-🗂 СУБЪЕКТЫ И РЕСУРСЫ
- 🏫 Аудиторный фонд <-- (Объединенные Аудитории + Оборудование)
- 🎓 Группы обучения <-- (Группы + модалки подгрупп/календарей)
- 🏛 Структура вуза <-- (Кафедры + Специальности + Профили)
- 📚 Дисциплины <-- (Дисциплины + модалки преподавателей)
-
-⚙️ СИСТЕМА
- 👥 Пользователи
- ⚙️ Настройки <-- (Переход в настройки SPA: слоты, БД, формы обучения)
----------------------------
-[ Профиль / Выход ]
-```
-
----
-
-## 6. Идеи по оптимизации фронтенда и взаимодействия с API
-
-### 6.1. Кэширование справочников на клиенте
-На данный момент при переключении почти каждой вкладки заново запрашиваются списки кафедр, специальностей, учебных годов и т.д.
-* **Решение:** Реализовать простой кэш-менеджер во фронтенд-клиенте (`api.js` или отдельный `cache.js`):
- ```javascript
- const cache = new Map();
- export async function getCachedData(key, fetchPromise) {
- if (!cache.has(key)) {
- cache.set(key, await fetchPromise);
- }
- return cache.get(key);
- }
- export function clearCache(key) {
- if (key) cache.delete(key);
- else cache.clear();
- }
- ```
- Это позволит избежать десятков дублирующих запросов при переключении между вкладками `groups`, `subjects`, `schedule`.
-
-### 6.2. Ленивая инициализация вкладок (Lazy Loading)
-Сейчас в `main.js` импортируются все JS-модули вкладок одновременно при загрузке страницы:
-```javascript
-import { initUsers } from './views/users.js';
-import { initGroups } from './views/groups.js';
-// ...еще 10 импортов
-```
-* **Решение:** Перейти на динамический импорт модулей инициализации при переходе на конкретную вкладку:
- ```javascript
- async function switchTab(tab) {
- // ...
- const viewModule = await import(`./views/${tab}.js`);
- viewModule.init();
- // ...
- }
- ```
- Это уменьшит размер начального JS-бандла и ускорит первую загрузку страницы.
-
-### 6.3. Единый реестр кастомных выпадающих списков
-В проекте реализованы кастомные селекты (выпадающие списки с поддержкой поиска и чекбоксов). При динамической подгрузке HTML-шаблонов часто требуется их повторная инициализация.
-* **Решение:** Создать глобальный шину событий (Event Bus) или MutationObserver, который автоматически подхватывает элементы с классами `.custom-select` или атрибутами `data-select` и инициализирует их без вызова ручного кода `initAllCustomDropdowns()` в каждом отдельном скрипте представления.
-
----
-
-## Резюме
-
-Предложенные изменения позволят:
-1. Сократить количество пунктов основного меню с **13** до **8-9** логически сгруппированных разделов.
-2. Исключить ручной ввод ID (заменив на селекты) и разгрузить перегруженные интерфейсы (выносом подгрупп и назначений в контекстные модальные окна групп).
-3. Повысить отзывчивость интерфейса за счет клиентского кэширования справочников и ленивой загрузки JS-модулей.
-4. Добавить полноценный Дашборд и Центр предупреждений о конфликтах, что выведет аналитические возможности системы на уровень премиум-класса.