Проверяем Yandex Code Assistant на сервисе для передачи секретов

Всем привет! Я Станислав Денисов, ML-инженер в «Инфосистемы Джет».

Вайбкодинг уже успел несколько раз поссорить интернеты и, похоже, еще не раз это сделает. Тема никуда не уходит: ИИ-инструменты стали частью разработки, нравится нам это или нет.

Уходить в крайности здесь бесполезно. Писать критичный код без понимания предметной области опасно. Но и тратить недели на ручную сборку MVP или небольшой внутренней утилиты, когда рядом есть агент, тоже странно.

Сценарий, где разработчик формулирует задачу, а ИИ проектирует, пишет, проверяет и доводит код до деплоя, уже не выглядит фантастикой. Claude Code, например, дает 4% публичных коммитов на GitHub, а Google говорит о 50% AI-generated кода внутри компании. Очевидно, что дальше эти цифры будут расти, но сама по себе эта динамика не показательна.

Вопрос в другом: кто управляет инструментом, как проверяет результат и где проводит границу доверия.

В этой статье разберу кодового ассистента Яндекса. Посмотрим не только на то, умеет ли он генерировать файлы, но и на то, как ведет задачу, замечает ли инженерные нюансы и где человеку все равно приходится брать управление на себя.

Короткая версия: местами очень похоже на Cursor.

Зачем проверять именно Yandex Code Assistant

Внутри команды разработки мы регулярно используем Cursor, GitHub Copilot и Claude Code. Ими мы уже пользуемся, поэтому сравнивать было с чем.

Yandex SourceCraft Code Assistant за последний год заметно вырос: это уже не просто чат для автодополнения, а агент, встроенный в процесс разработки. Логичный следующий шаг — прогнать его через задачу, где обычного «сгенерируй CRUD» недостаточно.

Для теста я взял MVP сервиса одноразовой передачи секретов. По смыслу — что-то вроде Privnote или Yopass. Пользователь создает секрет, получает ссылку, получатель открывает ее один раз, после чего данные больше недоступны.

На бумаге задача выглядит простой: создать запись, выдать токен, отдать секрет, удалить после чтения. На практике все упирается в безопасность. Если агент ограничится типовым CRUD-приложением, мы получим сервис, которому нельзя доверять. Поэтому было интересно проверить, дойдет ли он сам до threat model, правильного хранения токенов, TTL и одноразового доступа.

Как выглядит агент: режимы, роли и ход работы

Стартовали с пустого проекта. Первым делом ассистент предложил выбрать режим, в котором он будет работать.

Проверяем Yandex Code Assistant на сервисе для передачи секретов

В Code Assistant есть несколько режимов:

• Architect: проектирование и дизайн до реализации.

• Code: написание и рефакторинг кода.

• Ask: ответы на вопросы и объяснения.

• Debug: поиск и исправление багов.

• Orchestrator: автоматический координатор задач.

Больше всего здесь интересен Orchestrator. Это тот же подход, к которому быстро привыкаешь в Claude Code и Cursor: не нужно вручную дергать режимы и объяснять агенту, что сейчас пора думать об архитектуре, а не сразу писать файлы. Он сам переключает фокус по ходу задачи.

На первый промпт про MVP сервиса, архитектуру и threat model ассистент ответил не одним абзацем, а сразу набором из 8 markdown-файлов:

Проверяем Yandex Code Assistant на сервисе для передачи секретов

В них были этапы разработки, архитектурные схемы и описание основных частей системы.

Дальше после каждого запроса агент обновлял внутренний To-Do и двигался по нему достаточно последовательно:

Проверяем Yandex Code Assistant на сервисе для передачи секретов

Еще одна полезная деталь — показ изменений. Встроенный diff не просто подсвечивает правки, а помогает понять, зачем агент трогает конкретный файл и что именно в нем меняет.

Проверяем Yandex Code Assistant на сервисе для передачи секретов

Одними стандартными режимами ассистент не ограничивается. Внутри есть скиллы, знакомые по Cursor: например, create-mcp-server для подключения инструментов через Model Context Protocol и create-mode для собственных ролей. В этом тесте они не понадобились, но сама возможность важна.

Что получилось хорошо и где пришлось включаться человеку

Для проверки я собрал цепочку из 10 промптов: от архитектуры и бэкенда до тестов и фронтенда. Идея была в том, чтобы вести агента итерациями, но не зажимать его настолько, чтобы он просто исполнял пошаговую инструкцию.

Ниже несколько ключевых запросов. Формулировки немного адаптированы для статьи, смысл сохранен:

Проектирование: «Помоги спроектировать MVP сервиса для безопасной одноразовой передачи паролей и секретов. Пользователь создает секрет, получает ссылку, секрет можно открыть только один раз или до истечения TTL. Опиши архитектуру, threat model и минимальные меры безопасности».

Бэкенд: «Сгенерируй backend на FastAPI для сервиса one-time secret share. Нужны эндпоинты: создать секрет, получить секрет по токену, пометить как прочитанный и удалить просроченные записи. Используй SQLAlchemy и SQLite/PostgreSQL».

Безопасность: «Покажи безопасный подход к хранению секретов: чем шифровать секрет, как генерировать токен, нужно ли хранить хэш токена вместо самого токена, как реализовать TTL и одноразовый доступ. Перепиши текущий код в безопасном виде и объясни изменения».

QA: «Напиши pytest-тесты для этого сервиса: проверь одноразовое чтение, истекший TTL, неверный токен, попытку повторного доступа и физическое удаление после просмотра».

Нормальная основа без ручной рутины

