Skip to content

Fix V2 Control Center Dashboard, Users and Groups 500s; remove Data health - #1702

Merged
Paul Lizer (paullizer) merged 5 commits into
paullizer-react-v2-uifrom
paullizer-control-center-v2-fixes
Oct 7, 2026
Merged

Paul Lizer (paullizer) merged 5 commits into
paullizer-react-v2-uifrom
paullizer-control-center-v2-fixes

Conversation

@paullizer

@paullizer Paul Lizer (paullizer) commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • The V2 Control Center Dashboard, Users and Groups load again. All three returned HTTP 500 ("Failed to retrieve dashboard insights.", "Unable to retrieve users.", "Unable to retrieve groups."). On the live deployment, App Insights recorded every failure as a CosmosHttpResponseError, meaning Cosmos DB answered HTTP 400. The azure-cosmos Python SDK cannot run cross-partition GROUP BY or COUNT over a DISTINCT subquery, because its query-plan request advertises neither the GroupBy nor the DCount feature. That is still true in 4.16.3 (the app pins 4.9.0), so upgrading would not help. Separately, the Users sort used ORDER BY <field>, c.id, which needs a composite index that user_settings does not have.
  • Only the query shapes change; response contracts are unchanged. The Dashboard counts SELECT DISTINCT VALUE results, derives uploads by workspace type from VALUE COUNT totals, tallies a SELECT VALUE c.status projection, and builds insights from two streamed projections. Users pages through users with a recorded sort value, ordered by that single property, and then users without one, ordered by c.id; Public Workspaces already uses this pattern. The Groups inventory keeps its four batched queries and 90-second snapshot but aggregates streamed projections. Existing deployments need no index change or App Maintenance step.
  • Data health is removed because it is no longer needed. Its now-unused GET /api/admin/control-center/migrate/status and POST /api/admin/control-center/migrate/all APIs and the backfill-only has_activity_log_for_resource helper are removed with it. The classic Control Center stopped calling these APIs in 0.261.278. Old /v2/control-center/data-health bookmarks now open the Dashboard.
  • Regression guard: functional_tests/test_support/cosmos_query_guard.py rejects these query shapes in test fakes, and a new test AST-scans every V2 Control Center SQL string through it. The old fakes accepted any SQL, and some tests asserted that the GROUP BY text was present.

Notes for reviewers:

  • Live traces show the GROUP BY rejection directly: the groups query-plan request itself returned 400. The COUNT over DISTINCT finding comes from the SDK source, which has no DCount support; no trace shows it because the dashboard summary fails on a GROUP BY first.
  • The login heatmap now totals each UTC weekday and hour across the whole period. Before, the API returned one cell per date and hour and the UI showed only the first matching date, so repeated weekdays were undercounted. The response shape is the same.
  • Users with no recorded value for the sort column are listed last in either direction, in ID order. As in Public Workspaces, equal recorded values have no guaranteed secondary order.
  • The Users CSV export runs its first query before streaming, so a storage failure returns the JSON 500 instead of a header-only file.
  • In-app aggregation reads the same documents the GROUP BY queries would have read, but returns narrow projections. The 90-second dashboard cache and groups snapshot are unchanged.
  • Activity Logs is not changed. Its 500s at 17:51 UTC (also a Cosmos 400) stopped after a manual App Maintenance run at 17:52, consistent with its documented composite-index dependency, and that index is present on the live container.
  • Out-of-scope follow-up: the classic /admin/control-center "active users (30 days)" stat uses the same COUNT over DISTINCT pattern inside a try/except, so it likely shows 0.

Linked issue

N/A. There is no tracking issue; the cause was found in the live deployment's App Insights logs.

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only (0.261.291 -> 0.261.292; the base took 0.261.290 and 0.261.291 while this PR was open)
  • deployers/version.txt bumped, or not needed because deployers/ was not changed (deployers/ not changed)

