# Django

### DJA-001: Файлы Poetry
`pyproject.toml` и `poetry.lock` НЕ ДОЛЖНЫ создаваться или редактироваться вручную; они ДОЛЖНЫ появляться и обновляться только через команды Poetry.

### DJA-002: Добавление зависимостей
Зависимости ДОЛЖНЫ добавляться только командой: `poetry add <package>`. Ручное редактирование `pyproject.toml` и `poetry.lock` запрещено.

### DJA-003: Создание миграций
Миграции ДОЛЖНЫ создаваться командой: `poetry run python manage.py makemigrations`. Локально применять при необходимости командой: `poetry run python manage.py migrate`. Ручное создание файлов миграций запрещено. Применение миграций выполняется на стенде Dokploy при старте контейнера.

### DJA-004: Сборка и запуск
Сборка ДОЛЖНА выполняться через Nixpacks на Dokploy. Старт-команда в `nixpacks.toml` ДОЛЖНА включать автоматическое применение миграций (`python manage.py migrate && gunicorn...`).

### DJA-005: Загрузка секретов через Infisical
Django проект ДОЛЖЕН загружать секреты через `InfisicalSDKClient` на старте приложения или через `infisical run` перед запуском; INFISICAL_API_URL, INFISICAL_TOKEN, INFISICAL_PROJECT_ID, INFISICAL_ENV ДОЛЖНЫ быть заданы, при их отсутствии приложение ДОЛЖНО падать.

### DJA-006: Sentry
Sentry ДОЛЖЕН быть подключён через `sentry_sdk.init`; DSN, release и environment ДОЛЖНЫ браться из переменных окружения; включение ОБЯЗАТЕЛЬНО для прод и стейдж.

### DJA-007: Модели в Django Admin
Все модели ДОЛЖНЫ быть зарегистрированы в Django Admin через `admin.site.register()` или декоратор `@admin.register()`.


---

# Nuxt

### NXT-001: Добавление модулей
Nuxt модули ДОЛЖНЫ добавляться командой `npx nuxi module add <module>`. Пример: `npx nuxi module add @nuxtjs/eslint-module`.

### NXT-002: Запрет редактирования package.json
ИИ НЕ ДОЛЖЕН редактировать `package.json`, `pnpm-lock.yaml`.

### NXT-003: Использование сгенерированной схемы
Сгенерированная схема (`composables/graphql/generated.ts`) ДОЛЖНА использоваться для всех GraphQL операций.

### NXT-004: Storybook для компонентов
Все компоненты ДОЛЖНЫ быть зарегистрированы в Storybook.

### NXT-005: Использование @nuxt/eslint
Все Nuxt проекты ДОЛЖНЫ использовать модуль `@nuxt/eslint` для проверки кода.

### NXT-006: GraphQL документы
Все GraphQL операции (queries, mutations) ДОЛЖНЫ храниться в `.graphql` файлах и подключаться как документы, а не через импорт схемы в код.

### NXT-007: Codegen из удалённой схемы
GraphQL codegen ДОЛЖЕН выполняться командой `pnpm codegen`, брать СХЕМУ ТОЛЬКО УДАЛЁННУЮ для hot-gen (локальную схему НЕ берём) и использовать локальные `.graphql` документы (`graphql/operations/**/*.graphql`, компоненты/компосеблы); сгенерированные файлы ДОЛЖНЫ коммититься для повторного использования другими фронтами.

### NXT-008: Один документ — один файл
Каждый GraphQL документ (query/mutation/subscription/fragment) ДОЛЖЕН храниться в отдельном `.graphql` файле; НЕ СКЛАДЫВАТЬ несколько документов в один файл.

### NXT-009: Использование документов в коде
В коде ДОЛЖНЫ использоваться документы из `.graphql` файлов и их сгенерированные TypedDocumentNode/хелперы (а не строковые запросы); импортируем только готовые операции из `graphql/operations`.

### NXT-010: Apollo + codegen
Фронт ДОЛЖЕН использовать `@nuxtjs/apollo` и `@vue/apollo-composable`; codegen ДОЛЖЕН использовать `@graphql-codegen/typescript-vue-apollo` для генерации typed-document-node и опираться на `.graphql` документы.

### NXT-011: daisyUI
Все Nuxt проекты ДОЛЖНЫ использовать daisyUI как базовую библиотеку; кастомные компоненты ДОЛЖНЫ собираться на примитивах daisyUI.

