Skip to content

Feature/team management - #130

Merged
Mikelarg merged 9 commits into
mainfrom
feature/team-management
Jul 15, 2026
Merged

Feature/team management#130
Mikelarg merged 9 commits into
mainfrom
feature/team-management

Conversation

@Mikelarg

Copy link
Copy Markdown
Collaborator

Draft / RFC — открыто для обсуждения. Готов разбить на части и доработать под требования проекта.

Мотивация

Сейчас онбординг участника в self-hosted GigaAgent — ручной: админ создаёт пользователя с паролем, а доступы к LLM/коннекторам раздаются точечно. Для командного использования («настроил один раз — команда работает», как в Claude Enterprise) не хватает приглашений, ролей и шаринга по умолчанию.

Что в PR

Дизайн-принцип: инстанс = одна команда. Никакой мульти-тенантности — всё строится поверх существующих Group и ResourcePermission, схема которых не менялась.

1. Роли (owner / admin / member)

  • User.role — источник правды; is_superuser сохранён и поддерживается синхронно → существующие проверки работают без изменений.
  • Миграция с бэкфиллом: superuser'ы → admin, самый ранний → owner.
  • Защита owner'а: менять/передавать владение может только owner; создать owner'а нельзя (только передача).

2. Приглашения по ссылке (core_invites)

  • В БД хранится только SHA-256 хэш токена; персональные (max_uses=1) и командные (max_uses=N) ссылки; TTL; отзыв; опциональная привязка к email.
  • Публичная страница /join/<token>: форма → аккаунт → авто-вход.
  • Онбординг «вошёл и работает»: опциональное копирование runtime-ссылок создателя + read-права (та же механика, что в админ-создании юзера).
  • Единый 404 без оракула (нет/просрочен/исчерпан неразличимы), row-lock против гонки used_count.

3. Системная группа All Members

  • Создаётся на старте, членство автоматическое (бэкфилл + UserCreatedEvent), удаление/исключение запрещены.
  • Тумблер «Доступно команде» в компоненте ResourcePermissions — один клик = read-право группы. Автоматически появился на всех карточках (LLM, коннекторы, эмбеддинги, генераторы, песочницы, RAG-коллекции).

4. Учёт использования

  • core_usage_events + UsageTrackingMiddleware (fire-and-forget, ошибки учёта не влияют на поток).
  • GET /auth/team/usage?days=N + колонка «Токены (30д)» в админке.

5. UI

  • Админка: вкладка «Приглашения» (создание/статусы/отзыв, ссылка показывается один раз), селект роли в формах пользователя.

Тестирование (всё E2E на живом инстансе)

  • Вступление по ссылке через браузер: форма → авто-логин → приложение.
  • Повтор исчерпанной ссылки → 404; member не допускается в админку.
  • Шаринг: member без скопированных настроек видит расшаренный LLM.
  • RAG: до шаринга — 403 и пустой список; после — видит коллекцию, семантический поиск по чужому документу работает, запись отбивается 403 (read ≠ write). Достигнуто нулём нового кода — только существующий ACL.
  • Usage: вызов → журнал → агрегат → колонка.

Открытые вопросы

  1. Разбивка: роли+инвайты отдельно от usage — если так удобнее ревьюить.
  2. Судьба is_superuser: держим синхронным или планово выпиливаем.
  3. Передача владения — сейчас только через PATCH role owner'ом; нужен ли отдельный UX.
  4. Квоты per-user поверх core_rate_limits — вне скоупа, но напрашивается.

🤖 Generated with Claude Code

nyddle and others added 9 commits July 15, 2026 03:39
- User.role — источник правды; is_superuser поддерживается синхронно
  для обратной совместимости существующих проверок.
- Миграция с бэкфиллом: superuser'ы → admin, самый ранний → owner.
- require_role() по иерархии member < admin < owner.
- Админ-PATCH: поле role, защита owner'а (менять/передавать владение
  может только owner), легаси-синк из is_superuser.
- Bootstrap первого пользователя — сразу owner.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Модель core_invites: в БД только SHA-256 хэш токена; персональные
  (max_uses=1) и командные (max_uses=N) ссылки; TTL; отзыв; привязка
  к email; роль и группы для вступающего.
- API: POST/GET/DELETE /invites (admin+), публичные GET/POST /join —
  вступление с созданием юзера, авто-логином и онбордингом «вошёл
  и работает» (копия runtime-ссылок создателя + read-права, как в
  админ-создании пользователя).
- Безопасность: единый 404 для несуществующих/просроченных/исчерпанных
  токенов, row-lock против гонки used_count, транзакционность.

Проверено E2E: логин → инвайт → join-info → вступление (member, llm
скопирован) → повторное использование отбито 404.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- core/team.py: создание группы на старте (идемпотентно), бэкфилл всех
  пользователей, авто-членство новых по UserCreatedEvent.
- Гарды в groups-роутах: системную группу нельзя удалить, участников
  нельзя исключать.
- Ресурс, расшаренный на All Members (ResourcePermission read) =
  «доступен команде» — тумблер в UI подключим на шаге 4.

Проверено E2E: группа создана с бэкфиллом owner'а; вступивший по
инвайту автоматически в группе; оба гарда отдают 422.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Публичная страница /join/<token>: проверка инвайта, форма
  имя/email/пароль×2, создание аккаунта и авто-вход.
- Админка → вкладка «Приглашения»: список со статусами
  (активно/использовано/истекло/отозвано), создание с ролью/сроком/
  лимитом использований, ссылка показывается один раз с копированием,
  отзыв.
- Фикс ApiProvider: фоновые 401 на публичных страницах (/join, /login)
  больше не редиректят на логин и не показывают «Сессия истекла».

Проверено в браузере E2E: форма → вступление → авто-логин → приложение;
member не допускается в админку; вкладка рендерится, инвайт в таблице.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Один клик в ResourcePermissions добавляет/убирает read-право группы
All Members — ресурс (LLM/коннектор/эмбеддинги/генератор/песочница)
становится доступен всей команде. Виден без разворачивания секции
прав; появляется на всех карточках, использующих компонент.

Проверено E2E в браузере: тумблер на карточке GigaChat-2-Max →
сохранение → право в core_resource_permissions; новый member,
вступивший по инвайту БЕЗ копирования настроек, видит расшаренный
LLM в GET /llms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- core_usage_events: одна строка = один вызов модели (user, model,
  input/output tokens). UsageTrackingMiddleware пишет usage_metadata
  каждого ответа fire-and-forget — ошибки учёта не влияют на поток.
- GET /auth/team/usage?days=N (admin+): агрегат по пользователям
  (запросы, токены, последняя активность).
- Админка → Пользователи: колонка «Токены (30д)» с деталями в тултипе;
  бейдж роли показывает реальную роль (owner/admin/member).

Проверено: симулированный вызов → строка в журнале → корректный
агрегат в API → колонка в UI (скриншот).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Формы админки: селект роли (member/admin) вместо свитча
  «Суперпользователь»; owner отображается, но не редактируется
  (владение только передаётся).
- create_user: явная role в приоритете над легаси is_superuser;
  создание owner'а запрещено (422).

Проверено: POST role=admin → role+is_superuser синхронны;
POST role=owner → 422.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- moved prefill users to default group to migrations
- added helper how to connect to telegram
@Mikelarg
Mikelarg merged commit a1b3b32 into main Jul 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants