Apache Superset is a data visualization platform with Flask/Python backend and React/TypeScript frontend.
ALWAYS run pre-commit run --all-files before pushing commits. CI will fail if pre-commit checks don't pass. This is non-negotiable.
# Stage your changes first git add . # Run pre-commit on all files pre-commit run --all-files # If there are auto-fixes, stage them and commit git add . git commit --amend # or new commit
Common pre-commit failures:
These migrations are actively happening - avoid deprecated patterns:
any types - Use proper TypeScript typestest() instead of describe() - Follow avoid nesting when testing principlespre-commit run mypy to validateBefore evaluating any code path for security issues, read SECURITY.md. It is the canonical, authoritative source for Apache Superset's security model and is referenced by both human reporters and automated scanners.
In short, the test for whether a finding is in scope is one question:
Does it let a principal perform an action the role and capability matrix in
SECURITY.mddoes not entitle them to?
If yes, it is in scope. If no, it is not.
The three trust boundaries are:
The security model assumes that operator-controlled infrastructure, including the metadata database, cache backends, message brokers, secret stores, and deployment environment, remains within the operator's trust boundary. Vulnerabilities must demonstrate a security boundary violation by an attacker who does not already control those systems.
Route-level authorization in this codebase uses one of three Flask-AppBuilder decorators depending on the route type:
@protect() for REST API routes (ModelRestApi / BaseApi)@has_access_api for legacy view routes@has_access for legacy HTML view routesObject-level authorization via security_manager.raise_for_access(...) applies to data-bearing resources: dashboards, charts, datasets and datasources, queries, database and table access, and query contexts. Other resources (annotations, tags, CSS templates, reports, RLS rules, and similar) rely on the route-level decorator plus DAO base_filters for ownership scoping; the absence of raise_for_access on these resources is by design, not a finding. Code that omits the per-object gate on a route that returns or mutates a specific data-bearing object is in scope; code that follows the correct pattern for its resource class can still contain injection, SSRF, XSS, or other classes of finding unrelated to authorization, which are evaluated separately.
The full role and capability matrix, in-scope and out-of-scope class lists, and CVE aggregation rules are in SECURITY.md. Defer to that document for any specifics.
Requirements for findings filed by automated tooling
Automated scanners (LLM-based code scanners, static analyzers, dependency tools) that file findings against this codebase must, in each finding, name:
SECURITY.md the finding believes is violated.Findings that cannot identify both should be filed as questions, not vulnerabilities. This requirement exists to ensure every reported issue is testable against the published security model and to keep speculative or pattern-match-only reports out of the triage queue.
superset/ ├── superset/ # Python backend (Flask, SQLAlchemy) │ ├── views/api/ # REST API endpoints │ ├── models/ # Database models │ └── connectors/ # Database connections ├── superset-frontend/src/ # React TypeScript frontend │ ├── components/ # Reusable components │ ├── explore/ # Chart builder │ ├── dashboard/ # Dashboard interface │ └── SqlLab/ # SQL editor ├── superset-frontend/packages/ │ └── superset-ui-core/ # UI component library (USE THIS) ├── tests/ # Python/integration tests ├── docs/ # Documentation (UPDATE FOR CHANGES) └── UPDATING.md # Breaking changes log
any types - Use proper TypeScript, reuse existing typespre-commit run mypy.rat-excludes to avoid header token overheadThe Developer Portal auto-generates MDX documentation from Storybook stories. Stories are the single source of truth.
export default { title: '...' } (inline), not const meta = ...; export default meta;Interactive${ComponentName} (e.g., InteractiveButton)args for default prop valuesargTypes at the story level (not meta level) with control types and descriptionsparameters.docs.gallery for size×style variant gridsparameters.docs.sampleChildren for components that need childrenparameters.docs.liveExample for custom live code blocksparameters.docs.staticProps for complex object props that can't be parsed inlinedocs/scripts/generate-superset-components.mjsdocs/src/components/StorybookWrapper.jsxdocs/developer_portal/components/SECURITY.mdSupersetTestCase - Base class in tests/integration_tests/base_tests.py@with_config - Config mocking decorator@with_feature_flags - Feature flag testinglogin_as(), login_as_admin() - Authentication helperscreate_dashboard(), create_slice() - Data setup utilitiessuperset-frontend/spec/helpers/testing-library.tsx - Custom render() with providerscreateWrapper() - Redux/Router/Theme wrapperselectOption() - Select component helperMagicMock() for config objects, avoid AsyncMock for synchronous code# Frontend npm run test # All tests npm run test -- filename.test.tsx # Single file # E2E Tests (Playwright - NEW) npm run playwright:test # All Playwright tests npm run playwright:ui # Interactive UI mode npm run playwright:headed # See browser during tests npx playwright test tests/auth/login.spec.ts # Single file npm run playwright:debug tests/auth/login.spec.ts # Debug specific file # E2E Tests (Cypress - DEPRECATED) cd superset-frontend/cypress-base npm run cypress-run-chrome # All Cypress tests (headless) npm run cypress-debug # Interactive Cypress UI # Backend pytest # All tests pytest tests/unit_tests/specific_test.py # Single file pytest tests/unit_tests/ # Directory # If pytest fails with database/setup issues, ask the user to run test environment setup
Quick Setup Check (run this first):
# Verify Superset is running curl -f http://localhost:8088/health || echo "❌ Setup required - see https://superset.apache.org/docs/contributing/development#working-with-llms"
If health checks fail: “It appears you aren't set up properly. Please refer to the Working with LLMs section in the development docs for setup instructions.”
Key Project Files:
superset-frontend/package.json - Frontend build scripts (npm run dev on port 9000, npm run test, npm run lint)pyproject.toml - Python tooling (ruff, mypy configs)requirements/ folder - Python dependencies (base.txt, development.txt)~Model.field instead of == False to avoid ruff E712 errors~Model.is_active instead of Model.is_active == FalseWhen creating pull requests:
.github/PULL_REQUEST_TEMPLATE.md for the latest formattype(scope): descriptionfix(dashboard): load charts correctlyfix, feat, docs, style, refactor, perf, test, choreImportant: Always reference the actual template file at .github/PULL_REQUEST_TEMPLATE.md instead of using cached content, as the template may be updated over time.
Use pre-commit hooks for quality validation:
# Install hooks pre-commit install # IMPORTANT: Stage your changes first! 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 eslint # Frontend linting
Important pre-commit usage notes:
git add . before pre-commit run to check only changed files (much faster)# Common virtual environment locations (yours may differ): source .venv/bin/activate # if using .venv source venv/bin/activate # if using venv source ~/venvs/superset/bin/activate # if using a central locationIf you get a “command not found” error, ask the user which virtual environment to activate
/api.py - REST endpoints with decorators and OpenAPI docstrings/schemas.py - Marshmallow validation schemas for OpenAPI spec/commands/ - Business logic classes with @transaction() decorators/models/ - SQLAlchemy database models/swagger/v1 from docstrings and schemassuperset/migrations/versions/YYYY-MM-DD_HH-MM_hash_description.pysuperset.migrations.shared.utils for database compatibilityLLM Note: This codebase is actively modernizing toward full TypeScript and type safety. Always run pre-commit run to validate changes. Follow the ongoing refactors section to avoid deprecated patterns.