semantics

This commit is contained in:
2026-05-19 18:36:15 +03:00
parent 64feca2e46
commit b916ef94d5
79 changed files with 19791 additions and 11925 deletions

View File

@@ -1,12 +1,15 @@
# #region AuthApi [C:3] [TYPE Module] [SEMANTICS fastapi, auth, api]
#
# #region AuthApi [C:5] [TYPE Module] [SEMANTICS fastapi, auth, api]
# @BRIEF Authentication API endpoints.
# @LAYER: API
# @RELATION DEPENDS_ON -> [AuthService]
# @RELATION DEPENDS_ON -> [get_auth_db]
# @RELATION DEPENDS_ON -> [get_current_user]
# @LAYER API
# @RELATION DEPENDS_ON -> [is_adfs_configured]
# @INVARIANT: All auth endpoints must return consistent error codes.
# @RELATION DEPENDS_ON -> [is_adfs_configured]
# @RELATION DEPENDS_ON -> [is_adfs_configured]
# @RELATION DEPENDS_ON -> [is_adfs_configured]
# @PRE Python environment and dependencies installed; database available.
# @POST FastAPI app instance with auth routes registered.
# @SIDE_EFFECT Registers API routes; configures OAuth and CORS middleware.
# @DATA_CONTRACT Input -> OAuth2PasswordRequestForm -> Token, User
# @INVARIANT All auth endpoints must return consistent error codes.
import starlette.requests
from fastapi import APIRouter, Depends, HTTPException, status
@@ -29,12 +32,14 @@ router = APIRouter(prefix="/api/auth", tags=["auth"])
# #endregion router
# #region login_for_access_token [C:3] [TYPE Function]
# #region login_for_access_token [C:4] [TYPE Function]
# @BRIEF Authenticates a user and returns a JWT access token.
# @PRE: form_data contains username and password.
# @POST: Returns a Token object on success.
# @RELATION CALLS -> [AuthService.authenticate_user]
# @PRE form_data contains username and password.
# @POST Returns a Token object on success.
# @RELATION CALLS -> [AuthService.create_session]
# @RELATION CALLS -> [AuthService.create_session]
# @SIDE_EFFECT DB read/write for auth session; writes security event log.
@router.post("/login", response_model=Token)
async def login_for_access_token(
form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_auth_db)
@@ -58,11 +63,13 @@ async def login_for_access_token(
# #endregion login_for_access_token
# #region read_users_me [C:3] [TYPE Function]
# #region read_users_me [C:4] [TYPE Function]
# @BRIEF Retrieves the profile of the currently authenticated user.
# @PRE: Valid JWT token provided.
# @POST: Returns the current user's data.
# @PRE Valid JWT token provided.
# @POST Returns the current user's data.
# @RELATION DEPENDS_ON -> [get_current_user]
# @SIDE_EFFECT Reads current user from DB via auth middleware; writes security event log.
@router.get("/me", response_model=UserSchema)
async def read_users_me(current_user: UserSchema = Depends(get_current_user)):
with belief_scope("api.auth.me"):
@@ -72,11 +79,13 @@ async def read_users_me(current_user: UserSchema = Depends(get_current_user)):
# #endregion read_users_me
# #region logout [C:3] [TYPE Function]
# #region logout [C:4] [TYPE Function]
# @BRIEF Logs out the current user (placeholder for session revocation).
# @PRE: Valid JWT token provided.
# @POST: Returns success message.
# @PRE Valid JWT token provided.
# @POST Returns success message.
# @RELATION DEPENDS_ON -> [get_current_user]
# @SIDE_EFFECT Writes security event LOGOUT event.
@router.post("/logout")
async def logout(current_user: UserSchema = Depends(get_current_user)):
with belief_scope("api.auth.logout"):
@@ -89,10 +98,12 @@ async def logout(current_user: UserSchema = Depends(get_current_user)):
# #endregion logout
# #region login_adfs [C:3] [TYPE Function]
# #region login_adfs [C:4] [TYPE Function]
# @BRIEF Initiates the ADFS OIDC login flow.
# @POST: Redirects the user to ADFS.
# @POST Redirects the user to ADFS.
# @RELATION USES -> [is_adfs_configured]
# @SIDE_EFFECT Redirects user to ADFS external OIDC provider.
@router.get("/login/adfs")
async def login_adfs(request: starlette.requests.Request):
with belief_scope("api.auth.login_adfs"):
@@ -108,12 +119,14 @@ async def login_adfs(request: starlette.requests.Request):
# #endregion login_adfs
# #region auth_callback_adfs [C:3] [TYPE Function]
# #region auth_callback_adfs [C:4] [TYPE Function]
# @BRIEF Handles the callback from ADFS after successful authentication.
# @POST: Provisions user JIT and returns session token.
# @RELATION DEPENDS_ON -> [is_adfs_configured]
# @RELATION CALLS -> [AuthService.provision_adfs_user]
# @POST Provisions user JIT and returns session token.
# @RELATION CALLS -> [AuthService.create_session]
# @RELATION CALLS -> [AuthService.create_session]
# @RELATION CALLS -> [AuthService.create_session]
# @SIDE_EFFECT Provisions user in DB, creates auth session, writes security event log.
@router.get("/callback/adfs", name="auth_callback_adfs")
async def auth_callback_adfs(
request: starlette.requests.Request, db: Session = Depends(get_auth_db)

View File

@@ -1,8 +1,10 @@
# #region ApiRoutesModule [C:3] [TYPE Module] [SEMANTICS api, package, router, lazy, import]
# #region ApiRoutesModule [C:5] [TYPE Module] [SEMANTICS api, package, router, lazy, import]
# @BRIEF Provide lazy route module loading to avoid heavyweight imports during tests.
# @LAYER: API
# @RELATION CALLS -> [ApiRoutesGetAttr]
# @RELATION BINDS_TO -> [Route_Group_Contracts]
# @PRE: FastAPI app initialized, route modules available in package
# @POST: Route modules are lazily loadable via __getattr__
# @INVARIANT: Only names listed in __all__ are importable via __getattr__.
# #region Route_Group_Contracts [C:3] [TYPE Block]
@@ -13,6 +15,8 @@
# @RELATION DEPENDS_ON -> [ConnectionsRouter]
# @RELATION DEPENDS_ON -> [ReportsRouter]
# @RELATION DEPENDS_ON -> [LlmRoutes]
# @SIDE_EFFECT: Registers route group imports via __getattr__
# @DATA_CONTRACT: Package -> RouterModule mapping
__all__ = [
"admin",
"assistant",

View File

@@ -3,7 +3,7 @@ import os
os.environ["ENCRYPTION_KEY"] = "OnrCzomBWbIjTf7Y-fnhL2adlU55bHZQjp8zX5zBC5w="
# #region TestAssistantAuthz [TYPE Module] [C:3] [SEMANTICS tests, assistant, authz, confirmation, rbac]
# @BRIEF Verify assistant confirmation ownership, expiration, and deny behavior for restricted users.
# @LAYER: UI (API Tests)
# @LAYER: API
# @RELATION DEPENDS_ON -> AssistantApi
# @INVARIANT: Security-sensitive flows fail closed for unauthorized actors.
import asyncio

View File

@@ -1,6 +1,6 @@
# #region TestGitStatusRoute [TYPE Module] [C:3] [SEMANTICS tests, git, api, status, no_repo]
# @BRIEF Validate status endpoint behavior for missing and error repository states.
# @LAYER: Domain (Tests)
# @LAYER: Domain
# @RELATION VERIFIES -> [GitApi]
import asyncio
from unittest.mock import MagicMock

View File

@@ -1,7 +1,7 @@
# #region TestReportsApi [TYPE Module] [C:3] [SEMANTICS tests, reports, api, contract, pagination, filtering]
# @RELATION BELONGS_TO -> SrcRoot
# @BRIEF Contract tests for GET /api/reports defaults, pagination, and filtering behavior.
# @LAYER: Domain (Tests)
# @LAYER: Domain
# @INVARIANT: API response contract contains {items,total,page,page_size,has_next,applied_filters}.
from datetime import UTC, datetime, timedelta
from types import SimpleNamespace

View File

@@ -1,7 +1,7 @@
# #region TestReportsDetailApi [TYPE Module] [C:3] [SEMANTICS tests, reports, api, detail, diagnostics]
# @RELATION BELONGS_TO -> SrcRoot
# @BRIEF Contract tests for GET /api/reports/{report_id} detail endpoint behavior.
# @LAYER: Domain (Tests)
# @LAYER: Domain
# @INVARIANT: Detail endpoint tests must keep deterministic assertions for success and not-found contracts.
from datetime import datetime, timedelta
from types import SimpleNamespace

View File

@@ -1,7 +1,7 @@
# #region TestReportsOpenapiConformance [TYPE Module] [C:3] [SEMANTICS tests, reports, openapi, conformance]
# @RELATION BELONGS_TO -> SrcRoot
# @BRIEF Validate implemented reports payload shape against OpenAPI-required top-level contract fields.
# @LAYER: Domain (Tests)
# @LAYER: Domain
# @INVARIANT: List and detail payloads include required contract keys.
from datetime import datetime
from types import SimpleNamespace

View File

@@ -1,7 +1,7 @@
# #region test_tasks_logs_module [TYPE Module] [C:2] [SEMANTICS tests, tasks, logs, api, contract, validation]
# @RELATION VERIFIES -> [src.api.routes.tasks:Module]
# @BRIEF Contract testing for task logs API endpoints.
# @LAYER: Domain (Tests)
# @LAYER: Domain
from unittest.mock import MagicMock
import pytest

View File

@@ -1,7 +1,7 @@
# #region AdminApi [C:3] [TYPE Module] [SEMANTICS fastapi, admin, api, rbac, user]
# #region AdminApi [C:5] [TYPE Module] [SEMANTICS fastapi, admin, api, rbac, user]
#
# @BRIEF Admin API endpoints for user and role management.
# @LAYER: API
# @LAYER: API
# @RELATION DEPENDS_ON -> [AuthRepository:Class]
# @RELATION DEPENDS_ON -> [get_auth_db:Function]
# @RELATION DEPENDS_ON -> [has_permission:Function]

View File

@@ -1,10 +1,14 @@
# #region AssistantLlmPlanner [C:3] [TYPE Module] [SEMANTICS assistant, llm, planner, tool, catalog]
# #region AssistantLlmPlanner [C:5] [TYPE Module] [SEMANTICS assistant, llm, planner, tool, catalog]
# @BRIEF LLM-based intent planning, tool catalog construction, and authorization for the assistant API.
# @LAYER: API
# @RELATION DEPENDS_ON -> [AssistantSchemas]
# @RELATION DEPENDS_ON -> [AssistantResolvers]
# @RELATION DISPATCHES -> [AssistantLlmPlannerIntent]
# @PRE: Assistant routes initialized, user authenticated
# @POST: LLM tool catalog filtered and returned
# @INVARIANT: Tool catalog is filtered by user permissions before being sent to LLM.
# @SIDE_EFFECT: Filters tool catalog by user permissions
# @DATA_CONTRACT: UserPermissions -> ToolCatalog
from __future__ import annotations

View File

@@ -1,9 +1,13 @@
# #region AssistantLlmPlannerIntent [C:3] [TYPE Module] [SEMANTICS assistant, llm, intent, planning, authorization]
# #region AssistantLlmPlannerIntent [C:5] [TYPE Module] [SEMANTICS assistant, llm, intent, planning, authorization]
# @BRIEF LLM-based intent planning and authorization for the assistant API — separated from tool catalog.
# @LAYER: API
# @RELATION DEPENDS_ON -> [AssistantLlmPlanner]
# @RELATION DEPENDS_ON -> [AssistantResolvers]
# @PRE: Assistant routes initialized, user authenticated
# @POST: Intent planning registered with confirmation gate
# @INVARIANT: Production deployments always require confirmation.
# @SIDE_EFFECT: Registers intent planning routes
# @DATA_CONTRACT: UserIntent -> PlannedAction
from __future__ import annotations

View File

@@ -1,6 +1,6 @@
# #region CleanReleaseV2Api [C:4] [TYPE Module] [SEMANTICS fastapi, clean-release, candidate, lifecycle, api]
# @BRIEF Redesigned clean release API for headless candidate lifecycle.
# @LAYER: UI (API)
# @LAYER: API
# @RELATION DEPENDS_ON -> [CleanReleaseRepository]
# @RELATION CALLS -> [approve_candidate]
# @RELATION CALLS -> [publish_candidate]

View File

@@ -1,6 +1,6 @@
# #region ConnectionsRouter [C:3] [TYPE Module] [SEMANTICS fastapi, connection, api, search]
# @BRIEF Defines the FastAPI router for managing external database connections.
# @LAYER: UI (API)
# @LAYER: API
# @RELATION DEPENDS_ON -> [get_db]
# @RELATION DEPENDS_ON -> [ConnectionConfig]

View File

@@ -1,4 +1,4 @@
# #region DatasetsApi [C:3] [TYPE Module] [SEMANTICS fastapi, dataset, api, search, mapping, mapped-fields]
# #region DatasetsApi [C:5] [TYPE Module] [SEMANTICS fastapi, dataset, api, search, mapping, mapped-fields]
#
# @BRIEF API endpoints for the Dataset Hub - listing datasets with mapping progress
# @LAYER: API
@@ -6,6 +6,10 @@
# @RELATION DEPENDS_ON -> [ResourceService]
# @RELATION DEPENDS_ON -> [SupersetClient]
#
# @PRE SupersetClient is available; env_id is valid.
# @POST Returns dataset metadata with mapping status.
# @SIDE_EFFECT Reads from Superset API and task manager.
# @DATA_CONTRACT Input -> DatasetQuery, Output -> DatasetsResponse, DatasetDetailResponse
# @INVARIANT: All dataset responses include last_task metadata
@@ -102,7 +106,7 @@ class TaskResponse(BaseModel):
task_id: str
# #endregion TaskResponse
# #region get_dataset_ids [C:3] [TYPE Function]
# #region get_dataset_ids [C:4] [TYPE Function]
# @BRIEF 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
@@ -150,7 +154,7 @@ async def get_dataset_ids(
raise HTTPException(status_code=503, detail=f"Failed to fetch dataset IDs: {e!s}")
# #endregion get_dataset_ids
# #region get_datasets [C:3] [TYPE Function]
# #region get_datasets [C:4] [TYPE Function]
# @BRIEF 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
@@ -234,7 +238,7 @@ class MapColumnsRequest(BaseModel):
file_data: str | None = Field(None, description="File path or data for XLSX source")
# #endregion MapColumnsRequest
# #region map_columns [C:3] [TYPE Function]
# #region map_columns [C:4] [TYPE Function]
# @BRIEF Trigger bulk column mapping for datasets
# @PRE: User has permission plugin:mapper:execute
# @PRE: env_id is a valid environment ID
@@ -302,7 +306,7 @@ class GenerateDocsRequest(BaseModel):
options: dict | None = Field(None, description="Additional options for documentation generation")
# #endregion GenerateDocsRequest
# #region generate_docs [C:3] [TYPE Function]
# #region generate_docs [C:4] [TYPE Function]
# @BRIEF Trigger bulk documentation generation for datasets
# @PRE: User has permission plugin:llm_analysis:execute
# @PRE: env_id is a valid environment ID
@@ -355,7 +359,7 @@ async def generate_docs(
raise HTTPException(status_code=503, detail=f"Failed to create documentation generation task: {e!s}")
# #endregion generate_docs
# #region get_dataset_detail [C:3] [TYPE Function]
# #region get_dataset_detail [C:4] [TYPE Function]
# @BRIEF 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
@@ -381,6 +385,11 @@ async def get_dataset_detail(
client = SupersetClient(env)
dataset_detail = client.get_dataset_detail(dataset_id)
# Normalize 'database' field: Superset returns an object, model expects a string
if isinstance(dataset_detail.get("database"), dict):
db_obj = dataset_detail["database"]
dataset_detail["database"] = db_obj.get("database_name", str(db_obj.get("id", "")))
logger.info(f"[get_dataset_detail][Coherence:OK] Retrieved dataset {dataset_id} with {dataset_detail['column_count']} columns and {dataset_detail['linked_dashboard_count']} linked dashboards")
return DatasetDetailResponse(**dataset_detail)

View File

@@ -1,7 +1,7 @@
# #region EnvironmentsApi [C:3] [TYPE Module] [SEMANTICS fastapi, environment, api]
# #region EnvironmentsApi [C:5] [TYPE Module] [SEMANTICS fastapi, environment, api]
#
# @BRIEF API endpoints for listing environments and their databases.
# @LAYER: API
# @LAYER: API
# @RELATION DEPENDS_ON -> [AppDependencies]
# @RELATION DEPENDS_ON -> [SupersetClient]
#

View File

@@ -1,10 +1,14 @@
# #region GitPackage [C:3] [TYPE Module] [SEMANTICS git, api, package, sync]
# #region GitPackage [C:5] [TYPE Module] [SEMANTICS git, api, package, sync]
# @BRIEF Package root for decomposed git routes. Re-exports all public symbols from submodules.
# @LAYER: API
# @RELATION USES -> [GitRouter, GitDeps, GitHelpers, GitConfigRoutes, GitGiteaRoutes,
# GitRepoRoutes, GitRepoOperationsRoutes, GitRepoLifecycleRoutes,
# GitMergeRoutes, GitEnvironmentRoutes]
# @INVARIANT: git_service and os are module-level attributes for test monkeypatch compatibility.
# @PRE: Git service initialized
# @POST: Git API package exported
# @SIDE_EFFECT: Registers git route submodules
# @DATA_CONTRACT: GitRequest -> GitResponse
# All route functions are re-exported for direct access via `from src.api.routes import git`.
import os

View File

@@ -1,6 +1,6 @@
# #region LlmRoutes [C:3] [TYPE Module] [SEMANTICS fastapi, llm, api, provider]
# @BRIEF API routes for LLM provider configuration and management.
# @LAYER: UI (API)
# @LAYER: API
# @RELATION DEPENDS_ON -> [LLMProviderService]
# @RELATION DEPENDS_ON -> [LLMProviderConfig]
# @RELATION DEPENDS_ON -> [get_current_user]
@@ -30,10 +30,12 @@ class FetchModelsRequest(BaseModel):
# #endregion FetchModelsRequest
# #region router [TYPE Global]
# #region router [C:1] [TYPE Global]
# @BRIEF APIRouter instance for LLM routes.
router = APIRouter(tags=["LLM"])
# #endregion router
# #endregion router
# #region _is_valid_runtime_api_key [C:4] [TYPE Function]

View File

@@ -1,6 +1,6 @@
# #region PluginsRouter [C:3] [TYPE Module] [SEMANTICS fastapi, plugin, api]
# @BRIEF Defines the FastAPI router for plugin-related endpoints, allowing clients to list available plugins.
# @LAYER: UI (API)
# @LAYER: API
# @RELATION DEPENDS_ON -> [PluginConfig]
# @RELATION DEPENDS_ON -> [get_plugin_loader]
# @RELATION BINDS_TO -> [API_Routes]

View File

@@ -1,4 +1,4 @@
# #region ProfileApiModule [C:3] [TYPE Module] [SEMANTICS fastapi, profile, api, validate, search, superset]
# #region ProfileApiModule [C:5] [TYPE Module] [SEMANTICS fastapi, profile, api, validate, search, superset]
#
# @BRIEF Exposes self-scoped profile preference endpoints and environment-based Superset account lookup.
# @LAYER: API
@@ -7,11 +7,15 @@
# @RELATION DEPENDS_ON -> [get_db]
#
# @INVARIANT: Endpoints are self-scoped and never mutate another user preference.
# @PRE: Auth middleware configured, database session available
# @POST: Profile endpoints registered
# @UX_STATE: ProfileLoad -> Returns stable ProfilePreferenceResponse for authenticated user.
# @UX_STATE: Saving -> Validation errors map to actionable 422 details.
# @UX_STATE: LookupLoading -> Returns success/degraded Superset lookup payload.
# @UX_FEEDBACK: Stable status/message/warning payloads support profile page feedback.
# @UX_RECOVERY: Lookup degradation keeps manual username save path available.
# @SIDE_EFFECT: Registers /api/profile/* routes
# @DATA_CONTRACT: ProfileRequest -> ProfileResponse
from fastapi import APIRouter, Depends, HTTPException, Query

View File

@@ -1,6 +1,6 @@
# #region ReportsRouter [C:5] [TYPE Module] [SEMANTICS fastapi, report, api, transform, search, task]
# @BRIEF FastAPI router for unified task report list and detail retrieval endpoints.
# @LAYER: UI (API)
# @LAYER: API
# @RELATION DEPENDS_ON -> [ReportsService:Class]
# @RELATION DEPENDS_ON -> [get_task_manager:Function]
# @RELATION DEPENDS_ON -> [get_clean_release_repository:Function]

View File

@@ -1,4 +1,4 @@
# #region SettingsRouter [C:3] [TYPE Module] [SEMANTICS fastapi, api, superset, logging-config-response]
# #region SettingsRouter [C:5] [TYPE Module] [SEMANTICS fastapi, api, superset, logging-config-response]
#
# @BRIEF Provides API endpoints for managing application settings and Superset environments.
# @LAYER: API
@@ -6,6 +6,10 @@
# @RELATION DEPENDS_ON -> [get_config_manager]
# @RELATION DEPENDS_ON -> [has_permission]
#
# @PRE ConfigManager is initialized and accessible.
# @POST Settings are read or written via ConfigManager.
# @SIDE_EFFECT Persists config changes to disk via ConfigManager.
# @DATA_CONTRACT Input -> ConfigUpdateRequest, Output -> AppConfig, LoggingConfigResponse
# @INVARIANT: All settings changes must be persisted via ConfigManager.
# @PUBLIC_API: router

View File

@@ -1,7 +1,7 @@
# #region storage_routes [C:3] [TYPE Module] [SEMANTICS fastapi, storage, api, upload, download]
# #region storage_routes [C:5] [TYPE Module] [SEMANTICS fastapi, storage, api, upload, download]
#
# @BRIEF API endpoints for file storage management (backups and repositories).
# @LAYER: API
# @LAYER: API
# @RELATION DEPENDS_ON -> [StorageModels]
# @RELATION DEPENDS_ON -> [StoragePlugin]
#

View File

@@ -1,6 +1,6 @@
# #region TasksRouter [C:3] [TYPE Module] [SEMANTICS fastapi, task, api, search, create-task-request, resolve-task-request]
# @BRIEF Defines the FastAPI router for task-related endpoints, allowing clients to create, list, and get the status of tasks.
# @LAYER: UI (API)
# @LAYER: API
# @RELATION DEPENDS_ON -> [TaskManager]
# @RELATION DEPENDS_ON -> [ConfigManager]
# @RELATION DEPENDS_ON -> [LLMProviderService]