mirror of
https://github.com/EDeev/mospolytech-mcp.git
synced 2026-10-07 20:49:52 +03:00
229 lines
20 KiB
Markdown
229 lines
20 KiB
Markdown
# План проекта «Mospolytech MCP»
|
||
|
||
Команда: Деев Егор Викторович, Шмыговский Никита Сергеевич, Старков Руслан
|
||
Владимирович (гр. 241–327).
|
||
|
||
Это наш рабочий план — не сдаём его никому, правим постоянно. Основан на
|
||
официальных методичках всех 8 лабораторных из СДО
|
||
([`docs/sdo/`](../sdo/)) и на нашем [техническом задании](../official/lab01-tech-spec.pdf).
|
||
|
||
## 0. Важное уточнение
|
||
|
||
Предыдущая версия этого файла угадывала содержание лабораторных №2–8 (мы
|
||
на тот момент их не видели) и придумала, что они про поэтапную разработку
|
||
функций MCP-сервера — БД, потом инструменты, потом авторизация и т.д. Это
|
||
оказалось неверно. Реальные методички описывают совсем другой курс — про
|
||
DevOps-практики: виртуализацию, контейнеризацию, CI/CD, статический анализ,
|
||
автотесты, миграции БД. Этот файл переписан заново по факту.
|
||
|
||
## 1. Два параллельных трека
|
||
|
||
Тут важно не путать две разные вещи:
|
||
|
||
- **Продуктовый трек** — сам MCP-сервер (то, что мы пишем в `src/`). Он не
|
||
привязан к номерам лабораторных — методички вообще не говорят, что
|
||
конкретно писать и когда. Наша задача — держать его в рабочем состоянии,
|
||
потому что начиная с ЛР2 он становится "объектом", который мы
|
||
виртуализируем, контейнеризируем, гоняем через CI/CD, статически
|
||
анализируем и тестируем. Без работающего прототипа лабораторные 2–8
|
||
выполнять физически не на чем.
|
||
- **Инфраструктурный трек** — собственно 8 лабораторных. Это последовательность
|
||
DevOps-практик, каждая следующая опирается на результат предыдущей
|
||
(нельзя настроить CI, не имея Docker-образа; нельзя гонять автотесты в
|
||
пайплайне, не имея пайплайна).
|
||
|
||
## 2. Логические этапы лабораторных (2–8)
|
||
|
||
Реальные лабораторные естественно группируются в 4 этапа — каждый следующий
|
||
физически невозможен без результата предыдущего.
|
||
|
||
### Этап А. Стенды (ЛР 2–3)
|
||
|
||
| ЛР | Тема | Что делаем |
|
||
|---|---|---|
|
||
| 2 | Виртуализация | Гипервизор, 3+ ВМ (test/stage/prod), объединяем в общую сеть (ping "от всех ко всем"), на test выкладываем проект через git, разворачиваем тулчейн, запускаем прототип |
|
||
| 3 | Контейнеризация | Docker на всех ВМ; Dockerfile для сборки и запуска приложения; docker-compose.yaml с приложением + БД/другим сервисом, volumes для сохранения данных между рестартами |
|
||
|
||
Итог этапа: на трёх ВМ поднята сеть, на test приложение собирается и
|
||
запускается в Docker вместе с БД, данные переживают рестарт контейнера.
|
||
|
||
### Этап Б. Конвейер CI/CD (ЛР 4–5)
|
||
|
||
| ЛР | Тема | Что делаем |
|
||
|---|---|---|
|
||
| 4 | Непрерывная интеграция | Пушим собранный образ в DockerHub; разворачиваем TeamCity server; заводим пользователей (по одному на каждого из нас); подключаем репозиторий; настраиваем сборку → образ → push в DockerHub для веток dev и prod |
|
||
| 5 | Непрерывная доставка | Добавляем шаг деплоя на stage из образа в DockerHub вместе с БД; разворачиваем TeamCity agent на test; переходим на GitFlow (или другую модель веток); feature-ветка → PR в dev с ревью от другого участника команды → после мержа сборка + автодеплой на stage |
|
||
|
||
Итог этапа: у нас настоящий CI/CD-конвейер — коммит в feature-ветку
|
||
собирается, PR в dev требует ревью, после мержа приложение само уезжает на
|
||
stage.
|
||
|
||
### Этап В. Ворота качества в конвейере (ЛР 6–7)
|
||
|
||
| ЛР | Тема | Что делаем |
|
||
|---|---|---|
|
||
| 6 | Статический анализ кода | Минимум 2 анализатора (качество кода / безопасность / поиск секретов), шаги в пайплайне TeamCity — билд падает при находках максимальной критичности |
|
||
| 7 | Автоматизированное тестирование | Юнит + интеграционные тесты, покрытие ≥40% функционала из ТЗ; шаг тестирования в пайплайне для всех веток; демонстрация и провала, и прохождения на feature/dev/prod |
|
||
|
||
Итог этапа: код, который не проходит статический анализ или тесты, до
|
||
stage/prod физически не доезжает — пайплайн его останавливает.
|
||
|
||
У нас тут есть fora — часть офлайн-тестов (`tests/`) уже написана заранее
|
||
(лк_api + open_api, 14 тестов). Они пригодятся напрямую в ЛР7, но 40% от
|
||
всего функционала ТЗ ими одними не наберём — MCP-сервера и слоя БД ещё нет,
|
||
их тоже придётся покрывать тестами.
|
||
|
||
### Этап Г. Жизненный цикл базы данных в конвейере (ЛР 8)
|
||
|
||
| ЛР | Тема | Что делаем |
|
||
|---|---|---|
|
||
| 8 | Миграции БД | Директория со схемой БД в репозитории; статический анализатор безопасности SQL как шаг пайплайна; ручной, а затем автоматизированный деплой схемы на stage (со сверкой test/stage); отдельный prod-пайплайн с бэкапом БД перед изменениями |
|
||
|
||
Самая тяжёлая лабораторная — по сути весь этап Б, применённый отдельно к
|
||
базе данных. Логично начинать только после того, как этапы А–В полностью
|
||
стабильны, иначе непонятно, на чём проверять сверку схем.
|
||
|
||
## 3. Как отсюда следует планировать работу
|
||
|
||
Порядок такой, что физически нельзя пропустить шаг:
|
||
|
||
1. ~~Прямо сейчас~~ **Сделано** — продуктовый трек: минимальный работающий
|
||
MCP-сервер (`server.py` поверх `lk_api`/`open_api`) + слой БД
|
||
(SQLAlchemy-модели, первая миграция Alembic, реальный PostgreSQL на
|
||
общем сервере команды). Один инструмент (`list_groups`, ФОД-001) уже
|
||
реально ходит в кэш и обратно — то, что нужно было к ЛР2 (пункт
|
||
"запустить прототип"). Подробности — раздел 6.
|
||
2. **ЛР2 → ЛР3** — как только прототип есть, поднимаем стенды и
|
||
контейнеризируем. Здесь же нужна настоящая БД в docker-compose — та,
|
||
что мы придумали в разделе 4 ниже.
|
||
3. **ЛР4 → ЛР5** — пайплайн настраиваем один раз и дальше живём с ним
|
||
постоянно: каждая следующая лабораторная (6, 7, 8) — это новые шаги в
|
||
том же самом пайплайне, а не новый пайплайн с нуля.
|
||
4. **ЛР8 — в конце**, когда схема БД уже не черновик, а что-то, что реально
|
||
меняется по ходу разработки (иначе нечего мигрировать).
|
||
|
||
Отчёты по каждой лабораторной — отдельный текстовый документ со
|
||
скриншотами (см. задания в каждой методичке), кладём в `docs/official/`
|
||
рядом с ТЗ, по мере сдачи. Устная защита есть на каждой — со стороны
|
||
методичек 2–8 всегда есть блок "Вопросы для изучения", их надо реально
|
||
понимать, а не просто списать шаги.
|
||
|
||
### 3.1. По каким лабораторным двигаем функционал продукта, а где — фиксируем
|
||
|
||
Методички сами по себе не требуют конкретного объёма функций ни на одном
|
||
шаге, кроме одного жёсткого места — ЛР7 требует покрытие тестами ≥40%
|
||
функционала из ТЗ. Это и есть якорь, вокруг которого стоит планировать:
|
||
|
||
- **До ЛР2 — сделано.** MCP-сервер запускается и отвечает на ФОД-001
|
||
(`list_groups`) через `open_api`.
|
||
- **Между ЛР2 и ЛР3 — тоже сделано.** Слой БД (SQLAlchemy + Alembic) и
|
||
реальная запись — кэш списка групп (ФХД-003, `cache.py`). Проверили
|
||
живьём: 638 групп с rasp.dmami.ru легли в `groups_cache` на реальном
|
||
PostgreSQL, повторный вызов идёт уже из кэша. Ровно то, что нужно для
|
||
демонстрации в ЛР3 (записать → рестарт контейнера → данные на месте).
|
||
Лог обращений к ЛК (ФХД-004) — кандидат на следующую функцию с записью,
|
||
не обязательно прямо сейчас.
|
||
- **ЛР4–5 — основной спринт разработки функционала.** Сами эти лабы не
|
||
требуют нового кода продукта (там настраивается TeamCity и ветки), а
|
||
значит это окно, где можно спокойно писать оставшиеся функции —
|
||
ФЛК-001..007 целиком, оставшиеся ФОД, ФХД-001/002. Цель — закончить
|
||
**весь функционал раздела 4.2 ТЗ к концу ЛР5**.
|
||
- **ЛР6–7 — новый функционал не пишем, только фиксы.** Это осознанное
|
||
решение, а не жёсткое требование методичек: как только заработал
|
||
статический анализ и тесты (этап В), любой новый код надо будет через
|
||
них проводить, а переписывать тесты под ещё нестабильный функционал —
|
||
двойная работа. Дешевле сначала закончить фичи (ЛР4-5), потом накрыть их
|
||
готовыми тестами и спокойно поймать находки анализаторов. В ЛР7 40%
|
||
покрытия наберётся без напряжения, раз к этому моменту реализовано
|
||
фактически всё.
|
||
- **ЛР8 — точечное изменение схемы, не новая фича.** Заданию нужно, чтобы
|
||
было что мигрировать (реальное изменение схемы БД + кода). Это может
|
||
быть небольшая, специально приберёгнутая правка (например, добавить
|
||
таблицу/поле под одну из уже реализованных функций) — не ради
|
||
пользовательской ценности, а чтобы через неё честно продемонстрировать
|
||
процесс миграции.
|
||
|
||
Если по ходу дела окажется, что часть функционала (раздел 4.2 ТЗ) реально
|
||
не укладывается в ЛР4-5 по времени — переносим доделку на ЛР6-7 без
|
||
проблем, план не жёсткий. Но если можем — лучше не тащить фиче-работу до
|
||
последних лаб: чем раньше код "заморожен", тем меньше сюрпризов от
|
||
анализаторов и тестов ближе к сдаче.
|
||
|
||
## 4. Продуктовый трек: черновая схема базы данных
|
||
|
||
Нужна к ЛР3 (для docker-compose) и будет меняться к ЛР8 (миграции), так что
|
||
это живой черновик, не финал:
|
||
|
||
- `users` — id, guid (из ЛК), login, отображаемое имя, created_at
|
||
- `user_sessions` — user_id → legacy token, jwt, jwt_refresh, updated_at
|
||
(пароль **не хранится** нигде и никогда — используется один раз при login)
|
||
- `groups_cache`, `schedule_cache` — справочные данные с TTL (ФХД-003)
|
||
- `performance_history`, `payments_history`, `requests_history` — append-only
|
||
снимки (ФХД-002): каждое новое значение — новая строка, а не UPDATE
|
||
- `notifications` — уведомления пользователя с внешним id для дедупликации
|
||
- `lk_access_log` — user_id, action, status, created_at (ФХД-004; для
|
||
открытого API строк не создаётся — ТЭ-001)
|
||
|
||
## 5. Открытые вопросы и риски (продуктовый трек)
|
||
|
||
1. **ФОД-003 (расписание преподавателя) фактически не доступно без
|
||
авторизации.** Публичный `rasp.dmami.ru` (на который опирается
|
||
`mospolytech_api`) не имеет маршрута для поиска по преподавателю — мы
|
||
проверили руками (`site/teacher` не существует, `teachers-list.json`
|
||
отсутствует). Единственный найденный источник — `getScheduleTeacher` в
|
||
лёгаси-API личного кабинета, требует авторизации и в самой Go-библиотеке
|
||
MPU_LK_API помечен как неподтверждённый (🔎 в её API.md). Формально
|
||
противоречит ТЭ-001 ("без авторизации"). Пока реализовано через ЛК-сессию
|
||
как временное решение (`LKClient.get_teacher_schedule`).
|
||
2. **ФЛК-007 (отправка сообщения) не имеет подтверждённого формата
|
||
запроса.** Го-библиотека документирует действие только как
|
||
`POST newMessage=1&<...>`, реальные поля формы нигде не зафиксированы.
|
||
Реализован best-effort вариант (`LKClient.send_message`, поля `id` +
|
||
`text`) — надо проверить на реальном аккаунте перед тем, как полагаться
|
||
на него.
|
||
3. **ТСФ-003 (10 запросов/сек)** пока не проверялось — станет актуальным,
|
||
когда появится реальный MCP-сервер и нагрузочные тесты (перекликается с
|
||
ЛР7, раздел про нагрузочное тестирование в теории, хотя оно явно не
|
||
входит в задания).
|
||
|
||
## 6. Что уже сделано (продуктовый трек, заранее)
|
||
|
||
`src/mospolytech_mcp/`:
|
||
|
||
- **`lk_api/`** — наш Python-порт Go-библиотеки MPU_LK_API (личный кабинет):
|
||
авторизация (обе системы токенов), расписание, успеваемость, платежи,
|
||
заявки, уведомления/объявления, диалоги, отправка сообщений (см. риски
|
||
выше), плюс `lk_get`/`lk_post_form` как escape hatch.
|
||
- **`open_api/`** — обёртка над вендоренной `mospolytech_api` (открытые
|
||
данные: группы, расписание группы). Код библиотеки лежит в
|
||
`open_api/_vendor/` нетронутым — так и задумано автором (ТПО-004).
|
||
- **`api.py`** — `UniversityAPI`: один объект, который держит `open` и `lk`
|
||
вместе.
|
||
- **`db/`** — SQLAlchemy-модели (пока одна — `GroupsCache`), схема
|
||
версионируется через Alembic (`alembic/`, `alembic upgrade head`
|
||
применяет миграции).
|
||
- **`cache.py`** — `GroupsCacheStore`: TTL-кэш списка групп поверх БД
|
||
(ФХД-003), плюс fallback на устаревший кэш при недоступности источника
|
||
(ТН-001).
|
||
- **`server.py`** — сам MCP-сервер (официальный Python SDK, ТПО-002),
|
||
сейчас с одним инструментом — `list_groups`.
|
||
|
||
14/14 офлайн-тестов зелёные (`tests/`). `open_api` живьём прогнан против
|
||
настоящего `rasp.dmami.ru`. MCP-сервер живьём прогнан целиком: протокол →
|
||
`list_groups` → `open_api` → запись в `groups_cache` на реальном
|
||
PostgreSQL → повторный вызов из кэша. Для ручной проверки `lk_api` на
|
||
своём аккаунте — `scripts/check_lk_api.py`.
|
||
|
||
**БД:** общий PostgreSQL-сервер команды (не наш локальный, реальный
|
||
удалённый инстанс). У каждого свой пользователь — не шарим `postgres`/
|
||
admin. Подключение — через `DATABASE_URL` в `.env` (см. `.env.example`),
|
||
сам файл не коммитится. Если у вас его нет — спросите данные в чате
|
||
команды, пересылать их через репозиторий/коммиты не будем.
|
||
|
||
**Дальше по плану (раздел 3.1):** окно ЛР4-5 — дописываем ФЛК-001..007
|
||
целиком и оставшиеся ФОД/ФХД, дальше по разделу 3.1 фичи не трогаем.
|
||
|
||
Не портировано из MPU_LK_API (вне текущей области ТЗ, добавим при
|
||
необходимости): finance.go (банковские карты), pep.go, roles.go,
|
||
vaccines.go, directory.go, profile.go (семья/дети/проектная
|
||
деятельность/смена группы/справки).
|