С типовым кодом ассистент справился уверенно. На такой части задачи он действительно экономит часы: модели, схемы, эндпоинты, базовые проверки, инфраструктурные файлы.

Например, он сразу добавил Pydantic-валидацию и ограничения на размер секрета. Это важно: без лимитов сервис можно случайно или намеренно нагрузить слишком большим payload:

# schemas.py class SecretCreate(BaseModel): """Schema for creating a new secret.""" secret: str = Field(..., description="The secret text to store", min\_length=1, max\_length=10000) ttl\_seconds: int = Field( default=3600, description="Time to live in seconds", ge=60, # Minimum 1 minute le=30 \* 24 \* 3600 # Maximum 30 days ) max\_views: int = Field( default=1, description="Maximum number of times the secret can be viewed", ge=1, le=10 )

Также агент не забыл про уборку просроченных записей. Для MVP он не стал сразу тащить отдельный cron или воркер, а использовал BackgroundTasks из FastAPI:

# main.py @app.post("/secrets", response\_model=SecretResponse, status\_code=status.HTTP\_201\_CREATED) def create\_secret( secret\_data: SecretCreate, background\_tasks: BackgroundTasks, db: Session = Depends(get\_db) ): # ... (генерация ID, шифрование, сохранение в БД) ... # Schedule cleanup task for expired secrets background\_tasks.add\_task(cleanup\_expired\_secrets, db) return SecretResponse( id=secret\_id, access\_url=access\_url, expires\_at=expires\_at, message="Secret created successfully." )

Про перебор токенов ассистент тоже подумал: добавил In-Memory Rate Limiter и подключил его как middleware:

# main.py from .rate\_limiter import RateLimitMiddleware # Add rate limiting middleware app.add\_middleware( RateLimitMiddleware, requests\_per\_minute=int(os.getenv("RATE\_LIMIT\_PER\_MINUTE", "60")) )

На первый взгляд, после такого уже хочется завернуть проект в Docker (его агент тоже подготовил) и отправить в прод. Но именно здесь начинается самое интересное.

Где без человека пока никак

Серверное шифрование

Ассистент выбрал шифрование на сервере через cryptography.fernet. Ключ при этом выводится из мастер-ключа сервера и ID секрета.

Формально данные в базе зашифрованы. Практически сервер все равно знает слишком много: администратор с доступом к базе и переменным окружения сможет восстановить секреты.

Для zero-knowledge-сценария нужен другой подход: шифровать на клиенте через Web Crypto API, а ключ передавать во фрагменте URL после #KEY. Такой фрагмент браузер не отправляет на сервер, поэтому бэкенд хранит только ciphertext и не получает материал для расшифровки.

Race Condition (TOCTOU)

В эндпоинте чтения секрета агент сделал типичный сценарий: сначала SELECT, затем проверка if db\_secret.accessed: raise, потом выдача секрета и UPDATE accessed = True.

Это классический TOCTOU — Time-of-Check to Time-of-Use. Два параллельных запроса могут одновременно увидеть accessed = False и оба получить секрет. В этот момент одноразовый доступ перестает быть одноразовым.

Исправлять такое лучше на уровне БД: через транзакционные блокировки (SELECT ... FOR UPDATE) или атомарный UPDATE ... RETURNING, где проверка и изменение состояния происходят одной операцией.

Удаление данных

После чтения ассистент помечает запись как удаленную: secret.deleted = True. Для обычной бизнес-сущности этого иногда достаточно. Для сервиса секретов — нет

Зашифрованный текст при soft delete продолжает лежать в базе. Для такого класса данных нужен физический DELETE, а в более строгом варианте — крипто-шреддинг: перед удалением перезаписать колонку мусором, чтобы снизить шанс восстановления по следам в WAL и резервных копиях.

Промежуточный итог

ИИ хорошо берет на себя рутину: каркас приложения, типовые эндпоинты, схемы, тестовую инфраструктуру, Docker и связку файлов вокруг проекта. Это уже не игрушечная автоподстановка, а рабочий способ быстро получить первую версию.

Но контроль остается на стороне разработчика. Особенно там, где важны бизнес-правила, безопасность и гарантии поведения под нагрузкой. Можно не писать каждую строчку руками, но нужно понимать, какие свойства система обязана сохранять.

Что запомнилось

Сильные стороны:

• Orchestrator работает ожидаемо и удобно. Агент сам понимает, когда нужно проектировать, а когда переходить к коду.

• Контекст держится неплохо. Если попросить добавить ограничение на число просмотров, ассистент меняет схему и связанную логику, а не переписывает все вокруг.

• Diff с пояснениями помогает ревьюить результат. Для кода, который сгенерировал ИИ, это особенно важно.

• Инфраструктурную часть агент собрал без особых проблем: docker-compose.yml, Dockerfile для фронтенда и бэкенда, конфиг Nginx.

Что насторожило:

• Языки местами смешались: промпты и документация были на русском, а интерфейс фронтенда получился на английском.

Проверяем Yandex Code Assistant на сервисе для передачи секретов

Выводы

Паниковать рано: разработчиков ИИ пока не заменяет. Код, который получился в тесте, нельзя было бы отдавать в прод без внимательного технического ревью. Впрочем, это справедливо почти для любого ИИ-ассистента на рынке.

При этом результат мне понравился. Задачу, на которую раньше легко ушел бы день, агент довел до рабочей версии примерно за час. Роль разработчика в таком процессе смещается: меньше ручного набора типового кода, больше архитектуры, ревью, проверки инвариантов и безопасности. Если держать это в голове, инструмент получается действительно полезным.