Skip to main content

Секреты и токены

Велес хранит секреты отдельно от обычного config.json. Конфигурация может содержать только ссылку на секрет (SecretRef) или пустое значение, а реальные токены загружаются во время работы и не отправляются в интерфейс Велеса или модель.

Что обязательно для запуска

Шлюз Велеса запускается только при наличии двух серверных секретов:
  • gateway.token или переопределяющего его VELES_GATEWAY_TOKEN — для доступа Nerve к шлюзу;
  • VELES_SECRETS_MASTER_KEY — для чтения и записи зашифрованного хранилища.
Создайте главный ключ шифрования:
VELES_SECRETS_MASTER_KEY должен быть корректным ключом в окружении процесса сервера Велеса. Интерфейс Велеса не должен получать этот ключ. Ключи поставщиков моделей, векторной памяти, распознавания аудио, глубокого исследования, веб-поиска, каналов и навыков для запуска шлюза не нужны. Если они ещё не заполнены, Nerve всё равно откроется и покажет их в разделе «Секреты»; зависимая возможность сообщит об ошибке только при попытке её использовать. Вместо задания переменной в текущей оболочке её можно записать в .env каталога, из которого выполняется uv run veles gateway. Уже заданная переменная окружения имеет приоритет над значением из файла. Не добавляйте .env с настоящими ключами в репозиторий.

Где лежат локальные секреты

Зашифрованное локальное хранилище пишет файлы в каталог secrets внутри рабочей области, указанной в agents.defaults.workspace активного config.json:
  • <workspace>/secrets/values.enc.json — обычные ключи API и секреты окружения навыков;
  • <workspace>/secrets/auth-profiles.enc.json — OAuth-профили, например OpenAI Codex.
Файлы содержат зашифрованную оболочку AES-GCM (version, alg, nonce, ciphertext, timestamps). Значения секретов не лежат там открытым текстом.

SecretRef

SecretRef говорит Велесу, откуда брать секрет:
  • local — зашифрованное локальное хранилище Велеса;
  • env — переменная окружения процесса сервера;
  • file — файл на машине сервера;
  • exec — команда, которая возвращает секрет.
Для local используется объект, а не строковая подстановка:
Короткая строка вида "${NAME}" означает только ссылку на переменную окружения и не подходит для локальных секретов Велеса. Несколько потребителей могут ссылаться на один локальный id: зашифрованное значение при этом хранится в одном экземпляре. Например, источник задач Bitrix24 использует те же два значения, что и навык alor-bitrix24:
Шаблон scripts/config.template.json использует тот же приём для OpenRouter. Поля providers.openrouter.apiKey, tools.audio.apiKey и tools.vectorMemory.embeddingApiKey ссылаются на единый идентификатор providers.openrouter.api_key; глубокое исследование тоже читает ключ этого поставщика. Поэтому в Nerve достаточно один раз заполнить цель OpenRouter. Токен Telegram, ключ Tavily и ключ разбора документов Mistral имеют отдельные цели и также записываются через раздел «Секреты». Обычными владельцами этих значений в панели секретов остаются канонические цели навыка. Когда навык alor-bitrix24 обнаружен, технические цели tasks.bitrix.webhook_user_id и tasks.bitrix.webhook_code скрыты из каталога, предупреждений и признаков перезапуска, но продолжают разрешать и маскировать поля конфигурации задач. Если навыка ещё нет, они показываются как запасной способ первоначальной настройки и записывают значение по тому же каноническому идентификатору. Поэтому повторно сохранять идентификатор пользователя и код вебхука для доски не нужно. Очистка такой ссылки потребителя не удаляет общее значение, которым владеет цель навыка. Интерфейс Велеса в первую очередь управляет local: пользователь вводит значение один раз, Велес шифрует его и дальше возвращает только замаскированный статус. Пароль входа в Nerve тоже хранится на стороне Велеса, но не показывается как обычная цель в каталоге секретов. Велес записывает только scrypt-хэш пароля во внутренний ключ зашифрованного хранилища. Nerve при входе отправляет пароль в auth.login, получает gateway.token только в серверный процесс и не сохраняет его в браузере. Если это зашифрованное хранилище нельзя прочитать, Велес не считает пароль отсутствующим и не включает вход через gateway.token. Сначала восстановите ключ шифрования или доступ к хранилищу секретов.

Как интерфейс показывает секреты

В интерфейсе Велеса откройте «Рабочая область» → «Секреты». Интерфейс получает список целей так:
  1. GET /api/secrets;
  2. внутренний вызов secrets.catalog;
  3. Велес строит каталог из провайдеров, инструментов, каналов, MCP-серверов и метаданных навыков.
