from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore") # Runtime security profile. Development remains convenient, while the # server overlay enables strict mode so placeholder secrets or unsafe # network settings stop the process instead of producing a warning. app_environment: str = "development" security_strict_mode: bool = False cors_allowed_origins: str = ( "http://localhost:8102,http://127.0.0.1:8102," "http://localhost:5173,http://127.0.0.1:5173" ) trusted_hosts: str = "*" security_headers_enabled: bool = True # Database database_url: str = "postgresql://postgres:postgres@localhost:5432/kg_db" db_schema: str = "kg_admin" db_migrations_enabled: bool = True # Data Center (independent MySQL service; PostgreSQL above remains the # system/graph-metadata store and is intentionally not replaced here). data_mysql_url: str = ( "mysql://data_center:data_center@localhost:3306/platform_control" ) data_mysql_required: bool = False data_mysql_pool_min_size: int = 1 data_mysql_pool_max_size: int = 10 data_sql_console_write_enabled: bool = False interface_api_secret: str = "" # Optional connection information shown to trusted data administrators. # The secure production path is two-stage: DBeaver reaches the server over # an SSH tunnel, then connects to the MySQL host port on 127.0.0.1. Keep # the legacy public host/port fields for older deployments, but do not use # them to imply that the MySQL port should be exposed publicly. data_mysql_direct_access_enabled: bool = False data_mysql_public_host: str = "" data_mysql_public_port: int = 0 data_mysql_direct_transport: str = "SSH 隧道(强制)" data_mysql_ssh_tunnel_required: bool = True data_mysql_ssh_host: str = "" data_mysql_ssh_port: int = 2222 data_mysql_ssh_username: str = "dbeaver" data_mysql_ssh_auth_method: str = "SSH 私钥 / SSH Agent" data_mysql_managed_access_enabled: bool = False data_mysql_ssh_authorized_keys_file: str = "" data_mysql_ssh_host_public_key_file: str = "" data_mysql_provisioner_user: str = "" data_mysql_provisioner_password: str = "" data_mysql_admin_host: str = "127.0.0.1" data_mysql_admin_port: int = 0 data_mysql_admin_account_policy: str = "一人一号 · 单库授权 · 禁止 root" data_mysql_audit_enabled: bool = False # Mirrors the host-side Docker port binding so the Interface Center can # report an unsafe deployment instead of merely showing reassuring copy. mysql_host_bind: str = "127.0.0.1" # Production MySQL must use a durable block/filesystem mount outside the # application checkout. The host path and storage identity are passed in # for fail-closed readiness checks; the API never reads the data directory. data_mysql_storage_backend: str = "docker-volume" data_mysql_storage_id: str = "" data_mysql_storage_mount: str = "" data_mysql_data_dir: str = "" data_backup_enabled: bool = False data_backup_encryption_required: bool = True data_backup_retention_days: int = 30 data_backup_root: str = "" # FalkorDB falkordb_host: str = "localhost" falkordb_port: int = 6379 falkordb_graph: str = "guiyang" falkordb_password: str = "" # Auth auth_secret: str = "change-me-at-least-32-chars-long-secret" auth_algorithm: str = "HS256" auth_issuer: str = "zn-kg-admin" auth_audience: str = "zn-kg-admin-web" auth_token_expire_minutes: int = 60 auth_default_username: str = "admin@example.com" auth_default_password: str = "admin" auth_login_max_attempts: int = 5 auth_login_window_seconds: int = 300 auth_login_lock_seconds: int = 900 interface_api_default_expiry_days: int = 30 interface_api_max_expiry_days: int = 90 interface_api_rate_limit_per_minute: int = 120 # LLM llm_api_base: str = "" llm_api_key: str = "" llm_model: str = "deepseek-chat" llm_timeout_seconds: int = 30 llm_extraction_enabled: bool = False # App default_tenant: str = "guiyang" default_project: str = "default" ingest_api_keys: str = "dev-key-1" # AMap / Gaode JS API amap_web_key: str = "" amap_js_key: str = "" amap_security_jscode: str = "" # QWeather / 和风天气 (逐小时预报,高德无此能力,仅用于逐小时气温) qweather_api_key: str = "" qweather_api_host: str = "https://devapi.qweather.com" qweather_libo_location: str = "101260412" # 荔波县 LocationID # 阿里云 OCR (ocr-api.cn-hangzhou.aliyuncs.com, 2021-07-07) # 控制台 → AccessKey 管理 处生成;推荐用 RAM 子账号,仅授权 AliyunOCRFullAccess aliyun_ocr_access_key_id: str = "" aliyun_ocr_access_key_secret: str = "" aliyun_ocr_endpoint: str = "ocr-api.cn-hangzhou.aliyuncs.com" settings = Settings()