AACSearch / руководство
Операции платформы
Экраны SaaS-команды: бизнес-обзор, организации, каталог моделей, поисковый кластер, планировщик и ресурсы.
Экраны платформы видны только аккаунтам, перечисленным в API в
PLATFORM_ADMIN_EMAILS. Роль владельца организации не даёт к ним доступа
ни на одном тарифе: клиент, открывший URL платформы, увидит пояснение, а не
сломанный экран, а API в любом случае отклонит соответствующие вызовы.
Группа в боковой панели появляется, как только сессия распознана как сессия
оператора платформы.
Бизнес-обзор
/dashboard/admin/overview — платформа с одного взгляда: те показатели, ради
которых владелец открывает консоль администратора:
- Organizations, paying organizations (активные или на пробном периоде платного тарифа), users и live API keys по всем тенантам.
- Signups за последние 30 дней, по дням.
- Wallets — организации с кошельком, кредиты на балансах и кредиты, перемещённые за последние 30 дней, с разбивкой по типу (пополнение, использование, корректировка).
- Subscriptions by plan — тариф и статус по всем тенантам.
Все показатели получены одним агрегирующим вызовом (admin.overview). Суммы
указаны в кредитах, а не в валюте: курс пересчёта кредитов в валюту задаётся
политикой биллинга, поэтому страница честно придерживается единиц измерения и не
выдумывает показатель выручки.
Организации
/dashboard/admin/organizations — каталог тенантов, единственное представление,
которое не может дать ни один клиентский экран: оператор не является участником
этих организаций, и любой маршрут с областью тенанта ему откажет.
- Список — все организации с тарифом, статусом подписки, датой продления, числом участников и активных ключей, балансом кошелька и датой регистрации. Поиск по названию, slug или id, фильтрация по тарифу и статусу подписки, постраничный вывод.
- Карточка (
/dashboard/admin/organizations/{id}) — идентификационные данные (включая поля биллинга для юридических лиц РФ и клиента Stripe), биллинг (тариф, период, пробный период, места, баланс кошелька, списанные и пополненные кредиты, функции тарифа), команда с ролями, API-ключи (только префиксы — материал ключей хранится в виде хеша) и последние 50 движений по кошельку. - Приостановка / возобновление — собственный инструмент оператора. Клиент может приостановить только свою организацию и только в роли владельца; ни один клиентский экран не позволяет приостановить другого тенанта. Приостановка блокирует поиск и вызовы API тенанта до её снятия, а причина записывается в журнал аудита платформы.
- Корректировка кредитов — возврат, компенсационное начисление или
исправление с обязательным указанием причины. Операция идемпотентна по
референсу, поэтому повторный запрос не начислит кредиты дважды; отрицательная
сумма означает списание (возврат). Корректировка попадает в журнал операций
кошелька тенанта как
adjustmentи в журнал аудита платформы.
Выручка
/dashboard/admin/revenue отвечает на вопрос «кто и сколько заплатил» по всем
тенантам.
Два реестра, которые никогда не суммируются. Страница разделяет две разные единицы:
- Полученные деньги — кредиты, поступившие в кошелёк через платёжного провайдера (пополнение через Stripe или Robokassa). Это деньги, которые действительно пришли.
- Списанные / удерживаемые кредиты — расходуемая внутренняя предоплаченная единица. Баланс кредитов — это обязательство, а не выручка, поэтому он никогда не прибавляется к деньгам.
MRR нормализуется помесячно по списку тарифов платформы и помечается соответствующим образом. Цены тарифов сейчас хранятся у провайдера, поэтому для тарифа без локальной цены выводится «—», а не предполагаемое число, и страница сообщает, скольких платящих тенантов это касается.
Проблемы с оплатой
/dashboard/admin/billing-issues — очередь работы с задолженностями: подписки в
статусах past_due, unpaid, incomplete, incomplete_expired или canceled,
а также тенанты, отменяющие подписку в конце периода, — со сводными счётчиками
просроченных, пробных и отменяемых подписок. Способы оплаты и повторное списание
находятся в Stripe; каждая строка ведёт на вкладку Billing тенанта.
У каждой организации также есть вкладка Billing
(/dashboard/admin/organizations/{id}/billing): счета Stripe, стоящие за
кошельком (оплачено на текущий момент, статус, сумма и период каждого счёта,
ссылки на размещённые счета), рядом с журналом операций с кредитами. Список
счетов загружается в реальном времени — ничего не кешируется.
Браузер данных
/dashboard/admin/resources — браузер в режиме полного доступа (god mode): любая
строка с областью тенанта любой организации. Список ресурсов, их столбцы и
признак доступности для записи приходят из API (admin.resources), поэтому
интерфейс никогда не предлагает таблицу, которую API отклонит.
Его защитные механизмы структурные, а не косметические:
- Список разрешённых, а не запрещённых — таблица, отсутствующая в реестре, возвращает 404. Новая таблица остаётся невидимой, пока её не добавят намеренно.
- Секреты исключаются из запроса, а не скрываются в интерфейсе:
hashedKey,signingSecret,publishToken,keyHashи подобные никогда не покидают базу данных. - Ресурс с областью тенанта требует id организации — список сразу по нескольким тенантам отклоняется, поэтому правило «ни один запрос не опускает область тенанта» соблюдается по построению.
- По умолчанию только чтение; запись разрешена лишь для ресурсов, явно её
включивших, а
id,organization_id,reference_idиcreated_atнеизменяемы, так что правка никогда не перенесёт строку в другого тенанта. - Ничего нельзя удалить через god mode: у удаления тенанта, его журнала операций или ключей есть свой рабочий процесс (приостановка, отзыв, отключение).
- Каждая правка попадает в аудит — с состоянием до и после, причиной и оператором.
- Экспорт в CSV проходит через тот же реестр, поэтому скрытый столбец нельзя запросить по имени. Лимит — 10 000 строк, и его достижение указывается и в ответе, и в файле: молчаливое усечение хуже отказа.
Тарифы и цены
/dashboard/admin/plans управляет каталогом тарифов. Цена — это версия, а не
столбец: установка новой цены добавляет строку с новой датой вступления в силу
и закрывает окно действия предыдущей версии, поэтому подписка, проданная по
старой цене, её сохраняет — это сохранение прежних условий (grandfathering), и по
той же причине Stripe делает суммы цен неизменяемыми. Страница показывает все
версии, кто и почему их установил, и никогда не предлагает редактировать историю.
Архивация тарифа прекращает новые продажи, не затрагивая существующие подписки.
Как только цена задана, MRR на странице выручки становится измеренным числом вместо «—».
Состояние тенантов
/dashboard/admin/health ранжирует тенантов по риску оттока на основе сигналов,
уже имеющихся в данных: never used, idle 30d+, paying with an empty
wallet, past due и free past the trial window. Оценка намеренно
грубая — один сигнал равен 25 баллам, — потому что правило, с которым оператор
может поспорить, лучше модели, которую он не может проверить.
Вход от имени клиента для поддержки
На странице организации кнопка Impersonate открывает ограниченную по времени сессию поддержки. Это не сессионная cookie, и она не позволяет оператору стать пользователем: это запись — с областью организации, по умолчанию на 30 минут и только для чтения, — а каждое действие внутри неё остаётся закреплённым за оператором.
Меры защиты, каждая из которых закрывает задокументированный недостаток наивной реализации:
- Причина обязательна и показывается тенанту.
- По умолчанию только чтение; режим
writeнужно запросить явно, и даже в нём запрещены операции с деньгами, API-ключами и управлением доступом: выпуск ключа во время входа от имени клиента — классическая эскалация, ведь ключ переживает сессию. - Намеренно записывается дважды: в журнал аудита платформы и в собственный журнал аудита организации, чтобы команда комплаенса тенанта видела, что входила поддержка. Это единственное осознанное исключение из правила «действия оператора никогда не попадают в журнал тенанта».
- Запрещено для организаций только с SSO или со списком разрешённых IP, если это не переопределено явно: вход от имени таких организаций незаметно обошёл бы механизм контроля, установленный тенантом.
- Истечение срока — настоящая страховка: закрытая вкладка никогда не вызывает «завершение», поэтому истёкшая сессия окончена независимо от того, что думает клиент. Сессии также можно отозвать массово для всей организации.
Аудит платформы
/dashboard/admin/platform-audit — собственный журнал команды платформы: что
оператор сделал с платформой: приостановил тенанта, скорректировал кредиты,
изменил каталог моделей, запустил задачу. Это отдельная таблица
(platform_audit_log), не связанная с журналом аудита организации, и поэтому он
показан здесь, а не в разделе организации: оператор, действующий в отношении
тенанта, не является его участником, это действие — не событие, которое должен
видеть тенант, а журнал аудита организации доступен её участникам, так что запись
оператора туда и приписала бы действие не тому, и раскрыла бы клиенту личности
операторов.
Поисковый кластер
/dashboard/engine — представление только для чтения единственного поискового
движка, стоящего за API тенантов:
- Индикатор состояния по
GET /v1/health, различающий состояния «исправен», «недоступен» и «доступен, но не готов». - Статистика движка из
GET /v1/stats.json— счётчики запросов и задержек по операциям, доля попаданий в кеш, ожидающие пакеты записи — а также разбивка задержек и пропускной способности по эндпоинтам. Пока все счётчики равны нулю, отображается индикатор Idle, а строка «Updated hh:mm:ss» отмечает время последнего чтения. - Общее число коллекций и документов активной организации (карточка читает эндпоинт коллекций тенанта, который ограничен организацией, а не всей платформой).
- Карточка подключения с базовым URL API, заголовком
X-NOVA-API-KEYи двумя областями доступа (scope) ключей, со ссылками на API-ключи и коллекции организации. - Кнопка Refresh в заголовке.
Каждый из трёх запросов выполняется независимо, поэтому сбой одного ухудшает только его карточку. Счётчики равны нулю, пока узел не получит трафик.
Операции обслуживания, которые предоставляет сам движок, — снимки, очистка кеша,
компактизация базы данных, перевыборы raft и статус изменения схемы — намеренно
не проксируются через API тенантов: любой вызывающий, включая операторов
платформы, получает 403 — not available through the tenant API. Выполняйте их
непосредственно на хосте движка.
Планировщик
/dashboard/admin/scheduler показывает cron-задачи платформы и историю их
запусков:
- Задачи — имя, расписание (или «every tick»), последний запуск (или «never run»), индикатор статуса (включая пометку о деструктивности) и длительность. Задачи упорядочены по имени.
- Недавние запуски — последние 100 запусков: время, задача, триггер, статус, длительность и ошибка.
- Run now — запускает задачу вручную. Ручной запуск для журнала аудита приписывается активной организации вызывающего, поэтому экран сначала требует выбрать активную организацию; результат (причина, по которой задача не запустилась, или ошибка) выводится прямо на месте.
- Кнопка Refresh в заголовке и перекрёстная ссылка Raw resources.
Глубина очереди Cloudflare Queue намеренно не показывается: Worker не может инспектировать собственную очередь или очередь недоставленных сообщений во время выполнения, а у приложения нет токена уровня аккаунта.
Сырые ресурсы
/dashboard/admin выводит каждый ресурс контракта OpenAPI в виде простых
CRUD-таблиц для команды платформы, используя ту же сессионную cookie и активную
организацию. В отличие от остального дашборда, у него собственное оформление
администратора: узкая панель выхода с подписью «Raw resources · platform team» со
ссылкой Console обратно на Overview, ссылками на Audit log, Scheduler и Models, а также
меню аккаунта. Боковая панель мерчанта скрывается именно на этом маршруте.
- Полный набор: создание / чтение / изменение / удаление — коллекции, документы, псевдонимы, наборы синонимов, наборы курирования, наборы стоп-слов, пресеты, модели NL-поиска, поисковые правила, диалоговые модели, ассистенты, модели рекомендаций и правила аналитики.
- Создание / чтение / изменение, без удаления — словари стемминга, удаление которых API не допускает (чтобы заменить словарь, импортируйте его повторно с тем же id).
- Только чтение — предложения синонимов и синглтон прав (entitlement).
- Только список — события аналитики, для которых в фильтрах обязательны и id пользователя, и имя правила.
- Эксперименты также имеют отдельное детальное представление поверх API тенантов — для отчёта по эксперименту и действий по продвижению варианта.
Медиа и голос здесь не зарегистрированы: это эндпоинты-действия без формы «вывести всё списком».
Модели
/dashboard/admin/models — каталог моделей: какая языковая модель, модель
эмбеддингов, реранжирования или распознавания речи используется для каждой
роли и какая из них выбрана по умолчанию. Каталог общий для всей платформы: одни
и те же строки действуют для всех организаций, поэтому организация читает каталог
и выбирает из него, а изменять его могут только операторы платформы
(model.create / model.update / model.delete; вызов клиента отклоняется
с кодом 403).
- Роли —
chat,embedding,vision,rerank,speller,query_rewrite,graph_extract,graph_map,graph_reduce,asrиconversation. Первые десять платформа выбирает сама; организация никогда их не указывает.chatтакже служит списком разрешённых моделей для ассистентов: ассистент может использовать только модель, которую каталог для него предлагает.conversationуправляет моделями на стороне движка, которые организация регистрирует для диалогового поиска и поиска на естественном языке (POST /conversations/models,POST /nl_search_models), — такие запросы проверяются по каталогу до того, как попадут в движок. - Добавление / назначение по умолчанию / отключение / удаление — одна запись на пару «роль + id модели», не более одной модели по умолчанию на роль (назначение новой снимает этот признак с предыдущей в той же транзакции). Отключённую запись нельзя ни выбрать, ни разрешить.
- Разрешённые модели — текущая модель каждой роли и её источник: Catalog default или Built-in — собственная модель платформы, если у роли нет включённой записи в каталоге.
Пустой каталог намеренно ничего не меняет: ничего не отклоняется — так
система работала до появления каталога. Миграция 0046_seed_model_catalog
заполняет каждую роль моделями, которые API уже использует (теми же значениями,
что и встроенные резервные), поэтому новое развёртывание начинается с явного
каталога, не меняющего поведения. Задайте в API MODEL_CATALOG_STRICT=1, чтобы
закрыть последнюю лазейку: с этим флагом пустой каталог chat отклоняет
произвольную модель вместо того, чтобы принимать любую строку. Заполните роли,
которые собираетесь предлагать, а затем включите флаг.
Матрица готовности
/dashboard/capabilities описана в обзоре консоли.
На неё нет ссылки в боковой панели: откройте URL напрямую. Второй скрытый
экран, /dashboard/ranking, — это Ranking Studio.
Средства навигации
- Переключатель организаций (вверху боковой панели) — показывает активную организацию и позволяет переключиться на другую или создать новую; переключение меняет то, что читает и записывает каждый экран.
- Палитра команд (⌘K / Ctrl-K или кнопка поиска на мобильных устройствах) — переход к любому экрану, коллекциям организации и нескольким стартовым действиям (новая коллекция, импорт документов, пробный поиск, новый API-ключ). Она скрывает пункты только для платформы и только для администраторов, которые недоступны аккаунту, и запоминает недавно посещённые страницы в браузере.
- Колокольчик уведомлений — число открытых оповещений, обновляется каждую минуту, ведёт на Оповещения и SLO. Оповещения — единственная лента событий, которую предоставляет API; в API нет состояния прочтения для отдельного пользователя, поэтому признак «просмотрено» хранится в браузере.
- Баннеры квоты и подписки — отображаются над экраном, когда API приостановлен, квота исчерпана, кошелёк пуст или темп расхода приближается к лимиту, а также для пробных, просроченных и отменённых подписок. Баннеры приводят те же цифры, что и экраны Usage и Billing, и скрыты на этих двух экранах, где полная информация и так видна.