### NXT-012: Декомпозиция компонентов
Компоненты ДОЛЖНЫ быть максимально декомпозированы (atomic/feature/layout); страницы НЕ ДОЛЖНЫ содержать монолитную логику; переиспользуемые части ДОЛЖНЫ выноситься в общие UI-пакеты.

### NXT-013: Sentry
Фронт ДОЛЖЕН быть подключён к Sentry через `@sentry/nuxt`; DSN, release и environment ДОЛЖНЫ браться из переменных окружения; включение ОБЯЗАТЕЛЬНО для прод и стейдж.

### NXT-014: Секреты через Infisical
Сборка и запуск Nuxt ДОЛЖНЫ выполняться под `infisical run --env=$INFISICAL_ENV --projectId=$INFISICAL_PROJECT_ID -- ...`; переменные INFISICAL_ENV, INFISICAL_PROJECT_ID, INFISICAL_TOKEN ДОЛЖНЫ быть заданы, при их отсутствии сборка/старт ДОЛЖНЫ падать.


---

# Odoo

### ODO-001: Установка модулей

Установка Odoo модулей ДОЛЖНА выполняться через playbook `odoo_install_modules.yml`

### ODO-002: Обновление модулей

Обновление Odoo модулей ДОЛЖНО выполняться через playbook `odoo_update_modules.yml`

### ODO-003: Структура XML-файлов

Каждый XML-файл ДОЛЖЕН описывать только один артефакт (view/action/menu/record) и именоваться из трех частей через подчёркивание `<сущность>_<тип>_<вариант>` (например, `company_view_form.xml`, `order_stage_view_kanban.xml`, `menu_orders_trips.xml`). Меню собираем в одном файле модуля `menu.xml`, без дробления на несколько файлов. Нельзя складывать несколько несвязанных записей в один XML, чтобы содержимое файла однозначно соответствовало артефакту.

### ODO-004: Статусы, чаттер и трекинг

Новая модель ДОЛЖНА наследоваться от `mail.thread`/`mail.activity.mixin`, иметь поле `state` со статусбаром и `<chatter/>` в форме, а ключевые поля — `tracking=True`.

### ODO-005: Базовые роли модуля

В каждом модуле ДОЛЖНО быть `security/groups.xml` (или `security/security.xml`) с парами `group_<module>_user` и `group_<module>_manager`, где manager наследуется от user через `implied_ids`, и эти же группы ДОЛЖНЫ использоваться в `security/ir.model.access.csv` вместо `base.group_user`.

### ODO-006: Настраиваемые листинги

Листинги ДОЛЖНЫ быть в `<list>` с первым столбцом без `optional`, прочими с `optional="show"` (техполями с `optional="hide"`) и `state` как `widget="badge"`, чтобы работал выбор колонок.

### ODO-007: Редактируемые статусы

Поле `state` ДОЛЖНО быть selection с полным набором значений в модели, иметь `statusbar_visible` и `options="{'clickable': '1'}"` в форме, и `group_expand` по `state`, чтобы статусы были редактируемы и доступны во всех видах.

### ODO-008: Kanban по статусам

Kanban view ДОЛЖЕН использовать стандартный шаблон `kanban-box`, быть `default_group_by="state"` и опираться на `group_expand` по `state`, чтобы все статусы показывались сразу.


---

# Внешние API

### API-001: Коллекции в Bruno

Коллекции внешних API ДОЛЖНЫ быть созданы и протестированы в Bruno перед интеграцией

### API-002: Артефакты ответов

Примеры ответов API ДОЛЖНЫ быть сохранены для генерации типов данных

---

# Дизайн

### DES-001: Документация при интеграции

При интеграции нового модуля, библиотеки или API разработчик ДОЛЖЕН прочитать официальную документацию продукта и изучить примеры использования перед началом работы.

### DES-002: Документация при ошибках

При возникновении ошибки разработчик ДОЛЖЕН прочитать раздел Troubleshooting в официальной документации и проверить примеры в официальном репозитории перед поиском решения в issues.

### DES-003: Актуальные версии

Все продукты и зависимости ДОЛЖНЫ использовать стабильные версии, выпущенные не позднее последних 12 месяцев; это предотвращает проблемы совместимости.


---

# Инфраструктура

### INF-001: Демонстрационный стенд Dokploy
Проект НЕ разворачивается локально; полностью работоспособный стенд (включая домены) ДОЛЖЕН работать на Dokploy, сборка и публикация выполняются только через Dokploy Nixpacks.

