Справочник API: тенанты (пространства) и участники
Управление рабочими пространствами, участниками, приглашениями, API Key и журналом аудита. Операции действуют на текущее активное пространство; кросс-пространственный доступ проверяется по правам эндпоинта.
Все маршруты /tenants/:id/* на уровне группы используют PathTenantMatch() (internal/middleware/access.go): :id в URL должен равняться текущему активному пространству (исключение — кросс-пространственный суперадмин), что предотвращает несанкционированные операции над чужими пространствами.
Поля конфигурации memory_config тенанта и личные эндпоинты памяти см. в API долговременной памяти. При обновлении конфигурации администратор пространства отправляет полный объект, который нужно сохранить.
Жизненный цикл пространства
POST /api/v1/tenants
Назначение: создание пространства (самостоятельное открытие нового рабочего пространства; вызывающий автоматически становится Owner). Права: любой авторизованный пользователь (может быть без пространства); API key — только platform key с system_tenants_manage. Handler: internal/handler/tenant.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
name | string | Да (binding:"required,min=1,max=128") | Название пространства |
description | string | Нет (binding:"max=512") | Описание |
Кросс-пространственный суперадмин может отправить полный types.Tenant (включая storage_quota, status и т. п.).
Ответ: 201 {"success":true,"data":{Tenant}} (при разрешающей конфигурации может нести api_key). Если самостоятельное создание запрещено, возвращается 403 (code 2005); при превышении квоты — 429.
curl -X POST $BASE/api/v1/tenants -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"Моё пространство"}'GET /api/v1/tenants
Назначение: список пространств, к которым у меня есть доступ. Права: требуется вход; API key требует manage_tenant_settings или full-access. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"data":{"items":[TenantResponse]}}
curl $BASE/api/v1/tenants -H "Authorization: Bearer $TOKEN"GET /api/v1/tenants/all
Назначение: список всех пространств (кросс-пространственный суперадмин). Права: CrossTenant() (CanAccessAllTenants и включённый в кластере EnableCrossTenantAccess); platform key требует system_tenants_read|manage. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"data":{"items":[TenantResponse]}}
curl $BASE/api/v1/tenants/all -H "Authorization: Bearer $TOKEN"GET /api/v1/tenants/search
Назначение: поиск пространств по ключевому слову (кросс-пространственный суперадмин). Права: как выше. Handler: internal/handler/tenant.go
| Параметр запроса | Тип | Обязательный | Описание |
|---|---|---|---|
keyword | string | Нет | Ключевое слово |
tenant_id | string | Нет | Точный ID пространства |
page / page_size | int | Нет | Пагинация (по умолчанию 1/20, верхняя граница 100) |
Ответ: 200 {"success":true,"data":{"items":[...],"total","page","page_size"}}
curl "$BASE/api/v1/tenants/search?keyword=demo&page=1" -H "Authorization: Bearer $TOKEN"GET /api/v1/tenants/:id
Назначение: сведения о пространстве. Права: Viewer+; platform key требует system_tenants_read|manage. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"data":{TenantResponse}}
curl $BASE/api/v1/tenants/1 -H "Authorization: Bearer $TOKEN"PUT /api/v1/tenants/:id
Назначение: обновление конфигурации пространства. Права: Owner; platform key требует system_tenants_manage. Handler: internal/handler/tenant.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
name | *string | Нет (binding:"omitempty,min=1,max=128") | Новое название |
description | *string | Нет (binding:"omitempty,max=512") | Новое описание |
Ответ: 200 {"success":true,"data":{TenantResponse}}
curl -X PUT $BASE/api/v1/tenants/1 -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"Новое имя"}'DELETE /api/v1/tenants/:id
Назначение: удаление пространства. Права: Owner; platform key требует system_tenants_manage. Запись пространства и все членства мягко удаляются, участники сразу теряют доступ; данные пространства — базы знаний, модели и т. п. — не удаляются физически немедленно, а стоящие в очереди задачи Wiki удалённого пространства больше не вызывают модель. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"message":"Workspace deleted successfully"}
curl -X DELETE $BASE/api/v1/tenants/1 -H "Authorization: Bearer $TOKEN"KV-конфигурация пространства
:key — это ключ конфигурации, а не ID пространства (пространство берётся из контекста аутентификации); возможные значения: web-search-config, prompt-templates, parser-engine-config, storage-engine-config, chat-history-config, retrieval-config, memory-config, assistant-config.
assistant-config — настройки помощника aihelpme.ru для пространства: display_name (имя помощника в интерфейсе, не более 24 знаков; пусто — имя по умолчанию) и max_access_level (максимальный уровень доступа, доступный участнику: read_only — только чтение, confirm — подтверждение перед изменением, auto_write — необратимые изменения выполняются сразу, удаление всё равно требует подтверждения; по умолчанию confirm). Участник выбирает свой уровень полей assistant_access в запросе диалога, сервер обрезает его по верхней границе пространства.
GET /api/v1/tenants/kv/:key
Назначение: чтение KV-конфигурации уровня пространства. Права: Viewer+; API key требует manage_tenant_settings или full-access. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"data":{...соответствующий объект конфигурации...}}
curl $BASE/api/v1/tenants/kv/retrieval-config -H "Authorization: Bearer $TOKEN"PUT /api/v1/tenants/kv/:key
Назначение: обновление KV-конфигурации уровня пространства. Права: Admin+; API key требует manage_tenant_settings или full-access. Тело запроса: JSON-объект конфигурации, соответствующий :key. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"message":"Configuration updated"}
curl -X PUT $BASE/api/v1/tenants/kv/web-search-config -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"enabled":true}'API Key и субъект API
GET /api/v1/tenants/:id/api-keys
Назначение: список API key пространства (с маскировкой). Права: Owner, только JWT (API key по умолчанию запрещён). Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"data":[{id,scope_type,name,api_key(маскировка),full_access,knowledge_base_ids,capabilities,last_used_at,expires_at,created_at}]}
curl $BASE/api/v1/tenants/1/api-keys -H "Authorization: Bearer $TOKEN"POST /api/v1/tenants/:id/api-keys
Назначение: создание API key пространства (открытый текст возвращается только один раз). Права: Owner, только JWT. Handler: internal/handler/tenant.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
name | string | Да | Название key |
full_access | bool | Нет | Key с полными правами в пространстве (по умолчанию false) |
knowledge_base_ids | []string | Нет | Белый список KB (scoped key) |
capabilities | []string | Нет | Список capability (см. обзор) |
expires_at_unix | *int64 | Нет | Метка времени истечения |
Ответ: 201 {"success":true,"data":{...,"api_key":"<открытый текст>","token":"<открытый текст>"}}
curl -X POST $BASE/api/v1/tenants/1/api-keys -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"ingest-bot","capabilities":["ingest","retrieve"],"knowledge_base_ids":["kb-1"]}'PUT /api/v1/tenants/:id/api-keys/:key_id
Owner, только JWT. Обновляет name, full_access, knowledge_base_ids, capabilities, expires_at_unix существующего Key; поля авторизации отправляются как полный набор конфигурации; это не PATCH для изменения одного поля. Пропуск или null в expires_at_unix очищает существующее время истечения. После изменения прав используется тот же token; новые права вступают в силу при последующей аутентификации, открытый текст заново не возвращается.
Возвращает 200 {success,data:APIKeyResponse}, Key маскируется; недопустимые способности/область баз знаний возвращают 400, отсутствие — 404.
curl -X PUT "$BASE/api/v1/tenants/1/api-keys/5" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"search-bot","full_access":false,"knowledge_base_ids":["kb-1"],"capabilities":["retrieve"]}'DELETE /api/v1/tenants/:id/api-keys/:key_id
Назначение: удаление API key. Права: Owner, только JWT. Параметр пути: key_id.
Ответ: 200 {"success":true}
curl -X DELETE $BASE/api/v1/tenants/1/api-keys/5 -H "Authorization: Bearer $TOKEN"GET /api/v1/tenants/:id/api-principal-config
Назначение: чтение конфигурации субъекта внешнего пользователя API. Права: Owner, только JWT. Handler: internal/handler/tenant.go
Ответ: 200 {"success":true,"data":{"mode":"tenant|direct|signed_token","direct_header_name","signed_token_header_name","require_direct_header","has_hmac_secret"}}
curl $BASE/api/v1/tenants/1/api-principal-config -H "Authorization: Bearer $TOKEN"PUT /api/v1/tenants/:id/api-principal-config
Назначение: обновление конфигурации субъекта внешнего пользователя API. Права: Owner, только JWT.
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
mode | string | Да | tenant / direct / signed_token |
require_direct_header | bool | Нет | Обязателен ли Header в режиме direct |
hmac_secret | *string | Нет | Секрет режима signed_token (при передаче *** сохраняется прежнее значение) |
Ответ: 200, как у GET.
curl -X PUT $BASE/api/v1/tenants/1/api-principal-config -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"mode":"signed_token","hmac_secret":"topsecret"}'POST /api/v1/tenants/:id/api-principal-test-token
Назначение: выдача JWT внешнего пользователя для тестирования. Права: Owner, только JWT.
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
external_user_id | string | Да | ID внешнего пользователя (≤128 символов) |
expires_in_seconds | int | Нет | 1-3600, по умолчанию 900 |
Ответ: 200 {"success":true,"data":{"token","header_name","expires_in_seconds","expires_at_unix","external_user_id"}}
curl -X POST $BASE/api/v1/tenants/1/api-principal-test-token -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"external_user_id":"u-123"}'Управление участниками (/tenants/:id/members)
Handler: internal/handler/tenant_member.go. API key требует manage_members или full-access.
GET /api/v1/tenants/:id/members
Назначение: список участников. Права: Viewer+.
| Параметр запроса | Тип | Обязательный | Описание |
|---|---|---|---|
q | string | Нет | Фильтр по email/имени пользователя |
page / page_size | int | Нет | Пагинация |
Ответ: 200 {"success":true,"data":{"members":[{user_id,email,username,avatar,role,status,invited_by,joined_at}],"total","page","page_size"}}
curl $BASE/api/v1/tenants/1/members -H "Authorization: Bearer $TOKEN"POST /api/v1/tenants/:id/members
Назначение: прямое добавление участника. Права: Owner.
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
email | string | Да (binding:"required,email") | Email участника (должен быть уже зарегистрирован) |
role | string | Да (binding:"required") | owner/admin/contributor/viewer |
Ответ: 201 {"success":true,"data":{объект участника}}
curl -X POST $BASE/api/v1/tenants/1/members -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"email":"b@ex.com","role":"contributor"}'PUT /api/v1/tenants/:id/members/:user_id
Назначение: изменение роли участника. Права: Owner. Тело запроса: {"role":"admin"} (binding:"required").
Ответ: 200 {"success":true}
curl -X PUT $BASE/api/v1/tenants/1/members/u-123 -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"role":"admin"}'DELETE /api/v1/tenants/:id/members/:user_id
Назначение: удаление участника. Права: Owner.
Ответ: 200 {"success":true}
curl -X DELETE $BASE/api/v1/tenants/1/members/u-123 -H "Authorization: Bearer $TOKEN"POST /api/v1/tenants/:id/leave
Назначение: выход из пространства (любой участник может выйти самостоятельно; сервисный слой отклоняет выход, приводящий к отсутствию Owner в пространстве). Права: Viewer+, только JWT.
Ответ: 200 {"success":true}
curl -X POST $BASE/api/v1/tenants/1/leave -H "Authorization: Bearer $TOKEN"Приглашения пространства (/tenants/:id/invitations и invite-links)
Handler: internal/handler/tenant_invitation.go, internal/handler/tenant_invite_link.go. API key требует manage_members или full-access.
GET /api/v1/tenants/:id/invitations
Назначение: список приглашений пространства. Права: Viewer+.
| Параметр запроса | Тип | Обязательный | Описание |
|---|---|---|---|
include_terminal | bool | Нет | Включать завершённые приглашения |
page / page_size | int | Нет | Пагинация |
Ответ: 200 {"success":true,"data":{"invitations":[{id,tenant_id,invitee_email,inviter_email,role,status,message,expires_at,is_share_link,accepted_count,...}],"total","page","page_size"}}
curl $BASE/api/v1/tenants/1/invitations -H "Authorization: Bearer $TOKEN"POST /api/v1/tenants/:id/invitations
Назначение: приглашение участника (приглашённый попадает в базу только после подтверждения в /me/invitations). Права: Owner.
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
email | string | Да (binding:"required,email") | Email приглашаемого |
role | string | Да (binding:"required") | Предоставляемая роль |
message | string | Нет | Сопроводительное сообщение |
Ответ: 201 {"success":true,"data":{TenantInvitationResponse}}
curl -X POST $BASE/api/v1/tenants/1/invitations -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"email":"c@ex.com","role":"viewer"}'DELETE /api/v1/tenants/:id/invitations/:inv_id
Назначение: отзыв приглашения. Права: Owner.
Ответ: 200 {"success":true}
curl -X DELETE $BASE/api/v1/tenants/1/invitations/12 -H "Authorization: Bearer $TOKEN"POST /api/v1/tenants/:id/invite-links
Назначение: создание ссылки общего доступа (многоразовой регистрационной ссылки-приглашения). Права: Owner. Handler: internal/handler/tenant_invite_link.go
| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
role | string | Да (binding:"required") | Роль, предоставляемая ссылкой |
message | string | Нет | Сопроводительное сообщение |
Ответ: 201 {"success":true,"data":{id,token,invite_url,role,status,expires_at,is_share_link:true,accepted_count}}
curl -X POST $BASE/api/v1/tenants/1/invite-links -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"role":"viewer"}'Журнал аудита
Handler: internal/handler/audit_log.go. Курсорная пагинация.
GET /api/v1/tenants/:id/audit-log
Назначение: журнал аудита пространства (включая записи об отклонённых операциях). Права: Admin+, только JWT.
| Параметр запроса | Тип | Обязательный | Описание |
|---|---|---|---|
after_id | int | Нет | Курсор (next_cursor из предыдущего ответа) |
limit | int | Нет | 1-100, по умолчанию 50 |
action | string | Нет | Фильтр по действию (например, rbac.member_added) |
outcome | string | Нет | success / denied |
actor | string | Нет | Фильтр по user_id действующего лица |
Ответ: 200 {"success":true,"data":[AuditLog],"next_cursor":N}
curl "$BASE/api/v1/tenants/1/audit-log?limit=50" -H "Authorization: Bearer $TOKEN"GET /api/v1/knowledge-bases/:id/activity
Назначение: поток активности одной KB (аудит только для чтения). Права: создатель KB OR Admin+, и есть право read на KB; только JWT. Параметры запроса те же (after_id/limit/action/outcome/actor). Зарегистрирован в RegisterKnowledgeBaseActivityRoutes.
Ответ: 200 {"success":true,"data":[AuditLog],"next_cursor":N}. details — полезная нагрузка действия; если запись вызвана API Key, она будет содержать api_key_id и api_key_name (снимок имени, без открытого текста Key).
curl $BASE/api/v1/knowledge-bases/kb-1/activity -H "Authorization: Bearer $TOKEN"Справочник по реализации
Регистрация маршрутов: RegisterTenantRoutes в internal/router/routes_auth_tenant.go. Handler: internal/handler/tenant.go, internal/handler/tenant_member.go, internal/handler/tenant_invitation.go, internal/handler/tenant_invite_link.go, internal/handler/audit_log.go.
