Skip to content

feat(BA-5022): K8s bridge multi-tenant access control API extensions#10765

Open
hhoikoo wants to merge 5 commits intomainfrom
feat/BA-5022/k8s-bridge-access-control
Open

feat(BA-5022): K8s bridge multi-tenant access control API extensions#10765
hhoikoo wants to merge 5 commits intomainfrom
feat/BA-5022/k8s-bridge-access-control

Conversation

@hhoikoo
Copy link
Copy Markdown
Member

@hhoikoo hhoikoo commented Apr 3, 2026

Summary

API extensions to support Kubernetes Bridge multi-tenant access control (kubernetes-bridge#231).

These changes enable the K8s bridge driver to:

  1. Resolve K8s usernames to Backend.AI users via integration_name lookup
  2. Validate group memberships for namespace-level access control
  3. Set/clear external integration identifiers on user, domain, and group records

Changes

  • DTOs: Add integration_name to UpdateUserRequest, UserDTO, UserFilter; add groups array to UserDTO; add v2 user DTOs
  • Data types: Add integration_name and groups to UserData; add UserGroupMembership
  • ORM: Wire integration_id through to_data()
  • Conditions: Add UserConditions with integration_name filter support
  • DB source: JOIN association_groups_users + groups for group membership loading
  • Repository: Add get_group_memberships() method
  • Adapter: Wire new fields through convert_to_dto(), build_updater(), _convert_filter()
  • GraphQL: Add integrationName filter to UserV2Filter; rename integrationId to integrationName on domain/group types
  • Group updater: Change GroupUpdaterSpec.integration_name from OptionalState to TriState so that setting it to null clears the DB column (aligns with domain updater behavior)

No new database columns, no new endpoints, no new dependencies. All changes confined to the REST/GraphQL API layer.

Test plan

  • Unit tests for user v2 DTOs (request/response serialization)
  • Unit tests for user adapter (convert_to_dto, build_updater, convert_filter)
  • Unit tests for UserConditions (integration_name filter)
  • Unit tests for user updaters (integration_name field)
  • Existing domain/group/resource_group tests updated for integration_id to integration_name rename
  • CI passes on all lint, type check, and test targets

Copilot AI review requested due to automatic review settings April 3, 2026 02:36
@github-actions github-actions bot added size:L 100~500 LoC area:docs Documentations comp:manager Related to Manager component comp:common Related to Common component labels Apr 3, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extends the Manager API surface to support Kubernetes Bridge multi-tenant access control by exposing an external user integration identifier (integration_name) end-to-end (mapped to the existing DB integration_id column), adding integration_name filtering across REST/GraphQL, and returning user group memberships in the admin user detail response.

Changes:

  • Add integration_name to user/domain/group/resource-group v2 DTOs and wire create/update/filter logic through adapters, conditions, and repository specs (DB column remains integration_id).
  • Add integration_name search filtering to REST (v1/v2) and GraphQL user search.
  • Add group memberships (groups) to GET /admin/users/{id} by introducing UserDetail and loading memberships in the user repository DB source.

Reviewed changes

Copilot reviewed 74 out of 74 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/manager/services/user/test_user_service.py Update user service unit test to expect UserDetail from get_user.
tests/unit/manager/services/test_group.py Rename group integration_idintegration_name in service tests.
tests/unit/manager/services/test_domain.py Rename domain integration_idintegration_name in service tests.
tests/unit/manager/services/group/test_group_service.py Update group service fixture to use integration_name.
tests/unit/manager/services/domain/test_domain_service.py Update domain service fixture to use integration_name.
tests/unit/manager/repositories/user/test_user_updaters.py Add unit tests for integration_name TriState mapping to DB integration_id.
tests/unit/manager/repositories/group/test_group_repository.py Update group repository tests to use integration_name.
tests/unit/manager/repositories/domain/test_domain_repository.py Update domain repository tests for integration_name rename.
tests/unit/manager/repositories/auth/test_auth_repository.py Update auth repository tests to populate integration_name from ORM integration_id.
tests/unit/manager/models/user/test_conditions.py Add tests for UserConditions integration-name string matching factories.
tests/unit/manager/api/user/test_adapter.py Add adapter tests for integration_name user search filters.
tests/unit/manager/api/group/test_group_node.py Update group node tests to use integration_name.
tests/unit/manager/api/gql/test_project_v2_types.py Update v2 project GraphQL type tests to integration_name.
tests/unit/manager/api/gql/test_domain_v2_types.py Update v2 domain GraphQL type tests to integration_name.
tests/unit/manager/api/adapters/test_user_adapter.py New tests for v2 UserAdapter group-membership mapping.
tests/unit/common/dto/manager/v2/user/test_response.py Add integration_name and groups coverage for v2 user response DTOs.
tests/unit/common/dto/manager/v2/user/test_request.py Add integration_name to v2 user request DTO tests and filter tests.
tests/unit/common/dto/manager/v2/resource_group/test_response.py Update v2 resource-group response DTO tests to integration_name.
tests/unit/common/dto/manager/v2/resource_group/test_request.py Update v2 resource-group request DTO tests to integration_name.
tests/unit/common/dto/manager/v2/group/test_response.py Update v2 group response DTO tests to integration_name.
tests/unit/common/dto/manager/v2/group/test_request.py Update v2 group request DTO tests to integration_name.
tests/unit/common/dto/manager/v2/domain/test_response.py Update v2 domain response DTO tests to integration_name.
tests/unit/common/dto/manager/v2/domain/test_request.py Update v2 domain request DTO tests to integration_name.
src/ai/backend/manager/services/user/service.py Change get_user service to return UserDetail (with group memberships).
src/ai/backend/manager/services/user/actions/get_user.py Update GetUserActionResult to carry UserDetail.
src/ai/backend/manager/repositories/user/updaters.py Add integration_name TriState to user updater spec mapped to integration_id.
src/ai/backend/manager/repositories/user/repository.py Add repository method get_user_detail_by_uuid.
src/ai/backend/manager/repositories/user/db_source/db_source.py Implement group-membership eager loading for user detail query.
src/ai/backend/manager/repositories/user/creators.py Add integration_name to user creator spec mapped to DB integration_id.
src/ai/backend/manager/repositories/group/updaters.py Rename group updater field to integration_name mapped to DB integration_id.
src/ai/backend/manager/repositories/group/creators.py Rename group creator field to integration_name mapped to DB integration_id.
src/ai/backend/manager/repositories/domain/updaters.py Rename domain updater field to integration_name mapped to DB integration_id.
src/ai/backend/manager/repositories/domain/creators.py Rename domain creator field to integration_name mapped to DB integration_id.
src/ai/backend/manager/repositories/auth/db_source/db_source.py Map auth-layer UserData.integration_name from ORM integration_id.
src/ai/backend/manager/models/user/row.py Populate UserData.integration_name in UserRow.to_data().
src/ai/backend/manager/models/user/conditions.py Add integration-name query condition factories (backed by integration_id).
src/ai/backend/manager/models/group/row.py Rename group data/model sensitive attribute to integration_name.
src/ai/backend/manager/models/domain/row.py Rename domain data/model sensitive attribute to integration_name.
src/ai/backend/manager/models/domain/conditions.py Rename domain integration filter factories to integration_name.
src/ai/backend/manager/data/user/types.py Add integration_name, UserGroupMembership, and UserDetail dataclasses.
src/ai/backend/manager/data/group/types.py Rename group data/modifier field to integration_name.
src/ai/backend/manager/data/domain/types.py Rename domain data/modifier field to integration_name.
src/ai/backend/manager/data/auth/types.py Rename auth-layer integration_id field to integration_name.
src/ai/backend/manager/api/rest/user/handler.py Adapt REST user handler to UserDetail shape (result.user.user).
src/ai/backend/manager/api/rest/user/adapter.py Add REST v1 user search filter conversion for integration_name.
src/ai/backend/manager/api/rest/domain/handler.py Bridge v1 domain DTO integration_id to internal integration_name.
src/ai/backend/manager/api/rest/domain/adapter.py Bridge internal integration_name back to v1 domain DTO integration_id.
src/ai/backend/manager/api/gql/user/types/filters.py Add v2 GraphQL integrationName user filter field with version metadata.
src/ai/backend/manager/api/gql/project_v2/types/nested.py Rename v2 project GraphQL field to integration_name.
src/ai/backend/manager/api/gql/project_v2/types/mutations.py Rename v2 project GraphQL inputs to integration_name.
src/ai/backend/manager/api/gql/domain_v2/types/nested.py Rename v2 domain GraphQL field to integration_name.
src/ai/backend/manager/api/gql/domain_v2/types/mutations.py Rename v2 domain GraphQL inputs to integration_name.
src/ai/backend/manager/api/gql_legacy/group.py Bridge legacy GraphQL integration_id to internal integration_name.
src/ai/backend/manager/api/gql_legacy/domain.py Bridge legacy GraphQL integration_id to internal integration_name.
src/ai/backend/manager/api/adapters/user.py Wire user integration_name, group memberships, and filters through v2 adapter.
src/ai/backend/manager/api/adapters/resource_group.py Rename v2 resource-group node field to integration_name.
src/ai/backend/manager/api/adapters/project.py Rename v2 project adapter plumbing to integration_name.
src/ai/backend/manager/api/adapters/domain.py Rename v2 domain adapter plumbing to integration_name.
src/ai/backend/common/dto/manager/v2/user/response.py Add integration_name and groups to v2 user response DTOs.
src/ai/backend/common/dto/manager/v2/user/request.py Add integration_name to v2 user request DTOs and filters.
src/ai/backend/common/dto/manager/v2/user/init.py Export UserGroupMembershipInfo in v2 user DTO module.
src/ai/backend/common/dto/manager/v2/resource_group/response.py Rename v2 resource-group response field to integration_name.
src/ai/backend/common/dto/manager/v2/resource_group/request.py Rename v2 resource-group request field to integration_name.
src/ai/backend/common/dto/manager/v2/group/response.py Rename v2 group response field to integration_name.
src/ai/backend/common/dto/manager/v2/group/request.py Rename v2 group request field to integration_name.
src/ai/backend/common/dto/manager/v2/domain/response.py Rename v2 domain response field to integration_name.
src/ai/backend/common/dto/manager/v2/domain/request.py Rename v2 domain request field to integration_name.
src/ai/backend/common/dto/manager/user/request.py Add v1 REST user filter field integration_name.
docs/manager/graphql-reference/v2-schema.graphql Update v2 schema docs for integrationName and user filter field.
docs/manager/graphql-reference/supergraph.graphql Update supergraph docs for integrationName and user filter field.
changes/10645.enhance.md Changelog entry for integration_idintegration_name rename above model layer.
changes/10613.feature.md Changelog entry for user search integration_name filter.
changes/10612.feature.md Changelog entry for user detail group memberships.
changes/10610.feature.md Changelog entry for user integration identifier API exposure.
Comments suppressed due to low confidence (1)

src/ai/backend/common/dto/manager/v2/resource_group/request.py:113

  • The field description says “Use SENTINEL to clear, null to keep existing value”, but in this DTO layer SENTINEL represents “field omitted / no-op” while explicit null typically indicates clearing (as used in other v2 update DTOs). This description is likely inverted and will mislead API consumers—please correct it (and keep consistent wording across the other Sentinel-based fields in this DTO).
    integration_name: str | Sentinel | None = Field(
        default=SENTINEL,
        description=(
            "Updated external integration ID. Use SENTINEL to clear, null to keep existing value."
        ),
    )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ring

GroupUpdaterSpec.integration_name was using OptionalState which cannot
represent "clear to NULL". The domain updater already uses TriState
correctly. Align the group/project adapter and updater to use TriState
so that setting integration_name to null actually clears the DB column.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:docs Documentations comp:common Related to Common component comp:manager Related to Manager component size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants