Compare commits

...
Author SHA1 Message Date
Elizabeth ThompsonandClaude Opus 4.8 45b643a686 fix(chart/data): handle QueryObjectValidationError in _get_data_response
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-12 23:39:43 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8bd25b3fed chore(deps-dev): bump the typescript-eslint group across 1 directory with 2 updates (#43038)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 16:28:52 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>rusackasClaude Opus 4.8
0a2cfb9fba chore(deps-dev): bump oxfmt from 0.61.0 to 0.62.0 in /superset-frontend (#43046)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 16:28:48 -07:00
5248367587 fix: verify database access before dataset repointing, and tab ownership before tab-state updates (#42936)
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 16:07:58 -07:00
bdf8ce69ab feat(Reports&Alerts): remove Selenium support, require Playwright (#43028)
Co-authored-by: madhushree agarwal <madhushree_agarwal@apple.com>
2026-08-11 16:06:26 -07:00
Dang DaoandGitHub d91ca50872 perf(charts): reuse datasource in query context (#42476) 2026-08-11 14:31:47 -07:00
f6077eeaa1 fix(dataset): validate stored column and metric expressions at query time (#42087)
Signed-off-by: sha174n <shaitan@zx48.net>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-11 21:48:26 +01:00
0d57c5ab50 fix(dashboard): consistently apply the datasource-access check when serializing member charts and datasets (#42716)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 21:47:47 +01:00
edf30c7019 chore: add logging event for drill to detail (#42563)
Co-authored-by: Ayush Kumar Sharaf <ayush.sharaf@314ecorp.com>
2026-08-11 13:47:00 -07:00
3ded398a1f fix(chart): dataset dropdown sorted by name (#42475)
Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
2026-08-11 13:45:48 -07:00
63a81c2125 fix(dashboard): remeasure chart description height after markdown render (#41536)
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 13:44:48 -07:00
af258c21d0 fix(mixed-chart): Mixed chart secondary yaxis title position misplaced fix (#42713)
Co-authored-by: Mallikarjuna Reddy N <MallikarjunaReddy.Nimmakayala@gevernova.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 13:13:34 -07:00
9086bab2c2 ci(e2e): stop gunicorn worker recycling mid-run; slow-test budget for mixed-chart filter spec (#42867)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 12:43:51 -07:00
4c5a3356f3 fix(dashboard): redirect using sanitized slug from save response (#42853)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: rusackas <evan@rusackas.com>
2026-08-11 12:43:24 -07:00
998c408686 fix(rls): return a descriptive error for duplicate rule names (#42819)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: rusackas <evan@rusackas.com>
2026-08-11 12:41:24 -07:00
Joe LiandGitHub a3d58d1211 fix(ci): use current actions for Docker refresh (#42482) 2026-08-11 12:04:09 -07:00
7b32b870e1 chore: Fix/remove hardcode of admin role (#27779)
Co-authored-by: Evan <evan@preset.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Joe Li <joe@preset.io>
Co-authored-by: rusackas <evan@rusackas.com>
2026-08-11 10:26:50 -07:00
3cd4150539 chore(deps): bump sqlglot from 30.15.0 to 30.16.0 (#43029)
Co-authored-by: Superset Dev <dev@superset.apache.org>
2026-08-11 10:16:44 -07:00
2feb6c2bb5 refactor(deletion-retention): add declarative purge policies (#42888)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 09:55:36 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5767c3981d chore(deps): bump the storybook group across 1 directory with 2 updates (#43037)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 09:48:45 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ec6b2d2347 chore(deps-dev): bump oxfmt from 0.61.0 to 0.62.0 in /superset-websocket (#43033)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 09:48:42 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
aade32cad8 chore(deps-dev): bump the typescript-eslint group across 1 directory with 3 updates (#43039)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 09:48:38 -07:00
d6771e96d2 fix(core): let UnsavedChangesModal use Ant Design's automatic z-index stacking (#42548)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 09:42:49 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
305638e98c chore(deps-dev): bump baseline-browser-mapping from 2.11.11 to 2.11.12 in /superset-frontend (#43048)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 09:42:16 -07:00
5099b6ffa9 fix(export): derive chart_hashes and zip from a single chart list (#42946)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 09:35:59 -07:00
bc436bacad chore(security): warn when legacy encryption engine is configured (#42937)
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
2026-08-11 09:35:46 -07:00
e31a894be6 fix(common): remove unsupported cross join mode from left_join_df (#43016)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-11 09:35:16 -07:00
553808daa3 fix(reports): make webhook notification request timeout configurable (#43018)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-11 09:35:01 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
544756a631 chore(deps): bump github/codeql-action/analyze from 4.37.5 to 4.37.6 (#43040)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 09:34:49 -07:00
c4e8a9da90 test(explore): add end-to-end regression test for DatasourcePanel through the real AutoSizer + react-window List pipeline (#43023)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-11 09:34:06 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
47adbe31d5 chore(deps-dev): bump typescript-eslint from 8.65.0 to 8.66.0 in /superset-websocket (#43034)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:43:16 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
64165fbdae chore(deps-dev): bump @typescript-eslint/parser from 8.65.0 to 8.66.0 in /superset-websocket (#43035)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:43:12 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
581fb876e4 chore(deps-dev): bump oxfmt from 0.61.0 to 0.62.0 in /docs (#43042)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:43:09 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
29e8e396ee chore(deps-dev): bump the storybook group in /superset-frontend with 5 updates (#43045)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:43:05 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8bbf0cfc20 chore(deps-dev): bump oxlint from 1.76.0 to 1.77.0 in /superset-frontend (#43049)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:43:01 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
497c73e837 chore(deps): bump github/codeql-action/init from 4.37.5 to 4.37.6 (#43044)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:42:53 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a5a6f5a5b1 chore(deps): bump ws from 8.21.1 to 8.21.2 in /superset-websocket (#43036)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:42:50 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
156a59a190 chore(deps): bump swagger-ui-react from 5.32.11 to 5.32.12 in /docs (#43041)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:42:46 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
590003cbee chore(deps): bump baseline-browser-mapping from 2.11.11 to 2.11.12 in /docs (#43043)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:42:43 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
579011dea9 chore(deps): bump nanoid from 6.0.0 to 6.0.1 in /superset-frontend (#43050)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:42:39 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
65d808a5fe chore(deps): bump markdown-to-jsx from 9.10.1 to 9.10.2 in /superset-frontend (#43052)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-11 06:42:34 -07:00
5ee279363c fix(mcp): reject list values for ne on relationship filters (#42944)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-11 00:42:13 -07:00
34b2d3a533 fix(rls): match null-schema datasets in predicate lookup (#41426)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 19:58:51 -07:00
7157b752ee fix(pie): apply percentage number format to labels (#42880)
Co-authored-by: Joe Li <joe@preset.io>
2026-08-10 19:36:03 -07:00
d84a00f3c6 feat(dashboard): handle empty chart query context in Excel export (#42284)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Elizabeth Thompson <eschutho@gmail.com>
2026-08-10 21:12:08 -04:00
bfa1e775c4 fix(theming): guard ensureStaticPrefix against null/undefined input (#43019)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 17:41:33 -07:00
265269018e fix(mcp): require issuer-aware resolver for multi-issuer JWT, fix sanitizer input ordering (#42935)
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:56:46 -07:00
5f204a9af2 fix(frontend): remove any type and duplicate route in routes.tsx (#43014)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:51:58 -07:00
0c09cf087d fix(reports): translate execute-now success message (#43012)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:51:05 -07:00
651f75b1e8 docs(dashboard): document native filters on semantic views (#43011)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:50:34 -07:00
e48512568d docs(dashboard): document the expand_all_slices metadata flag (#43010)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:50:03 -07:00
4d0eeb7d86 docs: document FAB_API_SWAGGER_UI_SUPERSET_APP_ROOT config flag (#43009)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 15:49:47 -07:00
Elizabeth ThompsonandGitHub fdfc49461f fix(sqllab): wrap process_template() in format_sql to prevent raw UndefinedError leak (#42917) 2026-08-10 15:02:10 -07:00
2eb1e04283 fix: hydrate JWT user before list API filters (#39946)
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-08-10 14:18:28 -07:00
bc85f1eacf fix(database): resolve default schema when file upload schema is empty (#42603)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 13:56:47 -07:00
Gabriel Torres RuizandGitHub 0dedc55f38 fix(dashboard): changing a theme no longer discards unsaved edits or reloads charts 2026-08-10 16:52:43 -03:00
178d9c4ceb fix(explore): stacked Timeseries Bar total excludes the sort-only metric (#42881)
Co-authored-by: Joe Li <joe@preset.io>
2026-08-10 12:40:18 -07:00
Luc VerdierandGitHub 347774f9b8 fix(explore): stop the viz switcher from overflowing the control panel (#42911) 2026-08-10 12:36:23 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
776f70bf63 chore(deps): bump ioredis from 5.11.1 to 6.0.0 in /superset-websocket (#42959)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 12:35:56 -07:00
572f86c3c3 fix(deckgl): normalize legend swatch alpha channel to 0-1 for CSS rgba() (#42942)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-10 12:35:24 -07:00
Sepuri Sai KrishnaandGitHub 50c811280e fix(lru-cache): don't evict another entry when overwriting an existing key (#42409) 2026-08-10 12:29:20 -07:00
BandarandGitHub 9d6832c927 feat(formatting): add network throughput number formats for bits/s and bytes/s (#42437) 2026-08-10 12:29:05 -07:00
b6504eb111 fix(sql): resolve schema/catalog-qualified table references in CTE detection (#42717)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-10 12:28:31 -07:00
d62a9eeda6 fix(calendar): clean up d3-tip tooltips (#41589)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 12:28:06 -07:00
651c046e69 fix(deckgl): remove visibility condition in deckgl fill color (#42712)
Co-authored-by: Damian Pendrak <dpendrak@gmail.com>
2026-08-10 20:58:44 +02:00
Joe LiandGitHub d9ae0ec2fc fix(deckgl): hide legend when Legend Position is None (#42402) 2026-08-10 11:24:35 -07:00
varadendrasimha511andGitHub b98e157104 fix(sqla): preserve float precision when mixing int/float values in IN filters (#42752) 2026-08-10 11:12:43 -07:00
4defdbabd2 fix(dashboard): force-render virtualized charts before client-side export (#42561)
Signed-off-by: Jenwit Amonpongitsara <jenwit.amonpongitsara@agoda.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: rusackas <evan@rusackas.com>
2026-08-10 10:57:21 -07:00
7dc2afd377 docs(cache): document native filter option cache warm-up strategy (#42953)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-10 10:28:36 -07:00
5bcd9cd078 docs(exploring-data): document CSV/XLSX download in drill modals (#42952)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 10:28:14 -07:00
341ca94ba2 docs(security): document the read-only Subject REST API (#42951)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 10:27:54 -07:00
4b68da82a7 docs: document number format presets, including distance/length units (#42950)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 10:27:22 -07:00
a9eab4a0df docs: document color picker for conditional formatting rule colors (#42948)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 10:26:37 -07:00
f60370b695 docs: document CACHE_REDIS_SOCKET_TIMEOUT/CONNECT_TIMEOUT config keys (#42947)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-10 10:26:18 -07:00
c02dc7780b docs(mcp): add update_dashboard to write-tools enumeration (#42943)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 10:25:03 -07:00
Mehmet Salih YavuzandGitHub daf1718b44 fix(embedded): redact database errors in API responses to guest users (#42796) 2026-08-10 18:45:20 +03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b815640b8f chore(deps): bump actions/setup-java from 5.6.0 to 5.7.0 (#42968)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 07:54:41 -07:00
Antonio RiveroandGitHub 9e2cb69a39 feat(database): identify configured database connection errors (#42996) 2026-08-10 14:14:42 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
db88abe0bb chore(deps-dev): bump globals from 17.8.0 to 17.9.0 in /superset-websocket (#42958)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 04:53:29 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f53f634f23 chore(deps): bump antd from 6.5.2 to 6.5.3 in /docs (#42961)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 04:53:13 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
916c50284b chore(deps): bump github/codeql-action/analyze from 4.37.3 to 4.37.5 (#42965)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 11:39:14 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6a2e20cdb7 chore(deps): bump zizmorcore/zizmor-action from 0.6.1 to 0.6.2 (#42960)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:29:49 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9719c7de24 chore(deps-dev): bump globals from 17.8.0 to 17.9.0 in /docs (#42962)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:29:09 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
346dbd6a98 chore(deps): bump js-yaml from 5.2.2 to 5.2.3 in /docs (#42963)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:29 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
73478c5274 chore(deps): bump baseline-browser-mapping from 2.11.8 to 2.11.11 in /docs (#42964)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:25 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d7edf610a9 chore(deps-dev): bump @babel/types from 7.29.7 to 7.29.8 in /superset-frontend in the babel group (#42966)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:20 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e12818897d chore(deps): bump github/codeql-action/init from 4.37.3 to 4.37.5 (#42967)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:16 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d41032b70a chore(deps): bump Kesin11/actions-timeline from 3.1.1 to 3.2.0 (#42969)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:10 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
10cf2e20f9 chore(deps-dev): bump eslint-plugin-jest-dom from 5.7.0 to 5.10.1 in /superset-frontend (#42970)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:05 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2be726ddad chore(deps-dev): bump tsx from 4.23.1 to 4.23.5 in /superset-frontend (#42971)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:28:02 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ee5fb095da chore(deps-dev): bump baseline-browser-mapping from 2.11.8 to 2.11.11 in /superset-frontend (#42972)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:27:58 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4c9bd69eb4 chore(deps): bump antd from 6.5.2 to 6.5.3 in /superset-frontend (#42973)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:27:55 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7cd6c74757 chore(deps-dev): bump @types/lodash from 4.17.24 to 4.17.25 in /superset-frontend (#42974)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 01:27:51 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
3539c41dab chore(deps): bump cryptography from 49.0.0 to 50.0.0 (#42906)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-09 23:42:10 -07:00
c09d5bf6a9 fix(helm): add missing task modules to default CeleryConfig imports (#42945)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-08-09 22:06:45 -07:00
Đỗ Trọng HảiandGitHub f8925cc726 feat(build): reinstate no-restricted-imports lint rule for lodash (#42940) 2026-08-10 09:28:41 +07:00
Jetha ChanGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
fea84e81ef fix(tech-debt): measure oxlint metrics against the project's ruleset (#42955)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-10 09:26:15 +07:00
Amin GhadersohiandGitHub b413060030 chore(deps): restore redis floor to >=5.0.0 (#42915) 2026-08-09 17:41:54 -07:00
3b164e4270 fix(ci): remove extraneous plugins build job (#42677)
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-08 17:27:51 -07:00
bf294cfa43 perf(dashboard): avoid query context N+1 queries (#42474)
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-08-08 17:27:04 -07:00
42e4030104 feat(security): add guest user attributes and get_guest_user_attribute() macro (#33924)
Co-authored-by: Yash Janoria <yash.janoria@314ecorp.com>
Co-authored-by: Evan <evan@preset.io>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Evan Rusackas <evan@rusackas.com>
2026-08-08 16:56:07 -07:00
8181917f79 fix: Apply timezone offset to convert local time boundaries to UTC (#37014)
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-08 16:40:31 -07:00
d14ab29dcb feat(a11y): enable ECharts aria-label (#28171)
Co-authored-by: rusackas <evan@preset.io>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-08 15:36:24 -07:00
a75665b014 fix(i18n): improve Simplified Chinese translations (#42794)
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 12:51:59 -07:00
db5cd1aa38 chore(i18n): update Italian messages.po translations (#38948)
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 12:40:08 -07:00
abb6dd6e39 fix(i18n): add Tamil (ta) locale with corrected catalog path (#38962)
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 12:31:29 -07:00
4a587b8539 feat(security): actionable, request-access-aware data permission errors (#41843)
Co-authored-by: Greg Neighbors <gregneighbors@Gregs-Air-2.lan>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Greg Neighbors <gregneighbors@Gregs-MacBook-Air-2.local>
2026-08-08 11:51:15 -07:00
127a6f92a6 chore(i18n): update french po file to match latest pot file version (#40635)
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-08 10:43:30 -07:00
25481799f6 test(deckgl): pin GeoJSON layer against multi-row payloads (#34748) (#42734)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-08 08:06:05 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1da7a7fdb1 chore(deps-dev): update starrocks requirement from <2,>=1.3.3 to >=1.3.4,<2 (#42903)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-08 01:54:54 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
185b5938ba chore(deps-dev): bump pyinstrument from 5.1.2 to 5.1.3 (#42905)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-08 01:54:51 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
503309531f chore(deps-dev): update playwright requirement from <2,>=1.61.0 to >=1.62.0,<2 (#42908)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-08 01:54:48 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
44a86b725f chore(deps-dev): update teradatasql requirement from >=20.0.0.63 to >=20.0.0.64 (#42909)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-08 01:54:46 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Amin GhadersohiClaude Sonnet 5
38727906a2 chore(deps): bump react-window and @types/react-window in /superset-frontend (#42528)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 23:02:27 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Joe LirusackasClaude Opus 4.8
2a9c5acb01 chore(deps): bump numpy from 1.26.4 to 2.4.6 (#42778)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 22:55:20 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d8b97e31fa chore(deps-dev): bump @playwright/test from 1.61.1 to 1.62.1 in /superset-frontend (#42699)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 21:05:56 -07:00
bd03440ac8 feat(alerts-reports): add per-schedule toggle to include/exclude the Explore in Superset link (#42494)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 21:05:16 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a6c478c59d chore(deps-dev): bump lerna from 9.0.4 to 10.0.0 in /superset-frontend (#42829)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-08 10:19:24 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fd36419ca2 chore(deps): bump nanoid from 3.3.16 to 3.3.18 in /docs (#42902)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-08 10:08:38 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Joe Li
d80f4c841d chore(deps-dev): update sqlalchemy-risingwave requirement from <2.0.0,>=1.4.1 to <3.0.0,>=1.4.1 (#42856)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-08 09:59:53 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Joe Li
6baa467f59 chore(deps): bump google-auth-library from 10.9.1 to 11.0.0 in /superset-frontend (#42870)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-08 09:58:51 +07:00
b18015f63b feat: Color Picker replaces the color selection drop-down list in conditional formatting (#42053)
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-08 02:00:56 +03:00
eb8592d4bf fix(sqla): don't mislabel DB errors as ColumnNotFoundException in adhoc_column_to_sqla (#42889)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 15:03:49 -07:00
55af4685a2 fix(i18n-es): correct fuzzy-matcher strandings in Spanish catalog (#42808)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 11:29:14 -07:00
c901f01693 fix(datasets): preserve metric/column uuids on dataset export (#42393)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 11:15:24 -07:00
4c894affb2 fix(models): purge_oauth2_tokens filters on wrong column (#42211)
Signed-off-by: Martin Brodeur <addressedemartin@gmail.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 11:04:11 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Joe Li
0f9049608a chore(deps): bump dompurify from 3.4.12 to 3.4.13 in /superset-frontend (#42893)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-07 11:00:19 -07:00
Gabriel Torres RuizandGitHub 91b1a6cac5 feat(theme): allow deployments to register extra theme tokens 2026-08-07 14:37:45 -03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
86a328ca9e chore(deps): bump dompurify from 3.4.12 to 3.4.13 in /docs (#42894)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 10:23:30 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
38ba4a69bf chore(deps): bump react-intersection-observer from 10.1.0 to 11.0.0 in /superset-frontend (#42869)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 10:13:31 -07:00
280253b1fb fix(deletion-retention): dedupe repeated blocked audits (#42863)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-08-07 10:11:36 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Joe Li
79c2cd367d chore(deps): update flask-sqlalchemy requirement from <3.0,>=2.5.1 to <4.0,>=2.5.1 (#42771)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-07 09:42:42 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
fd6a0a60a6 chore(deps): bump holidays from 0.100 to 0.102 (#42860)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 09:41:57 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
c2b5311f47 chore(deps-dev): bump google-cloud-bigquery from 3.42.2 to 3.43.0 (#42861)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 09:41:26 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
70a82a28bf chore(deps): bump redis from 8.0.1 to 8.1.0 (#42857)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 09:41:03 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
f348cf425d chore(deps): bump shillelagh from 1.4.4 to 1.4.5 (#42858)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 09:41:00 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
74196cf694 chore(deps): bump markdown from 3.10.2 to 3.10.3 (#42859)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 09:40:57 -07:00
fe06ebe796 feat(versioning): enable version history and capture by default (#42801)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 10:25:48 -03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f1411ccd6c chore(deps-dev): update pyathena requirement from <4,>=3.35.2 to >=3.35.4,<4 (#42862)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 06:19:46 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1770823f0a chore(deps-dev): bump eslint-plugin-jest-dom from 5.6.0 to 5.7.0 in /superset-frontend (#42868)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 06:18:31 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b7b873321d chore(deps-dev): bump baseline-browser-mapping from 2.11.7 to 2.11.8 in /superset-frontend (#42872)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 06:17:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d363cabec9 chore(deps): bump markdown-to-jsx from 9.9.0 to 9.10.1 in /superset-frontend (#42885)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 06:17:18 -07:00
Joe LiandGitHub 8683d1608e fix(migrations): merge divergent Alembic heads into a single chain (#42878) 2026-08-07 09:27:03 -03:00
Mehmet Salih YavuzandGitHub 14583b6a5f fix(themes): serve system themes with the algorithm of the slot they fill (#42700) 2026-08-07 14:29:49 +03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
27498d26aa chore(deps): bump the docusaurus-openapi group in /docs with 2 updates (#42883)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 02:42:39 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
39e66476e1 chore(deps): bump actions/setup-java from 5.6.0 to 5.7.0 (#42884)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-07 02:42:33 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Đỗ Trọng Hải
8153a82489 chore(deps): bump baseline-browser-mapping from 2.11.7 to 2.11.8 in /docs (#42852)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-08-06 23:24:24 -07:00
448eb25d76 feat(docs): add documentation for usage of minio or other s3 compatible service as a cache backend or celery results backend (#35825)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 18:36:34 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9cec7411e9 chore(deps): bump mermaid from 11.16.0 to 11.16.1 in /docs (#42873)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 18:33:23 -07:00
ae66b697e5 fix(plugin-chart-table): align sticky header column dividers with table body (#42573)
Co-authored-by: Juliann Forbes <juliann@preset.io>
2026-08-06 15:40:44 -07:00
22fb1b3a44 test(dashboard): migrate edit-mode component E2E tests to Playwright (#41438)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 15:22:19 -07:00
Elizabeth ThompsonandGitHub 7dd6ce835f fix(datasets): catch TemplateError instead of narrower TemplateSyntaxError in render_dataset_fields (#42802) 2026-08-06 15:05:08 -07:00
4f2147009f feat(dashboard): expand all chart descriptions (#32958)
Co-authored-by: Urban Pettersson <urban.pettersson@alteryx.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-06 14:47:30 -07:00
2ecce20e48 chore(viz): remove legacy explore_json + viz.py pipeline (#41714)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-06 13:22:15 -07:00
01a9fdc621 chore(reports): thread cache-key/execution-id log context through screenshot capture logs (#42657)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-06 09:43:12 -07:00
ba09f399ac feat(soft-delete): enable soft delete by default and purge for real (#42800)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 09:34:55 -07:00
e4c306f5eb fix(deps): revert simple-zstd from 2.1.0 back to 1.4.2, again (#42804)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 13:18:07 -03:00
ea8fa58158 docs: scope AI pre-commit checks to changed files, to align with ci's pre-commit checks (#42835)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-08-06 10:59:33 -03:00
a00e2952a1 style(frontend): apply oxfmt to existing files (#42813)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-08-06 10:58:27 -03:00
de93a19b3c fix(engine): update databend engine spec for dialect version >=0.4.6 (#28627)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 06:28:16 -07:00
Alexandru SoareandGitHub 57d6e5c637 feat(hooks): add configurable post-creation hook for dashboards (#42837) 2026-08-06 16:11:55 +03:00
dependabot[bot]andGitHub 0fc0d21dd3 chore(deps): bump github/codeql-action/init from 4.37.3 to 4.37.4 (#42827)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-06 14:12:22 +03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
76e6909cfd chore(deps): bump @swc/core from 1.15.46 to 1.15.47 in /docs (#42825)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 03:14:34 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
450e43b8f2 chore(deps): bump baseline-browser-mapping from 2.11.6 to 2.11.7 in /docs (#42826)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 03:14:31 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a7dd86adc6 chore(deps): bump github/codeql-action/analyze from 4.37.3 to 4.37.4 (#42828)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 03:14:25 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
bbd7ac7278 chore(deps-dev): bump baseline-browser-mapping from 2.11.6 to 2.11.7 in /superset-frontend (#42830)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 03:14:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
05af8eeff2 chore(deps): bump react-map-gl from 8.1.1 to 8.1.2 in /superset-frontend (#42831)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 03:14:18 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3f413e6e10 chore(deps-dev): bump @swc/core from 1.15.46 to 1.15.47 in /superset-frontend (#42832)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 03:14:14 -07:00
4278f4b3d9 fix(explore): honor explicit List legend selection instead of flipping to scroll (#41749)
Co-authored-by: Joe Li <joe@preset.io>
2026-08-05 23:08:05 -07:00
Joe LiandGitHub b8c44a1ad5 fix(ci): restore master validation checks (#42807) 2026-08-05 22:58:05 -07:00
d594a4d157 fix(mcp): make streamable-http session mode configurable via MCP_STATELESS_HTTP (#42814)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 21:31:22 -07:00
442995481c test(deckgl): Polygon chart with a column literally named "polygon" (#33669) (#42591)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 20:27:13 -07:00
1de35d1361 fix(mcp): reject unknown fields in nested chart-config models too (#42626) (#42732)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 16:24:55 -07:00
3f011edabb fix(mcp): supply required DBEventLogger args so mcp_tool_error events are logged (#42579) (#42730)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 16:22:10 -07:00
f5bca3bf3f fix(sqllab): stop OAuth2 banner from ballooning the database selector popover (#42652)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 15:40:42 -07:00
32e4e3c6a8 fix(reports): enforce dashboard readiness and execution budget (#42624)
Co-authored-by: Matt Fitzgerald <matt.fitzgerald@preset.io>
Co-authored-by: Elizabeth Thompson <eschutho@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-05 14:30:35 -07:00
ad0538935d fix(pivot-table): blank ambiguous cross-metric totals and null values in fraction mode (#42810)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 14:17:31 -07:00
633f393880 feat(pivot-table): reintroduce show-values-as-fraction display option (#42761)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 14:17:30 -07:00
0e4e368768 feat(mcp): add observability to MCP service (#41921)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-05 11:52:34 -07:00
126c93b495 fix(versioning): pin shadow-row reads and restore to (id, uuid) (#42797)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 11:12:20 -07:00
e880711bbb fix(migrations): actually drop _customer_location_uc (list == set no-op) (#42642)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 11:12:14 -07:00
47a4dabd14 feat(soft-delete): warn at startup when a retention task's Celery config is incomplete (#42641)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 11:12:09 -07:00
JUST.in DO ITandGitHub 657e2d2267 perf(TimeTable): skip rendering TableView while the window is resizing (#42097) 2026-08-05 10:41:39 -07:00
05193ed7e1 fix(models): guard three more backref cascades for SQLAlchemy 2.0 (#42787)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 09:58:45 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>rusackasClaude Opus 4.8
2c7adcaef8 chore(deps): bump sqlglot from 30.12.0 to 30.14.0 (#42772)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 09:44:05 -07:00
f65b42408e fix(tasks): gate exception_type in task properties behind SHOW_STACKTRACE (#40587)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 09:31:30 -07:00
482a59ec72 fix(docker): replace stale superset_app hostname in dev WEBDRIVER_BASEURL (#42495)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Joe Li <joe@preset.io>
2026-08-05 09:31:10 -07:00
e7338a2add fix(mcp): route FastMCP ValidationError through the validation error handler (#42578) (#42738)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 09:27:28 -07:00
9c97d4859c fix(mcp): stop false-flagging successful responses with error_type:null as failures (#42580) (#42736)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-05 09:27:17 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
19399a5068 chore(deps-dev): bump jsdom from 30.0.0 to 30.0.1 in /superset-frontend (#42791)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 22:25:56 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
efab63d42c chore(deps): bump docker/login-action from 4.5.2 to 4.6.0 (#42769)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 22:24:57 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
816f37f5b9 chore(deps-dev): bump gevent from 26.4.0 to 26.7.0 (#42770)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-04 23:33:55 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
872311b3c2 chore(deps-dev): bump duckdb from 1.5.4 to 1.5.5 (#42773)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-04 23:33:52 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6713f1be45 chore(deps-dev): update teradatasql requirement from >=20.0.0.62 to >=20.0.0.63 (#42774)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:48 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0692607b4a chore(deps-dev): update taospy requirement from >=2.8.9 to >=2.8.10 (#42775)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:44 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
fcfee7efbc chore(deps-dev): bump fastmcp from 3.4.4 to 3.4.5 (#42776)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-04 23:33:41 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
0cc5c51ba3 chore(deps): bump selenium from 4.45.0 to 4.46.0 (#42777)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-04 23:33:37 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a57c9b34c9 chore(deps-dev): bump webpack from 5.109.1 to 5.109.2 in /docs (#42779)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:33 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ae8c4bd451 chore(deps): bump baseline-browser-mapping from 2.11.5 to 2.11.6 in /docs (#42780)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:30 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
247f610ee1 chore(deps-dev): bump eslint-plugin-jest-dom from 5.5.0 to 5.6.0 in /superset-frontend (#42781)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:27 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4c33258b9d chore(deps): bump react-draggable from 4.7.0 to 4.7.1 in /superset-frontend (#42782)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:23 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3cf83f0a5a chore(deps-dev): bump baseline-browser-mapping from 2.11.5 to 2.11.6 in /superset-frontend (#42783)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:20 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
425c70ae37 chore(deps-dev): bump webpack from 5.109.1 to 5.109.2 in /superset-frontend (#42784)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 23:33:16 -07:00
ab124a333c fix(SafeMarkdown): let htmlSchemaOverrides replace matching default attribute rules (#42202)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 23:10:14 -07:00
7324225c77 fix(filters): sort numeric filter values numerically, not lexicographically (#36775) (#42596)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-04 23:06:39 -07:00
endimonanandGitHub 1605676aa7 fix(reports): use zip extension for bundled CSV attachments (#42640) 2026-08-04 21:09:19 -07:00
SkinnyPigeonandGitHub d6c8fdd10d fix(explore): recompute currency_formats when dataset is saved from c… (#42480) 2026-08-04 20:41:06 -07:00
Abdul RehmanandGitHub 956231b9ee fix(dataset): make post-save column refresh best-effort for Jinja SQL (#42463) 2026-08-04 20:40:09 -07:00
2f9bde5579 fix(sql): preserve quoted-identifier casing for the HANA dialect (#39328) (#42731)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-04 20:39:35 -07:00
Joe LiandGitHub 5720e9c7fd chore(deps): require manual deck.gl upgrades (#42653) 2026-08-05 10:06:07 +07:00
e871ee27cf fix(i18n-es): correct format-placeholder defects in Spanish catalog (#42728)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 09:21:27 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1a74c8ef67 chore(deps-dev): bump fast-uri from 3.1.4 to 3.1.5 in /superset-embedded-sdk (#42764)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 09:07:27 +07:00
22909bb039 fix(sqllab): retry table metadata preview after OAuth2 redirect (#42390)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-04 21:32:13 -04:00
da27b4ed80 chore(sqla2): bump SQLAlchemy-dependent drivers to dual-compat versions (#42542)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-04 17:08:41 -07:00
Amin GhadersohiandGitHub 86b2076169 fix(mcp): handle missing metrics/columns and null data in chart preview (#42576) 2026-08-04 19:59:47 -04:00
a0895a1fbd fix(native-filters): allow X-clear on defaultToFirstItem filters with required warning (#42762)
Co-authored-by: madhushree agarwal <madhushree_agarwal@apple.com>
2026-08-04 16:57:34 -07:00
043163b54c fix(mcp): reject unparseable time_range instead of silently matching full table (#42283)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-04 19:45:30 -04:00
Amin GhadersohiandGitHub 33c386a2d6 fix(core): reduce metric expression log noise (#42619) 2026-08-04 16:35:02 -07:00
Elizabeth ThompsonandGitHub 7c03736623 fix(alerts): wrap Jinja rendering errors in AlertCommand._execute_query (#42714) 2026-08-04 15:07:10 -07:00
Elizabeth ThompsonandGitHub 4e9e884dd8 fix(sqllab): wrap process_template() in QueryEstimationCommand to prevent raw UndefinedError leak (#42757) 2026-08-04 15:02:47 -07:00
1478e32bc2 fix(mcp): persist Handlebars template under camelCase key so it renders (#42725)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-04 16:21:57 -04:00
e103d92b48 feat(versioning): version-history UI (#41551)
Co-authored-by: Kamil Gabryjelski <kamil.gabryjelski@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
2026-08-04 12:37:46 -07:00
Dang DaoandGitHub 9377659ffa fix(dashboard): preserve duplicate chart holders in filter scopes (#42502) 2026-08-04 21:24:25 +02:00
Lalith KothuruandGitHub 50c84f220b docs: fix parameter name in Explorable.get_query_result docstring (#42646) 2026-08-04 10:15:05 -07:00
Alexandru SoareandGitHub 3dde95d809 feat(reports): add retry on failure support for reports (#42481) 2026-08-04 18:04:32 +03:00
dependabot[bot]andGitHub 0615c73ff3 chore(deps): bump docker/setup-buildx-action from 3.12.0 to 4.2.0 (#42692) 2026-08-04 21:57:40 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e66c7fcb63 chore(deps-dev): bump oxfmt from 0.60.0 to 0.61.0 in /superset-frontend (#42746)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 06:19:36 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
29098afff7 chore(deps): bump react-arborist from 3.15.1 to 3.16.0 in /superset-frontend (#42689)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:13:38 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>hainenber
46b583668b chore(deps-dev): bump ip-address from 10.2.0 to 10.4.0 in /superset-frontend (#42727)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2026-08-04 03:11:11 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ebda22bdfc chore(deps-dev): bump @types/node from 26.1.1 to 26.1.2 in /superset-websocket (#42741)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:11:06 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5f2bc09b9f chore(deps): bump the storybook group in /docs with 2 updates (#42742)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:11:03 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f67d12edf8 chore(deps-dev): bump webpack from 5.109.0 to 5.109.1 in /docs (#42743)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:59 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
64590b5138 chore(deps): bump baseline-browser-mapping from 2.11.4 to 2.11.5 in /docs (#42744)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:56 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
327f526a63 chore(deps-dev): bump the storybook group in /superset-frontend with 5 updates (#42745)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:53 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0048c4d30b chore(deps): bump acorn from 8.17.0 to 8.18.0 in /superset-frontend (#42747)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:48 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
720f36e763 chore(deps-dev): bump webpack from 5.109.0 to 5.109.1 in /superset-frontend (#42748)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:44 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e52f22226f chore(deps): bump ol from 10.9.0 to 10.10.0 in /superset-frontend (#42749)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:40 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
89d544c2ed chore(deps-dev): bump @types/node from 26.1.1 to 26.1.2 in /superset-frontend (#42750)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:36 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
cf7527f2e6 chore(deps-dev): bump oxlint from 1.75.0 to 1.76.0 in /superset-frontend (#42751)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 03:10:33 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9a5cf76336 chore(deps): bump fast-uri from 3.1.4 to 3.1.5 in /superset-frontend/cypress-base (#42721)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 02:49:02 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1666ccaa2b chore(deps-dev): bump jsdom from 29.1.1 to 30.0.0 in /superset-frontend (#42691)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-04 09:18:35 +07:00
Yuriy KrasilnikovandGitHub 457cd3487d fix(api): include query lifecycle timing in /api/v1/chart/data response (#37516) 2026-08-03 17:27:57 -07:00
03b35186e5 fix(jinja): handle UndefinedError from virtual dataset templates (#42366)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-03 17:09:31 -07:00
25ab96188f fix(sqllab): roll back session before retrying get_query after a broken transaction (#42675)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-03 15:04:28 -07:00
4b11fa09c7 fix(errors): map uncaught SupersetException status/log-level correctly (#42643)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-03 15:03:00 -07:00
Joe LiandGitHub 5075253b91 fix(ci): validate frontend dependency tree (#42720) 2026-08-03 14:38:00 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
da537cae00 chore(deps): bump fast-uri from 3.1.4 to 3.1.5 in /superset-frontend (#42722)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 14:30:35 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f877c29f39 chore(deps): bump fast-uri from 3.1.4 to 3.1.5 in /docs (#42723)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 14:30:17 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6de5f12e09 chore(deps): bump antd from 6.5.1 to 6.5.2 in /superset-frontend (#42637)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:30:57 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
de675aee01 chore(deps): bump yargs from 18.0.0 to 18.1.0 in /superset-frontend (#42693)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:27:19 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
366764d7af chore(deps-dev): bump eslint from 10.7.0 to 10.8.0 in /superset-frontend (#42695)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:27:09 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
110c094e35 chore(deps-dev): bump baseline-browser-mapping from 2.11.1 to 2.11.5 in /superset-frontend (#42697)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:27:01 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0517e6ec25 chore(deps-dev): bump postcss from 8.5.18 to 8.5.25 in /superset-websocket (#42719)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:26:32 -07:00
8f10bda68e feat(soft-delete): Recently Archived view with restore and permanent delete (#41550)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 12:21:48 -07:00
da9f4216e1 fix(dashboard): count extra_editors when deciding who may edit a dashboard (#42708)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:20:52 -07:00
bf34c7f2b4 fix(versioning): stop filing every operational failure under the migration race (#42709)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:08:59 -07:00
db0b8b1513 test(versioning): un-skip the two obsolete activity-view skips (#42710)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:07:49 -07:00
081515d52f fix(versioning): drop username from version-history attribution (#42711)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 12:07:02 -07:00
df2786692f fix(semantic-layers): survive large multi-metric selection in Semantic View modal (#42535)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 12:01:54 -07:00
d0503c1b98 fix(dashboard): keep refresh_frequency set via the Advanced JSON editor (#42116) (#42142)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 12:00:39 -07:00
Evan RusackasandGitHub 564ef599ab fix(ci): collapse Cypress e2e matrix from 2 runners to 1 (#42715) 2026-08-03 11:49:47 -07:00
Đỗ Trọng HảiandGitHub e4ef84ca72 feat(build): migrate from Prettier to Oxfmt for performant code formatting (#42434) 2026-08-04 00:27:05 +07:00
Đỗ Trọng HảiandGitHub 10f7927603 feat(ci): switch to ubuntu-slim runner image for faster startup time when running light CI workloads (#39656) 2026-08-03 23:31:06 +07:00
566d23ea33 fix(chart): stop duplicate metrics when switching between Waterfall and other chart types (#42533)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 09:22:22 -07:00
JUST.in DO ITandGitHub ac97484b2a fix(mcp): missing params in MCP tool call logs (#42660) 2026-08-03 08:38:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5b31e0fee6 chore(deps-dev): bump concurrently from 10.0.3 to 10.0.4 in /superset-frontend (#42694)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 22:04:03 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
791305dfcf chore(deps): bump ngeohash from 0.6.3 to 0.6.4 in /superset-frontend (#42698)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:51:33 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
de0acdc73e chore(deps-dev): bump html-webpack-plugin from 5.6.7 to 5.6.8 in /superset-frontend (#42688)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:46:29 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3d5f0813c3 chore(deps): bump the rjsf group in /superset-frontend with 2 updates (#42686)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:45:54 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4939d6863f chore(deps): bump baseline-browser-mapping from 2.11.1 to 2.11.4 in /docs (#42681)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:45:22 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
788181beba chore(deps-dev): bump globals from 17.7.0 to 17.8.0 in /docs (#42682)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:45:03 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
8b3142c57c chore(deps): bump the storybook group in /docs with 2 updates (#42680)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:44:36 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
11f502d705 chore(deps): bump hot-shots from 17.0.1 to 17.1.0 in /superset-websocket (#42685)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:44:24 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
271dfbf6d5 chore(deps-dev): bump the storybook group in /superset-frontend with 5 updates (#42687)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:43:50 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5aaaa3472d chore(deps-dev): bump eslint from 10.7.0 to 10.8.0 in /superset-websocket (#42683)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:43:17 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ad0247208a chore(deps-dev): bump globals from 17.7.0 to 17.8.0 in /superset-websocket (#42684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:42:48 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
84a33b75d2 chore(deps): bump docker/login-action from 4.5.1 to 4.5.2 (#42690)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:42:15 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ac1002bddd chore(deps): bump chalk from 5.6.2 to 6.0.0 in /superset-frontend (#42696)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 21:41:13 +07:00
06628bbd68 feat(i18n): serve language packs as versioned, immutable-cacheable scripts (#41780)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 21:59:44 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>hainenberrusackasClaude Sonnet 5Đỗ Trọng Hải
d64eaf9cdb chore(deps-dev): bump @testing-library/jest-dom from 6.9.1 to 7.0.0 in /superset-frontend (#42525)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2026-08-03 09:00:44 +07:00
Luc VerdierandGitHub 4915a3e8c7 fix(mcp): report the committed chart when its instance is detached (#42621) 2026-08-02 14:56:46 -07:00
7ce56d369a ci: add Kesin11/actions-timeline to the heavy CI workflows (#42507)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 14:53:27 -07:00
b6d8c830e7 test(jinja): pin filter_values() drill-to-detail native-filter fallback for virtual datasets (#35263) (#42595)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-02 14:44:38 -07:00
Đỗ Trọng HảiandGitHub 4e3ff37137 chore(ci): resolve shellcheck-flagged errors (#42430)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-08-03 00:09:04 +07:00
Joe LiandGitHub 120b4420b9 fix(versioning): narrow UUIDs in restore tests (#42654) 2026-08-02 23:54:30 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0628b0b813 chore(deps-dev): update thrift requirement from <1.0.0,>=0.23.0 to >=0.24.0,<1.0.0 (#42667)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-02 23:45:06 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
378634cceb chore(deps-dev): update pyathena requirement from <4,>=2 to >=3.35.2,<4 (#42665)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-02 23:44:48 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
af7472fd7e chore(deps-dev): update databricks-sql-connector requirement from <4.4.0,>=4.2.6 to >=4.4.0,<4.5.0 (#42668)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-02 23:36:20 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
36e3ebecfa chore(deps): bump croniter from 6.2.2 to 6.2.4 (#42664)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-02 17:22:56 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
3f201c1c77 chore(deps): bump polyline from 2.0.2 to 2.0.4 (#42666)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-02 17:22:48 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
cc4cd3e98a chore(deps): bump cachetools from 7.1.4 to 7.1.6 (#42663)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-02 17:06:14 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
322ae841e5 chore(deps-dev): update clickhouse-connect requirement from <2.0,>=1.4.2 to >=1.6.0,<2.0 (#42669)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-02 17:05:57 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
5ccccc8c69 chore(deps): bump greenlet from 3.5.3 to 3.5.4 (#42670)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-02 17:05:34 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
3d0ee8b4c5 chore(deps-dev): bump prophet from 1.2.0 to 1.3.0 (#42672)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-02 17:05:20 +07:00
ff9bec2b99 fix(dashboard): make chart error messages expandable again (#42491)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-01 15:26:31 -07:00
Beto DealmeidaandGitHub 9f66cb566b feat(semantic layers): don't show samples tab in explore (#41509) 2026-08-01 16:03:20 -04:00
29ac93862e fix(i18n-fr): translate the 85 remaining untranslated strings (#42577)
Signed-off-by: Dorian Saint-Martin <dorian.saintmartin@outlook.fr>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-08-01 10:39:59 -07:00
c9b159b4e7 docs(db_engine_specs): link upstream Pinot timestamp fix in TODO (#42623)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-01 10:39:14 -07:00
d336d2a8b6 feat(ci): auto-label PRs with merge conflicts using requires:rebase (#42504)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 10:38:02 -07:00
Amin GhadersohiandGitHub 22c305f758 fix(dataset): retry metadata after OAuth2 authorization (#42581) 2026-07-31 20:41:42 -04:00
6929d032b8 fix(reports): time-budget tiled screenshot to fail cleanly instead of hitting Celery kill (#42118)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-31 15:37:46 -07:00
f6c574edd8 fix(screenshots): validate cached screenshot image bytes on read and write (#42120)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-31 15:13:59 -07:00
b452c1634d fix(a11y): add aria-label to dashboard IconButton and unlabeled call sites (#41470)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-31 15:05:32 -07:00
Elizabeth ThompsonandGitHub 1bfbce3cfd fix(alerts-reports): catch CroniterBadDateError in report frequency validation (#42650) 2026-07-31 15:04:30 -07:00
85bab0b07c fix(reports): downgrade chart-container timeout log level and fix tiling veto on unknown height (#42153)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-31 15:00:38 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0981b1101a chore(deps-dev): bump nx from 22.6.1 to 22.7.8 in /superset-frontend (#42651)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-31 12:49:05 -07:00
f607e17e3a fix(reports): fail loudly instead of falling back to unguarded screenshot when tiled capture fails (#42273)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-31 12:41:29 -07:00
6c8763bf5a fix(db2): stop truncating table comments to one character (#42645)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-31 12:36:36 -07:00
035eaa8b80 fix(time-comparison): preserve inner bounds for relative offsets (#42357)
Co-authored-by: Prathamesh Hukkeri <prathamesh04@users.noreply.github.com>
2026-07-31 11:03:47 -07:00
Arijit Kumar RoyandGitHub ec8405aeea chore(mcp): remove unused MCP_SERVICE_HOST and MCP_SERVICE_PORT config (#42569)
Signed-off-by: arijitroy003 <arijitroy003@gmail.com>
2026-07-31 11:01:39 -07:00
dc632a9737 fix(db_engine_specs): stop filtering out Postgres schemas prefixed with pg (#42312)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 10:58:59 -07:00
Abdul RehmanandGitHub e391691328 fix(menu): highlight Datasets tab on /dataset/add/ and /dataset/:id (#42529) 2026-07-31 10:56:36 -07:00
a419a2a47f docs: fix incorrect capitalization 'PiPY' to 'PyPI' in RELEASING/README.md (#42649)
Co-authored-by: pi <pi@m2.local>
2026-07-31 10:44:51 -07:00
263d793b77 docs: fix missing apostrophe in 'doesn't' in superset/mcp_service/README.md (#42648)
Co-authored-by: pi <pi@m2.local>
2026-07-31 10:44:30 -07:00
cd77d13cfe docs: fix typo 'throuth' → 'through' in superset-embedded-sdk/README.md (#42647)
Co-authored-by: pi <pi@m2.local>
2026-07-31 10:44:11 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
268662fa49 chore(deps): bump mapbox-gl from 3.26.0 to 3.27.0 in /superset-frontend (#42636)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-31 10:41:41 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c0f9dec963 chore(deps): bump docker/login-action from 3.7.0 to 4.5.1 (#42632)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-31 10:41:06 -07:00
dependabot[bot]andGitHub 8e08a65abb chore(deps): bump google-auth-library from 10.9.0 to 10.9.1 in /superset-frontend (#42633) 2026-07-31 23:37:20 +07:00
dependabot[bot]andGitHub 1a7f2afae9 chore(deps): bump antd from 6.5.1 to 6.5.2 in /docs (#42630) 2026-07-31 23:36:46 +07:00
dependabot[bot]andGitHub 05f45863cb chore(deps-dev): bump webpack from 5.108.4 to 5.109.0 in /docs (#42631) 2026-07-31 23:36:21 +07:00
dependabot[bot]andGitHub 96a12e0442 chore(deps-dev): bump webpack from 5.108.4 to 5.109.0 in /superset-frontend (#42634) 2026-07-31 23:20:44 +07:00
dependabot[bot]andGitHub 06effe2961 chore(deps): bump fs-extra from 11.3.2 to 11.4.0 in /superset-frontend (#42635) 2026-07-31 23:19:50 +07:00
Evan RusackasandGitHub 8235d0c4fb fix(alerts-reports): skip inactive users when resolving report executor (#42612) 2026-07-31 09:15:59 -07:00
67d05d0ed7 docs(installation): document how to add translations to a custom Docker image (#42586)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 09:15:42 -07:00
837ae95b7b feat(ci): auto-approve Dependabot patch-level bumps (#42508)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 09:15:26 -07:00
3692ac5870 ci: de-vendor helm/chart-releaser-action (#42506)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-31 09:15:11 -07:00
1df022b364 ci: mirror CI service images to GHCR (fork-safe Docker Hub pulls, groundwork) (#40880)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 09:14:30 -07:00
7d2b184079 fix(explore): show selected current date range (#42616)
Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
2026-07-31 10:55:09 +02:00
Amin GhadersohiandGitHub 7b351d53cf fix(mcp): fall back to a temporal dataset column (#42575) 2026-07-30 17:39:49 -04:00
Yousuf AnsariandGitHub 6279cafbbd fix(echarts): correct time shift handling in Timeseries transformProps (#38126) 2026-07-30 12:35:35 -07:00
4b3801a447 fix(select): don't cap multi-row tag container to single-line height (#42600)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-30 12:32:34 -07:00
Mallikarjuna Reddy NimmakayalaandGitHub dae374b75b fix(dashboard): prevent result set overlap in mixed chart View as Table (#42018) 2026-07-30 12:17:46 -07:00
1df0cca2f9 docs(databricks): include Databricks in user impersonation UI text (#36850)
Co-authored-by: Joe Li <joe@preset.io>
2026-07-30 11:50:30 -07:00
bfa7dabb34 test(query): normalize_dttm_col with UTC offset at second-level grain (#37925) (#42589)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-30 11:44:52 -07:00
Vitor AvilaandGitHub 6e1c2fbcb8 chore: Mask specific Druid/Presto/Trino fields (#42492) 2026-07-30 10:49:19 -07:00
Evan RusackasandGitHub 9f5611aca5 chore(country-map): regenerate all country GeoJSON files from the notebook (#42493) 2026-07-30 10:32:42 -07:00
8cd7793cd2 fix(db-engine-specs): handle bare-year python_date_format columns in time-grain expressions (#42432)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-30 10:32:20 -07:00
69801a57b1 fix(explore): resolve now/today anchors to local time, not UTC (#42308)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 10:30:18 -07:00
Evan RusackasandGitHub 0fa176c1b2 fix(embedded): respect show_filters URL param in standalone report mode (#42307) 2026-07-30 10:29:11 -07:00
c392a560e6 fix(plugin-chart-echarts): preserve null radar metric values as gaps (#30270) (#41962)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-30 10:28:40 -07:00
e71ade5824 fix(clickhouse): use equality for boolean filters instead of IS (#41867)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 10:27:29 -07:00
3588c9ad86 feat(scatter): add chart orientation and dot size metric controls (#40967)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 10:27:04 -07:00
Alejandro SolaresandGitHub dbaab6d6f4 fix: upgrade brace-expansion to patched versions (CVE-2026-14257) (#42583) 2026-07-31 00:22:48 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
bb4bd75426 chore(deps-dev): bump baseline-browser-mapping from 2.11.0 to 2.11.1 in /superset-frontend (#42607)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-30 10:22:05 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6a32c53070 chore(deps): bump zizmorcore/zizmor-action from 0.6.0 to 0.6.1 (#42606)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-30 10:21:50 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d1b211d4ab chore(deps): bump docker/login-action from 4.4.0 to 4.5.0 (#42605)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-30 10:21:38 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6282f3907f chore(deps): bump baseline-browser-mapping from 2.11.0 to 2.11.1 in /docs (#42604)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-30 10:21:22 -07:00
473f447c1b fix(explore): keep the annotation layer modal usable in a small viewport (#42614)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 19:09:58 +02:00
Mike BridgeandGitHub 59a5ae0df3 feat(soft-delete): deletion-retention purge of soft-deleted entities (#41549) 2026-07-30 09:01:12 -07:00
Evan RusackasandGitHub 673f928589 fix(ci): stop helm release PRs from piling up and going stale (#42209) 2026-07-30 07:46:56 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Evan RusackasJoe Li
23d5b63421 chore(deps): bump pyarrow from 24.0.0 to 25.0.0 (#42415)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Joe Li <joe@preset.io>
2026-07-29 16:16:00 -07:00
cec033e59c fix(table): pick totals query positionally so all_records percent metrics don't shift it (#42428)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 15:47:57 -07:00
Evan RusackasandGitHub d9c0f19b0c fix(pivot-table): keep each Rows field as its own CSV/XLSX column (#42443) 2026-07-29 15:47:28 -07:00
8955593b85 fix: close gaps in pkg_resources/sqlalchemy-redshift warning suppression (#41935)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 15:05:18 -07:00
bab40cf437 fix(errors): downgrade SSH tunnel connection-failure logging to WARNING (SC-115347) (#42538)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-29 15:03:17 -07:00
e553910240 fix(sqllab): add filterBySqlLab prop to decouple expose_in_sqllab filter from UI rendering mode (#42440)
Co-authored-by: Prathamesh Hukkeri <prathamesh04@users.noreply.github.com>
2026-07-29 14:12:02 -07:00
Arijit Kumar RoyandGitHub 1e3601a641 fix(docs): Fix insecure HTTP links in README.md (#42565)
Signed-off-by: arijitroy003 <arijitroy003@gmail.com>
2026-07-29 13:10:39 -07:00
SBIN2010andGitHub 68528281b1 fix(explore): ensure unsaved-changes dialog renders above View SQL modal v2 (#42546) 2026-07-29 12:57:08 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7d542a9e87 chore(deps): bump github/codeql-action/analyze from 4.37.2 to 4.37.3 (#42551)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 12:12:55 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
34e71c91f2 chore(deps-dev): bump oxlint from 1.74.0 to 1.75.0 in /superset-frontend (#42558)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 12:12:28 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
6bb0d92279 chore(deps-dev): bump wait-on from 9.0.10 to 9.1.0 in /superset-frontend (#42556)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:39:36 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
bdaa53575f chore(deps): bump react-arborist from 3.15.0 to 3.15.1 in /superset-frontend (#42557)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:39:31 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7e9c2a347a chore(deps): bump the ag-grid group in /superset-frontend with 2 updates (#42553)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:39:22 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ffb4fcceb9 chore(deps-dev): bump ts-jest from 29.4.11 to 29.4.12 in /superset-frontend (#42554)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:39:16 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dd54aabc61 chore(deps-dev): bump baseline-browser-mapping from 2.10.44 to 2.11.0 in /superset-frontend (#42555)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:39:12 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e36cbe48f2 chore(deps): bump baseline-browser-mapping from 2.10.44 to 2.11.0 in /docs (#42550)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:38:59 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4c64ec6efa chore(deps): bump github/codeql-action/init from 4.37.2 to 4.37.3 (#42552)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:38:55 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
f486783b02 chore(deps): bump swagger-ui-react from 5.32.9 to 5.32.11 in /docs (#42549)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 11:38:44 -07:00
Luiz OtavioandGitHub afb863684b feat(cache): add DATA_CACHE_MAX_VALUE_SIZE to skip caching oversized results (#42570) 2026-07-29 11:35:42 -07:00
Joe LiandGitHub 5286e565e4 refactor(e2e): model dashboard filter bar (#42017) 2026-07-29 10:41:02 -07:00
435fb8babc fix(sqllab): make dark-theme occurrence highlight readable (#42403)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:22:58 -07:00
f8c05bba6e fix(clickhouse): bound system sampling reads instead of failing on max_rows_to_read (#42464)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-29 10:20:20 -07:00
9d2dcf2198 fix(oauth2): clear schema/catalog auth banner after OAuth2 redirect refetch (#41913)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:20:15 -07:00
c257fa7d66 fix(chart): render chart error stack trace in monospace in dark mode (#42320)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 10:20:11 -07:00
Jean PommierandGitHub 87f7dbf337 fix(i18n-fr): improve French translation (#42572) 2026-07-29 10:06:52 -07:00
940b670636 feat(versioning): version-restore engine and endpoints for charts, dashboards, and datasets (#42469)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 09:54:37 -07:00
069605828d feat(subjects): scope principal listings and default new assets to creator groups (#42472)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-29 14:36:45 +02:00
Mehmet Salih YavuzandGitHub 7999b7410f fix(explore): restore Back button undo for chart changes (#42473) 2026-07-29 13:55:57 +03:00
Alexandru SoareandGitHub 6a801ff94f fix(explore): sync FilterInput value with parent filter state (#42342) 2026-07-29 13:26:49 +03:00
dac69f9bcd feat(pie): geometric recentering and scaling for partial arcs (#42151)
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-28 22:27:11 -07:00
Rehan IslamandGitHub d984fb08a4 feat(explore): add download control to standalone charts (#42238) 2026-07-28 22:06:45 -07:00
jesperctandGitHub 8be430014e fix(dashboard): make Clear All clear filters that have default values (#42111) 2026-07-28 22:05:51 -07:00
aikawa-ohnoandGitHub 00c60bf2de fix(i18n): Update Japanese translations (#42444) 2026-07-28 17:04:47 -07:00
1d4c3a2adb fix(core): don't blank a datetime column when its format coerces every value to NaT (#42405)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-28 15:18:53 -07:00
Elizabeth ThompsonandGitHub 4a4f0685fd fix(reports): prevent bad-date crontab from crashing the report scheduler for all tenants (#42486) 2026-07-28 15:02:36 -07:00
Kobi HikriandGitHub 22ad3f2c34 fix(ci): make the Dependency Review check able to fail again (#42537) 2026-07-28 11:52:12 -07:00
Joe LiandGitHub 9cdb555255 fix(docker): isolate tagged images from host packages (#42249) 2026-07-28 11:51:48 -07:00
fc59d9c0cf fix(i18n): improve french translations (#42470)
Co-authored-by: Elsanbot <elsanbot@elsan.care>
2026-07-28 11:48:31 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
623348f190 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 8.64.0 to 8.65.0 in /superset-frontend in the typescript-eslint group across 1 directory (#42512)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 10:29:58 -07:00
Amin GhadersohiandGitHub 5aaf9d337b fix(jinja): handle non-JSON body with JSON content-type in get_form_data (#42196) 2026-07-28 09:18:08 -07:00
JUST.in DO ITandGitHub 181f5bc9c1 fix(mcp): capture created chart/dashboard id in generate_chart/generate_dashboard audit logs (#42367) 2026-07-28 09:16:58 -07:00
Đỗ Trọng HảiandGitHub e426fb7bc6 chore(ci): correct GH event type for opening new issue and PR in supersetbot orglabel job (#42424)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2026-07-28 09:16:41 -07:00
b5c8d4a5df fix(mixed-timeseries): stop duplicating first metric in multi-metric + group-by series names (#40146)
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-07-28 09:15:26 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>rusackasClaude Opus 4.8
236c9a52fd chore(deps-dev): bump @typescript-eslint/eslint-plugin from 8.63.0 to 8.65.0 in /superset-websocket (#42515)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: rusackas <evan@rusackas.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 08:06:12 -07:00
Mehmet Salih YavuzandGitHub b983161eef feat(async): cancel running chart queries under GLOBAL_ASYNC_QUERIES (#42305) 2026-07-28 18:02:16 +03:00
7b767f6c1d chore(ci): swap linkinator-action for lychee-action in docs link checker (#42501)
Co-authored-by: Superset Dev <dev@superset.apache.org>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 21:33:01 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
526cebac73 chore(deps-dev): bump prettier from 3.9.5 to 3.9.6 in /superset-websocket (#42514)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 21:30:23 +07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
39f9b7029b chore(deps): bump github/codeql-action/analyze from 4.37.1 to 4.37.2 (#42520)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 16:05:23 +03:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
25a985893d chore(deps-dev): bump typescript-eslint from 8.64.0 to 8.65.0 in /superset-websocket (#42516)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:49:06 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ad15c4ddd1 chore(deps): bump the storybook group in /docs with 2 updates (#42517)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:49:02 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a301e7c511 chore(deps-dev): bump the typescript-eslint group in /docs with 3 updates (#42518)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:59 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dd7bbe0adf chore(deps-dev): bump prettier from 3.9.5 to 3.9.6 in /docs (#42519)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:56 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2e81eb580f chore(deps): bump baseline-browser-mapping from 2.10.43 to 2.10.44 in /docs (#42521)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:49 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a970838b5c chore(deps): bump github/codeql-action/init from 4.37.1 to 4.37.2 (#42522)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:46 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2c061f1e05 chore(deps-dev): bump the storybook group in /superset-frontend with 5 updates (#42523)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:42 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
be012c8faa chore(deps): bump markdown-to-jsx from 9.8.2 to 9.9.0 in /superset-frontend (#42524)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:39 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
e754b73af2 chore(deps-dev): bump baseline-browser-mapping from 2.10.43 to 2.10.44 in /superset-frontend (#42526)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:35 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
435e7825a6 chore(deps-dev): bump prettier from 3.9.5 to 3.9.6 in /superset-frontend (#42527)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 03:48:32 -07:00
ecc7f726a4 fix: guard potential null derefs and remove dead branches (#42358)
Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
2026-07-28 11:43:46 +03:00
26b6f7bb5d fix(dashboard): preserve refresh_frequency when absent from save data (#42354)
Co-authored-by: Prathamesh Hukkeri <prathamesh04@users.noreply.github.com>
2026-07-27 23:13:11 -07:00
a10c3f0b1d test(result_set): add regression test for empty result set column metadata (#35962)
Co-authored-by: Phuc Hung Nguyen <phucnguyen@geotab.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-27 23:08:59 -07:00
3095d7b07f fix(metadata-bar): add max-width to text for proper ellipsis truncation (#42237)
Co-authored-by: Prathamesh Hukkeri <prathamesh04@users.noreply.github.com>
2026-07-27 20:38:29 -07:00
a8e2a340f1 fix(select): exclude null-valued options from "Select all" count (#42220)
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-07-27 20:24:44 -07:00
PawanandGitHub c0117f78a9 feat(dashboard): respect GranularExportControls for download permission (#41799) 2026-07-27 20:00:03 -07:00
a73e2485de feat(versioning): version-history retention cleanup job (#41075)
Co-authored-by: Mike Bridge <michael.bridge@ext.preset.io>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 19:59:11 -07:00
79f3fed1f9 fix(country-map): carve the Great Lakes out of USA map states (#29503)
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2026-07-27 19:58:32 -07:00
c792752a58 fix(db_engine_specs): preserve DATE semantics when applying Postgres time grains (#42254) (#42329)
Co-authored-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
2026-07-27 17:31:28 -07:00
eb914b8ae3 fix(datasets): log datetime format-detection DB query failures at WARNING (#42388)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-27 15:09:28 -07:00
Elizabeth ThompsonandGitHub 276b7e2d67 fix(importers): catch YAMLError instead of narrower ParserError in dataset v0 importer (#42442) 2026-07-27 15:04:52 -07:00
Elizabeth ThompsonandGitHub 3e7ae85cc2 fix(importers): catch YAMLError instead of narrower ParserError in load_yaml (#42426) 2026-07-27 15:03:37 -07:00
12d7179c21 fix(hive): select schema via USE prequery instead of rewriting the URI database (#36603)
Co-authored-by: Job <job@samax.nu>
Co-authored-by: Evan Rusackas <evan@preset.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 14:54:16 -07:00
1d752a0ced fix(embedded): load guest charts with missing or stale query_context (#42150)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 14:14:55 -07:00
a44afd8105 chore: drop legacy /superset prefix from remaining hardcoded URLs (#42156)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 14:13:35 -07:00
Nitish AgarwalandGitHub 74924ae73a fix(db_engine_specs): use CAST(DATE({col}) AS DATETIME) in MySQL HOUR time grain (#38617) 2026-07-27 12:52:25 -07:00
3778 changed files with 221005 additions and 76212 deletions
+2 -2
View File
@@ -105,9 +105,9 @@ Charts built from enriched datasets containing:
pre-commit install
# Quick validation (faster than --all-files)
pre-commit run # Staged files only
pre-commit run # Staged files only
pre-commit run mypy # Python type checking
pre-commit run prettier # Code formatting
pre-commit run format # Code formatting
pre-commit run eslint # Frontend linting
```
-1
View File
@@ -32,7 +32,6 @@
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
-1
View File
@@ -59,7 +59,6 @@
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
+1 -1
View File
@@ -34,7 +34,7 @@
**/*.geojson @villebro @rusackas
**/*.ipynb @villebro @rusackas
/superset-frontend/plugins/legacy-plugin-chart-country-map/ @villebro @rusackas
/superset-frontend/plugins/plugin-chart-country-map/ @villebro @rusackas
# Notify translation maintainers of changes to translations
+12 -6
View File
@@ -28,6 +28,11 @@ updates:
# See https://github.com/apache/superset/pull/37384#issuecomment-3793991389
# TODO: remove the plugin once Lodash usage has been migrated to a more readily tree-shakeable alternative
- dependency-name: "@swc/plugin-transform-imports"
# deck.gl and luma.gl share strict peer constraints across the root and
# plugin workspaces, and root overrides pin their transitive versions.
# Upgrade both families together in a manually validated change.
- dependency-name: "@deck.gl/*"
- dependency-name: "@luma.gl/*"
# `just-handlerbars-helpers` library in plugin-chart-handlebars requires `currencyformatter`` to be < 2
- dependency-name: "currencyformatter.js"
update-types: ["version-update:semver-major"]
@@ -42,6 +47,13 @@ updates:
# as a single manual upgrade anyway. TODO: remove when Babel 8 support is viable.
- dependency-name: "@babel/*"
update-types: ["version-update:semver-major"]
# v2.0.0 renamed ZSTDDecompress to decompress and made it async, breaking
# the webpack dev proxy (see #38662, #39138, #39139). Dependabot reopened
# the same bump in #39369 after the first revert, so pin it here instead
# of relying on a package.json comment (package.json is JSON and can't
# hold comments). Remove this once the proxy code is updated to await
# the async decompress() API.
- dependency-name: "simple-zstd"
directory: "/superset-frontend/"
schedule:
interval: "daily"
@@ -59,12 +71,6 @@ updates:
babel:
patterns:
- "@babel/*"
deckgl:
patterns:
- "@deck.gl/*"
lumagl:
patterns:
- "@luma.gl/*"
storybook:
patterns:
- "@storybook/*"
+12 -9
View File
@@ -201,18 +201,23 @@ cypress-run-all() {
# navigation flow under E2E. We diverge from the entrypoint on:
# --timeout 120: heavy dashboard import/export specs exceed the 60s
# default
# --max-requests / --max-requests-jitter: recycle the worker under
# test load to avoid leaks accumulating across the run
# superset.app:create_app(): explicit factory so we don't depend on
# FLASK_APP being exported
#
# No --max-requests, matching the entrypoint's default of 0 (recycling
# off). With a single worker a recycle takes the whole backend offline for
# the graceful-timeout drain — browser keep-alive connections hold it open
# for the full 30s — plus ~5s of app boot. A run issues ~3800 requests in
# ~8 minutes, so recycling every 500 produced seven ~35s outages per run
# and flaked whichever specs happened to navigate into one. Lowering
# --graceful-timeout is not enough: a dashboard load plus chart render
# needs 6-10s, which still lands inside the window.
nohup gunicorn \
--bind "127.0.0.1:$port" \
--workers 1 \
--worker-class gthread \
--threads 20 \
--timeout 120 \
--max-requests 500 \
--max-requests-jitter 50 \
--access-logfile - \
--error-logfile - \
"superset.app:create_app()" \
@@ -256,7 +261,7 @@ cypress-run-all() {
# UNCOMMENT the next few commands to monitor memory usage
# monitor_memory & # Start memory monitoring in the background
# memoryMonitorPid=$!
python ../../scripts/cypress_run.py --parallelism $PARALLELISM --parallelism-id $PARALLEL_ID --group $PARALLEL_ID --retries 5 $USE_DASHBOARD_FLAG
python ../../scripts/cypress_run.py --retries 5 $USE_DASHBOARD_FLAG
# kill $memoryMonitorPid
}
@@ -294,16 +299,14 @@ playwright-run() {
export PLAYWRIGHT_BASE_URL
# See cypress-run-all() above for the args rationale (1 worker × 20
# gthread threads matching docker/entrypoints/run-server.sh, plus a
# 120s timeout and request-recycling for heavy E2E load).
# gthread threads matching docker/entrypoints/run-server.sh, a 120s
# timeout for heavy E2E load, and why worker recycling is off).
nohup gunicorn \
--bind "127.0.0.1:$port" \
--workers 1 \
--worker-class gthread \
--threads 20 \
--timeout 120 \
--max-requests 500 \
--max-requests-jitter 50 \
--access-logfile - \
--error-logfile - \
"superset.app:create_app()" \
+1 -1
View File
@@ -23,7 +23,7 @@ on:
jobs:
bump-python-package:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
permissions:
actions: write
contents: write
@@ -19,7 +19,7 @@ concurrency:
jobs:
check_db_migration_conflict:
name: Check DB migration conflict
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
+6 -1
View File
@@ -11,6 +11,7 @@ on:
permissions:
contents: read
pull-requests: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
@@ -21,6 +22,10 @@ jobs:
check-python-deps:
runs-on: ubuntu-26.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
@@ -46,7 +51,7 @@ jobs:
- name: Login to Docker Hub
if: steps.check.outputs.python
continue-on-error: true
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+2 -2
View File
@@ -64,7 +64,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -75,6 +75,6 @@ jobs:
# queries: security-extended,security-and-quality
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
with:
category: "/language:${{matrix.language}}"
@@ -0,0 +1,63 @@
name: Auto-approve Dependabot patch bumps
# Posts an approving review on Dependabot PRs that only bump a patch
# version, using the same trigger/guard convention already proven to work
# for Dependabot PRs in sync-requirements-for-python-dep-upgrade-pr.yml
# (plain `pull_request` gets a working, write-capable GITHUB_TOKEN here
# because Dependabot pushes branches directly to this repo, not a fork).
#
# This does NOT auto-merge anything - repo-wide auto-merge is disabled
# (Settings > General > Pull Requests > "Allow auto-merge" is off), and
# flipping that is a separate, repo-wide decision this workflow doesn't
# make on its own. Branch protection also still requires 1 approving
# review; this just means that review can already exist by the time a
# human looks at the PR, for the (large majority of) ecosystems whose
# files aren't matched by any CODEOWNERS pattern. One ecosystem - the npm
# bump under .github/actions - matches the /.github/ CODEOWNERS entry, so
# those PRs will still need a human owner's approval regardless of this
# workflow; it posts a review there too, but that alone won't satisfy the
# code-owner requirement.
on:
pull_request:
types: [opened, synchronize]
# Cancel a superseded run if Dependabot pushes to the same PR again before
# the previous run finished (matches the pattern used elsewhere in
# superset-docs-verify.yml).
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions: {}
jobs:
approve-patch-bump:
name: Approve patch-level bump
# Mirrors the guard in sync-requirements-for-python-dep-upgrade-pr.yml:
# limited to (1) PRs authored by Dependabot and (2) the upstream repo,
# since forked PRs don't get a write-capable token here anyway.
if: >
github.repository == 'apache/superset' &&
github.event.pull_request.user.login == 'dependabot[bot]' &&
github.event.pull_request.head.repo.fork == false
runs-on: ubuntu-latest
permissions:
pull-requests: write # to post the approving review via `gh pr review`
steps:
- name: Fetch Dependabot metadata
id: metadata
# This exact SHA is on ASF Infra's action allowlist
# (apache/infrastructure-actions approved_patterns.yml) as of this
# writing. Do not bump without opening an Infra ticket to allow
# the new SHA first!
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
- name: Approve patch-level bump
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
DEPENDENCY_NAMES: ${{ steps.metadata.outputs.dependency-names }}
run: |
gh pr review --approve "$PR_URL" \
--body "Auto-approved: patch-level bump only ($DEPENDENCY_NAMES)."
+7 -3
View File
@@ -20,11 +20,12 @@ concurrency:
permissions:
contents: read
actions: read
jobs:
dependency-review:
if: github.event_name == 'pull_request'
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- name: "Checkout Repository"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -32,7 +33,6 @@ jobs:
persist-credentials: false
- name: "Dependency Review"
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
continue-on-error: true
with:
fail-on-severity: critical
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html
@@ -48,8 +48,12 @@ jobs:
python-dependency-liccheck:
# NOTE: Configuration for liccheck lives in our pyproject.yml.
# You cannot use a liccheck.ini file in this workflow.
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout Repository"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
+12 -1
View File
@@ -40,7 +40,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
setup_matrix:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
timeout-minutes: 5
outputs:
matrix_config: ${{ steps.set_matrix.outputs.matrix_config }}
@@ -213,3 +213,14 @@ jobs:
shell: bash
run: |
docker compose -f docker-compose-image-tag.yml up superset-init --exit-code-from superset-init
actions-timeline:
needs: [docker-build, docker-compose-image-tag]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
# gate on. Restrict to the canonical repo: forks cannot mint a valid OIDC
# token for this package and must not publish.
if: github.repository == 'apache/superset'
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
permissions:
contents: read
id-token: write # required for npm trusted publishing (OIDC)
+1 -1
View File
@@ -16,7 +16,7 @@ concurrency:
jobs:
embedded-sdk-test:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
defaults:
run:
working-directory: superset-embedded-sdk
+3 -3
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
config:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -29,7 +29,7 @@ jobs:
needs: config
if: needs.config.outputs.has-secrets
name: Generate Report
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -37,7 +37,7 @@ jobs:
persist-credentials: false
submodules: recursive
- name: Setup Java
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: "temurin"
java-version: "11"
@@ -46,4 +46,4 @@ jobs:
run: bash .github/workflows/github-action-validator.sh
- name: Check for security issues on GHA workflows
uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0
uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2
@@ -2,14 +2,14 @@ name: supersetbot orglabel based on author
on:
issues:
types: [created, edited]
types: [opened, edited]
pull_request:
types: [created, edited]
types: [opened, edited]
jobs:
superbot-orglabel:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
@@ -30,4 +30,4 @@ jobs:
# Label the issue with the appropriate org using supersetbot
# - this requires for the author to be publicly associated with their org
# - and for the org to be listed in `supersetbot/src/metadata.js`
supersetbot orglabel --issue ${{ github.event.number }} --repo ${{ github.repository }} || true
supersetbot orglabel --issue ${{ github.event.number || github.event.issue.number }} --repo ${{ github.repository }} || true
@@ -0,0 +1,54 @@
name: Label Merge Conflicts
# Sweeps every open PR and labels the ones GitHub reports as CONFLICTING with
# `requires:rebase` (removing it once a rebase makes the PR mergeable again),
# so the label can be used to filter the PR backlog for the ones that need a
# rebase before they can be reviewed/merged.
#
# The action itself always re-checks *every* open PR via GraphQL on each run
# regardless of what triggered it (see eps1lon/actions-label-merge-conflict's
# sources/main.ts) - there's no way to scope it to "just this PR". The
# project's own README suggests triggering on `push` (to the default branch)
# plus `pull_request_target: [synchronize]`, but on a repo with Superset's PR
# volume that combination would re-sweep the entire open-PR list on every
# merge to master *and* every push to *any* open PR - many times an hour.
# A schedule bounds that to a fixed, predictable cadence instead; adjust it
# if 2 hours turns out to be too slow or too chatty in practice.
on:
schedule:
- cron: "0 */2 * * *"
workflow_dispatch:
# Avoid two full backlog sweeps racing (a manual workflow_dispatch landing
# mid-schedule-tick, say); queue rather than cancel so an in-progress
# paginated sweep always runs to completion.
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions: {}
jobs:
label-merge-conflicts:
# Scheduled/dispatch workflows still run on forks that carry this file;
# skip anywhere but the canonical repo.
if: github.repository == 'apache/superset'
name: Label Merge Conflicts
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # to add/remove requires:rebase and need:merge
steps:
# ASF Infra allowlists this whole action via a wildcard
# (eps1lon/actions-label-merge-conflict@*), so any pinned SHA/version
# is already fine here - no Infra ticket needed for future bumps.
- uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0
with:
dirtyLabel: "requires:rebase"
# A conflicting PR isn't actually ready to merge; strip that signal
# if it was previously set so reviewers don't act on a stale one.
removeOnDirtyLabel: "need:merge"
repoToken: ${{ secrets.GITHUB_TOKEN }}
# Intentionally no commentOnDirty/commentOnClean: the label alone is
# the signal (matches the label's existing description, and avoids
# a one-time comment storm across the whole backlog on first run).
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
with:
+1 -1
View File
@@ -6,7 +6,7 @@ on:
jobs:
latest-release:
name: Add/update tag to new release
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
permissions:
contents: write
+2 -2
View File
@@ -15,7 +15,7 @@ concurrency:
jobs:
license_check:
name: License Check
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -23,7 +23,7 @@ jobs:
persist-credentials: false
submodules: recursive
- name: Setup Java
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: "temurin"
java-version: "11"
+113
View File
@@ -0,0 +1,113 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Mirror the Docker Hub service-container images that CI relies on into the
# repository's GitHub Container Registry (GHCR) namespace.
#
# WHY: CI jobs declare Postgres/MySQL/Redis/Presto as `services:` containers
# pulled anonymously from Docker Hub. Anonymous pulls share the runner's IP
# rate limit, which causes intermittent timeouts / 429s / 502s on `master`
# and same-repo PRs. The obvious fix — adding `credentials:` to the service
# blocks — breaks fork PRs hard: forks can't read secrets, so the templated
# username/password resolve to '' and GitHub rejects the workflow at parse
# time ("Unexpected value ''"), failing every fork job at "Set up job".
#
# Mirroring to GHCR sidesteps both problems: public GHCR images are pulled
# without Docker Hub's anonymous rate limit AND without any credentials, so
# the consuming workflows need no `credentials:` block and forks work
# unchanged.
#
# ONE-TIME BOOTSTRAP (maintainer, after this lands on the default branch):
# 1. Run this workflow once (Actions tab → "Mirror service images to GHCR"
# → Run workflow), or wait for the weekly schedule.
# 2. In the org's Packages settings, set each mirrored package's visibility
# to **public** (apache/superset → ci/postgres, ci/mysql, ci/redis,
# ci/presto). Public visibility is what lets fork CI pull without auth.
# 3. Only then merge the follow-up that repoints the `services.*.image`
# refs at these GHCR copies and drops the `credentials:` blocks.
#
# NOTE: this mirrors only the images declared as `services:` containers (the
# ones that broke forks). The `bde2020` hive-metastore image pulled via
# `docker compose` in the Presto/Hive job is a separate path and is left for
# a follow-up.
name: Mirror service images to GHCR
on:
schedule:
# Weekly, Monday 06:00 UTC — keeps the mirror fresh as upstream tags move.
- cron: "0 6 * * 1"
workflow_dispatch: {}
concurrency:
group: mirror-service-images
cancel-in-progress: false
permissions:
contents: read
packages: write
jobs:
mirror:
# Never run on forks: they lack both the secrets and write access to the
# apache GHCR namespace, so a scheduled run there would only ever fail.
if: github.repository == 'apache/superset'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Keep this list in sync with the `services.*.image` refs in
# superset-e2e.yml, superset-python-integrationtest.yml, and
# superset-python-presto-hive.yml.
image:
- postgres:17-alpine
- redis:7-alpine
- mysql:8.0
- starburstdata/presto:350-e.6
steps:
- name: Log in to Docker Hub (authenticated source pulls)
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GHCR (push target)
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Copy image to GHCR
env:
# Pass the matrix value through the environment rather than
# interpolating it into the shell, to avoid template injection.
SRC_IMAGE: ${{ matrix.image }}
run: |
set -euo pipefail
# Destination keeps the image's short name (drop any namespace),
# under a `ci/` prefix in this repo's GHCR namespace.
name="${SRC_IMAGE##*/}"
dst="ghcr.io/${GITHUB_REPOSITORY}/ci/${name}"
echo "Mirroring docker.io/${SRC_IMAGE} -> ${dst}"
# imagetools copies the full (multi-arch) manifest registry-to-
# registry without a local pull/retag/push round trip.
docker buildx imagetools create --tag "${dst}" "docker.io/${SRC_IMAGE}"
echo "- \`docker.io/${SRC_IMAGE}\` → \`${dst}\`" >> "${GITHUB_STEP_SUMMARY}"
+1 -1
View File
@@ -17,7 +17,7 @@ concurrency:
jobs:
check-hold-label:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- name: Check for 'hold' label
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
+1 -1
View File
@@ -21,7 +21,7 @@ concurrency:
jobs:
lint-check:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
permissions:
contents: read
pull-requests: write
+10
View File
@@ -15,6 +15,7 @@ on:
permissions:
contents: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
@@ -188,3 +189,12 @@ jobs:
echo "📖 More details here: https://superset.apache.org/docs/contributing/development#git-hooks"
exit 1
fi
actions-timeline:
needs: pre-commit
if: always()
runs-on: ubuntu-26.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+1 -1
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
config:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -108,8 +108,18 @@ jobs:
fetch-depth: 0
persist-credentials: false
# Keep workflow tooling on the triggering revision. Release tags can
# contain action pins that no longer satisfy the repository allowlist.
- name: Checkout workflow actions
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
path: workflow-source
persist-credentials: false
sparse-checkout: .github/actions
- name: Setup Docker Environment
uses: ./.github/actions/setup-docker
uses: ./workflow-source/.github/actions/setup-docker
with:
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -122,7 +132,7 @@ jobs:
node-version: 20
- name: Setup supersetbot
uses: ./.github/actions/setup-supersetbot/
uses: ./workflow-source/.github/actions/setup-supersetbot/
- name: Rebuild and push
env:
@@ -171,7 +181,7 @@ jobs:
--repo "$REPOSITORY" \
--title "Scheduled Docker image refresh failed for ${LATEST_RELEASE}" \
--label "infra:container" \
--label "bug" \
--label "#bug" \
--body "The weekly Docker base-image refresh failed for release \`${LATEST_RELEASE}\`. Published images may be missing upstream base-layer security patches until this is resolved.
Failed run: ${RUN_URL}"
+5
View File
@@ -11,6 +11,7 @@ on:
permissions:
contents: read
pull-requests: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
@@ -40,6 +41,10 @@ jobs:
ports:
- 16379:6379
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
+6 -1
View File
@@ -30,6 +30,7 @@ concurrency:
permissions:
contents: read
actions: read
jobs:
config:
@@ -59,6 +60,10 @@ jobs:
name: Build & Deploy
runs-on: ubuntu-26.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.event.workflow_run.head_sha || github.sha }}"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
@@ -71,7 +76,7 @@ jobs:
node-version-file: "./docs/.nvmrc"
- name: Setup Python
uses: ./.github/actions/setup-backend/
- uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
- uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: "zulu"
java-version: "21"
+46 -31
View File
@@ -21,8 +21,8 @@ permissions:
contents: read
jobs:
linkinator:
# See docs here: https://github.com/marketplace/actions/linkinator
lychee:
# See docs here: https://github.com/lycheeverse/lychee-action
# Only run on pull_request, not workflow_run
if: github.event_name == 'pull_request'
name: Link Checking
@@ -31,37 +31,52 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Do not bump this linkinator-action version without opening
# an ASF Infra ticket to allow the new version first!
- uses: JustinBeckwith/linkinator-action@af984b9f30f63e796ae2ea5be5e07cb587f1bbd9 # v2.3
# Restores the on-disk request cache (.lycheecache) lychee writes when
# `--cache` is set, so re-runs don't re-check every external link from
# scratch. Key never matches exactly (github.run_id is unique per run),
# so actions/cache always saves a fresh copy afterwards; restore-keys
# falls back to the most recent prior cache on lookup.
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .lycheecache
key: lychee-cache-${{ github.run_id }}
restore-keys: lychee-cache-
# v2.8.0 and v2.9.0 are both on ASF Infra's action allowlist
# (apache/infrastructure-actions approved_patterns.yml) as of this
# writing. Do not bump past v2.9.0 without opening an Infra ticket
# to allow the new SHA first!
- uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
with:
paths: "**/*.md, **/*.mdx"
linksToSkip: >-
^https://github.com/apache/(superset|incubator-superset)/(pull|issues)/\d+,
^https://github.com/apache/(superset|incubator-superset)/commit/[a-f0-9]+,
superset-frontend/.*CHANGELOG\.md,
http://localhost:8088/,
http://127.0.0.1:3000/,
http://localhost:9001/,
https://charts.bitnami.com/bitnami,
https://www.li.me/,
https://www.fanatics.com/,
https://tails.com/gb/,
https://www.techaudit.info/,
https://avetilearning.com/,
https://www.udemy.com/,
https://trustmedis.com/,
http://theiconic.com.au/,
https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html,
^https://img\.shields\.io/.*,
https://vkusvill.ru/,
https://www.linkedin.com/in/mark-thomas-b16751158/,
https://theiconic.com.au/,
https://wattbewerb.de/,
https://timbr.ai/,
https://opensource.org/license/apache-2-0,
https://www.plaidcloud.com/
fail: false
args: >-
--verbose --no-progress
--cache --max-cache-age 7d
--exclude '^https://github.com/apache/(superset|incubator-superset)/(pull|issues)/\d+'
--exclude '^https://github.com/apache/(superset|incubator-superset)/commit/[a-f0-9]+'
--exclude 'superset-frontend/.*CHANGELOG\.md'
--exclude 'http://localhost:8088/'
--exclude 'http://127.0.0.1:3000/'
--exclude 'http://localhost:9001/'
--exclude 'https://charts.bitnami.com/bitnami'
--exclude 'https://www.li.me/'
--exclude 'https://www.fanatics.com/'
--exclude 'https://tails.com/gb/'
--exclude 'https://www.techaudit.info/'
--exclude 'https://avetilearning.com/'
--exclude 'https://www.udemy.com/'
--exclude 'https://trustmedis.com/'
--exclude 'http://theiconic.com.au/'
--exclude 'https://dev.mysql.com/doc/refman/5.7/en/innodb-limits.html'
--exclude '^https://img\.shields\.io/.*'
--exclude 'https://vkusvill.ru/'
--exclude 'https://www.linkedin.com/in/mark-thomas-b16751158/'
--exclude 'https://theiconic.com.au/'
--exclude 'https://wattbewerb.de/'
--exclude 'https://timbr.ai/'
--exclude 'https://opensource.org/license/apache-2-0'
--exclude 'https://www.plaidcloud.com/'
'./**/*.md' './**/*.mdx'
build-on-pr:
# Build docs when PR changes docs/** (uses committed databases.json)
+28 -10
View File
@@ -57,19 +57,13 @@ jobs:
pull-requests: read
strategy:
# when one test fails, DO NOT cancel the other
# parallel_id, because this will kill Cypress processes
# app_root variant, because this will kill Cypress processes
# leaving the Dashboard hanging ...
# https://github.com/cypress-io/github-action/issues/48
fail-fast: false
matrix:
parallel_id: [0, 1]
browser: ["chrome"]
app_root: ${{ github.event_name == 'push' && fromJSON('["", "/app/prefix"]') || fromJSON('[""]') }}
# The /app/prefix variant (push events only) is smoke-tested on a single
# shard rather than the full matrix, so exclude it from the other shards.
exclude:
- parallel_id: 1
app_root: "/app/prefix"
env:
SUPERSET_ENV: development
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -148,8 +142,6 @@ jobs:
uses: ./.github/actions/cached-dependencies
env:
CYPRESS_BROWSER: ${{ matrix.browser }}
PARALLEL_ID: ${{ matrix.parallel_id }}
PARALLELISM: 2
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
NODE_OPTIONS: "--max-old-space-size=4096"
with:
@@ -167,7 +159,7 @@ jobs:
if: failure()
with:
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
playwright-tests:
needs: changes
@@ -264,6 +256,21 @@ jobs:
NODE_OPTIONS: "--max-old-space-size=4096"
with:
run: playwright-run "${{ matrix.app_root }}"
- name: Run Playwright (Soft-delete Tests)
uses: ./.github/actions/cached-dependencies
env:
NODE_OPTIONS: "--max-old-space-size=4096"
# Scoped to this step: each playwright-run boots its own gunicorn
# with the step's env, so the Required Tests server above keeps
# master's Flask configuration while this one runs with SOFT_DELETE
# on — the same isolation pattern as the Embedded step in
# superset-playwright.yml. Without a flag-on server the
# recently-archived specs skip themselves everywhere and ship zero
# executed E2E coverage; in the Required run above they are
# collected and skipped, which is expected.
SUPERSET_FEATURE_SOFT_DELETE: "true"
with:
run: playwright-run "${{ matrix.app_root }}" recently-archived/
- name: Set safe app root
if: failure()
id: set-safe-app-root
@@ -340,3 +347,14 @@ jobs:
exit 1
fi
echo "playwright-tests result: $RESULT (changes: $CHANGES)"
actions-timeline:
needs: [cypress-matrix, playwright-tests, cypress-matrix-required, playwright-tests-required]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -11,6 +11,7 @@ on:
permissions:
contents: read
pull-requests: read
actions: read
# cancel previous workflow jobs for PRs
concurrency:
@@ -69,3 +70,12 @@ jobs:
with:
name: superset-extensions-cli-coverage-html
path: htmlcov/
actions-timeline:
needs: test-superset-extensions-cli-package
if: always()
runs-on: ubuntu-26.04
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+19 -2
View File
@@ -23,6 +23,12 @@ jobs:
frontend-build:
runs-on: ubuntu-26.04
timeout-minutes: 30
# The change detector reads the PR's file list, which needs
# `pull-requests: read`. Public repos serve that endpoint without it;
# private forks return 403.
permissions:
contents: read
pull-requests: read
outputs:
should-run: ${{ steps.check.outputs.frontend }}
steps:
@@ -171,10 +177,10 @@ jobs:
run: |
zstd -d < docker-image.tar.zst | docker load
- name: Build Plugins Packages
- name: Validate dependency tree
run: |
docker run --rm $TAG bash -c \
"npm run plugins:build"
"npm ls --all --package-lock-only --depth=0 --json > /dev/null"
test-storybook:
needs: frontend-build
@@ -195,3 +201,14 @@ jobs:
run: |
docker run --rm $TAG bash -c \
"npm run build-storybook && npx playwright install-deps && npx playwright install chromium && npm run test-storybook:ci"
actions-timeline:
needs: [report-coverage, lint-frontend, validate-frontend, test-storybook]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+11 -1
View File
@@ -8,6 +8,7 @@ on:
permissions:
contents: read
actions: read
# Serialize runs per PR without cancelling: when a first-time contributor's
# queued runs are approved together, cancel-in-progress lets an older run
@@ -19,8 +20,12 @@ concurrency:
jobs:
lint-test:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
@@ -38,6 +43,11 @@ jobs:
with:
install-superset: "false"
# Still vendored (not de-vendored like chart-releaser-action below): the
# allowlisted helm/chart-testing-action@v2.8.0 depends internally on
# astral-sh/setup-uv@v7.0.0, which isn't itself on the ASF Actions
# allowlist (only v8.1.0+ are, at apache/infrastructure-actions'
# actions.yml). Needs an INFRA request before this can de-vendor too.
- name: Set up chart-testing
uses: ./.github/actions/chart-testing-action
+83 -17
View File
@@ -1,6 +1,9 @@
# This workflow automates the release process for Helm charts.
# The workflow creates a new branch for the release and opens a pull request against the 'gh-pages' branch,
# allowing the changes to be reviewed and merged manually.
# Each run force-recreates a single 'helm-publish' branch from the tip of 'gh-pages' and
# opens (or reuses) one pull request against 'gh-pages', allowing the changes to be
# reviewed and merged manually. Because chart-releaser rebuilds index.yaml from all
# published GitHub releases, the branch always contains every chart released since the
# last merge, and the PR can never go stale or conflict with gh-pages.
name: "Helm: release charts"
@@ -18,6 +21,12 @@ on:
required: false
default: "master"
# Serialize runs: concurrent runs would race on force-pushing the shared
# helm-publish branch while chart-releaser is mid-release.
concurrency:
group: helm-release
cancel-in-progress: false
jobs:
release:
runs-on: ubuntu-26.04
@@ -57,9 +66,9 @@ jobs:
echo "DEBUG TAGS"
git show-ref --tags
- name: Create unique pages branch name
- name: Set pages branch name
id: vars
run: echo "branch_name=helm-publish-${GITHUB_SHA:0:7}" >> $GITHUB_ENV
run: echo "branch_name=helm-publish" >> $GITHUB_ENV
- name: Force recreate branch from gh-pages
env:
@@ -86,23 +95,23 @@ jobs:
# Return to the original branch
git checkout local_gha_temp
- name: Fetch/list all tags
run: |
git submodule update
cat .github/actions/chart-releaser-action/action.yml
- name: Run chart-releaser
uses: ./.github/actions/chart-releaser-action
uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
with:
version: v1.6.0
charts_dir: helm
mark_as_latest: false
# A helm/** change without a Chart.yaml version bump repackages the
# already-released version; without this, cr aborts on the existing
# release tag (422 already_exists) instead of proceeding to rebuild
# the index, and the whole run fails.
skip_existing: true
pages_branch: ${{ env.branch_name }}
env:
CR_TOKEN: "${{ github.token }}"
CR_RELEASE_NAME_TEMPLATE: "superset-helm-chart-{{ .Version }}"
- name: Open Pull Request
- name: Open or reuse Pull Request
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
@@ -113,15 +122,72 @@ jobs:
throw new Error("Branch name is not defined.");
}
const pr = await github.rest.pulls.create({
// The branch is force-recreated from gh-pages on every run, so an
// already-open PR for it now reflects this run's charts; opening
// another would both fail (422) and recreate the stale-PR pileup
// this fixed branch exists to avoid.
const { data: existing } = await github.rest.pulls.list({
owner,
repo,
title: `Helm chart release for ${branchName}`,
head: branchName,
base: "gh-pages", // Adjust if the target branch is different
body: `This PR releases Helm charts to the gh-pages branch.`,
state: "open",
head: `${owner}:${branchName}`,
base: "gh-pages",
});
core.info(`Pull request created: ${pr.data.html_url}`);
let current;
if (existing.length > 0) {
current = existing[0];
core.info(`Reusing existing pull request: ${current.html_url}`);
} else {
const { data: pr } = await github.rest.pulls.create({
owner,
repo,
title: "Helm chart release",
head: branchName,
base: "gh-pages", // Adjust if the target branch is different
body: [
"This PR releases Helm charts to the gh-pages branch.",
"",
"It is force-updated from the tip of `gh-pages` by every release run,",
"so it always contains every chart released since the last merge and",
"never needs to be closed as superseded.",
].join("\n"),
});
current = pr;
core.info(`Pull request created: ${current.html_url}`);
}
// Sweep release PRs left open by older runs (per-SHA helm-publish-*
// branches from the previous scheme). Their content is a subset of
// the evergreen PR, so close them with a pointer to it.
const { data: openPrs } = await github.rest.pulls.list({
owner,
repo,
state: "open",
base: "gh-pages",
per_page: 100,
});
for (const stale of openPrs) {
if (
stale.number !== current.number &&
stale.head.repo?.full_name === process.env.GITHUB_REPOSITORY &&
stale.head.ref.startsWith("helm-publish")
) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: stale.number,
body: `Superseded by #${current.number}, which now carries all unreleased charts. Closing.`,
});
await github.rest.pulls.update({
owner,
repo,
pull_number: stale.number,
state: "closed",
});
core.info(`Closed superseded release PR #${stale.number}`);
}
}
env:
BRANCH_NAME: ${{ env.branch_name }}
+11
View File
@@ -170,3 +170,14 @@ jobs:
${{ github.workspace }}/superset-frontend/playwright-results/
${{ github.workspace }}/superset-frontend/test-results/
name: playwright-experimental-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
actions-timeline:
needs: playwright-tests-experimental
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -255,3 +255,14 @@ jobs:
exit 1
fi
echo "test-postgres result: $RESULT"
actions-timeline:
needs: [test-mysql, test-postgres, test-sqlite, test-postgres-required]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -158,3 +158,14 @@ jobs:
verbose: true
use_oidc: true
slug: apache/superset
actions-timeline:
needs: [test-postgres-presto, test-postgres-hive]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
@@ -101,7 +101,14 @@ jobs:
if: always()
runs-on: ubuntu-26.04
timeout-minutes: 5
permissions:
contents: read
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
- name: Check unit-tests result
env:
RESULT: ${{ needs.unit-tests.result }}
@@ -153,3 +153,14 @@ jobs:
- name: Fail if regression detected
if: steps.regression.outcome == 'failure'
run: exit 1
actions-timeline:
needs: [frontend-check-translations, babel-extract]
if: always()
runs-on: ubuntu-26.04
permissions:
actions: read
steps:
- uses: Kesin11/actions-timeline@57fc93f20c6da7fbc14063c6d24a2a5627c799ad # v3.2.0
with:
expand-composite-actions: true
+3 -3
View File
@@ -21,7 +21,7 @@ concurrency:
jobs:
app-checks:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
timeout-minutes: 20
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
@@ -41,9 +41,9 @@ jobs:
- name: typescript checks
working-directory: ./superset-websocket
run: npm run type
- name: prettier
- name: code format check
working-directory: ./superset-websocket
run: npm run prettier-check
run: npm run format-check
- name: unit tests
working-directory: ./superset-websocket
run: npm run test
@@ -38,7 +38,7 @@ jobs:
- name: Login to Docker Hub
if: ${{ steps.dependabot-metadata.outputs.package-ecosystem == 'pip' }}
continue-on-error: true
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+1 -1
View File
@@ -32,7 +32,7 @@ concurrency:
jobs:
config:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
+2 -2
View File
@@ -11,7 +11,7 @@ permissions:
jobs:
config:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
@@ -28,7 +28,7 @@ jobs:
process-and-upload:
needs: config
if: needs.config.outputs.has-secrets
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
name: Generate Reports
steps:
- name: Checkout Repository
+1 -1
View File
@@ -7,7 +7,7 @@ on:
jobs:
welcome:
runs-on: ubuntu-26.04
runs-on: ubuntu-slim
if: github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
permissions:
pull-requests: write
+1
View File
@@ -138,6 +138,7 @@ PROJECT.md
.aider*
.claude_rc*
.claude/settings.local.json
.claude/worktrees/
.env.local
oxc-custom-build/
*.code-workspace
-3
View File
@@ -30,9 +30,6 @@
[submodule ".github/actions/chart-testing-action"]
path = .github/actions/chart-testing-action
url = https://github.com/helm/chart-testing-action
[submodule ".github/actions/chart-releaser-action"]
path = .github/actions/chart-releaser-action
url = https://github.com/helm/chart-releaser-action
[submodule ".github/actions/github-action-push-to-another-repository"]
path = .github/actions/github-action-push-to-another-repository
url = https://github.com/cpina/github-action-push-to-another-repository
+3 -3
View File
@@ -62,9 +62,9 @@ repos:
args: ["--markdown-linebreak-ext=md"]
- repo: local
hooks:
- id: prettier-frontend
name: prettier (frontend)
entry: bash -c 'cd superset-frontend && files=(); for f in "$@"; do files+=("${f#superset-frontend/}"); done; npx prettier --write -- "${files[@]}"' --
- id: oxfmt-frontend
name: oxfmt (frontend)
entry: bash -c 'cd superset-frontend && files=(); for f in "$@"; do files+=("${f#superset-frontend/}"); done; npx oxfmt --write --no-error-on-unmatched-pattern -- "${files[@]}"' --
language: system
pass_filenames: true
files: ^superset-frontend/.*\.(js|jsx|ts|tsx|css|scss|sass|json)$
-2
View File
@@ -10,7 +10,6 @@
.stylelintignore
.flake8
.nvmrc
.prettierrc
.rat-excludes
.swcrc
.*log
@@ -64,7 +63,6 @@ tsconfig.tsbuildinfo
.*yml
.*iml
.esprintrc
.prettierignore
generator-superset/*
temporary_superset_ui/*
+13 -6
View File
@@ -2,24 +2,31 @@
Apache Superset is a data visualization platform with Flask/Python backend and React/TypeScript frontend.
## ⚠️ CRITICAL: Always Run Pre-commit Before Pushing
## Run Pre-commit Before Pushing
**ALWAYS run `pre-commit run --all-files` before pushing commits.** CI will fail if pre-commit checks don't pass. This is non-negotiable.
Always run pre-commit against the files changed by the current branch before
pushing. This matches CI and keeps unrelated failures already present on
`master` from blocking otherwise independent work.
```bash
# Stage your changes first
git add .
# Run pre-commit on all files
pre-commit run --all-files
# Run pre-commit on staged files
pre-commit run
# If there are auto-fixes, stage them and commit
git add .
git commit --amend # or new commit
```
Use `pre-commit run --all-files` when auditing or repairing the repository-wide
baseline. If that check finds failures in files untouched by the current branch,
fix them in a separate branch rather than adding unrelated changes to the
current pull request.
Common pre-commit failures:
- **Formatting** - black, prettier, eslint will auto-fix
- **Formatting** - black, oxfmt, eslint will auto-fix
- **Type errors** - mypy failures need manual fixes
- **Linting** - ruff, pylint issues need manual fixes
@@ -263,7 +270,7 @@ git add . # Pre-commit only checks staged files
# Quick validation (faster than --all-files)
pre-commit run # Staged files only
pre-commit run mypy # Python type checking
pre-commit run prettier # Code formatting
pre-commit run format # Code formatting
pre-commit run eslint # Frontend linting
```
+1 -1
View File
@@ -95,7 +95,7 @@ py-format: pre-commit
pre-commit run black --all-files
js-format:
cd superset-frontend; npm run prettier
cd superset-frontend; npm run format
flask-app:
flask run -p 8088 --reload --debugger
+2 -2
View File
@@ -29,7 +29,7 @@ under the License.
[![Last Commit](https://img.shields.io/github/last-commit/apache/superset)](https://github.com/apache/superset/commits/master)
[![Open Issues](https://img.shields.io/github/issues/apache/superset)](https://github.com/apache/superset/issues)
[![Open PRs](https://img.shields.io/github/issues-pr/apache/superset)](https://github.com/apache/superset/pulls)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](http://bit.ly/join-superset-slack)
[![Get on Slack](https://img.shields.io/badge/slack-join-orange.svg)](https://bit.ly/join-superset-slack)
[![Documentation](https://img.shields.io/badge/docs-apache.org-blue.svg)](https://superset.apache.org)
<picture width="500">
@@ -186,7 +186,7 @@ Try out Superset's [quickstart](https://superset.apache.org/docs/quickstart/) gu
## Get Involved
- Ask and answer questions on [StackOverflow](https://stackoverflow.com/questions/tagged/apache-superset) using the **apache-superset** tag
- [Join our community's Slack](http://bit.ly/join-superset-slack)
- [Join our community's Slack](https://bit.ly/join-superset-slack)
and please read our [Slack Community Guidelines](https://github.com/apache/superset/blob/master/CODE_OF_CONDUCT.md#slack-community-guidelines)
- [Join our dev@superset.apache.org Mailing list](https://lists.apache.org/list.html?dev@superset.apache.org). To join, simply send an email to [dev-subscribe@superset.apache.org](mailto:dev-subscribe@superset.apache.org)
- Follow us on social media:
+1 -1
View File
@@ -423,7 +423,7 @@ git push origin ${SUPERSET_VERSION}
### Publishing a Convenience Release to PyPI
Extract the release to the `/tmp` folder to build the PiPY release. Files in the `/tmp` folder will be automatically deleted by the OS.
Extract the release to the `/tmp` folder to build the PyPI release. Files in the `/tmp` folder will be automatically deleted by the OS.
```bash
mkdir -p /tmp/superset && cd /tmp/superset
+2 -2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -15,8 +17,6 @@
# specific language governing permissions and limitations
# under the License.
#!/bin/bash
# Function to determine Python command
get_python_command() {
if command -v python3 &>/dev/null; then
+301 -35
View File
@@ -24,6 +24,181 @@ assists people when migrating to a new version.
## Next
- [42935](https://github.com/apache/superset/pull/42935): The MCP service now refuses to start (`MCPAuthConfigError`) when `MCP_JWT_ISSUER` trusts more than one issuer and no `MCP_USER_RESOLVER` is configured, instead of only logging a warning. This was already a documented misconfiguration (the default resolver isn't issuer-scoped, so distinct trusted issuers minting the same username/email would resolve to the same Superset user); deployments trusting multiple issuers must configure an `MCP_USER_RESOLVER` that derives its identity from the token's `iss` claim before upgrading. Single-issuer deployments are unaffected.
- [42393](https://github.com/apache/superset/pull/42393): Exported dataset YAML now carries a `uuid` for each metric and column so that custom folder assignments (which reference metrics/columns by UUID) survive an import into another workspace. This affects any export bundle that contains datasets, not just a dataset export: chart, dashboard, database and full-asset exports all embed the same dataset YAML, so a dashboard exported from this release also fails to import into an older one even though no dataset was exported directly. As with `folders` and `currency_code_column`, the affected `datasets/` files fail schema validation (`Unknown field: uuid`) when imported into Superset releases that predate this change; regenerate or hand-edit exports for older targets in mixed-version fleets.
- [42087](https://github.com/apache/superset/pull/42087): Stored calculated-column and metric expressions are validated when a query is built, under the same sub-query policy already applied to adhoc expressions. Previously only the dataset update path checked them on save, so expressions written by v1 import, by dataset duplication, or before that check existed were never validated. Since `ALLOW_ADHOC_SUBQUERY` defaults to `False` (see [19242](https://github.com/apache/superset/pull/19242)), a dataset whose stored expression contains a sub-query works before upgrading and afterwards fails at chart render with `Custom SQL fields cannot contain sub-queries.` There is no migration step, and the error does not name the offending dataset column, so audit stored expressions before upgrading: either rewrite them without the sub-query, or set `ALLOW_ADHOC_SUBQUERY = True` to keep the previous behaviour for both stored and adhoc expressions.
### Selenium support removed — Playwright is now required for screenshots
Selenium support has been removed. **Playwright is now required** for all
report and thumbnail screenshot generation. Install it with:
```bash
pip install playwright && playwright install chromium
```
**Breaking config changes:**
- `PLAYWRIGHT_REPORTS_AND_THUMBNAILS` feature flag removed (Playwright is the only backend now)
- `WEBDRIVER_TYPE` config key removed (Playwright always uses Chromium)
- `WEBDRIVER_CONFIGURATION` config key removed (Selenium-only)
- `SCREENSHOT_PAGE_LOAD_WAIT` config key removed (Selenium-only)
- `SCREENSHOT_SELENIUM_RETRIES` config key removed (Selenium-only)
- `SCREENSHOT_WAIT_FOR_ERROR_MODAL_VISIBLE` config key removed (Selenium-only)
- `SCREENSHOT_WAIT_FOR_ERROR_MODAL_INVISIBLE` config key removed (Selenium-only)
- `MachineAuthProvider.authenticate_webdriver()` removed; use `authenticate_browser_context()` instead
**What operators should do before upgrading:**
1. Install Playwright: `pip install playwright && playwright install chromium`
2. Remove any references to the removed config keys from custom `superset_config.py`
3. If you subclassed `MachineAuthProvider`, remove any `authenticate_webdriver` override and migrate auth logic to `authenticate_browser_context`
### Soft delete is on by default, and purging is live
`SOFT_DELETE` now ships **on** (`DEFAULT_FEATURE_FLAGS`), so deleting a
dashboard, chart, or dataset archives it rather than removing it. Archived
objects are hidden from normal listings, recoverable from **Recently Archived**,
and permanently removed once the retention window elapses.
`SOFT_DELETE_PURGE_DRY_RUN` also flips to `False`, so the nightly
`deletion_retention.purge_soft_deleted` task deletes for real instead of only
logging `would_purge` counts.
**What operators should do before upgrading:**
- **Size the first live purge.** The first real run removes every entity that
aged past `SOFT_DELETE_RETENTION_DAYS` (default 30) since soft delete began
capturing, which on a busy deployment can be a large batch in one window. To
see the size first, set `SOFT_DELETE_PURGE_DRY_RUN = True`, read the
`would_purge` counts from one nightly run, then set it back.
- **Check a replaced `CELERY_CONFIG`.** A deployment that redefines it rather
than inheriting must carry both `superset.tasks.deletion_retention` in
`imports` and the `deletion_retention.purge_soft_deleted` beat entry;
a startup warning now names whichever is absent.
**Both switches are retained.** `SOFT_DELETE = False` restores hard-delete
behaviour and `SOFT_DELETE_PURGE_DRY_RUN = True` suspends purging, at any time.
One caveat on turning soft delete back off: objects archived while it was on are
**resurrected** into normal listings, since the rows were never removed — an
emergency stop rather than a clean rollback.
### Version history is on by default
`VERSION_HISTORY` and `ENABLE_VERSIONING_CAPTURE` now both ship **on**. Every
save of a chart, dashboard, or dataset writes version rows, and the version
history panel appears on Explore and Dashboard pages. The two flip together
deliberately: a panel with capture off renders an empty "No history yet" that
misrepresents the entity as unchanged.
**What operators should expect:**
- **Storage growth.** Capture writes shadow rows per save, so the metadata
database grows with edit volume. The `version_history.prune_old_versions`
beat task removes rows whose transaction is older than
`SUPERSET_VERSION_HISTORY_RETENTION_DAYS` (default 30). A deployment that
replaces `CELERY_CONFIG` rather than inheriting it must carry both the
`superset.tasks.version_history_retention` import and the beat entry; a
startup warning names whichever is absent.
- **`PUT` responses change shape.** Entity updates now return populated
`old_version_uuid` / `new_version_uuid` fields and an `ETag` header, which
were null or absent while capture was off.
`ENABLE_VERSIONING_CAPTURE` is **retained permanently** as an operational
kill-switch — not removed with the rollout toggles. Setting it to a falsy value
stops capture within a restart, without a revert-and-redeploy. Unlike the
soft-delete toggle, turning it off is a clean stop: existing version rows remain
readable and no entity state is altered.
### Scheduled report execution now enforces one application deadline
Scheduled report (not alert) executions are now governed by a single
end-to-end deadline shared by browser readiness, capture/PDF generation,
notification delivery, and terminal-state persistence, configured via
`ALERT_REPORTS_EXECUTION_BUDGET_SECONDS` (with per-phase reserve settings).
Behavior changes to be aware of:
- The effective budget for a schedule is
`min(ALERT_REPORTS_EXECUTION_BUDGET_SECONDS, working_timeout)`. The default
budget (one hour) matches the historical `working_timeout` model default,
so default installations see no change in how long a report may run —
but reports now fail cleanly (with an error notification) at the deadline
instead of being killed silently by Celery.
- For REPORT schedules, the Celery `soft_time_limit`/`time_limit` are now
derived from that same effective budget plus
`ALERT_REPORTS_EXECUTION_HARD_TIMEOUT_GRACE_SECONDS`, replacing the
previous `working_timeout + ALERT_REPORTS_WORKING_TIME_OUT_LAG` /
`+ ALERT_REPORTS_WORKING_SOFT_TIME_OUT_LAG` derivation. Alert schedules
keep the previous behavior.
- A `working_timeout` smaller than the summed phase reserves is floored at
the minimum viable budget (reserves + 30s) with a warning; such reports
fail fast at the first phase check rather than erroring at setup.
- Dashboard reports whose charts have not mounted are no longer captured
blank: readiness is polled until the deadline, and the report fails loudly
if charts never mount. Thumbnails and non-report screenshots keep their
previous behavior.
### Embedded (guest token) API responses no longer echo database errors
API responses served to a guest-token principal now carry a generic
`An error occurred while fetching the data.` in place of the underlying error
(`You don't have permission to access this resource.` on a 401/403), and drop
the `stacktrace` and error `extra` payloads. Engine errors routinely quote
catalog, schema, table and column names of the warehouse, which embedded
viewers should not see. Errors Superset authors itself — access denials, OAuth2
redirects, timeouts, payload validation — keep their message and type, though
their `extra` is still reduced to the fields the client needs. Responses to
every non-guest principal are unchanged, and the full error is still logged
server-side.
### `UnsavedChangesModal` no longer accepts a `zIndex` prop
`@superset-ui/core`'s `UnsavedChangesModal` dropped its `zIndex` prop (and the
hardcoded default it fed) in favor of letting Ant Design's own stacking
handle placement. Callers passing `zIndex` to override the modal's layering
will now get a TypeScript error and must remove the prop; keeping a manual
override was exactly the footgun this change removes (see #42510). No
callers in the Superset frontend codebase itself passed this prop.
### Principal listing APIs now honour related-field filters
Two authorization-related listing behaviors changed for API clients. Neither
affects the Superset UI — `include_ids` and `security/subject` have no frontend
callers — but external clients will notice:
- `GET /api/v1/<resource>/related/<column>?include_ids=...` now applies the
endpoint's `base_related_field_filters`. Previously the forced IDs were fetched
with no filtering, so a caller could resolve principals the related-field
filters deliberately hide; those IDs are now omitted from the response.
- `GET /api/v1/security/subject/` now honours `EXCLUDE_USERS_FROM_LISTS` and
`EXTRA_RELATED_QUERY_FILTERS`, matching every other principal-listing endpoint.
List counts may drop, and fetching an excluded principal via
`GET /api/v1/security/subject/<id>` now returns `404`.
### v1 chart import no longer re-adds the importer as editor on overwrite
Re-importing over an existing chart (an overwrite or a soft-delete restore) no
longer appends the importing user to the chart's `editors`, matching the
dashboard importer's behavior. This changes anything only for a user who was not
already an editor of that chart — typically an admin overwriting a chart they do
not own, who was previously added as an editor as a side effect of the import.
Newly-created charts are unaffected.
### ClickHouse: system sampling queries retry with a bounded read
System-generated sampling queries — filter-value dropdowns, the Samples
tab/dataset preview, and datetime format detection — that ClickHouse rejects
with a `max_rows_to_read` error (`TOO_MANY_ROWS`, code 158) are now retried
once with `SETTINGS read_overflow_mode='break'` appended, so they return a
partial result bounded by the operator's row cap instead of failing. The retry
applies only to statements Superset generates for physical-table datasets;
virtual datasets and user-authored SQL remain fully governed by configured
read limits, and queries that already succeed are never altered. Operators who
rely on `max_rows_to_read` as a hard failure gate for these system queries can
restore the previous behavior per database with
`"disable_sampling_read_limit_override": true` in the database's Extra JSON.
Note that a retried query returns partial data with no truncation indicator
(e.g. a filter dropdown may list only a subset of values on tables above the
row cap).
### Dashboard "Export Data to Excel" requires a Celery worker and S3 bucket
A new dashboard action exports every chart's data to a single multi-sheet
@@ -32,12 +207,24 @@ A new dashboard action exports every chart's data to a single multi-sheet
requires a running Celery worker and a configured SMTP transport, since the task
emails the requesting user a pre-signed download link. New config keys:
`EXCEL_EXPORT_S3_BUCKET`, `EXCEL_EXPORT_S3_KEY_PREFIX`,
`EXCEL_EXPORT_LINK_TTL_SECONDS`, `EXCEL_EXPORT_S3_CLIENT_KWARGS`, and
`EXCEL_EXPORT_TABLE_VIZ_TYPES`.
`EXCEL_EXPORT_LINK_TTL_SECONDS`, `EXCEL_EXPORT_S3_CLIENT_KWARGS`,
`EXCEL_EXPORT_TABLE_VIZ_TYPES`, and `EXCEL_EXPORT_QUERY_CONTEXT_BUILDER`.
The feature depends on `boto3`, which is **not** installed by default; install it
with `pip install apache-superset[excel-export]`.
Charts store their `query_context` only once they have been (re-)saved in
Explore, so older charts may have none. For a fixed, conservative set of viz
types (`table`, `big_number_total`, `big_number`, `pie`) the export rebuilds a
query context from the chart's saved form data so those charts still export.
The rebuild is a single-query mapping and does **not** reproduce plugin
post-processing (pivot, rolling, forecast) or multi-query charts, so any chart of
another type without a saved query context is skipped and listed in the email for
the user to re-save. To cover those types, set `EXCEL_EXPORT_QUERY_CONTEXT_BUILDER`
to a callable that receives the chart's form data and returns a query-context
payload (or `None` to fall back to the built-in rebuild) — for example one backed
by a service that runs the chart's real frontend `buildQuery`.
A second mode, **Export Images to Excel**, embeds non-table charts as rendered
images (which viz types stay tabular is controlled by
`EXCEL_EXPORT_TABLE_VIZ_TYPES`). It renders through the headless webdriver, so the
@@ -193,6 +380,10 @@ are the intended model going forward; deprecating and removing implicit viewersh
in a later major version.
- [41044](https://github.com/apache/superset/issues/41044): Removes the deprecated `AVOID_COLORS_COLLISION` feature flag (it defaulted to `True`). Color-collision avoidance is now permanently enabled; any config override setting it to `False` is ignored.
- [41714](https://github.com/apache/superset/pull/41714): **Breaking — the legacy `explore_json` chart-data pipeline is removed** at its long-declared `5.0.0` EOL. The `/superset/explore_json/` and `/superset/explore_json/data/<cache_key>` endpoints, `superset/viz.py`, the `Slice.viz` property, the `get_viz` factory, the `load_explore_json_into_cache` celery task and the `viz=` overload of `security_manager.raise_for_access` are gone. Anything importing `superset.viz` must migrate to the QueryContext / `pandas_postprocessing` pipeline behind `/api/v1/chart/data`. All 15 remaining legacy charts were migrated first: most keep their `viz_type` and renderer (no action needed for saved charts), while saved nvd3 Bubble charts are auto-migrated to the ECharts Bubble Chart (`bubble_v2`) and saved "Time-series Percent Change" (`compare`) charts to the ECharts Line Chart, which restores the nvd3 renderer's interactive percent re-basing via a draggable baseline. The deck.gl Multiple Layers chart now fetches its layers entirely client-side, refitting the viewport as each layer's data arrives, and caps the number of sub-slices fanned out per chart at `DECK_MULTI_MAX_SLICES` (default 50, configurable); dashboard filter badges no longer aggregate child-layer filter metadata.
- [41714](https://github.com/apache/superset/pull/41714): Charts migrated in place keep a `NULL` saved query context until they are next opened in Explore (which regenerates it automatically) or re-saved. Until then, cache warm-up and annotation layers referencing such a chart report an actionable error rather than warming/rendering; opening the chart once resolves it.
- [41714](https://github.com/apache/superset/pull/41714): **Breaking for third-party viz plugins** — the `useLegacyApi` field of `ChartMetadata` in `@superset-ui/core` is removed. Plugins that set it must provide a `buildQuery` and consume `/api/v1/chart/data`. The migrated first-party packages also drop their `legacy-` prefix: `@superset-ui/legacy-plugin-chart-{calendar,chord,country-map,horizon,paired-t-test,parallel-coordinates,partition,rose,world-map}``@superset-ui/plugin-chart-*`, and `@superset-ui/legacy-preset-chart-nvd3``@superset-ui/preset-chart-nvd3`. The `can_explore_json` permission is no longer created or granted; custom roles referencing it should switch to the `can_read` permissions on `Chart`.
- [41813](https://github.com/apache/superset/pull/41813): `redis` (the Python client, `redis-py`) is bumped from 5.3.1 to 8.0.1. redis-py 8 changes several connection defaults; Superset's own Redis-backed features (`GLOBAL_ASYNC_QUERIES_CACHE_BACKEND`, `DISTRIBUTED_COORDINATION_CONFIG`, and the MCP Redis store) explicitly pin the pre-upgrade behavior so this bump is a no-op for them: the wire protocol stays RESP2 (not the new RESP3 default, which requires Redis/Sentinel 6+ to speak `HELLO`) and there is still no socket timeout by default (redis-py 8 defaults to 5s, which could otherwise newly time out large cached payloads or slow networks). The no-timeout default can now be overridden via two new config keys, `CACHE_REDIS_SOCKET_TIMEOUT` / `CACHE_REDIS_SOCKET_CONNECT_TIMEOUT`, on any `CacheConfig` dict using `CACHE_TYPE: RedisCache` or `RedisSentinelCache`. Separately, redis-py 6+ changed the default for `ssl_check_hostname` from `False` to `True` for SSL connections using `ssl_cert_reqs="required"` (the default) — this is a security improvement, so it has **not** been reverted; deployments with `CACHE_REDIS_SSL=True` whose certificates lack a hostname matching the connection address should set `CACHE_REDIS_SSL_CERT_REQS="none"` (disables cert verification entirely, matching hostname-check bypass) or replace the certificate. General-purpose cache/results backends configured via `CACHE_CONFIG` / `DATA_CACHE_CONFIG` / `RESULTS_BACKEND` with `CACHE_TYPE: RedisCache` go through `flask-caching`'s own Redis backend (outside Superset's code) and are subject to the same new defaults; pass `socket_timeout` / `protocol` via `CACHE_OPTIONS` there if needed. Celery broker and result-backend connections (built by `kombu`, also outside Superset's code) keep their no-socket-timeout behavior (`kombu` passes `socket_timeout=None` explicitly) but do **not** pin the wire protocol, so they follow redis-py's RESP3 default — which requires a Redis server new enough to speak `HELLO` (Redis 6+). Deployments using a pre-6.0 Redis server (EOL) as a Celery broker should upgrade the server before taking this bump.
@@ -212,7 +403,7 @@ in a later major version.
- **`SqlaTable.sql_url` query-string format.** `SqlaTable.sql_url` now URL-encodes `table_name` and joins it as a query parameter rather than concatenating a second `?`. Previously, with `Database.sql_url` returning `/sqllab/?dbid=<id>`, the concatenation produced `/sqllab/?dbid=<id>?table_name=<raw>` — a malformed second `?` that broke the query parser. External code that parsed the legacy `<base>?table_name=<raw>` shape now sees properly percent-encoded values (e.g. `/``%2F`, ` ``+` or `%20`); decode with `urllib.parse.parse_qsl`.
- **New config flag `EMBEDDED_DISABLE_PERMALINK_ORIGIN_REWRITE` (default `False`).** Share/permalink URLs now substitute `window.location.origin` for the backend-supplied origin so a proxied or subdirectory-deployed Superset never hands the user an unreachable internal hostname. Operators whose reverse proxy correctly forwards `X-Forwarded-Host` *and* who want permalinks to carry the backend's literal origin can opt out by setting `EMBEDDED_DISABLE_PERMALINK_ORIGIN_REWRITE = True` in `superset_config.py`. Default `False` (rewrite is on); flipping the default would regress the dominant proxied/subdir deployment to an unreachable host.
- **New config flag `EMBEDDED_DISABLE_PERMALINK_ORIGIN_REWRITE` (default `False`).** Share/permalink URLs now substitute `window.location.origin` for the backend-supplied origin so a proxied or subdirectory-deployed Superset never hands the user an unreachable internal hostname. Operators whose reverse proxy correctly forwards `X-Forwarded-Host` _and_ who want permalinks to carry the backend's literal origin can opt out by setting `EMBEDDED_DISABLE_PERMALINK_ORIGIN_REWRITE = True` in `superset_config.py`. Default `False` (rewrite is on); flipping the default would regress the dominant proxied/subdir deployment to an unreachable host.
- [41651](https://github.com/apache/superset/pull/41651): **New do-not-translate standard for translation catalogs.** Strings that must stay identical to the source — icon names (e.g. `bolt`), enum/option values (`step-after`), SQL keywords, API field names (`error_message`), code constants, and example placeholders — are now marked with a `#. do-not-translate` extracted comment. The list lives in the `superset/translations/do-not-translate.txt` registry; `scripts/translations/apply_do_not_translate.py` stamps the marker onto `messages.pot` during `babel_update.sh`, and `pybabel update` propagates it to every `.po`, so the status is consistent across all languages. The AI backfill (`backfill_po.py`) and translators leave these entries untranslated (source fallback). The legacy per-catalog convention (a `# Не переводить` translator comment in the `ru` catalog) is still honored for back-compat but is superseded by this standard; contributors adding new machine-read strings should add the msgid to the registry rather than annotating individual catalogs.
@@ -249,7 +440,7 @@ Theme tokens are unaffected — antd 6 removed none of the tokens Superset expos
### Guest-token RLS rules reject unknown fields
The `rls` rules passed to `POST /api/v1/security/guest_token/` are now validated strictly: a rule may only contain `dataset` and `clause`. Previously unknown fields were silently dropped, so a mistyped or legacy scope key (most commonly `datasource` instead of `dataset`) produced a rule with no `dataset`, which is treated as a *global* rule applied to every dataset the embedded resource can reach. Such a request now returns HTTP 400 identifying the offending field instead of issuing a token with an unintended global rule. Integrators that were sending extra fields in RLS rules must remove them; valid dataset-scoped (`{"dataset": 41, "clause": "..."}`) and global (`{"clause": "..."}`) rules are unaffected.
The `rls` rules passed to `POST /api/v1/security/guest_token/` are now validated strictly: a rule may only contain `dataset` and `clause`. Previously unknown fields were silently dropped, so a mistyped or legacy scope key (most commonly `datasource` instead of `dataset`) produced a rule with no `dataset`, which is treated as a _global_ rule applied to every dataset the embedded resource can reach. Such a request now returns HTTP 400 identifying the offending field instead of issuing a token with an unintended global rule. Integrators that were sending extra fields in RLS rules must remove them; valid dataset-scoped (`{"dataset": 41, "clause": "..."}`) and global (`{"clause": "..."}`) rules are unaffected.
### MCP service requires `MCP_JWT_AUDIENCE` when JWT auth is enabled
@@ -300,9 +491,23 @@ As a result the per-table **"Aggregation function"** control (which let you pick
how totals were aggregated client-side, e.g. Sum/Average/Count) has been
removed: totals now always reflect the metric's own definition evaluated at the
total's granularity. For additive metrics (`SUM`/`COUNT`/`MIN`/`MAX`) the result
is unchanged. Saved charts that set `aggregateFunction` will ignore it; no
migration is required. If you previously relied on a plain sum-of-cells total
for a non-additive metric, that specific behavior is no longer available.
is unchanged. If you previously relied on a plain sum-of-cells total for a
non-additive metric, that specific behavior is no longer available.
The "Sum as Fraction of Total/Rows/Columns" display options are back as a
new, standalone **"Show values as"** control (below "Combine metrics" in the
Options panel), since those were mathematically correct even before this
change and are unrelated to the totals-correctness fix. A DB migration
derives the new field from any still-present `aggregateFunction` Sum-fraction
value, so a chart that had one of those options configured picks the
equivalent "Show values as" setting back up automatically. The "Count as
Fraction of ..." variants are **not** migrated: they divided a record count,
while the new control divides the metric's own value, so translating them
automatically would silently change what the chart displays rather than
restore it; those charts need to be manually reconfigured if the value-based
percentage is what's wanted. Charts that used any other non-fraction
`aggregateFunction` value (Sum, Average, Count, ...) are unaffected, since
that specific behavior remains unavailable per the above.
### `thumbnail_url` removed from dashboard list API response
@@ -333,6 +538,7 @@ ALTER TABLE tagged_object DROP CONSTRAINT <constraint_name>;
-- MySQL: find names via `SHOW CREATE TABLE tagged_object;`
ALTER TABLE tagged_object DROP FOREIGN KEY <constraint_name>;
```
### Entity version-history infrastructure (gated off by default)
Introduces the schema and SQLAlchemy-Continuum wiring that captures version history for charts, dashboards, and datasets, plus read-only `GET /api/v1/{chart,dashboard,dataset}/<uuid>/versions/` endpoints. This ships **inert**: a new config flag `ENABLE_VERSIONING_CAPTURE` defaults to `False`, so no save writes any version rows and the endpoints return empty. It is an operational kill-switch (a release toggle that becomes a permanent ops switch), not a feature flag — set it to `True` to enable capture once validated. The migration is additive; existing entity `PUT` responses gain `old_version_uuid` / `new_version_uuid` body fields and an `ETag` header (both null/absent when capture is off).
@@ -349,15 +555,48 @@ These are behavior changes that take effect on upgrade regardless of `ENABLE_VER
A read-only companion to the version-history endpoints: each entity type gains a `GET /api/v1/{chart,dashboard,dataset}/<uuid>/activity/` endpoint returning a chronological, access-filtered stream of edits — the entity's own edits plus, for charts and dashboards, transitive edits to related entities during their association windows. Datasets have no related layer in V2, so `include=related` returns an empty stream for a dataset and `include=all` reduces to the dataset's own edits.
| Param | Type | Default | Purpose |
|---|---|---|---|
| `since` / `until` | ISO 8601 | — | Bound `issued_at` |
| `include` | `self` \| `related` \| `all` | `all` | Own edits, related edits, or both |
| `q` | string | — | Case-insensitive search over the full history, applied before pagination (so `count` reflects matches) |
| `page` / `page_size` | integer | `0` / `25` | Pagination (`page_size` clamped to 200) |
| Param | Type | Default | Purpose |
| -------------------- | ---------------------------- | ---------- | ------------------------------------------------------------------------------------------------------ |
| `since` / `until` | ISO 8601 | — | Bound `issued_at` |
| `include` | `self` \| `related` \| `all` | `all` | Own edits, related edits, or both |
| `q` | string | — | Case-insensitive search over the full history, applied before pagination (so `count` reflects matches) |
| `page` / `page_size` | integer | `0` / `25` | Pagination (`page_size` clamped to 200) |
Authorization reuses the resource's `can_read` permission and per-object `raise_for_access`; related-entity rows are visibility-filtered to what the caller may see. The stream is empty unless version capture is on (`ENABLE_VERSIONING_CAPTURE`).
### Version-history retention (pruning)
Entity version history (the `version_transaction` / `*_version` shadow tables that back version capture) is aged out by a nightly Celery beat task, `version_history.prune_old_versions` (`superset.tasks.version_history_retention`).
| Key | Default | Purpose |
|---|---|---|
| `SUPERSET_VERSION_HISTORY_RETENTION_DAYS` | `30` | Version rows whose owning `version_transaction.issued_at` is older than this many days are pruned. Each entity's live row (`end_transaction_id IS NULL`) is always preserved, as are the live rows of its children and associations; closed historical rows (including the baseline) age out. Set to `0` or a negative value to disable pruning. |
The task ships in the default `CeleryConfig` (both the `superset.tasks.version_history_retention` import and the beat entry). A deployment that overrides `CELERY_CONFIG` without the beat entry logs a startup warning. When the override explicitly defines `imports`, a missing retention module is also reported; an absent `imports` setting is not diagnosed because Celery may register tasks through `include`, autodiscovery, or worker startup imports. Retention only prunes whatever history exists — capture itself is gated separately by `ENABLE_VERSIONING_CAPTURE`, which now ships on.
### Deletion retention (soft-deleted entities are eventually purged)
Soft-deleted dashboards, charts, and datasets are now permanently removed after a retention window (default 30 days; `SOFT_DELETE_RETENTION_DAYS`, `0` disables; settable per workspace at runtime via the `deletion-retention set-window` CLI, which takes precedence). The `deletion_retention.purge_soft_deleted` Celery beat task runs daily and removes each aged-out entity together with its M:N join rows, owned children, datasource permission, and version-history shadow rows. After purge an entity is **unrecoverable** — its detail and `/restore` endpoints return 404 and its version history is gone.
Purging is **live by default** (`SOFT_DELETE_PURGE_DRY_RUN=False`), so the retention promise above is real on a stock deployment. Set it to `True` to have the task log `would_purge` counts and delete nothing — the lever is retained, so an operator can return to dry-run at any time. Note `would_purge` is an **upper bound** — it counts every entity past the retention window without evaluating deletion blockers, so a real run may purge fewer (entities referenced by report schedules or set as a user's welcome dashboard are blocked and reported separately). The task only acts while the `SOFT_DELETE` rollout flag is on; it now ships on by default.
Deployments that replace the default `CELERY_CONFIG` must ensure workers register `superset.tasks.deletion_retention` and schedule the `deletion_retention.purge_soft_deleted` task themselves. The shipped Docker development config uses `imports` and includes both entries. While `SOFT_DELETE` is statically enabled, a missing beat entry logs a startup warning; when the override explicitly defines `imports`, a missing purge module is also reported.
Operators can immediately erase a specific entity for compliance (GDPR) via `superset deletion-retention force-purge --uuid <uuid>`; this applies legacy hard-delete semantics — a live chart referencing a force-purged dataset is left without a datasource until re-pointed (the chart is not modified), and it purges the named entity even when it was never soft-deleted. Every scheduled evaluation writes a provisional, content-free record to the new `purge_audit_log` table before the cascade starts. Meaningful retained outcomes survive the entity they name. Consecutive scheduled evaluations with the same blocked outcome suppress only the redundant current provisional record; completed outcomes, outcome transitions, and every force-purge attempt remain independent and immutable. The **scheduled** purge fails closed when its provisional record cannot be written, while **force-purge** proceeds even if the audit write fails — the operator is present and deletion outranks audit for a compliance erasure. Operators can monitor `deletion_retention.blocked_audit_suppressed` and `deletion_retention.blocked_audit_dedupe_fallback` to verify suppression and fail-safe fallback behavior without changing the existing blocked-workload gauge.
### Recently Archived view and permanent delete (purge) endpoints
Behind the same `SOFT_DELETE` flag, a **Recently Archived** page (Settings menu, `/archived/`) lists soft-deleted charts, dashboards, and datasets with their archive time and archiving user, and offers **Recover** and **Delete permanently** row actions. The page admits any viewer holding `can_read` on **any** of the three types and offers each viewer only the types they can read; a viewer with none of the three sees an explanatory empty state, and unauthenticated requests are redirected to login.
**New endpoints**`POST /api/v1/{chart,dashboard,dataset}/<uuid>/purge` permanently delete a single **soft-deleted** row, running the same cascade as the retention task. Irreversible. Requires `can_write` on the entity plus editorship of the row (or admin), mirroring `/restore`. The endpoints answer 404 while `SOFT_DELETE` is off (restore deliberately stays live so rows archived before a flag-off remain recoverable), 404 for rows that are not soft-deleted, and 422 with a reason when the purge is blocked (an alert/report references the entity, a user has the dashboard as their welcome page, or a restrictive foreign key intervenes). A purge that cannot write its audit record is refused with 422 rather than executed unrecorded — unlike the operator CLI, an end user's purge never outranks the audit.
With the flag on, delete confirmations across the chart/dashboard/dataset list pages change shape: a recoverable archive is confirmed with a primary **Archive** button and no type-DELETE friction, and the copy states the retention window when one is configured. A bulk dataset selection that includes semantic views keeps the full danger treatment, because semantic views have no soft-delete — they are deleted permanently and the confirmation says so.
This also resolves the limitation noted under *Soft delete and restore for datasets*: a database blocked by soft-deleted datasets can now be freed by purging those datasets (per-entity endpoint, retention task, or `force-purge` CLI) instead of hard-deleting `tables` rows out-of-band.
The `purge_audit_log` table is **never pruned by design** — the audit must survive the entities it names; operators who need to age it out should prune manually.
### Webhook alerts/reports block private/internal hosts by default
Webhook alert/report dispatch (`WebhookNotification.send`) now validates the target URL's host against the same private/internal-IP block applied to dataset import URLs. If the resolved host is in a loopback, link-local, private (RFC-1918), shared-CGNAT, or multicast range, the webhook is rejected with `NotificationParamException`.
@@ -405,6 +644,7 @@ Operators can tune or disable the policy via config:
### Data uploads bounded by UPLOAD_MAX_FILE_SIZE_BYTES
Single data-file uploads (CSV, Excel, columnar) are now bounded by the `UPLOAD_MAX_FILE_SIZE_BYTES` config option, which defaults to `100 * 1024 * 1024` (100 MB). Files larger than this are rejected with a `413` before their contents are buffered into memory. Set `UPLOAD_MAX_FILE_SIZE_BYTES = None` to disable the check and restore unbounded uploads.
### Currency symbol position follows the locale when unset
When a chart's currency control leaves the **Prefix or suffix** field empty, the currency symbol position is now derived from the deployment locale's own convention via `Intl.NumberFormat` instead of always defaulting to a suffix. For example, under the default `en-US` locale `USD`, `GBP`, and `EUR` render as a prefix (`$ 1,000`), while eurozone locales such as `fr-FR` render `EUR` as a suffix (`1 000 €`). An explicit Prefix/Suffix selection is always honored and is unaffected.
@@ -530,7 +770,7 @@ SQLALCHEMY_ENCRYPTED_FIELD_ENGINE = "aes"
```bash
superset re-encrypt-secrets --engine aes-gcm
```
A live instance keeps writing *new* secrets as AES-CBC during the window between step 2 and the restart in step 4; this second pass sweeps those up (it is idempotent, so already-migrated values are skipped).
A live instance keeps writing _new_ secrets as AES-CBC during the window between step 2 and the restart in step 4; this second pass sweeps those up (it is idempotent, so already-migrated values are skipped).
Schedule the cutover in a quiet window. Runtime reads use only the single configured engine, so in a multi-worker deployment there is an unavoidable brief decrypt-outage between the migration commit and the last worker restarting with the new config — each migrator run is transactional, but the fleet-wide cutover is not zero-downtime.
@@ -558,11 +798,11 @@ With the flag enabled: `DELETE /api/v1/dataset/<id>` no longer hard-deletes the
**Schema migration:** the migration adds a nullable `deleted_at` column and an index on it (`ix_tables_deleted_at`) to the `tables` table. The column add is instant; the index build runs inline (no `CONCURRENTLY`) and may briefly block writes on the `tables` table (INSERT/UPDATE/DELETE are queued while the index builds; reads are unaffected) on large Postgres deployments. MySQL InnoDB builds the index online (no blocking). Production deployments with many thousands of datasets should run this migration during a maintenance window.
**Rollback note:** if the application code is rolled back after datasets have been soft-deleted, the older code path's visibility filter no longer applies and previously hidden rows become visible to the older code. Pair the rollback with a data decision (restore the rows, hard-delete them, or also downgrade the migration) rather than assuming the old hard-delete semantics still hold. **Downgrading the migration destroys the deletion markers**: `downgrade()` drops the `deleted_at` column, so any not-yet-restored soft-deleted datasets silently become live, active datasets with no record they were ever deleted. Reconcile the trash (restore or hard-delete each row) *before* downgrading, and disable the `SOFT_DELETE` flag first so no new soft deletes land mid-rollback.
**Rollback note:** if the application code is rolled back after datasets have been soft-deleted, the older code path's visibility filter no longer applies and previously hidden rows become visible to the older code. Pair the rollback with a data decision (restore the rows, hard-delete them, or also downgrade the migration) rather than assuming the old hard-delete semantics still hold. **Downgrading the migration destroys the deletion markers**: `downgrade()` drops the `deleted_at` column, so any not-yet-restored soft-deleted datasets silently become live, active datasets with no record they were ever deleted. Reconcile the trash (restore or hard-delete each row) _before_ downgrading, and disable the `SOFT_DELETE` flag first so no new soft deletes land mid-rollback.
**SQL Lab / dataset-creation flows:** creating a dataset over a table whose dataset sits in the trash is refused. The SQL Lab "save as dataset" flow (`get_or_create_dataset`) and file uploads return a **422 naming the hidden twin and the restore endpoint**; the plain create, update, and duplicate paths currently fail with the generic "already exists" 422. In all cases the remediation is the same: restore the hidden dataset (or use a different table name). Perm-string maintenance also covers hidden rows: renaming a database rewrites `perm`/`schema_perm`/`catalog_perm` on soft-deleted datasets and their charts, so a later restore does not resurrect stale permission strings.
**Importer behavior:** importing a dataset YAML whose UUID matches an existing **soft-deleted** dataset is treated as an implicit restore-with-update — **and this happens even when `overwrite` is not set**. This is a deliberate asymmetry with active rows: an active dataset imported without `overwrite=true` is returned unchanged, but a soft-deleted UUID match is restored *and* has the upload's contents applied regardless of the `overwrite` argument, on the reasoning that re-importing a deleted dataset's exact UUID is an explicit request to bring it back. The restore preserves the original PK, the chart back-reference, `table_columns`, and `sql_metrics`. Non-editors get `ImportFailedError`. Callers without `can_write` get `ImportFailedError` instead of silently receiving the soft-deleted row.
**Importer behavior:** importing a dataset YAML whose UUID matches an existing **soft-deleted** dataset is treated as an implicit restore-with-update — **and this happens even when `overwrite` is not set**. This is a deliberate asymmetry with active rows: an active dataset imported without `overwrite=true` is returned unchanged, but a soft-deleted UUID match is restored _and_ has the upload's contents applied regardless of the `overwrite` argument, on the reasoning that re-importing a deleted dataset's exact UUID is an explicit request to bring it back. The restore preserves the original PK, the chart back-reference, `table_columns`, and `sql_metrics`. Non-editors get `ImportFailedError`. Callers without `can_write` get `ImportFailedError` instead of silently receiving the soft-deleted row.
**Uniqueness-validation changes that apply regardless of the feature flag:** two dataset uniqueness checks were tightened alongside this work and are active even with `SOFT_DELETE` off. (1) Create/update uniqueness treats a dataset whose `catalog` is `NULL` as belonging to the database's default catalog, so a legacy twin pair (`catalog=NULL` vs. `catalog=<default>`, same database/schema/name) that older versions allowed now fails validation with "already exists" when either row is edited — resolve by renaming or removing one of the twins. (2) Duplicating a dataset now checks name collisions scoped to the target (database, catalog, schema) instead of globally by name alone: duplicates into other databases that were previously blocked are now allowed.
@@ -582,9 +822,9 @@ With the flag enabled: `DELETE /api/v1/chart/<id>` no longer hard-deletes the ch
**Schema migration:** the migration adds a nullable `deleted_at` column and an index on it (`ix_slices_deleted_at`) to the `slices` table. The column add is instant; the index build runs inline (no `CONCURRENTLY`) and may briefly block writes on the `slices` table (INSERT/UPDATE/DELETE are queued while the index builds; reads are unaffected) on large Postgres deployments. MySQL InnoDB builds the index online (no blocking).
**Rollback note:** if the application code is rolled back after charts have been soft-deleted, the older code path's visibility filter no longer applies and previously hidden rows become visible to the older code. Pair the rollback with a data decision (restore the rows, hard-delete them, or also downgrade the migration) rather than assuming the old hard-delete semantics still hold. **Downgrading the migration destroys the deletion markers**: `downgrade()` drops the `deleted_at` column, so any not-yet-restored soft-deleted charts silently become live, active charts with no record they were ever deleted. Reconcile the trash (restore or hard-delete each row) *before* downgrading, and disable the `SOFT_DELETE` flag first so no new soft deletes land mid-rollback.
**Rollback note:** if the application code is rolled back after charts have been soft-deleted, the older code path's visibility filter no longer applies and previously hidden rows become visible to the older code. Pair the rollback with a data decision (restore the rows, hard-delete them, or also downgrade the migration) rather than assuming the old hard-delete semantics still hold. **Downgrading the migration destroys the deletion markers**: `downgrade()` drops the `deleted_at` column, so any not-yet-restored soft-deleted charts silently become live, active charts with no record they were ever deleted. Reconcile the trash (restore or hard-delete each row) _before_ downgrading, and disable the `SOFT_DELETE` flag first so no new soft deletes land mid-rollback.
**Importer behavior:** importing a chart YAML whose UUID matches an existing **soft-deleted** chart is treated as an implicit restore-with-update — **and this happens even when `overwrite` is not set**. This is a deliberate asymmetry with active rows: an active chart imported without `overwrite=true` is returned unchanged, but a soft-deleted UUID match is restored *and* has the upload's contents applied regardless of the `overwrite` argument, on the reasoning that re-importing a deleted chart's exact UUID is an explicit request to bring it back. The restore preserves the original PK and all out-of-archive references (`dashboard_slices` junctions, `report.chart_id`, tag rows). The operation is permission-gated: non-editors get `ImportFailedError`, and callers without `can_write` get `ImportFailedError` instead of silently receiving the soft-deleted row.
**Importer behavior:** importing a chart YAML whose UUID matches an existing **soft-deleted** chart is treated as an implicit restore-with-update — **and this happens even when `overwrite` is not set**. This is a deliberate asymmetry with active rows: an active chart imported without `overwrite=true` is returned unchanged, but a soft-deleted UUID match is restored _and_ has the upload's contents applied regardless of the `overwrite` argument, on the reasoning that re-importing a deleted chart's exact UUID is an explicit request to bring it back. The restore preserves the original PK and all out-of-archive references (`dashboard_slices` junctions, `report.chart_id`, tag rows). The operation is permission-gated: non-editors get `ImportFailedError`, and callers without `can_write` get `ImportFailedError` instead of silently receiving the soft-deleted row.
- [39914](https://github.com/apache/superset/pull/39914) `ALERT_REPORT_SLACK_V2` now defaults to `True` and the legacy Slack v1 integration (`Slack` recipient type, `files.upload` API) is deprecated for removal in the next major. Slack blocked new apps from `files.upload` in May 2024 and fully retired the method for all apps on November 12, 2025; because the v1 path sends files through `files.upload`, v1 file-bearing sends now fail at the API level — only text-only `chat_postMessage` still works via the legacy path. Grant your Slack bot the `channels:read` and `groups:read` scopes so existing `Slack` recipients can be auto-upgraded to `SlackV2` on next send. Operators who explicitly override the flag to `False`, or whose Slack bot is missing those scopes, will see deprecation warnings while text-only sends continue through the legacy path.
@@ -608,7 +848,7 @@ The partial-index replacement is dialect-dependent: PostgreSQL uses a native `WH
**Slug semantics:** on PostgreSQL and MySQL 8.0.13+, the slug of a soft-deleted dashboard is **free for reuse**. A new active dashboard can claim it immediately. Restoring a soft-deleted dashboard whose slug has since been claimed returns **422 with a clean error** (`DashboardSlugConflictError`) — rename one of the dashboards and retry; the restore is not silently rejected by a database-level constraint violation.
**Importer behavior:** importing a dashboard YAML whose UUID matches an existing **soft-deleted** dashboard is treated as an implicit restore-with-update — **and this happens even when `overwrite` is not set**. This is a deliberate asymmetry with active rows: an active dashboard imported without `overwrite=true` is returned unchanged (the import never mutates it), but a soft-deleted UUID match is restored *and* has the upload's contents applied regardless of the `overwrite` argument, on the reasoning that re-importing a deleted dashboard's exact UUID is an explicit request to bring it back. The restore preserves the original PK and all pre-deletion relationship rows (`dashboard_slices` junctions, editor/viewer subjects, tags). Callers whose imports must never mutate existing state should treat bundles that may contain previously deleted UUIDs accordingly. The operation is permission-gated: it requires `can_write` and editorship of the deleted row (or admin) — non-editors get `ImportFailedError`, and callers without `can_write` get `ImportFailedError` instead of silently receiving the soft-deleted row.
**Importer behavior:** importing a dashboard YAML whose UUID matches an existing **soft-deleted** dashboard is treated as an implicit restore-with-update — **and this happens even when `overwrite` is not set**. This is a deliberate asymmetry with active rows: an active dashboard imported without `overwrite=true` is returned unchanged (the import never mutates it), but a soft-deleted UUID match is restored _and_ has the upload's contents applied regardless of the `overwrite` argument, on the reasoning that re-importing a deleted dashboard's exact UUID is an explicit request to bring it back. The restore preserves the original PK and all pre-deletion relationship rows (`dashboard_slices` junctions, editor/viewer subjects, tags). Callers whose imports must never mutate existing state should treat bundles that may contain previously deleted UUIDs accordingly. The operation is permission-gated: it requires `can_write` and editorship of the deleted row (or admin) — non-editors get `ImportFailedError`, and callers without `can_write` get `ImportFailedError` instead of silently receiving the soft-deleted row.
### Engine spec capability flag: `supports_offset`
@@ -620,10 +860,10 @@ A new `BaseEngineSpec.supports_offset` attribute (default `True`) indicates whet
A new feature flag `GRANULAR_EXPORT_CONTROLS` introduces three fine-grained permissions that replace the legacy `can_csv` permission:
| Permission | Controls |
|---|---|
| `can_export_data` | CSV, Excel, JSON exports |
| `can_export_image` | Screenshot/PDF exports |
| Permission | Controls |
| -------------------- | ---------------------------- |
| `can_export_data` | CSV, Excel, JSON exports |
| `can_export_image` | Screenshot/PDF exports |
| `can_copy_clipboard` | Copy-to-clipboard operations |
When the feature flag is enabled, these permissions are enforced on both the frontend (disabled buttons with tooltips) and backend (403 responses from API endpoints). When disabled, legacy `can_csv` behavior is preserved.
@@ -646,6 +886,12 @@ Added a new combined datasource list endpoint at `GET /api/v1/datasource/` to se
- Semantic views are included only when the `SEMANTIC_LAYERS` feature flag is enabled.
- The endpoint enforces strict `order_column` validation and returns `400` for invalid sort columns.
### Custom time range "Now"/"Today" anchors resolve in local time
Custom time ranges that use the "Now" or "Today" anchor (for the Start, End, or the relative anchor itself) previously resolved that anchor in UTC before formatting it into a naive datetime string, which was then re-parsed elsewhere as local time. For users outside UTC, this made the resolved anchor drift by their browser's UTC offset. "Now"/"Today" now resolve directly in local time, matching the later local re-parse.
Charts and dashboards using these anchors will compute a different (correct) timestamp after upgrading; if a chart's filters or drill-downs were tuned to compensate for the old offset, review them after upgrading.
## 6.1.0
### ClickHouse minimum driver version bump
@@ -661,14 +907,17 @@ The Kenya country map has been updated to reflect the 47 counties established un
MCP (Model Context Protocol) tools now include enhanced observability instrumentation for monitoring and debugging:
**Two-layer instrumentation:**
1. **Middleware layer** (`LoggingMiddleware`): Automatically logs all MCP tool calls with `duration_ms` and `success` status in the audit log (Action Log UI, logs table)
2. **Sub-operation tracking**: All 19 MCP tools include granular `event_logger.log_context()` blocks for tracking individual operations like validation, database writes, and query execution
**Action naming convention:**
- Tool-level logs: `mcp_tool_call` (via middleware)
- Sub-operation logs: `mcp.{tool_name}.{operation}` (e.g., `mcp.generate_chart.validation`, `mcp.execute_sql.query_execution`)
**Querying MCP logs:**
```sql
-- Top slowest MCP operations
SELECT action, COUNT(*) as calls, AVG(duration_ms) as avg_ms
@@ -703,6 +952,7 @@ A new `DISTRIBUTED_COORDINATION_CONFIG` configuration provides a unified Redis-b
The distributed coordination is used by the Global Task Framework (GTF) for abort notifications and task completion signaling, and will eventually replace `GLOBAL_ASYNC_QUERIES_CACHE_BACKEND` as the standard signaling backend. Configuring this is recommended for Redis enabled production deployments.
Example configuration in `superset_config.py`:
```python
DISTRIBUTED_COORDINATION_CONFIG = {
"CACHE_TYPE": "RedisCache",
@@ -717,9 +967,11 @@ See `superset/config.py` for complete configuration options.
### WebSocket config for GAQ with Docker
[35896](https://github.com/apache/superset/pull/35896) and [37624](https://github.com/apache/superset/pull/37624) updated documentation on how to run and configure Superset with Docker. Specifically for the WebSocket configuration, a new `docker/superset-websocket/config.example.json` was added to the repo, so that users could copy it to create a `docker/superset-websocket/config.json` file. The existing `docker/superset-websocket/config.json` was removed and git-ignored, so if you're using GAQ / WebSocket make sure to:
- Stash/backup your existing `config.json` file, to re-apply it after (will get git-ignored going forward)
- Update the `volumes` configuration for the `superset-websocket` service in your `docker-compose.override.yml` file, to include the `docker/superset-websocket/config.json` file. For example:
``` yaml
```yaml
services:
superset-websocket:
volumes:
@@ -732,7 +984,9 @@ services:
### Example Data Loading Improvements
#### New Directory Structure
Examples are now organized by name with data and configs co-located:
```
superset/examples/
├── _shared/ # Shared database & metadata configs
@@ -745,12 +999,14 @@ superset/examples/
```
#### Simplified Parquet-based Loading
- Auto-discovery: create `superset/examples/my_dataset/data.parquet` to add a new example
- Parquet is an Apache project format: compressed (~27% smaller), self-describing schema
- YAML configs define datasets, charts, and dashboards declaratively
- Removed Python-based data generation from individual example files
#### Test Data Reorganization
- Moved `big_data.py` to `superset/cli/test_loaders.py` - better reflects its purpose as a test utility
- Fixed inverted logic for `--load-test-data` flag (now correctly includes .test.yaml files when flag is set)
- Clarified CLI flags:
@@ -760,6 +1016,7 @@ superset/examples/
- `--load-big-data` / `-b`: Generate synthetic stress-test data
#### Bug Fixes
- Fixed numpy array serialization for PostgreSQL (converts complex types to JSON strings)
- Fixed KeyError for `allow_csv_upload` field in database configs (now optional with default)
- Fixed test data loading logic that was incorrectly filtering files
@@ -769,6 +1026,7 @@ superset/examples/
The MCP (Model Context Protocol) service enables AI assistants and automation tools to interact programmatically with Superset.
#### New Features
- MCP service infrastructure with FastMCP framework
- Tools for dashboards, charts, datasets, SQL Lab, and instance metadata
- Optional dependency: install with `pip install apache-superset[fastmcp]`
@@ -778,6 +1036,7 @@ The MCP (Model Context Protocol) service enables AI assistants and automation to
#### New Configuration Options
**Development** (single-user, local testing):
```python
# superset_config.py
MCP_DEV_USERNAME = "admin" # User for MCP authentication
@@ -786,6 +1045,7 @@ MCP_SERVICE_PORT = 5008
```
**Production** (JWT-based, multi-user):
```python
# superset_config.py
MCP_AUTH_ENABLED = True
@@ -831,12 +1091,14 @@ superset mcp run --port 5008 --use-factory-config
The MCP service runs as a **separate process** from the Superset web server.
**Important**:
- Requires same Python environment and configuration as Superset
- Shares database connections with main Superset app
- Can be scaled independently from web server
- Requires `fastmcp` package (optional dependency)
**Installation**:
```bash
# Install with MCP support
pip install apache-superset[fastmcp]
@@ -850,6 +1112,7 @@ Use systemd, supervisord, or Kubernetes to manage the MCP service process.
See `superset/mcp_service/PRODUCTION.md` for deployment guides.
**Security**:
- Development: Uses `MCP_DEV_USERNAME` for single-user access
- Production: **MUST** configure JWT authentication
- See `superset/mcp_service/SECURITY.md` for details
@@ -869,8 +1132,10 @@ See `superset/mcp_service/PRODUCTION.md` for deployment guides.
- [35062](https://github.com/apache/superset/pull/35062): Changed the function signature of `setupExtensions` to `setupCodeOverrides` with options as arguments.
### Breaking Changes
- [37370](https://github.com/apache/superset/pull/37370): The `APP_NAME` configuration variable no longer controls the browser window/tab title or other frontend branding. Application names should now be configured using the theme system with the `brandAppName` token. The `APP_NAME` config is still used for backend contexts (MCP service, logs, etc.) and serves as a fallback if `brandAppName` is not set.
- **Migration:**
```python
# Before (Superset 5.x)
APP_NAME = "My Custom App"
@@ -914,16 +1179,16 @@ See `superset/mcp_service/PRODUCTION.md` for deployment guides.
Eight M:N association tables move from a synthetic `id INTEGER PRIMARY KEY` to a composite `PRIMARY KEY (fk1, fk2)` on their two foreign-key columns. The surrogate `id` is dropped, and the redundant `UNIQUE (fk1, fk2)` on the two tables that carried one is removed (now subsumed by the PK).
| Table | Composite PK |
|---|---|
| `dashboard_roles` | `(dashboard_id, role_id)` |
| `dashboard_slices` | `(dashboard_id, slice_id)` |
| `dashboard_user` | `(user_id, dashboard_id)` |
| Table | Composite PK |
| ---------------------- | ------------------------------- |
| `dashboard_roles` | `(dashboard_id, role_id)` |
| `dashboard_slices` | `(dashboard_id, slice_id)` |
| `dashboard_user` | `(user_id, dashboard_id)` |
| `report_schedule_user` | `(user_id, report_schedule_id)` |
| `rls_filter_roles` | `(role_id, rls_filter_id)` |
| `rls_filter_tables` | `(table_id, rls_filter_id)` |
| `slice_user` | `(user_id, slice_id)` |
| `sqlatable_user` | `(user_id, table_id)` |
| `rls_filter_roles` | `(role_id, rls_filter_id)` |
| `rls_filter_tables` | `(table_id, rls_filter_id)` |
| `slice_user` | `(user_id, slice_id)` |
| `sqlatable_user` | `(user_id, table_id)` |
**Before upgrading:**
@@ -934,6 +1199,7 @@ Eight M:N association tables move from a synthetic `id INTEGER PRIMARY KEY` to a
For large `dashboard_slices` / `report_schedule_user` tables, see the operator runbook in [#39859](https://github.com/apache/superset/pull/39859) — pre-flight inventory queries, per-dialect lock-window sizing, and the duplicate / NULL-FK roll-up — to plan the maintenance window.
## 6.0.0
- [33055](https://github.com/apache/superset/pull/33055): Upgrades Flask-AppBuilder to 5.0.0. The AUTH_OID authentication type has been deprecated and is no longer available as an option in Flask-AppBuilder. OpenID (OID) is considered a deprecated authentication protocol - if you are using AUTH_OID, you will need to migrate to an alternative authentication method such as OAuth, LDAP, or database authentication before upgrading.
- [34871](https://github.com/apache/superset/pull/34871): Fixed Jest test hanging issue from Ant Design v5 upgrade. MessageChannel is now mocked in test environment to prevent rc-overflow from causing Jest to hang. Test environment only - no production impact.
- [34782](https://github.com/apache/superset/pull/34782): Dataset exports now include the dataset ID in their file name (similar to charts and dashboards). If managing assets as code, make sure to rename existing dataset YAMLs to include the ID (and avoid duplicated files).
@@ -942,8 +1208,8 @@ For large `dashboard_slices` / `report_schedule_user` tables, see the operator r
- Change any hex color values to one of: `"success"`, `"processing"`, `"error"`, `"warning"`, `"default"`
- Custom colors are no longer supported to maintain consistency with Ant Design components
- [34561](https://github.com/apache/superset/pull/34561) Added tiled screenshot functionality for Playwright-based reports to handle large dashboards more efficiently. When enabled (default: `SCREENSHOT_TILED_ENABLED = True`), dashboards with 20+ charts or height exceeding 5000px will be captured using multiple viewport-sized tiles and combined into a single image. This improves report generation performance and reliability for large dashboards.
Note: Pillow is now a required dependency (previously optional) to support image processing for tiled screenshots.
`thumbnails` optional dependency is now deprecated and will be removed in the next major release (7.0).
Note: Pillow is now a required dependency (previously optional) to support image processing for tiled screenshots.
`thumbnails` optional dependency is now deprecated and will be removed in the next major release (7.0).
- [33084](https://github.com/apache/superset/pull/33084) The DISALLOWED_SQL_FUNCTIONS configuration now includes additional potentially sensitive database functions across PostgreSQL, MySQL, SQLite, MS SQL Server, and ClickHouse. Existing queries using these functions may now be blocked. Review your SQL Lab queries and dashboards if you encounter "disallowed function" errors after upgrading
- [34235](https://github.com/apache/superset/pull/34235) CSV exports now use `utf-8-sig` encoding by default to include a UTF-8 BOM, improving compatibility with Excel.
- [34258](https://github.com/apache/superset/pull/34258) changing the default in Dockerfile to INCLUDE_CHROMIUM="false" (from "true") in the past. This ensures the `lean` layer is lean by default, and people can opt-in to the `chromium` layer by setting the build arg `INCLUDE_CHROMIUM=true`. This is a breaking change for anyone using the `lean` layer, as it will no longer include Chromium by default.
+7 -1
View File
@@ -28,8 +28,10 @@ x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset
x-superset-volumes:
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
- ./docker:/app/docker
- ./superset-core:/app/superset-core
- superset_home:/app/superset_home
x-superset-environment: &superset-environment
# Tagged images must use their bundled packages rather than host bind mounts.
DEV_MODE: "false"
services:
redis:
@@ -58,6 +60,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
image: *superset-image
container_name: superset_app
command: ["/app/docker/docker-bootstrap.sh", "app-gunicorn"]
@@ -79,6 +82,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
depends_on:
db:
condition: service_started
@@ -98,6 +102,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
restart: unless-stopped
depends_on:
superset-init:
@@ -120,6 +125,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
environment: *superset-environment
restart: unless-stopped
depends_on:
superset-init:
+1 -1
View File
@@ -38,7 +38,7 @@ RESET='\033[0m'
echo -e "${GREEN}Updating package lists...${RESET}"
apt-get update -qq
echo -e "${GREEN}Installing packages: $@${RESET}"
echo -e "${GREEN}Installing packages: $*${RESET}"
apt-get install -yqq --no-install-recommends "$@"
echo -e "${GREEN}Autoremoving unnecessary packages...${RESET}"
+15 -1
View File
@@ -84,6 +84,7 @@ class CeleryConfig:
broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}"
imports = (
"superset.sql_lab",
"superset.tasks.deletion_retention",
"superset.tasks.scheduler",
"superset.tasks.thumbnails",
"superset.tasks.cache",
@@ -101,6 +102,13 @@ class CeleryConfig:
"task": "reports.prune_log",
"schedule": crontab(minute=10, hour=0),
},
# Gated on the SOFT_DELETE feature flag, which is off by default: the
# task is scheduled either way, but purges nothing while the flag is
# unset. Enable it in FEATURE_FLAGS below to exercise retention locally.
"deletion_retention.purge_soft_deleted": {
"task": "deletion_retention.purge_soft_deleted",
"schedule": crontab(minute=0, hour=0),
},
}
@@ -114,7 +122,13 @@ FEATURE_FLAGS = {
}
EXTENSIONS_PATH = "/app/docker/extensions"
ALERT_REPORTS_NOTIFICATION_DRY_RUN = True
WEBDRIVER_BASEURL = f"http://superset_app{os.environ.get('SUPERSET_APP_ROOT', '/')}/" # When using docker compose baseurl should be http://superset_nginx{ENV{BASEPATH}}/ # noqa: E501
# The Docker Compose app service is named "superset" and listens on 8088. Report
# paths are root-relative, so urljoin drops the base path; only the scheme, host,
# and port must be correct here. SUPERSET_APP_ROOT is kept for consumers that
# concatenate paths directly (e.g. cache warm-up). For screenshots in the dev
# stack (unbuilt static assets) point this at the nginx service instead:
# http://nginx{SUPERSET_APP_ROOT}/
WEBDRIVER_BASEURL = f"http://superset:8088{os.environ.get('SUPERSET_APP_ROOT', '/')}/"
# The base URL for the email report hyperlinks.
WEBDRIVER_BASEURL_USER_FRIENDLY = (
f"http://localhost:8888/{os.environ.get('SUPERSET_APP_ROOT', '/')}/"
+2 -2
View File
@@ -163,10 +163,10 @@ do
# Iterate through the components of the version strings
for (( j=0; j<${#THIS_TAG_NAME_ARRAY[@]}; j++ )); do
echo "Comparing ${THIS_TAG_NAME_ARRAY[$j]} to ${LATEST_RELEASE_TAG_ARRAY[$j]}"
if [[ $((THIS_TAG_NAME_ARRAY[$j])) > $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
if [[ $((THIS_TAG_NAME_ARRAY[$j])) -gt $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
compare_result="greater"
break
elif [[ $((THIS_TAG_NAME_ARRAY[$j])) < $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
elif [[ $((THIS_TAG_NAME_ARRAY[$j])) -lt $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
compare_result="lesser"
break
fi
+16 -7
View File
@@ -9,11 +9,13 @@ When working on the Storybook-to-MDX documentation system:
## Why This Matters
The generator (`scripts/generate-superset-components.mjs`) should be lightweight - it extracts data from stories and passes it through. When you add special cases to the generator:
- It becomes harder to maintain
- Stories diverge from their docs representation
- Future stories need to know about generator quirks
When you fix stories to match the expected patterns:
- Stories work identically in Storybook and Docs
- The generator stays simple and predictable
- Patterns are consistent and learnable
@@ -21,6 +23,7 @@ When you fix stories to match the expected patterns:
## Story Patterns for Docs Generation
### Required Structure
```tsx
// Use inline export default (NOT const meta = ...; export default meta)
export default {
@@ -45,6 +48,7 @@ export const InteractiveMyComponent: Story = {
```
### For Components with Variants (size × style grids)
```tsx
const sizes = ['small', 'medium', 'large'];
const variants = ['primary', 'secondary', 'danger'];
@@ -63,16 +67,20 @@ InteractiveButton.parameters = {
```
### For Components Requiring Children
```tsx
InteractiveIconTooltip.parameters = {
docs: {
// Component descriptors with dot notation for nested components
sampleChildren: [{ component: 'Icons.InfoCircleOutlined', props: { iconSize: 'l' } }],
sampleChildren: [
{ component: 'Icons.InfoCircleOutlined', props: { iconSize: 'l' } },
],
},
};
```
### For Custom Live Code Examples
```tsx
InteractiveMyComponent.parameters = {
docs: {
@@ -84,6 +92,7 @@ InteractiveMyComponent.parameters = {
```
### For Complex Props (objects, arrays)
```tsx
InteractiveMenu.parameters = {
docs: {
@@ -99,13 +108,13 @@ InteractiveMenu.parameters = {
## Common Issues and How to Fix Them (in the Story)
| Issue | Wrong Approach | Right Approach |
|-------|---------------|----------------|
| Component not generated | Add pattern to generator | Change story to use inline `export default` |
| Issue | Wrong Approach | Right Approach |
| --------------------------------------- | ----------------------------- | ------------------------------------------------- |
| Component not generated | Add pattern to generator | Change story to use inline `export default` |
| Control shows as text instead of select | Add special case in generator | Add `argTypes` with `control: { type: 'select' }` |
| Missing children/content | Modify StorybookWrapper | Add `parameters.docs.sampleChildren` |
| Gallery not showing | Add to generator output | Add `parameters.docs.gallery` config |
| Wrong live example | Hardcode in generator | Add `parameters.docs.liveExample` |
| Missing children/content | Modify StorybookWrapper | Add `parameters.docs.sampleChildren` |
| Gallery not showing | Add to generator output | Add `parameters.docs.gallery` config |
| Wrong live example | Hardcode in generator | Add `parameters.docs.liveExample` |
## Files
+9
View File
@@ -0,0 +1,9 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "avoid",
"printWidth": 80,
"sortPackageJson": false,
"ignorePatterns": ["**/*.mdx"]
}
-5
View File
@@ -1,5 +0,0 @@
{
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "avoid"
}
+77 -53
View File
@@ -69,6 +69,7 @@ yarn eslint # Lint TypeScript/JavaScript files
## 📁 Documentation Structure
### Main Documentation (`/docs`)
The primary documentation lives in `/docs` with this structure:
```
@@ -104,54 +105,57 @@ docs/
```
### Admin Docs (`/admin_docs`)
Admin-focused content: installation, configuration, security.
### Developer Docs (`/developer_docs`)
Developer-focused content: API documentation, architecture guides, CLI tools, code examples.
### Component Playground (`/components`)
Interactive component examples for UI development.
## 📝 Documentation Standards
### File Types
- **`.md` files**: Basic Markdown documents
- **`.mdx` files**: Markdown with JSX - can include React components
- **`.tsx` files in `/src`**: Custom React components and pages
### Frontmatter Structure
Every documentation page should have frontmatter:
```yaml
---
title: Page Title
description: Brief description for SEO
sidebar_position: 1 # Optional: controls order in sidebar
sidebar_position: 1 # Optional: controls order in sidebar
---
```
### MDX Component Usage
MDX files can import and use React components:
```mdx
````mdx
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs>
<TabItem value="npm" label="npm" default>
```bash
npm install superset
```
```bash npm install superset ```
</TabItem>
<TabItem value="yarn" label="yarn">
```bash
yarn add superset
```
```bash yarn add superset ```
</TabItem>
</Tabs>
```
````
### Code Blocks
Use triple backticks with language identifiers:
````markdown
@@ -171,6 +175,7 @@ pip install apache-superset
````
### Admonitions
Docusaurus supports various admonition types:
```markdown
@@ -198,20 +203,21 @@ This is an info box
## 🔄 Version Management
### Version Configuration
Versions are managed through `versions-config.json`:
```json
{
"docs": {
"disabled": false,
"lastVersion": "6.0.0", // Default version shown
"includeCurrentVersion": true, // Show "Next" version
"lastVersion": "6.0.0", // Default version shown
"includeCurrentVersion": true, // Show "Next" version
"onlyIncludeVersions": ["current", "6.0.0"],
"versions": {
"current": {
"label": "Next",
"path": "",
"banner": "unreleased" // Shows warning banner
"banner": "unreleased" // Shows warning banner
},
"6.0.0": {
"label": "6.0.0",
@@ -224,6 +230,7 @@ Versions are managed through `versions-config.json`:
```
### Creating New Versions
**IMPORTANT**: Always use the custom scripts, NOT native Docusaurus commands:
```bash
@@ -235,8 +242,10 @@ yarn docusaurus docs:version 6.1.0
```
### Version Files Created
When versioning, these files are created (per section, with the
section's plugin id as prefix):
- `<section>_versioned_docs/version-X.X.X/` - Snapshot of current docs
- `<section>_versioned_sidebars/version-X.X.X-sidebars.json` - Sidebar config
- `<section>_versions.json` - List of all versions
@@ -246,6 +255,7 @@ Section plugin ids: `user_docs`, `admin_docs`, `developer_docs`, `components`.
## 🎨 Styling and Theming
### Custom CSS
Add custom styles in `/src/css/custom.css`:
```css
@@ -256,13 +266,14 @@ Add custom styles in `/src/css/custom.css`:
```
### Custom Components
Create React components in `/src/components/`:
```tsx
// src/components/FeatureCard.tsx
import React from 'react';
export default function FeatureCard({title, description}) {
export default function FeatureCard({ title, description }) {
return (
<div className="card">
<h3>{title}</h3>
@@ -277,10 +288,7 @@ Use in MDX:
```mdx
import FeatureCard from '@site/src/components/FeatureCard';
<FeatureCard
title="Fast"
description="Lightning fast queries"
/>
<FeatureCard title="Fast" description="Lightning fast queries" />
```
## 📦 Key Dependencies
@@ -295,6 +303,7 @@ import FeatureCard from '@site/src/components/FeatureCard';
## 🔗 Linking Strategies
### Internal Links
Use relative paths for internal documentation:
```markdown
@@ -303,6 +312,7 @@ Use relative paths for internal documentation:
```
### External Links
Always use full URLs:
```markdown
@@ -310,6 +320,7 @@ Always use full URLs:
```
### Linking to Code
Reference code in the main repository:
```markdown
@@ -319,21 +330,24 @@ See the [main configuration file](https://github.com/apache/superset/blob/master
## 🛠️ Common Documentation Tasks
### Adding a New Guide
1. Create the `.mdx` file in the appropriate directory
2. Add frontmatter with title and description
3. Update sidebar if needed (for manual sidebar configs)
### Adding API Documentation
The API docs use Swagger UI embedded in `/docs/api.mdx`:
```mdx
import SwaggerUI from "swagger-ui-react";
import "swagger-ui-react/swagger-ui.css";
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
<SwaggerUI url="/api/v1/openapi.json" />
```
### Adding Interactive Examples
Use MDX to create interactive documentation:
```mdx
@@ -360,6 +374,7 @@ When creating or updating documentation:
## 🔍 Searching and Navigation
### Sidebar Configuration
Sidebars are configured in `/sidebars.js`:
```javascript
@@ -385,6 +400,7 @@ module.exports = {
```
### Search
Docusaurus includes Algolia DocSearch integration configured in `docusaurus.config.ts`.
## 🚫 Common Pitfalls to Avoid
@@ -398,6 +414,7 @@ Docusaurus includes Algolia DocSearch integration configured in `docusaurus.conf
## 🔧 Troubleshooting
### Dev Server Issues
```bash
yarn stop # Kill any running servers
yarn clear # Clear cache
@@ -405,6 +422,7 @@ yarn start # Restart
```
### Build Failures
```bash
# Check for broken links
yarn build
@@ -417,7 +435,9 @@ yarn eslint
```
### Version Issues
If versions don't appear in dropdown:
1. Check `versions-config.json` includes the version
2. Verify version files exist in `<section>_versioned_docs/`
3. Restart dev server
@@ -432,9 +452,10 @@ If versions don't appear in dropdown:
## 📖 Real Examples and Patterns
### Example: Configuration Documentation Pattern
From `docs/configuration/configuring-superset.mdx`:
```mdx
````mdx
---
title: Configuring Superset
hide_title: true
@@ -452,7 +473,9 @@ Superset exposes hundreds of configurable parameters through its
```bash
export SUPERSET_CONFIG_PATH=/app/superset_config.py
```
```
````
````
**Key patterns:**
- Links to source code for reference
@@ -476,9 +499,10 @@ documentation at [docs.preset.io](https://docs.preset.io/).
### Connecting to a new database
<img src={useBaseUrl("/img/tutorial/tutorial_01_add_database_connection.png")} width="600" />
```
````
**Key patterns:**
- Import Docusaurus hooks for dynamic URLs
- Use of admonitions (:::tip) for helpful information
- Screenshots with useBaseUrl for proper path resolution
@@ -486,11 +510,12 @@ documentation at [docs.preset.io](https://docs.preset.io/).
- Step-by-step visual guides
### Example: API Documentation Pattern
From `docs/api.mdx`:
```mdx
import SwaggerUI from "swagger-ui-react";
import "swagger-ui-react/swagger-ui.css";
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
## API Documentation
@@ -498,6 +523,7 @@ import "swagger-ui-react/swagger-ui.css";
```
**Key patterns:**
- Embedding interactive Swagger UI
- Importing necessary CSS
- Direct API spec integration
@@ -508,49 +534,39 @@ import "swagger-ui-react/swagger-ui.css";
// For images in static folder
import useBaseUrl from "@docusaurus/useBaseUrl";
<img src={useBaseUrl("/img/feature-screenshot.png")} width="600" />
<img src={useBaseUrl('/img/feature-screenshot.png')} width="600" />
// With caption
<figure>
<img src={useBaseUrl("/img/dashboard.png")} alt="Dashboard view" />
<img src={useBaseUrl('/img/dashboard.png')} alt="Dashboard view" />
<figcaption>Superset Dashboard Interface</figcaption>
</figure>
```
### Multi-Tab Code Examples
```mdx
````mdx
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs
defaultValue="docker"
values={[
{label: 'Docker', value: 'docker'},
{label: 'Kubernetes', value: 'k8s'},
{label: 'PyPI', value: 'pypi'},
]}>
<TabItem value="docker">
```bash
docker-compose up
```
</TabItem>
<TabItem value="k8s">
```bash
kubectl apply -f superset.yaml
```
</TabItem>
<TabItem value="pypi">
```bash
pip install apache-superset
```
</TabItem>
{ label: 'Docker', value: 'docker' },
{ label: 'Kubernetes', value: 'k8s' },
{ label: 'PyPI', value: 'pypi' },
]}
>
<TabItem value="docker">```bash docker-compose up ```</TabItem>
<TabItem value="k8s">```bash kubectl apply -f superset.yaml ```</TabItem>
<TabItem value="pypi">```bash pip install apache-superset ```</TabItem>
</Tabs>
```
````
### Configuration File Examples
```mdx
````mdx
```python title="superset_config.py"
# Database connection example
SQLALCHEMY_DATABASE_URI = 'postgresql://user:password@localhost/superset'
@@ -565,7 +581,9 @@ FEATURE_FLAGS = {
'DASHBOARD_NATIVE_FILTERS': True,
}
```
```
````
````
### Cross-Referencing Pattern
@@ -578,11 +596,11 @@ For detailed configuration options, see:
External resources:
- [SQLAlchemy Documentation](https://docs.sqlalchemy.org/)
- [Flask Configuration](https://flask.palletsprojects.com/config/)
```
````
### Writing Installation Guides
```mdx
````mdx
## Prerequisites
:::warning
@@ -596,8 +614,10 @@ Ensure you have Python 3.9+ and Node.js 16+ installed before proceeding.
git clone https://github.com/apache/superset.git
cd superset
```
````
2. **Install Python dependencies**
```bash
pip install -e .
```
@@ -611,7 +631,8 @@ Ensure you have Python 3.9+ and Node.js 16+ installed before proceeding.
:::tip Success Check
Navigate to http://localhost:8088 and login with admin/admin
:::
```
````
### Documenting API Endpoints
@@ -630,9 +651,10 @@ Returns a list of charts.
```bash
curl -X GET "http://localhost:8088/api/v1/chart/" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
````
**Example Response:**
```json
{
"count": 42,
@@ -645,8 +667,10 @@ curl -X GET "http://localhost:8088/api/v1/chart/" \
]
}
```
```
---
**Note**: This documentation site serves as the primary resource for Superset users, administrators, and contributors. Always prioritize clarity, accuracy, and completeness when creating or updating documentation.
```
+13
View File
@@ -66,6 +66,7 @@ yarn version:add:components 1.2.0
```
What the script does:
1. Refreshes auto-generated content via `generate:smart` (database pages, API reference, component pages).
2. Calls `yarn docusaurus docs:version` (or the per-section equivalent) to snapshot the section.
3. Freezes any data-file imports (`@site/static/*.json`, `../../data/*.json`) into a snapshot-local `_versioned_data/` dir so the historical version doesn't silently mutate when the source files change.
@@ -73,6 +74,7 @@ What the script does:
5. Updates `versions-config.json` and `<section>_versions.json`.
**Do NOT use** the native Docusaurus commands directly (`yarn docusaurus docs:version`), as they will:
- ❌ Create version files but NOT update `versions-config.json`
- ❌ Skip auto-gen refresh, freezing whatever was on disk
- ❌ Skip data-import freezing, leaving the snapshot pointed at live data
@@ -82,9 +84,11 @@ What the script does:
### Managing Versions
#### With Automated Scripts
The automated scripts handle all configuration updates automatically. No manual editing required!
#### Manual Configuration
If creating versions manually, you'll need to:
1. **Update `versions-config.json`** (or `docusaurus.config.ts` if not using dynamic config):
@@ -109,6 +113,7 @@ If creating versions manually, you'll need to:
### Removing a Version
#### Using Automated Scripts (Recommended)
```bash
# Main Documentation
yarn version:remove:user_docs 1.0.0
@@ -124,6 +129,7 @@ yarn version:remove:components 1.0.0
```
#### Manual Removal
To manually remove a version:
1. **Delete the version folder** from the appropriate location:
@@ -153,6 +159,7 @@ To manually remove a version:
### Version Configuration Examples
#### Main Documentation (default plugin)
```typescript
docs: {
includeCurrentVersion: true,
@@ -174,6 +181,7 @@ docs: {
```
#### Developer Docs & Components (custom plugins)
```typescript
{
id: 'developer_docs',
@@ -210,23 +218,28 @@ docs: {
#### Version Not Showing After Creation
If you accidentally used `yarn docusaurus docs:version` instead of `yarn version:add`:
1. **Problem**: The version files were created but `versions-config.json` wasn't updated
2. **Solution**: Either:
- Revert the changes: `git restore user_docs_versions.json && rm -rf user_docs_versioned_docs/ user_docs_versioned_sidebars/`
- Then use the correct command: `yarn version:add:user_docs <version>`
For other issues:
- **Restart the server**: Changes to version configuration require a server restart
- **Check config file**: Ensure `versions-config.json` includes the new version
- **Verify files exist**: Check that versioned docs folder was created
#### Broken Links in Versioned Documentation
When creating a new version, links in the documentation are preserved as-is. Common issues:
- **Cross-section links**: Links between sections (e.g., from developer_docs to docs) need to be version-aware
- **Absolute vs relative paths**: Use relative paths within the same section
- **Version-specific URLs**: Update hardcoded URLs to use version variables
To fix broken links:
1. Use `type: 'doc'` with `docId` for version-aware navigation in navbar
2. Use relative paths within the same documentation section
3. Test all versions after creation to identify broken links
@@ -9,8 +9,8 @@ version: 2
Users can configure automated alerts and reports to send dashboards or charts to an email recipient or Slack channel.
- *Alerts* are sent when a SQL condition is reached
- *Reports* are sent on a schedule
- _Alerts_ are sent when a SQL condition is reached
- _Reports_ are sent on a schedule
Alerts and reports are disabled by default. To turn them on, you'll need to change configuration settings and install a suitable headless browser in your environment.
@@ -26,16 +26,18 @@ Alerts and reports are disabled by default. To turn them on, you'll need to chan
- emails: `SMTP_*` settings
- Slack messages: `SLACK_API_TOKEN`
- Users can customize the email subject by including date code placeholders, which will automatically be replaced with the corresponding UTC date when the email is sent. To enable this functionality, activate the `"DATE_FORMAT_IN_EMAIL_SUBJECT"` [feature flag](/admin-docs/configuration/configuring-superset#feature-flags). This enables date formatting in email subjects, preventing all reporting emails from being grouped into the same thread (optional for the reporting feature).
- Use date codes from [strftime.org](https://strftime.org/) to create the email subject.
- If no date code is provided, the original string will be used as the email subject.
- Use date codes from [strftime.org](https://strftime.org/) to create the email subject.
- If no date code is provided, the original string will be used as the email subject.
- Each alert/report has an "Include a link back to Superset" option (enabled by default) controlling whether the call-to-action link is included in email and Slack notifications. The link text in emails is configurable via `EMAIL_REPORTS_CTA`; the Slack message always uses "Explore in Superset". Uncheck the option when recipients should not receive a link to your Superset host, e.g. for external audiences.
##### Disable dry-run mode
Screenshots will be taken but no messages actually sent as long as `ALERT_REPORTS_NOTIFICATION_DRY_RUN = True`, its default value in `docker/pythonpath_dev/superset_config.py`. To disable dry-run mode and start receiving email/Slack notifications, set `ALERT_REPORTS_NOTIFICATION_DRY_RUN` to `False` in [superset config](https://github.com/apache/superset/blob/master/docker/pythonpath_dev/superset_config.py).
Screenshots will be taken but no messages actually sent as long as `ALERT_REPORTS_NOTIFICATION_DRY_RUN = True`, its default value in `docker/pythonpath_dev/superset_config.py`. To disable dry-run mode and start receiving email/Slack notifications, set `ALERT_REPORTS_NOTIFICATION_DRY_RUN` to `False` in [superset config](https://github.com/apache/superset/blob/master/docker/pythonpath_dev/superset_config.py).
#### In your `Dockerfile`
You'll need to extend the Superset image to include a headless browser. Your options include:
- Use Playwright with Chromium: this is the recommended approach as of version 4.1.x or greater. Playwright always uses Chromium — the `WEBDRIVER_TYPE` config setting has no effect when Playwright is active. A working example of a Dockerfile that installs these tools is provided under "Building your own production Docker image" on the [Docker Builds](/admin-docs/installation/docker-builds#building-your-own-production-docker-image) page. Enable the `PLAYWRIGHT_REPORTS_AND_THUMBNAILS` feature flag in your config to activate it.
- Use Firefox (Selenium): you'll need to install geckodriver and Firefox. Set `WEBDRIVER_TYPE` to `"firefox"` in your `superset_config.py`.
- Use Chrome (Selenium): you'll need to install Chrome. Set `WEBDRIVER_TYPE` to `"chrome"` in your `superset_config.py`.
@@ -131,7 +133,7 @@ Superset sends an HTTP POST with `Content-Type: application/json`:
},
"text": "Alert condition met: value exceeded threshold",
"description": "Monthly revenue dropped below target",
"url": "https://your-superset-host/superset/dashboard/1/"
"url": "https://your-superset-host/dashboard/1/"
}
```
@@ -173,6 +175,16 @@ ALERT_REPORTS_WEBHOOK_HTTPS_ONLY = True
When enabled, Superset rejects webhook configurations that use `http://` URLs.
#### Request Timeout
Webhook deliveries use a socket timeout so a request can't hang forever if the webhook target is unreachable, which would otherwise leave the report schedule stuck in a `WORKING` state. Configure it with:
```python
ALERT_REPORTS_WEBHOOK_TIMEOUT = 60 # seconds
```
Set to `None` to disable the timeout (not recommended).
#### Retry Behavior
Superset automatically retries webhook deliveries on `429 Too Many Requests` and `5xx` server errors using exponential backoff. Retries are bounded to roughly 120 seconds of cumulative wall-clock time (worst case ~210 seconds, because the bound is checked against the time elapsed before each attempt, so the final request can begin just under the limit and still run its full request timeout), after which the delivery is abandoned.
@@ -204,7 +216,7 @@ You need to replace default values with your custom Redis, Slack and/or SMTP con
Superset uses Celery beat and Celery worker(s) to send alerts and reports.
- The beat is the scheduler that tells the worker when to perform its tasks. This schedule is defined when you create the alert or report.
- The worker will process the tasks that need to be performed when an alert or report is fired.
- The worker will process the tasks that need to be performed when an alert or report is fired.
In the `CeleryConfig`, only the `beat_schedule` is relevant to this feature, the rest of the `CeleryConfig` can be changed for your needs.
@@ -244,6 +256,53 @@ class CeleryConfig:
}
CELERY_CONFIG = CeleryConfig
# Scheduled reports share one deadline across browser readiness, capture/PDF
# generation, delivery, and terminal-state persistence. The effective budget
# for a schedule is min(this value, the schedule's working_timeout), so the
# per-schedule field keeps its meaning as a user-facing cap. The default (one
# hour) matches the historical working_timeout default, so upgrading changes
# no default behavior; lower it to enforce a tighter report SLA.
ALERT_REPORTS_EXECUTION_BUDGET_SECONDS = 3600
# These reserves are part of (not additions to) the total budget and their sum
# must be less than it. Readiness polling stops in time to leave capacity for
# the later phases.
ALERT_REPORTS_EXECUTION_CAPTURE_RESERVE_SECONDS = 60
ALERT_REPORTS_EXECUTION_DELIVERY_RESERVE_SECONDS = 120
ALERT_REPORTS_EXECUTION_CLEANUP_RESERVE_SECONDS = 30
# Celery's hard limit leaves this additional window for terminal cleanup after
# the soft limit, which equals the resolved execution budget (the configured
# budget capped by each schedule's working_timeout).
# ALERT_REPORTS_WORKING_TIME_OUT_KILL controls these Celery limits; disabling
# it does not disable the application deadline above.
ALERT_REPORTS_EXECUTION_HARD_TIMEOUT_GRACE_SECONDS = 30
# Invalid budget/reserve combinations fail application startup instead of
# allowing every scheduled report to fail later. A report Celery soft timeout
# records ERROR and increments `reports.execute.celery_soft_timeout`; it does
# not attempt an in-band customer error notification during the hard-limit
# grace window. Alert schedules retain their existing timeout notifications.
#
# The application deadline is cooperative between synchronous phases. The
# Celery limits provide the final preemption boundary when the worker pool
# supports them; PDF construction is checked immediately before and after the
# synchronous builder but cannot be interrupted inside that call.
#
# Sizing the budget against infrastructure limits:
# - Kubernetes (or similar) pod termination grace must exceed
# budget + hard-timeout grace, or in-flight reports are killed mid-run on
# every deploy/node drain despite the application deadline.
# - The web server's per-request timeout (e.g. gunicorn ``timeout``) bounds
# each individual chart data request made by the headless browser -- not
# the report as a whole. Readiness allowance beyond that per-request
# ceiling buys nothing for a single slow chart (its request dies at the
# web layer and the chart reaches an error state), but multi-chart and
# tiled captures legitimately accumulate total time well past it.
# Screenshot-specific waits continue to apply to thumbnails and other
# standalone screenshot calls. Scheduled reports derive their waits from the
# shared execution deadline above.
SCREENSHOT_LOCATE_WAIT = 100
SCREENSHOT_LOAD_WAIT = 600
@@ -277,7 +336,7 @@ WEBDRIVER_OPTION_ARGS = [
]
# This is for internal use, you can keep http
WEBDRIVER_BASEURL = "http://superset:8088" # When running using docker compose use "http://superset_app:8088'
WEBDRIVER_BASEURL = "http://superset:8088" # This is also the default for Docker Compose, where the app service is named "superset"
# This is the link sent to the recipient. Change to your domain, e.g. https://superset.mydomain.com
WEBDRIVER_BASEURL_USER_FRIENDLY = "http://localhost:8088"
```
@@ -313,7 +372,7 @@ Please refer to `ExecutorType` in the codebase for other executor types.
It's also possible to specify a minimum interval between each report's execution through the config file:
``` python
```python
# Set a minimum interval threshold between executions (for each Alert/Report)
# Value should be an integer
ALERT_MINIMUM_INTERVAL = int(timedelta(minutes=10).total_seconds())
@@ -322,7 +381,7 @@ REPORT_MINIMUM_INTERVAL = int(timedelta(minutes=5).total_seconds())
Alternatively, you can assign a function to `ALERT_MINIMUM_INTERVAL` and/or `REPORT_MINIMUM_INTERVAL`. This is useful to dynamically retrieve a value as needed:
``` python
```python
def alert_dynamic_minimal_interval(**kwargs) -> int:
"""
Define logic here to retrieve the value dynamically
@@ -335,7 +394,7 @@ ALERT_MINIMUM_INTERVAL = alert_dynamic_minimal_interval
For security, Superset rewrites external links in alert/report email HTML so
they go through a warning page before the user is navigated to the external
site. Internal links (matching your configured base URL) are not affected.
site. Internal links (matching your configured base URL) are not affected.
```python
# Disable external link redirection entirely (default: True)
@@ -347,17 +406,17 @@ to determine which hosts are internal.
## Troubleshooting
There are many reasons that reports might not be working. Try these steps to check for specific issues.
There are many reasons that reports might not be working. Try these steps to check for specific issues.
### Confirm feature flag is enabled and you have sufficient permissions
If you don't see "Alerts & Reports" under the *Manage* section of the Settings dropdown in the Superset UI, you need to enable the `ALERT_REPORTS` feature flag (see above). Enable another feature flag and check to see that it took effect, to verify that your config file is getting loaded.
If you don't see "Alerts & Reports" under the _Manage_ section of the Settings dropdown in the Superset UI, you need to enable the `ALERT_REPORTS` feature flag (see above). Enable another feature flag and check to see that it took effect, to verify that your config file is getting loaded.
Log in as an admin user to ensure you have adequate permissions.
### Check the logs of your Celery worker
This is the best source of information about the problem. In a docker compose deployment, you can do this with a command like `docker logs superset_worker --since 1h`.
This is the best source of information about the problem. In a docker compose deployment, you can do this with a command like `docker logs superset_worker --since 1h`.
### Check web browser and webdriver installation
@@ -369,7 +428,7 @@ If you are handling the installation of the headless browser on your own, do you
One symptom of an invalid connection to an email server is receiving an error of `[Errno 110] Connection timed out` in your logs when the report tries to send.
Confirm via testing that your outbound email configuration is correct. Here is the simplest test, for an un-authenticated email SMTP email service running on port 25. If you are sending over SSL, for instance, study how [Superset's codebase sends emails](https://github.com/apache/superset/blob/master/superset/utils/core.py#L818) and then test with those commands and arguments.
Confirm via testing that your outbound email configuration is correct. Here is the simplest test, for an un-authenticated email SMTP email service running on port 25. If you are sending over SSL, for instance, study how [Superset's codebase sends emails](https://github.com/apache/superset/blob/master/superset/utils/core.py#L818) and then test with those commands and arguments.
Start Python in your worker environment, replace all example values, and run:
@@ -395,16 +454,16 @@ This should send an email.
Possible fixes:
- Some cloud hosts disable outgoing unauthenticated SMTP email to prevent spam. For instance, [Azure blocks port 25 by default on some machines](https://learn.microsoft.com/en-us/azure/virtual-network/troubleshoot-outbound-smtp-connectivity). Enable that port or use another sending method.
- Some cloud hosts disable outgoing unauthenticated SMTP email to prevent spam. For instance, [Azure blocks port 25 by default on some machines](https://learn.microsoft.com/en-us/azure/virtual-network/troubleshoot-outbound-smtp-connectivity). Enable that port or use another sending method.
- Use another set of SMTP credentials that you verify works in this setup.
### Browse to your report from the worker
The worker may be unable to reach the report. It will use the value of `WEBDRIVER_BASEURL` to browse to the report. If that route is invalid, or presents an authentication challenge that the worker can't pass, the report screenshot will fail.
The worker may be unable to reach the report. It will use the value of `WEBDRIVER_BASEURL` to browse to the report. If that route is invalid, or presents an authentication challenge that the worker can't pass, the report screenshot will fail.
Check this by attempting to `curl` the URL of a report that you see in the error logs of your worker. For instance, from the worker environment, run `curl http://superset_app:8088/superset/dashboard/1/`. You may get different responses depending on whether the dashboard exists - for example, you may need to change the `1` in that URL. If there's a URL in your logs from a failed report screenshot, that's a good place to start. The goal is to determine a valid value for `WEBDRIVER_BASEURL` and determine if an issue like HTTPS or authentication is redirecting your worker.
Check this by attempting to `curl` the URL of a report that you see in the error logs of your worker. For instance, from the worker environment, run `curl http://superset:8088/dashboard/1/`. You may get different responses depending on whether the dashboard exists - for example, you may need to change the `1` in that URL. If there's a URL in your logs from a failed report screenshot, that's a good place to start. The goal is to determine a valid value for `WEBDRIVER_BASEURL` and determine if an issue like HTTPS or authentication is redirecting your worker.
In a deployment with authentication measures enabled like HTTPS and Single Sign-On, it may make sense to have the worker navigate directly to the Superset application running in the same location, avoiding the need to sign in. For instance, you could use `WEBDRIVER_BASEURL="http://superset_app:8088"` for a docker compose deployment, and set `"force_https": False,` in your `TALISMAN_CONFIG`.
In a deployment with authentication measures enabled like HTTPS and Single Sign-On, it may make sense to have the worker navigate directly to the Superset application running in the same location, avoiding the need to sign in. For instance, you could use `WEBDRIVER_BASEURL="http://superset:8088"` for a docker compose deployment, and set `"force_https": False,` in your `TALISMAN_CONFIG` — appropriate only for an isolated development stack or when HTTPS is enforced by a trusted proxy in front of Superset.
### Duplicate report deliveries
@@ -512,6 +571,7 @@ schedule the queries that have `schedule_info` in their JSON metadata. For sched
Airflow, additional fields can be easily added to the configuration file above.
:::resources
- [Tutorial: Automated Alerts and Reporting via Slack/Email in Superset](https://dev.to/ngtduc693/apache-superset-topic-5-automated-alerts-and-reporting-via-slackemail-in-superset-2gbe)
- [Blog: Integrating Slack alerts and Apache Superset for better data observability](https://medium.com/affinityanswers-tech/integrating-slack-alerts-and-apache-superset-for-better-data-observability-fd2f9a12c350)
:::
:::
@@ -54,8 +54,8 @@ celery --app=superset.tasks.celery_app:app beat
To setup a result backend, you need to pass an instance of a derivative of `BaseCache` (`from
flask_caching.backends.base import BaseCache`) to the RESULTS_BACKEND configuration key in your
superset_config.py. You can use Memcached, Redis, S3 (https://pypi.python.org/pypi/s3werkzeugcache),
memory or the file system (in a single server-type setup or for testing), or to write your own
superset_config.py. You can use Memcached, Redis, S3, MinIO, memory
or the file system (in a single server-type setup or for testing), or to write your own
caching interface. Your `superset_config.py` may look something like:
```python
@@ -89,6 +89,12 @@ issues arise. Please clear your existing results cache store when upgrading an e
- SQL Lab will _only run your queries asynchronously if_ you enable **Asynchronous Query Execution**
in your database settings (Sources > Databases > Edit record).
- In order to use dedicated results backend, additional python libraries must be installed. These libraries can be installed using pip.
- [redis-py](https://pypi.org/project/redis/) for Redis.
- [pylibmc](https://pypi.org/project/pylibmc/) for memcached
- [s3werkzeugcache](https://pypi.python.org/pypi/s3werkzeugcache) for S3
- [minio-flask-cache](https://github.com/greggailly/minio-flask-cache) for MinIO or other S3 compatible service
## Celery Flower
Flower is a web based tool for monitoring the Celery cluster which you can install from pip:
@@ -104,5 +110,6 @@ celery --app=superset.tasks.celery_app:app flower
```
:::resources
- [Blog: How to Set Up Global Async Queries (GAQ) in Apache Superset](https://medium.com/@ngigilevis/how-to-set-up-global-async-queries-gaq-in-apache-superset-a-complete-guide-9d2f4a047559)
:::
:::
+9 -9
View File
@@ -13,7 +13,7 @@ Cross-account IAM role assumption via STS `AssumeRole` is supported, allowing a
## Prerequisites
- Enable the `AWS_DATABASE_IAM_AUTH` feature flag in `superset_config.py`. IAM authentication is gated behind this flag; if it is disabled, connections using `aws_iam` fail with *"AWS IAM database authentication is not enabled."*
- Enable the `AWS_DATABASE_IAM_AUTH` feature flag in `superset_config.py`. IAM authentication is gated behind this flag; if it is disabled, connections using `aws_iam` fail with _"AWS IAM database authentication is not enabled."_
```python
FEATURE_FLAGS = {
"AWS_DATABASE_IAM_AUTH": True,
@@ -48,14 +48,14 @@ IAM authentication is configured via the **encrypted_extra** field of the databa
}
```
| Field | Required | Description |
|-------|----------|-------------|
| `enabled` | Yes | Set to `true` to activate IAM auth |
| `role_arn` | No | ARN of the cross-account IAM role to assume via STS. Omit for same-account auth |
| `external_id` | No | External ID for the STS `AssumeRole` call, if required by the target role's trust policy |
| `region` | Yes | AWS region of the database cluster |
| `db_username` | Yes | The database username associated with the IAM identity |
| `session_duration` | No | STS session duration in seconds (default: `3600`) |
| Field | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------------------------- |
| `enabled` | Yes | Set to `true` to activate IAM auth |
| `role_arn` | No | ARN of the cross-account IAM role to assume via STS. Omit for same-account auth |
| `external_id` | No | External ID for the STS `AssumeRole` call, if required by the target role's trust policy |
| `region` | Yes | AWS region of the database cluster |
| `db_username` | Yes | The database username associated with the IAM identity |
| `session_duration` | No | STS session duration in seconds (default: `3600`) |
### Redshift (Serverless)
+82 -4
View File
@@ -15,9 +15,8 @@ fail-fast behavior ensures operators are immediately aware of infrastructure iss
Superset uses [Flask-Caching](https://flask-caching.readthedocs.io/) for caching purposes.
Flask-Caching supports various caching backends, including Redis (recommended), Memcached,
SimpleCache (in-memory), or the local filesystem.
[Custom cache backends](https://flask-caching.readthedocs.io/en/latest/#custom-cache-backends)
are also supported.
SimpleCache (in-memory), MinIO/S3, or the local filesystem.
[Custom cache backends](https://flask-caching.readthedocs.io/en/latest/#custom-cache-backends) are also supported.
Caching can be configured by providing dictionaries in
`superset_config.py` that comply with [the Flask-Caching config specifications](https://flask-caching.readthedocs.io/en/latest/#configuring-flask-caching).
@@ -47,6 +46,7 @@ In order to use dedicated cache stores, additional python libraries must be inst
- For Redis: we recommend the [redis](https://pypi.python.org/pypi/redis) Python package
- Memcached: we recommend using [pylibmc](https://pypi.org/project/pylibmc/) client library as
`python-memcached` does not handle storing binary data correctly.
- MinIO (S3): we recommend using the [minio-flask-cache](https://github.com/greggailly/minio-flask-cache) package
These libraries can be installed using pip.
@@ -76,6 +76,21 @@ value defined in `DATA_CACHE_CONFIG`.
Note, that by setting the cache timeout to `-1`, caching for charting data can be disabled, either
per chart, dataset or database, or by default if set in `DATA_CACHE_CONFIG`.
## Limiting Cached Result Size
Very large chart or SQL query results can flood the cache backend (Redis/Memcached), evicting many
smaller useful entries or exhausting memory. To cap the size of any single value written to the data
cache, set `DATA_CACHE_MAX_VALUE_SIZE` (in bytes) in `superset_config.py`:
```python
DATA_CACHE_MAX_VALUE_SIZE = 10 * 1024 * 1024 # 10 MB
```
When a result's serialized size exceeds this threshold it is not written to the data cache — the
chart still renders, but the next load re-queries the datasource instead of getting a cache hit. The
`skip_cache_value_too_large` statsd metric is incremented each time this happens. Set to `None` (the
default) to disable the check.
## SQL Lab Query Results
Caching for SQL Lab query results is used when async queries are enabled and is configured using
@@ -119,6 +134,50 @@ CELERY_CONFIG = CustomCeleryConfig
This will cache the top 5 most popular dashboards every hour. For other
strategies, check the `superset/tasks/cache.py` file.
### Warming Up Native Filter Options
Native filter Value-type dropdown option queries (e.g. `SELECT DISTINCT column FROM table`) are
cached the same way as chart data, via `DATA_CACHE_CONFIG`. However, the strategies above only warm
up chart render queries, so the first user to open a dashboard's filter dropdown after a cache entry
expires still triggers a fresh database query.
The `native_filter_options` strategy pre-populates the cache for these dropdown queries. It reads
each dashboard's `native_filter_configuration`, builds the same `filter_select` chart-data query the
frontend would send, and executes it as the configured `SUPERSET_CACHE_WARMUP_USER`:
```python
class CustomCeleryConfig(CeleryConfig):
beat_schedule = {
**CeleryConfig.beat_schedule,
'cache-warmup-native-filters': {
'task': 'cache-warmup',
'schedule': crontab(minute=0, hour=3), # daily at 03:00
'kwargs': {
'strategy_name': 'native_filter_options',
'dashboard_ids': [1, 2, 3],
},
},
}
```
Requirements and limitations:
- `SUPERSET_CACHE_WARMUP_USER` must be set to a user with access to the dashboards and datasets
referenced by the native filters.
- `DATA_CACHE_CONFIG` must use a backend that actually persists entries (Redis recommended); the
default `NullCache` discards writes, so warming has nothing to warm. The effective timeout also
needs to be positive — `NATIVE_FILTER_OPTIONS_CACHE_TIMEOUT = -1` disables cache writes for these
queries entirely, even with a working backend.
- Schedule the warm-up at least as often as the effective native filter cache timeout (whichever of
`NATIVE_FILTER_OPTIONS_CACHE_TIMEOUT`, the chart/dataset/database timeout, or `DATA_CACHE_CONFIG`'s
default applies). A looser schedule still leaves a window of cold, unwarmed queries between expiry
and the next run — the daily example above assumes a TTL of a day or more.
- Cache entries are warmed under the warm-up user's own cache partition, the same entry that user
would create by opening the filter dropdown manually. Users with a different role set or row-level
security context may still see a cache miss on first load.
- Cascading/dependent native filters and search-term variants of filter option queries are not
warmed by this strategy.
## Caching Thumbnails
This is an optional feature that can be turned on by activating its [feature flag](/admin-docs/configuration/configuring-superset#feature-flags) on config:
@@ -286,6 +345,24 @@ DISTRIBUTED_COORDINATION_CONFIG = {
}
```
By default, connections opened for `DISTRIBUTED_COORDINATION_CONFIG` (as well as
`GLOBAL_ASYNC_QUERIES_CACHE_BACKEND`, which uses the same `RedisCache`/`RedisSentinelCache`
backend) have no socket timeout. This can be overridden with `CACHE_REDIS_SOCKET_TIMEOUT` and
`CACHE_REDIS_SOCKET_CONNECT_TIMEOUT`, both in seconds:
```python
DISTRIBUTED_COORDINATION_CONFIG = {
"CACHE_TYPE": "RedisCache",
"CACHE_REDIS_HOST": "localhost",
"CACHE_REDIS_PORT": 6379,
"CACHE_REDIS_SOCKET_TIMEOUT": 5, # seconds
"CACHE_REDIS_SOCKET_CONNECT_TIMEOUT": 5, # seconds
}
```
These apply to `RedisSentinelCache` connections as well, covering both the sentinel-node
connections and the resolved master connection.
### Distributed Lock TTL
You can configure the default lock TTL (time-to-live) in seconds. Locks automatically expire after
@@ -308,6 +385,7 @@ While database-backed operations work reliably, the Redis backend is recommended
deployments where low latency and reduced database load are important.
:::resources
- [Blog: The Data Engineer's Guide to Lightning-Fast Superset Dashboards](https://preset.io/blog/the-data-engineers-guide-to-lightning-fast-apache-superset-dashboards/)
- [Blog: Accelerating Dashboards with Materialized Views](https://preset.io/blog/accelerating-apache-superset-dashboards-with-materialized-views/)
:::
:::
@@ -97,6 +97,50 @@ for more information on how to configure it.
At the very least, you'll want to change `SECRET_KEY` and `SQLALCHEMY_DATABASE_URI`. Continue reading for more about each of these.
## Chart-data query timing
Set `CHART_DATA_INCLUDE_TIMING = True` to add an optional versioned timing object
to every successful JSON query result returned by the chart-data API. The setting
is `False` by default, so enabling it is an explicit API-contract choice for an
operator. File exports, streaming responses, and HTTP error responses do not
include this object.
```json
{
"timing": {
"version": 1,
"query": {
"query_planning_ms": 1.23,
"cache_resolution_ms": 0.45,
"data_acquisition_ms": null,
"payload_assembly_ms": 0.67,
"total_ms": 2.98
}
}
}
```
Durations are milliseconds rounded to two decimal places. A numeric `0.0`
means that the corresponding stage ran but rounded below that precision;
`null` means it did not apply. For example, `data_acquisition_ms` is null for
a normal dataframe cache hit, while metadata-only results have null phase values
and a numeric total.
The phases have fixed ownership: `query_planning_ms` includes Jinja rendering,
row-level-security transformation, and cache identity; `cache_resolution_ms`
includes cache lookup, compatibility policy, deserialization, and rehydration;
`data_acquisition_ms` includes database work and annotation dependencies; and
`payload_assembly_ms` includes response shaping and AUTO-currency fallback.
`total_ms` is measured over one continuous per-query execution interval. It
contains the exposed stages and unattributed work such as query-result cache
persistence, so it is not the sum of the phase values. Query-context cache
persistence is excluded. The total also excludes request parsing,
authorization, contribution-total work before the per-query loop, client
post-processing, JSON serialization, network transfer, and background async
producer execution. Additive optional fields can preserve version 1; a field
rename, removal, or semantic change requires a new version.
## Specifying a SECRET_KEY
### Adding an initial SECRET_KEY
@@ -225,7 +269,7 @@ RequestHeader set X-Forwarded-Proto "https"
## Configuring the application root
*Please be advised that this feature is in BETA.*
_Please be advised that this feature is in BETA._
Superset supports running the application under a non-root path. The root path
prefix can be specified in one of three ways:
@@ -263,6 +307,22 @@ to simplify the process of setting up a non-default root path across the service
In `docker/.env-local` set `SUPERSET_APP_ROOT` to the desired prefix and then bring the
services up with `docker compose up --detach`.
### Swagger UI
By default, Superset's Swagger UI and OpenAPI spec (enabled via `FAB_API_SWAGGER_UI`) are
served by Flask-AppBuilder and don't account for a non-root `APPLICATION_ROOT` prefix. If
you're running Superset behind a URL prefix and want the Swagger UI and OpenAPI spec to
resolve correctly, set:
```python
FAB_API_SWAGGER_UI_SUPERSET_APP_ROOT = True
```
in your `superset_config.py` file. This serves an `APPLICATION_ROOT`-aware Swagger UI and
OpenAPI spec at `/swagger/<version>` and `/api/<version>/_openapi` respectively, resolved
through the configured prefix. This flag only takes effect when `FAB_API_SWAGGER_UI` is
also enabled, and defaults to `False`.
## Custom OAuth2 Configuration
Superset is built on Flask-AppBuilder (FAB), which supports many providers out of the box
@@ -312,10 +372,13 @@ AUTH_USER_REGISTRATION_ROLE = "Public"
```
In case you want to assign the `Admin` role on new user registration, it can be assigned as follows:
```python
AUTH_USER_REGISTRATION_ROLE = "Admin"
```
If you encounter the [issue](https://github.com/apache/superset/issues/13243) of not being able to list users from the Superset main page settings, although a newly registered user has an `Admin` role, please re-run `superset init` to sync the required permissions. Below is the command to re-run `superset init` using docker compose.
```
docker-compose exec superset superset init
```
@@ -568,5 +631,6 @@ SUPERSET_DASHBOARD_POSITION_DATA_LIMIT = 131072 # double the default
Alternatively, split a very large dashboard into several smaller ones. Note that this check is enforced when saving layout edits in the UI; a dashboard imported from a ZIP with an oversized layout will load and render, but cannot be edited and re-saved until the limit is raised.
:::resources
- [Blog: Feature Flags in Apache Superset](https://preset.io/blog/feature-flags-in-apache-superset-and-preset/)
:::
:::
@@ -18,23 +18,23 @@ code is less ambiguous and is unique to all regions in the world.
## Included Maps
The current list of countries can be found in the src
[legacy-plugin-chart-country-map/src/countries.ts](https://github.com/apache/superset/blob/master/superset-frontend/plugins/legacy-plugin-chart-country-map/src/countries.ts)
[plugin-chart-country-map/src/countries.ts](https://github.com/apache/superset/blob/master/superset-frontend/plugins/plugin-chart-country-map/src/countries.ts)
The Country Maps visualization already ships with the maps for the following countries:
<ul style={{columns: 3}}>
{countriesData.countries.map((country, index) => (
<li key={index}>{country}</li>
))}
<ul style={{ columns: 3 }}>
{countriesData.countries.map((country, index) => (
<li key={index}>{country}</li>
))}
</ul>
## Adding a New Country
To add a new country to the list, you'd have to edit files in
[@superset-ui/legacy-plugin-chart-country-map](https://github.com/apache/superset/tree/master/superset-frontend/plugins/legacy-plugin-chart-country-map).
[@superset-ui/plugin-chart-country-map](https://github.com/apache/superset/tree/master/superset-frontend/plugins/plugin-chart-country-map).
1. Generate a new GeoJSON file for your country following the guide in [this Jupyter notebook](https://github.com/apache/superset/blob/master/superset-frontend/plugins/legacy-plugin-chart-country-map/scripts/Country%20Map%20GeoJSON%20Generator.ipynb).
2. Edit the countries list in [legacy-plugin-chart-country-map/src/countries.ts](https://github.com/apache/superset/blob/master/superset-frontend/plugins/legacy-plugin-chart-country-map/src/countries.ts).
1. Generate a new GeoJSON file for your country following the guide in [this Jupyter notebook](https://github.com/apache/superset/blob/master/superset-frontend/plugins/plugin-chart-country-map/scripts/Country%20Map%20GeoJSON%20Generator.ipynb).
2. Edit the countries list in [plugin-chart-country-map/src/countries.ts](https://github.com/apache/superset/blob/master/superset-frontend/plugins/plugin-chart-country-map/src/countries.ts).
3. Install superset-frontend dependencies: `cd superset-frontend && npm install`
4. Verify your countries in Superset plugins storybook: `npm run plugins:storybook`.
5. Build and install Superset from source code.
+17 -10
View File
@@ -7,7 +7,7 @@ version: 1
import featureFlags from '@site/static/feature-flags.json';
export const FlagTable = ({flags}) => (
export const FlagTable = ({ flags }) => (
<table>
<thead>
<tr>
@@ -17,14 +17,21 @@ export const FlagTable = ({flags}) => (
</tr>
</thead>
<tbody>
{flags.map((flag) => (
{flags.map(flag => (
<tr key={flag.name}>
<td><code>{flag.name}</code></td>
<td><code>{flag.default ? 'True' : 'False'}</code></td>
<td>
<code>{flag.name}</code>
</td>
<td>
<code>{flag.default ? 'True' : 'False'}</code>
</td>
<td>
{flag.description}
{flag.docs && (
<> (<a href={flag.docs}>docs</a>)</>
<>
{' '}
(<a href={flag.docs}>docs</a>)
</>
)}
</td>
</tr>
@@ -50,12 +57,12 @@ FEATURE_FLAGS = {
Feature flags progress through lifecycle stages:
| Stage | Description |
|-------|-------------|
| Stage | Description |
| --------------- | ------------------------------------------------------------------------------ |
| **Development** | Experimental features under active development. May be incomplete or unstable. |
| **Testing** | Feature complete but undergoing testing. Usable but may contain bugs. |
| **Stable** | Production-ready features. Safe for all deployments. |
| **Deprecated** | Features scheduled for removal. Migrate away from these. |
| **Testing** | Feature complete but undergoing testing. Usable but may contain bugs. |
| **Stable** | Production-ready features. Safe for all deployments. |
| **Deprecated** | Features scheduled for removal. Migrate away from these. |
---
@@ -148,10 +148,10 @@ datasets by saving the following YAML to file and then running the **import_data
```yaml
databases:
- database_name: main
tables:
- table_name: random_time_series
columns:
- column_name: ds
verbose_name: datetime
- database_name: main
tables:
- table_name: random_time_series
columns:
- column_name: ds
verbose_name: datetime
```
@@ -18,7 +18,9 @@ DECKGL_BASE_MAP = [
['tile://https://your_personal_url/{z}/{x}/{y}.png', 'MyTile']
]
```
Openstreetmap tiles url can be added without prefix.
```python
DECKGL_BASE_MAP = [
['https://c.tile.openstreetmap.org/{z}/{x}/{y}.png', 'OpenStreetMap']
@@ -53,6 +55,7 @@ DECKGL_BASE_MAP = [
```
Default values are:
```python
DECKGL_BASE_MAP = [
['https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'Streets (OSM)'],
@@ -73,6 +76,7 @@ Setting `DECKGL_BASE_MAP` overwrite default values
:::
After defining your map tiles, set them in these variables:
- `CORS_OPTIONS`
- `connect-src` of `TALISMAN_CONFIG` and `TALISMAN_CONFIG_DEV` variables.
+89 -87
View File
@@ -55,11 +55,11 @@ The MCP server runs as a separate process alongside Superset:
superset mcp run --host 127.0.0.1 --port 5008
```
| Flag | Default | Description |
|------|---------|-------------|
| `--host` | `127.0.0.1` | Host to bind to |
| `--port` | `5008` | Port to bind to |
| `--debug` | off | Enable debug logging |
| Flag | Default | Description |
| --------- | ----------- | -------------------- |
| `--host` | `127.0.0.1` | Host to bind to |
| `--port` | `5008` | Port to bind to |
| `--debug` | off | Enable debug logging |
The endpoint is available at `http://<host>:<port>/mcp`.
@@ -193,22 +193,24 @@ MCP_JWT_AUDIENCE = "your-audience"
:::warning
Store `MCP_JWT_SECRET` securely. Never commit it to version control. Use environment variables:
```python
import os
MCP_JWT_SECRET = os.environ.get("MCP_JWT_SECRET")
```
:::
#### JWT claims
The MCP server validates these standard claims:
| Claim | Config Key | Description |
|-------|-----------|-------------|
| `exp` | -- | Expiration time (always validated) |
| `iss` | `MCP_JWT_ISSUER` | Token issuer (optional but recommended) |
| `aud` | `MCP_JWT_AUDIENCE` | Token audience (optional but recommended) |
| `sub` | -- | Subject -- primary claim used to resolve the Superset user |
| Claim | Config Key | Description |
| ----- | ------------------ | ---------------------------------------------------------- |
| `exp` | -- | Expiration time (always validated) |
| `iss` | `MCP_JWT_ISSUER` | Token issuer (optional but recommended) |
| `aud` | `MCP_JWT_AUDIENCE` | Token audience (optional but recommended) |
| `sub` | -- | Subject -- primary claim used to resolve the Superset user |
#### User resolution
@@ -435,7 +437,7 @@ services:
superset:
image: apache/superset:latest
ports:
- "8088:8088"
- '8088:8088'
volumes:
- ./superset_config.py:/app/superset_config.py
environment:
@@ -443,9 +445,9 @@ services:
mcp:
image: apache/superset:latest
command: ["superset", "mcp", "run", "--host", "0.0.0.0", "--port", "5008"]
command: ['superset', 'mcp', 'run', '--host', '0.0.0.0', '--port', '5008']
ports:
- "5008:5008"
- '5008:5008'
volumes:
- ./superset_config.py:/app/superset_config.py
environment:
@@ -494,31 +496,31 @@ All MCP settings go in `superset_config.py`. Defaults are defined in `superset/m
### Core
| Setting | Default | Description |
|---------|---------|-------------|
| `MCP_SERVICE_HOST` | `"localhost"` | Host the MCP server binds to |
| `MCP_SERVICE_PORT` | `5008` | Port the MCP server binds to |
| `MCP_SERVICE_URL` | `None` | Public base URL for MCP-generated links (set this when behind a reverse proxy) |
| `MCP_DEBUG` | `False` | Enable debug logging |
| `MCP_DEV_USERNAME` | -- | Superset username for development mode (no auth) |
| `MCP_RBAC_ENABLED` | `True` | Enforce Superset's role-based access control on MCP tool calls. When `True`, each tool checks that the authenticated user has the required FAB permission before executing. Disable only for testing or trusted-network deployments. |
| `MCP_DISABLED_TOOLS` | `set()` | Set of tool names to remove from the MCP server at startup. Disabled tools are never advertised to AI clients during tool discovery. Useful when a custom extension tool should replace a built-in Superset tool. See [Disabling built-in tools](#disabling-built-in-tools). |
| Setting | Default | Description |
| -------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MCP_SERVICE_HOST` | `"localhost"` | Host the MCP server binds to |
| `MCP_SERVICE_PORT` | `5008` | Port the MCP server binds to |
| `MCP_SERVICE_URL` | `None` | Public base URL for MCP-generated links (set this when behind a reverse proxy) |
| `MCP_DEBUG` | `False` | Enable debug logging |
| `MCP_DEV_USERNAME` | -- | Superset username for development mode (no auth) |
| `MCP_RBAC_ENABLED` | `True` | Enforce Superset's role-based access control on MCP tool calls. When `True`, each tool checks that the authenticated user has the required FAB permission before executing. Disable only for testing or trusted-network deployments. |
| `MCP_DISABLED_TOOLS` | `set()` | Set of tool names to remove from the MCP server at startup. Disabled tools are never advertised to AI clients during tool discovery. Useful when a custom extension tool should replace a built-in Superset tool. See [Disabling built-in tools](#disabling-built-in-tools). |
### Authentication
| Setting | Default | Description |
|---------|---------|-------------|
| `MCP_AUTH_ENABLED` | `False` | Enable JWT authentication |
| `MCP_JWT_ALGORITHM` | `"RS256"` | JWT signing algorithm (`RS256` or `HS256`) |
| `MCP_JWKS_URI` | `None` | JWKS endpoint URL (RS256) |
| `MCP_JWT_PUBLIC_KEY` | `None` | Static RSA public key string (RS256) |
| `MCP_JWT_SECRET` | `None` | Shared secret string (HS256) |
| `MCP_JWT_ISSUER` | `None` | Expected `iss` claim |
| `MCP_JWT_AUDIENCE` | `None` | Expected `aud` claim |
| `MCP_REQUIRED_SCOPES` | `[]` | Required JWT scopes |
| `MCP_JWT_DEBUG_ERRORS` | `False` | Log detailed JWT errors server-side (never exposed in HTTP responses per RFC 6750) |
| `MCP_AUTH_FACTORY` | `None` | Custom auth provider factory `(flask_app) -> auth_provider`. Takes precedence over built-in JWT |
| `MCP_USER_RESOLVER` | `None` | Custom function `(app, access_token) -> username` to extract a Superset username from a validated JWT token. When `None`, the default resolver checks `preferred_username`, `username`, `email`, and `sub` claims in that order. |
| Setting | Default | Description |
| ---------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MCP_AUTH_ENABLED` | `False` | Enable JWT authentication |
| `MCP_JWT_ALGORITHM` | `"RS256"` | JWT signing algorithm (`RS256` or `HS256`) |
| `MCP_JWKS_URI` | `None` | JWKS endpoint URL (RS256) |
| `MCP_JWT_PUBLIC_KEY` | `None` | Static RSA public key string (RS256) |
| `MCP_JWT_SECRET` | `None` | Shared secret string (HS256) |
| `MCP_JWT_ISSUER` | `None` | Expected `iss` claim |
| `MCP_JWT_AUDIENCE` | `None` | Expected `aud` claim |
| `MCP_REQUIRED_SCOPES` | `[]` | Required JWT scopes |
| `MCP_JWT_DEBUG_ERRORS` | `False` | Log detailed JWT errors server-side (never exposed in HTTP responses per RFC 6750) |
| `MCP_AUTH_FACTORY` | `None` | Custom auth provider factory `(flask_app) -> auth_provider`. Takes precedence over built-in JWT |
| `MCP_USER_RESOLVER` | `None` | Custom function `(app, access_token) -> username` to extract a Superset username from a validated JWT token. When `None`, the default resolver checks `preferred_username`, `username`, `email`, and `sub` claims in that order. |
### Response Size Guard
@@ -539,13 +541,13 @@ MCP_RESPONSE_SIZE_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `True` | Enable response size checking |
| `token_limit` | `25000` | Maximum estimated token count per response |
| `warn_threshold_pct` | `80` | Warn when response exceeds this percentage of the limit |
| `max_list_items` | `100` | Cap on list-field length (e.g. `charts`, `native_filters`) applied to the `get_*_info` tools before falling back to more aggressive truncation. Raised from a hardcoded 30 in earlier versions; the higher default only keeps more data before the same token-budget fallback kicks in, so it's not a breaking change, but tenants that tuned workflows around the old 30-item cap should lower this value explicitly. |
| `excluded_tools` | See above | Tools exempt from size checking (e.g., tools that return URLs, not data) |
| Key | Default | Description |
| -------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled` | `True` | Enable response size checking |
| `token_limit` | `25000` | Maximum estimated token count per response |
| `warn_threshold_pct` | `80` | Warn when response exceeds this percentage of the limit |
| `max_list_items` | `100` | Cap on list-field length (e.g. `charts`, `native_filters`) applied to the `get_*_info` tools before falling back to more aggressive truncation. Raised from a hardcoded 30 in earlier versions; the higher default only keeps more data before the same token-budget fallback kicks in, so it's not a breaking change, but tenants that tuned workflows around the old 30-item cap should lower this value explicitly. |
| `excluded_tools` | See above | Tools exempt from size checking (e.g., tools that return URLs, not data) |
### Caching
@@ -571,18 +573,18 @@ MCP_CACHE_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `False` | Enable response caching |
| `CACHE_KEY_PREFIX` | `None` | Optional prefix for cache keys (useful for shared Redis) |
| `list_tools_ttl` | `300` | Cache TTL in seconds for `tools/list` |
| `list_resources_ttl` | `300` | Cache TTL for `resources/list` |
| `list_prompts_ttl` | `300` | Cache TTL for `prompts/list` |
| `read_resource_ttl` | `3600` | Cache TTL for `resources/read` |
| `get_prompt_ttl` | `3600` | Cache TTL for `prompts/get` |
| `call_tool_ttl` | `3600` | Cache TTL for `tools/call` |
| `max_item_size` | `1048576` | Maximum cached item size in bytes (1 MB) |
| `excluded_tools` | See above | Tools that are never cached (mutating or non-deterministic) |
| Key | Default | Description |
| -------------------- | --------- | ----------------------------------------------------------- |
| `enabled` | `False` | Enable response caching |
| `CACHE_KEY_PREFIX` | `None` | Optional prefix for cache keys (useful for shared Redis) |
| `list_tools_ttl` | `300` | Cache TTL in seconds for `tools/list` |
| `list_resources_ttl` | `300` | Cache TTL for `resources/list` |
| `list_prompts_ttl` | `300` | Cache TTL for `prompts/list` |
| `read_resource_ttl` | `3600` | Cache TTL for `resources/read` |
| `get_prompt_ttl` | `3600` | Cache TTL for `prompts/get` |
| `call_tool_ttl` | `3600` | Cache TTL for `tools/call` |
| `max_item_size` | `1048576` | Maximum cached item size in bytes (1 MB) |
| `excluded_tools` | See above | Tools that are never cached (mutating or non-deterministic) |
### Redis Store (Multi-Pod)
@@ -597,12 +599,12 @@ MCP_STORE_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `False` | Enable Redis-backed store |
| `CACHE_REDIS_URL` | `None` | Redis connection URL (e.g., `redis://redis-host:6379/0`) |
| `event_store_max_events` | `100` | Maximum events retained per session |
| `event_store_ttl` | `3600` | Event TTL in seconds |
| Key | Default | Description |
| ------------------------ | ------- | -------------------------------------------------------- |
| `enabled` | `False` | Enable Redis-backed store |
| `CACHE_REDIS_URL` | `None` | Redis connection URL (e.g., `redis://redis-host:6379/0`) |
| `event_store_max_events` | `100` | Maximum events retained per session |
| `event_store_ttl` | `3600` | Event TTL in seconds |
### Tool Search
@@ -625,15 +627,15 @@ MCP_TOOL_SEARCH_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `True` | Enable tool search. When `False`, all tools are listed upfront |
| `strategy` | `"bm25"` | Search ranking algorithm. `"bm25"` supports natural language; `"regex"` supports pattern matching |
| `max_results` | `5` | Maximum tools returned per search query |
| `always_visible` | See above | Tools that always appear in `list_tools`, regardless of search |
| `include_schemas` | `False` | When `False` (default, "summary mode"), search results omit `inputSchema` entirely and include a lightweight `parameters_hint` listing top-level parameter names. Set to `True` to include the full `inputSchema` in search results. Full schemas are always used when a tool is actually invoked via `call_tool`. |
| `compact_schemas` | `True` | Strip `$defs` / `$ref` and replace with `{"type": "object"}` in search results to reduce token cost. Only takes effect when `include_schemas=True` — ignored in summary mode. |
| `max_description_length` | `300` | Truncate tool descriptions in search results (0 = no truncation). Applies in both summary and full-schema modes. |
| Key | Default | Description |
| ------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `enabled` | `True` | Enable tool search. When `False`, all tools are listed upfront |
| `strategy` | `"bm25"` | Search ranking algorithm. `"bm25"` supports natural language; `"regex"` supports pattern matching |
| `max_results` | `5` | Maximum tools returned per search query |
| `always_visible` | See above | Tools that always appear in `list_tools`, regardless of search |
| `include_schemas` | `False` | When `False` (default, "summary mode"), search results omit `inputSchema` entirely and include a lightweight `parameters_hint` listing top-level parameter names. Set to `True` to include the full `inputSchema` in search results. Full schemas are always used when a tool is actually invoked via `call_tool`. |
| `compact_schemas` | `True` | Strip `$defs` / `$ref` and replace with `{"type": "object"}` in search results to reduce token cost. Only takes effect when `include_schemas=True` — ignored in summary mode. |
| `max_description_length` | `300` | Truncate tool descriptions in search results (0 = no truncation). Applies in both summary and full-schema modes. |
:::tip
Set `enabled: False` to revert to the traditional "show all tools at once" behavior, which some clients or workflows may prefer.
@@ -670,16 +672,16 @@ The MCP server respects Superset's full role-based access control (RBAC). Every
Each tool declares one or more required FAB permissions. The table below maps tool groups to their permission requirements:
| Tool group | Required FAB permission |
|------------|------------------------|
| `list_charts`, `get_chart_info`, `get_chart_data`, `get_chart_preview`, `generate_chart`, `update_chart` | `can_read` on `Chart` (read), `can_write` on `Chart` (mutate) |
| `list_dashboards`, `get_dashboard_info`, `generate_dashboard`, `add_chart_to_existing_dashboard` | `can_read` on `Dashboard` (read), `can_write` on `Dashboard` (mutate) |
| `list_datasets`, `get_dataset_info`, `create_virtual_dataset` | `can_read` on `Dataset` (read), `can_write` on `Dataset` (mutate) |
| `list_databases`, `get_database_info` | `can_read` on `Database` |
| `execute_sql` | `can_execute_sql_query` on `SQLLab` |
| `open_sql_lab_with_context` | `can_read` on `SQLLab` |
| `save_sql_query` | `can_write` on `SavedQuery` |
| `health_check` | None (public) |
| Tool group | Required FAB permission |
| -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `list_charts`, `get_chart_info`, `get_chart_data`, `get_chart_preview`, `generate_chart`, `update_chart` | `can_read` on `Chart` (read), `can_write` on `Chart` (mutate) |
| `list_dashboards`, `get_dashboard_info`, `generate_dashboard`, `add_chart_to_existing_dashboard` | `can_read` on `Dashboard` (read), `can_write` on `Dashboard` (mutate) |
| `list_datasets`, `get_dataset_info`, `create_virtual_dataset` | `can_read` on `Dataset` (read), `can_write` on `Dataset` (mutate) |
| `list_databases`, `get_database_info` | `can_read` on `Database` |
| `execute_sql` | `can_execute_sql_query` on `SQLLab` |
| `open_sql_lab_with_context` | `can_read` on `SQLLab` |
| `save_sql_query` | `can_write` on `SavedQuery` |
| `health_check` | None (public) |
To disable RBAC checking globally (for trusted-network deployments or testing), set:
@@ -706,13 +708,13 @@ This makes MCP activity fully auditable alongside regular Superset activity. The
Every MCP request passes through a middleware stack before reaching the tool function. The default stack (assembled in `build_middleware_list()` in `server.py`) is:
| Middleware | Purpose | Default |
|------------|---------|---------|
| `StructuredContentStripperMiddleware` | Strips `structuredContent` from responses for Claude.ai bridge compatibility | Enabled |
| `LoggingMiddleware` | Logs each tool call with user, parameters, and duration | Enabled |
| `GlobalErrorHandlerMiddleware` | Catches unhandled exceptions and sanitizes sensitive data before it reaches the client | Enabled |
| `ResponseSizeGuardMiddleware` | Estimates token count, warns at 80% of limit, blocks at limit | Enabled (configurable via `MCP_RESPONSE_SIZE_CONFIG`) |
| `ResponseCachingMiddleware` | Caches read-heavy tool responses (in-memory or Redis) | Disabled (enable via `MCP_CACHE_CONFIG`) |
| Middleware | Purpose | Default |
| ------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| `StructuredContentStripperMiddleware` | Strips `structuredContent` from responses for Claude.ai bridge compatibility | Enabled |
| `LoggingMiddleware` | Logs each tool call with user, parameters, and duration | Enabled |
| `GlobalErrorHandlerMiddleware` | Catches unhandled exceptions and sanitizes sensitive data before it reaches the client | Enabled |
| `ResponseSizeGuardMiddleware` | Estimates token count, warns at 80% of limit, blocks at limit | Enabled (configurable via `MCP_RESPONSE_SIZE_CONFIG`) |
| `ResponseCachingMiddleware` | Caches read-heavy tool responses (in-memory or Redis) | Disabled (enable via `MCP_CACHE_CONFIG`) |
Additional middleware classes (`RateLimitMiddleware`, `FieldPermissionsMiddleware`, `PrivateToolMiddleware`) are implemented in `superset/mcp_service/middleware.py` but are not added to the default pipeline. They are available for operators who want to layer them in via a custom startup path.
@@ -8,12 +8,10 @@ version: 1
## CORS
:::note
In Superset versions prior to `5.x` you have to install to install `flask-cors` with `pip install flask-cors` to enable CORS support.
:::
The following keys in `superset_config.py` can be specified to configure CORS:
- `ENABLE_CORS`: Must be set to `True` in order to enable CORS
@@ -54,11 +52,13 @@ Restart Superset for this configuration change to take effect.
There are two approaches to making dashboards publicly accessible:
**Option 1: Dataset-based access (simpler)**
1. Set `PUBLIC_ROLE_LIKE = "Public"` in `superset_config.py`
2. Grant the Public role access to the relevant datasets (Menu → Security → List Roles → Public)
3. All published dashboards using those datasets become visible to anonymous users
**Option 2: Dashboard-level access (selective control)**
1. Set `PUBLIC_ROLE_LIKE = "Public"` in `superset_config.py`
2. Add the `'ENABLE_VIEWERS': True` [Feature Flag](/admin-docs/configuration/feature-flags)
3. Edit each dashboard's properties and add the "Public" role subject as a viewer
@@ -75,7 +75,7 @@ Now anybody can directly access the dashboard's URL. You can embed it in an ifra
width="600"
height="400"
seamless
frameBorder="0"
frameborder="0"
scrolling="no"
src="https://superset.my-domain.com/superset/dashboard/10/?standalone=1&height=400"
>
@@ -123,17 +123,17 @@ running a custom auth postback endpoint), you can add the endpoints to `WTF_CSRF
## SSH Tunneling
1. Turn on feature flag
- Change [`SSH_TUNNELING`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L489) to `True`
- If you want to add more security when establishing the tunnel we allow users to overwrite the `SSHTunnelManager` class [here](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L507)
- You can also set the [`SSH_TUNNEL_LOCAL_BIND_ADDRESS`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L508) this the host address where the tunnel will be accessible on your VPC
- Change [`SSH_TUNNELING`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L489) to `True`
- If you want to add more security when establishing the tunnel we allow users to overwrite the `SSHTunnelManager` class [here](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L507)
- You can also set the [`SSH_TUNNEL_LOCAL_BIND_ADDRESS`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L508) this the host address where the tunnel will be accessible on your VPC
2. Create database w/ ssh tunnel enabled
- With the feature flag enabled you should now see ssh tunnel toggle.
- Click the toggle to enable SSH tunneling and add your credentials accordingly.
- Superset allows for two different types of authentication (Basic + Private Key). These credentials should come from your service provider.
- With the feature flag enabled you should now see ssh tunnel toggle.
- Click the toggle to enable SSH tunneling and add your credentials accordingly.
- Superset allows for two different types of authentication (Basic + Private Key). These credentials should come from your service provider.
3. Verify data is flowing
- Once SSH tunneling has been enabled, go to SQL Lab and write a query to verify data is properly flowing.
- Once SSH tunneling has been enabled, go to SQL Lab and write a query to verify data is properly flowing.
## Domain Sharding
@@ -90,7 +90,7 @@ In the UI you can assign a set of parameters as JSON
The parameters become available in your SQL (example: `SELECT * FROM {{ my_table }}` ) by using Jinja templating syntax.
SQL Lab template parameters are stored with the dataset as `TEMPLATE PARAMETERS`.
There is a special ``_filters`` parameter which can be used to test filters used in the jinja template.
There is a special `_filters` parameter which can be used to test filters used in the jinja template.
```json
{
@@ -111,7 +111,7 @@ WHERE action in {{ filter_values('action_type')|where_in }}
GROUP BY action
```
Note ``_filters`` is not stored with the dataset. It's only used within the SQL Lab UI.
Note `_filters` is not stored with the dataset. It's only used within the SQL Lab UI.
Besides default Jinja templating, SQL lab also supports self-defined template processor by setting
the `CUSTOM_TEMPLATE_PROCESSORS` in your superset configuration. The values in this dictionary
@@ -245,16 +245,19 @@ cache key by adding the following parameter to your Jinja code:
```
You can json-stringify the array by adding `|tojson` to your Jinja code:
```python
{{ current_user_roles()|tojson }}
```
You can use the `|where_in` filter to use your roles in a SQL statement. For example, if `current_user_roles()` returns `['admin', 'viewer']`, the following template:
```python
SELECT * FROM users WHERE role IN {{ current_user_roles()|where_in }}
```
Will be rendered as:
```sql
SELECT * FROM users WHERE role IN ('admin', 'viewer')
```
@@ -280,6 +283,7 @@ Always treat `url_param()` values as untrusted input. Escaping behaviour varies
{% if cc not in ('US', 'ES', 'FR') %}{% set cc = 'US' %}{% endif %}
WHERE country_code = '{{ cc }}'
```
:::
Here's a concrete example:
@@ -311,6 +315,76 @@ Here's a concrete example:
WHERE country_code = 'US'
```
**Guest User Attributes**
The `{{ get_guest_user_attribute('attribute_name') }}` macro returns a specific attribute value from the guest user context.
This is useful when working with embedded Superset where guest tokens can contain custom attributes that need to be
accessed in SQL queries.
This macro only works when the current user is a guest user (authenticated via guest token). If the current user is
not a guest user, or if the specified attribute doesn't exist, the macro will return `None` or the provided default value.
If you have caching enabled in your Superset configuration, then by default the resolved value (whether it
came from the guest token, a null attribute, or the provided default) will be used by Superset when
calculating the cache key. A cache key is a unique identifier that determines if there's a cache hit in the
future and Superset can retrieve cached data. Including the resolved value on every branch ensures two guests
whose tokens render different SQL never share a cache entry.
You can disable the inclusion of the attribute value in the calculation of the
cache key by adding the following parameter to your Jinja code, but only do so
when the value cannot affect the query results:
```
{{ get_guest_user_attribute('department', add_to_cache_keys=False) }}
```
You can also provide a default value if the attribute is not found:
```
{{ get_guest_user_attribute('region', default='US') }}
```
Here's a concrete example of using guest user attributes in a query:
```sql
SELECT *
FROM sales_data
WHERE region = '{{ get_guest_user_attribute("user_region", default="global") }}'
AND department = '{{ get_guest_user_attribute("department") }}'
```
:::warning[Security Warning]
Guest token attributes come from the embedding application. By default,
`get_guest_user_attribute()` escapes string values — including strings nested inside
arrays and object values, and caller-supplied defaults — through the database dialect's
literal rendering (the same mechanism as `url_param()`). This covers dialect-specific
escape characters such as the backslash on MySQL/MariaDB, so the example above is safe
to interpolate directly. If you pass `escape_result=False`, or interpolate non-string
values (numbers, booleans), you are responsible for validating or allowlisting the
values, since they originate outside Superset.
If a guest attribute is an array and you plan to pipe it through the `|where_in` filter
(for example `full_name IN {{ get_guest_user_attribute('names')|where_in }}`), call
`get_guest_user_attribute('names', escape_result=False)`. `where_in` already applies its
own dialect-safe quoting, so escaping the values twice can corrupt them (a value such as
`O'Brien` would come back doubly escaped and match nothing).
Only individual string values are escaped as SQL literals. Interpolating an entire array
or object directly (rather than through `|where_in`, or by accessing a specific element)
renders Python's string form of that structure, which is not valid SQL, and object keys
are not escaped at all. Use `|where_in` for arrays, `|tojson` where you need a
JSON-stringified value, or read individual keys/elements out of the structure yourself.
The same double-escaping problem described above for `|where_in` applies to `|tojson`:
pass `escape_result=False` before piping to `|tojson` (for example
`{{ get_guest_user_attribute('profile', escape_result=False)|tojson }}`), since JSON
already handles its own quoting and re-escaping a value first would corrupt it (a nested
string such as `O'Brien` would come back as the altered `O''Brien` in the serialized
JSON).
:::
### Explicitly Including Values in Cache Key
The `{{ cache_key_wrapper() }}` function explicitly instructs Superset to add a value to the
@@ -364,6 +438,7 @@ This is useful if:
AND full_name LIKE '{{ filter.get('val') | replace("'", "''") }}'
{%- endif -%}
```
:::
Here's a concrete example:
@@ -431,7 +506,7 @@ The macro takes the following parameters:
- `column`: Name of the temporal column. Leave undefined to reference the time range from a Dashboard Native Time Range
filter (when present).
- `default`: The default value to fall back to if the time filter is not present, or has the value `No filter`
- `target_type`: The target temporal type as recognized by the target database (e.g. `TIMESTAMP`, `DATE` or
- `target_type`: The target temporal type as recognized by the target database (e.g. `TIMESTAMP`, `DATE` or
`DATETIME`). If `column` is defined, the format will default to the type of the column. This is used to produce
the format of the `from_expr` and `to_expr` properties of the returned `TimeFilter` object.
- `strftime`: format using the `strftime` method of `datetime` for custom time formatting.
@@ -537,6 +612,7 @@ The parameter can be used in SQL Lab, or when fetching a metric from another dat
Superset supports [builtin filters from the Jinja2 templating package](https://jinja.palletsprojects.com/en/stable/templates/#builtin-filters). Custom filters have also been implemented:
### Where In
Parses a list into a SQL-compatible statement. This is useful with macros that return an array (for example the `filter_values` macro):
```
@@ -556,6 +632,7 @@ Dashboard filter without any value applied
### To Datetime
Loads a string as a `datetime` object. This is useful when performing date operations. For example:
```
{% set from_expr = get_time_filter("dttm", strftime="%Y-%m-%d").from_expr %}
{% set to_expr = get_time_filter("dttm", strftime="%Y-%m-%d").to_expr %}
@@ -567,5 +644,6 @@ Loads a string as a `datetime` object. This is useful when performing date opera
```
:::resources
- [Blog: Intro to Jinja Templating in Apache Superset](https://preset.io/blog/intro-jinja-templating-apache-superset/)
:::
:::
+7 -1
View File
@@ -4,6 +4,7 @@ hide_title: true
sidebar_position: 12
version: 1
---
# Theming Superset
:::note
@@ -34,11 +35,13 @@ You can also extend with Superset-specific tokens (documented in the default the
When `ENABLE_UI_THEME_ADMINISTRATION = True` is configured, administrators can manage system-wide themes directly from the UI:
#### Setting System Themes
- **System Default Theme**: Click the sun icon on any theme to set it as the system-wide default
- **System Dark Theme**: Click the moon icon on any theme to set it as the system dark mode theme
- **Automatic OS Detection**: When both default and dark themes are set, Superset automatically detects and applies the appropriate theme based on OS preferences
#### Managing System Themes
- System themes are indicated with special badges in the theme list
- Only administrators with write permissions can modify system theme settings
- Removing a system theme designation reverts to configuration file defaults
@@ -46,6 +49,7 @@ When `ENABLE_UI_THEME_ADMINISTRATION = True` is configured, administrators can m
### Applying Themes to Dashboards
Once created, themes can be applied to individual dashboards:
- Edit any dashboard and select your custom theme from the theme dropdown
- Each dashboard can have its own theme, allowing for branded or context-specific styling
@@ -127,6 +131,7 @@ When `ENABLE_UI_THEME_ADMINISTRATION = True`:
Superset validates theme JSON when it is saved, either through the UI or via configuration. If a theme contains invalid tokens or an unrecognized structure, Superset logs a warning and falls back to the built-in default theme rather than applying a broken configuration. This prevents a bad theme from rendering the application unusable.
The fallback order is:
1. **UI-configured system theme** (highest priority, if `ENABLE_UI_THEME_ADMINISTRATION = True`)
2. **`THEME_DEFAULT` / `THEME_DARK`** from `superset_config.py`
3. **Built-in Superset default theme** (always present as a safety net)
@@ -455,9 +460,10 @@ For programmatic theme management, Superset provides REST endpoints:
These endpoints require appropriate permissions and are subject to RBAC controls.
:::resources
- [Video: Live Demo — Theming Apache Superset](https://www.youtube.com/watch?v=XsZAsO9tC3o)
- [CSS and Theming](https://docs.preset.io/docs/css-and-theming) - Additional theming techniques and CSS customization
- [Blog: Customizing Apache Superset Dashboards with CSS](https://preset.io/blog/customizing-superset-dashboards-with-css/)
- [Blog: Customizing Dashboards with CSS — Tips and Tricks](https://preset.io/blog/customizing-apache-superset-dashboards-with-css-additional-tips-and-tricks/)
- [Blog: Customizing Chart Colors](https://preset.io/blog/customizing-chart-colors-with-superset-and-preset/)
:::
:::
@@ -5,7 +5,7 @@ sidebar_position: 1
version: 1
---
import useBaseUrl from "@docusaurus/useBaseUrl";
import useBaseUrl from '@docusaurus/useBaseUrl';
# Architecture
+54 -6
View File
@@ -11,8 +11,7 @@ The Apache Superset community extensively uses Docker for development, release,
and productionizing Superset. This page details our Docker builds and tag naming
schemes to help users navigate our offerings.
Images are built and pushed to the [Superset Docker Hub repository](
https://hub.docker.com/r/apache/superset) using GitHub Actions.
Images are built and pushed to the [Superset Docker Hub repository](https://hub.docker.com/r/apache/superset) using GitHub Actions.
Different sets of images are built and/or published at different times:
- **Published releases** (`release`): published using
@@ -112,12 +111,61 @@ USER superset
CMD ["/app/docker/entrypoints/run-server.sh"]
```
### Adding translations to a custom image
The pattern above, a small Dockerfile that just extends `FROM apache/superset:...`, can't add
translations after the fact. By the time an official tag is published, its frontend and backend
layers have already had non-English translation files stripped out unless `BUILD_TRANSLATIONS`
was set at build time (see below), and there's no `superset/translations` source tree left in the
final image to compile from.
To get translations into your own image, you need to build from the full Superset source (a
clone or fork of this repo) rather than extend a published tag. The most efficient way to do this
is to append your customizations as one more stage at the end of the repo's own `Dockerfile`, so
Docker can reuse the cached upstream layers and only rebuild what your stage adds:
```Dockerfile
# Append this to the end of the repo's Dockerfile
# Keep this tag in sync with the branch/tag of the repo you cloned, so the
# translation files built from source match the keys the runtime expects:
FROM apache/superset:5.0.0 AS my-custom-image
USER root
# Pull the translation files out of the earlier build stages (frontend
# .json in `superset-node`, backend .mo in `python-translation-compiler`).
# Those stages' own cleanup only matches single-character extensions, so
# the source `.po` files can still be present here; strip them explicitly
# so this stage only keeps the compiled translations.
COPY --from=superset-node /app/superset/translations superset/translations
COPY --from=python-translation-compiler /app/translations_mo superset/translations
RUN find superset/translations -name '*.po' -delete
USER superset
```
Then build with:
```bash
docker build --target=my-custom-image --build-arg=BUILD_TRANSLATIONS=true -t mysuperset:5.0.0 .
```
You can combine this with the database-driver/dependency pattern above by adding your own
`RUN uv pip install ...` step before switching back to `USER superset`. See
[issue #35959](https://github.com/apache/superset/issues/35959) for the discussion this pattern
came out of, credit to the community for working it out.
## Key ARGs in Dockerfile
- `BUILD_TRANSLATIONS`: whether to build the translations into the image. For the
frontend build this tells webpack to strip out all locales other than `en` from
the `moment-timezone` library. For the backendthis skips compiling the
`*.po` translation files
- `BUILD_TRANSLATIONS`: whether to compile non-English translations into the image.
When `true`, the frontend build converts the `*.po` files to locale JSON and the
backend runs `pybabel compile` to produce `*.mo` files; both source `*.po` files
are stripped afterward either way. When `false` (the default), those compile
steps are skipped and only `en` ships. This only takes effect when building the image from source
(`docker build` against this repo's own `Dockerfile`); it has no effect on a downstream
Dockerfile that just extends an already-published tag, see
"Adding translations to a custom image" above. Note that the backend `pybabel compile`
step ignores its exit code, so a `.po` file with a compile error won't fail the build;
check the build logs for `pybabel` warnings if a locale's backend strings aren't showing up.
- `DEV_MODE`: whether to skip the frontend build, this is used by our `docker-compose` dev setup
where we mount the local volume and build using `webpack` in `--watch` mode, meaning as you
alter the code in the local file system, webpack, from within a docker image used for this
+39 -37
View File
@@ -5,12 +5,13 @@ sidebar_position: 5
version: 1
---
import useBaseUrl from "@docusaurus/useBaseUrl";
import useBaseUrl from '@docusaurus/useBaseUrl';
# Using Docker Compose
<img src={useBaseUrl("/img/docker-compose.webp" )} width="150" />
<br /><br />
<img src={useBaseUrl('/img/docker-compose.webp')} width="150" />
<br />
<br />
:::caution
Since `docker compose` is primarily designed to run a set of containers on **a single host**
@@ -29,23 +30,23 @@ way to launch a fully functioning **development environment** quickly.
Note that there are 4 major ways we support to run `docker compose`:
1. **docker-compose.yml:** for interactive development, where we mount your local folder with the
frontend/backend files that you can edit and experience the changes you
make in the app in real time
frontend/backend files that you can edit and experience the changes you
make in the app in real time
1. **docker-compose-light.yml:** a lightweight configuration with minimal services (database,
Superset app, and frontend dev server) for development. Uses in-memory caching instead of Redis
and is designed for running multiple instances simultaneously
Superset app, and frontend dev server) for development. Uses in-memory caching instead of Redis
and is designed for running multiple instances simultaneously
1. **docker-compose-non-dev.yml** where we just build a more immutable image based on the
local branch and get all the required images running. Changes in the local branch
at the time you fire this up will be reflected, but changes to the code
while `up` won't be reflected in the app
local branch and get all the required images running. Changes in the local branch
at the time you fire this up will be reflected, but changes to the code
while `up` won't be reflected in the app
1. **docker-compose-image-tag.yml** where we fetch an image from docker-hub say for the
`5.0.0` release for instance, and fire it up so you can try it. Here what's in
the local branch has no effects on what's running, we just fetch and run
pre-built images from docker-hub. For `docker compose` to work along with the
Postgres image it boots up, you'll want to point to a `-dev`-suffixed TAG, as in
`export TAG=5.0.0-dev` or `export TAG=4.1.2-dev`, with `latest-dev` being the default.
The `dev` builds include the `psycopg2-binary` required to connect
to the Postgres database launched as part of the `docker compose` builds.
`5.0.0` release for instance, and fire it up so you can try it. Here what's in
the local branch has no effects on what's running, we just fetch and run
pre-built images from docker-hub. For `docker compose` to work along with the
Postgres image it boots up, you'll want to point to a `-dev`-suffixed TAG, as in
`export TAG=5.0.0-dev` or `export TAG=4.1.2-dev`, with `latest-dev` being the default.
The `dev` builds include the `psycopg2-binary` required to connect
to the Postgres database launched as part of the `docker compose` builds.
More on these approaches after setting up the requirements for either.
@@ -92,7 +93,7 @@ like to try out Superset without making any code changes follow the steps docume
:::tip
By default, we mount the local superset-frontend folder here and run `npm install` as well
as `npm run dev` which triggers webpack to compile/bundle the frontend code. Depending
on your local setup, especially if you have less than 16GB of memory, it may be very slow to
on your local setup, especially if you have less than 16GB of memory, it may be very slow to
perform those operations. In this case, we recommend you set the env var
`BUILD_SUPERSET_FRONTEND_IN_DOCKER` to `false`, and to run this locally instead in a terminal.
Simply trigger `npm i && npm run dev`, this should be MUCH faster.
@@ -121,6 +122,7 @@ NODE_PORT=9003 docker compose -p superset-3 -f docker-compose-light.yml up
```
This configuration includes:
- PostgreSQL database (internal network only)
- Superset application server
- Frontend development server with webpack hot reloading
@@ -165,7 +167,7 @@ looking to fire up.
:::caution
All of the content belonging to a Superset instance - charts, dashboards, users, etc. - is stored in
its metadata database. In production, this database should be backed up. The default installation
its metadata database. In production, this database should be backed up. The default installation
with docker compose will store that data in a PostgreSQL database contained in a Docker
[volume](https://docs.docker.com/storage/volumes/), which is not backed up.
@@ -174,7 +176,7 @@ Again, **THE DOCKER-COMPOSE INSTALLATION IS NOT PRODUCTION-READY OUT OF THE BOX.
:::
You should see a stream of logging output from the containers being launched on your machine. Once
this output slows, you should have a running instance of Superset on your local machine! To avoid
this output slows, you should have a running instance of Superset on your local machine! To avoid
the wall of text on future runs, add the `-d` option to the end of the `docker compose up` command.
### Configuring Further
@@ -259,24 +261,24 @@ Superset (which is running in its docker container). Other databases may have sl
configurations but gist would be same and boils down to 2 steps -
1. **(Mac users may skip this step)** Configuring the local postgresql/database instance to accept
public incoming connections. By default, postgresql only allows incoming connections from
`localhost` and under Docker, unless you use `--network=host`, `localhost` will refer to different
endpoints on the host machine and in a docker container respectively. Allowing postgresql to accept
connections from the Docker involves making one-line changes to the files `postgresql.conf` and
`pg_hba.conf`; you can find helpful links tailored to your OS / PG version on the web easily for
this task. For Docker it suffices to only whitelist IPs `172.0.0.0/8` instead of `*`, but in any
case you are _warned_ that doing this in a production database _may_ have disastrous consequences as
you are opening your database to the public internet.
public incoming connections. By default, postgresql only allows incoming connections from
`localhost` and under Docker, unless you use `--network=host`, `localhost` will refer to different
endpoints on the host machine and in a docker container respectively. Allowing postgresql to accept
connections from the Docker involves making one-line changes to the files `postgresql.conf` and
`pg_hba.conf`; you can find helpful links tailored to your OS / PG version on the web easily for
this task. For Docker it suffices to only whitelist IPs `172.0.0.0/8` instead of `*`, but in any
case you are _warned_ that doing this in a production database _may_ have disastrous consequences as
you are opening your database to the public internet.
1. Instead of `localhost`, try using `host.docker.internal` (Mac users, Ubuntu) or `172.18.0.1`
(Linux users) as the hostname when attempting to connect to the database. This is a Docker internal
detail -- what is happening is that, in Mac systems, Docker Desktop creates a dns entry for the
hostname `host.docker.internal` which resolves to the correct address for the host machine, whereas
in Linux this is not the case (at least by default). If neither of these 2 hostnames work then you
may want to find the exact hostname you want to use, for that you can do `ifconfig` or
`ip addr show` and look at the IP address of `docker0` interface that must have been created by
Docker for you. Alternately if you don't even see the `docker0` interface try (if needed with sudo)
`docker network inspect bridge` and see if there is an entry for `"Gateway"` and note the IP
address.
(Linux users) as the hostname when attempting to connect to the database. This is a Docker internal
detail -- what is happening is that, in Mac systems, Docker Desktop creates a dns entry for the
hostname `host.docker.internal` which resolves to the correct address for the host machine, whereas
in Linux this is not the case (at least by default). If neither of these 2 hostnames work then you
may want to find the exact hostname you want to use, for that you can do `ifconfig` or
`ip addr show` and look at the IP address of `docker0` interface that must have been created by
Docker for you. Alternately if you don't even see the `docker0` interface try (if needed with sudo)
`docker network inspect bridge` and see if there is an entry for `"Gateway"` and note the IP
address.
## 4. To build or not to build
@@ -5,7 +5,7 @@ sidebar_position: 2
version: 1
---
import useBaseUrl from "@docusaurus/useBaseUrl";
import useBaseUrl from '@docusaurus/useBaseUrl';
# Installation Methods
+12 -10
View File
@@ -1,16 +1,17 @@
---
title: Kubernetes
title: Kubernetes
hide_title: true
sidebar_position: 3
version: 1
---
import useBaseUrl from "@docusaurus/useBaseUrl";
import useBaseUrl from '@docusaurus/useBaseUrl';
# Installing on Kubernetes
<img src={useBaseUrl("/img/k8s.png" )} width="150" />
<br /><br />
<img src={useBaseUrl('/img/k8s.png')} width="150" />
<br />
<br />
Running Superset on Kubernetes is supported with the provided [Helm](https://helm.sh/) chart
found in the official [Superset helm repository](https://apache.github.io/superset/index.yaml).
@@ -134,7 +135,7 @@ init:
```
:::note
Superset uses [Scarf Gateway](https://about.scarf.sh/scarf-gateway) to collect telemetry data. Knowing the installation counts for different Superset versions informs the project's decisions about patching and long-term support. Scarf purges personally identifiable information (PII) and provides only aggregated statistics.
Superset uses [Scarf Gateway](https://about.scarf.sh/scarf-gateway) to collect telemetry data. Knowing the installation counts for different Superset versions informs the project's decisions about patching and long-term support. Scarf purges personally identifiable information (PII) and provides only aggregated statistics.
There are two independent telemetry channels:
@@ -143,11 +144,11 @@ There are two independent telemetry channels:
```yaml
extraEnv:
SCARF_ANALYTICS: "false"
SCARF_ANALYTICS: 'false'
```
This is read at runtime, so it takes effect on the pre-built images without rebuilding the frontend.
:::
:::
### Dependencies
@@ -205,7 +206,7 @@ Those can be passed as key/values either with `extraEnv` or `extraSecretEnv` if
extraEnv:
SMTP_HOST: smtp.gmail.com
SMTP_USER: user@gmail.com
SMTP_PORT: "587"
SMTP_PORT: '587'
SMTP_MAIL_FROM: user@gmail.com
extraSecretEnv:
@@ -366,7 +367,7 @@ supersetCeleryBeat:
extraEnv:
SMTP_HOST: smtp.gmail.com
SMTP_USER: user@gmail.com
SMTP_PORT: "587"
SMTP_PORT: '587'
SMTP_MAIL_FROM: user@gmail.com
extraSecretEnv:
@@ -456,6 +457,7 @@ init:
```
:::resources
- [Tutorial: Mastering Data Visualization — Installing Superset on Kubernetes with Helm Chart](https://mahira-technology.medium.com/mastering-data-visualization-installing-superset-on-kubernetes-cluster-using-helm-chart-e4ec99199e1e)
- [Tutorial: Installing Apache Superset in Kubernetes](https://aws.plainenglish.io/installing-apache-superset-in-kubernetes-1aec192ac495)
:::
:::
+5 -3
View File
@@ -5,12 +5,13 @@ sidebar_position: 4
version: 1
---
import useBaseUrl from "@docusaurus/useBaseUrl";
import useBaseUrl from '@docusaurus/useBaseUrl';
# Installing Superset from PyPI
<img src={useBaseUrl("/img/pypi.png" )} width="150" />
<br /><br />
<img src={useBaseUrl('/img/pypi.png')} width="150" />
<br />
<br />
This page describes how to install Superset using the `apache_superset` package [published on PyPI](https://pypi.org/project/apache_superset/).
@@ -126,6 +127,7 @@ pip install apache_superset
```
Then, define mandatory configurations, SECRET_KEY and FLASK_APP:
```bash
export SUPERSET_SECRET_KEY=YOUR-SECRET-KEY # For production use, make sure this is a strong key, for example generated using `openssl rand -base64 42`. See https://superset.apache.org/admin-docs/configuration/configuring-superset#specifying-a-secret_key
export FLASK_APP=superset
@@ -55,6 +55,7 @@ For a detailed list of breaking changes and migration notes for each version, se
This file documents backwards-incompatible changes and provides guidance for migrating between
major versions, including:
- Configuration changes
- API changes
- Database migrations
+64 -63
View File
@@ -2,41 +2,42 @@
title: CVEs fixed by release
sidebar_position: 2
---
#### Version 6.0.0
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------------|---------:|
| CVE-2026-23980 | Improper Neutralization of Special Elements used in a SQL Command | < 6.0.0 |
| CVE-2026-23982 | Improper Authorization in Dataset Creation Allows Access Control Bypass | < 6.0.0 |
| CVE-2026-23983 | Information Disclosure of sensitive user info via Tags | < 6.0.0 |
| CVE-2026-23984 | SQLLab Read-Only Bypass on PostgreSQL (DML execution) | < 6.0.0 |
| CVE | Title | Affected |
| :------------- | :---------------------------------------------------------------------- | -------: |
| CVE-2026-23980 | Improper Neutralization of Special Elements used in a SQL Command | < 6.0.0 |
| CVE-2026-23982 | Improper Authorization in Dataset Creation Allows Access Control Bypass | < 6.0.0 |
| CVE-2026-23983 | Information Disclosure of sensitive user info via Tags | < 6.0.0 |
| CVE-2026-23984 | SQLLab Read-Only Bypass on PostgreSQL (DML execution) | < 6.0.0 |
#### Version 5.0.0
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------------|---------:|
| CVE-2025-55673 | Exposure of Sensitive Information to an Unauthorized Actor | < 5.0.0 |
| CVE-2025-55674 | Improper Neutralization of Special Elements used in an SQL Command | < 5.0.0 |
| CVE-2025-55675 | Improper Access Control leading to Information Disclosure | < 5.0.0 |
| CVE | Title | Affected |
| :------------- | :----------------------------------------------------------------- | -------: |
| CVE-2025-55673 | Exposure of Sensitive Information to an Unauthorized Actor | < 5.0.0 |
| CVE-2025-55674 | Improper Neutralization of Special Elements used in an SQL Command | < 5.0.0 |
| CVE-2025-55675 | Improper Access Control leading to Information Disclosure | < 5.0.0 |
#### Version 4.1.3
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------------|---------:|
| CVE-2025-55672 | Improper Neutralization of Input During Web Page Generation | < 4.1.3 |
| CVE | Title | Affected |
| :------------- | :---------------------------------------------------------- | -------: |
| CVE-2025-55672 | Improper Neutralization of Input During Web Page Generation | < 4.1.3 |
#### Version 4.1.2
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------------|---------:|
| CVE-2025-27696 | Improper authorization leading to resource ownership takeover | < 4.1.2 |
| CVE-2025-48912 | Improper authorization bypass on row level security via SQL Injection | < 4.1.2 |
| CVE-2026-23969 | Exposure of Sensitive Information via Incomplete ClickHouse Function Filtering | < 4.1.2 |
| CVE | Title | Affected |
| :------------- | :----------------------------------------------------------------------------- | -------: |
| CVE-2025-27696 | Improper authorization leading to resource ownership takeover | < 4.1.2 |
| CVE-2025-48912 | Improper authorization bypass on row level security via SQL Injection | < 4.1.2 |
| CVE-2026-23969 | Exposure of Sensitive Information via Incomplete ClickHouse Function Filtering | < 4.1.2 |
#### Version 4.1.0
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------------|---------:|
| :------------- | :--------------------------------------------------------------------------------- | -------: |
| CVE-2024-53947 | Improper SQL authorisation, parse for specific postgres functions | < 4.1.0 |
| CVE-2024-53948 | Error verbosity exposes metadata in analytics databases | < 4.1.0 |
| CVE-2024-53949 | Lower privilege users are able to create Role when FAB_ADD_SECURITY_API is enabled | < 4.1.0 |
@@ -44,84 +45,84 @@ sidebar_position: 2
#### Version 4.0.2
| CVE | Title | Affected |
|:---------------|:----------------------------|---------:|
| CVE-2024-39887 | Improper SQL authorization | < 4.0.1 |
| CVE | Title | Affected |
| :------------- | :------------------------- | -------: |
| CVE-2024-39887 | Improper SQL authorization | < 4.0.1 |
#### Version 3.1.3, 4.0.1
| CVE | Title | Affected |
|:---------------|:----------------------------|----------------------------:|
| CVE-2024-34693 | Server arbitrary file read | < 3.1.3, >= 4.0.0, < 4.0.1 |
| CVE | Title | Affected |
| :------------- | :------------------------- | -------------------------: |
| CVE-2024-34693 | Server arbitrary file read | < 3.1.3, >= 4.0.0, < 4.0.1 |
#### Version 3.1.2
| CVE | Title | Affected |
|:---------------|:--------------------------------------------------------|---------:|
| CVE-2024-28148 | Incorrect datasource authorization on explore REST API | < 3.1.2 |
| CVE | Title | Affected |
| :------------- | :----------------------------------------------------- | -------: |
| CVE-2024-28148 | Incorrect datasource authorization on explore REST API | < 3.1.2 |
#### Version 3.0.4, 3.1.1
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------|----------------------------:|
| CVE-2024-27315 | Improper error handling on alerts | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-24773 | Improper validation of SQL statements allows for unauthorized access to data | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-24772 | Improper Neutralisation of custom SQL on embedded context | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-24779 | Improper data authorization when creating a new dataset | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-26016 | Improper authorization validation on dashboards and charts import | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE | Title | Affected |
| :------------- | :--------------------------------------------------------------------------- | -------------------------: |
| CVE-2024-27315 | Improper error handling on alerts | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-24773 | Improper validation of SQL statements allows for unauthorized access to data | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-24772 | Improper Neutralisation of custom SQL on embedded context | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-24779 | Improper data authorization when creating a new dataset | < 3.0.4, >= 3.1.0, < 3.1.1 |
| CVE-2024-26016 | Improper authorization validation on dashboards and charts import | < 3.0.4, >= 3.1.0, < 3.1.1 |
#### Version 3.0.3
| CVE | Title | Affected |
|:---------------|:----------------------------------------------|---------:|
| :------------- | :-------------------------------------------- | -------: |
| CVE-2023-49657 | Stored XSS in Dashboard Title and Chart Title | < 3.0.3 |
#### Version 3.0.2, 2.1.3
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------|---------------------------:|
| :------------- | :---------------------------------------------------------- | -------------------------: |
| CVE-2023-46104 | Allows for uncontrolled resource consumption via a ZIP bomb | < 2.1.3, >= 3.0.0, < 3.0.2 |
| CVE-2023-49736 | SQL Injection on where_in JINJA macro | < 2.1.3, >= 3.0.0, < 3.0.2 |
| CVE-2023-49734 | Privilege Escalation Vulnerability | < 2.1.3, >= 3.0.0, < 3.0.2 |
#### Version 3.0.0
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------------------|---------:|
| CVE-2023-42502 | Open Redirect Vulnerability | < 3.0.0 |
| CVE-2023-42505 | Sensitive information disclosure on db connection details | < 3.0.0 |
| CVE | Title | Affected |
| :------------- | :-------------------------------------------------------- | -------: |
| CVE-2023-42502 | Open Redirect Vulnerability | < 3.0.0 |
| CVE-2023-42505 | Sensitive information disclosure on db connection details | < 3.0.0 |
#### Version 2.1.3
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------------------|---------:|
| CVE-2023-42504 | Lack of rate limiting allows for possible denial of service | < 2.1.3 |
| CVE | Title | Affected |
| :------------- | :---------------------------------------------------------- | -------: |
| CVE-2023-42504 | Lack of rate limiting allows for possible denial of service | < 2.1.3 |
#### Version 2.1.2
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------------------|---------:|
| CVE-2023-40610 | Privilege escalation with default examples database | < 2.1.2 |
| CVE-2023-42501 | Unnecessary read permissions within the Gamma role | < 2.1.2 |
| CVE-2023-43701 | Stored XSS on API endpoint | < 2.1.2 |
| CVE | Title | Affected |
| :------------- | :-------------------------------------------------- | -------: |
| CVE-2023-40610 | Privilege escalation with default examples database | < 2.1.2 |
| CVE-2023-42501 | Unnecessary read permissions within the Gamma role | < 2.1.2 |
| CVE-2023-43701 | Stored XSS on API endpoint | < 2.1.2 |
#### Version 2.1.1
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------------------|---------:|
| CVE-2023-36387 | Improper API permission for low privilege users | < 2.1.1 |
| CVE-2023-36388 | Improper API permission for low privilege users allows for SSRF | < 2.1.1 |
| CVE-2023-27523 | Improper data permission validation on Jinja templated queries | < 2.1.1 |
| CVE-2023-27526 | Improper Authorization check on import charts | < 2.1.1 |
| CVE-2023-39264 | Stack traces enabled by default | < 2.1.1 |
| CVE-2023-39265 | Possible Unauthorized Registration of SQLite Database Connections | < 2.1.1 |
| CVE-2023-37941 | Metadata db write access can lead to remote code execution | < 2.1.1 |
| CVE-2023-32672 | SQL parser edge case bypasses data access authorization | < 2.1.1 |
| CVE | Title | Affected |
| :------------- | :---------------------------------------------------------------- | -------: |
| CVE-2023-36387 | Improper API permission for low privilege users | < 2.1.1 |
| CVE-2023-36388 | Improper API permission for low privilege users allows for SSRF | < 2.1.1 |
| CVE-2023-27523 | Improper data permission validation on Jinja templated queries | < 2.1.1 |
| CVE-2023-27526 | Improper Authorization check on import charts | < 2.1.1 |
| CVE-2023-39264 | Stack traces enabled by default | < 2.1.1 |
| CVE-2023-39265 | Possible Unauthorized Registration of SQLite Database Connections | < 2.1.1 |
| CVE-2023-37941 | Metadata db write access can lead to remote code execution | < 2.1.1 |
| CVE-2023-32672 | SQL parser edge case bypasses data access authorization | < 2.1.1 |
#### Version 2.1.0
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------------------|---------:|
| :------------- | :---------------------------------------------------------------------- | -------: |
| CVE-2023-25504 | Possible SSRF on import datasets | < 2.1.0 |
| CVE-2023-27524 | Session validation vulnerability when using provided default SECRET_KEY | < 2.1.0 |
| CVE-2023-27525 | Incorrect default permissions for Gamma role | < 2.1.0 |
@@ -129,8 +130,8 @@ sidebar_position: 2
#### Version 2.0.1
| CVE | Title | Affected |
|:---------------|:------------------------------------------------------------|------------------: |
| CVE | Title | Affected |
| :------------- | :---------------------------------------------------------- | -----------------: |
| CVE-2022-41703 | SQL injection vulnerability in adhoc clauses | < 2.0.1 or < 1.5.2 |
| CVE-2022-43717 | Cross-Site Scripting on dashboards | < 2.0.1 or < 1.5.2 |
| CVE-2022-43718 | Cross-Site Scripting vulnerability on upload forms | < 2.0.1 or < 1.5.2 |
+57 -55
View File
@@ -3,7 +3,7 @@ title: Securing Your Superset Installation for Production
sidebar_position: 3
---
> *This guide applies to Apache Superset version 4.0 and later and is an evolving set of best practices that administrators should adapt to their specific deployment architecture.*
> _This guide applies to Apache Superset version 4.0 and later and is an evolving set of best practices that administrators should adapt to their specific deployment architecture._
The default Apache Superset configuration is optimized for ease of use and development, not for security. For any production deployment, it is **critical** that you review and apply the following security configurations to harden your instance, protect user data, and prevent unauthorized access.
@@ -13,25 +13,25 @@ This guide provides a comprehensive checklist of essential security configuratio
Running Superset without HTTPS (TLS) is not secure. Without it, all network traffic—including user credentials, session tokens, and sensitive data—is sent in cleartext and can be easily intercepted.
* **Use a Reverse Proxy:** Your Superset instance should always be deployed behind a reverse proxy (e.g., Nginx, Traefik) or a load balancer (e.g., AWS ALB, Google Cloud Load Balancer) that is configured to handle HTTPS termination.
* **Enforce Modern TLS:** Configure your proxy to enforce TLS 1.2 or higher with strong, industry-standard cipher suites.
* **Implement HSTS:** Use the HTTP Strict Transport Security (HSTS) header to ensure browsers only connect to your Superset instance over HTTPS. This can be configured in your reverse proxy or within Superset's Talisman settings.
- **Use a Reverse Proxy:** Your Superset instance should always be deployed behind a reverse proxy (e.g., Nginx, Traefik) or a load balancer (e.g., AWS ALB, Google Cloud Load Balancer) that is configured to handle HTTPS termination.
- **Enforce Modern TLS:** Configure your proxy to enforce TLS 1.2 or higher with strong, industry-standard cipher suites.
- **Implement HSTS:** Use the HTTP Strict Transport Security (HSTS) header to ensure browsers only connect to your Superset instance over HTTPS. This can be configured in your reverse proxy or within Superset's Talisman settings.
### **`SUPERSET_SECRET_KEY` Management (CRITICAL)**
This is the most critical security setting for your Superset instance. It is used to sign all session cookies and encrypt sensitive information in the metadata database, such as database connection credentials.
* **Generate a Unique, Strong Key:** A unique key must be generated for every Superset instance. Use a cryptographically secure method to create it.
```bash
# Example using openssl to generate a strong key
openssl rand -base64 42
```
* **Store the Key Securely:** The key must be kept confidential. The recommended approach is to store it as an environment variable or in a secrets management system (e.g., AWS Secrets Manager, HashiCorp Vault). **Do not hardcode the key in `superset_config.py` or commit it to version control.**
```python
# In superset_config.py
import os
SECRET_KEY = os.environ.get('SUPERSET_SECRET_KEY')
```
- **Generate a Unique, Strong Key:** A unique key must be generated for every Superset instance. Use a cryptographically secure method to create it.
```bash
# Example using openssl to generate a strong key
openssl rand -base64 42
```
- **Store the Key Securely:** The key must be kept confidential. The recommended approach is to store it as an environment variable or in a secrets management system (e.g., AWS Secrets Manager, HashiCorp Vault). **Do not hardcode the key in `superset_config.py` or commit it to version control.**
```python
# In superset_config.py
import os
SECRET_KEY = os.environ.get('SUPERSET_SECRET_KEY')
```
> #### ⚠️ Warning: Your `SUPERSET_SECRET_KEY` Must Be Unique
>
@@ -75,7 +75,7 @@ SESSION_USE_SIGNER = True
#### **Configure Session Lifetime and Cookie Security Flags**
This is mandatory for *all* deployments, whether stateless or server-side.
This is mandatory for _all_ deployments, whether stateless or server-side.
```python
# superset_config.py
@@ -92,7 +92,8 @@ SESSION_COOKIE_SAMESITE = 'Lax' # Provide protection against CSRF attacks
```
> ##### Note on iFrame Embedding and `SESSION_COOKIE_SAMESITE`
>The recommended default setting `'Lax'` provides good CSRF protection for most use cases. However, if you need to embed Superset dashboards into other applications using an iFrame, you will need to change this setting to `'None'`.
>
> The recommended default setting `'Lax'` provides good CSRF protection for most use cases. However, if you need to embed Superset dashboards into other applications using an iFrame, you will need to change this setting to `'None'`.
SESSION_COOKIE_SAMESITE = 'None'
@@ -102,9 +103,9 @@ Setting SameSite to 'None' requires that SESSION_COOKIE_SECURE is also set to Tr
While Superset's built-in database authentication is convenient, for production it's highly recommended to integrate with an enterprise-grade identity provider (IdP).
* **Use an Enterprise IdP:** Configure authentication via OAuth or LDAP to leverage your organization's existing identity management system. This provides benefits like Single Sign-On (SSO), Multi-Factor Authentication (MFA), and centralized user provisioning/deprovisioning.
* **Principle of Least Privilege:** Assign users to the most restrictive roles necessary for their jobs. Avoid over-provisioning users with Admin or Alpha roles, and ensure row-level security is applied where appropriate.
* **Admin Accounts:** Delete or disable the default admin user after a new administrative account has been configured.
- **Use an Enterprise IdP:** Configure authentication via OAuth or LDAP to leverage your organization's existing identity management system. This provides benefits like Single Sign-On (SSO), Multi-Factor Authentication (MFA), and centralized user provisioning/deprovisioning.
- **Principle of Least Privilege:** Assign users to the most restrictive roles necessary for their jobs. Avoid over-provisioning users with Admin or Alpha roles, and ensure row-level security is applied where appropriate.
- **Admin Accounts:** Delete or disable the default admin user after a new administrative account has been configured.
### **Content Security Policy (CSP) and Other Headers**
@@ -122,48 +123,48 @@ Here's the documentation section how how to set up Talisman: https://superset.ap
>
> It is essential to understand that **Apache Superset is a data visualization and exploration platform, not a database firewall or a comprehensive security solution for your data warehouse.** While Superset provides features to help manage data access, the ultimate responsibility for securing your underlying databases lies with your database administrators (DBAs) and security teams. This includes managing network access, user privileges, and fine-grained permissions directly within the database. The configurations below are an important secondary layer of security but should not be your only line of defense.
* **Use a Dedicated Database User:** The database connection configured in Superset should use a dedicated, limited-privilege database user. This user should only have the minimum required permissions (e.g., `SELECT` on specific schemas) for the data sources it needs to query. It should **not** have `INSERT`, `UPDATE`, `DELETE`, or administrative privileges.
* **Restrict Dangerous SQL Functions:** To mitigate potential SQL injection risks, configure the `DISALLOWED_SQL_FUNCTIONS` list in your `superset_config.py`. Be aware that this is a defense-in-depth measure, not a substitute for proper database permissions.
- **Use a Dedicated Database User:** The database connection configured in Superset should use a dedicated, limited-privilege database user. This user should only have the minimum required permissions (e.g., `SELECT` on specific schemas) for the data sources it needs to query. It should **not** have `INSERT`, `UPDATE`, `DELETE`, or administrative privileges.
- **Restrict Dangerous SQL Functions:** To mitigate potential SQL injection risks, configure the `DISALLOWED_SQL_FUNCTIONS` list in your `superset_config.py`. Be aware that this is a defense-in-depth measure, not a substitute for proper database permissions.
### **Additional Security Layers**
* **Web Application Firewall (WAF):** Deploying Superset behind a WAF (e.g., Cloudflare, AWS WAF) is strongly recommended. A WAF with a standard ruleset (like the OWASP Core Rule Set) provides a critical layer of defense against common attacks like SQL Injection, XSS, and remote code execution.
- **Web Application Firewall (WAF):** Deploying Superset behind a WAF (e.g., Cloudflare, AWS WAF) is strongly recommended. A WAF with a standard ruleset (like the OWASP Core Rule Set) provides a critical layer of defense against common attacks like SQL Injection, XSS, and remote code execution.
### **Monitoring and Logging**
* **Configure Structured Logging:** Set up a robust logging configuration to capture important security events.
* **Centralize Logs:** Ship logs from all Superset components (frontend, worker, etc.) to a centralized SIEM (Security Information and Event Management) system for analysis and alerting.
* **Monitor Key Events:** Create alerts for suspicious activities, including:
* Multiple failed login attempts for a single user or from a single IP address.
* Changes to user roles or permissions.
* Creation or deletion of high-privilege users.
* Attempts to use disallowed SQL functions.
- **Configure Structured Logging:** Set up a robust logging configuration to capture important security events.
- **Centralize Logs:** Ship logs from all Superset components (frontend, worker, etc.) to a centralized SIEM (Security Information and Event Management) system for analysis and alerting.
- **Monitor Key Events:** Create alerts for suspicious activities, including:
- Multiple failed login attempts for a single user or from a single IP address.
- Changes to user roles or permissions.
- Creation or deletion of high-privilege users.
- Attempts to use disallowed SQL functions.
-----
---
### **Appendix A: Production Deployment Checklist**
#### **Initial Setup:**
- [ ] HTTPS/TLS is configured and enforced via a reverse proxy.
- [ ] A unique, strong `SUPERSET_SECRET_KEY` is generated and secured in an environment variable or secrets vault.
- [ ] Server-side session management is configured (e.g., Redis).
- [ ] `PERMANENT_SESSION_LIFETIME` is set to a short duration (e.g., 8 hours).
- [ ] All session cookie security flags (`Secure`, `HttpOnly`, `SameSite`) are enabled.
- [ ] `DEBUG` mode is set to `False`.
- [ ] Talisman is explicitly enabled and configured with a strict Content Security Policy.
- [ ] Database connections use dedicated, limited-privilege accounts.
- [ ] Authentication is integrated with an enterprise identity provider (OAuth/LDAP).
- [ ] A Web Application Firewall (WAF) is deployed in front of Superset.
- [ ] Logging is configured and logs are shipped to a central monitoring system.
- [ ] HTTPS/TLS is configured and enforced via a reverse proxy.
- [ ] A unique, strong `SUPERSET_SECRET_KEY` is generated and secured in an environment variable or secrets vault.
- [ ] Server-side session management is configured (e.g., Redis).
- [ ] `PERMANENT_SESSION_LIFETIME` is set to a short duration (e.g., 8 hours).
- [ ] All session cookie security flags (`Secure`, `HttpOnly`, `SameSite`) are enabled.
- [ ] `DEBUG` mode is set to `False`.
- [ ] Talisman is explicitly enabled and configured with a strict Content Security Policy.
- [ ] Database connections use dedicated, limited-privilege accounts.
- [ ] Authentication is integrated with an enterprise identity provider (OAuth/LDAP).
- [ ] A Web Application Firewall (WAF) is deployed in front of Superset.
- [ ] Logging is configured and logs are shipped to a central monitoring system.
#### **Ongoing Maintenance:**
- [ ] Regularly update to the latest major or minor versions of Superset. Those versions receive up-to-date security patches.
- [ ] Rotate the `SUPERSET_SECRET_KEY` periodically (e.g., quarterly) and after any potential security incident.
- [ ] Rotate the other security-critical secrets (guest-token and async-query JWT secrets, SMTP and database credentials) on the cadence in Appendix C, and after any potential security incident.
- [ ] Conduct quarterly access reviews for all users.
- [ ] Assuming logging and monitoring is in place, review security monitoring alerts weekly.
- [ ] Regularly update to the latest major or minor versions of Superset. Those versions receive up-to-date security patches.
- [ ] Rotate the `SUPERSET_SECRET_KEY` periodically (e.g., quarterly) and after any potential security incident.
- [ ] Rotate the other security-critical secrets (guest-token and async-query JWT secrets, SMTP and database credentials) on the cadence in Appendix C, and after any potential security incident.
- [ ] Conduct quarterly access reviews for all users.
- [ ] Assuming logging and monitoring is in place, review security monitoring alerts weekly.
### **Appendix B: `SECRET_KEY` Rotation and Compromise Response**
@@ -178,13 +179,13 @@ https://superset.apache.org/admin-docs/configuration/configuring-superset/#rotat
`SUPERSET_SECRET_KEY` is not the only security-critical secret in a Superset deployment. Maintain an inventory of all such secrets, store each in a secrets manager (not in `superset_config.py` or version control), assign a responsible maintainer, and rotate them on a defined cadence as well as after any suspected compromise.
| Secret | Purpose | Risk if leaked | Suggested rotation |
|---|---|---|---|
| `SUPERSET_SECRET_KEY` | Signs session cookies; key material for encrypting stored DB credentials (Fernet/AES) | Forged sessions (auth bypass / privilege escalation); decryption of exfiltrated metadata-DB secrets | Quarterly + post-incident |
| `GUEST_TOKEN_JWT_SECRET` | Signs embedded-dashboard guest tokens | Forged guest tokens → unauthorized dashboard/data access | Quarterly + post-incident |
| `GLOBAL_ASYNC_QUERIES_JWT_SECRET` | Signs the async-query channel JWT | Forged async-query tokens | Quarterly + post-incident |
| SMTP password | Outbound email for alerts & reports | Email relay abuse / spoofing | Per organizational policy + post-incident |
| Database connection passwords | Access to analytical databases and the metadata DB | Direct database access | Per organizational policy + post-incident |
| Secret | Purpose | Risk if leaked | Suggested rotation |
| --------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| `SUPERSET_SECRET_KEY` | Signs session cookies; key material for encrypting stored DB credentials (Fernet/AES) | Forged sessions (auth bypass / privilege escalation); decryption of exfiltrated metadata-DB secrets | Quarterly + post-incident |
| `GUEST_TOKEN_JWT_SECRET` | Signs embedded-dashboard guest tokens | Forged guest tokens → unauthorized dashboard/data access | Quarterly + post-incident |
| `GLOBAL_ASYNC_QUERIES_JWT_SECRET` | Signs the async-query channel JWT | Forged async-query tokens | Quarterly + post-incident |
| SMTP password | Outbound email for alerts & reports | Email relay abuse / spoofing | Per organizational policy + post-incident |
| Database connection passwords | Access to analytical databases and the metadata DB | Direct database access | Per organizational policy + post-incident |
Notes:
@@ -193,6 +194,7 @@ Notes:
- Keep the register under change control so new secrets introduced by future features are added to the rotation schedule.
:::resources
- [Blog: Running Apache Superset on the Open Internet](https://preset.io/blog/running-apache-superset-on-the-open-internet-a-report-from-the-fireline/)
- [Blog: How Security Vulnerabilities are Reported & Handled in Apache Superset](https://preset.io/blog/how-security-vulnerabilities-are-reported-and-handled-in-apache-superset/)
:::
:::
+122 -28
View File
@@ -24,13 +24,13 @@ A table with the permissions for these roles can be found at [/RESOURCES/STANDAR
Admins have all possible rights, including granting or revoking rights from other
users and altering other peoples slices and dashboards.
>#### Threat Model and Privilege Boundaries: The Admin Role
> #### Threat Model and Privilege Boundaries: The Admin Role
>
>Apache Superset is built with a granular permission model where users assigned the Admin role are considered fully trusted. Admins possess complete control over the application's configuration, UI rendering, and access controls.
> Apache Superset is built with a granular permission model where users assigned the Admin role are considered fully trusted. Admins possess complete control over the application's configuration, UI rendering, and access controls.
>
>Consequently, actions performed by an Admin that alter the application's behavior or presentation—such as injecting custom CSS, modifying Jinja templates, or altering security flags—are intended administrative capabilities by design.
> Consequently, actions performed by an Admin that alter the application's behavior or presentation—such as injecting custom CSS, modifying Jinja templates, or altering security flags—are intended administrative capabilities by design.
>
>In accordance with MITRE CNA Rule 4.1, a vulnerability must represent a violation of an explicit security policy. Because the Admin role is defined as a trusted operational boundary, actions executed with Admin privileges do not cross a security perimeter. Therefore, exploit vectors that strictly require Admin access are not classified as security vulnerabilities and are ineligible for CVE assignment.
> In accordance with MITRE CNA Rule 4.1, a vulnerability must represent a violation of an explicit security policy. Because the Admin role is defined as a trusted operational boundary, actions executed with Admin privileges do not cross a security perimeter. Therefore, exploit vectors that strictly require Admin access are not classified as security vulnerabilities and are ineligible for CVE assignment.
### Alpha
@@ -54,10 +54,10 @@ to all databases by default, both **Alpha** and **Gamma** users need to be given
Beyond the base `sql_lab` role, two additional SQL Lab permissions must be explicitly granted for users who need these capabilities:
| Permission | Feature |
|------------|---------|
| `can_estimate_query_cost` on `SQLLab` | Estimate query cost before running |
| `can_format_sql` on `SQLLab` | Format SQL using the database's dialect |
| Permission | Feature |
| ------------------------------------- | --------------------------------------- |
| `can_estimate_query_cost` on `SQLLab` | Estimate query cost before running |
| `can_format_sql` on `SQLLab` | Format SQL using the database's dialect |
Grant these in **Security → List Roles** by adding the permissions to the relevant role.
@@ -73,6 +73,7 @@ users who need to view dashboards. It provides minimal read-only access for:
- Viewing annotations on charts
The Public role explicitly excludes:
- Any write permissions on dashboards, charts, or datasets
- SQL Lab access
- Share functionality
@@ -197,6 +198,51 @@ Available per-entity overrides are:
When an override is set, it replaces `SUBJECTS_RELATED_TYPES` for that picker. When it is `None`,
the picker inherits the global default.
#### Looking Up Subjects via API
Superset exposes a read-only REST API for resolving subjects:
```
GET /api/v1/security/subject/
```
The main use case is **id mapping** — given a user, role, or group id, callers (including
extensions) can look up the corresponding subject entity, and vice versa. Access is gated by
the `can_read` permission on the `Subject` resource, which is granted to **Admins only** by
default, since subjects enumerate every user, role, and group on the instance. Callers without
that permission receive a `403`. Only `GET` (list, get, info) is exposed — there is no create,
update, or delete, because subjects are derived automatically from users, roles, and groups and
kept in sync internally.
**Resolve the subject for a given principal id** using [Rison](https://github.com/Nanonid/rison)
query syntax:
```
GET /api/v1/security/subject/?q=(filters:!((col:user_id,opr:eq,value:5)))
GET /api/v1/security/subject/?q=(filters:!((col:role_id,opr:eq,value:3)))
GET /api/v1/security/subject/?q=(filters:!((col:group_id,opr:eq,value:2)))
```
**Filter by subject type or active status:**
```
GET /api/v1/security/subject/?q=(filters:!((col:type,opr:eq,value:1)))
GET /api/v1/security/subject/?q=(filters:!((col:active,opr:eq,value:!t)))
```
The `type` column is an integer enum: `1` for User, `2` for Role, `3` for Group
(`superset.subjects.types.SubjectType`).
**Search by label:**
```
GET /api/v1/security/subject/?q=(filters:!((col:label,opr:subject_all_text,value:finance)))
```
Each subject in the response includes flat scalar ids (`user_id`, `role_id`, `group_id`) rather
than a nested object, so callers can match directly on whichever id they already have — only the
id field matching the subject's `type` is populated; the others are `null`.
### Dashboard Access Control
Access to dashboards is managed via editors (subjects that have edit permissions to the dashboard).
@@ -236,6 +282,7 @@ viewers returns the resource to the dataset-based fallback. Explicit Viewers are
going forward; the implicit fallback may be deprecated and removed in a later major version.
**Important considerations:**
- Viewer access uses normal dataset checks unless `VIEWER_PROMISCUOUS_MODE` is enabled
- With `VIEWER_PROMISCUOUS_MODE`, dashboard viewer access can bypass dataset-level checks for
charts and datasets in that dashboard
@@ -243,10 +290,56 @@ going forward; the implicit fallback may be deprecated and removed in a later ma
- The dashboard must still be published to be visible
This feature is particularly useful for:
- Making specific dashboards public while keeping others private
- Granting access to dashboards without exposing the underlying datasets for other uses
- Creating dashboard-specific access patterns that don't align with dataset permissions
#### Assigning the creator's groups automatically
```python
FEATURE_FLAGS = {
"ENABLE_VIEWERS": True,
"ASSIGN_CREATOR_GROUPS_AS_VIEWERS": True,
}
```
This requires `ENABLE_VIEWERS` — it has no effect on its own, since it works by populating the
`viewers` relationship that `ENABLE_VIEWERS` governs.
With this enabled, a newly created dashboard or chart is shared read-only with every group its
creator belongs to, unless the create payload names viewers explicitly. It applies to every path
that creates an asset: the REST API, `/dashboard/new/`, save-as from Explore, dashboard copy,
the import commands, and the MCP tools. Datasets are unaffected, as they have editors but no
viewers.
For dashboards, viewer access additionally requires the dashboard to be **published** — the same
rule that governs every dashboard viewer. Until a new dashboard is published its creator's groups
see nothing, and because it now has viewers the dataset-based fallback no longer applies to it
either; group members gain access only once it is published. Charts have no such publish gate, so a
new chart's viewer grant takes effect immediately. Note, though, that the viewer relationship
governs access to the chart itself; rendering its **data** still runs the normal datasource
permission check unless `VIEWER_PROMISCUOUS_MODE` is enabled — a group member without access to the
underlying dataset can open the chart but won't load its data.
Note that this **narrows** access rather than widening it. Because an asset with no viewers falls
back to dataset-based access, giving new assets a viewer makes that fallback unreachable for them:
a colleague who could previously open a new dashboard by virtue of dataset access can no longer do
so unless they share one of the creator's groups. Existing assets are untouched — only assets
created after the feature flag is enabled are affected.
The same narrowing affects background execution as a fixed identity. Alerts, reports, and
thumbnails that run as a `FixedExecutor` service account (via `ALERT_REPORTS_EXECUTE_AS` or
`THUMBNAIL_EXECUTE_AS`) reach a chart or dashboard through the dataset fallback when that account
is neither an editor nor a viewer. Once a new asset is scoped to the creator's groups that
fallback is gone, so rendering fails `raise_for_access` unless the executor account is an admin,
an editor, or shares one of those groups. If a fixed executor must render assets it does not own,
grant it the needed access (make it an admin or add it to the relevant groups) — or leave the
feature flag off.
The setting assigns groups as *viewers*, not editors, so group members get read-only access and
cannot modify or delete the asset.
### SQL Execution Security Considerations
Apache Superset includes features designed to provide safeguards when interacting with connected databases, such as the `DISALLOWED_SQL_FUNCTIONS` configuration setting. This aims to prevent the execution of potentially harmful database functions or system variables directly from Superset interfaces like SQL Lab.
@@ -260,10 +353,11 @@ However, it is crucial to understand the following:
**Database Security is Paramount**: The ultimate responsibility for securing database access, controlling permissions, and preventing unauthorized function execution lies with the database administrators (DBAs) and security teams managing the underlying database instance.
**Recommended Database Practices**: We strongly recommend implementing security best practices at the database level, including:
* **Least Privilege**: Connecting Superset using dedicated database user accounts with the minimum permissions required for Superset's operation (typically read-only access to necessary schemas/tables).
* **Database Roles & Permissions**: Utilizing database-native roles and permissions to restrict access to sensitive functions, system variables (like `@@hostname`), schemas, or tables.
* **Network Security**: Employing network-level controls like database firewalls or proxies to restrict connections.
* **Auditing**: Enabling database-level auditing to monitor executed queries and access patterns.
- **Least Privilege**: Connecting Superset using dedicated database user accounts with the minimum permissions required for Superset's operation (typically read-only access to necessary schemas/tables).
- **Database Roles & Permissions**: Utilizing database-native roles and permissions to restrict access to sensitive functions, system variables (like `@@hostname`), schemas, or tables.
- **Network Security**: Employing network-level controls like database firewalls or proxies to restrict connections.
- **Auditing**: Enabling database-level auditing to monitor executed queries and access patterns.
By combining Superset's configurable safeguards with strong database-level security practices, you can achieve a more robust and layered security posture.
@@ -419,11 +513,11 @@ rules are:
For example, if a dataset has three filters:
| Filter | Clause | Group Key |
|--------|--------|-----------|
| F1 | `department = 'Finance'` | `department` |
| F2 | `department = 'Marketing'` | `department` |
| F3 | `region = 'Europe'` | `region` |
| Filter | Clause | Group Key |
| ------ | -------------------------- | ------------ |
| F1 | `department = 'Finance'` | `department` |
| F2 | `department = 'Marketing'` | `department` |
| F3 | `region = 'Europe'` | `region` |
The resulting WHERE clause would be:
@@ -507,7 +601,7 @@ GET /api/v1/rowlevelsecurity/<id>
```
The response includes the filter's `name`, `filter_type` (Regular or Base), `clause`,
`group_key`, assigned `tables` (with id, schema, and table\_name), and assigned `subjects`.
`group_key`, assigned `tables` (with id, schema, and table_name), and assigned `subjects`.
:::tip Auditing RLS for virtual datasets
To find all RLS rules that could affect a particular virtual dataset, query the list
@@ -553,13 +647,13 @@ This reduces the risk for replay attacks and session hijacking.
Superset uses [Flask-Session](https://flask-session.readthedocs.io/en/latest/) to manage server side sessions.
To enable this extension you have to set:
``` python
```python
SESSION_SERVER_SIDE = True
```
Flask-Session offers multiple backend session interfaces for Flask, here's an example for Redis:
``` python
```python
from redis import Redis
SESSION_TYPE = "redis"
@@ -588,8 +682,8 @@ It's extremely important to correctly configure a Content Security Policy when d
prevent many types of attacks. Superset provides two variables in `config.py` for deploying a CSP:
- `TALISMAN_ENABLED` defaults to `True`; set this to `False` in order to disable CSP
- `TALISMAN_CONFIG` holds the actual the policy definition (*see example below*) as well as any
other arguments to be passed to Talisman.
- `TALISMAN_CONFIG` holds the actual the policy definition (_see example below_) as well as any
other arguments to be passed to Talisman.
When running in production mode, Superset will check at startup for the presence
of a CSP. If one is not found, it will issue a warning with the security risks. For environments
@@ -605,12 +699,12 @@ this warning using the `CONTENT_SECURITY_POLICY_WARNING` key in `config.py`.
```
- Only scripts marked with a [nonce](https://content-security-policy.com/nonce/) can be loaded and executed.
Nonce is a random string automatically generated by Talisman on each page load.
You can get current nonce value by calling jinja macro `csp_nonce()`.
Nonce is a random string automatically generated by Talisman on each page load.
You can get current nonce value by calling jinja macro `csp_nonce()`.
```html
<script nonce="{{ csp_nonce() }}">
/* my script */
/* my script */
</script>
```
@@ -628,7 +722,7 @@ You can get current nonce value by calling jinja macro `csp_nonce()`.
```
- Cartodiagram charts request map data (image and json) from external resources that can be edited by users,
and therefore either require a list of allowed domains to request from or a wildcard (`'*'`) for `img-src` and `connect-src`.
and therefore either require a list of allowed domains to request from or a wildcard (`'*'`) for `img-src` and `connect-src`.
- Other CSP directives default to `'self'` to limit content to the same origin as the Superset server.
@@ -639,12 +733,12 @@ In order to adjust provided CSP configuration to your needs, follow the instruct
Setting `TALISMAN_ENABLED = True` will invoke Talisman's protection with its default arguments,
of which `content_security_policy` is only one. Those can be found in the
[Talisman documentation](https://pypi.org/project/flask-talisman/) under *Options*.
[Talisman documentation](https://pypi.org/project/flask-talisman/) under _Options_.
These generally improve security, but administrators should be aware of their existence.
In particular, the option of `force_https = True` (`False` by default) may break Superset's Alerts & Reports
if workers are configured to access charts via a `WEBDRIVER_BASEURL` beginning
with `http://`. As long as a Superset deployment enforces https upstream, e.g.,
with `http://`. As long as a Superset deployment enforces https upstream, e.g.,
through a load balancer or application gateway, it should be acceptable to keep this
option disabled. Otherwise, you may want to enable `force_https` like this:
@@ -9,8 +9,8 @@ version: 2
Users can configure automated alerts and reports to send dashboards or charts to an email recipient or Slack channel.
- *Alerts* are sent when a SQL condition is reached
- *Reports* are sent on a schedule
- _Alerts_ are sent when a SQL condition is reached
- _Reports_ are sent on a schedule
Alerts and reports are disabled by default. To turn them on, you'll need to change configuration settings and install a suitable headless browser in your environment.
@@ -26,16 +26,17 @@ Alerts and reports are disabled by default. To turn them on, you'll need to chan
- emails: `SMTP_*` settings
- Slack messages: `SLACK_API_TOKEN`
- Users can customize the email subject by including date code placeholders, which will automatically be replaced with the corresponding UTC date when the email is sent. To enable this functionality, activate the `"DATE_FORMAT_IN_EMAIL_SUBJECT"` [feature flag](/admin-docs/configuration/configuring-superset#feature-flags). This enables date formatting in email subjects, preventing all reporting emails from being grouped into the same thread (optional for the reporting feature).
- Use date codes from [strftime.org](https://strftime.org/) to create the email subject.
- If no date code is provided, the original string will be used as the email subject.
- Use date codes from [strftime.org](https://strftime.org/) to create the email subject.
- If no date code is provided, the original string will be used as the email subject.
##### Disable dry-run mode
Screenshots will be taken but no messages actually sent as long as `ALERT_REPORTS_NOTIFICATION_DRY_RUN = True`, its default value in `docker/pythonpath_dev/superset_config.py`. To disable dry-run mode and start receiving email/Slack notifications, set `ALERT_REPORTS_NOTIFICATION_DRY_RUN` to `False` in [superset config](https://github.com/apache/superset/blob/master/docker/pythonpath_dev/superset_config.py).
Screenshots will be taken but no messages actually sent as long as `ALERT_REPORTS_NOTIFICATION_DRY_RUN = True`, its default value in `docker/pythonpath_dev/superset_config.py`. To disable dry-run mode and start receiving email/Slack notifications, set `ALERT_REPORTS_NOTIFICATION_DRY_RUN` to `False` in [superset config](https://github.com/apache/superset/blob/master/docker/pythonpath_dev/superset_config.py).
#### In your `Dockerfile`
You'll need to extend the Superset image to include a headless browser. Your options include:
- Use Playwright with Chrome: this is the recommended approach as of version 4.1.x or greater. A working example of a Dockerfile that installs these tools is provided under "Building your own production Docker image" on the [Docker Builds](/admin-docs/installation/docker-builds#building-your-own-production-docker-image) page. Read the code comments there as you'll also need to change a feature flag in your config.
- Use Firefox: you'll need to install geckodriver and Firefox.
- Use Chrome without Playwright: you'll need to install Chrome and set the value of `WEBDRIVER_TYPE` to `"chrome"` in your `superset_config.py`.
@@ -189,7 +190,7 @@ You need to replace default values with your custom Redis, Slack and/or SMTP con
Superset uses Celery beat and Celery worker(s) to send alerts and reports.
- The beat is the scheduler that tells the worker when to perform its tasks. This schedule is defined when you create the alert or report.
- The worker will process the tasks that need to be performed when an alert or report is fired.
- The worker will process the tasks that need to be performed when an alert or report is fired.
In the `CeleryConfig`, only the `beat_schedule` is relevant to this feature, the rest of the `CeleryConfig` can be changed for your needs.
@@ -296,7 +297,7 @@ Please refer to `ExecutorType` in the codebase for other executor types.
It's also possible to specify a minimum interval between each report's execution through the config file:
``` python
```python
# Set a minimum interval threshold between executions (for each Alert/Report)
# Value should be an integer
ALERT_MINIMUM_INTERVAL = int(timedelta(minutes=10).total_seconds())
@@ -305,7 +306,7 @@ REPORT_MINIMUM_INTERVAL = int(timedelta(minutes=5).total_seconds())
Alternatively, you can assign a function to `ALERT_MINIMUM_INTERVAL` and/or `REPORT_MINIMUM_INTERVAL`. This is useful to dynamically retrieve a value as needed:
``` python
```python
def alert_dynamic_minimal_interval(**kwargs) -> int:
"""
Define logic here to retrieve the value dynamically
@@ -318,7 +319,7 @@ ALERT_MINIMUM_INTERVAL = alert_dynamic_minimal_interval
For security, Superset rewrites external links in alert/report email HTML so
they go through a warning page before the user is navigated to the external
site. Internal links (matching your configured base URL) are not affected.
site. Internal links (matching your configured base URL) are not affected.
```python
# Disable external link redirection entirely (default: True)
@@ -330,17 +331,17 @@ to determine which hosts are internal.
## Troubleshooting
There are many reasons that reports might not be working. Try these steps to check for specific issues.
There are many reasons that reports might not be working. Try these steps to check for specific issues.
### Confirm feature flag is enabled and you have sufficient permissions
If you don't see "Alerts & Reports" under the *Manage* section of the Settings dropdown in the Superset UI, you need to enable the `ALERT_REPORTS` feature flag (see above). Enable another feature flag and check to see that it took effect, to verify that your config file is getting loaded.
If you don't see "Alerts & Reports" under the _Manage_ section of the Settings dropdown in the Superset UI, you need to enable the `ALERT_REPORTS` feature flag (see above). Enable another feature flag and check to see that it took effect, to verify that your config file is getting loaded.
Log in as an admin user to ensure you have adequate permissions.
### Check the logs of your Celery worker
This is the best source of information about the problem. In a docker compose deployment, you can do this with a command like `docker logs superset_worker --since 1h`.
This is the best source of information about the problem. In a docker compose deployment, you can do this with a command like `docker logs superset_worker --since 1h`.
### Check web browser and webdriver installation
@@ -352,7 +353,7 @@ If you are handling the installation of the headless browser on your own, do you
One symptom of an invalid connection to an email server is receiving an error of `[Errno 110] Connection timed out` in your logs when the report tries to send.
Confirm via testing that your outbound email configuration is correct. Here is the simplest test, for an un-authenticated email SMTP email service running on port 25. If you are sending over SSL, for instance, study how [Superset's codebase sends emails](https://github.com/apache/superset/blob/master/superset/utils/core.py#L818) and then test with those commands and arguments.
Confirm via testing that your outbound email configuration is correct. Here is the simplest test, for an un-authenticated email SMTP email service running on port 25. If you are sending over SSL, for instance, study how [Superset's codebase sends emails](https://github.com/apache/superset/blob/master/superset/utils/core.py#L818) and then test with those commands and arguments.
Start Python in your worker environment, replace all example values, and run:
@@ -378,16 +379,16 @@ This should send an email.
Possible fixes:
- Some cloud hosts disable outgoing unauthenticated SMTP email to prevent spam. For instance, [Azure blocks port 25 by default on some machines](https://learn.microsoft.com/en-us/azure/virtual-network/troubleshoot-outbound-smtp-connectivity). Enable that port or use another sending method.
- Some cloud hosts disable outgoing unauthenticated SMTP email to prevent spam. For instance, [Azure blocks port 25 by default on some machines](https://learn.microsoft.com/en-us/azure/virtual-network/troubleshoot-outbound-smtp-connectivity). Enable that port or use another sending method.
- Use another set of SMTP credentials that you verify works in this setup.
### Browse to your report from the worker
The worker may be unable to reach the report. It will use the value of `WEBDRIVER_BASEURL` to browse to the report. If that route is invalid, or presents an authentication challenge that the worker can't pass, the report screenshot will fail.
The worker may be unable to reach the report. It will use the value of `WEBDRIVER_BASEURL` to browse to the report. If that route is invalid, or presents an authentication challenge that the worker can't pass, the report screenshot will fail.
Check this by attempting to `curl` the URL of a report that you see in the error logs of your worker. For instance, from the worker environment, run `curl http://superset_app:8088/superset/dashboard/1/`. You may get different responses depending on whether the dashboard exists - for example, you may need to change the `1` in that URL. If there's a URL in your logs from a failed report screenshot, that's a good place to start. The goal is to determine a valid value for `WEBDRIVER_BASEURL` and determine if an issue like HTTPS or authentication is redirecting your worker.
In a deployment with authentication measures enabled like HTTPS and Single Sign-On, it may make sense to have the worker navigate directly to the Superset application running in the same location, avoiding the need to sign in. For instance, you could use `WEBDRIVER_BASEURL="http://superset_app:8088"` for a docker compose deployment, and set `"force_https": False,` in your `TALISMAN_CONFIG`.
In a deployment with authentication measures enabled like HTTPS and Single Sign-On, it may make sense to have the worker navigate directly to the Superset application running in the same location, avoiding the need to sign in. For instance, you could use `WEBDRIVER_BASEURL="http://superset_app:8088"` for a docker compose deployment, and set `"force_https": False,` in your `TALISMAN_CONFIG`.
### Duplicate report deliveries
@@ -495,6 +496,7 @@ schedule the queries that have `schedule_info` in their JSON metadata. For sched
Airflow, additional fields can be easily added to the configuration file above.
:::resources
- [Tutorial: Automated Alerts and Reporting via Slack/Email in Superset](https://dev.to/ngtduc693/apache-superset-topic-5-automated-alerts-and-reporting-via-slackemail-in-superset-2gbe)
- [Blog: Integrating Slack alerts and Apache Superset for better data observability](https://medium.com/affinityanswers-tech/integrating-slack-alerts-and-apache-superset-for-better-data-observability-fd2f9a12c350)
:::
:::
@@ -104,5 +104,6 @@ celery --app=superset.tasks.celery_app:app flower
```
:::resources
- [Blog: How to Set Up Global Async Queries (GAQ) in Apache Superset](https://medium.com/@ngigilevis/how-to-set-up-global-async-queries-gaq-in-apache-superset-a-complete-guide-9d2f4a047559)
:::
:::
@@ -1,26 +1,28 @@
{/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/}
---
title: AWS IAM Authentication
sidebar_label: AWS IAM Authentication
sidebar_position: 15
---
# AWS IAM Authentication for AWS Databases
@@ -31,7 +33,7 @@ Cross-account IAM role assumption via STS `AssumeRole` is supported, allowing a
## Prerequisites
- Enable the `AWS_DATABASE_IAM_AUTH` feature flag in `superset_config.py`. IAM authentication is gated behind this flag; if it is disabled, connections using `aws_iam` fail with *"AWS IAM database authentication is not enabled."*
- Enable the `AWS_DATABASE_IAM_AUTH` feature flag in `superset_config.py`. IAM authentication is gated behind this flag; if it is disabled, connections using `aws_iam` fail with _"AWS IAM database authentication is not enabled."_
```python
FEATURE_FLAGS = {
"AWS_DATABASE_IAM_AUTH": True,
@@ -66,14 +68,14 @@ IAM authentication is configured via the **encrypted_extra** field of the databa
}
```
| Field | Required | Description |
|-------|----------|-------------|
| `enabled` | Yes | Set to `true` to activate IAM auth |
| `role_arn` | No | ARN of the cross-account IAM role to assume via STS. Omit for same-account auth |
| `external_id` | No | External ID for the STS `AssumeRole` call, if required by the target role's trust policy |
| `region` | Yes | AWS region of the database cluster |
| `db_username` | Yes | The database username associated with the IAM identity |
| `session_duration` | No | STS session duration in seconds (default: `3600`) |
| Field | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------------------------- |
| `enabled` | Yes | Set to `true` to activate IAM auth |
| `role_arn` | No | ARN of the cross-account IAM role to assume via STS. Omit for same-account auth |
| `external_id` | No | External ID for the STS `AssumeRole` call, if required by the target role's trust policy |
| `region` | Yes | AWS region of the database cluster |
| `db_username` | Yes | The database username associated with the IAM identity |
| `session_duration` | No | STS session duration in seconds (default: `3600`) |
### Redshift (Serverless)
@@ -271,6 +271,7 @@ While database-backed operations work reliably, the Redis backend is recommended
deployments where low latency and reduced database load are important.
:::resources
- [Blog: The Data Engineer's Guide to Lightning-Fast Superset Dashboards](https://preset.io/blog/the-data-engineers-guide-to-lightning-fast-apache-superset-dashboards/)
- [Blog: Accelerating Dashboards with Materialized Views](https://preset.io/blog/accelerating-apache-superset-dashboards-with-materialized-views/)
:::
:::
@@ -225,7 +225,7 @@ RequestHeader set X-Forwarded-Proto "https"
## Configuring the application root
*Please be advised that this feature is in BETA.*
_Please be advised that this feature is in BETA._
Superset supports running the application under a non-root path. The root path
prefix can be specified in one of three ways:
@@ -312,10 +312,13 @@ AUTH_USER_REGISTRATION_ROLE = "Public"
```
In case you want to assign the `Admin` role on new user registration, it can be assigned as follows:
```python
AUTH_USER_REGISTRATION_ROLE = "Admin"
```
If you encounter the [issue](https://github.com/apache/superset/issues/13243) of not being able to list users from the Superset main page settings, although a newly registered user has an `Admin` role, please re-run `superset init` to sync the required permissions. Below is the command to re-run `superset init` using docker compose.
```
docker-compose exec superset superset init
```
@@ -505,5 +508,6 @@ CELERY_BEAT_SCHEDULE = {
Adjust `retention_period_days` to control how long query rows are kept. Companion opt-in tasks (`prune_logs`, `prune_tasks`) exist for pruning the logs and tasks tables; see the commented-out examples in `superset/config.py`. Without enabling these tasks, the metadata database will grow unbounded over time.
:::resources
- [Blog: Feature Flags in Apache Superset](https://preset.io/blog/feature-flags-in-apache-superset-and-preset/)
:::
:::
@@ -22,10 +22,10 @@ The current list of countries can be found in the src
The Country Maps visualization already ships with the maps for the following countries:
<ul style={{columns: 3}}>
{countriesData.countries.map((country, index) => (
<li key={index}>{country}</li>
))}
<ul style={{ columns: 3 }}>
{countriesData.countries.map((country, index) => (
<li key={index}>{country}</li>
))}
</ul>
## Adding a New Country
@@ -7,7 +7,7 @@ version: 1
import featureFlags from '../_versioned_data/static/feature-flags.json';
export const FlagTable = ({flags}) => (
export const FlagTable = ({ flags }) => (
<table>
<thead>
<tr>
@@ -17,14 +17,21 @@ export const FlagTable = ({flags}) => (
</tr>
</thead>
<tbody>
{flags.map((flag) => (
{flags.map(flag => (
<tr key={flag.name}>
<td><code>{flag.name}</code></td>
<td><code>{flag.default ? 'True' : 'False'}</code></td>
<td>
<code>{flag.name}</code>
</td>
<td>
<code>{flag.default ? 'True' : 'False'}</code>
</td>
<td>
{flag.description}
{flag.docs && (
<> (<a href={flag.docs}>docs</a>)</>
<>
{' '}
(<a href={flag.docs}>docs</a>)
</>
)}
</td>
</tr>
@@ -50,12 +57,12 @@ FEATURE_FLAGS = {
Feature flags progress through lifecycle stages:
| Stage | Description |
|-------|-------------|
| Stage | Description |
| --------------- | ------------------------------------------------------------------------------ |
| **Development** | Experimental features under active development. May be incomplete or unstable. |
| **Testing** | Feature complete but undergoing testing. Usable but may contain bugs. |
| **Stable** | Production-ready features. Safe for all deployments. |
| **Deprecated** | Features scheduled for removal. Migrate away from these. |
| **Testing** | Feature complete but undergoing testing. Usable but may contain bugs. |
| **Stable** | Production-ready features. Safe for all deployments. |
| **Deprecated** | Features scheduled for removal. Migrate away from these. |
---
@@ -148,10 +148,10 @@ datasets by saving the following YAML to file and then running the **import_data
```yaml
databases:
- database_name: main
tables:
- table_name: random_time_series
columns:
- column_name: ds
verbose_name: datetime
- database_name: main
tables:
- table_name: random_time_series
columns:
- column_name: ds
verbose_name: datetime
```
@@ -18,7 +18,9 @@ DECKGL_BASE_MAP = [
['tile://https://your_personal_url/{z}/{x}/{y}.png', 'MyTile']
]
```
Openstreetmap tiles url can be added without prefix.
```python
DECKGL_BASE_MAP = [
['https://c.tile.openstreetmap.org/{z}/{x}/{y}.png', 'OpenStreetMap']
@@ -26,6 +28,7 @@ DECKGL_BASE_MAP = [
```
Default values are:
```python
DECKGL_BASE_MAP = [
['https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'Streets (OSM)'],
@@ -46,6 +49,7 @@ Setting `DECKGL_BASE_MAP` overwrite default values
:::
After defining your map tiles, set them in these variables:
- `CORS_OPTIONS`
- `connect-src` of `TALISMAN_CONFIG` and `TALISMAN_CONFIG_DEV` variables.
@@ -55,11 +55,11 @@ The MCP server runs as a separate process alongside Superset:
superset mcp run --host 127.0.0.1 --port 5008
```
| Flag | Default | Description |
|------|---------|-------------|
| `--host` | `127.0.0.1` | Host to bind to |
| `--port` | `5008` | Port to bind to |
| `--debug` | off | Enable debug logging |
| Flag | Default | Description |
| --------- | ----------- | -------------------- |
| `--host` | `127.0.0.1` | Host to bind to |
| `--port` | `5008` | Port to bind to |
| `--debug` | off | Enable debug logging |
The endpoint is available at `http://<host>:<port>/mcp`.
@@ -193,22 +193,24 @@ MCP_JWT_AUDIENCE = "your-audience"
:::warning
Store `MCP_JWT_SECRET` securely. Never commit it to version control. Use environment variables:
```python
import os
MCP_JWT_SECRET = os.environ.get("MCP_JWT_SECRET")
```
:::
#### JWT claims
The MCP server validates these standard claims:
| Claim | Config Key | Description |
|-------|-----------|-------------|
| `exp` | -- | Expiration time (always validated) |
| `iss` | `MCP_JWT_ISSUER` | Token issuer (optional but recommended) |
| `aud` | `MCP_JWT_AUDIENCE` | Token audience (optional but recommended) |
| `sub` | -- | Subject -- primary claim used to resolve the Superset user |
| Claim | Config Key | Description |
| ----- | ------------------ | ---------------------------------------------------------- |
| `exp` | -- | Expiration time (always validated) |
| `iss` | `MCP_JWT_ISSUER` | Token issuer (optional but recommended) |
| `aud` | `MCP_JWT_AUDIENCE` | Token audience (optional but recommended) |
| `sub` | -- | Subject -- primary claim used to resolve the Superset user |
#### User resolution
@@ -435,7 +437,7 @@ services:
superset:
image: apache/superset:latest
ports:
- "8088:8088"
- '8088:8088'
volumes:
- ./superset_config.py:/app/superset_config.py
environment:
@@ -443,9 +445,9 @@ services:
mcp:
image: apache/superset:latest
command: ["superset", "mcp", "run", "--host", "0.0.0.0", "--port", "5008"]
command: ['superset', 'mcp', 'run', '--host', '0.0.0.0', '--port', '5008']
ports:
- "5008:5008"
- '5008:5008'
volumes:
- ./superset_config.py:/app/superset_config.py
environment:
@@ -494,30 +496,30 @@ All MCP settings go in `superset_config.py`. Defaults are defined in `superset/m
### Core
| Setting | Default | Description |
|---------|---------|-------------|
| `MCP_SERVICE_HOST` | `"localhost"` | Host the MCP server binds to |
| `MCP_SERVICE_PORT` | `5008` | Port the MCP server binds to |
| `MCP_SERVICE_URL` | `None` | Public base URL for MCP-generated links (set this when behind a reverse proxy) |
| `MCP_DEBUG` | `False` | Enable debug logging |
| `MCP_DEV_USERNAME` | -- | Superset username for development mode (no auth) |
| `MCP_RBAC_ENABLED` | `True` | Enforce Superset's role-based access control on MCP tool calls. When `True`, each tool checks that the authenticated user has the required FAB permission before executing. Disable only for testing or trusted-network deployments. |
| Setting | Default | Description |
| ------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `MCP_SERVICE_HOST` | `"localhost"` | Host the MCP server binds to |
| `MCP_SERVICE_PORT` | `5008` | Port the MCP server binds to |
| `MCP_SERVICE_URL` | `None` | Public base URL for MCP-generated links (set this when behind a reverse proxy) |
| `MCP_DEBUG` | `False` | Enable debug logging |
| `MCP_DEV_USERNAME` | -- | Superset username for development mode (no auth) |
| `MCP_RBAC_ENABLED` | `True` | Enforce Superset's role-based access control on MCP tool calls. When `True`, each tool checks that the authenticated user has the required FAB permission before executing. Disable only for testing or trusted-network deployments. |
### Authentication
| Setting | Default | Description |
|---------|---------|-------------|
| `MCP_AUTH_ENABLED` | `False` | Enable JWT authentication |
| `MCP_JWT_ALGORITHM` | `"RS256"` | JWT signing algorithm (`RS256` or `HS256`) |
| `MCP_JWKS_URI` | `None` | JWKS endpoint URL (RS256) |
| `MCP_JWT_PUBLIC_KEY` | `None` | Static RSA public key string (RS256) |
| `MCP_JWT_SECRET` | `None` | Shared secret string (HS256) |
| `MCP_JWT_ISSUER` | `None` | Expected `iss` claim |
| `MCP_JWT_AUDIENCE` | `None` | Expected `aud` claim |
| `MCP_REQUIRED_SCOPES` | `[]` | Required JWT scopes |
| `MCP_JWT_DEBUG_ERRORS` | `False` | Log detailed JWT errors server-side (never exposed in HTTP responses per RFC 6750) |
| `MCP_AUTH_FACTORY` | `None` | Custom auth provider factory `(flask_app) -> auth_provider`. Takes precedence over built-in JWT |
| `MCP_USER_RESOLVER` | `None` | Custom function `(app, access_token) -> username` to extract a Superset username from a validated JWT token. When `None`, the default resolver checks `preferred_username`, `username`, `email`, and `sub` claims in that order. |
| Setting | Default | Description |
| ---------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MCP_AUTH_ENABLED` | `False` | Enable JWT authentication |
| `MCP_JWT_ALGORITHM` | `"RS256"` | JWT signing algorithm (`RS256` or `HS256`) |
| `MCP_JWKS_URI` | `None` | JWKS endpoint URL (RS256) |
| `MCP_JWT_PUBLIC_KEY` | `None` | Static RSA public key string (RS256) |
| `MCP_JWT_SECRET` | `None` | Shared secret string (HS256) |
| `MCP_JWT_ISSUER` | `None` | Expected `iss` claim |
| `MCP_JWT_AUDIENCE` | `None` | Expected `aud` claim |
| `MCP_REQUIRED_SCOPES` | `[]` | Required JWT scopes |
| `MCP_JWT_DEBUG_ERRORS` | `False` | Log detailed JWT errors server-side (never exposed in HTTP responses per RFC 6750) |
| `MCP_AUTH_FACTORY` | `None` | Custom auth provider factory `(flask_app) -> auth_provider`. Takes precedence over built-in JWT |
| `MCP_USER_RESOLVER` | `None` | Custom function `(app, access_token) -> username` to extract a Superset username from a validated JWT token. When `None`, the default resolver checks `preferred_username`, `username`, `email`, and `sub` claims in that order. |
### Response Size Guard
@@ -537,12 +539,12 @@ MCP_RESPONSE_SIZE_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `True` | Enable response size checking |
| `token_limit` | `25000` | Maximum estimated token count per response |
| `warn_threshold_pct` | `80` | Warn when response exceeds this percentage of the limit |
| `excluded_tools` | See above | Tools exempt from size checking (e.g., tools that return URLs, not data) |
| Key | Default | Description |
| -------------------- | --------- | ------------------------------------------------------------------------ |
| `enabled` | `True` | Enable response size checking |
| `token_limit` | `25000` | Maximum estimated token count per response |
| `warn_threshold_pct` | `80` | Warn when response exceeds this percentage of the limit |
| `excluded_tools` | See above | Tools exempt from size checking (e.g., tools that return URLs, not data) |
### Caching
@@ -568,18 +570,18 @@ MCP_CACHE_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `False` | Enable response caching |
| `CACHE_KEY_PREFIX` | `None` | Optional prefix for cache keys (useful for shared Redis) |
| `list_tools_ttl` | `300` | Cache TTL in seconds for `tools/list` |
| `list_resources_ttl` | `300` | Cache TTL for `resources/list` |
| `list_prompts_ttl` | `300` | Cache TTL for `prompts/list` |
| `read_resource_ttl` | `3600` | Cache TTL for `resources/read` |
| `get_prompt_ttl` | `3600` | Cache TTL for `prompts/get` |
| `call_tool_ttl` | `3600` | Cache TTL for `tools/call` |
| `max_item_size` | `1048576` | Maximum cached item size in bytes (1 MB) |
| `excluded_tools` | See above | Tools that are never cached (mutating or non-deterministic) |
| Key | Default | Description |
| -------------------- | --------- | ----------------------------------------------------------- |
| `enabled` | `False` | Enable response caching |
| `CACHE_KEY_PREFIX` | `None` | Optional prefix for cache keys (useful for shared Redis) |
| `list_tools_ttl` | `300` | Cache TTL in seconds for `tools/list` |
| `list_resources_ttl` | `300` | Cache TTL for `resources/list` |
| `list_prompts_ttl` | `300` | Cache TTL for `prompts/list` |
| `read_resource_ttl` | `3600` | Cache TTL for `resources/read` |
| `get_prompt_ttl` | `3600` | Cache TTL for `prompts/get` |
| `call_tool_ttl` | `3600` | Cache TTL for `tools/call` |
| `max_item_size` | `1048576` | Maximum cached item size in bytes (1 MB) |
| `excluded_tools` | See above | Tools that are never cached (mutating or non-deterministic) |
### Redis Store (Multi-Pod)
@@ -594,12 +596,12 @@ MCP_STORE_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `False` | Enable Redis-backed store |
| `CACHE_REDIS_URL` | `None` | Redis connection URL (e.g., `redis://redis-host:6379/0`) |
| `event_store_max_events` | `100` | Maximum events retained per session |
| `event_store_ttl` | `3600` | Event TTL in seconds |
| Key | Default | Description |
| ------------------------ | ------- | -------------------------------------------------------- |
| `enabled` | `False` | Enable Redis-backed store |
| `CACHE_REDIS_URL` | `None` | Redis connection URL (e.g., `redis://redis-host:6379/0`) |
| `event_store_max_events` | `100` | Maximum events retained per session |
| `event_store_ttl` | `3600` | Event TTL in seconds |
### Tool Search
@@ -622,15 +624,15 @@ MCP_TOOL_SEARCH_CONFIG = {
}
```
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `True` | Enable tool search. When `False`, all tools are listed upfront |
| `strategy` | `"bm25"` | Search ranking algorithm. `"bm25"` supports natural language; `"regex"` supports pattern matching |
| `max_results` | `5` | Maximum tools returned per search query |
| `always_visible` | See above | Tools that always appear in `list_tools`, regardless of search |
| `include_schemas` | `False` | When `False` (default, "summary mode"), search results omit `inputSchema` entirely and include a lightweight `parameters_hint` listing top-level parameter names. Set to `True` to include the full `inputSchema` in search results. Full schemas are always used when a tool is actually invoked via `call_tool`. |
| `compact_schemas` | `True` | Strip `$defs` / `$ref` and replace with `{"type": "object"}` in search results to reduce token cost. Only takes effect when `include_schemas=True` — ignored in summary mode. |
| `max_description_length` | `300` | Truncate tool descriptions in search results (0 = no truncation). Applies in both summary and full-schema modes. |
| Key | Default | Description |
| ------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `enabled` | `True` | Enable tool search. When `False`, all tools are listed upfront |
| `strategy` | `"bm25"` | Search ranking algorithm. `"bm25"` supports natural language; `"regex"` supports pattern matching |
| `max_results` | `5` | Maximum tools returned per search query |
| `always_visible` | See above | Tools that always appear in `list_tools`, regardless of search |
| `include_schemas` | `False` | When `False` (default, "summary mode"), search results omit `inputSchema` entirely and include a lightweight `parameters_hint` listing top-level parameter names. Set to `True` to include the full `inputSchema` in search results. Full schemas are always used when a tool is actually invoked via `call_tool`. |
| `compact_schemas` | `True` | Strip `$defs` / `$ref` and replace with `{"type": "object"}` in search results to reduce token cost. Only takes effect when `include_schemas=True` — ignored in summary mode. |
| `max_description_length` | `300` | Truncate tool descriptions in search results (0 = no truncation). Applies in both summary and full-schema modes. |
:::tip
Set `enabled: False` to revert to the traditional "show all tools at once" behavior, which some clients or workflows may prefer.
@@ -667,16 +669,16 @@ The MCP server respects Superset's full role-based access control (RBAC). Every
Each tool declares one or more required FAB permissions. The table below maps tool groups to their permission requirements:
| Tool group | Required FAB permission |
|------------|------------------------|
| `list_charts`, `get_chart_info`, `get_chart_data`, `get_chart_preview`, `generate_chart`, `update_chart` | `can_read` on `Chart` (read), `can_write` on `Chart` (mutate) |
| `list_dashboards`, `get_dashboard_info`, `generate_dashboard`, `add_chart_to_existing_dashboard` | `can_read` on `Dashboard` (read), `can_write` on `Dashboard` (mutate) |
| `list_datasets`, `get_dataset_info`, `create_virtual_dataset` | `can_read` on `Dataset` (read), `can_write` on `Dataset` (mutate) |
| `list_databases`, `get_database_info` | `can_read` on `Database` |
| `execute_sql` | `can_execute_sql_query` on `SQLLab` |
| `open_sql_lab_with_context` | `can_read` on `SQLLab` |
| `save_sql_query` | `can_write` on `SavedQuery` |
| `health_check` | None (public) |
| Tool group | Required FAB permission |
| -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `list_charts`, `get_chart_info`, `get_chart_data`, `get_chart_preview`, `generate_chart`, `update_chart` | `can_read` on `Chart` (read), `can_write` on `Chart` (mutate) |
| `list_dashboards`, `get_dashboard_info`, `generate_dashboard`, `add_chart_to_existing_dashboard` | `can_read` on `Dashboard` (read), `can_write` on `Dashboard` (mutate) |
| `list_datasets`, `get_dataset_info`, `create_virtual_dataset` | `can_read` on `Dataset` (read), `can_write` on `Dataset` (mutate) |
| `list_databases`, `get_database_info` | `can_read` on `Database` |
| `execute_sql` | `can_execute_sql_query` on `SQLLab` |
| `open_sql_lab_with_context` | `can_read` on `SQLLab` |
| `save_sql_query` | `can_write` on `SavedQuery` |
| `health_check` | None (public) |
To disable RBAC checking globally (for trusted-network deployments or testing), set:
@@ -703,13 +705,13 @@ This makes MCP activity fully auditable alongside regular Superset activity. The
Every MCP request passes through a middleware stack before reaching the tool function. The default stack (assembled in `build_middleware_list()` in `server.py`) is:
| Middleware | Purpose | Default |
|------------|---------|---------|
| `StructuredContentStripperMiddleware` | Strips `structuredContent` from responses for Claude.ai bridge compatibility | Enabled |
| `LoggingMiddleware` | Logs each tool call with user, parameters, and duration | Enabled |
| `GlobalErrorHandlerMiddleware` | Catches unhandled exceptions and sanitizes sensitive data before it reaches the client | Enabled |
| `ResponseSizeGuardMiddleware` | Estimates token count, warns at 80% of limit, blocks at limit | Enabled (configurable via `MCP_RESPONSE_SIZE_CONFIG`) |
| `ResponseCachingMiddleware` | Caches read-heavy tool responses (in-memory or Redis) | Disabled (enable via `MCP_CACHE_CONFIG`) |
| Middleware | Purpose | Default |
| ------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| `StructuredContentStripperMiddleware` | Strips `structuredContent` from responses for Claude.ai bridge compatibility | Enabled |
| `LoggingMiddleware` | Logs each tool call with user, parameters, and duration | Enabled |
| `GlobalErrorHandlerMiddleware` | Catches unhandled exceptions and sanitizes sensitive data before it reaches the client | Enabled |
| `ResponseSizeGuardMiddleware` | Estimates token count, warns at 80% of limit, blocks at limit | Enabled (configurable via `MCP_RESPONSE_SIZE_CONFIG`) |
| `ResponseCachingMiddleware` | Caches read-heavy tool responses (in-memory or Redis) | Disabled (enable via `MCP_CACHE_CONFIG`) |
Additional middleware classes (`RateLimitMiddleware`, `FieldPermissionsMiddleware`, `PrivateToolMiddleware`) are implemented in `superset/mcp_service/middleware.py` but are not added to the default pipeline. They are available for operators who want to layer them in via a custom startup path.
@@ -8,12 +8,10 @@ version: 1
## CORS
:::note
In Superset versions prior to `5.x` you have to install to install `flask-cors` with `pip install flask-cors` to enable CORS support.
:::
The following keys in `superset_config.py` can be specified to configure CORS:
- `ENABLE_CORS`: Must be set to `True` in order to enable CORS
@@ -54,11 +52,13 @@ Restart Superset for this configuration change to take effect.
There are two approaches to making dashboards publicly accessible:
**Option 1: Dataset-based access (simpler)**
1. Set `PUBLIC_ROLE_LIKE = "Public"` in `superset_config.py`
2. Grant the Public role access to the relevant datasets (Menu → Security → List Roles → Public)
3. All published dashboards using those datasets become visible to anonymous users
**Option 2: Dashboard-level access (selective control)**
1. Set `PUBLIC_ROLE_LIKE = "Public"` in `superset_config.py`
2. Add the `'DASHBOARD_RBAC': True` [Feature Flag](/admin-docs/configuration/feature-flags)
3. Edit each dashboard's properties and add the "Public" role
@@ -75,7 +75,7 @@ Now anybody can directly access the dashboard's URL. You can embed it in an ifra
width="600"
height="400"
seamless
frameBorder="0"
frameborder="0"
scrolling="no"
src="https://superset.my-domain.com/superset/dashboard/10/?standalone=1&height=400"
>
@@ -123,17 +123,17 @@ running a custom auth postback endpoint), you can add the endpoints to `WTF_CSRF
## SSH Tunneling
1. Turn on feature flag
- Change [`SSH_TUNNELING`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L489) to `True`
- If you want to add more security when establishing the tunnel we allow users to overwrite the `SSHTunnelManager` class [here](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L507)
- You can also set the [`SSH_TUNNEL_LOCAL_BIND_ADDRESS`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L508) this the host address where the tunnel will be accessible on your VPC
- Change [`SSH_TUNNELING`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L489) to `True`
- If you want to add more security when establishing the tunnel we allow users to overwrite the `SSHTunnelManager` class [here](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L507)
- You can also set the [`SSH_TUNNEL_LOCAL_BIND_ADDRESS`](https://github.com/apache/superset/blob/eb8386e3f0647df6d1bbde8b42073850796cc16f/superset/config.py#L508) this the host address where the tunnel will be accessible on your VPC
2. Create database w/ ssh tunnel enabled
- With the feature flag enabled you should now see ssh tunnel toggle.
- Click the toggle to enable SSH tunneling and add your credentials accordingly.
- Superset allows for two different types of authentication (Basic + Private Key). These credentials should come from your service provider.
- With the feature flag enabled you should now see ssh tunnel toggle.
- Click the toggle to enable SSH tunneling and add your credentials accordingly.
- Superset allows for two different types of authentication (Basic + Private Key). These credentials should come from your service provider.
3. Verify data is flowing
- Once SSH tunneling has been enabled, go to SQL Lab and write a query to verify data is properly flowing.
- Once SSH tunneling has been enabled, go to SQL Lab and write a query to verify data is properly flowing.
## Domain Sharding

Some files were not shown because too many files have changed in this diff Show More