Skip to content

feat(mcp): apply native dashboard filters from an MCP client - #44096

Merged
aminghadersohi merged 27 commits into
apache:masterfrom
aminghadersohi:aminghadersohi/mcp-apply-dashboard-filters
Sep 18, 2026
Merged

aminghadersohi merged 27 commits into
apache:masterfrom
aminghadersohi:aminghadersohi/mcp-apply-dashboard-filters

Conversation

@aminghadersohi

@aminghadersohi aminghadersohi commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

SUMMARY

Why

An MCP client needs to apply a viewer's filter selections without redefining native filters or changing the saved dashboard for everyone. A permalink stores shareable view state using the existing authorized load path; a best-effort realtime notification can apply that state to an open dashboard without turning a transient selection into shared configuration.

What

Adds apply_dashboard_filters for existing exact-match select filters without inverse selection, and time filters, with name/ID targeting and an optional base permalink for stacking selections across requests. It returns a permalink and attempts a principal-scoped notification; an open dashboard resolves that permalink, applies its selections, and offers an Undo toast that stays up until it is acted on or dismissed. Saved dashboard configuration is unchanged.

Deployment requirements

The realtime half is inert unless WEBSOCKET_ENABLE is on with a coordination backend (DISTRIBUTED_COORDINATION_CONFIG), a running superset-websocket, and a strong, non-default WEBSOCKET_JWT_SECRET of at least 32 bytes. The MCP process and websocket transport must share REALTIME_CHANNEL_PREFIX, and the browser user needs can_read on Realtime. With the default configuration the tool still works and returns a permalink URL. live_update_pushed means publication succeeded, not that a browser received or applied the update. No Global Task Framework feature flag is required.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Live realtime + Undo browser validation completed at db84fe4897. The authenticated browser received the principal-scoped event, applied Country = France without a reload, refreshed the charts, displayed the Undo toast, and restored the prior unset filter state and chart totals when Undo was clicked. The full evidence and uncropped screenshots are in the validation comment.

Note on the screenshots: they predate 10196a117d, so they show the toast as it behaved then, on an eight-second auto-dismiss timer. Since that commit an actionable toast has no timer and stays up until Undo or its close button is used, and Undo restores only the entries whose current state still matches what was applied. Both behaviors are covered by unit tests (an actionable toast remains until it is explicitly dismissed, and the Undo snapshot test in useDashboardFilterSync.test.tsx); what the screenshots show of the applied and restored dashboard state is otherwise unchanged.

Applied live — Country = France and Undo toast visible

Sales Dashboard after MCP live update with Country France and Undo toast visible

After Undo — prior unset filter state and totals restored

Sales Dashboard after Undo restored the prior unset Country filter

TESTING INSTRUCTIONS

How to test

The core realtime + Undo path has been exercised in a browser as documented above. The broader edge-case steps below remain the manual validation runbook.

  1. Use an MCP-enabled instance and a dashboard with existing Region (select) and Time Range filters. As a user with dashboard read access, call:
    {"request":{"dashboard_id":42,"filters":[{"filter_name_or_id":"Region","values":["EMEA"]}]}}
    Substitute the actual dashboard ID and filter name. Open the returned dashboard_url; check the selection and chart queries. Verify the saved native-filter configuration and another user's view remain unchanged.
  2. Pass the response's permalink_key as base_permalink_key in a second call applying Time Range = 2024-01-01 : 2025-01-01. Check that Region persists. Replace Region, clear it with values: [], and omit the base key to start from dashboard defaults. Also validate required-filter behavior: clearing a required select must match no rows both live and after opening its permalink, even when a saved default exists. Non-exact matching modes and inverse-selection configurations must return an explicit unsupported-mode error.
  3. Try unknown/ambiguous names, duplicate targets, incorrect value types, an inaccessible dashboard, and invalid/expired/wrong-dashboard base permalinks. Confirm explicit errors without replacement links on base-resolution failures.
  4. With all realtime prerequisites above configured, keep the dashboard open under the same principal and repeat the call. Check chart/filter updates without reload and the “Filters applied from chat” toast. Click Undo and verify prior selections return; the toast has no auto-dismiss timer, so it waits for Undo or its close button. Edit one of the applied filters before clicking Undo and verify that edit survives while the untouched filters revert. Check navigation during resolution and rapid successive calls.
  5. Disconnect/reconnect the socket and confirm no stale state is replayed over manual selections or Undo. Disable websocket delivery and verify the returned permalink remains usable.

