Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.250.195"
VERSION = "0.250.196"
IS_DEVELOPMENT = is_development_env_enabled()

SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax')
Expand Down
2 changes: 1 addition & 1 deletion application/single_app/templates/_top_nav.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{% set is_chat_page = request.endpoint == 'frontend_chats.chats' %}
{% set latest_features_nav_is_hidden = latest_features_nav_hidden | default(false) %}
{% set public_workspace_labels = app_settings.public_workspace_labels %}

Check warning on line 3 in application/single_app/templates/_top_nav.html

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top top-nav-bar{% if is_chat_page %} top-nav-bar-chat{% endif %}">
<div class="container-fluid top-nav-shell{% if is_chat_page %} top-nav-shell-chat{% endif %}">
<div class="top-nav-brand">
Expand Down Expand Up @@ -396,4 +397,3 @@
</div>
</div>
{% endif %}
{% set public_workspace_labels = app_settings.public_workspace_labels %}
64 changes: 64 additions & 0 deletions docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Top Navigation Public Workspace Label Crash Fix

Fixed/Implemented in version: **0.250.196**

Version reference: `application/single_app/config.py` reports version `0.250.196`.

## Issue Description

Users could save the top navigation preference, but subsequent page requests returned a server error when Public Workspaces was enabled. Removing `"navLayout": "top"` from the user's Cosmos settings document allowed the application to render again because it restored the sidebar navigation path.

Check warning on line 9 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.

## Root Cause Analysis

The stored navigation preference was valid. It caused `base.html` to include `_top_nav.html`, where the signed-in user menu referenced `public_workspace_labels.plural` before the template assigned `public_workspace_labels`.

Check warning on line 13 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.

Jinja treats an assignment in the template as a template-local variable. The earlier attribute lookup therefore raised `jinja2.exceptions.UndefinedError` instead of using the label context already available through `app_settings`. The sidebar navigation did not fail because it initialized the same variable before its first use.

## Technical Details

Files modified:

- `application/single_app/templates/_top_nav.html`
- `application/single_app/config.py`
- `functional_tests/test_public_workspace_display_name_settings.py`

Check warning on line 23 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
- `ui_tests/test_chat_sidebar_toggle_controls.py`
- `docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md`

Check warning on line 25 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
- `docs/explanation/release_notes.md`

Code changes summary:

- Moved the `public_workspace_labels` assignment to the top-navigation initialization block.

Check warning on line 30 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
- Preserved the existing `navLayout` setting, Cosmos document shape, navigation conditions, routes, and responsive behavior.

Check warning on line 31 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
- Added a deterministic render regression using the real top-navigation template with a signed-in user, Public Workspaces enabled, a custom label, and the persisted top-navigation preference.
- Strengthened the authenticated browser workflow to verify that a page loaded with persisted top navigation returns successfully and exposes a usable user menu.

Impact:

- Users can select top navigation without becoming locked out of the application when Public Workspaces is enabled.
- Default and customized Public Workspace labels continue to appear in the top-navigation user menu.
- No settings migration or manual Cosmos profile repair is required after deployment.

Check warning on line 39 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.

## Validation

Testing approach:

- Run `python functional_tests/test_public_workspace_display_name_settings.py`.

Check warning on line 45 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains AI, plugin, agent, or workspace boundary marker. Recommendation%3A Check whether prompts, chat history, uploaded documents, embeddings, citations, settings, or identity can cross a new boundary.
- Run `pytest ui_tests/test_chat_sidebar_toggle_controls.py::test_chat_sidebar_desktop_uses_sidebar_toggle_without_inline_duplicate` against an authenticated UI environment.
- Run `git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check`.

Test results:

- The Public Workspace display-name functional test passed all four checks, including the real top-navigation render regression.

Check warning on line 51 in docs/explanation/fixes/TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
- The changed Python test files passed syntax compilation.
- The authenticated Playwright test was collected successfully and skipped because the local UI base URL and storage state were not configured.
- The repository diff check passed.

Before:

- Rendering `_top_nav.html` for a signed-in user with Public Workspaces enabled raised `UndefinedError: 'public_workspace_labels' is undefined`.
- Any page using the persisted top-navigation layout could return a server error.

After:

- The label context is initialized before any top-navigation branch reads it.
- The same render path succeeds and includes the configured Public Workspace label.
9 changes: 9 additions & 0 deletions docs/explanation/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

For feature-focused and fix-focused drill-downs by version, see [Features by Version](/explanation/features/) and [Fixes by Version](/explanation/fixes/).

### **(v0.250.196)**

#### Bug Fixes

* **Top Navigation Public Workspace Lockout**
* Fixed a server-rendering failure that could lock users out after they selected top navigation while Public Workspaces was enabled.
* Preserved the saved navigation preference and default or customized Public Workspace labels without requiring a Cosmos profile repair.
* (Ref: `_top_nav.html`, `test_public_workspace_display_name_settings.py`, `TOP_NAV_PUBLIC_WORKSPACE_LABEL_CRASH_FIX.md`)

