prompt_settings — core-ORM (singleton) с CRUD в Admin,
как PlatformSettings. Дефолты обоих блоков — seed-константы в коде,
NULL = «взять дефолт». Тут — хранение, кап токенов и
сброс; саму подстановку prompt в запрос модели держит и тестирует
Query Engine.
PlatformSettingsFactory,
NotificationChannelFactory,
PromptSettingsFactory
@pytest.mark.unit, @pytest.mark.integration —
общие
Mars/Olympus) → rejectru | en → reject@parametrize access / refresh / session_absolute < 0 → reject@parametrize TTL = 0 → reject (CHECK > 0)красный) → rejectdark | light → rejectkind=webhook без url/preset → rejectkind=in_app|email → preset/url запрещеныsync|security|budget|system|discovery → rejectinfo|warning|critical → rejectsafety_text / org_text в пределах капа → схема проходитNone допустимы → блок берёт встроенный дефолт'' ≠ None: либо нормализуется в None (сброс), либо reject — без «пустого» override{org_name} / {today} (или без них) → схема проходит: оба токена необязательны{foo} → reject: whitelist закрыт, буквальный {…} в prompt не утекаетVALIDATION_ERRORlocale=fr → 422 VALIDATION_ERRORaccess_token_ttl=-1 → 422 VALIDATION_ERRORMETHOD_NOT_ALLOWEDMETHOD_NOT_ALLOWEDupdated_at строго больше предыдущегоdaily / weekly → 200; иное (hourly) → 422 (CHECK)curation_weekday BETWEEN 0 AND 6 задан только при weekly; при daily он NULL, ненулевой → 422; weekday=7 → 422@parametrize ≤ 0 → 422 (CHECK > 0); положительное → 200@parametrize ≤ 0 → 422 (CHECK > 0); положительное → 200true/false → 200, значение в singleton; не-булево → 422/mcp отклонён до проверки ключа — закрытая дверь MCPRetry-After (недоступность временная)maintenance_mode в singleton); Admin/Member PATCH → 403 FORBIDDENis_builtin, неудаляемыurl_enc / secret_enc не возвращаются наружуCONFLICTenabled в БДlocked + CHECK enabled OR NOT locked) → 422 · прочие маршруты выключаются свободноFORBIDDEN на бэкенде (не только фронтовое read-only); аноним → 401 UNAUTHORIZEDFORBIDDEN; аноним → 401 UNAUTHORIZEDurl_enc / secret_enc не отдаются ни в списке, ни в детали — только признак наличияenabled=false → его deliveries не создаются; активные каналы доставленыenabled=false) → reject (CHECK)in_app_enabled / email_enabled раздельно гасят свой канал по типуdedup_key в окне → одна строка, dedup_count растёт, last_seen_at двигается; за окном — новая строкаread_at, unread-счётчик уменьшаетсяfailed, in_app доставленоnullis_default=true; после PATCH блока → false; фронт по флагу метит «на дефолте» и гасит «Сбросить»locale=en → effective-дефолт по-английски; ru → по-русски; override пуст в обоих{foo} → 422 VALIDATION_ERROR; {org_name}/{today} → 200org_text → 200, в БД сохранён; safety_text не тронутNULL, GET снова отдаёт встроенный дефолтVALIDATION_ERRORupdated_by = текущий админ; updated_at строго большеMETHOD_NOT_ALLOWEDFORBIDDENagent_weekly_token_budget · chat_weekly_token_budget → 200, значения в singletonai_monthly_budget + ai_budget_alert_enabled → 200; включить флаг без суммы → 422 (CHECK); порог достигнут → уведомление типа Budget, запрос не блокируется@parametrize ≤ 0 → 422 (CHECK > 0); null → без лимитаSUM(agent_runs.tokens_used) по agents.user_id за окно неделиSUM(messages.tokens_used) по conversations.user_id, только assistantmodel_usage) к пользователю не привязаны — в суммы не попадаютchat_weekly_token_budget → индикатор «сверх», запрос не блокируется (v1)messages.modelmodel_usage (модель · функция, вход/выход, стоимость) — org-уровень, к людям не привязан; топ-5 по стоимости, остальные за «Показать все»SUM(model_usage) за неделю / месяц / год (все функции, токены + $); производное, без таблицы-счётчика; @parametrize по окнуai_monthly_budgetFORBIDDENFORBIDDENUNAUTHORIZEDerrors[] у соответствующих полейauth.test) → чип статусаslack_settings.enabled; off → бот не отвечаетsetWebhook, вручную не вводится — в ответе/UI не возвращаютсяgetMe) → чип статуса + bot_usernametelegram_settings.enabled; off → бот не отвечаетusers/me) → чип статуса + хэндл ботаmattermost_settings.enabled; включение атомарно — живая проверка, отказ → 409 и переключатель откатывается; off → бот не отвечаетenabled; in-app тумблер залочен (disabled)null, блок показывает встроенный дефолтis_default=true → блок помечен «на дефолте», «Сбросить» погашена; после правки флаг false → кнопка активнаplatform_settingsread_at IS NULL); клик открывает панель хвоста событийread_at, счётчик обнуляется
Бэкенд тонкий (PlatformSettings CRUD), основная логика — фронтенд.
User management и audit log API покрыты в auth-security — здесь только
UI поверх них. Экраны данных/AI (Агенты, AI-модели, Инструменты,
Расходы, Harvester, Knowledge Store) и лента уведомлений покрыты
FE-карточками здесь — только React-компонент и его guarded-действия;
доменную бэкенд-логику держат и тестируют сами модули. Приоритет
(P0–P1) ортогонален каталогам и задаётся маркерами
(pytest -m p0), а не папками.
tests/backend — общий каркас
conftest.pyБД, сессия, app client (уже есть)factories/фабрики данных
admin.pyPlatformSettingsFactory · NotificationChannelFactory · PromptSettingsFactoryadmin/каталог модуля
conftest.pyadmin fixtures, admin_clientunit/без БД
test_settings_schema.pyPydantic DTOtest_notification_schema.pyканалы · маршруты · payloadtest_prompt_schema.pyprompt_settings DTO · кап токеновintegration/с БД
test_platform_settings.pyCRUD · validation · singleton CHECKtest_maintenance.py503 · allow-list · пауза sync/агентовtest_admin_access.pyrole-based accesstest_notifications.pychannels · routes · dispatch · deliverytest_prompt_settings.pyoverride · reset · cap · singletonfrontend/…/admin/__tests__/рядом с кодом
AdminLayout.test.tsxsidebar · role · toggles · logoutPlatformSettings.test.tsxform · save · validation · statesUsersPage.test.tsxlist · tabs · invite · actionsUserDetailPage.test.tsxprofile · role · actions · RBACAuditLogPage.test.tsxtable · filters · statesNotificationsPage.test.tsxchannels · matrix · recipientsAiBehaviorPage.test.tsxbubbles · edit · reset · cap · tooltipListControls.test.tsxshared: search threshold · reset page · facets · clampAgentsPage.test.tsxpause · resume · limits (guarded)AiModelsPage.test.tsxchange & reembed · disable (guarded)ToolsPage.test.tsxchat/agents toggles · configure · testUsagePage.test.tsxslices · window · → detailHarvesterPage.test.tsxrun · pause source (guarded)KnowledgeStorePage.test.tsxcuration · backups (guarded)NotificationFeed.test.tsxbell · read/unread · в scope · unread-facet