Automated checks:

PYTHONPATH="$PWD/superset-core/src:$PWD" pytest -q \
  tests/unit_tests/mcp_service/dashboard/tool/test_apply_dashboard_filters.py \
  tests/unit_tests/mcp_service/dashboard/test_permalink.py \
  tests/unit_tests/test_realtime_publish.py
PYTHONPATH="$PWD/superset-core/src:$PWD" pytest -q tests/unit_tests/tasks/test_manager.py
cd superset-frontend
npm run test -- src/dashboard/useDashboardFilterSync.test.tsx src/components/MessageToasts/Toast.test.tsx src/dataMask/reducer.test.ts

Validation: 86 focused backend/publisher tests, 41 existing TaskManager tests, and 51 frontend tests passed. At db84fe4897, the live websocket + browser flow also passed: MCP publication, no-reload filter/chart update, toast display, and Undo restoration. Base/PR translation extraction and comparison passed with no translation regressions. The full uvx pre-commit run --files <changed files> gate passed without bypassing any hooks, after formatting fixes and rebuilding stale local package declarations. No evaluation or performance run has happened; those results are pending.

ADDITIONAL INFORMATION

Risk & rollback

The shared realtime publisher can affect existing task notifications, while live updates and Undo can overwrite affected filters' in-memory selections. The toast action stores a callback in Redux state, so consumers expecting serializable toast metadata deserve attention. Permalink resolution remains behind the existing dashboard access checks. Delivery is best effort, with no reconnect replay. Roll back by reverting this PR; no database migration or saved filter-configuration changes need reversal. Disabling websocket delivery stops live application but also affects other realtime consumers; permalink creation remains available.

Follow-up validation

The pre-existing failure in tests/unit_tests/mcp_service/test_mcp_e2e_smoke.py::test_tools_call_health_check_over_real_asgi_transport is excluded from this change and needs separate investigation. Evaluation/performance measurements and the broader manual edge-case runbook remain pending; the core live browser flow and screenshots are complete as noted above.

The pre-existing required-filter hydration logic treats a complete NULL-only select value ([null]) as empty and can restore a saved default. Correcting that shared hydration behavior is deferred to a separate change.

Review follow-up

  • Shared the explicit-clear SQL predicate across frontend producer/hydration sites with a matching backend constant.
  • Documented the intentionally non-serializable toast action.
  • Guarded malformed permalink adhoc filters and added hydration regression cases.
  • Used deployment-aware permalink URL generation, with public-origin and mount-prefix tests and documentation.
  • Protected concurrent realtime channel initialization while retaining the fixed-channel subscription contract.
  • Synchronized the seven flagged Chinese translations with their confirmed upstream corrections.

Review guidance

The riskiest hunk is the extraction of TaskManager._publish_realtime into superset/realtime/publish.py: it is shared surface and deserves the most scrutiny, especially callable channel-prefix resolution, envelope compatibility, routing, and no-backend behavior. Also review the optional ToastMeta.action field as an additive change to a widely imported primitive. Check raw base-permalink merging and access enforcement, plus the frontend's in-flight request ordering, unmount cleanup, and Undo snapshot handling.

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@github-actions github-actions Bot added the doc Namespace | Anything related to documentation label Sep 9, 2026
@netlify

netlify Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit c6adc8b
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6aabd70bcd758700085ef9fb
😎 Deploy Preview https://deploy-preview-44096--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov

codecov Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.52997% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.44%. Comparing base (2ef8e0c) to head (c6adc8b).