Если строка показывает MISSING или EMPTY, это не значит, что секрет находится в интерфейсе. Это только замаскированная цель: Велес знает, что такой секрет может понадобиться, но значение ещё не настроено. Общие предупреждения каталога в Nerve не показываются. Ошибка конкретного секрета отображается рядом с его целью, поэтому сообщение остаётся связано с нужным полем. Значения секретов при этом не показываются. Поле поиска в панели Секреты фильтрует уже загруженный список на стороне Nerve. Оно не делает дополнительных запросов к gateway и ищет по названию секрета, target id, пути конфигурации и источнику.

Секреты навыков

Навык может объявить нужный секрет окружения в SKILL.md:
Тогда Велес создаст цель вроде skills.github.env.GH_TOKEN. Если значение сохранить в панели секретов, Велес будет подставлять GH_TOKEN только на время выполнения ответа. Значение не попадает в инструкцию модели и не записывается в config.json. requires.env делает переменную обязательной: без неё навык считается недоступным. Для опциональных API-ключей используйте отдельный список секретов:
Такой ключ появится в панели секретов и будет подставлен при наличии, но отсутствие значения не выключит навык. При установке навыка из маркетплейса те же цели показываются в диалоге настройки. Для ввода используется тот же защищённый элемент управления, что и на панели секретов. В диалоге навыка предупреждающее выделение включается только для пустого обязательного секрета; необязательный секрет сохраняет обычное оформление. На общей панели секретов поля не получают такое выделение: наличие значения передаётся отдельным статусом цели. Значения передаются Велесу для записи в локальное зашифрованное хранилище и никогда не сохраняются в открытом config.json. Необязательный секрет можно оставить пустым или удалить позднее; обязательный разрешено заменить, но не удалить через редактор навыка. Например, устанавливаемый из каталога навык fda-database объявляет опциональный OPENFDA_API_KEY как skills.fda-database.env.OPENFDA_API_KEY: ключ повышает дневной лимит openFDA, но без него навык всё равно работает. Навык entrez-search аналогично объявляет необязательные NCBI_API_KEY и NCBI_EMAIL. Эти значения подставляются из защищённого окружения и не передаются в аргументах команды. Навык google-workspace хранит более крупные значения: файл клиента Google, токен и временное состояние авторизации. Они тоже записываются в зашифрованное локальное хранилище, но как JSON-значения с ключами skills.google-workspace.google_client_secret_json, skills.google-workspace.google_token_json и skills.google-workspace.google_oauth_pending_json. Навык alor-teamly читает логин и параметры выбора домена/аккаунта из обычной настройки skills.entries.alor-teamly.config. Только пароль LDAP хранится как секрет skills.alor-teamly.env.TEAMLY_PASSWORD. Полученные от Teamly куки сохраняются отдельно под внутренним ключом skills.alor-teamly.session_json. Пароль не передаётся модели, не помещается в командную строку и не записывается в открытый файл.

OpenAI Codex OAuth

OpenAI Codex использует OAuth, а не ключ API. Его токены хранятся в зашифрованном хранилище профилей:
Подключить или отключить Codex можно через интерфейс Велеса: «Рабочая область» → «Секреты». Браузер получает только ссылку и статус OAuth; токены доступа и обновления остаются внутри Велеса. Если после нажатия «Подключить» окно входа не открылось, панель покажет причину. При блокировке всплывающего окна разрешите такие окна для сайта или нажмите ссылку «Продолжить вход в OpenAI». Каждое сообщение об ошибке входа содержит:
  • этап, на котором возникла ошибка;
  • исходные технические сведения от Велеса;
  • рекомендуемое следующее действие.
Если вставленный адрес возврата содержит ошибку OpenAI, Велес передаёт в Nerve её тип и описание. При отказе конечной точки токенов также отображаются код ответа и безопасное описание OpenAI. Панель отдельно распознаёт отсутствие главного ключа, недоступность или превышение времени ожидания шлюза, неверный токен шлюза, устаревшую попытку входа, отсутствие кода авторизации, ошибку обмена кода и истечение времени попытки. Коды авторизации, значения состояния попытки и токены в сообщение не попадают.

Что важно помнить

  • config.json не должен хранить новые секреты открытым текстом.
  • Интерфейс Велеса никогда не показывает сохранённое значение секрета.
  • Без корректного VELES_SECRETS_MASTER_KEY шлюз Велеса не запускается. Ссылки на остальные отсутствующие секреты не блокируют запуск: их можно заполнить через Nerve после подключения.
  • Для постоянного развёртывания нужно сохранять каталог .veles и передавать главный ключ через менеджер секретов окружения.