refactor(semantics): migrate legacy @TIER to @COMPLEXITY annotations
- Replaced @TIER: TRIVIAL with @COMPLEXITY: 1 - Replaced @TIER: STANDARD with @COMPLEXITY: 3 - Replaced @TIER: CRITICAL with @COMPLEXITY: 5 - Manually elevated specific critical/complex components to levels 2 and 4 - Ignored legacy, specs, and node_modules directories - Updated generated semantic map
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__init__:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: routes, lazy-import, module-registry
|
||||
# @PURPOSE: Provide lazy route module loading to avoid heavyweight imports during tests.
|
||||
# @LAYER: API
|
||||
@@ -10,7 +10,7 @@ __all__ = ['plugins', 'tasks', 'settings', 'connections', 'environments', 'mappi
|
||||
|
||||
|
||||
# [DEF:__getattr__:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Lazily import route module by attribute name.
|
||||
# @PRE: name is module candidate exposed in __all__.
|
||||
# @POST: Returns imported submodule or raises AttributeError.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_assistant_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, assistant, api, confirmation, status
|
||||
# @PURPOSE: Validate assistant API endpoint logic via direct async handler invocation.
|
||||
# @LAYER: UI (API Tests)
|
||||
@@ -26,7 +26,7 @@ from src.models.assistant import (
|
||||
|
||||
|
||||
# [DEF:_run_async:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Execute async endpoint handler in synchronous test context.
|
||||
# @PRE: coroutine is awaitable endpoint invocation.
|
||||
# @POST: Returns coroutine result or raises propagated exception.
|
||||
@@ -36,7 +36,7 @@ def _run_async(coroutine):
|
||||
|
||||
# [/DEF:_run_async:Function]
|
||||
# [DEF:_FakeTask:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Lightweight task stub used by assistant API tests.
|
||||
class _FakeTask:
|
||||
def __init__(self, task_id: str, status: str = "RUNNING", user_id: str = "u-admin"):
|
||||
@@ -47,7 +47,7 @@ class _FakeTask:
|
||||
|
||||
# [/DEF:_FakeTask:Class]
|
||||
# [DEF:_FakeTaskManager:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Minimal async-compatible TaskManager fixture for deterministic test flows.
|
||||
class _FakeTaskManager:
|
||||
def __init__(self):
|
||||
@@ -71,7 +71,7 @@ class _FakeTaskManager:
|
||||
|
||||
# [/DEF:_FakeTaskManager:Class]
|
||||
# [DEF:_FakeConfigManager:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Environment config fixture with dev/prod aliases for parser tests.
|
||||
class _FakeConfigManager:
|
||||
def get_environments(self):
|
||||
@@ -87,7 +87,7 @@ class _FakeConfigManager:
|
||||
)
|
||||
# [/DEF:_FakeConfigManager:Class]
|
||||
# [DEF:_admin_user:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Build admin principal fixture.
|
||||
# @PRE: Test harness requires authenticated admin-like principal object.
|
||||
# @POST: Returns user stub with Admin role.
|
||||
@@ -98,7 +98,7 @@ def _admin_user():
|
||||
|
||||
# [/DEF:_admin_user:Function]
|
||||
# [DEF:_limited_user:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Build non-admin principal fixture.
|
||||
# @PRE: Test harness requires restricted principal for deny scenarios.
|
||||
# @POST: Returns user stub without admin privileges.
|
||||
@@ -109,7 +109,7 @@ def _limited_user():
|
||||
|
||||
# [/DEF:_limited_user:Function]
|
||||
# [DEF:_FakeQuery:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Minimal chainable query object for fake SQLAlchemy-like DB behavior in tests.
|
||||
class _FakeQuery:
|
||||
def __init__(self, rows):
|
||||
@@ -141,7 +141,7 @@ class _FakeQuery:
|
||||
|
||||
# [/DEF:_FakeQuery:Class]
|
||||
# [DEF:_FakeDb:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: In-memory fake database implementing subset of Session interface used by assistant routes.
|
||||
class _FakeDb:
|
||||
def __init__(self):
|
||||
@@ -191,7 +191,7 @@ class _FakeDb:
|
||||
|
||||
# [/DEF:_FakeDb:Class]
|
||||
# [DEF:_clear_assistant_state:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Reset in-memory assistant registries for isolation between tests.
|
||||
# @PRE: Assistant module globals may contain residues from previous test runs.
|
||||
# @POST: In-memory conversation/confirmation/audit dictionaries are empty.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_assistant_authz:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, assistant, authz, confirmation, rbac
|
||||
# @PURPOSE: Verify assistant confirmation ownership, expiration, and deny behavior for restricted users.
|
||||
# @LAYER: UI (API Tests)
|
||||
@@ -28,7 +28,7 @@ from src.models.assistant import (
|
||||
|
||||
|
||||
# [DEF:_run_async:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Execute async endpoint handler in synchronous test context.
|
||||
# @PRE: coroutine is awaitable endpoint invocation.
|
||||
# @POST: Returns coroutine result or raises propagated exception.
|
||||
@@ -38,7 +38,7 @@ def _run_async(coroutine):
|
||||
|
||||
# [/DEF:_run_async:Function]
|
||||
# [DEF:_FakeTask:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Lightweight task model used for assistant authz tests.
|
||||
class _FakeTask:
|
||||
def __init__(self, task_id: str, status: str = "RUNNING", user_id: str = "u-admin"):
|
||||
@@ -49,7 +49,7 @@ class _FakeTask:
|
||||
|
||||
# [/DEF:_FakeTask:Class]
|
||||
# [DEF:_FakeTaskManager:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Minimal task manager for deterministic operation creation and lookup.
|
||||
class _FakeTaskManager:
|
||||
def __init__(self):
|
||||
@@ -73,7 +73,7 @@ class _FakeTaskManager:
|
||||
|
||||
# [/DEF:_FakeTaskManager:Class]
|
||||
# [DEF:_FakeConfigManager:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Provide deterministic environment aliases required by intent parsing.
|
||||
class _FakeConfigManager:
|
||||
def get_environments(self):
|
||||
@@ -85,7 +85,7 @@ class _FakeConfigManager:
|
||||
|
||||
# [/DEF:_FakeConfigManager:Class]
|
||||
# [DEF:_admin_user:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Build admin principal fixture.
|
||||
# @PRE: Test requires privileged principal for risky operations.
|
||||
# @POST: Returns admin-like user stub with Admin role.
|
||||
@@ -96,7 +96,7 @@ def _admin_user():
|
||||
|
||||
# [/DEF:_admin_user:Function]
|
||||
# [DEF:_other_admin_user:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Build second admin principal fixture for ownership tests.
|
||||
# @PRE: Ownership mismatch scenario needs distinct authenticated actor.
|
||||
# @POST: Returns alternate admin-like user stub.
|
||||
@@ -107,7 +107,7 @@ def _other_admin_user():
|
||||
|
||||
# [/DEF:_other_admin_user:Function]
|
||||
# [DEF:_limited_user:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Build limited principal without required assistant execution privileges.
|
||||
# @PRE: Permission denial scenario needs non-admin actor.
|
||||
# @POST: Returns restricted user stub.
|
||||
@@ -118,7 +118,7 @@ def _limited_user():
|
||||
|
||||
# [/DEF:_limited_user:Function]
|
||||
# [DEF:_FakeQuery:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Minimal chainable query object for fake DB interactions.
|
||||
class _FakeQuery:
|
||||
def __init__(self, rows):
|
||||
@@ -150,7 +150,7 @@ class _FakeQuery:
|
||||
|
||||
# [/DEF:_FakeQuery:Class]
|
||||
# [DEF:_FakeDb:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: In-memory session substitute for assistant route persistence calls.
|
||||
class _FakeDb:
|
||||
def __init__(self):
|
||||
@@ -197,7 +197,7 @@ class _FakeDb:
|
||||
|
||||
# [/DEF:_FakeDb:Class]
|
||||
# [DEF:_clear_assistant_state:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Reset assistant process-local state between test cases.
|
||||
# @PRE: Assistant globals may contain state from prior tests.
|
||||
# @POST: Assistant in-memory state dictionaries are cleared.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.tests.api.routes.test_clean_release_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, api, clean-release, checks, reports
|
||||
# @PURPOSE: Contract tests for clean release checks and reports endpoints.
|
||||
# @LAYER: Domain
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_clean_release_legacy_compat:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Compatibility tests for legacy clean-release API paths retained during v2 migration.
|
||||
# @LAYER: Tests
|
||||
# @RELATION: TESTS -> backend.src.api.routes.clean_release
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.tests.api.routes.test_clean_release_source_policy:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, api, clean-release, source-policy
|
||||
# @PURPOSE: Validate API behavior for source isolation violations in clean release preparation.
|
||||
# @LAYER: Domain
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:test_clean_release_v2_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: API contract tests for redesigned clean release endpoints.
|
||||
# @LAYER: Domain
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:test_clean_release_v2_release_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: API contract test scaffolding for clean release approval and publication endpoints.
|
||||
# @LAYER: Domain
|
||||
# @RELATION: IMPLEMENTS -> clean_release_v2_release_api_contracts
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_connections_routes:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Verifies connection routes bootstrap their table before CRUD access.
|
||||
# @LAYER: API
|
||||
# @RELATION: VERIFIES -> backend.src.api.routes.connections
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_dashboards:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Unit tests for Dashboards API endpoints
|
||||
# @LAYER: API
|
||||
# @RELATION: TESTS -> backend.src.api.routes.dashboards
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_datasets:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: datasets, api, tests, pagination, mapping, docs
|
||||
# @PURPOSE: Unit tests for Datasets API endpoints
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_git_status_route:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, git, api, status, no_repo
|
||||
# @PURPOSE: Validate status endpoint behavior for missing and error repository states.
|
||||
# @LAYER: Domain (Tests)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_migration_routes:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Unit tests for migration API route handlers.
|
||||
# @LAYER: API
|
||||
# @RELATION: VERIFIES -> backend.src.api.routes.migration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.__tests__.test_profile_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, profile, api, preferences, lookup, contract
|
||||
# @PURPOSE: Verifies profile API route contracts for preference read/update and Superset account lookup.
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.tests.test_reports_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, reports, api, contract, pagination, filtering
|
||||
# @PURPOSE: Contract tests for GET /api/reports defaults, pagination, and filtering behavior.
|
||||
# @LAYER: Domain (Tests)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.tests.test_reports_detail_api:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, reports, api, detail, diagnostics
|
||||
# @PURPOSE: Contract tests for GET /api/reports/{report_id} detail endpoint behavior.
|
||||
# @LAYER: Domain (Tests)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.tests.test_reports_openapi_conformance:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, reports, openapi, conformance
|
||||
# @PURPOSE: Validate implemented reports payload shape against OpenAPI-required top-level contract fields.
|
||||
# @LAYER: Domain (Tests)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.admin:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, admin, users, roles, permissions
|
||||
# @PURPOSE: Admin API endpoints for user and role management.
|
||||
# @LAYER: API
|
||||
@@ -36,7 +36,7 @@ router = APIRouter(prefix="/api/admin", tags=["admin"])
|
||||
# [/DEF:router:Variable]
|
||||
|
||||
# [DEF:list_users:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Lists all registered users.
|
||||
# @PRE: Current user has 'Admin' role.
|
||||
# @POST: Returns a list of UserSchema objects.
|
||||
@@ -53,7 +53,7 @@ async def list_users(
|
||||
# [/DEF:list_users:Function]
|
||||
|
||||
# [DEF:create_user:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Creates a new local user.
|
||||
# @PRE: Current user has 'Admin' role.
|
||||
# @POST: New user is created in the database.
|
||||
@@ -91,7 +91,7 @@ async def create_user(
|
||||
# [/DEF:create_user:Function]
|
||||
|
||||
# [DEF:update_user:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates an existing user.
|
||||
@router.put("/users/{user_id}", response_model=UserSchema)
|
||||
async def update_user(
|
||||
@@ -126,7 +126,7 @@ async def update_user(
|
||||
# [/DEF:update_user:Function]
|
||||
|
||||
# [DEF:delete_user:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Deletes a user.
|
||||
@router.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_user(
|
||||
@@ -150,7 +150,7 @@ async def delete_user(
|
||||
# [/DEF:delete_user:Function]
|
||||
|
||||
# [DEF:list_roles:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Lists all available roles.
|
||||
# @RETURN: List[RoleSchema] - List of roles.
|
||||
# @RELATION: CALLS -> backend.src.models.auth.Role
|
||||
@@ -164,7 +164,7 @@ async def list_roles(
|
||||
# [/DEF:list_roles:Function]
|
||||
|
||||
# [DEF:create_role:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Creates a new system role with associated permissions.
|
||||
# @PRE: Role name must be unique.
|
||||
# @POST: New Role record is created in auth.db.
|
||||
@@ -202,7 +202,7 @@ async def create_role(
|
||||
# [/DEF:create_role:Function]
|
||||
|
||||
# [DEF:update_role:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates an existing role's metadata and permissions.
|
||||
# @PRE: role_id must be a valid existing role UUID.
|
||||
# @POST: Role record is updated in auth.db.
|
||||
@@ -247,7 +247,7 @@ async def update_role(
|
||||
# [/DEF:update_role:Function]
|
||||
|
||||
# [DEF:delete_role:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Removes a role from the system.
|
||||
# @PRE: role_id must be a valid existing role UUID.
|
||||
# @POST: Role record is removed from auth.db.
|
||||
@@ -274,7 +274,7 @@ async def delete_role(
|
||||
# [/DEF:delete_role:Function]
|
||||
|
||||
# [DEF:list_permissions:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Lists all available system permissions for assignment.
|
||||
# @POST: Returns a list of all PermissionSchema objects.
|
||||
# @PARAM: db (Session) - Auth database session.
|
||||
@@ -300,7 +300,7 @@ async def list_permissions(
|
||||
# [/DEF:list_permissions:Function]
|
||||
|
||||
# [DEF:list_ad_mappings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Lists all AD Group to Role mappings.
|
||||
@router.get("/ad-mappings", response_model=List[ADGroupMappingSchema])
|
||||
async def list_ad_mappings(
|
||||
@@ -312,7 +312,7 @@ async def list_ad_mappings(
|
||||
# [/DEF:list_ad_mappings:Function]
|
||||
|
||||
# [DEF:create_ad_mapping:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Creates a new AD Group mapping.
|
||||
@router.post("/ad-mappings", response_model=ADGroupMappingSchema)
|
||||
async def create_ad_mapping(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.assistant:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, assistant, chat, command, confirmation
|
||||
# @PURPOSE: API routes for LLM assistant command parsing and safe execution orchestration.
|
||||
# @LAYER: API
|
||||
@@ -47,7 +47,7 @@ git_service = GitService()
|
||||
|
||||
|
||||
# [DEF:AssistantMessageRequest:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Input payload for assistant message endpoint.
|
||||
# @PRE: message length is within accepted bounds.
|
||||
# @POST: Request object provides message text and optional conversation binding.
|
||||
@@ -58,7 +58,7 @@ class AssistantMessageRequest(BaseModel):
|
||||
|
||||
|
||||
# [DEF:AssistantAction:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: UI action descriptor returned with assistant responses.
|
||||
# @PRE: type and label are provided by orchestration logic.
|
||||
# @POST: Action can be rendered as button on frontend.
|
||||
@@ -70,7 +70,7 @@ class AssistantAction(BaseModel):
|
||||
|
||||
|
||||
# [DEF:AssistantMessageResponse:Class]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Output payload contract for assistant interaction endpoints.
|
||||
# @PRE: Response includes deterministic state and text.
|
||||
# @POST: Payload may include task_id/confirmation_id/actions for UI follow-up.
|
||||
@@ -88,7 +88,7 @@ class AssistantMessageResponse(BaseModel):
|
||||
|
||||
|
||||
# [DEF:ConfirmationRecord:Class]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: In-memory confirmation token model for risky operation dispatch.
|
||||
# @PRE: intent/dispatch/user_id are populated at confirmation request time.
|
||||
# @POST: Record tracks lifecycle state and expiry timestamp.
|
||||
@@ -125,7 +125,7 @@ INTENT_PERMISSION_CHECKS: Dict[str, List[Tuple[str, str]]] = {
|
||||
|
||||
|
||||
# [DEF:_append_history:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Append conversation message to in-memory history buffer.
|
||||
# @PRE: user_id and conversation_id identify target conversation bucket.
|
||||
# @POST: Message entry is appended to CONVERSATIONS key list.
|
||||
@@ -157,7 +157,7 @@ def _append_history(
|
||||
|
||||
|
||||
# [DEF:_persist_message:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Persist assistant/user message record to database.
|
||||
# @PRE: db session is writable and message payload is serializable.
|
||||
# @POST: Message row is committed or persistence failure is logged.
|
||||
@@ -193,7 +193,7 @@ def _persist_message(
|
||||
|
||||
|
||||
# [DEF:_audit:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Append in-memory audit record for assistant decision trace.
|
||||
# @PRE: payload describes decision/outcome fields.
|
||||
# @POST: ASSISTANT_AUDIT list for user contains new timestamped entry.
|
||||
@@ -206,7 +206,7 @@ def _audit(user_id: str, payload: Dict[str, Any]):
|
||||
|
||||
|
||||
# [DEF:_persist_audit:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Persist structured assistant audit payload in database.
|
||||
# @PRE: db session is writable and payload is JSON-serializable.
|
||||
# @POST: Audit row is committed or failure is logged with rollback.
|
||||
@@ -230,7 +230,7 @@ def _persist_audit(db: Session, user_id: str, payload: Dict[str, Any], conversat
|
||||
|
||||
|
||||
# [DEF:_persist_confirmation:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Persist confirmation token record to database.
|
||||
# @PRE: record contains id/user/intent/dispatch/expiry fields.
|
||||
# @POST: Confirmation row exists in persistent storage.
|
||||
@@ -256,7 +256,7 @@ def _persist_confirmation(db: Session, record: ConfirmationRecord):
|
||||
|
||||
|
||||
# [DEF:_update_confirmation_state:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Update persistent confirmation token lifecycle state.
|
||||
# @PRE: confirmation_id references existing row.
|
||||
# @POST: State and consumed_at fields are updated when applicable.
|
||||
@@ -276,7 +276,7 @@ def _update_confirmation_state(db: Session, confirmation_id: str, state: str):
|
||||
|
||||
|
||||
# [DEF:_load_confirmation_from_db:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Load confirmation token from database into in-memory model.
|
||||
# @PRE: confirmation_id may or may not exist in storage.
|
||||
# @POST: Returns ConfirmationRecord when found, otherwise None.
|
||||
@@ -302,7 +302,7 @@ def _load_confirmation_from_db(db: Session, confirmation_id: str) -> Optional[Co
|
||||
|
||||
|
||||
# [DEF:_ensure_conversation:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve active conversation id in memory or create a new one.
|
||||
# @PRE: user_id identifies current actor.
|
||||
# @POST: Returns stable conversation id and updates USER_ACTIVE_CONVERSATION.
|
||||
@@ -322,7 +322,7 @@ def _ensure_conversation(user_id: str, conversation_id: Optional[str]) -> str:
|
||||
|
||||
|
||||
# [DEF:_resolve_or_create_conversation:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve active conversation using explicit id, memory cache, or persisted history.
|
||||
# @PRE: user_id and db session are available.
|
||||
# @POST: Returns conversation id and updates USER_ACTIVE_CONVERSATION cache.
|
||||
@@ -352,7 +352,7 @@ def _resolve_or_create_conversation(user_id: str, conversation_id: Optional[str]
|
||||
|
||||
|
||||
# [DEF:_cleanup_history_ttl:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Enforce assistant message retention window by deleting expired rows and in-memory records.
|
||||
# @PRE: db session is available and user_id references current actor scope.
|
||||
# @POST: Messages older than ASSISTANT_MESSAGE_TTL_DAYS are removed from persistence and memory mirrors.
|
||||
@@ -390,7 +390,7 @@ def _cleanup_history_ttl(db: Session, user_id: str):
|
||||
|
||||
|
||||
# [DEF:_is_conversation_archived:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Determine archived state for a conversation based on last update timestamp.
|
||||
# @PRE: updated_at can be null for empty conversations.
|
||||
# @POST: Returns True when conversation inactivity exceeds archive threshold.
|
||||
@@ -403,7 +403,7 @@ def _is_conversation_archived(updated_at: Optional[datetime]) -> bool:
|
||||
|
||||
|
||||
# [DEF:_coerce_query_bool:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Normalize bool-like query values for compatibility in direct handler invocations/tests.
|
||||
# @PRE: value may be bool, string, or FastAPI Query metadata object.
|
||||
# @POST: Returns deterministic boolean flag.
|
||||
@@ -417,7 +417,7 @@ def _coerce_query_bool(value: Any) -> bool:
|
||||
|
||||
|
||||
# [DEF:_extract_id:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Extract first regex match group from text by ordered pattern list.
|
||||
# @PRE: patterns contain at least one capture group.
|
||||
# @POST: Returns first matched token or None.
|
||||
@@ -431,7 +431,7 @@ def _extract_id(text: str, patterns: List[str]) -> Optional[str]:
|
||||
|
||||
|
||||
# [DEF:_resolve_env_id:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve environment identifier/name token to canonical environment id.
|
||||
# @PRE: config_manager provides environment list.
|
||||
# @POST: Returns matched environment id or None.
|
||||
@@ -449,7 +449,7 @@ def _resolve_env_id(token: Optional[str], config_manager: ConfigManager) -> Opti
|
||||
|
||||
|
||||
# [DEF:_is_production_env:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Determine whether environment token resolves to production-like target.
|
||||
# @PRE: config_manager provides environments or token text is provided.
|
||||
# @POST: Returns True for production/prod synonyms, else False.
|
||||
@@ -467,7 +467,7 @@ def _is_production_env(token: Optional[str], config_manager: ConfigManager) -> b
|
||||
|
||||
|
||||
# [DEF:_resolve_provider_id:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve provider token to provider id with active/default fallback.
|
||||
# @PRE: db session can load provider list through LLMProviderService.
|
||||
# @POST: Returns provider id or None when no providers configured.
|
||||
@@ -503,7 +503,7 @@ def _resolve_provider_id(
|
||||
|
||||
|
||||
# [DEF:_get_default_environment_id:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve default environment id from settings or first configured environment.
|
||||
# @PRE: config_manager returns environments list.
|
||||
# @POST: Returns default environment id or None when environment list is empty.
|
||||
@@ -525,7 +525,7 @@ def _get_default_environment_id(config_manager: ConfigManager) -> Optional[str]:
|
||||
|
||||
|
||||
# [DEF:_resolve_dashboard_id_by_ref:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard id by title or slug reference in selected environment.
|
||||
# @PRE: dashboard_ref is a non-empty string-like token.
|
||||
# @POST: Returns dashboard id when uniquely matched, otherwise None.
|
||||
@@ -568,7 +568,7 @@ def _resolve_dashboard_id_by_ref(
|
||||
|
||||
|
||||
# [DEF:_resolve_dashboard_id_entity:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard id from intent entities using numeric id or dashboard_ref fallback.
|
||||
# @PRE: entities may contain dashboard_id as int/str and optional dashboard_ref.
|
||||
# @POST: Returns resolved dashboard id or None when ambiguous/unresolvable.
|
||||
@@ -600,7 +600,7 @@ def _resolve_dashboard_id_entity(
|
||||
|
||||
|
||||
# [DEF:_get_environment_name_by_id:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve human-readable environment name by id.
|
||||
# @PRE: environment id may be None.
|
||||
# @POST: Returns matching environment name or fallback id.
|
||||
@@ -613,7 +613,7 @@ def _get_environment_name_by_id(env_id: Optional[str], config_manager: ConfigMan
|
||||
|
||||
|
||||
# [DEF:_extract_result_deep_links:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Build deep-link actions to verify task result from assistant chat.
|
||||
# @PRE: task object is available.
|
||||
# @POST: Returns zero or more assistant actions for dashboard open/diff.
|
||||
@@ -670,7 +670,7 @@ def _extract_result_deep_links(task: Any, config_manager: ConfigManager) -> List
|
||||
|
||||
|
||||
# [DEF:_build_task_observability_summary:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Build compact textual summary for completed tasks to reduce "black box" effect.
|
||||
# @PRE: task may contain plugin-specific result payload.
|
||||
# @POST: Returns non-empty summary line for known task types or empty string fallback.
|
||||
@@ -734,7 +734,7 @@ def _build_task_observability_summary(task: Any, config_manager: ConfigManager)
|
||||
|
||||
|
||||
# [DEF:_parse_command:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Deterministically parse RU/EN command text into intent payload.
|
||||
# @PRE: message contains raw user text and config manager resolves environments.
|
||||
# @POST: Returns intent dict with domain/operation/entities/confidence/risk fields.
|
||||
@@ -928,7 +928,7 @@ def _parse_command(message: str, config_manager: ConfigManager) -> Dict[str, Any
|
||||
|
||||
|
||||
# [DEF:_check_any_permission:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Validate user against alternative permission checks (logical OR).
|
||||
# @PRE: checks list contains resource-action tuples.
|
||||
# @POST: Returns on first successful permission; raises 403-like HTTPException otherwise.
|
||||
@@ -946,7 +946,7 @@ def _check_any_permission(current_user: User, checks: List[Tuple[str, str]]):
|
||||
|
||||
|
||||
# [DEF:_has_any_permission:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Check whether user has at least one permission tuple from the provided list.
|
||||
# @PRE: current_user and checks list are valid.
|
||||
# @POST: Returns True when at least one permission check passes.
|
||||
@@ -960,7 +960,7 @@ def _has_any_permission(current_user: User, checks: List[Tuple[str, str]]) -> bo
|
||||
|
||||
|
||||
# [DEF:_build_tool_catalog:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Build current-user tool catalog for LLM planner with operation contracts and defaults.
|
||||
# @PRE: current_user is authenticated; config/db are available.
|
||||
# @POST: Returns list of executable tools filtered by permission and runtime availability.
|
||||
@@ -1084,7 +1084,7 @@ def _build_tool_catalog(current_user: User, config_manager: ConfigManager, db: S
|
||||
|
||||
|
||||
# [DEF:_coerce_intent_entities:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Normalize intent entity value types from LLM output to route-compatible values.
|
||||
# @PRE: intent contains entities dict or missing entities.
|
||||
# @POST: Returned intent has numeric ids coerced where possible and string values stripped.
|
||||
@@ -1109,7 +1109,7 @@ _SAFE_OPS = {"show_capabilities", "get_task_status", "get_health_summary"}
|
||||
|
||||
|
||||
# [DEF:_confirmation_summary:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Build human-readable confirmation prompt for an intent before execution.
|
||||
# @PRE: intent contains operation and entities fields.
|
||||
# @POST: Returns descriptive Russian-language text ending with confirmation prompt.
|
||||
@@ -1205,7 +1205,7 @@ async def _async_confirmation_summary(intent: Dict[str, Any], config_manager: Co
|
||||
|
||||
|
||||
# [DEF:_clarification_text_for_intent:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Convert technical missing-parameter errors into user-facing clarification prompts.
|
||||
# @PRE: state was classified as needs_clarification for current intent/error combination.
|
||||
# @POST: Returned text is human-readable and actionable for target operation.
|
||||
@@ -1229,7 +1229,7 @@ def _clarification_text_for_intent(intent: Optional[Dict[str, Any]], detail_text
|
||||
|
||||
|
||||
# [DEF:_plan_intent_with_llm:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Use active LLM provider to select best tool/operation from dynamic catalog.
|
||||
# @PRE: tools list contains allowed operations for current user.
|
||||
# @POST: Returns normalized intent dict when planning succeeds; otherwise None.
|
||||
@@ -1340,7 +1340,7 @@ async def _plan_intent_with_llm(
|
||||
|
||||
|
||||
# [DEF:_authorize_intent:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Validate user permissions for parsed intent before confirmation/dispatch.
|
||||
# @PRE: intent.operation is present for known assistant command domains.
|
||||
# @POST: Returns if authorized; raises HTTPException(403) when denied.
|
||||
@@ -1352,7 +1352,7 @@ def _authorize_intent(intent: Dict[str, Any], current_user: User):
|
||||
|
||||
|
||||
# [DEF:_dispatch_intent:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Execute parsed assistant intent via existing task/plugin/git services.
|
||||
# @PRE: intent operation is known and actor permissions are validated per operation.
|
||||
# @POST: Returns response text, optional task id, and UI actions for follow-up.
|
||||
@@ -1674,7 +1674,7 @@ async def _dispatch_intent(
|
||||
|
||||
@router.post("/messages", response_model=AssistantMessageResponse)
|
||||
# [DEF:send_message:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Parse assistant command, enforce safety gates, and dispatch executable intent.
|
||||
# @PRE: Authenticated user is available and message text is non-empty.
|
||||
# @POST: Response state is one of clarification/confirmation/started/success/denied/failed.
|
||||
@@ -1844,7 +1844,7 @@ async def send_message(
|
||||
|
||||
@router.post("/confirmations/{confirmation_id}/confirm", response_model=AssistantMessageResponse)
|
||||
# [DEF:confirm_operation:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Execute previously requested risky operation after explicit user confirmation.
|
||||
# @PRE: confirmation_id exists, belongs to current user, is pending, and not expired.
|
||||
# @POST: Confirmation state becomes consumed and operation result is persisted in history.
|
||||
@@ -1911,7 +1911,7 @@ async def confirm_operation(
|
||||
|
||||
@router.post("/confirmations/{confirmation_id}/cancel", response_model=AssistantMessageResponse)
|
||||
# [DEF:cancel_operation:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Cancel pending risky operation and mark confirmation token as cancelled.
|
||||
# @PRE: confirmation_id exists, belongs to current user, and is still pending.
|
||||
# @POST: Confirmation becomes cancelled and cannot be executed anymore.
|
||||
@@ -1968,7 +1968,7 @@ async def cancel_operation(
|
||||
|
||||
|
||||
# [DEF:list_conversations:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Return paginated conversation list for current user with archived flag and last message preview.
|
||||
# @PRE: Authenticated user context and valid pagination params.
|
||||
# @POST: Conversations are grouped by conversation_id sorted by latest activity descending.
|
||||
@@ -2056,7 +2056,7 @@ async def list_conversations(
|
||||
|
||||
|
||||
# [DEF:delete_conversation:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Soft-delete or hard-delete a conversation and clear its in-memory trace.
|
||||
# @PRE: conversation_id belongs to current_user.
|
||||
# @POST: Conversation records are removed from DB and CONVERSATIONS cache.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.clean_release:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, clean-release, candidate-preparation, compliance
|
||||
# @PURPOSE: Expose clean release endpoints for candidate preparation and subsequent compliance flow.
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.clean_release_v2:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, clean-release, v2, headless
|
||||
# @PURPOSE: Redesigned clean release API for headless candidate lifecycle.
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.dashboards:Module]
|
||||
#
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @SEMANTICS: api, dashboards, resources, hub
|
||||
# @PURPOSE: API endpoints for the Dashboard Hub - listing dashboards with Git and task status
|
||||
# @LAYER: API
|
||||
@@ -66,7 +66,7 @@ from ...services.resource_service import ResourceService
|
||||
router = APIRouter(prefix="/api/dashboards", tags=["Dashboards"])
|
||||
|
||||
# [DEF:GitStatus:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for dashboard Git synchronization status.
|
||||
class GitStatus(BaseModel):
|
||||
branch: Optional[str] = None
|
||||
@@ -76,7 +76,7 @@ class GitStatus(BaseModel):
|
||||
# [/DEF:GitStatus:DataClass]
|
||||
|
||||
# [DEF:LastTask:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for the most recent background task associated with a dashboard.
|
||||
class LastTask(BaseModel):
|
||||
task_id: Optional[str] = None
|
||||
@@ -88,7 +88,7 @@ class LastTask(BaseModel):
|
||||
# [/DEF:LastTask:DataClass]
|
||||
|
||||
# [DEF:DashboardItem:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO representing a single dashboard with projected metadata.
|
||||
class DashboardItem(BaseModel):
|
||||
id: int
|
||||
@@ -104,7 +104,7 @@ class DashboardItem(BaseModel):
|
||||
# [/DEF:DashboardItem:DataClass]
|
||||
|
||||
# [DEF:EffectiveProfileFilter:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Metadata about applied profile filters for UI context.
|
||||
class EffectiveProfileFilter(BaseModel):
|
||||
applied: bool
|
||||
@@ -117,7 +117,7 @@ class EffectiveProfileFilter(BaseModel):
|
||||
# [/DEF:EffectiveProfileFilter:DataClass]
|
||||
|
||||
# [DEF:DashboardsResponse:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Envelope DTO for paginated dashboards list.
|
||||
class DashboardsResponse(BaseModel):
|
||||
dashboards: List[DashboardItem]
|
||||
@@ -129,7 +129,7 @@ class DashboardsResponse(BaseModel):
|
||||
# [/DEF:DashboardsResponse:DataClass]
|
||||
|
||||
# [DEF:DashboardChartItem:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for a chart linked to a dashboard.
|
||||
class DashboardChartItem(BaseModel):
|
||||
id: int
|
||||
@@ -141,7 +141,7 @@ class DashboardChartItem(BaseModel):
|
||||
# [/DEF:DashboardChartItem:DataClass]
|
||||
|
||||
# [DEF:DashboardDatasetItem:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for a dataset associated with a dashboard.
|
||||
class DashboardDatasetItem(BaseModel):
|
||||
id: int
|
||||
@@ -153,7 +153,7 @@ class DashboardDatasetItem(BaseModel):
|
||||
# [/DEF:DashboardDatasetItem:DataClass]
|
||||
|
||||
# [DEF:DashboardDetailResponse:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Detailed dashboard metadata including children.
|
||||
class DashboardDetailResponse(BaseModel):
|
||||
id: int
|
||||
@@ -170,7 +170,7 @@ class DashboardDetailResponse(BaseModel):
|
||||
# [/DEF:DashboardDetailResponse:DataClass]
|
||||
|
||||
# [DEF:DashboardTaskHistoryItem:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Individual history record entry.
|
||||
class DashboardTaskHistoryItem(BaseModel):
|
||||
id: str
|
||||
@@ -184,7 +184,7 @@ class DashboardTaskHistoryItem(BaseModel):
|
||||
# [/DEF:DashboardTaskHistoryItem:DataClass]
|
||||
|
||||
# [DEF:DashboardTaskHistoryResponse:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Collection DTO for task history.
|
||||
class DashboardTaskHistoryResponse(BaseModel):
|
||||
dashboard_id: int
|
||||
@@ -192,7 +192,7 @@ class DashboardTaskHistoryResponse(BaseModel):
|
||||
# [/DEF:DashboardTaskHistoryResponse:DataClass]
|
||||
|
||||
# [DEF:DatabaseMapping:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for cross-environment database ID mapping.
|
||||
class DatabaseMapping(BaseModel):
|
||||
source_db: str
|
||||
@@ -203,7 +203,7 @@ class DatabaseMapping(BaseModel):
|
||||
# [/DEF:DatabaseMapping:DataClass]
|
||||
|
||||
# [DEF:DatabaseMappingsResponse:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Wrapper for database mappings.
|
||||
class DatabaseMappingsResponse(BaseModel):
|
||||
mappings: List[DatabaseMapping]
|
||||
@@ -211,7 +211,7 @@ class DatabaseMappingsResponse(BaseModel):
|
||||
|
||||
|
||||
# [DEF:_find_dashboard_id_by_slug:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard numeric ID by slug using Superset list endpoint.
|
||||
# @PRE: `dashboard_slug` is non-empty.
|
||||
# @POST: Returns dashboard ID when found, otherwise None.
|
||||
@@ -239,7 +239,7 @@ def _find_dashboard_id_by_slug(
|
||||
|
||||
|
||||
# [DEF:_resolve_dashboard_id_from_ref:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard ID from slug-first reference with numeric fallback.
|
||||
# @PRE: `dashboard_ref` is provided in route path.
|
||||
# @POST: Returns a valid dashboard ID or raises HTTPException(404).
|
||||
@@ -264,7 +264,7 @@ def _resolve_dashboard_id_from_ref(
|
||||
|
||||
|
||||
# [DEF:_find_dashboard_id_by_slug_async:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard numeric ID by slug using async Superset list endpoint.
|
||||
# @PRE: dashboard_slug is non-empty.
|
||||
# @POST: Returns dashboard ID when found, otherwise None.
|
||||
@@ -292,7 +292,7 @@ async def _find_dashboard_id_by_slug_async(
|
||||
|
||||
|
||||
# [DEF:_resolve_dashboard_id_from_ref_async:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard ID from slug-first reference using async Superset client.
|
||||
# @PRE: dashboard_ref is provided in route path.
|
||||
# @POST: Returns valid dashboard ID or raises HTTPException(404).
|
||||
@@ -316,7 +316,7 @@ async def _resolve_dashboard_id_from_ref_async(
|
||||
|
||||
|
||||
# [DEF:_normalize_filter_values:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Normalize query filter values to lower-cased non-empty tokens.
|
||||
# @PRE: values may be None or list of strings.
|
||||
# @POST: Returns trimmed normalized list preserving input order.
|
||||
@@ -333,7 +333,7 @@ def _normalize_filter_values(values: Optional[List[str]]) -> List[str]:
|
||||
|
||||
|
||||
# [DEF:_dashboard_git_filter_value:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Build comparable git status token for dashboards filtering.
|
||||
# @PRE: dashboard payload may contain git_status or None.
|
||||
# @POST: Returns one of ok|diff|no_repo|error|pending.
|
||||
@@ -353,7 +353,7 @@ def _dashboard_git_filter_value(dashboard: Dict[str, Any]) -> str:
|
||||
# [/DEF:_dashboard_git_filter_value:Function]
|
||||
|
||||
# [DEF:_normalize_actor_alias_token:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Normalize actor alias token to comparable trim+lower text.
|
||||
# @PRE: value can be scalar/None.
|
||||
# @POST: Returns normalized token or None.
|
||||
@@ -364,7 +364,7 @@ def _normalize_actor_alias_token(value: Any) -> Optional[str]:
|
||||
|
||||
|
||||
# [DEF:_normalize_owner_display_token:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Project owner payload value into stable display string for API response contracts.
|
||||
# @PRE: owner can be scalar, dict or None.
|
||||
# @POST: Returns trimmed non-empty owner display token or None.
|
||||
@@ -391,7 +391,7 @@ def _normalize_owner_display_token(owner: Any) -> Optional[str]:
|
||||
|
||||
|
||||
# [DEF:_normalize_dashboard_owner_values:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Normalize dashboard owners payload to optional list of display strings.
|
||||
# @PRE: owners payload can be None, scalar, or list with mixed values.
|
||||
# @POST: Returns deduplicated owner labels preserving order, or None when absent.
|
||||
@@ -416,7 +416,7 @@ def _normalize_dashboard_owner_values(owners: Any) -> Optional[List[str]]:
|
||||
|
||||
|
||||
# [DEF:_project_dashboard_response_items:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Project dashboard payloads to response-contract-safe shape.
|
||||
# @PRE: dashboards is a list of dict-like dashboard payloads.
|
||||
# @POST: Returned items satisfy DashboardItem owners=list[str]|None contract.
|
||||
@@ -433,7 +433,7 @@ def _project_dashboard_response_items(dashboards: List[Dict[str, Any]]) -> List[
|
||||
|
||||
|
||||
# [DEF:_resolve_profile_actor_aliases:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve stable actor aliases for profile filtering without per-dashboard detail fan-out.
|
||||
# @PRE: bound username is available and env is valid.
|
||||
# @POST: Returns at least normalized username; may include Superset display-name alias.
|
||||
@@ -498,7 +498,7 @@ def _resolve_profile_actor_aliases(env: Any, bound_username: str) -> List[str]:
|
||||
|
||||
|
||||
# [DEF:_matches_dashboard_actor_aliases:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Apply profile actor matching against multiple aliases (username + optional display name).
|
||||
# @PRE: actor_aliases contains normalized non-empty tokens.
|
||||
# @POST: Returns True when any alias matches owners OR modified_by.
|
||||
@@ -520,7 +520,7 @@ def _matches_dashboard_actor_aliases(
|
||||
|
||||
|
||||
# [DEF:get_dashboards:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Fetch list of dashboards from a specific environment with Git status and last task status
|
||||
# @PRE: env_id must be a valid environment ID
|
||||
# @PRE: page must be >= 1 if provided
|
||||
@@ -823,7 +823,7 @@ async def get_dashboards(
|
||||
# [/DEF:get_dashboards:Function]
|
||||
|
||||
# [DEF:get_database_mappings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get database mapping suggestions between source and target environments
|
||||
# @PRE: User has permission plugin:migration:read
|
||||
# @PRE: source_env_id and target_env_id are valid environment IDs
|
||||
@@ -879,7 +879,7 @@ async def get_database_mappings(
|
||||
# [/DEF:get_database_mappings:Function]
|
||||
|
||||
# [DEF:get_dashboard_detail:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Fetch detailed dashboard info with related charts and datasets
|
||||
# @PRE: env_id must be valid and dashboard ref (slug or id) must exist
|
||||
# @POST: Returns dashboard detail payload for overview page
|
||||
@@ -917,7 +917,7 @@ async def get_dashboard_detail(
|
||||
|
||||
|
||||
# [DEF:_task_matches_dashboard:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Checks whether task params are tied to a specific dashboard and environment.
|
||||
# @PRE: task-like object exposes plugin_id and params fields.
|
||||
# @POST: Returns True only for supported task plugins tied to dashboard_id (+optional env_id).
|
||||
@@ -951,7 +951,7 @@ def _task_matches_dashboard(task: Any, dashboard_id: int, env_id: Optional[str])
|
||||
|
||||
|
||||
# [DEF:get_dashboard_tasks_history:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Returns history of backup and LLM validation tasks for a dashboard.
|
||||
# @PRE: dashboard ref (slug or id) is valid.
|
||||
# @POST: Response contains sorted task history (newest first).
|
||||
@@ -1038,7 +1038,7 @@ async def get_dashboard_tasks_history(
|
||||
|
||||
|
||||
# [DEF:get_dashboard_thumbnail:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Proxies Superset dashboard thumbnail with cache support.
|
||||
# @PRE: env_id must exist.
|
||||
# @POST: Returns image bytes or 202 when thumbnail is being prepared by Superset.
|
||||
@@ -1132,7 +1132,7 @@ async def get_dashboard_thumbnail(
|
||||
# [/DEF:get_dashboard_thumbnail:Function]
|
||||
|
||||
# [DEF:MigrateRequest:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for dashboard migration requests.
|
||||
class MigrateRequest(BaseModel):
|
||||
source_env_id: str = Field(..., description="Source environment ID")
|
||||
@@ -1143,14 +1143,14 @@ class MigrateRequest(BaseModel):
|
||||
# [/DEF:MigrateRequest:DataClass]
|
||||
|
||||
# [DEF:TaskResponse:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for async task ID return.
|
||||
class TaskResponse(BaseModel):
|
||||
task_id: str
|
||||
# [/DEF:TaskResponse:DataClass]
|
||||
|
||||
# [DEF:migrate_dashboards:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Trigger bulk migration of dashboards from source to target environment
|
||||
# @PRE: User has permission plugin:migration:execute
|
||||
# @PRE: source_env_id and target_env_id are valid environment IDs
|
||||
@@ -1211,7 +1211,7 @@ async def migrate_dashboards(
|
||||
# [/DEF:migrate_dashboards:Function]
|
||||
|
||||
# [DEF:BackupRequest:DataClass]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: DTO for dashboard backup requests.
|
||||
class BackupRequest(BaseModel):
|
||||
env_id: str = Field(..., description="Environment ID")
|
||||
@@ -1220,7 +1220,7 @@ class BackupRequest(BaseModel):
|
||||
# [/DEF:BackupRequest:DataClass]
|
||||
|
||||
# [DEF:backup_dashboards:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Trigger bulk backup of dashboards with optional cron schedule
|
||||
# @PRE: User has permission plugin:backup:execute
|
||||
# @PRE: env_id is a valid environment ID
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.datasets:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, datasets, resources, hub
|
||||
# @PURPOSE: API endpoints for the Dataset Hub - listing datasets with mapping progress
|
||||
# @LAYER: API
|
||||
@@ -22,7 +22,7 @@ from ...core.superset_client import SupersetClient
|
||||
router = APIRouter(prefix="/api/datasets", tags=["Datasets"])
|
||||
|
||||
# [DEF:MappedFields:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: DTO for dataset mapping progress statistics
|
||||
class MappedFields(BaseModel):
|
||||
total: int
|
||||
@@ -30,7 +30,7 @@ class MappedFields(BaseModel):
|
||||
# [/DEF:MappedFields:DataClass]
|
||||
|
||||
# [DEF:LastTask:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: DTO for the most recent task associated with a dataset
|
||||
class LastTask(BaseModel):
|
||||
task_id: Optional[str] = None
|
||||
@@ -38,7 +38,7 @@ class LastTask(BaseModel):
|
||||
# [/DEF:LastTask:DataClass]
|
||||
|
||||
# [DEF:DatasetItem:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Summary DTO for a dataset in the hub listing
|
||||
class DatasetItem(BaseModel):
|
||||
id: int
|
||||
@@ -53,7 +53,7 @@ class DatasetItem(BaseModel):
|
||||
# [/DEF:DatasetItem:DataClass]
|
||||
|
||||
# [DEF:LinkedDashboard:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: DTO for a dashboard linked to a dataset
|
||||
class LinkedDashboard(BaseModel):
|
||||
id: int
|
||||
@@ -62,7 +62,7 @@ class LinkedDashboard(BaseModel):
|
||||
# [/DEF:LinkedDashboard:DataClass]
|
||||
|
||||
# [DEF:DatasetColumn:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: DTO for a single dataset column's metadata
|
||||
class DatasetColumn(BaseModel):
|
||||
id: int
|
||||
@@ -74,7 +74,7 @@ class DatasetColumn(BaseModel):
|
||||
# [/DEF:DatasetColumn:DataClass]
|
||||
|
||||
# [DEF:DatasetDetailResponse:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Detailed DTO for a dataset including columns and links
|
||||
class DatasetDetailResponse(BaseModel):
|
||||
id: int
|
||||
@@ -96,7 +96,7 @@ class DatasetDetailResponse(BaseModel):
|
||||
# [/DEF:DatasetDetailResponse:DataClass]
|
||||
|
||||
# [DEF:DatasetsResponse:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Paginated response DTO for dataset listings
|
||||
class DatasetsResponse(BaseModel):
|
||||
datasets: List[DatasetItem]
|
||||
@@ -107,14 +107,14 @@ class DatasetsResponse(BaseModel):
|
||||
# [/DEF:DatasetsResponse:DataClass]
|
||||
|
||||
# [DEF:TaskResponse:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Response DTO containing a task ID for tracking
|
||||
class TaskResponse(BaseModel):
|
||||
task_id: str
|
||||
# [/DEF:TaskResponse:DataClass]
|
||||
|
||||
# [DEF:get_dataset_ids:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Fetch list of all dataset IDs from a specific environment (without pagination)
|
||||
# @PRE: env_id must be a valid environment ID
|
||||
# @POST: Returns a list of all dataset IDs
|
||||
@@ -166,7 +166,7 @@ async def get_dataset_ids(
|
||||
# [/DEF:get_dataset_ids:Function]
|
||||
|
||||
# [DEF:get_datasets:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Fetch list of datasets from a specific environment with mapping progress
|
||||
# @PRE: env_id must be a valid environment ID
|
||||
# @PRE: page must be >= 1 if provided
|
||||
@@ -246,7 +246,7 @@ async def get_datasets(
|
||||
# [/DEF:get_datasets:Function]
|
||||
|
||||
# [DEF:MapColumnsRequest:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Request DTO for initiating column mapping
|
||||
class MapColumnsRequest(BaseModel):
|
||||
env_id: str = Field(..., description="Environment ID")
|
||||
@@ -257,7 +257,7 @@ class MapColumnsRequest(BaseModel):
|
||||
# [/DEF:MapColumnsRequest:DataClass]
|
||||
|
||||
# [DEF:map_columns:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Trigger bulk column mapping for datasets
|
||||
# @PRE: User has permission plugin:mapper:execute
|
||||
# @PRE: env_id is a valid environment ID
|
||||
@@ -319,7 +319,7 @@ async def map_columns(
|
||||
# [/DEF:map_columns:Function]
|
||||
|
||||
# [DEF:GenerateDocsRequest:DataClass]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Request DTO for initiating documentation generation
|
||||
class GenerateDocsRequest(BaseModel):
|
||||
env_id: str = Field(..., description="Environment ID")
|
||||
@@ -329,7 +329,7 @@ class GenerateDocsRequest(BaseModel):
|
||||
# [/DEF:GenerateDocsRequest:DataClass]
|
||||
|
||||
# [DEF:generate_docs:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Trigger bulk documentation generation for datasets
|
||||
# @PRE: User has permission plugin:llm_analysis:execute
|
||||
# @PRE: env_id is a valid environment ID
|
||||
@@ -385,7 +385,7 @@ async def generate_docs(
|
||||
# [/DEF:generate_docs:Function]
|
||||
|
||||
# [DEF:get_dataset_detail:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get detailed dataset information including columns and linked dashboards
|
||||
# @PRE: env_id is a valid environment ID
|
||||
# @PRE: dataset_id is a valid dataset ID
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.environments:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, environments, superset, databases
|
||||
# @PURPOSE: API endpoints for listing environments and their databases.
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.git:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: git, routes, api, fastapi, repository, deployment
|
||||
# @PURPOSE: Provides FastAPI endpoints for Git integration operations.
|
||||
# @LAYER: API
|
||||
@@ -48,7 +48,7 @@ MAX_REPOSITORY_STATUS_BATCH = 50
|
||||
|
||||
|
||||
# [DEF:_build_no_repo_status_payload:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Build a consistent status payload for dashboards without initialized repositories.
|
||||
# @PRE: None.
|
||||
# @POST: Returns a stable payload compatible with frontend repository status parsing.
|
||||
@@ -73,7 +73,7 @@ def _build_no_repo_status_payload() -> dict:
|
||||
|
||||
|
||||
# [DEF:_handle_unexpected_git_route_error:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Convert unexpected route-level exceptions to stable 500 API responses.
|
||||
# @PRE: `error` is a non-HTTPException instance.
|
||||
# @POST: Raises HTTPException(500) with route-specific context.
|
||||
@@ -86,7 +86,7 @@ def _handle_unexpected_git_route_error(route_name: str, error: Exception) -> Non
|
||||
|
||||
|
||||
# [DEF:_resolve_repository_status:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve repository status for one dashboard with graceful NO_REPO semantics.
|
||||
# @PRE: `dashboard_id` is a valid integer.
|
||||
# @POST: Returns standard status payload or `NO_REPO` payload when repository path is absent.
|
||||
@@ -113,7 +113,7 @@ def _resolve_repository_status(dashboard_id: int) -> dict:
|
||||
|
||||
|
||||
# [DEF:_get_git_config_or_404:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve GitServerConfig by id or raise 404.
|
||||
# @PRE: db session is available.
|
||||
# @POST: Returns GitServerConfig model.
|
||||
@@ -126,7 +126,7 @@ def _get_git_config_or_404(db: Session, config_id: str) -> GitServerConfig:
|
||||
|
||||
|
||||
# [DEF:_find_dashboard_id_by_slug:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard numeric ID by slug in a specific environment.
|
||||
# @PRE: dashboard_slug is non-empty.
|
||||
# @POST: Returns dashboard ID or None when not found.
|
||||
@@ -153,7 +153,7 @@ def _find_dashboard_id_by_slug(
|
||||
|
||||
|
||||
# [DEF:_resolve_dashboard_id_from_ref:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard ID from slug-or-id reference for Git routes.
|
||||
# @PRE: dashboard_ref is provided; env_id is required for slug values.
|
||||
# @POST: Returns numeric dashboard ID or raises HTTPException.
|
||||
@@ -188,7 +188,7 @@ def _resolve_dashboard_id_from_ref(
|
||||
|
||||
|
||||
# [DEF:_find_dashboard_id_by_slug_async:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard numeric ID by slug asynchronously for hot-path Git routes.
|
||||
# @PRE: dashboard_slug is non-empty.
|
||||
# @POST: Returns dashboard ID or None when not found.
|
||||
@@ -215,7 +215,7 @@ async def _find_dashboard_id_by_slug_async(
|
||||
|
||||
|
||||
# [DEF:_resolve_dashboard_id_from_ref_async:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve dashboard ID asynchronously from slug-or-id reference for hot Git routes.
|
||||
# @PRE: dashboard_ref is provided; env_id is required for slug values.
|
||||
# @POST: Returns numeric dashboard ID or raises HTTPException.
|
||||
@@ -254,7 +254,7 @@ async def _resolve_dashboard_id_from_ref_async(
|
||||
|
||||
|
||||
# [DEF:_resolve_repo_key_from_ref:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve repository folder key with slug-first strategy and deterministic fallback.
|
||||
# @PRE: dashboard_id is resolved and valid.
|
||||
# @POST: Returns safe key to be used in local repository path.
|
||||
@@ -287,7 +287,7 @@ def _resolve_repo_key_from_ref(
|
||||
|
||||
|
||||
# [DEF:_sanitize_optional_identity_value:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Normalize optional identity value into trimmed string or None.
|
||||
# @PRE: value may be None or blank.
|
||||
# @POST: Returns sanitized value suitable for git identity configuration.
|
||||
@@ -301,7 +301,7 @@ def _sanitize_optional_identity_value(value: Optional[str]) -> Optional[str]:
|
||||
|
||||
|
||||
# [DEF:_resolve_current_user_git_identity:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve configured Git username/email from current user's profile preferences.
|
||||
# @PRE: `db` may be stubbed in tests; `current_user` may be absent for direct handler invocations.
|
||||
# @POST: Returns tuple(username, email) only when both values are configured.
|
||||
@@ -343,7 +343,7 @@ def _resolve_current_user_git_identity(
|
||||
|
||||
|
||||
# [DEF:_apply_git_identity_from_profile:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Apply user-scoped Git identity to repository-local config before write/pull operations.
|
||||
# @PRE: dashboard_id is resolved; db/current_user may be missing in direct test invocation context.
|
||||
# @POST: git_service.configure_identity is called only when identity and method are available.
|
||||
@@ -367,7 +367,7 @@ def _apply_git_identity_from_profile(
|
||||
|
||||
|
||||
# [DEF:get_git_configs:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: List all configured Git servers.
|
||||
# @PRE: Database session `db` is available.
|
||||
# @POST: Returns a list of all GitServerConfig objects from the database.
|
||||
@@ -388,7 +388,7 @@ async def get_git_configs(
|
||||
# [/DEF:get_git_configs:Function]
|
||||
|
||||
# [DEF:create_git_config:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Register a new Git server configuration.
|
||||
# @PRE: `config` contains valid GitServerConfigCreate data.
|
||||
# @POST: A new GitServerConfig record is created in the database.
|
||||
@@ -410,7 +410,7 @@ async def create_git_config(
|
||||
# [/DEF:create_git_config:Function]
|
||||
|
||||
# [DEF:update_git_config:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Update an existing Git server configuration.
|
||||
# @PRE: `config_id` corresponds to an existing configuration.
|
||||
# @POST: The configuration record is updated in the database.
|
||||
@@ -445,7 +445,7 @@ async def update_git_config(
|
||||
# [/DEF:update_git_config:Function]
|
||||
|
||||
# [DEF:delete_git_config:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Remove a Git server configuration.
|
||||
# @PRE: `config_id` corresponds to an existing configuration.
|
||||
# @POST: The configuration record is removed from the database.
|
||||
@@ -467,7 +467,7 @@ async def delete_git_config(
|
||||
# [/DEF:delete_git_config:Function]
|
||||
|
||||
# [DEF:test_git_config:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Validate connection to a Git server using provided credentials.
|
||||
# @PRE: `config` contains provider, url, and pat.
|
||||
# @POST: Returns success if the connection is validated via GitService.
|
||||
@@ -499,7 +499,7 @@ async def test_git_config(
|
||||
|
||||
|
||||
# [DEF:list_gitea_repositories:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: List repositories in Gitea for a saved Gitea config.
|
||||
# @PRE: config_id exists and provider is GITEA.
|
||||
# @POST: Returns repositories visible to PAT user.
|
||||
@@ -530,7 +530,7 @@ async def list_gitea_repositories(
|
||||
|
||||
|
||||
# [DEF:create_gitea_repository:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Create a repository in Gitea for a saved Gitea config.
|
||||
# @PRE: config_id exists and provider is GITEA.
|
||||
# @POST: Returns created repository payload.
|
||||
@@ -567,7 +567,7 @@ async def create_gitea_repository(
|
||||
|
||||
|
||||
# [DEF:create_remote_repository:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Create repository on remote Git server using selected provider config.
|
||||
# @PRE: config_id exists and PAT has creation permissions.
|
||||
# @POST: Returns normalized remote repository payload.
|
||||
@@ -628,7 +628,7 @@ async def create_remote_repository(
|
||||
|
||||
|
||||
# [DEF:delete_gitea_repository:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Delete repository in Gitea for a saved Gitea config.
|
||||
# @PRE: config_id exists and provider is GITEA.
|
||||
# @POST: Target repository is deleted on Gitea.
|
||||
@@ -654,7 +654,7 @@ async def delete_gitea_repository(
|
||||
# [/DEF:delete_gitea_repository:Function]
|
||||
|
||||
# [DEF:init_repository:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Link a dashboard to a Git repository and perform initial clone/init.
|
||||
# @PRE: `dashboard_ref` exists and `init_data` contains valid config_id and remote_url.
|
||||
# @POST: Repository is initialized on disk and a GitRepository record is saved in DB.
|
||||
@@ -712,7 +712,7 @@ async def init_repository(
|
||||
# [/DEF:init_repository:Function]
|
||||
|
||||
# [DEF:get_repository_binding:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Return repository binding with provider metadata for selected dashboard.
|
||||
# @PRE: `dashboard_ref` resolves to a valid dashboard and repository is initialized.
|
||||
# @POST: Returns dashboard repository binding and linked provider.
|
||||
@@ -747,7 +747,7 @@ async def get_repository_binding(
|
||||
# [/DEF:get_repository_binding:Function]
|
||||
|
||||
# [DEF:delete_repository:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Delete local repository workspace and DB binding for selected dashboard.
|
||||
# @PRE: `dashboard_ref` resolves to a valid dashboard.
|
||||
# @POST: Repository files and binding record are removed when present.
|
||||
@@ -772,7 +772,7 @@ async def delete_repository(
|
||||
# [/DEF:delete_repository:Function]
|
||||
|
||||
# [DEF:get_branches:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: List all branches for a dashboard's repository.
|
||||
# @PRE: Repository for `dashboard_ref` is initialized.
|
||||
# @POST: Returns a list of branches from the local repository.
|
||||
@@ -796,7 +796,7 @@ async def get_branches(
|
||||
# [/DEF:get_branches:Function]
|
||||
|
||||
# [DEF:create_branch:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Create a new branch in the dashboard's repository.
|
||||
# @PRE: `dashboard_ref` repository exists and `branch_data` has name and from_branch.
|
||||
# @POST: A new branch is created in the local repository.
|
||||
@@ -825,7 +825,7 @@ async def create_branch(
|
||||
# [/DEF:create_branch:Function]
|
||||
|
||||
# [DEF:checkout_branch:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Switch the dashboard's repository to a specific branch.
|
||||
# @PRE: `dashboard_ref` repository exists and branch `checkout_data.name` exists.
|
||||
# @POST: The local repository HEAD is moved to the specified branch.
|
||||
@@ -851,7 +851,7 @@ async def checkout_branch(
|
||||
# [/DEF:checkout_branch:Function]
|
||||
|
||||
# [DEF:commit_changes:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Stage and commit changes in the dashboard's repository.
|
||||
# @PRE: `dashboard_ref` repository exists and `commit_data` has message and files.
|
||||
# @POST: Specified files are staged and a new commit is created.
|
||||
@@ -880,7 +880,7 @@ async def commit_changes(
|
||||
# [/DEF:commit_changes:Function]
|
||||
|
||||
# [DEF:push_changes:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Push local commits to the remote repository.
|
||||
# @PRE: `dashboard_ref` repository exists and has a remote configured.
|
||||
# @POST: Local commits are pushed to the remote repository.
|
||||
@@ -904,7 +904,7 @@ async def push_changes(
|
||||
# [/DEF:push_changes:Function]
|
||||
|
||||
# [DEF:pull_changes:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Pull changes from the remote repository.
|
||||
# @PRE: `dashboard_ref` repository exists and has a remote configured.
|
||||
# @POST: Remote changes are fetched and merged into the local branch.
|
||||
@@ -952,7 +952,7 @@ async def pull_changes(
|
||||
# [/DEF:pull_changes:Function]
|
||||
|
||||
# [DEF:get_merge_status:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Return unfinished-merge status for repository (web-only recovery support).
|
||||
# @PRE: `dashboard_ref` resolves to a valid dashboard repository.
|
||||
# @POST: Returns merge status payload.
|
||||
@@ -975,7 +975,7 @@ async def get_merge_status(
|
||||
|
||||
|
||||
# [DEF:get_merge_conflicts:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Return conflicted files with mine/theirs previews for web conflict resolver.
|
||||
# @PRE: `dashboard_ref` resolves to a valid dashboard repository.
|
||||
# @POST: Returns conflict file list.
|
||||
@@ -998,7 +998,7 @@ async def get_merge_conflicts(
|
||||
|
||||
|
||||
# [DEF:resolve_merge_conflicts:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Apply mine/theirs/manual conflict resolutions from WebUI and stage files.
|
||||
# @PRE: `dashboard_ref` resolves; request contains at least one resolution item.
|
||||
# @POST: Resolved files are staged in index.
|
||||
@@ -1026,7 +1026,7 @@ async def resolve_merge_conflicts(
|
||||
|
||||
|
||||
# [DEF:abort_merge:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Abort unfinished merge from WebUI flow.
|
||||
# @PRE: `dashboard_ref` resolves to repository.
|
||||
# @POST: Merge operation is aborted or reports no active merge.
|
||||
@@ -1049,7 +1049,7 @@ async def abort_merge(
|
||||
|
||||
|
||||
# [DEF:continue_merge:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Finalize unfinished merge from WebUI flow.
|
||||
# @PRE: All conflicts are resolved and staged.
|
||||
# @POST: Merge commit is created.
|
||||
@@ -1073,7 +1073,7 @@ async def continue_merge(
|
||||
|
||||
|
||||
# [DEF:sync_dashboard:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Sync dashboard state from Superset to Git using the GitPlugin.
|
||||
# @PRE: `dashboard_ref` is valid; GitPlugin is available.
|
||||
# @POST: Dashboard YAMLs are exported from Superset and committed to Git.
|
||||
@@ -1105,7 +1105,7 @@ async def sync_dashboard(
|
||||
|
||||
|
||||
# [DEF:promote_dashboard:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Promote changes between branches via MR or direct merge.
|
||||
# @PRE: dashboard repository is initialized and Git config is valid.
|
||||
# @POST: Returns promotion result metadata.
|
||||
@@ -1208,7 +1208,7 @@ async def promote_dashboard(
|
||||
# [/DEF:promote_dashboard:Function]
|
||||
|
||||
# [DEF:get_environments:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: List all deployment environments.
|
||||
# @PRE: Config manager is accessible.
|
||||
# @POST: Returns a list of DeploymentEnvironmentSchema objects.
|
||||
@@ -1231,7 +1231,7 @@ async def get_environments(
|
||||
# [/DEF:get_environments:Function]
|
||||
|
||||
# [DEF:deploy_dashboard:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Deploy dashboard from Git to a target environment.
|
||||
# @PRE: `dashboard_ref` and `deploy_data.environment_id` are valid.
|
||||
# @POST: Dashboard YAMLs are read from Git and imported into the target Superset.
|
||||
@@ -1262,7 +1262,7 @@ async def deploy_dashboard(
|
||||
# [/DEF:deploy_dashboard:Function]
|
||||
|
||||
# [DEF:get_history:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: View commit history for a dashboard's repository.
|
||||
# @PRE: `dashboard_ref` repository exists.
|
||||
# @POST: Returns a list of recent commits from the repository.
|
||||
@@ -1288,7 +1288,7 @@ async def get_history(
|
||||
# [/DEF:get_history:Function]
|
||||
|
||||
# [DEF:get_repository_status:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get current Git status for a dashboard repository.
|
||||
# @PRE: `dashboard_ref` resolves to a valid dashboard.
|
||||
# @POST: Returns repository status; if repo is not initialized, returns `NO_REPO` payload.
|
||||
@@ -1313,7 +1313,7 @@ async def get_repository_status(
|
||||
|
||||
|
||||
# [DEF:get_repository_status_batch:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get Git statuses for multiple dashboard repositories in one request.
|
||||
# @PRE: `request.dashboard_ids` is provided.
|
||||
# @POST: Returns `statuses` map where each key is dashboard ID and value is repository status payload.
|
||||
@@ -1357,7 +1357,7 @@ async def get_repository_status_batch(
|
||||
# [/DEF:get_repository_status_batch:Function]
|
||||
|
||||
# [DEF:get_repository_diff:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get Git diff for a dashboard repository.
|
||||
# @PRE: `dashboard_ref` repository exists.
|
||||
# @POST: Returns the diff text for the specified file or all changes.
|
||||
@@ -1386,7 +1386,7 @@ async def get_repository_diff(
|
||||
# [/DEF:get_repository_diff:Function]
|
||||
|
||||
# [DEF:generate_commit_message:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Generate a suggested commit message using LLM.
|
||||
# @PRE: Repository for `dashboard_ref` is initialized.
|
||||
# @POST: Returns a suggested commit message string.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.git_schemas:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: git, schemas, pydantic, api, contracts
|
||||
# @PURPOSE: Defines Pydantic models for the Git integration API layer.
|
||||
# @LAYER: API
|
||||
@@ -14,7 +14,7 @@ from datetime import datetime
|
||||
from src.models.git import GitProvider, GitStatus, SyncStatus
|
||||
|
||||
# [DEF:GitServerConfigBase:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Base schema for Git server configuration attributes.
|
||||
class GitServerConfigBase(BaseModel):
|
||||
name: str = Field(..., description="Display name for the Git server")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:health_router:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: health, monitoring, dashboards
|
||||
# @PURPOSE: API endpoints for dashboard health monitoring and status aggregation.
|
||||
# @LAYER: UI/API
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend/src/api/routes/llm.py:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, routes, llm
|
||||
# @PURPOSE: API routes for LLM provider configuration and management.
|
||||
# @LAYER: UI (API)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.mappings:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, mappings, database, fuzzy-matching
|
||||
# @PURPOSE: API endpoints for managing database mappings and getting suggestions.
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:backend.src.api.routes.migration:Module]
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @SEMANTICS: api, migration, dashboards, sync, dry-run
|
||||
# @PURPOSE: HTTP contract layer for migration orchestration, settings, dry-run, and mapping sync endpoints.
|
||||
# @LAYER: Infra
|
||||
@@ -38,7 +38,7 @@ from ...models.mapping import ResourceMapping
|
||||
router = APIRouter(prefix="/api", tags=["migration"])
|
||||
|
||||
# [DEF:get_dashboards:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Fetch dashboard metadata from a requested environment for migration selection UI.
|
||||
# @PRE: env_id is provided and exists in configured environments.
|
||||
# @POST: Returns List[DashboardMetadata] for the resolved environment; emits HTTP_404 when environment is absent.
|
||||
@@ -66,7 +66,7 @@ async def get_dashboards(
|
||||
# [/DEF:get_dashboards:Function]
|
||||
|
||||
# [DEF:execute_migration:Function]
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @PURPOSE: Validate migration selection and enqueue asynchronous migration task execution.
|
||||
# @PRE: DashboardSelection payload is valid and both source/target environments exist.
|
||||
# @POST: Returns {"task_id": str, "message": str} when task creation succeeds; emits HTTP_400/HTTP_500 on failure.
|
||||
@@ -108,7 +108,7 @@ async def execute_migration(
|
||||
|
||||
|
||||
# [DEF:dry_run_migration:Function]
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @PURPOSE: Build pre-flight migration diff and risk summary without mutating target systems.
|
||||
# @PRE: DashboardSelection is valid, source and target environments exist, differ, and selected_ids is non-empty.
|
||||
# @POST: Returns deterministic dry-run payload; emits HTTP_400 for guard violations and HTTP_500 for orchestrator value errors.
|
||||
@@ -160,7 +160,7 @@ async def dry_run_migration(
|
||||
# [/DEF:dry_run_migration:Function]
|
||||
|
||||
# [DEF:get_migration_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Read and return configured migration synchronization cron expression.
|
||||
# @PRE: Configuration store is available and requester has READ permission.
|
||||
# @POST: Returns {"cron": str} reflecting current persisted settings value.
|
||||
@@ -178,7 +178,7 @@ async def get_migration_settings(
|
||||
# [/DEF:get_migration_settings:Function]
|
||||
|
||||
# [DEF:update_migration_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Validate and persist migration synchronization cron expression update.
|
||||
# @PRE: Payload includes "cron" key and requester has WRITE permission.
|
||||
# @POST: Returns {"cron": str, "status": "updated"} and persists updated cron value.
|
||||
@@ -204,7 +204,7 @@ async def update_migration_settings(
|
||||
# [/DEF:update_migration_settings:Function]
|
||||
|
||||
# [DEF:get_resource_mappings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Fetch synchronized resource mappings with optional filters and pagination for migration mappings view.
|
||||
# @PRE: skip>=0, 1<=limit<=500, DB session is active, requester has READ permission.
|
||||
# @POST: Returns {"items": [...], "total": int} where items reflect applied filters and pagination.
|
||||
@@ -255,7 +255,7 @@ async def get_resource_mappings(
|
||||
# [/DEF:get_resource_mappings:Function]
|
||||
|
||||
# [DEF:trigger_sync_now:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Trigger immediate ID synchronization for every configured environment.
|
||||
# @PRE: At least one environment is configured and requester has EXECUTE permission.
|
||||
# @POST: Returns sync summary with synced/failed counts after attempting all environments.
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
# [DEF:PluginsRouter:Module]
|
||||
# @TIER: STANDARD
|
||||
# @SEMANTICS: api, router, plugins, list
|
||||
# @PURPOSE: Defines the FastAPI router for plugin-related endpoints, allowing clients to list available plugins.
|
||||
# @LAYER: UI (API)
|
||||
# @RELATION: Depends on the PluginLoader and PluginConfig. It is included by the main app.
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from ...core.plugin_base import PluginConfig
|
||||
from ...dependencies import get_plugin_loader, has_permission
|
||||
from ...core.logger import belief_scope
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# [DEF:list_plugins:Function]
|
||||
# @PURPOSE: Retrieve a list of all available plugins.
|
||||
# @PRE: plugin_loader is injected via Depends.
|
||||
# @POST: Returns a list of PluginConfig objects.
|
||||
# @RETURN: List[PluginConfig] - List of registered plugins.
|
||||
@router.get("", response_model=List[PluginConfig])
|
||||
async def list_plugins(
|
||||
plugin_loader = Depends(get_plugin_loader),
|
||||
_ = Depends(has_permission("plugins", "READ"))
|
||||
):
|
||||
with belief_scope("list_plugins"):
|
||||
"""
|
||||
Retrieve a list of all available plugins.
|
||||
"""
|
||||
return plugin_loader.get_all_plugin_configs()
|
||||
# [/DEF:list_plugins:Function]
|
||||
# [DEF:PluginsRouter:Module]
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: api, router, plugins, list
|
||||
# @PURPOSE: Defines the FastAPI router for plugin-related endpoints, allowing clients to list available plugins.
|
||||
# @LAYER: UI (API)
|
||||
# @RELATION: Depends on the PluginLoader and PluginConfig. It is included by the main app.
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from ...core.plugin_base import PluginConfig
|
||||
from ...dependencies import get_plugin_loader, has_permission
|
||||
from ...core.logger import belief_scope
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# [DEF:list_plugins:Function]
|
||||
# @PURPOSE: Retrieve a list of all available plugins.
|
||||
# @PRE: plugin_loader is injected via Depends.
|
||||
# @POST: Returns a list of PluginConfig objects.
|
||||
# @RETURN: List[PluginConfig] - List of registered plugins.
|
||||
@router.get("", response_model=List[PluginConfig])
|
||||
async def list_plugins(
|
||||
plugin_loader = Depends(get_plugin_loader),
|
||||
_ = Depends(has_permission("plugins", "READ"))
|
||||
):
|
||||
with belief_scope("list_plugins"):
|
||||
"""
|
||||
Retrieve a list of all available plugins.
|
||||
"""
|
||||
return plugin_loader.get_all_plugin_configs()
|
||||
# [/DEF:list_plugins:Function]
|
||||
# [/DEF:PluginsRouter:Module]
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:backend.src.api.routes.profile:Module]
|
||||
#
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @SEMANTICS: api, profile, preferences, self-service, account-lookup
|
||||
# @PURPOSE: Exposes self-scoped profile preference endpoints and environment-based Superset account lookup.
|
||||
# @LAYER: API
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:ReportsRouter:Module]
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @SEMANTICS: api, reports, list, detail, pagination, filters
|
||||
# @PURPOSE: FastAPI router for unified task report list and detail retrieval endpoints.
|
||||
# @LAYER: UI (API)
|
||||
@@ -29,7 +29,7 @@ router = APIRouter(prefix="/api/reports", tags=["Reports"])
|
||||
|
||||
|
||||
# [DEF:_parse_csv_enum_list:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Parse comma-separated query value into enum list.
|
||||
# @PRE: raw may be None/empty or comma-separated values.
|
||||
# @POST: Returns enum list or raises HTTP 400 with deterministic machine-readable payload.
|
||||
@@ -64,7 +64,7 @@ def _parse_csv_enum_list(raw: Optional[str], enum_cls, field_name: str) -> List:
|
||||
|
||||
|
||||
# [DEF:list_reports:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Return paginated unified reports list.
|
||||
# @PRE: authenticated/authorized request and validated query params.
|
||||
# @POST: returns {items,total,page,page_size,has_next,applied_filters}.
|
||||
@@ -131,7 +131,7 @@ async def list_reports(
|
||||
|
||||
|
||||
# [DEF:get_report_detail:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Return one normalized report detail with diagnostics and next actions.
|
||||
# @PRE: authenticated/authorized request and existing report_id.
|
||||
# @POST: returns normalized detail envelope or 404 when report is not found.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:SettingsRouter:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: settings, api, router, fastapi
|
||||
# @PURPOSE: Provides API endpoints for managing application settings and Superset environments.
|
||||
# @LAYER: UI (API)
|
||||
@@ -29,7 +29,7 @@ from sqlalchemy.orm import Session
|
||||
# [/SECTION]
|
||||
|
||||
# [DEF:LoggingConfigResponse:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Response model for logging configuration with current task log level.
|
||||
# @SEMANTICS: logging, config, response
|
||||
class LoggingConfigResponse(BaseModel):
|
||||
@@ -42,7 +42,7 @@ router = APIRouter()
|
||||
|
||||
|
||||
# [DEF:_normalize_superset_env_url:Function]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Canonicalize Superset environment URL to base host/path without trailing /api/v1.
|
||||
# @PRE: raw_url can be empty.
|
||||
# @POST: Returns normalized base URL.
|
||||
@@ -55,7 +55,7 @@ def _normalize_superset_env_url(raw_url: str) -> str:
|
||||
|
||||
|
||||
# [DEF:_validate_superset_connection_fast:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Run lightweight Superset connectivity validation without full pagination scan.
|
||||
# @PRE: env contains valid URL and credentials.
|
||||
# @POST: Raises on auth/API failures; returns None on success.
|
||||
@@ -74,7 +74,7 @@ def _validate_superset_connection_fast(env: Environment) -> None:
|
||||
# [/DEF:_validate_superset_connection_fast:Function]
|
||||
|
||||
# [DEF:get_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieves all application settings.
|
||||
# @PRE: Config manager is available.
|
||||
# @POST: Returns masked AppConfig.
|
||||
@@ -96,7 +96,7 @@ async def get_settings(
|
||||
# [/DEF:get_settings:Function]
|
||||
|
||||
# [DEF:update_global_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates global application settings.
|
||||
# @PRE: New settings are provided.
|
||||
# @POST: Global settings are updated.
|
||||
@@ -116,7 +116,7 @@ async def update_global_settings(
|
||||
# [/DEF:update_global_settings:Function]
|
||||
|
||||
# [DEF:get_storage_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieves storage-specific settings.
|
||||
# @RETURN: StorageConfig - The storage configuration.
|
||||
@router.get("/storage", response_model=StorageConfig)
|
||||
@@ -129,7 +129,7 @@ async def get_storage_settings(
|
||||
# [/DEF:get_storage_settings:Function]
|
||||
|
||||
# [DEF:update_storage_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates storage-specific settings.
|
||||
# @PARAM: storage (StorageConfig) - The new storage settings.
|
||||
# @POST: Storage settings are updated and saved.
|
||||
@@ -152,7 +152,7 @@ async def update_storage_settings(
|
||||
# [/DEF:update_storage_settings:Function]
|
||||
|
||||
# [DEF:get_environments:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Lists all configured Superset environments.
|
||||
# @PRE: Config manager is available.
|
||||
# @POST: Returns list of environments.
|
||||
@@ -172,7 +172,7 @@ async def get_environments(
|
||||
# [/DEF:get_environments:Function]
|
||||
|
||||
# [DEF:add_environment:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Adds a new Superset environment.
|
||||
# @PRE: Environment data is valid and reachable.
|
||||
# @POST: Environment is added to config.
|
||||
@@ -200,7 +200,7 @@ async def add_environment(
|
||||
# [/DEF:add_environment:Function]
|
||||
|
||||
# [DEF:update_environment:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates an existing Superset environment.
|
||||
# @PRE: ID and valid environment data are provided.
|
||||
# @POST: Environment is updated in config.
|
||||
@@ -238,7 +238,7 @@ async def update_environment(
|
||||
# [/DEF:update_environment:Function]
|
||||
|
||||
# [DEF:delete_environment:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Deletes a Superset environment.
|
||||
# @PRE: ID is provided.
|
||||
# @POST: Environment is removed from config.
|
||||
@@ -255,7 +255,7 @@ async def delete_environment(
|
||||
# [/DEF:delete_environment:Function]
|
||||
|
||||
# [DEF:test_environment_connection:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Tests the connection to a Superset environment.
|
||||
# @PRE: ID is provided.
|
||||
# @POST: Returns success or error status.
|
||||
@@ -285,7 +285,7 @@ async def test_environment_connection(
|
||||
# [/DEF:test_environment_connection:Function]
|
||||
|
||||
# [DEF:get_logging_config:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieves current logging configuration.
|
||||
# @PRE: Config manager is available.
|
||||
# @POST: Returns logging configuration.
|
||||
@@ -305,7 +305,7 @@ async def get_logging_config(
|
||||
# [/DEF:get_logging_config:Function]
|
||||
|
||||
# [DEF:update_logging_config:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates logging configuration.
|
||||
# @PRE: New logging config is provided.
|
||||
# @POST: Logging configuration is updated and saved.
|
||||
@@ -333,7 +333,7 @@ async def update_logging_config(
|
||||
# [/DEF:update_logging_config:Function]
|
||||
|
||||
# [DEF:ConsolidatedSettingsResponse:Class]
|
||||
# @TIER: TRIVIAL
|
||||
# @COMPLEXITY: 1
|
||||
# @PURPOSE: Response model for consolidated application settings.
|
||||
class ConsolidatedSettingsResponse(BaseModel):
|
||||
environments: List[dict]
|
||||
@@ -346,7 +346,7 @@ class ConsolidatedSettingsResponse(BaseModel):
|
||||
# [/DEF:ConsolidatedSettingsResponse:Class]
|
||||
|
||||
# [DEF:get_consolidated_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieves all settings categories in a single call
|
||||
# @PRE: Config manager is available.
|
||||
# @POST: Returns all consolidated settings.
|
||||
@@ -400,7 +400,7 @@ async def get_consolidated_settings(
|
||||
# [/DEF:get_consolidated_settings:Function]
|
||||
|
||||
# [DEF:update_consolidated_settings:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Bulk update application settings from the consolidated view.
|
||||
# @PRE: User has admin permissions, config is valid.
|
||||
# @POST: Settings are updated and saved via ConfigManager.
|
||||
@@ -446,7 +446,7 @@ async def update_consolidated_settings(
|
||||
# [/DEF:update_consolidated_settings:Function]
|
||||
|
||||
# [DEF:get_validation_policies:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Lists all validation policies.
|
||||
# @RETURN: List[ValidationPolicyResponse] - List of policies.
|
||||
@router.get("/automation/policies", response_model=List[ValidationPolicyResponse])
|
||||
@@ -459,7 +459,7 @@ async def get_validation_policies(
|
||||
# [/DEF:get_validation_policies:Function]
|
||||
|
||||
# [DEF:create_validation_policy:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Creates a new validation policy.
|
||||
# @PARAM: policy (ValidationPolicyCreate) - The policy data.
|
||||
# @RETURN: ValidationPolicyResponse - The created policy.
|
||||
@@ -478,7 +478,7 @@ async def create_validation_policy(
|
||||
# [/DEF:create_validation_policy:Function]
|
||||
|
||||
# [DEF:update_validation_policy:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Updates an existing validation policy.
|
||||
# @PARAM: id (str) - The ID of the policy to update.
|
||||
# @PARAM: policy (ValidationPolicyUpdate) - The updated policy data.
|
||||
@@ -505,7 +505,7 @@ async def update_validation_policy(
|
||||
# [/DEF:update_validation_policy:Function]
|
||||
|
||||
# [DEF:delete_validation_policy:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Deletes a validation policy.
|
||||
# @PARAM: id (str) - The ID of the policy to delete.
|
||||
@router.delete("/automation/policies/{id}")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# [DEF:storage_routes:Module]
|
||||
#
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: storage, files, upload, download, backup, repository
|
||||
# @PURPOSE: API endpoints for file storage management (backups and repositories).
|
||||
# @LAYER: API
|
||||
@@ -22,7 +22,7 @@ from ...core.logger import belief_scope
|
||||
router = APIRouter(tags=["storage"])
|
||||
|
||||
# [DEF:list_files:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: List all files and directories in the storage system.
|
||||
#
|
||||
# @PRE: None.
|
||||
@@ -49,7 +49,7 @@ async def list_files(
|
||||
# [/DEF:list_files:Function]
|
||||
|
||||
# [DEF:upload_file:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Upload a file to the storage system.
|
||||
#
|
||||
# @PRE: category must be a valid FileCategory.
|
||||
@@ -83,7 +83,7 @@ async def upload_file(
|
||||
# [/DEF:upload_file:Function]
|
||||
|
||||
# [DEF:delete_file:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Delete a specific file or directory.
|
||||
#
|
||||
# @PRE: category must be a valid FileCategory.
|
||||
@@ -116,7 +116,7 @@ async def delete_file(
|
||||
# [/DEF:delete_file:Function]
|
||||
|
||||
# [DEF:download_file:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieve a file for download.
|
||||
#
|
||||
# @PRE: category must be a valid FileCategory.
|
||||
@@ -149,7 +149,7 @@ async def download_file(
|
||||
# [/DEF:download_file:Function]
|
||||
|
||||
# [DEF:get_file_by_path:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieve a file by validated absolute/relative path under storage root.
|
||||
#
|
||||
# @PRE: path must resolve under configured storage root.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# [DEF:TasksRouter:Module]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 4
|
||||
# @SEMANTICS: api, router, tasks, create, list, get, logs
|
||||
# @PURPOSE: Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks.
|
||||
# @LAYER: UI (API)
|
||||
@@ -43,7 +43,7 @@ class ResumeTaskRequest(BaseModel):
|
||||
passwords: Dict[str, str]
|
||||
|
||||
# [DEF:create_task:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Create and start a new task for a given plugin.
|
||||
# @PARAM: request (CreateTaskRequest) - The request body containing plugin_id and params.
|
||||
# @PARAM: task_manager (TaskManager) - The task manager instance.
|
||||
@@ -107,7 +107,7 @@ async def create_task(
|
||||
# [/DEF:create_task:Function]
|
||||
|
||||
# [DEF:list_tasks:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieve a list of tasks with pagination and optional status filter.
|
||||
# @PARAM: limit (int) - Maximum number of tasks to return.
|
||||
# @PARAM: offset (int) - Number of tasks to skip.
|
||||
@@ -147,7 +147,7 @@ async def list_tasks(
|
||||
# [/DEF:list_tasks:Function]
|
||||
|
||||
# [DEF:get_task:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Retrieve the details of a specific task.
|
||||
# @PARAM: task_id (str) - The unique identifier of the task.
|
||||
# @PARAM: task_manager (TaskManager) - The task manager instance.
|
||||
@@ -168,7 +168,7 @@ async def get_task(
|
||||
# [/DEF:get_task:Function]
|
||||
|
||||
# [DEF:get_task_logs:Function]
|
||||
# @TIER: CRITICAL
|
||||
# @COMPLEXITY: 5
|
||||
# @PURPOSE: Retrieve logs for a specific task with optional filtering.
|
||||
# @PARAM: task_id (str) - The unique identifier of the task.
|
||||
# @PARAM: level (Optional[str]) - Filter by log level (DEBUG, INFO, WARNING, ERROR).
|
||||
@@ -214,7 +214,7 @@ async def get_task_logs(
|
||||
# [/DEF:get_task_logs:Function]
|
||||
|
||||
# [DEF:get_task_log_stats:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get statistics about logs for a task (counts by level and source).
|
||||
# @PARAM: task_id (str) - The unique identifier of the task.
|
||||
# @PARAM: task_manager (TaskManager) - The task manager instance.
|
||||
@@ -235,7 +235,7 @@ async def get_task_log_stats(
|
||||
# [/DEF:get_task_log_stats:Function]
|
||||
|
||||
# [DEF:get_task_log_sources:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Get unique sources for a task's logs.
|
||||
# @PARAM: task_id (str) - The unique identifier of the task.
|
||||
# @PARAM: task_manager (TaskManager) - The task manager instance.
|
||||
@@ -256,7 +256,7 @@ async def get_task_log_sources(
|
||||
# [/DEF:get_task_log_sources:Function]
|
||||
|
||||
# [DEF:resolve_task:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resolve a task that is awaiting mapping.
|
||||
# @PARAM: task_id (str) - The unique identifier of the task.
|
||||
# @PARAM: request (ResolveTaskRequest) - The resolution parameters.
|
||||
@@ -280,7 +280,7 @@ async def resolve_task(
|
||||
# [/DEF:resolve_task:Function]
|
||||
|
||||
# [DEF:resume_task:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Resume a task that is awaiting input (e.g., passwords).
|
||||
# @PARAM: task_id (str) - The unique identifier of the task.
|
||||
# @PARAM: request (ResumeTaskRequest) - The input (passwords).
|
||||
@@ -304,7 +304,7 @@ async def resume_task(
|
||||
# [/DEF:resume_task:Function]
|
||||
|
||||
# [DEF:clear_tasks:Function]
|
||||
# @TIER: STANDARD
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Clear tasks matching the status filter.
|
||||
# @PARAM: status (Optional[TaskStatus]) - Filter by task status.
|
||||
# @PARAM: task_manager (TaskManager) - The task manager instance.
|
||||
|
||||
Reference in New Issue
Block a user