semantics

This commit is contained in:
2026-04-01 21:57:51 +03:00
parent 3bc4c8f885
commit 2b8e3831ef
71 changed files with 333 additions and 319 deletions

View File

@@ -7,6 +7,7 @@ os.environ["ENCRYPTION_KEY"] = "OnrCzomBWbIjTf7Y-fnhL2adlU55bHZQjp8zX5zBC5w="
# @PURPOSE: Verify assistant confirmation ownership, expiration, and deny behavior for restricted users.
# @LAYER: UI (API Tests)
# @RELATION: DEPENDS_ON -> backend.src.api.routes.assistant
# @RELATION: DEPENDS_ON -> AssistantApi
# @INVARIANT: Security-sensitive flows fail closed for unauthorized actors.
import os

View File

@@ -1025,6 +1025,7 @@ def _has_any_permission(current_user: User, checks: List[Tuple[str, str]]) -> bo
# @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.
# @RELATION: CALLS -> LLMProviderService
def _build_tool_catalog(
current_user: User,
config_manager: ConfigManager,
@@ -1264,6 +1265,9 @@ _DATASET_REVIEW_OPS = {
# @COMPLEXITY: 4
# @PURPOSE: Build assistant-safe dataset-review context snapshot with masked imported-filter payloads for session-scoped assistant routing.
# @RELATION: [DEPENDS_ON] ->[DatasetReviewSession]
# @PRE: session_id is a valid active review session identifier.
# @POST: Returns a serializable dictionary containing the complete review context.
# @SIDE_EFFECT: Reads session data from the database.
def _serialize_dataset_review_context(session: DatasetReviewSession) -> Dict[str, Any]:
with belief_scope('_serialize_dataset_review_context'):
logger.reason('Belief protocol reasoning checkpoint for _serialize_dataset_review_context')
@@ -1280,6 +1284,9 @@ def _serialize_dataset_review_context(session: DatasetReviewSession) -> Dict[str
# @COMPLEXITY: 4
# @PURPOSE: Load owner-scoped dataset-review context for assistant planning and grounded response generation.
# @RELATION: [DEPENDS_ON] ->[DatasetReviewSessionRepository]
# @PRE: session_id is a valid active review session identifier.
# @POST: Returns a loaded context object with session data and findings.
# @SIDE_EFFECT: Reads session data from the database.
def _load_dataset_review_context(dataset_review_session_id: Optional[str], current_user: User, db: Session) -> Optional[Dict[str, Any]]:
with belief_scope('_load_dataset_review_context'):
if not dataset_review_session_id:
@@ -1378,6 +1385,7 @@ def _dataset_review_conflict_http_exception(
# [DEF:_plan_dataset_review_intent:Function]
# @COMPLEXITY: 3
# @PURPOSE: Parse session-scoped dataset-review assistant commands before falling back to generic assistant tool routing.
# @RELATION: CALLS -> DatasetReviewOrchestrator
def _plan_dataset_review_intent(
message: str,
dataset_context: Dict[str, Any],
@@ -1532,6 +1540,10 @@ def _plan_dataset_review_intent(
# [DEF:_dispatch_dataset_review_intent:Function]
# @COMPLEXITY: 4
# @PURPOSE: Route confirmed dataset-review assistant intents through existing backend dataset-review APIs and orchestration boundaries.
# @RELATION: CALLS -> DatasetReviewOrchestrator
# @PRE: context contains valid session data and user intent.
# @POST: Returns a structured response with planned actions and confirmations.
# @SIDE_EFFECT: May update session state and enqueue tasks.
async def _dispatch_dataset_review_intent(
intent: Dict[str, Any],
current_user: User,
@@ -1757,8 +1769,10 @@ async def _dispatch_dataset_review_intent(
# [DEF:_confirmation_summary:Function]
# @COMPLEXITY: 4
# @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.
# @PRE: actions is a non-empty list of planned review actions.
# @POST: Returns a formatted summary string suitable for display to the user.
# @RELATION: CALLS -> DatasetReviewOrchestrator
# @SIDE_EFFECT: None - pure formatting function.
async def _async_confirmation_summary(intent: Dict[str, Any], config_manager: ConfigManager, db: Session) -> str:
with belief_scope('_confirmation_summary'):
logger.reason('Belief protocol reasoning checkpoint for _confirmation_summary')

View File

@@ -3,8 +3,8 @@
# @PURPOSE: Defines the FastAPI router for managing external database connections.
# @COMPLEXITY: 3
# @LAYER: UI (API)
# @RELATION: DEPENDS_ON -> Session
# @CONSTRAINT: Must use belief_scope for logging.
# @RELATION: DEPENDS_ON -> [get_db]
# @RELATION: DEPENDS_ON -> [ConnectionConfig]
# [SECTION: IMPORTS]
from typing import List, Optional

View File

@@ -4,8 +4,8 @@
# @SEMANTICS: api, environments, superset, databases
# @PURPOSE: API endpoints for listing environments and their databases.
# @LAYER: API
# @RELATION: DEPENDS_ON -> backend.src.dependencies
# @RELATION: DEPENDS_ON -> backend.src.core.superset_client
# @RELATION: DEPENDS_ON -> [AppDependencies]
# @RELATION: DEPENDS_ON -> [SupersetClient]
#
# @INVARIANT: Environment IDs must exist in the configuration.

View File

@@ -768,6 +768,7 @@ async def delete_gitea_repository(
# @POST: Repository is initialized on disk and a GitRepository record is saved in DB.
# @PARAM: dashboard_ref (str)
# @PARAM: init_data (RepoInitRequest)
# @RELATION: CALLS -> GitService.init_repo
@router.post("/repositories/{dashboard_ref}/init")
async def init_repository(
dashboard_ref: str,
@@ -1089,6 +1090,7 @@ async def push_changes(
# @PRE: `dashboard_ref` repository exists and has a remote configured.
# @POST: Remote changes are fetched and merged into the local branch.
# @PARAM: dashboard_ref (str)
# @RELATION: CALLS -> GitService.pull
@router.post("/repositories/{dashboard_ref}/pull")
async def pull_changes(
dashboard_ref: str,
@@ -1217,6 +1219,7 @@ async def get_merge_conflicts(
# @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.
# @RELATION: CALLS -> GitService.resolve_conflicts
@router.post("/repositories/{dashboard_ref}/merge/resolve")
async def resolve_merge_conflicts(
dashboard_ref: str,
@@ -1276,6 +1279,7 @@ async def abort_merge(
# @PURPOSE: Finalize unfinished merge from WebUI flow.
# @PRE: All conflicts are resolved and staged.
# @POST: Merge commit is created.
# @RELATION: CALLS -> GitService.continue_merge
@router.post("/repositories/{dashboard_ref}/merge/continue")
async def continue_merge(
dashboard_ref: str,
@@ -1306,6 +1310,7 @@ async def continue_merge(
# @POST: Dashboard YAMLs are exported from Superset and committed to Git.
# @PARAM: dashboard_ref (str)
# @PARAM: source_env_id (Optional[str])
# @RELATION: CALLS -> GitPlugin.execute
@router.post("/repositories/{dashboard_ref}/sync")
async def sync_dashboard(
dashboard_ref: str,
@@ -1343,6 +1348,7 @@ async def sync_dashboard(
# @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.
# @RELATION: CALLS -> GitPlugin.execute
@router.post("/repositories/{dashboard_ref}/promote", response_model=PromoteResponse)
async def promote_dashboard(
dashboard_ref: str,
@@ -1493,6 +1499,7 @@ async def get_environments(
# @POST: Dashboard YAMLs are read from Git and imported into the target Superset.
# @PARAM: dashboard_ref (str)
# @PARAM: deploy_data (DeployRequest)
# @RELATION: CALLS -> GitPlugin.execute
@router.post("/repositories/{dashboard_ref}/deploy")
async def deploy_dashboard(
dashboard_ref: str,
@@ -1670,6 +1677,7 @@ async def get_repository_diff(
# @PURPOSE: Generate a suggested commit message using LLM.
# @PRE: Repository for `dashboard_ref` is initialized.
# @POST: Returns a suggested commit message string.
# @RELATION: CALLS -> GitService.generate_commit_message
@router.post("/repositories/{dashboard_ref}/generate-message")
async def generate_commit_message(
dashboard_ref: str,

View File

@@ -4,9 +4,9 @@
# @SEMANTICS: api, mappings, database, fuzzy-matching
# @PURPOSE: API endpoints for managing database mappings and getting suggestions.
# @LAYER: API
# @RELATION: DEPENDS_ON -> backend.src.dependencies
# @RELATION: DEPENDS_ON -> backend.src.core.database
# @RELATION: DEPENDS_ON -> backend.src.services.mapping_service
# @RELATION: DEPENDS_ON -> [AppDependencies]
# @RELATION: DEPENDS_ON -> [DatabaseModule]
# @RELATION: DEPENDS_ON -> [mapping_service]
#
# @INVARIANT: Mappings are persisted in the SQLite database.

View File

@@ -4,7 +4,8 @@
# @SEMANTICS: storage, files, upload, download, backup, repository
# @PURPOSE: API endpoints for file storage management (backups and repositories).
# @LAYER: API
# @RELATION: DEPENDS_ON -> [backend.src.models.storage]
# @RELATION: DEPENDS_ON -> [StorageModels]
# @RELATION: DEPENDS_ON -> [StoragePlugin]
#
# @INVARIANT: All paths must be validated against path traversal.
@@ -31,8 +32,7 @@ router = APIRouter(tags=["storage"])
# @PARAM: category (Optional[FileCategory]) - Filter by category.
# @PARAM: path (Optional[str]) - Subpath within the category.
# @RETURN: List[StoredFile] - List of files/directories.
#
# @RELATION: CALLS -> [backend.src.plugins.storage.plugin.StoragePlugin.list_files]
# @RELATION: DEPENDS_ON -> [StoragePlugin]
@router.get("/files", response_model=List[StoredFile])
async def list_files(
category: Optional[FileCategory] = None,
@@ -63,7 +63,7 @@ async def list_files(
#
# @SIDE_EFFECT: Writes file to the filesystem.
#
# @RELATION: CALLS -> [backend.src.plugins.storage.plugin.StoragePlugin.save_file]
# @RELATION: DEPENDS_ON -> [StoragePlugin]
@router.post("/upload", response_model=StoredFile, status_code=201)
async def upload_file(
category: FileCategory = Form(...),
@@ -95,7 +95,7 @@ async def upload_file(
#
# @SIDE_EFFECT: Deletes item from the filesystem.
#
# @RELATION: CALLS -> [backend.src.plugins.storage.plugin.StoragePlugin.delete_file]
# @RELATION: DEPENDS_ON -> [StoragePlugin]
@router.delete("/files/{category}/{path:path}", status_code=204)
async def delete_file(
category: FileCategory,
@@ -126,7 +126,7 @@ async def delete_file(
# @PARAM: path (str) - Relative path of the file.
# @RETURN: FileResponse - The file content.
#
# @RELATION: CALLS -> [backend.src.plugins.storage.plugin.StoragePlugin.get_file_path]
# @RELATION: DEPENDS_ON -> [StoragePlugin]
@router.get("/download/{category}/{path:path}")
async def download_file(
category: FileCategory,
@@ -158,8 +158,7 @@ async def download_file(
# @PARAM: path (str) - Absolute or storage-root-relative file path.
# @RETURN: FileResponse - The file content.
#
# @RELATION: CALLS -> [backend.src.plugins.storage.plugin.StoragePlugin.get_storage_root]
# @RELATION: CALLS -> [backend.src.plugins.storage.plugin.StoragePlugin.validate_path]
# @RELATION: DEPENDS_ON -> [StoragePlugin]
@router.get("/file")
async def get_file_by_path(
path: str,