## ADDED Requirements ### Requirement: AiRuntimeConfig schema The system SHALL represent AI runtime settings as a shared `AiRuntimeConfig` document including at least: `version`, `updatedAt` (ISO8601), `source` (`pc` | `server`), `vendor`, `model`, `baseUrl`, `apiKey`, `prompts` (including `pdfAsk`, `videoAsk`, `audioAsk`), and `features` flags (`pdfChat`, `videoRegionAsk`, `audioClipAsk`). API keys MUST NOT be embedded in course pack zips or course manifests. #### Scenario: Config fields present after save - **WHEN** a parent saves AI settings on desktop StudyDeck - **THEN** the persisted config includes vendor, model, updatedAt, prompts, features, and a stored apiKey for later sync #### Scenario: Course pack excludes apiKey - **WHEN** a course pack zip is built for publish - **THEN** the pack MUST NOT contain the AI apiKey or AiRuntimeConfig secrets ### Requirement: Desktop AI settings UI Desktop StudyDeck SHALL provide an AI settings surface to edit vendor, model, optional baseUrl, apiKey, feature prompts, and feature toggles; to save (bumping `updatedAt`); and to run a minimal connectivity test against the configured endpoint. #### Scenario: Save bumps updatedAt - **WHEN** the parent saves AI settings - **THEN** `updatedAt` is set to the current time and `source` is `pc` #### Scenario: Key masked in UI - **WHEN** a saved apiKey exists - **THEN** the UI MUST NOT show the full key by default (e.g. only last four characters or a password field) #### Scenario: Test connection - **WHEN** the parent runs “测试连接” with a valid configuration - **THEN** the app attempts a minimal request to the configured baseUrl/model and reports success or a clear error ### Requirement: Secure desktop key storage Desktop StudyDeck SHALL store the apiKey using OS-backed secure storage (platform keychain/credential manager) or an encrypted local fallback, and MUST NOT write the raw apiKey to world-readable plaintext logs. #### Scenario: Key not in plaintext library JSON - **WHEN** AI settings are saved - **THEN** the raw apiKey is not stored in cleartext inside the ordinary library catalog JSON files