diff --git a/application/single_app/admin_settings_nav.py b/application/single_app/admin_settings_nav.py index 00dd71d46..e10f54c75 100644 --- a/application/single_app/admin_settings_nav.py +++ b/application/single_app/admin_settings_nav.py @@ -19,29 +19,35 @@ "icon": "bi-palette", "tabs": [ { - "id": "general", - "label": "General", - "icon": "bi-gear", + "id": "branding", + "label": "Branding", + "icon": "bi-palette", "sections": [ {"id": "branding-section", "label": "Branding", "icon": "bi-palette"}, {"id": "home-page-text-section", "label": "Home Page Text", "icon": "bi-house"}, {"id": "appearance-section", "label": "Appearance", "icon": "bi-brush"}, - {"id": "health-check-section", "label": "Health Check", "icon": "bi-heart-pulse"}, - {"id": "swagger-section", "label": "API Documentation", "icon": "bi-file-earmark-code"}, + ], + }, + { + # Everything the app states to the user before or during use: + # banners, notices and the agreements they must accept. + "id": "notices", + "label": "Notices & Agreements", + "icon": "bi-megaphone", + "sections": [ {"id": "classification-banner-section", "label": "Classification Banner", "icon": "bi-shield-exclamation"}, {"id": "ai-notice-section", "label": "Chat AI Notice", "icon": "bi-robot"}, {"id": "terms-of-use-section", "label": "Terms of Use", "icon": "bi-door-open"}, - {"id": "support-menu-section", "label": "Support", "icon": "bi-life-preserver"}, - {"id": "external-links-section", "label": "External Links", "icon": "bi-box-arrow-up-right"}, - {"id": "system-settings-section", "label": "System Settings", "icon": "bi-gear-fill"}, + {"id": "user-agreement-section", "label": "User Agreement", "icon": "bi-file-earmark-check"}, ], }, { "id": "custom-pages", - "label": "Custom Pages", + "label": "Pages & Links", "icon": "bi-window-plus", "sections": [ {"id": "custom-pages-section", "label": "Static Pages", "icon": "bi-file-earmark-richtext"}, + {"id": "external-links-section", "label": "External Links", "icon": "bi-box-arrow-up-right"}, ], }, ], @@ -138,7 +144,6 @@ {"id": "file-sharing-section", "label": "File Sharing", "icon": "bi-share"}, {"id": "metadata-extraction-section", "label": "Metadata Extraction", "icon": "bi-file-earmark-code"}, {"id": "multimodal-vision-section", "label": "Multi-Modal Vision Analysis", "icon": "bi-eye"}, - {"id": "user-agreement-section", "label": "User Agreement", "icon": "bi-file-earmark-check"}, ], }, { @@ -189,20 +194,40 @@ "icon": "bi-shield-lock", "tabs": [ { - "id": "security", - "label": "Security", - "icon": "bi-shield-lock", + # Who can get in and what role they need. Distinct from Content + # Safety, which is about what may be said once you are in. + "id": "access-roles", + "label": "Access & Roles", + "icon": "bi-person-check", + "sections": [ + {"id": "permissions-section", "label": "Permissions", "icon": "bi-person-check"}, + ], + }, + { + "id": "secrets", + "label": "Secrets", + "icon": "bi-safe", "sections": [ {"id": "keyvault-section", "label": "Key Vault", "icon": "bi-safe"}, ], }, { - "id": "safety", - "label": "Safety", - "icon": "bi-shield-check", + "id": "content-safety", + "label": "Content Safety", + "icon": "bi-shield-exclamation", "sections": [ {"id": "content-safety-section", "label": "Content Safety", "icon": "bi-shield-exclamation"}, - {"id": "permissions-section", "label": "Permissions", "icon": "bi-person-check"}, + ], + }, + { + # Interim home for the mixed System Settings card. Four of its + # eight fields are idle-timeout, which is the plurality; the + # rest are split out to their real homes in a later change. + "id": "session", + "label": "Session", + "icon": "bi-hourglass-split", + "sections": [ + {"id": "system-settings-section", "label": "System Settings", "icon": "bi-sliders"}, ], }, { @@ -348,12 +373,14 @@ }, { "id": "logging", - "label": "Logging", + "label": "Logging & Health", "icon": "bi-journal-text", "sections": [ {"id": "application-insights-section", "label": "Application Insights", "icon": "bi-graph-up"}, {"id": "debug-logging-section", "label": "Debug Logging", "icon": "bi-bug"}, {"id": "file-processing-logs-section", "label": "File Process Logging", "icon": "bi-file-earmark-text"}, + {"id": "health-check-section", "label": "Health Check", "icon": "bi-heart-pulse"}, + {"id": "swagger-section", "label": "API Documentation", "icon": "bi-file-earmark-code"}, ], }, ], @@ -363,6 +390,16 @@ "label": "Help", "icon": "bi-life-preserver", "tabs": [ + { + # Where an admin looks first when a user needs help, ahead of + # raising it with the project. + "id": "support-menu", + "label": "Support Menu", + "icon": "bi-life-preserver", + "sections": [ + {"id": "support-menu-section", "label": "Support", "icon": "bi-life-preserver"}, + ], + }, { "id": "send-feedback", "label": "Send Feedback", @@ -408,6 +445,18 @@ def get_group_for_tab(tab_id): return None +def get_landing_tab_id(): + """Return the tab an admin lands on when no tab is requested. + + This is the first tab of the first group rather than a fixed id, so the + landing pane follows the navigation map as cards are regrouped. Latest + Features is pinned last precisely so it can never win this. + """ + for _, tab in iter_tabs(): + return tab["id"] + return None + + def get_section_ids(): """Return every section target declared across the navigation.""" return [ diff --git a/application/single_app/app.py b/application/single_app/app.py index 35cc2d336..d8f837e33 100644 --- a/application/single_app/app.py +++ b/application/single_app/app.py @@ -31,7 +31,7 @@ from functions_content import * from functions_documents import * from functions_latest_features_nav import should_hide_latest_features_nav -from admin_settings_nav import ADMIN_NAV +from admin_settings_nav import ADMIN_NAV, get_landing_tab_id from functions_search import * from functions_settings import * from functions_mcp_server_config import is_mcp_ui_enabled @@ -600,6 +600,7 @@ def inject_settings(): user_settings=user_settings, custom_pages_nav=custom_pages_nav, admin_nav=ADMIN_NAV, + admin_landing_tab=get_landing_tab_id(), latest_features_current_version=VERSION, latest_features_nav_hidden=latest_features_nav_hidden, latest_features_nav_hidden_by_development=IS_DEVELOPMENT, diff --git a/application/single_app/config.py b/application/single_app/config.py index 0244ed3e0..e1fb9e3b7 100644 --- a/application/single_app/config.py +++ b/application/single_app/config.py @@ -96,7 +96,7 @@ EXECUTOR_TYPE = 'thread' EXECUTOR_MAX_WORKERS = 30 SESSION_TYPE = 'filesystem' -VERSION = "0.260.012" +VERSION = "0.260.013" IS_DEVELOPMENT = is_development_env_enabled() SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax') diff --git a/application/single_app/static/js/admin/admin_data_management.js b/application/single_app/static/js/admin/admin_data_management.js index 481b2069f..e8c2761a9 100644 --- a/application/single_app/static/js/admin/admin_data_management.js +++ b/application/single_app/static/js/admin/admin_data_management.js @@ -388,7 +388,8 @@ function bindEvents() { pendingDataManagementBackupDelete = null; }); elements.dataManagementConfirmBackupDeleteBtn?.addEventListener("click", deleteDataManagementBackup); - elements.dataManagementKeyVaultLink?.addEventListener("click", openKeyVaultSettings); + // The Key Vault link carries data-admin-link, so admin_card_links.js + // resolves the owning tab from the DOM and scrolls to the card. elements.dataManagementCosmosEditorOpenDangerBtn?.addEventListener("click", showCosmosEditorDangerModal); elements.datamanagementcosmoseditordangeraccept?.addEventListener("change", updateCosmosEditorDangerAcceptState); elements.dataManagementCosmosEditorAcceptDangerBtn?.addEventListener("click", acceptCosmosEditorDanger); @@ -909,20 +910,6 @@ function setKeyStorageAlert(variant, iconClass, title, message, linkText) { setText(elements.dataManagementKeyVaultLink, linkText); } -function openKeyVaultSettings(event) { - event?.preventDefault(); - const securityTabButton = document.getElementById("security-tab"); - if (securityTabButton && window.bootstrap?.Tab) { - window.bootstrap.Tab.getOrCreateInstance(securityTabButton).show(); - } else if (securityTabButton) { - securityTabButton.click(); - } - window.location.hash = "security"; - window.setTimeout(() => { - document.getElementById("keyvault-section")?.scrollIntoView({ block: "start", behavior: "smooth" }); - }, 100); -} - function collectSettings() { const backupStorageAuthenticationType = getValue(elements.datamanagementstorageauth) || backupStorageAuthManagedIdentity; return { diff --git a/application/single_app/static/js/admin/admin_sidebar_nav.js b/application/single_app/static/js/admin/admin_sidebar_nav.js index edad020d8..706c87e5f 100644 --- a/application/single_app/static/js/admin/admin_sidebar_nav.js +++ b/application/single_app/static/js/admin/admin_sidebar_nav.js @@ -145,12 +145,15 @@ function initAdminSidebarNav() { // Set the initial active tab - but only if no tab is already active. // Latest Features is deliberately excluded so it never opens by default. + // The landing tab is whichever tab the nav map renders first rather than a + // hardcoded id, so it stays correct as the information architecture moves. const activeTab = document.querySelector('.admin-nav-tab.active, .admin-nav-section.active'); if (!activeTab) { - const firstTab = document.querySelector('.admin-nav-tab[data-tab="general"]'); - if (firstTab) { + const firstTab = document.querySelector('.admin-nav-tab[data-tab]'); + const firstTabId = firstTab ? firstTab.getAttribute('data-tab') : null; + if (firstTabId) { firstTab.classList.add('active'); - showAdminTab('general'); + showAdminTab(firstTabId); } } else { console.log('initAdminSidebarNav - Found existing active tab, preserving current state:', activeTab.getAttribute('data-tab')); @@ -288,6 +291,9 @@ function revealAdminGroupForTab(tabId) { const LEGACY_TAB_REDIRECTS = { 'governance': 'feature-governance', 'scale': 'redis-caching', + 'general': 'branding', + 'safety': 'access-roles', + 'security': 'secrets', }; function resolveAdminTabId(tabId) { diff --git a/application/single_app/templates/admin/_panes/access-roles.html b/application/single_app/templates/admin/_panes/access-roles.html new file mode 100644 index 000000000..3e93d9ff7 --- /dev/null +++ b/application/single_app/templates/admin/_panes/access-roles.html @@ -0,0 +1,49 @@ +
+
+
+ Permissions +
+

Control which users can access specific administrative views related to safety and feedback.

+ + +
+ + + +
+

+ Required app role value: SafetyViolationAdmin. Assign this role to users or groups in the Enterprise App before enabling the requirement. If disabled, any user with the general Admin app role can access the Safety Violations admin page. +

+ + +
+ + + +
+

+ Required app role value: FeedbackAdmin. Assign this role to users or groups in the Enterprise App before enabling the requirement. If disabled, any user with the general Admin app role can access the User Feedback admin page. Requires Enable User Feedback to be active. +

+
+ + + + +
diff --git a/application/single_app/templates/admin/_panes/agents.html b/application/single_app/templates/admin/_panes/agents.html index 5994976d2..622dde43d 100644 --- a/application/single_app/templates/admin/_panes/agents.html +++ b/application/single_app/templates/admin/_panes/agents.html @@ -1,4 +1,4 @@ -
+

Configure AI agents and actions for enhanced functionality. Agents provide AI-driven task automation while Actions extend functionality with custom tools and integrations. diff --git a/application/single_app/templates/admin/_panes/ai-models.html b/application/single_app/templates/admin/_panes/ai-models.html index f12b06236..75437fded 100644 --- a/application/single_app/templates/admin/_panes/ai-models.html +++ b/application/single_app/templates/admin/_panes/ai-models.html @@ -1,4 +1,4 @@ -

+

Configure all AI model settings including GPT for text generation, embeddings for semantic search, and image generation capabilities. diff --git a/application/single_app/templates/admin/_panes/archiving.html b/application/single_app/templates/admin/_panes/archiving.html index 0d56b6223..d2943f47d 100644 --- a/application/single_app/templates/admin/_panes/archiving.html +++ b/application/single_app/templates/admin/_panes/archiving.html @@ -1,4 +1,4 @@ -

+
Conversation Archiving diff --git a/application/single_app/templates/admin/_panes/branding.html b/application/single_app/templates/admin/_panes/branding.html new file mode 100644 index 000000000..c648c07fa --- /dev/null +++ b/application/single_app/templates/admin/_panes/branding.html @@ -0,0 +1,165 @@ +
+ +

+ Configure general application settings, including the application's title, logo, and landing page text. +

+
+
+ Branding +
+

+ Configure your application's title, logo, and branding elements. +

+
+ + +
+
Logo Settings
+
+ + + +
+
+ + + +
+
+
+ + {{ settings.landing_page_logo_scale_percent | default(100) }}% +
+ +
+ 50% + 500% +
+ + Adjust the logo size on the home page only. This does not change the logo size in the top or sidebar navigation. + +
+
+ + + This logo will be displayed in light mode and stored at up to 500px tall so the main page can render it sharply without keeping oversized assets in settings. +
+
+ + + This logo will be displayed in dark mode. If not provided, the light mode logo will be used in both themes. Dark logos are also stored at up to 500px tall. +
+
+ + + Recommended: 16x16 or 32x32 pixel png or jpg or ico. +
+
+ +
+
+ Home Page Text +
+

Configure the text content displayed on your application's home page using Markdown formatting.

+ +
+ + + Choose how the landing page markdown is aligned on the home page. +
+ +
+ + + +
+ + + + +
+ +
+
+ Appearance +
+

Configure the app appearance and theme settings.

+ +
+ +
+ + + +
+

Users can still toggle dark mode individually from the navigation bar.

+
+ +
+ +
+ + + +
+

Users can still toggle the left navigation sidebar individually from the header.

+
+
+ + + + + + +
diff --git a/application/single_app/templates/admin/_panes/chat-experience.html b/application/single_app/templates/admin/_panes/chat-experience.html index 223e1beb0..37d8033a6 100644 --- a/application/single_app/templates/admin/_panes/chat-experience.html +++ b/application/single_app/templates/admin/_panes/chat-experience.html @@ -1,4 +1,4 @@ -
+
Processing Thoughts diff --git a/application/single_app/templates/admin/_panes/citation.html b/application/single_app/templates/admin/_panes/citation.html index 94f9788e1..4d42286e9 100644 --- a/application/single_app/templates/admin/_panes/citation.html +++ b/application/single_app/templates/admin/_panes/citation.html @@ -1,4 +1,4 @@ -
+

Configure standard and enhanced citations features for your and group workspaces. diff --git a/application/single_app/templates/admin/_panes/classification.html b/application/single_app/templates/admin/_panes/classification.html index 597736e46..425eeedcf 100644 --- a/application/single_app/templates/admin/_panes/classification.html +++ b/application/single_app/templates/admin/_panes/classification.html @@ -1,4 +1,4 @@ -

+
Document Classification diff --git a/application/single_app/templates/admin/_panes/safety.html b/application/single_app/templates/admin/_panes/content-safety.html similarity index 75% rename from application/single_app/templates/admin/_panes/safety.html rename to application/single_app/templates/admin/_panes/content-safety.html index c4973acdb..88eae95bb 100644 --- a/application/single_app/templates/admin/_panes/safety.html +++ b/application/single_app/templates/admin/_panes/content-safety.html @@ -1,4 +1,4 @@ -
+

Configure content safety, archiving, and user feedback settings. If Content Safety is enabled, user @@ -174,49 +174,6 @@

-
-
- Permissions -
-

Control which users can access specific administrative views related to safety and feedback.

- - -
- - - -
-

- Required app role value: SafetyViolationAdmin. Assign this role to users or groups in the Enterprise App before enabling the requirement. If disabled, any user with the general Admin app role can access the Safety Violations admin page. -

- - -
- - - -
-

- Required app role value: FeedbackAdmin. Assign this role to users or groups in the Enterprise App before enabling the requirement. If disabled, any user with the general Admin app role can access the User Feedback admin page. Requires Enable User Feedback to be active. -

-
diff --git a/application/single_app/templates/admin/_panes/control-center-config.html b/application/single_app/templates/admin/_panes/control-center-config.html index dd2143276..6567e5537 100644 --- a/application/single_app/templates/admin/_panes/control-center-config.html +++ b/application/single_app/templates/admin/_panes/control-center-config.html @@ -1,4 +1,4 @@ -
+

Configure Control Center access and permissions for administrators.

diff --git a/application/single_app/templates/admin/_panes/cosmos.html b/application/single_app/templates/admin/_panes/cosmos.html index 9d1fa89ca..33cf6b0f3 100644 --- a/application/single_app/templates/admin/_panes/cosmos.html +++ b/application/single_app/templates/admin/_panes/cosmos.html @@ -1,4 +1,4 @@ -
+
diff --git a/application/single_app/templates/admin/_panes/custom-pages.html b/application/single_app/templates/admin/_panes/custom-pages.html index a3d0f32ef..00fc68987 100644 --- a/application/single_app/templates/admin/_panes/custom-pages.html +++ b/application/single_app/templates/admin/_panes/custom-pages.html @@ -1,4 +1,4 @@ -
+

Enable trusted deployment-time custom pages and manage metadata for simple static pages served from the application custom_pages folders.

@@ -78,4 +78,56 @@
Static Page Metadata
+
diff --git a/application/single_app/templates/admin/_panes/data-management.html b/application/single_app/templates/admin/_panes/data-management.html index aba966397..d99c04990 100644 --- a/application/single_app/templates/admin/_panes/data-management.html +++ b/application/single_app/templates/admin/_panes/data-management.html @@ -1,4 +1,4 @@ -
+

Backup, Migrate & Restore

@@ -241,7 +241,7 @@
Encryption
Key Vault is strongly recommended
Generated backup encryption keys are stored in the Data Management settings document when Key Vault is not enabled.
- Open Key Vault settings + Open Key Vault settings
diff --git a/application/single_app/templates/admin/_panes/feature-governance.html b/application/single_app/templates/admin/_panes/feature-governance.html index d0f153d74..0b7dcfed1 100644 --- a/application/single_app/templates/admin/_panes/feature-governance.html +++ b/application/single_app/templates/admin/_panes/feature-governance.html @@ -1,4 +1,4 @@ -
+

Configure governance enforcement for endpoint, agent, and action creation or usage. Governance is disabled by default and only enforced when toggled on. diff --git a/application/single_app/templates/admin/_panes/feedback-alerts.html b/application/single_app/templates/admin/_panes/feedback-alerts.html index 4ee6ae562..5488e7242 100644 --- a/application/single_app/templates/admin/_panes/feedback-alerts.html +++ b/application/single_app/templates/admin/_panes/feedback-alerts.html @@ -1,4 +1,4 @@ -

+
User Feedback diff --git a/application/single_app/templates/admin/_panes/file-sync.html b/application/single_app/templates/admin/_panes/file-sync.html index 2d56920d2..eb440758a 100644 --- a/application/single_app/templates/admin/_panes/file-sync.html +++ b/application/single_app/templates/admin/_panes/file-sync.html @@ -1,4 +1,4 @@ -
+

Configure file synchronization for personal, group, and public workspaces.

diff --git a/application/single_app/templates/admin/_panes/general.html b/application/single_app/templates/admin/_panes/general.html deleted file mode 100644 index bd3d5be40..000000000 --- a/application/single_app/templates/admin/_panes/general.html +++ /dev/null @@ -1,682 +0,0 @@ -
- -

- Configure general application settings, including the application's title, logo, and landing page text. -

-
-
- Branding -
-

- Configure your application's title, logo, and branding elements. -

-
- - -
-
Logo Settings
-
- - - -
-
- - - -
-
-
- - {{ settings.landing_page_logo_scale_percent | default(100) }}% -
- -
- 50% - 500% -
- - Adjust the logo size on the home page only. This does not change the logo size in the top or sidebar navigation. - -
-
- - - This logo will be displayed in light mode and stored at up to 500px tall so the main page can render it sharply without keeping oversized assets in settings. -
-
- - - This logo will be displayed in dark mode. If not provided, the light mode logo will be used in both themes. Dark logos are also stored at up to 500px tall. -
-
- - - Recommended: 16x16 or 32x32 pixel png or jpg or ico. -
-
- -
-
- Home Page Text -
-

Configure the text content displayed on your application's home page using Markdown formatting.

- -
- - - Choose how the landing page markdown is aligned on the home page. -
- -
- - - -
- - - - -
- -
-
- Appearance -
-

Configure the app appearance and theme settings.

- -
- -
- - - -
-

Users can still toggle dark mode individually from the navigation bar.

-
- -
- -
- - - -
-

Users can still toggle the left navigation sidebar individually from the header.

-
-
- -
-
-
- Health Check -
- -
-

Configure health check endpoint for external monitoring systems.

- -
-
-
-
-
-
Authenticated Endpoint
-

Use when your monitoring system can reach a protected route and you want the endpoint governed by the normal app access boundary.

-
- Protected -
-
- - - -
-

Best for internal monitors or diagnostics tooling that already authenticates to the application.

-
-
-
-
-
-
-
Unauthenticated Endpoint
-

Use when a platform health probe cannot sign in and only needs a lightweight availability response.

-
- No Auth -
-
- - - -
- -
-
-
-
- -
-
-
- API Documentation -
-
- - - Open Swagger UI - -
-
-

Configure automatic OpenAPI/Swagger documentation for API endpoints.

- -
- - - -
-

- Provides interactive API documentation, endpoint testing, and schema validation. - Useful for developers, API integration, and system troubleshooting. -

-
- -
-
- Classification Banner -
-
- - - -
-
- - -
-
- - -
-
- - -
-
- - {{ settings.classification_banner_text or 'Banner Preview' }} - -
-
- -
-
- Chat AI Notice -
-

- Display an administrator-provided reminder directly below the chat input, such as guidance that responses are AI-generated and should be reviewed. -

-
- - -
-
-
- - -
Plain text only. Line breaks are preserved.
-
-
- - -
Changing the notice text or display behavior creates a new message version and shows it again.
-
-
-
- -
-
- Terms of Use -
-

- Require users to accept the Terms of Use before using SimpleChat. Standard Microsoft sign-in users see it before authentication; Teams SSO and other passive sign-in flows are gated immediately after the app session is created. -

- -
- - - -
- -
-
- - -
-
- - - Changing the title, message, or frequency creates a new terms version that users must accept again. -
-
- -
- - - Plain text is shown to users with line breaks preserved. -
- -
- - - Use a local path such as / or an admin-approved HTTP(S) URL. Signed-in users are locally logged out before this redirect. -
- -
-
- - -
-
- - -
-
- - -
- -
-
- Support -
-
- - - -
-

When enabled, users can access Support destinations like Send Feedback and Latest Features directly from navigation.

- -
-
- - - This name will appear in user navigation as the Support menu title. -
- -
- - - -
- -
- - - User Send Feedback drafts will be addressed to this internal email address. -
- -
- - - -
- -
-
User-Facing Latest Features
-

Choose which recent features are shared on the user Latest Features page. Deployment and Redis start unchecked because they are mainly admin-facing rollout and infrastructure topics.

-
- - - - When enabled, user-facing Latest Features cards can show public guide buttons in addition to the direct in-app shortcuts. -
- {% for release_group in support_latest_feature_release_groups %} - {% set checklist_collapse_id = release_group.collapse_id ~ 'Checklist' %} -
-
-
-
-
{{ release_group.label }}{% if release_group.release_version %}v{{ release_group.release_version }}{% endif %}
-

{{ release_group.description }}

-
- {% if not release_group.default_expanded %} - - {% endif %} -
-
-
- {% for feature in release_group.features %} -
-
- - -
-
- {% endfor %} -
-
-
-
- {% endfor %} -
-
-
- - - -
-
- System Settings -
-

- System-level settings that control application behavior, including file size limits, conversation history, - and default prompts. -

-
- - -
-
- - -
-
- - - -
-
-
- - - Users are logged out locally after this many minutes of inactivity. Minimum value: 10 minutes. -
-
- - - Show the warning modal after this many minutes of inactivity. Set this equal to the logout timeout to disable the warning dialog window. -
-
- - - Custom text shown at the top of the idle warning dialog. -
-
-
- - -
-
- - Shown to signed-in users who lack the required roles. Use Enter for line breaks. - -
-
-
diff --git a/application/single_app/templates/admin/_panes/governance-policies.html b/application/single_app/templates/admin/_panes/governance-policies.html index 8b9d2130f..da2b94fd1 100644 --- a/application/single_app/templates/admin/_panes/governance-policies.html +++ b/application/single_app/templates/admin/_panes/governance-policies.html @@ -1,4 +1,4 @@ -
+
Feature Policies
diff --git a/application/single_app/templates/admin/_panes/latest-features.html b/application/single_app/templates/admin/_panes/latest-features.html index 0ef37a941..a5d8c5f5d 100644 --- a/application/single_app/templates/admin/_panes/latest-features.html +++ b/application/single_app/templates/admin/_panes/latest-features.html @@ -1,4 +1,4 @@ -
+

Review the main capabilities introduced in v{{ config['VERSION'] }} and use this page as an admin-facing overview for what to highlight with your teams.

@@ -832,7 +832,7 @@

Admins can enable this once and let users see more of the model pipeline, including sending, generating, and responded states with clearer timing information.

  • Admins can choose whether this announcement is visible on the user-facing Latest Features page from General > User-Facing Latest Features.
  • +

    Configure health check endpoint for external monitoring systems.

    + +
    +
    +
    +
    +
    +
    Authenticated Endpoint
    +

    Use when your monitoring system can reach a protected route and you want the endpoint governed by the normal app access boundary.

    +
    + Protected +
    +
    + + + +
    +

    Best for internal monitors or diagnostics tooling that already authenticates to the application.

    +
    +
    +
    +
    +
    +
    +
    Unauthenticated Endpoint
    +

    Use when a platform health probe cannot sign in and only needs a lightweight availability response.

    +
    + No Auth +
    +
    + + + +
    + +
    +
    +
    +
    +
    +
    +
    + API Documentation +
    +
    + + + Open Swagger UI + +
    +
    +

    Configure automatic OpenAPI/Swagger documentation for API endpoints.

    + +
    + + + +
    +

    + Provides interactive API documentation, endpoint testing, and schema validation. + Useful for developers, API integration, and system troubleshooting. +

    +
    diff --git a/application/single_app/templates/admin/_panes/mcp-governance.html b/application/single_app/templates/admin/_panes/mcp-governance.html index 31080591e..8a57389de 100644 --- a/application/single_app/templates/admin/_panes/mcp-governance.html +++ b/application/single_app/templates/admin/_panes/mcp-governance.html @@ -1,4 +1,4 @@ -
    +
    MCP Action Destination Governance diff --git a/application/single_app/templates/admin/_panes/network.html b/application/single_app/templates/admin/_panes/network.html index 83ba4fb03..0f9216bad 100644 --- a/application/single_app/templates/admin/_panes/network.html +++ b/application/single_app/templates/admin/_panes/network.html @@ -1,4 +1,4 @@ -
    +
    diff --git a/application/single_app/templates/admin/_panes/notices.html b/application/single_app/templates/admin/_panes/notices.html new file mode 100644 index 000000000..c05ac2b68 --- /dev/null +++ b/application/single_app/templates/admin/_panes/notices.html @@ -0,0 +1,288 @@ +
    +
    +
    + Classification Banner +
    +
    + + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + {{ settings.classification_banner_text or 'Banner Preview' }} + +
    +
    + +
    +
    + Chat AI Notice +
    +

    + Display an administrator-provided reminder directly below the chat input, such as guidance that responses are AI-generated and should be reviewed. +

    +
    + + +
    +
    +
    + + +
    Plain text only. Line breaks are preserved.
    +
    +
    + + +
    Changing the notice text or display behavior creates a new message version and shows it again.
    +
    +
    +
    + +
    +
    + Terms of Use +
    +

    + Require users to accept the Terms of Use before using SimpleChat. Standard Microsoft sign-in users see it before authentication; Teams SSO and other passive sign-in flows are gated immediately after the app session is created. +

    + +
    + + + +
    + +
    +
    + + +
    +
    + + + Changing the title, message, or frequency creates a new terms version that users must accept again. +
    +
    + +
    + + + Plain text is shown to users with line breaks preserved. +
    + +
    + + + Use a local path such as / or an admin-approved HTTP(S) URL. Signed-in users are locally logged out before this redirect. +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    + + + +
    +
    + User Agreement +
    +

    + Configure a user agreement that users must accept before uploading files. + Supports Markdown formatting. +

    + + +
    + + + +
    + + +
    +
    + + +
    + +

    Select where the user agreement should be shown (at least one required):

    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    + +
    + + +
    + + +
    + 0 / 200 words + +
    +
    + + +
    + + + +
    + + +
    + +
    +
    +
    +
    diff --git a/application/single_app/templates/admin/_panes/redis-caching.html b/application/single_app/templates/admin/_panes/redis-caching.html index 16d846c71..5bbaa8c4d 100644 --- a/application/single_app/templates/admin/_panes/redis-caching.html +++ b/application/single_app/templates/admin/_panes/redis-caching.html @@ -1,4 +1,4 @@ -
    +
    {% set enable_dai_debug = settings.enable_dai_debug | default(false) %}

    Configure Redis cache to improve enterprise scale and performance by caching session data. Enabling Redis allows you to horizontally scale your application across multiple instances without losing session data. diff --git a/application/single_app/templates/admin/_panes/retention.html b/application/single_app/templates/admin/_panes/retention.html index c3aa2258a..a2bc06781 100644 --- a/application/single_app/templates/admin/_panes/retention.html +++ b/application/single_app/templates/admin/_panes/retention.html @@ -1,4 +1,4 @@ -

    +
    Retention Policy diff --git a/application/single_app/templates/admin/_panes/search-extract.html b/application/single_app/templates/admin/_panes/search-extract.html index 1db055f2b..04de8cc88 100644 --- a/application/single_app/templates/admin/_panes/search-extract.html +++ b/application/single_app/templates/admin/_panes/search-extract.html @@ -1,4 +1,4 @@ -
    +

    Configure Azure AI Search, Document Intelligence, and multimedia support settings. diff --git a/application/single_app/templates/admin/_panes/security.html b/application/single_app/templates/admin/_panes/secrets.html similarity index 99% rename from application/single_app/templates/admin/_panes/security.html rename to application/single_app/templates/admin/_panes/secrets.html index 40d43e1a9..dbf36ddc0 100644 --- a/application/single_app/templates/admin/_panes/security.html +++ b/application/single_app/templates/admin/_panes/secrets.html @@ -1,4 +1,4 @@ -

    +

    Manage security settings for key vault and other security configurations.

    diff --git a/application/single_app/templates/admin/_panes/send-feedback.html b/application/single_app/templates/admin/_panes/send-feedback.html index 1d9cdb365..5acd28833 100644 --- a/application/single_app/templates/admin/_panes/send-feedback.html +++ b/application/single_app/templates/admin/_panes/send-feedback.html @@ -1,4 +1,4 @@ -
    +

    Prepare a prefilled email draft for bug reports or feature requests. This utility is separate from saved settings and records each submission intent in the activity log before opening your local email client.

    diff --git a/application/single_app/templates/admin/_panes/session.html b/application/single_app/templates/admin/_panes/session.html new file mode 100644 index 000000000..cb8fe9abe --- /dev/null +++ b/application/single_app/templates/admin/_panes/session.html @@ -0,0 +1,87 @@ +
    +
    +
    + System Settings +
    +

    + System-level settings that control application behavior, including file size limits, conversation history, + and default prompts. +

    +
    + + +
    +
    + + +
    +
    + + + +
    +
    +
    + + + Users are logged out locally after this many minutes of inactivity. Minimum value: 10 minutes. +
    +
    + + + Show the warning modal after this many minutes of inactivity. Set this equal to the logout timeout to disable the warning dialog window. +
    +
    + + + Custom text shown at the top of the idle warning dialog. +
    +
    +
    + + +
    +
    + + Shown to signed-in users who lack the required roles. Use Enter for line breaks. + +
    +
    +
    \ No newline at end of file diff --git a/application/single_app/templates/admin/_panes/support-menu.html b/application/single_app/templates/admin/_panes/support-menu.html new file mode 100644 index 000000000..57c11877b --- /dev/null +++ b/application/single_app/templates/admin/_panes/support-menu.html @@ -0,0 +1,105 @@ +
    +
    +
    + Support +
    +
    + + + +
    +

    When enabled, users can access Support destinations like Send Feedback and Latest Features directly from navigation.

    + +
    +
    + + + This name will appear in user navigation as the Support menu title. +
    + +
    + + + +
    + +
    + + + User Send Feedback drafts will be addressed to this internal email address. +
    + +
    + + + +
    + +
    +
    User-Facing Latest Features
    +

    Choose which recent features are shared on the user Latest Features page. Deployment and Redis start unchecked because they are mainly admin-facing rollout and infrastructure topics.

    +
    + + + + When enabled, user-facing Latest Features cards can show public guide buttons in addition to the direct in-app shortcuts. +
    + {% for release_group in support_latest_feature_release_groups %} + {% set checklist_collapse_id = release_group.collapse_id ~ 'Checklist' %} +
    +
    +
    +
    +
    {{ release_group.label }}{% if release_group.release_version %}v{{ release_group.release_version }}{% endif %}
    +

    {{ release_group.description }}

    +
    + {% if not release_group.default_expanded %} + + {% endif %} +
    +
    +
    + {% for feature in release_group.features %} +
    +
    + + +
    +
    + {% endfor %} +
    +
    +
    +
    + {% endfor %} +
    +
    +
    +
    \ No newline at end of file diff --git a/application/single_app/templates/admin/_panes/workspace-identities.html b/application/single_app/templates/admin/_panes/workspace-identities.html index da77b91b5..7c3569ebd 100644 --- a/application/single_app/templates/admin/_panes/workspace-identities.html +++ b/application/single_app/templates/admin/_panes/workspace-identities.html @@ -1,4 +1,4 @@ -
    +

    Manage the global authentication profiles that File Sync sources and Actions reuse, so credentials stay scoped and are resolved server-side.

    diff --git a/application/single_app/templates/admin/_panes/workspaces.html b/application/single_app/templates/admin/_panes/workspaces.html index 9200f71d9..690a902af 100644 --- a/application/single_app/templates/admin/_panes/workspaces.html +++ b/application/single_app/templates/admin/_panes/workspaces.html @@ -1,4 +1,4 @@ -
    +

    Configure workspace settings like personal/group access, multimedia support, metadata, and document classification.

    @@ -640,107 +640,4 @@
    -
    -
    - User Agreement -
    -

    - Configure a user agreement that users must accept before uploading files. - Supports Markdown formatting. -

    - - -
    - - - -
    - - -
    -
    - - -
    - -

    Select where the user agreement should be shown (at least one required):

    -
    -
    -
    - - -
    -
    - - -
    -
    -
    -
    - - -
    -
    - - -
    -
    -
    - -
    - - -
    - - -
    - 0 / 200 words - -
    -
    - - -
    - - - -
    - - -
    - -
    -
    -
    diff --git a/application/single_app/templates/admin_settings.html b/application/single_app/templates/admin_settings.html index 65e958b1d..118431f86 100644 --- a/application/single_app/templates/admin_settings.html +++ b/application/single_app/templates/admin_settings.html @@ -980,7 +980,10 @@

    12. Enhanced Citations and Image Generation

    visible whichever governance tab is active. #}
    - {% include "admin/_panes/security.html" %} + {% include "admin/_panes/secrets.html" %} + {% include "admin/_panes/access-roles.html" %} + {% include "admin/_panes/content-safety.html" %} + {% include "admin/_panes/session.html" %} {% include "admin/_panes/agents.html" %} @@ -994,7 +997,8 @@

    12. Enhanced Citations and Image Generation

    {% include "admin/_panes/logging.html" %} - {% include "admin/_panes/general.html" %} + {% include "admin/_panes/branding.html" %} + {% include "admin/_panes/notices.html" %} {% include "admin/_panes/custom-pages.html" %} @@ -1031,11 +1035,11 @@

    12. Enhanced Citations and Image Generation

    {% include "admin/_panes/feedback-alerts.html" %} - {% include "admin/_panes/safety.html" %} {% include "admin/_panes/search-extract.html" %} + {% include "admin/_panes/support-menu.html" %} {% include "admin/_panes/send-feedback.html" %} {# Latest Features stays last so it never opens by default #} diff --git a/docs/explanation/features/ADMIN_SETTINGS_IA_REWORK_STATUS.md b/docs/explanation/features/ADMIN_SETTINGS_IA_REWORK_STATUS.md index 0e9a7ef64..3632338b9 100644 --- a/docs/explanation/features/ADMIN_SETTINGS_IA_REWORK_STATUS.md +++ b/docs/explanation/features/ADMIN_SETTINGS_IA_REWORK_STATUS.md @@ -22,8 +22,8 @@ Development ─── feature/admin-settings-ia ──┬── #1297 stage 1 └──► final PR ──► Development ``` -Current version: **0.260.012**. Fingerprint: **462 field names / 110 card ids**. -Navigation: **13 groups / 27 tabs / 88 sections**. +Current version: **0.260.013**. Fingerprint: **462 field names / 110 card ids**. +Navigation: **13 groups / 31 tabs / 88 sections**. ### Shipped @@ -109,6 +109,29 @@ moved from Scale to Security that way. | Scale | → Redis & Caching, Cosmos; Front Door moved to Security as Network | | Data Lifecycle | **New group.** Retention + Classification pulled from Workspaces, Archiving pulled from Safety | | Chat | **New group.** Chat Experience (thoughts from AI Models, file uploads + contents drawer and scope lock from Workspaces), Feedback & Alerts (feedback + desktop notifications from Safety) | +| Appearance | **General dismantled.** → Branding, Notices & Agreements (+ user agreement from Workspaces), Pages & Links (+ external links) | +| Security | **Safety dismantled.** → Access & Roles, Secrets, Content Safety, Session, Network | +| Operations | Logging is now Logging & Health, gaining health check and API documentation from General | +| Help | Gains Support Menu from General | + +### Two hardcoded-id traps found and closed + +Both were latent breakage that only surfaced because a tab id changed: + +- **`openKeyVaultSettings`** in `admin_data_management.js` switched tabs by the + literal id `security-tab`. It was dead weight anyway — the link now carries + `data-admin-link` and `admin_card_links.js` resolves the tab from the DOM. +- **The landing pane** was `show active` hardcoded in one pane's markup and + `showAdminTab('general')` hardcoded in the sidebar script. Splitting that + pane left Admin Settings with **no active pane at all**. Every pane now + renders `{% if admin_landing_tab == '' %} show active{% endif %}`, fed by + `get_landing_tab_id()`, and the sidebar reads the first rendered tab. + +**Assert durable properties, not current ids.** Four test files hardcoded +`general` or `security` and had to be rewritten to assert what actually matters +— Latest Features is last, exactly one pane is active, every tab renders one +pane. Any new test that names a tab id will need the same treatment next time. + ### The cross-pane move tool diff --git a/docs/explanation/release_notes.md b/docs/explanation/release_notes.md index 3d12d8127..8380fa7a2 100644 --- a/docs/explanation/release_notes.md +++ b/docs/explanation/release_notes.md @@ -2,6 +2,38 @@ For feature-focused and fix-focused drill-downs by version, see [Features by Version](/explanation/features/) and [Fixes by Version](/explanation/fixes/). +### **(v0.260.013)** + +#### User Interface Enhancements + +* **General Tab Broken Up Into Focused Tabs** + * General had grown into a catch-all of eleven unrelated cards: branding sat next to health checks, API documentation, terms of use and system settings. + * Appearance now has **Branding** (branding, home page text, appearance), **Notices & Agreements** (classification banner, chat AI notice, terms of use and the user agreement pulled across from Workspaces) and **Pages & Links** (static pages plus external links). + * Health Check and API Documentation moved to Operations, which is now **Logging & Health** — they report on how the app is running rather than how it looks. + * Support moved to Help as its own **Support Menu** tab, next to Send Feedback. + * (Ref: `branding`, `notices`, `custom-pages`, `logging`, `support-menu`) + +* **Security Split Into Five Purposeful Tabs** + * Security held a single Key Vault card while an unrelated Safety tab mixed content filtering with role permissions, which are different jobs. + * Security is now **Access & Roles** (who gets in and with what role), **Secrets** (Key Vault), **Content Safety** (what may be said once you are in), **Session** (idle timeout and related system settings) and **Network** (Azure Front Door). + * (Ref: `access-roles`, `secrets`, `content-safety`, `session`, `network`) + +#### Bug Fixes + +* **"Open Key Vault Settings" Link No Longer Depends On A Hardcoded Tab** + * The link from Data Management to Key Vault switched tabs by a hardcoded id, so it silently stopped working whenever that tab was renamed. + * It now uses the standard card link, which finds the owning tab from the page itself and stays correct however the settings are grouped. + * (Ref: `data-management-key-vault-link`, `admin_card_links.js`, `admin_data_management.js`) + +* **Admin Settings Always Opens On A Real Tab** + * The tab shown on arrival was pinned to a specific id in both the markup and the sidebar script. Regrouping settings could leave Admin Settings opening with no tab selected at all. + * The landing tab is now taken from the navigation map, so it follows the settings and can never be Latest Features. + * (Ref: `admin_landing_tab`, `get_landing_tab_id`, `admin_sidebar_nav.js`) + +* **Stale Tab Names In Latest Features** + * Several Latest Features entries pointed readers at tabs by their old names after the settings moved. + * (Ref: `latest-features` pane) + ### **(v0.260.012)** #### User Interface Enhancements diff --git a/functional_tests/test_admin_latest_features_tab.py b/functional_tests/test_admin_latest_features_tab.py index 322bfea1a..31d96dfc4 100644 --- a/functional_tests/test_admin_latest_features_tab.py +++ b/functional_tests/test_admin_latest_features_tab.py @@ -341,7 +341,7 @@ def test_latest_features_sidebar_navigation(): # Tab order is defined once in the nav map, which the sidebar renders from, # so ordering is asserted there rather than against the rendered markup. tab_ids = get_tab_ids() - assert tab_ids.index('latest-features') > tab_ids.index('general'), 'Latest Features should appear after General' + assert tab_ids[-1] == 'latest-features', 'Latest Features should be the last destination of all' assert tab_ids.index('latest-features') > tab_ids.index('send-feedback'), 'Latest Features should be the last destination, after Send Feedback' print('Latest Features sidebar navigation is present') @@ -372,10 +372,18 @@ def test_latest_features_top_nav_priority(): ) # Latest Features opened on every visit to Admin Settings, which is why it - # is pinned last and General is the landing tab instead. - assert 'class="tab-pane fade" id="latest-features" role="tabpanel" aria-labelledby="latest-features-tab"' in template_content, 'Latest Features pane should not be the default active tab' - assert 'class="tab-pane fade show active" id="general" role="tabpanel" aria-labelledby="general-tab"' in template_content, 'General pane should be the default active tab' - assert tab_ids[0] == 'general', 'General should be the first tab in the navigation map' + # is pinned last. The landing pane is not hardcoded: every pane derives its + # active state from admin_landing_tab, which is the first tab of the first + # group, so regrouping cards can never leave Admin Settings with no pane + # showing or with Latest Features showing. + assert '
    1}) assert not duplicates, f'Tabs listed more than once in the nav map: {duplicates}' - assert template_content.count('id="security" role="tabpanel"') == 1, 'Security tab pane should appear exactly once' - assert template_content.count('tab-pane fade show active') == 1, 'Only one tab pane should be marked show active' + # Every tab in the map must render exactly one pane. Checking all of them + # is stronger than naming one tab, and cannot go stale as tabs are renamed. + for tab_id in tab_ids: + pane_count = template_content.count(f'id="{tab_id}" role="tabpanel"') + assert pane_count == 1, f"Tab pane '{tab_id}' should appear exactly once, found {pane_count}" + # No pane may hardcode the active state; exactly one resolves it at render + # time from the nav map. + assert template_content.count('tab-pane fade show active') == 0, ( + 'No pane should hardcode "show active"; it is derived from admin_landing_tab' + ) + landing_conditionals = template_content.count("{% if admin_landing_tab == '") + assert landing_conditionals == len(tab_ids), ( + f'Every one of the {len(tab_ids)} panes should derive its active state ' + f'from admin_landing_tab, found {landing_conditionals}' + ) assert 'Managesecuritysettingsforkeyvaultandothersecurityconfigurations.

    ' in normalized_template, 'Security intro paragraph should be properly closed' # Every tab in the map must have a pane to activate. diff --git a/functional_tests/test_admin_settings_nav_map.py b/functional_tests/test_admin_settings_nav_map.py index ce015c6f6..0754dddf9 100644 --- a/functional_tests/test_admin_settings_nav_map.py +++ b/functional_tests/test_admin_settings_nav_map.py @@ -143,14 +143,23 @@ def test_latest_features_stays_last(): assert tab_ids[-1] == "latest-features", ( f"Latest Features must be the last tab, got '{tab_ids[-1]}'" ) - assert tab_ids[0] == "general", ( - f"General must be the first tab, got '{tab_ids[0]}'" - ) assert ADMIN_NAV[-1]["id"] == "help", ( "Latest Features should sit in the last group" ) - print("Latest Features is last; General leads.") + # The landing tab is whatever the map lists first, so it moves freely as the + # information architecture changes. What must never drift is that the admin + # does not land on Latest Features, which is the whole point of the move. + assert tab_ids[0] != "latest-features", ( + "Latest Features must never be the landing tab" + ) + assert ADMIN_NAV[0]["tabs"], "The first group must expose at least one tab" + assert tab_ids[0] == ADMIN_NAV[0]["tabs"][0]["id"], ( + "The landing tab must be the first tab of the first group, so the " + "sidebar and the tab strip agree on where an admin lands" + ) + + print(f"Latest Features is last; '{tab_ids[0]}' leads.") if __name__ == "__main__": diff --git a/functional_tests/test_admin_source_review_depth_save.py b/functional_tests/test_admin_source_review_depth_save.py index fa7a602cd..528bf0c0e 100644 --- a/functional_tests/test_admin_source_review_depth_save.py +++ b/functional_tests/test_admin_source_review_depth_save.py @@ -41,9 +41,11 @@ def test_source_review_depth_has_single_form_field(): f"Expected exactly one source_review_max_depth form field, found {depth_field_name_count}." ) + # Bound the Latest Features visibility block by its own container rather + # than by a neighbouring card, so the check survives cards moving between + # tabs during information architecture work. latest_features_start = template_content.index('id="support_latest_features_settings"') - external_links_start = template_content.index('id="external-links-section"') - latest_features_section = template_content[latest_features_start:external_links_start] + latest_features_section = template_content[latest_features_start:latest_features_start + 8000] assert 'name="source_review_max_depth"' not in latest_features_section, ( "Latest Features visibility controls must not post source_review_max_depth." diff --git a/functional_tests/test_data_management_security_patterns.py b/functional_tests/test_data_management_security_patterns.py index 422e3dfbf..284c123be 100644 --- a/functional_tests/test_data_management_security_patterns.py +++ b/functional_tests/test_data_management_security_patterns.py @@ -345,7 +345,6 @@ def test_admin_javascript_uses_safe_dom_patterns(): for required_snippet in [ 'document.createElement("tr")', 'document.createElement("td")', - 'openKeyVaultSettings', 'buildMigrationPlan()', 'queueMigration(false)', 'loadMigrationCatalog(targetType, "reset")',