Testing / validation

  • python -m pytest functional_tests/test_v2_control_center_dashboard.py functional_tests/test_v2_control_center_users.py functional_tests/test_v2_control_center_groups.py functional_tests/test_v2_control_center_foundation.py functional_tests/test_v2_control_center_cosmos_query_compatibility.py functional_tests/test_v2_control_center_public_workspaces.py functional_tests/test_v2_control_center_activity_logs_queries.py functional_tests/test_v2_control_center_activity_logs_routes.py ui_tests/test_v2_control_center_data_health_removed.py: 153 passed. This machine has Flask 2.2.5 rather than the pinned 3.1.3. The Flask 2.x test client reads werkzeug.__version__, so a local wrapper set it before pytest started.
  • Each new test fails on the pre-fix code. Against the previous route module, the compatibility scan reports 13 unsupported query sites across the dashboard summary and insights and the Users list and export. The dashboard and Users route tests fail, and the Groups inventory test rejects the old GROUP BY document count.
  • python -m pytest ui_tests/test_v2_control_center_data_health_removed.py ui_tests/test_v2_control_center_dashboard.py ui_tests/test_v2_control_center_users.py ui_tests/test_v2_control_center_groups.py ui_tests/test_v2_control_center_public_workspaces.py ui_tests/test_v2_control_center_activity_logs.py (local Chromium, after npm run build in application/v2_ui): 27 passed.
  • npm run typecheck and npm run build in application/v2_ui: passed.
  • python functional_tests/route_tests/test_route_blueprint_policy_inventory.py (12/12), python functional_tests/route_tests/test_route_unauthenticated_policy_contract.py (7/7) and python functional_tests/route_tests/test_route_policy_test_coverage.py (3/3): passed.
  • python scripts/check_broken_access_control.py --full-file application/single_app/route_backend_control_center.py application/single_app/functions_control_center_groups.py application/single_app/functions_activity_logging.py: passed.
  • python functional_tests/test_docs_site_quality.py (6/6) and python functional_tests/test_docs_app_surface_coverage.py (7/7): passed.
  • python functional_tests/test_docs_release_notes_integrity.py (0/1) and python functional_tests/test_docs_link_integrity.py (2/5): already failing on the parent commit, with the same failures. The generated release-notes pages were already missing 217 releases, and the same 11 relative links were already broken. This PR's 6 new links all resolve, and it does not regenerate the release-notes pages.
  • Broader regression check: 54 related functional test files (Control Center, activity logging, approvals, security hardening) had the same 57 failures and errors on this branch and on the parent commit. Examples include tests that need live Azure credentials, outdated imports and exact-version assertions. Passing tests went from 303 to 321.
  • After merging the base (V2: Fix left sidebar links opening the classic UI instead of V2 #1700 and Fix V2 Orchestrate Ask an agent steps refused before the agent runs #1701), the functional suites above plus functional_tests/test_v2_sidebar_primary_nav_stays_in_v2.py, functional_tests/test_orchestration_agent_document_type_fix.py, functional_tests/test_logging_tag_standardization.py and ui_tests/test_v2_control_center_data_health_removed.py: 189 passed, 1 failed. The failure is test_logging_tags_are_normalized_and_documented. It fails the same way on the base branch alone, and every tag it flags is in a workflow or editor-assist file this PR does not touch. npm run build passed after the first merge; the second merge changed no frontend files.
  • Not run: verification on the deployed site. After deployment, App Insights should show no 5xx responses on /api/v2/control-center/* and no [CONTROL_CENTER] ... failed events.

Documentation

  • Release notes updated, or not needed (v0.261.292: Bug Fixes and Breaking Changes)
  • Feature documentation updated, or not needed (V2_CONTROL_CENTER.md and docs/guides/v2-control-center.md)
  • Fix documentation updated, or not needed (new V2_CONTROL_CENTER_COSMOS_QUERY_COMPATIBILITY_FIX.md; update note in ACTIVITY_LOG_MIGRATION_PROMPT_FIX.md)

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()) (no new routes; two were removed)
  • Settings sent to non-admin frontends use sanitize_settings_for_user() (no settings payloads changed)
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS
  • No secrets, keys, connection strings, or local-only artifacts are included

Paul Lizer (paullizer) and others added 5 commits October 7, 2026 15:17
…ealth

Cosmos DB rejected the queries behind these sections with HTTP 400. The
azure-cosmos Python SDK cannot run cross-partition GROUP BY or COUNT over a
DISTINCT subquery, and the Users sort used a two-property ORDER BY with no
composite index on user_settings.

- Dashboard: count SELECT DISTINCT VALUE results, derive uploads by subtracting
  VALUE COUNTs, tally status values, and aggregate two streamed projections
  for insights. The login heatmap now totals each weekday and hour.
- Users: order one property at a time in recorded and missing populations;
  the export runs its first query before it starts streaming.
- Groups: the inventory aggregates streamed projections.
- Add a Cosmos query guard, route-level tests and an AST scan of every V2
  Control Center query.
- Remove the V2 Data health section and its now-unused migrate APIs.
- Version 0.261.290; feature doc, guide, fix doc and release notes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…lizer-control-center-v2-fixes

The base took 0.261.290 for the V2 sidebar links fix (#1700), so this change
moves to 0.261.291. The release notes keep both sections.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The merged base already uses 0.261.290 for the V2 sidebar links fix, so the
fix doc, feature doc, Data health removal note, test headers and version
assertions now name 0.261.291.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…lizer-control-center-v2-fixes

The base took 0.261.291 for the orchestrated Ask an agent fix (#1701), so
this change moves to 0.261.292. The release notes keep every section.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The merged base now uses 0.261.291 for the orchestrated Ask an agent fix, so
the fix doc, feature doc, Data health removal note, test headers and version
assertions now name 0.261.292.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 36f0af1 into paullizer-react-v2-ui Oct 7, 2026
11 checks passed
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
Brings in V2 at 36f0af1 (microsoft#1701, VERSION 0.261.291, and microsoft#1702,
VERSION 0.261.292).

Conflicts:
- application/single_app/config.py: V2's file byte-for-byte (VERSION
  0.261.292). This branch changes only that line.
- docs/explanation/release_notes.md: V2's file byte-for-byte, with this
  branch's own (v0.261.291) section inserted at the very top, above V2's
  first section, its (v0.261.292). Every V2 section is unchanged,
  including microsoft#1701's own (v0.261.291).

docs/admin/orchestration.md merged cleanly: microsoft#1701's notes and
troubleshooting rows and this branch's settings and hand-off pause rows
are separate hunks.

V2's other changes, to the Ask an agent step's access check, the V2
Control Center and their docs and tests, don't touch this branch's
files.

The next commit renumbers this branch's section and VERSION to
0.261.293, above V2's 0.261.292.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
V2 now uses 0.261.291 (microsoft#1701) and 0.261.292 (microsoft#1702), with their own
release notes sections, so this branch's version moves above them.
Renumbers the same 20 lines in 15 files as the previous bump: config.py,
this branch's release-notes section, the documentation version notes and
the new tests' headers. V2's own (v0.261.292) and (v0.261.291)
release-notes sections and microsoft#1701's 0.261.291 notes in orchestration.md
are untouched. The tests' version floor stays 0.261.253.

Refs microsoft#1549

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
microsoft#1702 merged into paullizer-react-v2-ui with 0.261.292, so this fix
takes 0.261.293. Adds the v0.261.293 release notes. The admin
troubleshooting row now links to the page's charts section, because the
site never publishes fix pages and the old link did not resolve.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
Brings in microsoft#1702 (V2 Control Center fixes, 0.261.292). VERSION keeps
0.261.293, and this fix's release notes stay above v0.261.292.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant