# Copyright (c) 2025 Patrick Motsch # All rights reserved. """FeatureDataSource model for exposing feature instance data to the AI workspace. A FeatureDataSource links a FeatureInstance table (DATA_OBJECT) to a workspace so the agent can query structured feature data (e.g. TrusteePosition rows). """ from typing import Any, Dict, List, Optional from pydantic import BaseModel, Field from modules.datamodels.datamodelBase import PowerOnModel from modules.shared.i18nRegistry import i18nModel import uuid @i18nModel("Feature-Datenquelle") class FeatureDataSource(PowerOnModel): """Feature-Instanz-Tabelle als Datenquelle im AI-Workspace.""" id: str = Field( default_factory=lambda: str(uuid.uuid4()), description="Primary key", json_schema_extra={"label": "ID"}, ) featureInstanceId: str = Field( description="FK to FeatureInstance", json_schema_extra={"label": "Feature-Instanz", "fk_target": {"db": "poweron_app", "table": "FeatureInstance", "labelField": "label"}}, ) featureCode: str = Field( description="Feature code (e.g. trustee, commcoach)", json_schema_extra={"label": "Feature", "fk_target": {"db": "poweron_app", "table": "Feature", "column": "code", "labelField": "code"}}, ) tableName: str = Field( description="Table name from DATA_OBJECTS meta (e.g. TrusteePosition)", json_schema_extra={"label": "Tabelle"}, ) objectKey: str = Field( description="RBAC object key (e.g. data.feature.trustee.TrusteePosition)", json_schema_extra={"label": "Objekt-Schluessel"}, ) label: str = Field( description="User-visible label", json_schema_extra={"label": "Bezeichnung"}, ) mandateId: str = Field( default="", description="Mandate scope", json_schema_extra={"label": "Mandant", "fk_target": {"db": "poweron_app", "table": "Mandate", "labelField": "label"}}, ) userId: str = Field( default="", description="Owner user ID", json_schema_extra={"label": "Benutzer", "fk_target": {"db": "poweron_app", "table": "UserInDB", "labelField": "username"}}, ) workspaceInstanceId: str = Field( description="Workspace feature instance where this source is used", json_schema_extra={"label": "Workspace", "fk_target": {"db": "poweron_app", "table": "FeatureInstance", "labelField": "label"}}, ) scope: Optional[str] = Field( default=None, description=( "Data visibility scope with inherit semantics. " "None = inherit; values: personal, featureInstance, mandate, global." ), json_schema_extra={"label": "Sichtbarkeit", "frontend_type": "select", "frontend_readonly": False, "frontend_required": False, "frontend_options": [ {"value": "personal", "label": "Persönlich"}, {"value": "featureInstance", "label": "Feature-Instanz"}, {"value": "mandate", "label": "Mandant"}, {"value": "global", "label": "Global"}, ]}, ) neutralize: Optional[bool] = Field( default=None, description=( "Three-state neutralization flag with cascade-inherit semantics. " "None = inherit; True/False = explicit. Cascade-reset on parent toggle." ), json_schema_extra={"label": "Neutralisieren", "frontend_type": "checkbox", "frontend_readonly": False, "frontend_required": False}, ) neutralizeFields: Optional[List[str]] = Field( default=None, description="Column names whose values are replaced with placeholders before AI processing", json_schema_extra={"label": "Zu neutralisierende Felder", "frontend_type": "multiselect", "frontend_readonly": False, "frontend_required": False}, ) recordFilter: Optional[Dict[str, str]] = Field( default=None, description="Record-level filter applied when querying this table, e.g. {'sessionId': 'abc-123'}", json_schema_extra={"label": "Datensatzfilter"}, ) settings: Optional[Dict[str, Any]] = Field( default=None, description=( "FeatureDataSource-scoped settings (JSON). Currently used keys: " "ragLimits.{maxBytes,maxFileSize,maxItems,maxDepth}. " "Mirror of DataSource.settings so the UDB settings modal can target both." ), json_schema_extra={"label": "Einstellungen", "frontend_type": "json", "frontend_readonly": True, "frontend_required": False}, )