semantic
This commit is contained in:
@@ -12,9 +12,6 @@
|
||||
- Persona: `.ai/PERSONA.md` -> `[DEF:Std:UserPersona:Standard]`
|
||||
- Constitution: `.ai/standards/constitution.md` -> `[DEF:Std:Constitution:Standard]`
|
||||
- Semantics standard: `.ai/standards/semantics.md` -> `[DEF:Std:Semantics:Standard]`
|
||||
- Module map: `.ai/MODULE_MAP.md` -> `[DEF:Module_Map]`
|
||||
- Project map: `.ai/PROJECT_MAP.md` -> `[DEF:Project_Map:Root]`
|
||||
- Project map snapshot: `.ai/structure/PROJECT_MAP.md` (generated backing artifact)
|
||||
- Normalized MCP config: `.kilo/mcp.json` -> `[DEF:MCP_Config:Block]`
|
||||
|
||||
## 0.1 MCP NORMALIZATION RULE
|
||||
|
||||
Binary file not shown.
@@ -1,84 +0,0 @@
|
||||
# ss-tools Development Guidelines
|
||||
|
||||
Auto-generated from all feature plans. Last updated: 2025-12-19
|
||||
|
||||
## Knowledge Graph (GRACE)
|
||||
**CRITICAL**: This project uses a GRACE Knowledge Graph for context. Always load the root map first:
|
||||
- **Root Map**: `.ai/ROOT.md` -> `[DEF:Project_Knowledge_Map:Root]`
|
||||
- **Project Map**: `.ai/PROJECT_MAP.md` -> `[DEF:Project_Map]`
|
||||
- **Standards**: Read `.ai/standards/` for architecture and style rules.
|
||||
|
||||
## Active Technologies
|
||||
- Python 3.9+, Node.js 18+ + `uvicorn`, `npm`, `bash` (003-project-launch-script)
|
||||
- Python 3.9+, Node.js 18+ + SvelteKit, FastAPI, Tailwind CSS (inferred from existing frontend) (004-integrate-svelte-kit)
|
||||
- N/A (Frontend integration) (004-integrate-svelte-kit)
|
||||
- Python 3.9+, Node.js 18+ + FastAPI, SvelteKit, Tailwind CSS, Pydantic (005-fix-ui-ws-validation)
|
||||
- N/A (Configuration based) (005-fix-ui-ws-validation)
|
||||
- Filesystem (plugins, logs, backups), SQLite (optional, for job history if needed) (005-fix-ui-ws-validation)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS (007-migration-dashboard-grid)
|
||||
- N/A (Superset API integration) (007-migration-dashboard-grid)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS, Pydantic, Superset API (007-migration-dashboard-grid)
|
||||
- N/A (Superset API integration - read-only for metadata) (007-migration-dashboard-grid)
|
||||
- Python 3.9+ (backend), Node.js 18+ (frontend) + FastAPI, SvelteKit, Tailwind CSS, Pydantic, SQLAlchemy, Superset API (008-migration-ui-improvements)
|
||||
- SQLite (optional for job history), existing database for mappings (008-migration-ui-improvements)
|
||||
- Python 3.9+, Node.js 18+ + FastAPI, SvelteKit, Tailwind CSS, Pydantic, SQLAlchemy, Superset API (008-migration-ui-improvements)
|
||||
- Python 3.9+, Node.js 18+ + FastAPI, APScheduler, SQLAlchemy, SvelteKit, Tailwind CSS (009-backup-scheduler)
|
||||
- SQLite (`tasks.db`), JSON (`config.json`) (009-backup-scheduler)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS, Pydantic, SQLAlchemy, `superset_tool` (internal lib) (010-refactor-cli-to-web)
|
||||
- SQLite (for job history/results, connection configs), Filesystem (for temporary file uploads) (010-refactor-cli-to-web)
|
||||
- Python 3.9+ + FastAPI, Pydantic, requests, pyyaml (migrated from superset_tool) (012-remove-superset-tool)
|
||||
- SQLite (tasks.db, migrations.db), Filesystem (012-remove-superset-tool)
|
||||
- Filesystem (local git repo), SQLite (for GitServerConfig, Environment) (011-git-integration-dashboard)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, GitPython (or CLI git), Pydantic, SQLAlchemy, Superset API (011-git-integration-dashboard)
|
||||
- SQLite (for config/history), Filesystem (local Git repositories) (011-git-integration-dashboard)
|
||||
- Node.js 18+ (Frontend Build), Svelte 5.x + SvelteKit, Tailwind CSS, `date-fns` (existing) (013-unify-frontend-css)
|
||||
- LocalStorage (for language preference) (013-unify-frontend-css)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI (Backend), SvelteKit (Frontend) (014-file-storage-ui)
|
||||
- Local Filesystem (for artifacts), Config (for storage path) (014-file-storage-ui)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI (Backend), SvelteKit + Tailwind CSS (Frontend) (015-frontend-nav-redesign)
|
||||
- N/A (UI reorganization and API integration) (015-frontend-nav-redesign)
|
||||
- SQLite (`auth.db`) for Users, Roles, Permissions, and Mappings. (016-multi-user-auth)
|
||||
- SQLite (existing `tasks.db` for results, `auth.db` for permissions, `mappings.db` or new `plugins.db` for provider config/metadata) (017-llm-analysis-plugin)
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend) + FastAPI, SvelteKit, Tailwind CSS, SQLAlchemy, WebSocket (existing) (019-superset-ux-redesign)
|
||||
- SQLite (tasks.db, auth.db, migrations.db) - no new database tables required (019-superset-ux-redesign)
|
||||
- Python 3.9+ (backend), Node.js 18+ (frontend) + FastAPI, SvelteKit, Tailwind CSS, SQLAlchemy/Pydantic task models, existing task/websocket stack (020-task-reports-design)
|
||||
- SQLite task/result persistence (existing task DB), filesystem only for existing artifacts (no new primary store required) (020-task-reports-design)
|
||||
- Node.js 18+ runtime, SvelteKit (existing frontend stack) + SvelteKit, Tailwind CSS, existing frontend UI primitives under `frontend/src/lib/components/ui` (001-unify-frontend-style)
|
||||
- N/A (UI styling and component behavior only) (001-unify-frontend-style)
|
||||
- Python 3.9+ (backend scripts/services), Shell (release tooling) + FastAPI stack (existing backend), ConfigManager, TaskManager, файловые утилиты, internal artifact registries (020-clean-repo-enterprise)
|
||||
- PostgreSQL (конфигурации/метаданные), filesystem (артефакты дистрибутива, отчёты проверки) (020-clean-repo-enterprise)
|
||||
- Python 3.9+ (backend), Node.js 18+ + SvelteKit (frontend) + FastAPI, SQLAlchemy, Pydantic, existing auth stack (`get_current_user`), existing dashboards route/service, Svelte runes (`$state`, `$derived`, `$effect`), Tailwind CSS, frontend `api` wrapper (024-user-dashboard-filter)
|
||||
- Existing auth database (`AUTH_DATABASE_URL`) with a dedicated per-user preference entity (024-user-dashboard-filter)
|
||||
- Python 3.9+ (Backend), Node.js 18+ / Svelte 5.x (Frontend) + FastAPI, SQLAlchemy, APScheduler (Backend) | SvelteKit, Tailwind CSS, existing UI components (Frontend) (026-dashboard-health-windows)
|
||||
- PostgreSQL / SQLite (existing database for `ValidationRecord` and new `ValidationPolicy`) (026-dashboard-health-windows)
|
||||
- Python 3.9+ backend, Node.js 18+ frontend with Svelte 5 / SvelteKit + FastAPI, SQLAlchemy, Pydantic, existing [SupersetClient](../../backend/src/core/superset_client.py), existing frontend API wrapper patterns, Svelte runes, existing task/websocket stack (027-dataset-llm-orchestration)
|
||||
- Existing application databases plus filesystem-backed uploaded semantic sources; reuse current configuration and task persistence stores (027-dataset-llm-orchestration)
|
||||
- Python 3.9+ backend, Node.js 18+ frontend, Svelte 5 / SvelteKit frontend runtime + FastAPI, SQLAlchemy, Pydantic, existing `TaskManager`, existing `SupersetClient`, existing LLM provider stack, SvelteKit, Tailwind CSS, frontend `requestApi`/`fetchApi` wrappers (027-dataset-llm-orchestration)
|
||||
- Existing application databases for persistent session/domain entities; existing tasks database for async execution metadata; filesystem for optional uploaded semantic sources/artifacts (027-dataset-llm-orchestration)
|
||||
|
||||
- Python 3.9+ (Backend), Node.js 18+ (Frontend Build) (001-plugin-arch-svelte-ui)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```text
|
||||
backend/
|
||||
frontend/
|
||||
tests/
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
cd src; pytest; ruff check .
|
||||
|
||||
## Code Style
|
||||
|
||||
Python 3.9+ (Backend), Node.js 18+ (Frontend Build): Follow standard conventions
|
||||
|
||||
## Recent Changes
|
||||
- 027-dataset-llm-orchestration: Added Python 3.9+ backend, Node.js 18+ frontend, Svelte 5 / SvelteKit frontend runtime + FastAPI, SQLAlchemy, Pydantic, existing `TaskManager`, existing `SupersetClient`, existing LLM provider stack, SvelteKit, Tailwind CSS, frontend `requestApi`/`fetchApi` wrappers
|
||||
- 027-dataset-llm-orchestration: Added Python 3.9+ backend, Node.js 18+ frontend with Svelte 5 / SvelteKit + FastAPI, SQLAlchemy, Pydantic, existing [SupersetClient](../../backend/src/core/superset_client.py), existing frontend API wrapper patterns, Svelte runes, existing task/websocket stack
|
||||
- 026-dashboard-health-windows: Added Python 3.9+ (Backend), Node.js 18+ / Svelte 5.x (Frontend) + FastAPI, SQLAlchemy, APScheduler (Backend) | SvelteKit, Tailwind CSS, existing UI components (Frontend)
|
||||
|
||||
|
||||
<!-- MANUAL ADDITIONS START -->
|
||||
<!-- MANUAL ADDITIONS END -->
|
||||
@@ -5,7 +5,7 @@ os.environ["ENCRYPTION_KEY"] = "OnrCzomBWbIjTf7Y-fnhL2adlU55bHZQjp8zX5zBC5w="
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: tests, assistant, api
|
||||
# @PURPOSE: Validate assistant API endpoint logic via direct async handler invocation.
|
||||
# @RELATION: DEPENDS_ON -> backend.src.api.routes.assistant
|
||||
# @RELATION: DEPENDS_ON -> [AssistantApi]
|
||||
# @INVARIANT: Every test clears assistant in-memory state before execution.
|
||||
|
||||
import asyncio
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: API contract tests for redesigned clean release endpoints.
|
||||
# @LAYER: Domain
|
||||
# @RELATION: DEPENDS_ON -> backend.src.api.routes.clean_release_v2
|
||||
# @RELATION: DEPENDS_ON -> [CleanReleaseV2Api]
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from types import SimpleNamespace
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: API contract test scaffolding for clean release approval and publication endpoints.
|
||||
# @LAYER: Domain
|
||||
# @RELATION: DEPENDS_ON -> backend.src.api.routes.clean_release_v2
|
||||
# @RELATION: DEPENDS_ON -> [CleanReleaseV2Api]
|
||||
|
||||
"""Contract tests for redesigned approval/publication API endpoints."""
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Unit tests for dashboards API endpoints.
|
||||
# @LAYER: API
|
||||
# @RELATION: DEPENDS_ON -> backend.src.api.routes.dashboards
|
||||
# @RELATION: DEPENDS_ON -> [DashboardsApi]
|
||||
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch, AsyncMock
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,13 @@
|
||||
# [DEF:backend.src.api.routes.clean_release:Module]
|
||||
# [DEF:CleanReleaseApi:Module]
|
||||
# @COMPLEXITY: 4
|
||||
# @SEMANTICS: api, clean-release, candidate-preparation, compliance
|
||||
# @PURPOSE: Expose clean release endpoints for candidate preparation and subsequent compliance flow.
|
||||
# @LAYER: API
|
||||
# @RELATION: DEPENDS_ON -> backend.src.dependencies.get_clean_release_repository
|
||||
# @RELATION: DEPENDS_ON -> backend.src.services.clean_release.preparation_service
|
||||
# @RELATION: DEPENDS_ON -> [get_clean_release_repository]
|
||||
# @RELATION: DEPENDS_ON -> [PreparationService]
|
||||
# @PRE: Clean release repository and preparation service dependencies are configured for the current request scope.
|
||||
# @POST: Candidate preparation, manifest, and compliance routes expose deterministic API payloads without reporting prepared state on failed preparation.
|
||||
# @SIDE_EFFECT: Persists candidate/compliance lifecycle state and triggers clean-release orchestration services.
|
||||
# @INVARIANT: API never reports prepared status if preparation errors are present.
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -633,4 +636,4 @@ async def get_report(
|
||||
|
||||
|
||||
# [/DEF:get_report:Function]
|
||||
# [/DEF:backend.src.api.routes.clean_release:Module]
|
||||
# [/DEF:CleanReleaseApi:Module]
|
||||
|
||||
@@ -1295,6 +1295,7 @@ async def get_dashboard_tasks_history(
|
||||
# [DEF:get_dashboard_thumbnail:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Proxies Superset dashboard thumbnail with cache support.
|
||||
# @RELATION: CALLS ->[AsyncSupersetClient]
|
||||
# @PRE: env_id must exist.
|
||||
# @POST: Returns image bytes or 202 when thumbnail is being prepared by Superset.
|
||||
@router.get("/{dashboard_ref}/thumbnail")
|
||||
|
||||
@@ -448,48 +448,34 @@ def _require_session_version_header(
|
||||
# [/DEF:_require_session_version_header:Function]
|
||||
|
||||
|
||||
from src.logger import belief_scope, logger
|
||||
|
||||
# [DEF:_enforce_session_version:Function]
|
||||
# @COMPLEXITY: 4
|
||||
# @PURPOSE: Convert repository optimistic-lock conflicts into deterministic HTTP 409 responses.
|
||||
# @RELATION: [DEPENDS_ON] ->[DatasetReviewSessionRepository]
|
||||
def _enforce_session_version(
|
||||
repository: DatasetReviewSessionRepository,
|
||||
session: DatasetReviewSession,
|
||||
expected_version: int,
|
||||
) -> DatasetReviewSession:
|
||||
try:
|
||||
repository.require_session_version(session, expected_version)
|
||||
return session
|
||||
except DatasetReviewSessionVersionConflictError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail={
|
||||
"error_code": "session_version_conflict",
|
||||
"message": str(exc),
|
||||
"session_id": exc.session_id,
|
||||
"expected_version": exc.expected_version,
|
||||
"actual_version": exc.actual_version,
|
||||
},
|
||||
) from exc
|
||||
|
||||
|
||||
def _enforce_session_version(repository: DatasetReviewSessionRepository, session: DatasetReviewSession, expected_version: int) -> DatasetReviewSession:
|
||||
with belief_scope('_enforce_session_version'):
|
||||
logger.reason('Belief protocol reasoning checkpoint for _enforce_session_version')
|
||||
try:
|
||||
repository.require_session_version(session, expected_version)
|
||||
logger.reflect('Belief protocol postcondition checkpoint for _enforce_session_version')
|
||||
return session
|
||||
except DatasetReviewSessionVersionConflictError as exc:
|
||||
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail={'error_code': 'session_version_conflict', 'message': str(exc), 'session_id': exc.session_id, 'expected_version': exc.expected_version, 'actual_version': exc.actual_version}) from exc
|
||||
# [/DEF:_enforce_session_version:Function]
|
||||
|
||||
|
||||
# [DEF:_prepare_owned_session_mutation:Function]
|
||||
# @COMPLEXITY: 4
|
||||
# @PURPOSE: Resolve owner-scoped mutation session and enforce optimistic-lock version before changing dataset review state.
|
||||
def _prepare_owned_session_mutation(
|
||||
repository: DatasetReviewSessionRepository,
|
||||
session_id: str,
|
||||
current_user: User,
|
||||
expected_version: int,
|
||||
) -> DatasetReviewSession:
|
||||
session = _get_owned_session_or_404(repository, session_id, current_user)
|
||||
_require_owner_mutation_scope(session, current_user)
|
||||
return _enforce_session_version(repository, session, expected_version)
|
||||
|
||||
|
||||
def _prepare_owned_session_mutation(repository: DatasetReviewSessionRepository, session_id: str, current_user: User, expected_version: int) -> DatasetReviewSession:
|
||||
with belief_scope('_prepare_owned_session_mutation'):
|
||||
logger.reason('Belief protocol reasoning checkpoint for _prepare_owned_session_mutation')
|
||||
session = _get_owned_session_or_404(repository, session_id, current_user)
|
||||
_require_owner_mutation_scope(session, current_user)
|
||||
logger.reflect('Belief protocol postcondition checkpoint for _prepare_owned_session_mutation')
|
||||
return _enforce_session_version(repository, session, expected_version)
|
||||
# [/DEF:_prepare_owned_session_mutation:Function]
|
||||
|
||||
|
||||
@@ -497,20 +483,16 @@ def _prepare_owned_session_mutation(
|
||||
# @COMPLEXITY: 4
|
||||
# @PURPOSE: Centralize dataset-review session version bumping and commit semantics for owner-scoped mutation endpoints.
|
||||
# @RELATION: [DEPENDS_ON] ->[DatasetReviewSessionRepository]
|
||||
def _commit_owned_session_mutation(
|
||||
repository: DatasetReviewSessionRepository,
|
||||
session: DatasetReviewSession,
|
||||
*,
|
||||
refresh_targets: Optional[List[Any]] = None,
|
||||
) -> DatasetReviewSession:
|
||||
repository.bump_session_version(session)
|
||||
repository.db.commit()
|
||||
repository.db.refresh(session)
|
||||
for target in refresh_targets or []:
|
||||
repository.db.refresh(target)
|
||||
return session
|
||||
|
||||
|
||||
def _commit_owned_session_mutation(repository: DatasetReviewSessionRepository, session: DatasetReviewSession, *, refresh_targets: Optional[List[Any]]=None) -> DatasetReviewSession:
|
||||
with belief_scope('_commit_owned_session_mutation'):
|
||||
logger.reason('Belief protocol reasoning checkpoint for _commit_owned_session_mutation')
|
||||
repository.bump_session_version(session)
|
||||
repository.db.commit()
|
||||
repository.db.refresh(session)
|
||||
for target in refresh_targets or []:
|
||||
repository.db.refresh(target)
|
||||
logger.reflect('Belief protocol postcondition checkpoint for _commit_owned_session_mutation')
|
||||
return session
|
||||
# [/DEF:_commit_owned_session_mutation:Function]
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# @PURPOSE: API endpoints for the Dataset Hub - listing datasets with mapping progress
|
||||
# @LAYER: API
|
||||
# @RELATION: DEPENDS_ON ->[AppDependencies]
|
||||
# @RELATION: DEPENDS_ON ->[backend.src.services.resource_service.ResourceService]
|
||||
# @RELATION: DEPENDS_ON ->[backend.src.core.superset_client.SupersetClient]
|
||||
# @RELATION: DEPENDS_ON ->[ResourceService]
|
||||
# @RELATION: DEPENDS_ON ->[SupersetClient]
|
||||
#
|
||||
# @INVARIANT: All dataset responses include last_task metadata
|
||||
|
||||
@@ -178,7 +178,7 @@ async def get_dataset_ids(
|
||||
# @PARAM: page (Optional[int]) - Page number (default: 1)
|
||||
# @PARAM: page_size (Optional[int]) - Items per page (default: 10, max: 100)
|
||||
# @RETURN: DatasetsResponse - List of datasets with status metadata
|
||||
# @RELATION: CALLS ->[backend.src.services.resource_service.ResourceService.get_datasets_with_status]
|
||||
# @RELATION: CALLS ->[get_datasets_with_status]
|
||||
@router.get("", response_model=DatasetsResponse)
|
||||
async def get_datasets(
|
||||
env_id: str,
|
||||
@@ -266,8 +266,8 @@ class MapColumnsRequest(BaseModel):
|
||||
# @POST: Task is created and queued for execution
|
||||
# @PARAM: request (MapColumnsRequest) - Mapping request with environment and dataset IDs
|
||||
# @RETURN: TaskResponse - Task ID for tracking
|
||||
# @RELATION: DISPATCHES ->[backend.src.plugins.mapper.MapperPlugin]
|
||||
# @RELATION: CALLS ->[backend.src.core.task_manager.manager.TaskManager:create_task]
|
||||
# @RELATION: DISPATCHES ->[MapperPlugin]
|
||||
# @RELATION: CALLS ->[create_task]
|
||||
@router.post("/map-columns", response_model=TaskResponse)
|
||||
async def map_columns(
|
||||
request: MapColumnsRequest,
|
||||
@@ -338,8 +338,8 @@ class GenerateDocsRequest(BaseModel):
|
||||
# @POST: Task is created and queued for execution
|
||||
# @PARAM: request (GenerateDocsRequest) - Documentation generation request
|
||||
# @RETURN: TaskResponse - Task ID for tracking
|
||||
# @RELATION: DISPATCHES ->[backend.src.plugins.llm_analysis.plugin.DocumentationPlugin]
|
||||
# @RELATION: CALLS ->[backend.src.core.task_manager.manager.TaskManager:create_task]
|
||||
# @RELATION: DISPATCHES ->[DocumentationPlugin]
|
||||
# @RELATION: CALLS ->[create_task]
|
||||
@router.post("/generate-docs", response_model=TaskResponse)
|
||||
async def generate_docs(
|
||||
request: GenerateDocsRequest,
|
||||
@@ -393,7 +393,7 @@ async def generate_docs(
|
||||
# @PARAM: env_id (str) - The environment ID
|
||||
# @PARAM: dataset_id (int) - The dataset ID
|
||||
# @RETURN: DatasetDetailResponse - Detailed dataset information
|
||||
# @RELATION: CALLS ->[backend.src.core.superset_client.SupersetClient:get_dataset_detail]
|
||||
# @RELATION: CALLS ->[SupersetClientGetDatasetDetail]
|
||||
@router.get("/{dataset_id}", response_model=DatasetDetailResponse)
|
||||
async def get_dataset_detail(
|
||||
env_id: str,
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
# @SEMANTICS: profile, service, validation, ownership, filtering, superset, preferences
|
||||
# @PURPOSE: Orchestrates profile preference persistence, Superset account lookup, and deterministic actor matching.
|
||||
# @LAYER: Domain
|
||||
# @RELATION: DEPENDS_ON -> backend.src.models.profile
|
||||
# @RELATION: DEPENDS_ON -> backend.src.schemas.profile
|
||||
# @RELATION: DEPENDS_ON -> backend.src.core.superset_client
|
||||
# @RELATION: DEPENDS_ON -> backend.src.core.auth.repository
|
||||
# @RELATION: DEPENDS_ON -> backend.src.models.auth
|
||||
# @RELATION: DEPENDS_ON -> sqlalchemy.orm.Session
|
||||
# @RELATION: DEPENDS_ON -> [UserDashboardPreference]
|
||||
# @RELATION: DEPENDS_ON -> [ProfilePreferenceResponse]
|
||||
# @RELATION: DEPENDS_ON -> [SupersetClient]
|
||||
# @RELATION: DEPENDS_ON -> [AuthRepositoryModule]
|
||||
# @RELATION: DEPENDS_ON -> [User]
|
||||
# @RELATION: DEPENDS_ON -> [sqlalchemy.orm.Session]
|
||||
#
|
||||
# @INVARIANT: Preference mutations are always scoped to authenticated user identity.
|
||||
# @INVARIANT: Username normalization is trim+lower and shared by save and matching paths.
|
||||
|
||||
Reference in New Issue
Block a user