Skip to content

Песочницы по запросу ​

Песочница — это ваша отдельная организация в Tango Vision: собственная база данных PostgreSQL, наполненный граф здания и выделенный стек tv-api — на собственном поддомене. Вы разрабатываете в ней вместо продакшена.

Что изолировано, а что общее ​

«Изоляция» — слово, которое стоит расшифровать: важно понимать, до чего может дотянуться ошибка в вашей песочнице.

Изолировано:

  • База данных. У каждой песочницы своя база и своя роль PostgreSQL для подключения к ней — на выделенном сервере Postgres, где нет продуктивных данных. Эта роль не может открыть базу другой песочницы, а также (tv-platform#822) базу postgres на этом сервере и — если провижинер хранит своё состояние на том же сервере — эту базу состояния.
  • Под. tv-api песочницы — отдельный Deployment в изолированном пространстве имён (dev), отличном от продуктивного, со своим Secret и своим токеном.
  • Сетевой путь до продакшена. Между этим пространством имён и продакшеном стоят NetworkPolicy. Кроме того, у пода песочницы выключены продуктивный брокер MQTT (WIFI_SENSING_MQTT_ENABLED=false) и регистрация на платформе — заданы в env контейнера, поэтому унаследовать другое значение он не может.
  • Оболочка, которая загружает ваш модуль. Сторонний код модуля работает только в оболочке песочницы, привязанной к вашей песочнице, и никогда — в продуктивной оболочке; см. Ваш модуль в оболочке песочницы.

Общее:

  • Кластер Kubernetes. Песочницы — это пространства имён в том же кластере, а не отдельный кластер. Именно поэтому существуют квоты ниже.
  • Один реалм Keycloak. Все песочницы аутентифицируются в единственном реалме sandboxes (никогда не в продуктивном). Разделение внутри него задумано по клейму tenant_id, равному organizationId вашей песочницы, а не по отдельному реалму на разработчика.
  • Сам провижинер и его база метаданных: в ней лежат записи песочниц и API-ключи всех разработчиков.

Вход в песочницы пока общий (на 26.09.2026)

Сейчас любая песочница пускает любого пользователя общего реалма sandboxes, для какой бы песочницы ни была заведена его учётная запись: описанная выше проверка tenant_id пока не применяется. Исправление, после которого каждая песочница будет пускать только пользователей своей организации, уже в работе; когда оно выйдет, это предупреждение уберём. До тех пор исходите из того, что в вашу песочницу может войти любой пользователь песочниц, и храните в ней только синтетические данные.

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

Только синтетические данные. Не загружайте в песочницу реальные данные компании (списки арендаторов, планы этажей, любые сведения о реальных людях), если это не согласовано с нами письменно. Песочницы — общая инфраструктура, у них ограниченный срок жизни, а сохранность данных не гарантируется.

Общего исходящего доступа в интернет нет. Поды песочницы не могут делать произвольные исходящие вызовы. Одно следствие всплывает сразу: Copilot песочницы не может достучаться до внешней LLM, поэтому ИИ-функции, которые ходят к провайдеру, в песочнице работать не будут. Разрабатывайте их на моках, см. Свой LLM-эндпоинт.

Зачем ​

  • Реалистичность. Она наполнена параметризованным зданием — mall, office или university — с помещениями, элементами и телеметрией, чтобы ваш модуль отрисовывался на данных реальной формы.
  • Одноразовость. Сбросьте её, когда навели беспорядок; она истекает автоматически.

Создание — через CLI ​

SDK покрывает весь жизненный цикл, так что писать curl руками не нужно. Войдите один раз (вход через CLI) — и каждая команда sandbox аутентифицируется сама, из системного хранилища ключей:

bash
npx @tv/extension-sdk login

npx @tv/extension-sdk sandbox create \
  --name="acme-cafm-dev" \
  --type=mall \
  --storeys=3 \
  --area-sqm=20000 \
  --seed-telemetry-days=14 \
  --ttl-days=30

В CI и любой другой неинтерактивной среде вместо входа используйте API-ключ, выпущенный в портале — явные учётные данные всегда важнее сохранённой сессии:

bash
export TV_API_TOKEN=$SANDBOX_API_KEY   # tvk_-ключ из портала
npx @tv/extension-sdk sandbox list

По умолчанию CLI обращается к https://sandbox-api.k8s.tangovision.dev; перенаправить его можно флагом --api=<url> (или переменной TV_SANDBOX_API_URL).

ПодкомандаЧто делает
createСоздаёт песочницу. --dry-run генерирует наполнение локально, не обращаясь к сервису. --type=university допустим начиная с 1.14.0 (требуется @tv/extension-sdk 1.14.0 или новее): сервис и шаблоны наполнения принимали его всегда, но собственный разбор аргументов в CLI отклонял его вплоть до 1.13.0 включительно. На более старом CLI создавайте университет через API ниже.
listСписок ваших песочниц
connect <id>Печатает запись песочницы, а затем её собственный URL tv-api и токен администратора как настройки TV_API_URL=… / TV_API_TOKEN=… — только для серверного кода (скрипта, локального бэкенда; никогда для кода в браузере). Не экспортируйте их в терминале, где вы запускаете команды sandbox: list и create читают их как адрес сервиса песочниц и ваш ключ и начнут обращаться к вашей песочнице. SDK 1.15.0 печатал их строками export.
extend <id> --days=NПродлевает TTL. --days обязателен, целое число 1–7.
reset <id>Очищает и заново наполняет, не удаляя
delete <id>Удаляет немедленно
install <manifest>Регистрирует ваш модуль в вашей собственной песочнице, выдаёт лицензию и печатает URL, который нужно открыть. Начиная с 1.14.0 (требуется @tv/extension-sdk 1.14.0 или новее); см. Ваш модуль в оболочке песочницы.

<id> (и install --sandbox=<id>) — это идентификатор песочницы вида sbx_…: его печатает create, а sandbox list показывает идентификаторы всех ваших песочниц. Это не slug из URL песочницы.

Дополнительные параметры наполнения: --spaces-min / --spaces-max (по умолчанию 10/30), --equipment-density=sparse|realistic|dense, --occupancy-profile=24x7|office-hours|peak-evenings, --ttl-days=N (1–30, по умолчанию 14) и --seed=<строка> для детерминированной генерации. Добавьте --format=json к любой подкоманде, чтобы использовать её в скриптах. create, list и connect показывают slug и organizationId каждой песочницы и в обычном выводе (SDK 1.15.1 и новее; 1.15.0 показывал их только с --format=json), а create заканчивает вывод строкой, которую нужно прислать нам для учётных записей в песочнице.

Поддомен — это slug, который сервис собирает как <ваша-организация>-<первые 16 символов имени>-<6 случайных символов>: он начинается с вашей организации и поэтому никогда не конфликтует с одноимённой песочницей другой организации:

https://dev-a1b2c3d4e5f6-acme-cafm-dev-k2x7p9.sandbox.k8s.tangovision.dev

Slug вашей организации — dev-<12 шестнадцатеричных символов>: каждая учётная запись разработчика — отдельная организация. Это же и граница «ваших» песочниц, и единица, в которой считаются квоты ниже. Если над одной песочницей работают двое, см. Два разработчика, одна песочница.

Создание — через API ​

bash
curl -X POST https://sandbox-api.k8s.tangovision.dev/api/v1/sandboxes \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "acme-cafm-dev",
    "buildingType": "mall",
    "storeys": 3,
    "areaSqm": 20000,
    "ttlDays": 14
  }'

