Files
site_aegisone/py_service/docs/AEGISONE_INFRASTRUCTURE_PLAN.md
T
angel 72b6879f4b v1.7.0: refactor max_bot to flat structure, add VCF+UserModel+NLP history context, portal pages and proxy fixes
- Refactored max_bot from nested packages to flat module structure
- Q2: Extended BotUser model (patronymic, email, org, address, vcf_raw, contact_hash, phone_verified, email_verified, last_interaction, total_conversations, total_tickets)
- Q2: VCF parser (FN, N, TEL, EMAIL, ORG, ADR), upsert on re-contact, NLP history context (_get_user_history_context -> YandexGPT)
- Q1: Broadcast preview modal with 10s confirmation timer
- Q3: CSS var(--white)->var(--bg-card), var(--text)->var(--text-primary)
- Q4: bot_settings showNotification(), editable max_bot_id
- Q5: Webhook secret passthrough via X-Max-Bot-Api-Secret
- Masking sensitive keys, dialog_cleared handler, migrate via _add_column_if_not_exists()
- Rate limit (asyncio.sleep 0.5 per 10), dead code removed, conv.intent context in contact.py
- Portal pages: bot_consent, bot_kb (edit), bot_settings, bot_test, bot_tickets, portal_settings
- Tests: 21/21 passing, added test_yandex_gpt.py, test_email_sender.py
- Deploy: deploy_full.sh, schema.sql, seed_knowledge_base.sql
2026-05-29 02:30:30 +03:00

43 KiB
Raw Blame History

AegisOne Engineering — План миграции инфраструктуры и переписывания сервисной части

Статус: План утверждён, готов к реализации
Дата: 2026-05-17
Команда: Владелец + AI-ассистент
Примечание: Если при реализации возникнут вопросы — лучше уточнить, чем переделывать потом.


1. Текущее состояние

1.1. Публичная часть (aegisone.ru)

  • Технологии: PHP 7.4, MySQL, inline CSS/JS
  • Хостинг: Shared-хостинг (проблемы: HTTP 302-редирект, блокировка /assets/, отключённый RewriteEngine, PHP 7.4 тупик)
  • Страницы: Главная, услуги, блог, контакты, форма обратной связи
  • SEO: robots.txt, sitemap.xml, канонические URL
  • Решение: Не трогать. Перенести на VPS как есть в Docker-контейнер.

1.2. Сервисная часть (service.aegisone.ru)

  • Технологии: PHP 7.4, MySQL, inline CSS/JS
  • Функционал: Админ-панель (управление пользователями, объектами, SLA, опросниками, блогом, документами), расчёты (Risk Score, Object Index, SLA price), паспорта объектов
  • Проблемы: PHP 7.4 ограничивает развитие, нет автоматизации отчётов, нет интеграций
  • Решение: Полностью переписать на Python/FastAPI + Jinja2

1.3. Инфраструктура

  • VPS: Уже есть, на нём один проект (FastAPI + Uvicorn + Celery + Nginx + PostgreSQL + Redis + Alembic)
  • Хостинг: Платный, планируется отказ
  • Git: Нет централизованного сервера, работа на локальной машине
  • SSL: От регистратора домена (статический, неудобно для мультидомена)
  • Домены: aegisone.ru (публичная часть), планируется service.aegisone.ru (админка)

2. Целевая архитектура

