Zero-deps SDK BOTIX: подключение, ключи, open-source
SDK с десятком зависимостей — это десяток будущих CVE в вашем `requirements.txt`. TL;DR: три SDK BOTIX (PHP, Python, Node) собраны без транзитивных пакетов, ключ хранится только через ENV и secret manager, а исходники лежат открытыми на GitHub. Ниже — установка построчно, семь антипаттернов работы с ключами и чек-лист код-ревью.
Коротко
- Zero-deps. Все три SDK не тянут ни одной транзитивной зависимости: HTTP из stdlib, JSON из stdlib, UUID и HMAC из stdlib.
composer audit/npm audit/safety checkзелёные по дизайну, а не по везению. - Ключ = бессрочный пароль. Семь антипаттернов (ключ в репо, в
.env, в логах, в URL, без ротации, без scope, один на всех) закрываются одной схемой: secret manager → ENV → SDK, маскирование в логах, отдельный ключ с минимальным scope на каждый сервис. - Open-source — не подарок, а инструмент. Открытый код SDK снимает блокировку security-команды без NDA и SOC 2, разблокирует bug fix через PR/форк и работает как сигнал зрелости API. При этом архитектуру API он не раскрывает: бизнес-логика остаётся на
api.botix.pro.
Почему 14 зависимостей в SDK — технический долг интегратора
SDK для публичного API — это не приложение, а тонкая обёртка над HTTP: сформировать запрос, подписать, распарсить ответ. Каждая зависимость этой обёртки становится головной болью того, кто её установит.
Команда подключает сторонний API. Видит на странице документации pip install vendor-sdk / composer require vendor/sdk / npm install @vendor/sdk, ставит — и через минуту в requirements.txt или composer.lock появляется не одна новая строка, а четырнадцать. SDK притащил HTTP-клиент, JSON-валидатор, UUID-библиотеку, retry-механизм, ещё один логгер и пару утилитарных пакетов от одного мейнтейнера «в свободное время». Каждая из них создаёт ровно три класса проблем.
Конфликт версий. SDK тянет requests==2.28.0, а у вас в проекте уже requests==2.31.0 из-за собственного фреймворка. Жёсткий pin — установка падает с конфликтом. Мягкий (>=2.20,<3.0) — установится одна из совместимых версий, и обновление основного фреймворка через полгода может сломать совместимость с SDK. В Python особенно больно: глобальное пространство имён не даёт держать две версии requests одновременно. В Node чуть легче за счёт node_modules per-package, но дубли раздувают бандл.
Supply-chain атаки. Каждая транзитивная зависимость — вектор атаки. event-stream в npm — мейнтейнер передал доступ незнакомцу, тот добавил код кражи криптокошельков. ua-parser-js — взлом аккаунта, релиз с майнером. colors.js — «протест-релиз», ломающий всё зависящее. PyPI и Composer — те же истории меньшего масштаба. Когда SDK тянет 14 пакетов, дерево транзитивных может перевалить за 100, и ваш npm audit / safety check начинает регулярно ругаться на advisories в зависимостях зависимостей — а фиксить их вы не можете, потому что не контролируете SDK, через который они пришли.
Устаревание. Зависимость, что год назад была свежей, сегодня имеет известную CVE. Активно поддерживаемый SDK обновляет их — нормальный жизненный цикл. Заброшенный — каждая зависимость становится миной под интегратором.
В BOTIX все три SDK построены по принципу zero-dependency: только стандартная библиотека языка. В PHP — curl через штатное расширение. В Python — urllib.request из stdlib. В Node — встроенные https/http. JSON-сериализация, UUIDv4 и HMAC для верификации webhook — тоже из stdlib. Возражение «но requests удобнее urllib» справедливо для прикладного кода. SDK — не прикладной код: он живёт в продакшене интегратора, и его задача не быть красивым, а минимизировать риск. «Нет 14 проблем с зависимостями» перевешивает «синтаксис чуть приятнее».
PHP, Python, Node — установка без единой зависимости
Порядок одинаковый для всех трёх языков: поставить пакет, прочитать ключ из ENV, сделать первый запрос, проверить дерево зависимостей.
1. PHP — composer require botix-pro/sdk. github.com/BOTIX-pro/sdk-php/blob/main/composer.json:
{
"require": {
"php": "^8.1",
"ext-curl": "*",
"ext-json": "*"
}
}Кроме самого PHP и двух стандартных расширений — ничего. Установка:
composer require botix-pro/sdk:^1.1Использование (ключ — только из ENV):
<?php
require __DIR__ . '/vendor/autoload.php';
use Botix\SDK\Client;
$client = new Client(apiKey: getenv('BOTIX_API_KEY'));
$contact = $client->contacts()->create([
'phone' => '+79991234567',
'name' => 'Test',
]);
echo $contact['id'];Внутри HTTP — через curl_exec, JSON — через json_encode/json_decode, UUIDv4 — собственная реализация на 6 строк через random_bytes(16). Проверка дерева:
composer show --tree
# botix-pro/sdk 1.1.0
# └── php >=8.1На фоне Guzzle (psr/http-client + psr/http-factory + psr/http-message + ralouphie/getallheaders + symfony/deprecation-contracts) разница очевидна.
2. Python — pip install botix. github.com/BOTIX-pro/sdk-python/blob/main/setup.py:
setup(
name="botix",
version="1.1.0",
install_requires=[], # пусто
python_requires=">=3.8",
)install_requires=[] — пустой список. SDK использует только stdlib: urllib.request для HTTP, json для сериализации, hmac и hashlib для верификации webhook, uuid для идемпотентности. Никакого requests, httpx, pydantic.
pip install botixИспользование:
import os
from botix import Client
client = Client(api_key=XXXXXXXX["BOTIX_API_KEY"])
contact = client.contacts.create(
phone="+79991234567",
name="Test",
)
print(contact.id)Дерево зависимостей:
pip show botix | grep Requires
# Requires:Пусто. pip list после установки покажет только сам botix. safety check не выдаёт новых CVE-предупреждений.
3. Node — npm install @botix/sdk. github.com/BOTIX-pro/sdk-node/blob/main/package.json:
{
"name": "@botix/sdk",
"version": "1.1.0",
"dependencies": {},
"devDependencies": {
"typescript": "^5.0",
"vitest": "^1.0"
}
}dependencies пустые. devDependencies — только билд-инструменты, в node_modules пользователя не попадают. HTTP — встроенные https и http, JSON — JSON.parse/JSON.stringify, HMAC — встроенный crypto.
npm install @botix/sdkИспользование:
const { Client } = require('@botix/sdk');
const client = new Client({ apiKey: XXXXXXXX });
const contact = await client.contacts.create({
phone: '+79991234567',
name: 'Test',
});
console.log(contact.id);npm ls
# my-app@1.0.0
# └── @botix/sdk@1.1.0Без вложенных. На фоне axios (follow-redirects + form-data + proxy-from-env + транзитивные) разница в размере node_modules заметная: установка @botix/sdk добавляет 30–40 КБ, а не 2 МБ. Структура методов у всех трёх SDK одинаковая — client.contacts.create(...) выглядит идентично в PHP, Python и Node, потому что все три генерируются из одного openapi.yaml. Подробнее про генерацию из спецификации — в разборе zero-deps SDK: генерация из OpenAPI и open-source и SDK BOTIX 1.1: zero-deps, генерация из OpenAPI, триал.
Семь антипаттернов хранения API-ключа
API-ключ — это аналог пароля, написанного в открытом виде. У него по умолчанию нет срока действия, защиты вторым фактором, попыточного лимита. Любой, кто получит ключ, делает всё, что доступно тарифу проекта: читает контакты, рассылает сообщения, меняет сценарии, удаляет данные. Формат ключа в BOTIX — Authorization: Bearer XXXXXXXX… (40 символов), каждый ключ привязан к одному project_id. Компрометация одного ключа — это не «инцидент в фиче», а потенциально полный slave проекта на платформе.
Большинство утечек происходит не из-за изощрённого взлома, а из-за стандартных антипаттернов. Их семь, и каждый встречается даже в зрелых командах.
- Ключ в репозитории. Разработчик пишет
$key = 'btx_live_XXXX…';прямо в конфиге, коммитит. Через неделю репозиторий становится публичным (open-source, переезд, бэкап) — ключ у всех. Секрет-сканеры (GitHub Secret Scanning, GitLab Secret Detection) ловят паттернbtx_live_…и уведомляют владельца за часы — но за эти часы базу контактов уже успевают выгрузить. - Ключ в
.envбез шифрования. Файл лежит на диске в plaintext. RCE-уязвимость, бэкап-копия или увольнённый админ — и ключи у всех разом. Классика: Docker-образ, попавший в публичный реестр с забытым.envвнутри..env— приемлемое место для *переменной*, но не для *хранения*. - Один ключ на всю команду. Master-ключ в Slack. Через два года ушли пятеро, при увольнении ключ не ротировался — любой бывший сотрудник может вернуться и навредить.
- Ключ в логах.
error_log('Request: ' . print_r($headers, true));— и в логах полныйAuthorization: Bearer XXXXXXXX…. Логи уходят в ELK/Loki/Datadog, где их видят все с доступом к мониторингу. Полу-публичная утечка. - Ключ в URL.
https://api.example.com/contacts?api_key=…— попадает в access.log nginx, логи прокси и Referer при переходах на третьи ресурсы. Платформа BOTIX категорически не принимает ключ через query-string, только черезAuthorization: Bearer— это закреплено явной проверкой источника заголовка вapp/Middleware/PublicApiAuth.php. - Ключ без ротации. Тот же ключ два года: сменилась половина команды, прошли рефакторинги, был инцидент «с подозрением, но не точно». Бессрочный пароль — чем дольше живёт, тем выше шанс, что уже утёк. Гигиена: плановая ротация раз в 6 месяцев плюс внеплановая после любого подозрения, с двумя состояниями (новый работает, старый ещё не отозван) для безболезненного свитча.
- Ключ с избыточными правами. Сервис, который только шлёт сообщения, использует ключ с полным набором прав. Контрмера — scopes на уровне ключа. У BOTIX
scopes— JSON-поле в таблицахbtx_api_keysиbtx_oauth_access_tokens. При создании ключа наapp.botix.pro/developersуказывается список scope, middleware проверяет соответствие при каждом запросе; без нужного —403 INSUFFICIENT_SCOPE. Сервису для рассылки выдаётся ключ сmessages:send— при компрометации никаких побочных эффектов вродеDELETE /contacts.
Нормальная схема: secret manager → ENV → SDK
Схема, закрывающая все семь антипаттернов сразу:
- Источник правды — secret manager (HashiCorp Vault, AWS Secrets Manager, Yandex Lockbox; в простом случае —
passповерх gpg). Ключ хранится зашифрованным, доступ выдаётся ролям, у каждого доступа — audit-лог. - При деплое скрипт читает ключ из secret manager и подставляет в ENV процесса. Файл
.envв репозитории отсутствует или содержит только placeholder'ы. Контейнер пересобирается без ключа — ключ инжектится в момент запуска:docker run -e BOTIX_API_KEY=...или через Kubernetes Secret. - SDK читает ключ из ENV (
os.environ,getenv,process.env). В коде нет строковой константы, конфига или файла с ключом. Если ENV не установлен — SDK падает на старте с понятной ошибкой. Примеры инициализации на PHP/Python/Node лежат наdevelopers.botix.pro/best-practices. - В логах ключ маскируется. SDK BOTIX делают это автоматически: при сериализации заголовков для логирования значение
Authorizationзаменяется наBearer ***. Если код пишется руками — правило проговаривается в код-ревью. - В URL ключ не передаётся. Каждый сервис — свой ключ с минимальным scope. Ротация — раз в полгода либо по событию.
- Audit-лог. Каждый запрос пишется в
btx_api_log, журнал API наapp.botix.pro/developersпоказывает, что именно шло с каждого ключа. Если ключ внезапно начал делатьDELETE /contacts, хотя в норме шлёт толькоPOST /messages, — это видно сразу, и ключ отзывается до масштабного ущерба.
Чек-лист для код-ревью или security-аудита — семь проверок по минуте каждая:
.envв.gitignore.- В исходниках нет строк, начинающихся с
btx_live_. - Конфиг читает ключ через
getenv()или эквивалент. - SDK инициализируется один раз на старте процесса, не на каждом запросе.
- В логах headers фильтруются — нет полного значения
Authorization. - URL'ы не содержат ключа.
- На каждый сервис — отдельный ключ, имя сервиса записано в поле
nameтаблицыbtx_api_keys.
Прохождение чек-листа — не паранойя, а уровень гигиены, ниже которого работать с публичным API в продакшене нельзя. Про выбор Authorization: Bearer против OAuth-токена и когда что применять — в разборе OAuth 2.0 vs API-key в SaaS-интеграциях и multi-tenant: один SDK на 100 ботов.
Зачем компании открывать исходный код SDK
Открытый код SDK обычно обсуждают через категорию «щедрость»: «принесём пользу сообществу» против «потратим время на фичи». В таком виде обсуждение буксует, потому что стороны спорят о морали, а не о функциях. На деле open-source SDK решает четыре конкретные задачи, которые закрытый SDK либо не решает, либо решает дорого.
Функция 1: security-аудит без участия поставщика. Корпоративная интеграция почти всегда проходит через security-команду. Закрытая библиотека для них — чёрный ящик, который что-то делает с данными. Дальше три дорогих варианта: заблокировать интеграцию (частый исход), потребовать SOC 2 Type II + ISO 27001 + DPA (десятки тысяч долларов и месяцы поставщику), либо запросить исходник под NDA (недели процедуры). Open-source закрывает все три: security открывает GitHub-репозиторий, видит, что библиотека делает только заявленное, и пропускает интеграцию. SOC 2 при этом всё равно нужен — но для инфраструктуры и процессов, а не для точки входа в собственный код.
Функция 2: bug fix не блокируется вендором. В закрытом SDK любая ошибка — тикет в поддержку и новая версия через месяц-три, всё это время у интегратора костыль. В открытом — два пути: PR с фиксом в upstream либо временный форк, который патчится через VCS-ссылку в composer.json/package.json, пока PR не приняли. Никакой блокировки.
Функция 3: сигнал зрелости API. Публикация SDK под открытой лицензией читается как «у API есть стабильный контракт, который не стыдно показать». Закрытый SDK часто прочитывается как «наколхозили, поэтому прячут» — не обязательно правда, но влияет на восприятие. Сигнал работает не на сознательном уровне: инженер посмотрел репозиторий, не нашёл ничего стыдного — и покупатель формулирует «серьёзные люди».
В BOTIX сигнал встроен в стратегию SDK с самого начала: три SDK, CLI и три example-репозитория выложены на GitHub в организацию BOTIX-pro под открытой лицензией, пакеты опубликованы в Composer, PyPI и npm:
composer require botix-pro/sdk:^1.1
pip install botix==1.1.0
npm install @botix/sdk@1.1.0Полная карта репозиториев:
| Репо | Пакет |
|---|---|
sdk-php | Composer botix-pro/sdk |
sdk-python | PyPI botix |
sdk-node | npm @botix/sdk |
cli | PyPI botix-cli |
example-laravel | Laravel 11 + Pest |
example-express | Express 4 + TypeScript + Vitest |
example-flask | Flask 3 + pytest |
Функция 4: контрибьюции от сообщества. На старте open-source SDK — односторонняя отдача: поставщик пишет, сообщество потребляет. По мере роста появляются PR на retry, timeout, прокси, совместимость с нетипичной версией зависимости — часы, которые поставщик не потратил. У зрелых SDK (Stripe, Twilio, Slack) — десятки внешних контрибьюторов; у молодых — единицы или ноль, и это нормально. SDK BOTIX молодые, контрибьюций пока нет, оценка — через 90 дней после релиза.
Открытость не раскрывает архитектуру API — при одном условии: SDK не содержит бизнес-логики. Он делает ровно три вещи — формирует запрос, подписывает, парсит ответ. Индекс категорий, бизнес-правила, расчёты остаются на стороне api.botix.pro. При такой дисциплине открытый код показывает только формат работы с публичным API, который и так лежит в OpenAPI-спецификации. Утащить SDK в чужой продукт бессмысленно: без своего API он бесполезен.
Подводные камни и когда open-source не нужен
Честно про издержки, чтобы не выглядело маркетингом.
HTTP-клиент в stdlib чуть менее удобен. На Python — urllib.request.Request вместо однострочного requests.get. Внутри SDK это закрыто; если пишете на голом HTTP — примите немного больше кода. Цена за ноль зависимостей.
Тесты SDK сложнее. Моки HTTP-вызовов через урезанный stdlib-клиент пишутся вручную. Это проблема разработчиков SDK, не интеграторов, и она снята генерацией из единого openapi.yaml: шаблоны настроены один раз, структура кода идентична во всех трёх языках.
Поддержка публичного репозитория — реальная работа. Входящие issues без выделенного человека превращают SDK в кладбище с просрочкой по 200 дней — антиреклама. В BOTIX этот пункт в фазе становления.
Open-source нужен не всякому API. Если API нишевой и аудитория — два-три интегратора по NDA; если API в стадии активного breaking-change (сообщество увидит нестабильность в публичном репозитории — сигнал, обратный ожидаемому); если нет человека на review PR и ответы на issues — открытие ухудшит ситуацию. Все три условия — про ранние стадии; когда продукт зреет и аудитория растёт, закрытый SDK становится якорем роста.
Проверяйте размер dependencies перед установкой любого SDK. 0–2 пакета — SDK с уважением к интегратору. 5–7 — приемлемо, но убедитесь, что это мейнстрим, а не маргинальные пакеты от одного автора. 10+ — SDK, который кладёт на вас груз чужой экосистемы.
Попробуйте API BOTIX
Получите ключ, отправьте первый запрос и поймайте webhook — прямо в браузере, без боевого канала.
Попробовать API бесплатноЧитайте также
SDK BOTIX 1.1: zero-deps, генерация из OpenAPI и триал
Почему в SDK ноль зависимостей и генерация из OpenAPI
Онбординг разработчика: quickstart, sandbox и API-ключи
Quickstart, триал-sandbox и polling vs webhook
Первый запрос к API за 5 минут: SDK из OpenAPI и триал
