# 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
```bash
# На 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.ru` → `aegisone-php:80`
  - `service.aegisone.ru` → `aegisone-py:8000`
  - `git.aegisone.ru` → `gitea:3000`
  - `other-project.ru` → `project2: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
```yaml
# /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.ru` → `aegisone-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 миграции для всех таблиц
- Написать скрипт миграции данных:
  - `users` → `users`
  - `customers` → `customers`
  - `objects` → `objects`
  - `sla_contracts` → `sla_contracts`
  - `questionnaire_sessions`, `questionnaire_answers`, `questionnaire_items` → аналогично
  - `blog_posts` → `blog_posts`
  - `cases` → `cases`
  - `audit_log` → `audit_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`:
  ```yaml
  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. Скрипт миграции
```python
# 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-ассистент + Владелец  
**Статус:** Готов к реализации после утверждения