Ответ — 202 Accepted. Развёртывание идёт в фоне (база данных, граф здания с данными и отдельный стек tv-api — на реалистичных параметрах это несколько минут), поэтому запись возвращается в статусе provisioning:

json
{
  "sandboxId": "sbx_...",
  "name": "acme-cafm-dev",
  "slug": "dev-a1b2c3d4e5f6-acme-cafm-dev-k2x7p9",
  "status": "provisioning",
  "apiUrl": "https://dev-a1b2c3d4e5f6-acme-cafm-dev-k2x7p9.sandbox.k8s.tangovision.dev",
  "consoleUrl": null,
  "apiToken": "...",
  "organizationId": null,
  "buildingId": null,
  "createdAt": "2026-05-30T...",
  "expiresAt": "2026-06-13T...",
  "extensionsUsed": 0,
  "extensionsRemaining": 2,
  "failureReason": null
}

apiToken — собственные учётные данные песочницы, сохраните их: они дают права администратора в API этой песочницы — и больше нигде. organizationId и buildingId остаются пустыми, пока развёртывание не завершится.

consoleUrl — интерфейс, привязанный к этой песочнице. Он равен null, пока не развёрнута оболочка песочницы. Если она развёрнута, это тот же хост песочницы: оболочка отдаётся на /, а API остаётся на /api и /socket.io, поэтому интерфейс и бэкенд работают в одном origin. Оболочка песочницы — отдельный деплой, не продовый: код модуля полностью доверен в той оболочке, которая его загружает, поэтому ваш модуль запускается только в оболочке, привязанной к вашей песочнице.

organizationId — идентификатор организации песочницы. У всех песочниц один общий реалм Keycloak, и по замыслу пользователь входит именно в вашу песочницу только тогда, когда его клейм tenant_id равен этому значению (пока это не применяется, см. предупреждение в разделе Что изолировано, а что общее). Это значение нужно оператору, чтобы завести учётную запись в песочнице; оно уникально для каждой песочницы, а не для её имени.

