-
Notifications
You must be signed in to change notification settings - Fork 163
feat(BA-4361): Add entity graph and scope-entity type converters #8739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Add ENTITY_GRAPH, get_relation_type, scope_type_to_entity_type/entity_type_to_scope_type converters with InvalidTypeConversionError. Add missing EntityType values and scope/entity maps. Co-Authored-By: Claude Opus 4.6 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds shared permission-type utilities to support RBAC entity relationships and conversions between ScopeType and EntityType, along with corresponding unit tests.
Changes:
- Introduces an
ENTITY_GRAPHdescribing parent→child entity edges and aget_relation_type()helper. - Adds
scope_type_to_entity_type()/entity_type_to_scope_type()converters plusInvalidTypeConversionError. - Expands
EntityTypewith several missing values and re-exports new APIs through manager permission types; adds unit tests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
tests/unit/manager/rbac/test_permission_types.py |
Adds tests for ENTITY_GRAPH, relation lookup helper, and scope/entity converters. |
src/ai/backend/manager/data/permission/types.py |
Re-exports new common permission graph/mapping utilities for manager-side imports. |
src/ai/backend/common/data/permission/types.py |
Implements entity graph, relation lookup helper, scope/entity converters, and adds new EntityType values. |
src/ai/backend/common/data/permission/exceptions.py |
Adds InvalidTypeConversionError exception type. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _get_entity_children(parent: EntityType) -> dict[EntityType, RelationType]: | ||
| """Return the children of a parent entity type with their relation types. | ||
|
|
||
| Every EntityType value must have an explicit case to ensure exhaustive coverage. | ||
| """ | ||
| match parent: |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_get_entity_children() is annotated to always return dict[...], but the match statement has no default (case _) branch. If a new EntityType is added and not handled here, Python will return None, and ENTITY_GRAPH will silently contain an invalid value until a later TypeError. Add an explicit default case that raises (e.g., AssertionError/NotImplementedError) to fail fast and preserve the intended exhaustiveness guarantee.
| def scope_type_to_entity_type(scope_type: ScopeType) -> EntityType: | ||
| """Convert a ScopeType to its corresponding EntityType. | ||
|
|
||
| Raises InvalidTypeConversionError for ScopeType.GLOBAL which has no entity mapping. | ||
| """ | ||
| match scope_type: | ||
| case ScopeType.GLOBAL: | ||
| raise InvalidTypeConversionError("ScopeType.GLOBAL has no corresponding EntityType") |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scope_type_to_entity_type() uses match without a default branch. If a new ScopeType is added and not mapped, this function will implicitly return None, which then propagates into SCOPE_TO_ENTITY_MAP during module import. Add a case _ branch that raises InvalidTypeConversionError (or a dedicated exception) so unmapped scope types fail fast with a clear message.
| def test_every_edge_has_distinct_parent_and_child(self) -> None: | ||
| for parent, children in ENTITY_GRAPH.items(): | ||
| for child in children: | ||
| assert parent != child, f"Self-referencing edge: {parent}" | ||
|
|
||
|
|
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_no_self_referencing_edges and test_every_edge_has_distinct_parent_and_child assert the same condition (parent != child). Consider removing one to avoid redundant coverage and keep the test suite lean.
| def test_every_edge_has_distinct_parent_and_child(self) -> None: | |
| for parent, children in ENTITY_GRAPH.items(): | |
| for child in children: | |
| assert parent != child, f"Self-referencing edge: {parent}" |
| APP_CONFIG_USER = "app_config:user" | ||
| # Session sub | ||
| SESSION_KERNEL = "session:kernel" | ||
| KERNEL_SCHEDULING_HISTORY = "session:kernel:scheduling_history" |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EntityType values are persisted in RBAC tables using StrEnumType(EntityType, length=32) (e.g., association_scopes_entities / object_permissions). The new value "session:kernel:scheduling_history" is 33 chars long, which will overflow the DB column size and can cause truncation or DB errors when stored. Either shorten this enum value to fit within 32 chars, or widen the related DB columns + alembic migrations and update the StrEnumType(..., length=...) usages accordingly.
| KERNEL_SCHEDULING_HISTORY = "session:kernel:scheduling_history" | |
| KERNEL_SCHEDULING_HISTORY = "session:kernel:sched_history" |
resolves #8738 (BA-4361)
Summary