Files with missing lines Patch % Lines
..._service/dashboard/tool/apply_dashboard_filters.py 92.56% 9 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #44096      +/-   ##
==========================================
+ Coverage   80.39%   80.44%   +0.04%     
==========================================
  Files        2932     2935       +3     
  Lines      174525   174821     +296     
  Branches    40548    40606      +58     
==========================================
+ Hits       140317   140639     +322     
+ Misses      31538    31513      -25     
+ Partials     2670     2669       -1     
Flag Coverage Δ
hive 37.15% <33.46%> (-0.01%) ⬇️
javascript 75.89% <100.00%> (+0.04%) ⬆️
mysql 56.54% <33.46%> (-0.06%) ⬇️
postgres 56.56% <33.46%> (-0.06%) ⬇️
presto 39.21% <33.46%> (-0.02%) ⬇️
python 84.80% <95.51%> (+0.04%) ⬆️
sqlite 56.25% <33.46%> (-0.06%) ⬇️
unit 76.43% <95.51%> (+0.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gabotorresruiz gabotorresruiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a careful pass, focused on the write-path security posture since this is a mutating tool. It holds up well:

  • Read gate is the correct entitlement. The tool creates a caller-scoped permalink plus a principal-scoped realtime nudge; it never mutates saved dashboard config, so method_permission_name="read" + class_permission_name="Dashboard" is right, and readOnlyHint=False correctly lands it in the cache excluded_tools list. Per-object access is enforced via DashboardDAO.get_by_id_or_slug.
  • Embedded guests are default-denied (not in MCP_GUEST_ALLOWED_TOOLS; the auth.py guest gate is default-deny even with RBAC off).
  • No injection surface. The IN-predicate column is server-derived from the dashboard's own filter config, values are parameterized scalars placed exactly as the UI does, and time_range goes through validate_time_range. The 1 = 0 clear predicate is a hardcoded constant.
  • Base-permalink stacking resolves under the caller's access and rejects a base key that does not belong to the target dashboard, so no cross-dashboard or cross-principal state injection; the raw base mask is merged server-side and not returned.

Three small non-blocking items:

  1. NIT — the 1 = 0 clear predicate is spelled out independently in three places across two languages (getSelectExtraFormData in filters/utils.ts, the backend _select_data_mask, and reducer.ts). If any one drifts (1=0, a different match-nothing predicate), a cleared required filter would silently restore its saved default and nothing in the current tests would catch it. A shared exported constant, or at least a comment cross-linking the three sites, would harden this coupling.

  2. Question (the realtime/publish.py hunk you flagged) — the resolved channel is memoized on app.extensions["realtime_channel"], so a callable REALTIME_CHANNEL_PREFIX is resolved exactly once per process and every later publisher, including this MCP path, reuses that first value. Stable and correct for the default empty prefix. Is once-and-cached the intended contract for the MCP publisher too, in a deployment where the prefix is a callable that could resolve differently by context, or should its channel be resolved per-call?

  3. NIT (you flagged this yourself) — action.onClick in MessageToasts/types.ts stores a function in Redux state. I checked: messageToasts is not persisted and serializableCheck is off in the default prod middleware, so the practical fallout is limited to DevTools time-travel and the opt-in dev warning. A one-line comment noting the field is deliberately non-serializable would save the next person a double-take.

Everything I could verify statically and via the extracted publisher tests looks correct, and CI is fully green. The one thing I could not exercise is the live realtime + Undo flow, which is inert without a websocket-enabled stack and is the piece you marked pending. I would love to see those screenshots before this merges; otherwise this is clean, careful work.

@aminghadersohi
aminghadersohi marked this pull request as ready for review September 10, 2026 03:49
@aminghadersohi
aminghadersohi marked this pull request as draft September 10, 2026 03:51
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

@gabotorresruiz Thanks for the careful review! Addressed the two nits and investigated the channel contract:

  1. Clear predicate: added EMPTY_FILTER_SQL_EXPRESSION in the frontend shared constants and in superset/constants.py, with cross-language synchronization comments. Both getSelectExtraFormData and data-mask hydration use the frontend constant; _select_data_mask uses the backend constant. Expanded the hydration regression test to exercise the actual UI-generated mask as well as the literal permalink wire representation, for both null and [] cleared values. The frontend producer and backend tool tests retain literal 1 = 0 expectations, so changing either side's emitted predicate independently fails tests rather than silently restoring a saved default.

  2. Callable channel prefix: once-and-cached is intended for the MCP publisher too; no behavior change made. I checked TaskManager.init_app / get_realtime_channel, the configuration contract, and the websocket subscription. REALTIME_CHANNEL_PREFIX is a deployment namespace, documented as resolved once at startup. The websocket server constructs one REALTIME_CHANNEL from its configured prefix and subscribes to that fixed channel. Resolving a context-dependent prefix per MCP call could publish to a different channel with no matching subscriber, breaking that invariant rather than making delivery safer. Strictly, the neutral helper caches per Flask app instance in app.extensions, not a global shared across processes; each producer must resolve the same stable deployment prefix as the websocket server. Context-varying prefixes are not supported by this single-channel architecture. Recipient targeting belongs in the envelope's principal/tab routes, not in a dynamically selected deployment channel. Existing callable-once and task/non-task channel-sharing tests pass.

  3. Toast callback: added a one-line comment documenting that the transient, non-persisted toast callback is deliberately non-serializable.

Screenshots remain outstanding. This environment does not have a running websocket-enabled stack (the local Superset health endpoint is unavailable), so I cannot exercise or capture the live realtime + Undo flow. The unit tests are not a substitute for that live validation, which is still needed before merge.

Local validation: 43 frontend tests and 50 backend/publisher tests passed.
uvx pre-commit run --files <all PR-changed files> passed, including mypy and frontend type checking. Changes pushed in c6c5ac4. CI for the new head has started and is pending; its final result is not yet known. The PR remains in draft.

Comment thread superset-frontend/src/dataMask/reducer.ts Outdated
Comment thread superset/mcp_service/dashboard/permalink.py Outdated
@bito-code-review

Copy link
Copy Markdown
Contributor

The issue described is a potential runtime error in the dashboard hydration process where adhoc_filters might be malformed (non-array or null). Since the requested file superset-frontend/src/dataMask/reducer.ts is not present in the provided PR diff, I cannot verify the code or implement a fix directly. Please ensure the file is included in the PR or provide the relevant code snippet for me to analyze and resolve.

Comment thread superset/realtime/publish.py Outdated
@aminghadersohi
aminghadersohi marked this pull request as ready for review September 10, 2026 15:33
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Translation Regression Detected

A source change in this PR renamed or reworded strings, invalidating existing translations (they are now #, fuzzy) in zh. Please resolve the affected .po files before merging.

Note: neither intentionally deleting a translatable string nor filling a previously-untranslated entry with a fuzzy guess (e.g. an AI backfill) is a regression — only a confirmed translation that a renamed/reworded source string turned fuzzy is flagged here.

Language Invalidated translations
zh 7

How to fix

1. Install dependencies (if not already set up):

pip install -r superset/translations/requirements.txt
sudo apt-get install gettext   # or: brew install gettext

2. Re-extract strings and sync .po files:

./scripts/translations/babel_update.sh

This rewrites superset/translations/messages.pot from the current source files and merges the changes into every .po file. Strings whose msgid changed will be marked #, fuzzy.

3. Resolve the fuzzy entries in the affected language files (zh):

grep -n '#, fuzzy' superset/translations/<lang>/LC_MESSAGES/messages.po

For each fuzzy entry, either rewrite the msgstr to match the new string and remove the #, fuzzy line, or clear the msgstr to "" if you cannot provide a translation.

4. Commit your changes to the .po files.

@aminghadersohi
aminghadersohi marked this pull request as draft September 10, 2026 15:45
@aminghadersohi
aminghadersohi marked this pull request as ready for review September 10, 2026 15:48
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

Follow-up covering every review item, including the three inline comments added after the earlier reply:

  • Malformed permalink hydration: guard adhoc_filters with Array.isArray and tolerate null/undefined entries. Added eight malformed-input regression cases verifying that a required select filter restores its default instead of throwing.
  • Permalink deployment URLs: use Superset's existing get_url_path("Superset.dashboard_permalink", user_friendly=True, key=...) rather than the MCP helper's hardcoded localhost fallback. Tests cover the configured public origin, root and subdirectory deployments, request and non-request contexts, and proxy SCRIPT_NAME. Documented the public URL and mount-prefix configuration.
  • Concurrent channel initialization: serialize cache initialization and recheck the app cache inside the lock. A deterministic two-thread regression test forces simultaneous initial cache misses and asserts that the callable runs exactly once and both callers receive the same channel. This preserves the once-per-app contract explained above; per-publish context-dependent deployment channels would still violate the websocket consumer's fixed subscription.
  • Shared clear predicate and toast callback: both earlier nits remain addressed by the shared frontend/backend constants, hydration coverage, and explicit non-serializability comment.
  • Translation CI: synchronized only the seven flagged Simplified Chinese entries with the confirmed corrections already on upstream master. Ran extraction/update for both the base and PR source and the translation regression comparison: no translation regressions.

Local validation: 86 focused backend/publisher tests, 41 TaskManager tests, and 51 frontend tests passed. The full PR-changed-file pre-commit gate also passed.

Live realtime + Undo screenshots are still outstanding: there is no running websocket-enabled stack in this environment, so neither screenshots nor live browser verification are claimed. This remains a pre-merge validation item, not something unit tests can replace.

@aminghadersohi
aminghadersohi marked this pull request as draft September 10, 2026 15:52
@github-actions github-actions Bot added i18n Namespace | Anything related to localization i18n:chinese Translation related to Chinese language labels Sep 10, 2026
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

CI follow-up: both Python unit-job attempts passed all 15,139 main tests, but exhausted the 30-minute job timeout during coverage processing. The first attempt also passed all 1,717 SQL coverage tests before cancellation. In 83d7a11, increased only that job budget to 45 minutes so the full suite, coverage finalization, and scoped coverage gates can finish. No tests, coverage thresholds, or required checks were removed or bypassed. The full PR-changed-file pre-commit gate passed again. Monitoring the new-head CI run to completion.

@github-actions github-actions Bot added the github_actions Pull requests that update GitHub Actions code label Sep 10, 2026
@aminghadersohi
aminghadersohi marked this pull request as ready for review September 10, 2026 17:33
@bito-code-review

bito-code-review Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6a3dfc

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: ffcfc7a..534427e
    • tests/unit_tests/mcp_service/dashboard/test_permalink.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/mcp_service/dashboard/tool/apply_dashboard_filters.py
Comment thread superset-frontend/src/dashboard/useDashboardFilterSync.ts
Comment thread superset-frontend/src/components/MessageToasts/Toast.tsx
@gabotorresruiz

Copy link
Copy Markdown
Contributor

Thanks @aminghadersohi for closing the loop on the live realtime + Undo validation, the screenshots and sequence in the validation comment are exactly what I was asking for. I also re-verified the delta since db84fe4897 empirically: the rebase and master merges are content neutral (same file set, line for line), and the three review response fixes for Joe's comments check out. The backend suites pass at the reviewed head (87 tests), test_required_time_range_cannot_be_cleared correctly fails on the pre fix code, and the two new Undo tests fail pre fix as well, so they genuinely pin the fixes.

Two small things before I approve:

  • The PR body still describes the eight second auto dismissing Undo toast in the SUMMARY, testing step 4, and the risk section; since actionable toasts now persist until dismissed, could you refresh those lines so the description matches the shipped behavior?
  • One test nit inline on Toast.test.tsx.

CI wise you are already unblocked: your latest master merge picked up the alembic heads fix from #44288, and the required checks are re running now. The one shard that failed so far (ReportModal.test.tsx in jest shard 7) looks unrelated to this change. Once the run is green and the body is refreshed, this is ready for my approval.

Comment thread superset-frontend/src/components/MessageToasts/Toast.test.tsx
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

Done — all reviewer feedback has been addressed, the PR branch is updated with current Apache master, and CI is green.

@bito-code-review

bito-code-review Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #90b4fd

Actionable Suggestions - 0
Additional Suggestions - 2
  • superset-frontend/src/components/MessageToasts/Toast.test.tsx - 1
    • Redundant timer advance · Line 158-158
      This toast has an `action`, so `Toast.tsx` (lines 103-105) never schedules the auto-dismiss timer (`!toast.action && toast.duration > 0`). Advancing timers by 200ms after already advancing 1000ms is a no-op and adds no coverage; it may mislead readers into thinking the toast auto-dismisses after some elapsed time. Consider removing it.
  • superset-frontend/src/components/MessageToasts/Toast.tsx - 1
    • Missing effect dependency · Line 103-103
      The effect body now reads `toast.action` (line 103), but the dependency array `[handleClosePress, toast.duration]` omits it. This triggers the repo's `react-hooks/exhaustive-deps` warning (oxlint.json:184) and leaves a stale-closure risk if the action changes during the toast's lifetime. Add `toast.action` to the deps.
Review Details
  • Files reviewed - 6 · Commit Range: 534427e..4370ed7
    • superset-frontend/src/components/MessageToasts/Toast.test.tsx
    • superset-frontend/src/components/MessageToasts/Toast.tsx
    • superset-frontend/src/dashboard/useDashboardFilterSync.test.tsx
    • superset-frontend/src/dashboard/useDashboardFilterSync.ts
    • superset/mcp_service/dashboard/tool/apply_dashboard_filters.py
    • tests/unit_tests/mcp_service/dashboard/tool/test_apply_dashboard_filters.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/mcp_service/dashboard/tool/apply_dashboard_filters.py Outdated
Comment thread superset/mcp_service/dashboard/tool/apply_dashboard_filters.py
Comment thread docs/admin_docs/configuration/mcp-server.mdx
aminghadersohi and others added 2 commits September 16, 2026 12:07
Address review on apply_dashboard_filters:

- Drop inherited data mask entries for filters the dashboard no longer
  defines, so a deleted or recreated filter cannot carry a stale column
  predicate into a live update that falls back to every chart.
- Reject more than one value for a single-select filter, which the
  dashboard control cannot render without rewriting the selection.
- Document the browser-reachable WEBSOCKET_URL prerequisite for live
  updates, whose loopback default silently never connects remotely.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ghadersohi/mcp-apply-dashboard-filters

# Conflicts:
#	.github/workflows/superset-python-unittest.yml
@github-actions github-actions Bot removed the github_actions Pull requests that update GitHub Actions code label Sep 16, 2026
The metadata inventory test that landed on master asserts the registered
tool set exactly matches its hand-maintained lists, so this branch's new
tool has to be declared there: an output field for the schema assertion
and MUTATING_TOOLS membership to match its readOnlyHint=False annotation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bito-code-review

bito-code-review Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #f049a0

Actionable Suggestions - 0
Review Details
  • Files reviewed - 4 · Commit Range: 4370ed7..a24ea52
    • docs/admin_docs/configuration/mcp-server.mdx
    • superset/mcp_service/dashboard/tool/apply_dashboard_filters.py
    • tests/unit_tests/mcp_service/dashboard/tool/test_apply_dashboard_filters.py
    • tests/unit_tests/mcp_service/test_mcp_tool_registration.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@gabotorresruiz gabotorresruiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed on a24ea52161. Everything I held on last time is addressed, and I checked it by execution rather than by reading the replies:

  • The amended Toast regression test really pins the behavior now. I reverted only the !toast.action guard in Toast.tsx on this branch: an actionable toast remains until it is explicitly dismissed fails, and passes again once the guard is restored.
  • test_single_select_rejects_multiple_values and test_inherited_mask_drops_filters_the_dashboard_no_longer_has both fail when I restore apply_dashboard_filters.py from df68ef0d85^, and pass at head, so they are real regression tests.
  • Full runs on this branch: 149 backend tests across test_apply_dashboard_filters.py, test_permalink.py, test_realtime_publish.py, test_manager.py and test_mcp_tool_registration.py, plus 41 frontend tests across Toast.test.tsx, useDashboardFilterSync.test.tsx and reducer.test.ts. All green, and CI is green on the head SHA.
  • The TaskManager refactor round trips: get_realtime_channel(app).removesuffix("realtime") reproduces the old prefix, so the channel and envelope are unchanged for the existing publishers.

Two small NITs inline, neither blocking.

One ask, also not blocking: the live browser validation is at db84fe4897, which predates 10196a117d. That commit made actionable toasts persistent and made Undo restore only the entries that still match the applied snapshot, so those screenshots show the old eight second toast rather than what ships here. The unit coverage for both changes is solid, so this is only about closing the loop: if it is cheap, a quick re-run of just the Undo flow at head would do it.

LGTM otherwise. Nice, careful work.

Comment thread superset/constants.py
Comment thread docs/admin_docs/configuration/mcp-server.mdx Outdated
aminghadersohi and others added 2 commits September 17, 2026 11:58
Address review on the dashboard filter PR:

- security/manager.py kept its own "1 = 0" literal as the guest-token
  allow-list for extras.where. It now aliases EMPTY_FILTER_SQL_EXPRESSION,
  the constant the frontend producer it cites already reads, so changing
  the predicate cannot leave the allow-list behind and start rejecting
  embedded charts whose required Select filter has no value selected.
- Add guest-token coverage for that coupling, written against the
  constant rather than its literal value.
- Drop the inert duration override on the Undo toast and correct the docs:
  an actionable toast has no auto-dismiss timer and stays up until it is
  acted on or closed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

On the non-blocking ask about the screenshots: you're right that db84fe4897 predates 10196a117d, so what they show is the old eight-second toast.

I could not re-run the live flow at head — this worktree has no running Superset or superset-websocket (localhost:8088 and localhost:8080 both refuse connections), and standing up the full realtime stack is more than the "if it is cheap" bar you set. Rather than leave the gap implicit, I've annotated it in the PR body: the screenshots are labelled as predating that commit, with the two behaviors that changed since spelled out, and a note that what they show of the applied and restored dashboard state is otherwise unchanged.

The behavior changes themselves are covered by the unit tests you already exercised — an actionable toast remains until it is explicitly dismissed, and the Undo snapshot test that edits a filter after the notification and checks the edit survives while the untouched filter reverts. I've also added that edit-then-Undo case to the manual runbook in the testing instructions, so whoever next runs the live pass covers it.

@bito-code-review

bito-code-review Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #57673d

Actionable Suggestions - 0
Review Details
  • Files reviewed - 4 · Commit Range: a24ea52..c6adc8b
    • docs/admin_docs/configuration/mcp-server.mdx
    • superset-frontend/src/dashboard/useDashboardFilterSync.ts
    • superset/security/manager.py
    • tests/unit_tests/security/test_guest_token_empty_filter.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@aminghadersohi
aminghadersohi merged commit fc80a14 into apache:master Sep 18, 2026
85 checks passed
villebro added a commit that referenced this pull request Sep 22, 2026
…n 7.0

apply_dashboard_filters (#44096) was never backported to 7.0, but the
cherry-pick of #44386's COMMITTED_WRITE_SPECS snapshot brought in a
stale entry for it, failing
test_committed_write_specs_cover_every_committing_mutating_tool's
set-equality assertion against MUTATING_TOOLS.
villebro added a commit that referenced this pull request Sep 30, 2026
apply_dashboard_filters (#44096) and get_dashboard_data (#44113) were
never backported to 7.0, but the cherry-pick of #44575's tool inventory
test brought in budget entries for them, failing
test_inventory_budgets_cover_every_registered_tool's set-equality
assertion against the registered tools.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc Namespace | Anything related to documentation size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants