Роль AI-ассистента
Контекст проекта
CUBIX CRM - модульная SaaS-платформа на Nuxt 4, Vue 3 и TypeScript. В target-проекте используются Nuxt UI, Tailwind CSS v4, Prisma, PostgreSQL и nuxt-auth-utils.
Архитектура разворачивается как isolated instance: отдельный экземпляр приложения и отдельная база данных для каждого клиента. Поэтому tenant isolation не следует моделировать как произвольный tenant, переданный из браузера. Границы экземпляра задаются конфигурацией и серверным контекстом.
Приоритеты
- Безопасность и изоляция данных.
- Сохранение существующей бизнес-логики и публичных API.
- Типобезопасность и проверяемость изменений.
- Производительность без преждевременных абстракций.
- Совместимость с текущим UI-стеком и Nuxt Content.
Перед изменением кода
- Найди ближайший компонент, composable, API endpoint или тест, который непосредственно управляет поведением.
- Проверь существующие решения в
app/@core/components/CS-UI/,app/@core/composables/CS-UI/и@cs-platform/ui-kit. - Для переноса сверяйся с фактическим кодом target, схемой Prisma и соседними обработчиками, а не только с legacy-документацией.
- Сформулируй одну проверяемую гипотезу о причине изменения и один узкий способ её опровергнуть.
- Не исправляй несвязанные проблемы и не перезаписывай изменения пользователя.
Серверный код
Каждый endpoint обязан:
- требовать пользовательскую сессию через
requireUserSession(event), если маршрут защищён; - получать идентификатор пользователя через серверный helper
getCurrentUserId(event), а не из тела запроса; - валидировать тело и query-параметры через Zod;
- использовать Prisma и явные типы;
- проверять, что запрошенная сущность доступна текущему пользователю и экземпляру;
- не принимать от клиента идентификаторы, которые определяют границу доступа;
- не возвращать пароли, токены и другие секреты.
tenantId добавляется в запросы только там, где он реально является частью модели и текущего контракта приложения. В isolated instance не следует искусственно добавлять несуществующее поле или притворяться, что одна база обслуживает всех клиентов.
Frontend и UI
- Новые страницы собирай из Nuxt UI и существующих
CS*-обёрток. - Не распространяй Vuetify напрямую в новые страницы target.
- Не создавай дубликат компонента, если подходящий уже есть в библиотеке.
- Для повторно используемой логики используй composable; бизнес-логику не прячь внутри базового визуального примитива.
- Сохраняй loading, pending, validation и server-error состояния.
- Форма не должна закрываться до успешного ответа API; после сохранения обновляй зависимые списки.
- Для пользовательских уведомлений используй существующий notification store, а не
alertилиconfirm. - Новые компоненты, composables и обработчики фиксируй в реестре компонентов, если такой реестр уже подключён к соответствующему модулю.
Проверка результата
После изменения:
- Запусти самый узкий доступный проверочный тест, typecheck или lint для изменённого среза.
- Проверь ошибки Nuxt/Vue через IDE или
get_errors. - Для UI проверь реальный маршрут и основные состояния: загрузка, пустой результат, ошибка, создание, редактирование и повторное обновление.
- Для API проверь аутентификацию, валидацию, права доступа и отсутствие утечки данных.
- Не объявляй перенос завершённым только потому, что маршрут компилируется.
Документация как источник контекста
Документы в этом разделе предназначены и для разработчиков, и для AI-инструментов. Они должны описывать текущий target, а не историческую архитектуру legacy-проекта. Если инструкция расходится с кодом, сначала проверь код и схему, затем обнови инструкцию отдельным изменением с явным указанием, что именно устарело.