Опрашивайте эндпоинт детализации, пока status не выйдет из provisioning:

bash
curl -H "Authorization: Bearer $SANDBOX_API_KEY" \
  https://sandbox-api.k8s.tangovision.dev/api/v1/sandboxes/sbx_...

Всего статусов пять: provisioning, ready, failed, expired и deleted. ready — песочница готова (заполнены buildingId и итоговый apiUrl); failed — в failureReason записана причина, и это терминальный статус. CLI (sandbox create) опрашивает сервис сам каждые 5 секунд и завершается, когда песочница готова, — либо сдаётся через 15 минут, после чего развёртывание продолжается на сервере, а результат покажет sandbox list.

Жизненный цикл ​

ДействиеЭндпоинтОтвет
СписокGET /api/v1/sandboxes200 { sandboxes: [...] }
Получить однуGET /api/v1/sandboxes/:id200 — именно её вы опрашиваете
СоздатьPOST /api/v1/sandboxes202, статус provisioning
Продлить TTLPOST /api/v1/sandboxes/:id/extend, тело { "days": 7 }201
СброситьPOST /api/v1/sandboxes/:id/reset201 либо 409, если статус не ready
УдалитьDELETE /api/v1/sandboxes/:id204, идемпотентно

Поле days при продлении обязательно и должно быть целым числом 1–7; без него — 400. Обратите внимание, что это другая граница, чем у --ttl-days при создании (1–30), поэтому --days=14 будет отклонён.

Что делает reset

Команда удаляет и заново создаёт базу данных песочницы, выполняет тот же шаг миграции и наполнения, что и create, с параметрами, с которыми песочница была создана, и перезапускает API песочницы на новой базе — вы получаете свежий граф здания с теми же id, URL и токеном. Идентификатор здания меняется, потому что граф генерируется заново. Пока API перезапускается, он около минуты недоступен.

Если наполнение не удалось, песочница переходит в статус failed, а не остаётся ready с пустой базой; удалите её и создайте новую.

Квоты ​

Чтобы общий кластер оставался здоровым:

  • 3 одновременно активные песочницы на организацию (считаются provisioning и ready; expired и deleted — нет)
  • 2 продления TTL на песочницу, по 7 дней максимум каждое
  • 30 дней — максимальный TTL при создании, то есть предельный срок жизни одной песочницы — 44 дня

Напоминаний перед истечением срока нет, а истёкшую песочницу продлить нельзя: её база и хост удаляются. Запишите дату expires при создании и продлевайте вовремя.

modules при создании не принимается: непустой массив — это 400 с кодом MODULES_NOT_SUPPORTED. Раньше поле принималось и молча отбрасывалось: песочница поднималась без запрошенных модулей, и ничто об этом не сообщало. Устанавливайте модуль в песочницу, когда она перешла в ready, командой sandbox install (SDK 1.14.0 или новее). Текст самой ошибки до сих пор утверждает, что эта команда не выпущена; он устарел.

Превышение квоты — это 403 с машиночитаемым кодом: QUOTA_CONCURRENCY при достижении лимита одновременных песочниц и QUOTA_EXTENSIONS, когда песочница израсходовала оба продления. Некорректное тело запроса — 400; неизвестные поля отклоняются, а не игнорируются.

Что внутри свежей песочницы ​

  • Организация + площадка + здание, наполненные через @tv/sandbox-seed (закрытый пакет; его перечисление BuildingType — ровно mall | office | university)
  • Этажи, помещения, элементы и точки, размер которых задан вашими параметрами
  • До 30 дней дозаполненной телеметрии (настраивается через seedTelemetryDays)
  • Стандартная схема tv-api, так что работают все эндпоинты платформы

Ваш модуль обращается к tv-api песочницы так же, как к продуктивному: относительные пути /api/… и authorizationHeader() из @tv/extension-sdk/context в каждом запросе — см. Вызов API из модуля. Структурно песочница — это продакшен.

Для сотрудников Tango Vision: консоль ​

Сотрудники могут создавать песочницы и из служебной консоли, для входа в которую нужна учётная запись сотрудника; приглашённые разработчики пользуются CLI (см. выше). Её страница Sandboxes (в админ-навигации) принимает API-ключ, затем — New sandbox:

ПолеЗначение
NameОтображаемое имя; поддомен выводится из него
Building typemall, office или university
Storeys1–50
Area (m²)Общая площадь
TTL (days)1–30; автоочистка после

Строка появляется в статусе provisioning и переходит в ready, когда база засеяна — от минуты на маленьком здании до нескольких минут на реалистичных параметрах.

Создано на платформе Tango Vision. Вопросы? developers@tango.vision