### INF-002: Git push после каждой задачи
После завершения задачи ДОЛЖЕН выполняться `git push`; Dokploy ДОЛЖЕН забирать изменения по webhook и запускать сборку.

### INF-003: Nixpacks + webhook
Приложения ДОЛЖНЫ собираться через Nixpacks на Dokploy и слушать webhook репозитория.

### INF-004: MCP dsrpt-dev-tools
MCP сервер ДОЛЖЕН быть настроен в `.mcp.json`:
```json
{
  "mcpServers": {
    "dsrpt-dev-tools": {
      "command": "node",
      "args": ["путь/к/dsrpt-dev-tools/dist/index.js"],
      "env": {
        "GLITCHTIP_URL": "",
        "GLITCHTIP_TOKEN": "",
        "GLITCHTIP_PROJECT_SLUG": "",
        "DOKPLOY_URL": "",
        "DOKPLOY_TOKEN": ""
      }
    }
  }
}
```

**Инструменты:**

`glitchtip_issues` — получение ошибок из GlitchTip. Возвращает список issues с полями: id, title, count, level, firstSeen, lastSeen, type, file. Параметры: `project` (опционально, по умолчанию из GLITCHTIP_PROJECT_SLUG), `limit` (по умолчанию 10).

`dokploy_deployments` — получение истории деплойментов из Dokploy. Возвращает список деплойментов с полями: id, status (running/done/error/queued), title, createdAt. Параметры: `applicationId` (обязательно), `limit` (по умолчанию 5).

### INF-005: Секреты в Infisical
Все секреты и переменные окружения ДОЛЖНЫ храниться в Infisical; сборка и запуск сервисов ДОЛЖНЫ получать значения только через Infisical SDK. Каждый проект ДОЛЖЕН подхватывать секреты из своей папки и из папки shared. Отсутствие обязательных секретов ДОЛЖНО приводить к ошибке сборки/старта.

### INF-006: Ansible inventory в репозитории
Ansible ДОЛЖЕН подключаться по SSH без дополнительных параметров (Tailscale endpoint + пользователь `root`), поэтому весь inventory (сервера, группы) ДОЛЖЕН храниться в репозитории целиком; секретные данные в inventory НЕ ДОЛЖНЫ размещаться. Подключение: `ssh root@имя-сервера` без пароля (Tailscale MagicDNS).

### INF-007: Коммиты без соавторов
Агенты НЕ ДОЛЖНЫ добавлять соавторов (например, строки Co-authored-by или аналогичные) при коммитах; коммит фиксирует работу одного автора и публикуется без указания совместного авторства.

### INF-008: Infisical CLI
Для работы с секретами агент ДОЛЖЕН запустить `infisical login --domain=https://infisical.dsrptlab.com`. У пользователя откроется браузер для авторизации. После авторизации CLI получит токен автоматически. Команды: `infisical secrets --projectId=... --env=prod` (просмотр), `infisical secrets set KEY=value --projectId=... --env=prod` (изменение).

### INF-009: Docker Compose — expose вместо ports
В docker-compose.yml НЕ ДОЛЖНЫ использоваться `ports` для проброса портов наружу; вместо этого ДОЛЖЕН использоваться `expose` для объявления портов внутри Docker-сети. Причина: инфраструктура работает под Dokploy/Traefik, внешний доступ осуществляется через reverse proxy, явный проброс портов усложняет конфигурацию и создаёт риски безопасности.

### INF-010: Temporal — именование и организация
Workflow ДОЛЖЕН именоваться по паттерну `{Resource}Workflow` (класс) и `{verb}_{resource}` (декоратор). Activity ДОЛЖЕН именоваться по паттерну `{verb}_{resource}_in_{service}` — например `create_application_in_odoo`. Каждая activity ДОЛЖНА быть в отдельном файле. Типы ввода/вывода ДОЛЖНЫ именоваться `{Verb}{Resource}In{Service}Input/Result`. Workflows и activities ДОЛЖНЫ быть в разных пакетах.

### INF-011: Ожидание завершения сборки Dokploy
Для работы с обновлённым кодом на сервере разработчик ДОЛЖЕН дождаться завершения сборки в Dokploy.

### INF-012: Запрет ручного запуска контейнеров
Разработчик НЕ ДОЛЖЕН самостоятельно запускать контейнеры — это нарушит работу Dokploy.

### INF-013: SSH для отладки и логов
Для отладки и сбора логов с контейнеров ДОЛЖЕН использоваться SSH через Tailscale: `ssh root@имя-сервера`.