### **(v0.250.185)**

#### Bug Fixes
Expand Down
60 changes: 58 additions & 2 deletions functional_tests/test_public_workspace_display_name_settings.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
#!/usr/bin/env python3
"""
Functional test for configurable Public Workspace end-user display names.
Version: 0.250.110
Version: 0.250.196
Implemented in: 0.250.110
Top-navigation crash regression added in: 0.250.196

This test ensures that Public Workspace display-name settings are normalized,
derived labels are safe for frontend use, and only the raw setting is persisted.
derived labels are safe for frontend use, only the raw setting is persisted,
and the top navigation can render those labels for signed-in users.
"""

import ast
import os
import sys
from types import SimpleNamespace

from jinja2 import Environment

sys.path.append(os.path.dirname(os.path.abspath(__file__)))

Expand All @@ -19,6 +24,7 @@
ADMIN_ROUTE = os.path.join(REPO_ROOT, "application", "single_app", "route_frontend_admin_settings.py")
ADMIN_TEMPLATE = os.path.join(REPO_ROOT, "application", "single_app", "templates", "admin_settings.html")
BASE_TEMPLATE = os.path.join(REPO_ROOT, "application", "single_app", "templates", "base.html")
TOP_NAV_TEMPLATE = os.path.join(REPO_ROOT, "application", "single_app", "templates", "_top_nav.html")


def read_source(path):
Expand Down Expand Up @@ -122,6 +128,55 @@ def test_display_name_persistence_shape():
return True


def test_top_navigation_renders_public_workspace_labels():
"""Validate persisted top navigation renders enabled Public Workspace labels."""
print("Testing top navigation Public Workspace label rendering...")
template_source = read_source(TOP_NAV_TEMPLATE)
app_settings = {
"show_logo": False,
"hide_app_title": False,
"app_title": "SimpleChat",
"enable_user_workspace": False,
"enable_group_workspaces": False,
"enable_public_workspaces": True,
"enable_custom_pages": False,
"enable_support_menu": False,
"enable_external_links": False,
"enable_user_feedback": False,
"enable_content_safety": False,
"require_member_of_control_center_admin": True,
"require_member_of_control_center_dashboard_reader": True,
"require_member_of_safety_violation_admin": True,
"require_member_of_feedback_admin": True,
"public_workspace_labels": {
"plural": "Knowledge Spaces",
},
}
rendered = Environment(autoescape=True).from_string(template_source).render(
request=SimpleNamespace(endpoint="frontend_workspace.workspace"),
session={
"user": {
"name": "Test User",
"roles": ["User"],
},
},
app_settings=app_settings,
user_settings={
"settings": {
"navLayout": "top",
},
},
latest_features_nav_hidden=False,
custom_pages_nav=[],
url_for=lambda endpoint, **kwargs: f"/{endpoint}",
)

assert '<nav class="navbar ' in rendered
assert "My Knowledge Spaces" in rendered
print("Top navigation Public Workspace label rendering passed.")
return True


def test_admin_and_frontend_wiring():
"""Validate Admin Settings and frontend sanitized-label wiring."""
print("Testing Public Workspace display-name wiring...")
Expand Down Expand Up @@ -179,6 +234,7 @@ def main():
tests = [
test_display_name_normalization,
test_display_name_persistence_shape,
test_top_navigation_renders_public_workspace_labels,
test_admin_and_frontend_wiring,
]
results = []
Expand Down
8 changes: 7 additions & 1 deletion ui_tests/test_chat_sidebar_toggle_controls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# test_chat_sidebar_toggle_controls.py
"""
UI test for the unified chat navigation shell.
Version: 0.241.018
Version: 0.250.196
Implemented in: 0.241.018
Top-navigation crash regression added in: 0.250.196

This test ensures that chats in top-nav mode use the adaptive conversation
rail, preserve compact desktop top-nav links, and become the hamburger drawer
Expand Down Expand Up @@ -100,9 +101,14 @@ def test_chat_sidebar_desktop_uses_sidebar_toggle_without_inline_duplicate(playw
expect(page.locator("#chat-sidebar-inline-toggle")).to_have_count(0)
expect(page.locator("#floating-expand-btn")).to_have_count(0)
expect(page.locator("#topNavMobileMenu")).to_have_count(0)
expect(page.locator("nav.top-nav-bar")).to_be_visible()
expect(page.locator(".top-nav-chat-nav")).to_be_visible()
expect(page.locator(".top-nav-chat-nav .nav-link").first).to_be_visible()

page.locator("#userDropdown").click()
expect(page.locator(".top-nav-user-menu.show")).to_be_visible()
page.locator("#userDropdown").click()

sidebar_toggle.click()
page.wait_for_function("document.body.classList.contains('sidebar-collapsed')")

Expand Down
Loading