┌─────────────────────────────────────────────────────────────────────┐
│                              VPS                                     │
│                                                                       │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                   Nginx (reverse proxy + SSL)                  │  │
│  │                   порт 80/443, Let's Encrypt                   │  │
│  │                                                                │  │
│  │  aegisone.ru ──────────────► php-fpm container (порт 9000)    │  │
│  │  service.aegisone.ru ─────► fastapi container (порт 8000)     │  │
│  │  other-project.ru ────────► project2 container (порт 8001)    │  │
│  │  git.aegisone.ru ─────────► gitea container (порт 3000)       │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                       │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐  │
│  │  AegisOne PHP    │  │  AegisOne Python │  │   Other Project  │  │
│  │  (публичная)     │  │  (админка)       │  │   (FastAPI)      │  │
│  │                  │  │                  │  │                  │  │
│  │  • Главная       │  │  • Аутентификация│  │  • ...           │  │
│  │  • Услуги        │  │  • Пользователи  │  │                  │  │
│  │  • Блог          │  │  • Объекты       │  │                  │  │
│  │  • Контакты      │  │  • Клиенты       │  │                  │  │
│  │  • FAQ           │  │  • SLA           │  │                  │  │
│  │  • Карусель      │  │  • Опросники     │  │                  │  │
│  │  • Форма         │  │  • Расчёты       │  │                  │  │
│  │                  │  │  • Отчёты (PDF)  │  │                  │  │
│  │                  │  │  • Документы     │  │                  │  │
│  │                  │  │  • Yandex Disk   │  │                  │  │
│  └────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘  │
│           │                     │                     │            │
│           └──────────┬──────────┘                     │            │
│                      │                                │            │
│           ┌──────────▼──────────┐          ┌─────────▼────────┐   │
│           │    PostgreSQL       │          │   PostgreSQL     │   │
│           │  (AegisOne БД)      │          │  (Project 2 БД)  │   │
│           │                     │          │                  │   │
│           │  • users            │          │  • ...           │   │
│           │  • customers        │          │                  │   │
│           │  • objects          │          │                  │   │
│           │  • sla_contracts    │          │                  │   │
│           │  • questionnaire_*  │          │                  │   │
│           │  • blog_posts       │          │                  │   │
│           │  • cases            │          │                  │   │
│           │  • documents        │          │                  │   │
│           │  • photos           │          │                  │   │
│           │  • audit_log        │          │                  │   │
│           └─────────────────────┘          └──────────────────┘   │
│                      │                                            │
│           ┌──────────▼──────────┐                                │
│           │       Redis         │  (кэш, Celery broker)           │
│           └─────────────────────┘                                │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │                  Celery Workers (Python)                     │  │
│  │                                                              │  │
│  │  • Генерация отчётов (PDF, Excel)                           │  │
│  │  • Загрузка фото на Yandex Disk                             │  │
│  │  • Интеграция с 1С (по мере необходимости)                  │  │
│  │  • Фоновые расчёты, уведомления                             │  │
│  └─────────────────────────────────────────────────────────────┘  │
│                                                                   │
│  ┌──────────────────┐  ┌──────────────────┐                      │
│  │    Gitea         │  │   Certbot        │                      │
│  │  (Git-сервер)    │  │  (Let's Encrypt) │                      │
│  │                  │  │                  │                      │
│  │  • aegisone-php  │  │  • aegisone.ru   │                      │
│  │  • aegisone-py   │  │  • service.aeg.. │                      │
│  │  • project2      │  │  • other.ru      │                      │
│  │  • CI/CD Actions │  │  • автообновление│                      │
│  └──────────────────┘  └──────────────────┘                      │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │              Yandex Disk API (облачное хранилище)            │  │
│  │                                                              │  │
│  │  /AegisOne/                                                  │  │
│  │  ├── objects/{object_id}/                                    │  │
│  │  │   ├── photos/{photo_id}.jpg                              │  │
│  │  │   └── documents/{doc_id}/                                │  │
│  │  │       ├── {photo_id}.jpg                                 │  │
│  │  │       └── report_{doc_id}.pdf                            │  │
│  │  └── ...                                                     │  │
│  │                                                              │  │
│  │  В PostgreSQL хранятся: file_id, file_url, привязка к объекту│  │
│  └─────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

3. Технологический стек

3.1. Публичная часть (без изменений)

Компонент Технология Примечание
Язык PHP 7.4 Не обновлять, не трогать
БД MySQL Мигрировать на PostgreSQL позже (опционально)
Веб-сервер Nginx + PHP-FPM В Docker-контейнере
CSS/JS Inline Без изменений

3.2. Сервисная часть (Python)

Компонент Технология Примечание
Язык Python 3.11+
Фреймворк FastAPI REST API + серверный рендеринг
Шаблоны Jinja2 Серверный рендеринг, как сейчас PHP
Веб-сервер Uvicorn ASGI-сервер
ORM SQLAlchemy 2.0 + Alembic Миграции БД
БД PostgreSQL 15+ Единая БД для всех проектов
Аутентификация JWT (python-jose) Токены для API и сессий
Фоновые задачи Celery + Redis Отчёты, загрузка файлов, интеграции
Генерация отчётов WeasyPrint (PDF), openpyxl (Excel)
Yandex Disk yandex-disk SDK / REST API OAuth 2.0
Валидация Pydantic Схемы данных

3.3. Инфраструктура

Компонент Технология Примечание
Контейнеризация Docker + Docker Compose
Reverse proxy Nginx Маршрутизация по доменам
SSL Let's Encrypt + Certbot Автообновление
Git-сервер Gitea Лёгкий, встроенный CI/CD
CI/CD Gitea Actions Автоматический деплой
Мониторинг (опционально) Uptime Kuma

3.4. Мобильные приложения (будущее)

Компонент Технология Примечание
Фреймворк Flutter
API FastAPI REST endpoints Те же, что для веб-админки
Аутентификация JWT

4. Почему Jinja2, а не SPA

4.1. Сравнение

Критерий Jinja2 (SSR) SPA (React/Vue)
Серверная нагрузка Рендерит HTML на сервере Отдаёт статику + JSON API
Масштабирование Горизонтальное: Nginx → N FastAPI инстансов CDN для статики + Nginx → API
Сложность разработки Один стек, один деплой Два стека, два деплоя, CORS
Скорость разработки Быстро Медленнее
Команда 1-2 Python-разработчика Python + JS/TS разработчики
SEO Не нужен (админка закрыта) Не нужен
Мобильные приложения API тот же — Flutter подключается API тот же — Flutter подключается
Поддержка Проще Сложнее (два кодовых базы)

4.2. Масштабирование Jinja2 по России

При росте нагрузки:

  1. Вертикальное: Увеличить ресурсы VPS (CPU, RAM)
  2. Горизонтальное: Несколько инстансов FastAPI за Nginx (load balancing)
  3. Кэширование: Redis для кэширования тяжёлых запросов
  4. CDN: Для статики (CSS, JS, изображения) — Cloudflare или аналог

Jinja2 не является узким местом. Узким местом будет БД или внешние API (Yandex Disk, 1С).

4.3. Вердикт

Jinja2 — правильный выбор. Для B2B-админки SPA — это оверинжиниринг. Jinja2 даёт:

  • Быструю разработку
  • Простую поддержку
  • Легкое масштабирование
  • Единую кодовую базу
  • Готовность к мобильным приложениям (тот же API)

5. Этапы реализации

Этап 1: Docker-фундамент на VPS (1-2 недели)

Цель: Подготовить VPS для мультипроектной работы с Docker.

1.1. Установка Docker и Docker Compose

# На VPS (Ubuntu/Debian)
apt update && apt upgrade -y
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

1.2. Базовая структура директорий на VPS

/opt/
├── nginx-proxy/           # Nginx reverse proxy + Certbot
│   ├── docker-compose.yml
│   ├── nginx.conf
│   └── certs/             # Let's Encrypt сертификаты
├── gitea/                 # Git-сервер
│   ├── docker-compose.yml
│   └── data/              # Данные Gitea
├── aegisone-php/          # Публичная часть (PHP)
│   ├── docker-compose.yml
│   └── src/               # Исходный код (git clone)
├── aegisone-py/           # Сервисная часть (Python)
│   ├── docker-compose.yml
│   ├── app/               # FastAPI приложение
│   ├── migrations/        # Alembic миграции
│   └── requirements.txt
└── project2/              # Существующий проект
    └── docker-compose.yml

1.3. Nginx reverse proxy + Certbot

  • Один Nginx-контейнер на портах 80/443
  • Маршрутизация по server_name:
    • aegisone.ruaegisone-php:80
    • service.aegisone.ruaegisone-py:8000
    • git.aegisone.rugitea:3000
    • other-project.ruproject2:8000
  • Certbot в отдельном контейнере или встроенный (nginx-proxy + acme-companion)

1.4. Gitea (Git-сервер)

  • Docker-образ gitea/gitea:latest
  • Порт 3000 → git.aegisone.ru
  • PostgreSQL для данных Gitea
  • Встроенный CI/CD (Gitea Actions)
  • Репозитории:
    • aegisone-php (публичная часть, перенос с текущего хостинга)
    • aegisone-py (новая сервисная часть)
    • project2 (существующий проект)
    • infra (конфигурации Docker, Nginx, CI/CD)

1.5. Обёртка существующего проекта в Docker

  • Создать docker-compose.yml для project2
  • Протестировать работоспособность
  • Настроить домен other-project.ru

Критерий завершения этапа:

  • Docker + Docker Compose установлены
  • Nginx reverse proxy работает, маршрутизирует по доменам
  • Certbot выдаёт SSL-сертификаты (Let's Encrypt)
  • Gitea запущен на git.aegisone.ru
  • Существующий проект работает в Docker
  • Все домены доступны по HTTPS

Этап 2: Перенос AegisOne на VPS (1 неделя)

Цель: Перенести публичную часть с хостинга на VPS, отключить хостинг.

2.1. Docker-контейнер для PHP

# /opt/aegisone-php/docker-compose.yml
services:
  nginx:
    image: nginx:alpine
    ports:
      - "9080:80"  # Внутренний порт, внешний через reverse proxy
    volumes:
      - ./src:/var/www/html
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php

  php:
    image: php:7.4-fpm
    volumes:
      - ./src:/var/www/html
    environment:
      - DB_HOST=mysql
      - DB_NAME=aegisone
      - DB_USER=aegisone
      - DB_PASS=<password>

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: <root_password>
      MYSQL_DATABASE: aegisone
      MYSQL_USER: aegisone
      MYSQL_PASSWORD: <password>
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

2.2. Перенос файлов

  • Скачать все файлы с хостинга (FTP/SFTP)
  • Загрузить в /opt/aegisone-php/src/
  • Настроить config.php для нового окружения (DB_HOST=mysql)

2.3. Миграция БД

  • Экспорт MySQL с хостинга: mysqldump -u user -p db_name > backup.sql
  • Импорт в Docker MySQL: docker exec -i aegisone-php-mysql mysql -u aegisone -p aegisone < backup.sql
  • Проверить работоспособность

2.4. Настройка домена

  • DNS: aegisone.ru → IP VPS
  • Nginx reverse proxy: server_name aegisone.ruaegisone-php:9080
  • SSL: Certbot для aegisone.ru

2.5. Тестирование и отключение хостинга

  • Проверить все страницы: главная, услуги, блог, контакты, форма
  • Проверить карусель, FAQ, тему (светлая/тёмная)
  • Проверить Яндекс.Карту с переключением темы
  • После подтверждения — отключить хостинг

Критерий завершения этапа:

  • Публичная часть работает на VPS
  • Все страницы загружаются корректно
  • Форма обратной связи работает
  • Яндекс.Карта переключает тему
  • Домен aegisone.ru указывает на VPS
  • Хостинг отключён

Этап 3: Python-админка (FastAPI + Jinja2) (3-5 недель)

Цель: Полностью переписать сервисную часть на Python.

3.1. Структура проекта

aegisone-py/
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
├── alembic.ini
├── migrations/                    # Alembic миграции
├── app/
│   ├── __init__.py
│   ├── main.py                    # FastAPI приложение
│   ├── config.py                  # Настройки (env vars)
│   ├── database.py                # SQLAlchemy engine, session
│   ├── models/                    # SQLAlchemy модели
│   │   ├── __init__.py
│   │   ├── user.py
│   │   ├── customer.py
│   │   ├── object.py
│   │   ├── sla.py
│   │   ├── questionnaire.py
│   │   ├── blog.py
│   │   ├── case.py
│   │   ├── document.py
│   │   ├── photo.py
│   │   └── audit_log.py
│   ├── schemas/                   # Pydantic схемы
│   │   ├── __init__.py
│   │   ├── user.py
│   │   ├── customer.py
│   │   └── ...
│   ├── api/                       # API endpoints
│   │   ├── __init__.py
│   │   ├── auth.py                # Логин, JWT
│   │   ├── users.py
│   │   ├── customers.py
│   │   ├── objects.py
│   │   ├── sla.py
│   │   ├── questionnaire.py
│   │   ├── blog.py
│   │   ├── cases.py
│   │   ├── documents.py
│   │   └── reports.py
│   ├── templates/                 # Jinja2 шаблоны
│   │   ├── base.html              # Базовый шаблон
│   │   ├── login.html
│   │   ├── dashboard.html
│   │   ├── users/
│   │   ├── customers/
│   │   ├── objects/
│   │   ├── sla/
│   │   ├── questionnaire/
│   │   ├── blog/
│   │   ├── documents/
│   │   └── reports/
│   ├── static/                    # CSS, JS, изображения
│   │   ├── css/
│   │   │   ├── service.css        # Стили админки
│   │   │   └── ...
│   │   ├── js/
│   │   │   ├── main.js
│   │   │   └── ...
│   │   └── img/
│   ├── services/                  # Бизнес-логика
│   │   ├── __init__.py
│   │   ├── auth_service.py
│   │   ├── calc_service.py        # Расчёты (Risk Score, Object Index, SLA)
│   │   ├── report_service.py      # Генерация отчётов
│   │   ├── yandex_disk_service.py # Интеграция с Yandex Disk
│   │   └── ...
│   ├── tasks/                     # Celery задачи
│   │   ├── __init__.py
│   │   ├── reports.py
│   │   ├── yandex_disk.py
│   │   └── ...
│   └── utils/                     # Утилиты
│       ├── __init__.py
│       ├── password.py
│       └── ...
└── tests/                         # Тесты (опционально)

3.2. Миграция данных из MySQL в PostgreSQL

  • Создать Alembic миграции для всех таблиц
  • Написать скрипт миграции данных:
    • usersusers
    • customerscustomers
    • objectsobjects
    • sla_contractssla_contracts
    • questionnaire_sessions, questionnaire_answers, questionnaire_items → аналогично
    • blog_postsblog_posts
    • casescases
    • audit_logaudit_log
  • Протестировать миграцию на копии БД

3.3. Аутентификация

  • JWT-токены (python-jose)
  • Логин/пароль (bcrypt)
  • Роли: owner, engineer, technician
  • Сессии через cookies (для Jinja2) + JWT (для API)
  • CSRF-защита для форм

3.4. CRUD-модули (по порядку приоритета)

3.4.1. Пользователи (/service/users/)

  • Список, создание, редактирование, удаление
  • Роль owner нельзя удалить, нельзя изменить роль
  • Блокировка/разблокировка
  • Аудит действий

3.4.2. Клиенты (/service/customers/)

  • Список, создание, редактирование, удаление
  • ИНН, КПП, юридический адрес, контакты
  • Связь с объектами и SLA

3.4.3. Объекты (/service/objects/)

  • Список, создание, редактирование, удаление
  • Привязка к клиенту
  • Тип, адрес, площадь, сотрудники
  • Risk Score, Complexity Index, Object Index (авторасчёт)
  • SLA price (авторасчёт)

3.4.4. SLA контракты (/service/sla/)

  • Список, создание, редактирование, удаление
  • Привязка к клиенту и объекту
  • Тарифы: Базовый, Оптимальный, Максимальный
  • Время реакции, периодичность ТО
  • Статус: active, expired, cancelled, negotiation

3.4.5. Опросник (/service/questionnaire/)

  • Создание новой сессии
  • 5 шагов: Коммерческий, Технический, Эксплуатация, Риски, Расчёт SLA
  • Вопросы из БД (questionnaire_items)
  • Сохранение ответов
  • Авторасчёт: Risk Score, Complexity Index, Infrastructure Load, Service History, Object Index, SLA Price
  • Формирование паспорта объекта

3.4.6. Блог (/service/blog/)

  • Список, создание, редактирование, удаление
  • Категории: audit, sla, incident, supervision, documentation, risk, cases
  • HTML-редактор (toolbar)
  • Автогенерация slug из заголовка
  • Статус: draft, published

3.4.7. Примеры из практики (/service/cases/)

  • Список, создание, редактирование, удаление
  • Заголовок, текст, эффект
  • Сортировка, активность

3.4.8. Документы (/service/documents/)

  • Список документов (из service/docs/*.md)
  • Ручная сортировка
  • Переименование
  • Гранулярные права: view, edit, cancel (по ролям)
  • JSON-хранилище прав (docs_permissions.json)

3.5. Расчёты (перенос из PHP)

  • calc_risk_score() — Risk Score
  • calc_complexity() — Complexity Index
  • calc_infrastructure_load() — Infrastructure Load
  • calc_service_history() — Service History
  • calc_object_index() — Object Index
  • calc_sla_price() — SLA Price
  • risk_multiplier() — множитель риска
  • risk_label() — текстовая метка риска
  • object_class() — класс объекта
  • fmt_money() — форматирование денег

Все функции переписать на Python, покрыть тестами.

3.6. Дашборд (/service/dashboard/)

  • Метрики: количество объектов, активных SLA, открытых задач
  • Графики (Chart.js или аналог)
  • Быстрые действия
  • Последние активности (audit_log)

3.7. Фронтенд (Jinja2)

  • Базовый шаблон (base.html) с:
    • Боковой панелью (sidebar) с навигацией
    • Верхней панелью (header) с пользователем и переключателем темы
    • Основным контентом
  • Темы: system → dark → light (localStorage, как сейчас)
  • Кастомные скроллбары
  • Тултипы на кнопках
  • Модальные окна (создание/редактирование)
  • Таблицы с поиском и пагинацией
  • Адаптивность (мобильная версия)

Критерий завершения этапа:

  • Все CRUD-модули работают
  • Расчёты корректны (сравнить с PHP-версией)
  • Миграция данных завершена
  • Фронтенд полностью функционален
  • Темы переключаются
  • Мобильная версия работает
  • service.aegisone.ru доступен по HTTPS

Этап 4: Интеграции (2-3 недели)

Цель: Добавить генерацию отчётов, интеграцию с Yandex Disk, фоновые задачи.

4.1. Yandex Disk API

  • Регистрация приложения в Yandex OAuth
  • Получение OAuth-токена
  • SDK: yandex-disk или REST API через requests
  • Структура папок:
    /AegisOne/
    ├── objects/{object_id}/
    │   ├── photos/
    │   │   └── {photo_id}.jpg
    │   └── documents/{doc_id}/
    │       ├── {photo_id}.jpg
    │       └── report_{doc_id}.pdf
    └── ...
    
  • Эндпоинты:
    • POST /api/documents/{id}/upload-photo — загрузка фото
    • GET /api/documents/{id}/photos — список фото
    • DELETE /api/photos/{id} — удаление фото
  • В БД: таблица photos (id, document_id, object_id, yandex_file_id, yandex_file_url, uploaded_at, uploaded_by)

4.2. Генерация отчётов

  • PDF: WeasyPrint (HTML → PDF)
    • Шаблон паспорта объекта
    • Шаблон отчёта по аудиту
    • Шаблон SLA-контракта
  • Excel: openpyxl
    • Экспорт списка объектов
    • Экспорт SLA-контрактов
    • Экспорт отчётов по KPI
  • Фоновая генерация через Celery (для тяжёлых отчётов)

4.3. Celery (фоновые задачи)

  • Broker: Redis
  • Задачи:
    • Генерация PDF-отчётов
    • Загрузка фото на Yandex Disk
    • Отправка уведомлений (email, Telegram)
    • Интеграция с 1С (по мере необходимости)
  • Мониторинг: Flower (веб-интерфейс для Celery)

4.4. Интеграция с 1С (опционально, по мере необходимости)

  • REST API 1С или OData
  • Синхронизация: клиенты, объекты, договоры
  • Фоновая задача Celery

Критерий завершения этапа:

  • Yandex Disk API интегрирован
  • Фото загружаются и привязываются к документам
  • PDF-отчёты генерируются
  • Excel-экспорт работает
  • Celery запущен, задачи выполняются
  • (Опционально) Интеграция с 1С настроена

Этап 5: CI/CD и автоматизация деплоя (1 неделя)

Цель: Настроить автоматический деплой при push в Git.

5.1. Gitea Actions (CI/CD)

  • Встроенный CI/CD в Gitea (совместим с GitHub Actions)
  • Workflow для aegisone-py:
    name: Deploy AegisOne Python
    
    on:
      push:
        branches: [main]
    
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
    
          - name: Build and push Docker image
            run: |
              docker build -t registry.git.aegisone.ru/aegisone-py:latest .
              docker push registry.git.aegisone.ru/aegisone-py:latest
    
          - name: Deploy to VPS
            run: |
              ssh user@vps "cd /opt/aegisone-py && docker compose pull && docker compose up -d"
    

5.2. Структура репозиториев в Gitea

git.aegisone.ru/
├── aegisone/aegisone-php       # Публичная часть (PHP)
├── aegisone/aegisone-py        # Сервисная часть (Python)
├── aegisone/infra              # Docker, Nginx, CI/CD конфиги
└── aegisone/project2           # Существующий проект

5.3. Автоматический деплой

  • Push в main → Gitea Actions → сборка Docker-образа → деплой на VPS
  • Rollback: docker compose down && docker compose up -d с предыдущим образом
  • Миграции БД: Alembic upgrade head автоматически при деплое

5.4. Локальная разработка

  • docker-compose.dev.yml для локальной разработки
  • Hot-reload для Python (uvicorn --reload)
  • Локальная БД (PostgreSQL в Docker)
  • Синхронизация с VPS: git push → автоматический деплой

Критерий завершения этапа:

  • Gitea Actions настроены для всех проектов
  • Push в main → автоматический деплой
  • Rollback работает
  • Миграции БД применяются автоматически
  • Локальная разработка через Docker

6. Миграция данных: MySQL → PostgreSQL

6.1. Таблицы для миграции

MySQL таблица PostgreSQL таблица Примечание
users users Без изменений
login_attempts login_attempts Без изменений
audit_log audit_log Без изменений
objects objects + customer_id FK
object_assignments object_assignments Без изменений
tasks tasks Без изменений
task_comments task_comments Без изменений
customers customers Новая таблица
sla_contracts sla_contracts + customer_id FK, contract_number, description, response_time_hours
incidents incidents Без изменений
engineer_kpi engineer_kpi Без изменений
questionnaire_sessions questionnaire_sessions Без изменений
questionnaire_answers questionnaire_answers Без изменений
questionnaire_items questionnaire_items Новая таблица
object_passports object_passports Без изменений
blog_posts blog_posts ENUM категории изменён
cases cases Без изменений

6.2. Скрипт миграции

# scripts/migrate_mysql_to_postgres.py
import mysql.connector
import psycopg2
from psycopg2.extras import execute_batch

# Подключение к MySQL
mysql_conn = mysql.connector.connect(host='...', user='...', password='...', database='...')
mysql_cursor = mysql_conn.cursor(dictionary=True)

# Подключение к PostgreSQL
pg_conn = psycopg2.connect(host='...', user='...', password='...', database='...')
pg_cursor = pg_conn.cursor()

# Миграция каждой таблицы
tables = ['users', 'customers', 'objects', 'sla_contracts', ...]
for table in tables:
    mysql_cursor.execute(f"SELECT * FROM {table}")
    rows = mysql_cursor.fetchall()

    if rows:
        columns = rows[0].keys()
        placeholders = ', '.join(['%s'] * len(columns))
        cols = ', '.join(columns)
        execute_batch(
            pg_cursor,
            f"INSERT INTO {table} ({cols}) VALUES ({placeholders}) ON CONFLICT DO NOTHING",
            [tuple(row[col] for col in columns) for row in rows]
        )

pg_conn.commit()

6.3. Проверка миграции

  • Сравнить количество записей в MySQL и PostgreSQL
  • Проверить FK-связи
  • Протестировать CRUD-операции на PostgreSQL
  • Откат: сохранить бэкап MySQL до миграции

7. Безопасность

7.1. Аутентификация и авторизация

  • JWT-токены с expiration (1 час)
  • Refresh tokens (7 дней)
  • Роли: owner, engineer, technician
  • Гранулярные права для документов (view, edit, cancel)
  • CSRF-защита для форм

7.2. Защита данных

  • Пароли: bcrypt (cost factor 12)
  • HTTPS для всех доменов (Let's Encrypt)
  • Firewall: только порты 80, 443, 22 (SSH)
  • Docker: изоляция контейнеров, нет root в контейнерах
  • БД: нет внешнего доступа, только из Docker-сети

7.3. Бэкапы

  • PostgreSQL: pg_dump ежедневно (cron)
  • Yandex Disk: файлы уже в облаке
  • Gitea: бэкап репозиториев (tar)
  • Хранение бэкапов: отдельный диск или облако

7.4. Мониторинг

  • (Опционально) Uptime Kuma для мониторинга доступности
  • Логи: Docker logs + ротация
  • Алерты: email/Telegram при ошибках

8. Риски и митигация

Риск Вероятность Влияние Митигация
Ошибка миграции данных Средняя Высокое Тестирование на копии, бэкап MySQL
Простои при деплое Низкая Среднее Zero-downtime деплой (docker compose up -d)
Проблемы с SSL Низкая Среднее Certbot автообновление, мониторинг
Yandex Disk API лимиты Низкая Низкое Кэширование, retry logic
Нехватка ресурсов VPS Средняя Высокое Мониторинг CPU/RAM, масштабирование
Ошибки в расчётах Средняя Высокое Тесты, сравнение с PHP-версией

9. Оценки времени

Этап Описание Оценка
Этап 1 Docker-фундамент 1-2 недели
Этап 2 Перенос AegisOne на VPS 1 неделя
Этап 3 Python-админка 3-5 недель
Этап 4 Интеграции 2-3 недели
Этап 5 CI/CD 1 неделя
Итого 8-12 недель

10. Контрольные точки

Точка Описание Критерий успеха
КП1 Docker-фундамент готов Все сервисы запущены, домены работают по HTTPS
КП2 Публичная часть на VPS aegisone.ru работает, хостинг отключён
КП3 Python-админка MVP CRUD для пользователей, объектов, SLA работает
КП4 Python-админка полная Все модули, расчёты, миграция данных завершены
КП5 Интеграции Yandex Disk, отчёты, Celery работают
КП6 CI/CD Автоматический деплой при push

11. Открытые вопросы (уточнить перед реализацией)

Важно: Если при реализации возникнут вопросы — лучше уточнить, чем переделывать потом.

  1. Миграция данных: Переносим все данные из MySQL в PostgreSQL или начинаем с чистой БД? (Рекомендация: мигрировать)
  2. Домен для админки: service.aegisone.ru или app.aegisone.ru? (Рекомендация: service.aegisone.ru)
  3. Yandex Disk OAuth: Использовать токен приложения или OAuth с авторизацией пользователя? (Рекомендация: токен приложения для простоты)
  4. Генерация отчётов: Какие именно отчёты нужны в первую очередь? (Паспорт объекта, отчёт по аудиту, SLA-контракт?)
  5. Интеграция с 1С: Какая версия 1С? Какой метод интеграции (REST API, OData, файловый обмен)?
  6. Мониторинг: Нужен ли Uptime Kuma или другой мониторинг? (Рекомендация: да, для продакшена)
  7. Бэкапы: Где хранить бэкапы PostgreSQL? (Отдельный диск на VPS, облако, другой сервер?)
  8. Тестирование: Покрывать ли код тестами? (Рекомендация: да, хотя бы критические расчёты)
  9. Документация: Вести ли документацию по API? (Рекомендация: да, через FastAPI автоматическую /docs)
  10. Логирование: Какой уровень логирования? Куда писать логи? (Рекомендация: INFO в stdout, Docker logs)

12. Следующие шаги

  1. Утвердить план — ответить на открытые вопросы (раздел 11)
  2. Начать Этап 1 — Docker-фундамент на VPS
  3. Параллельно — создать репозитории в Gitea, настроить CI/CD skeleton
  4. После Этапа 1 — приступить к Этапу 2 (перенос PHP)
  5. После Этапа 2 — приступить к Этапу 3 (Python-админка)

Документ создан: 2026-05-17
Версия: 1.0
Автор: AI-ассистент + Владелец
Статус: Готов к реализации после утверждения