Skip to content

fix(reports): require a Slack channel id in report recipients - #42850

Open
AryaKetanShCt wants to merge 5 commits into
apache:masterfrom
AryaKetanShCt:fix/slack-recipient-requires-channel-id
Open

fix(reports): require a Slack channel id in report recipients#42850
AryaKetanShCt wants to merge 5 commits into
apache:masterfrom
AryaKetanShCt:fix/slack-recipient-requires-channel-id

Conversation

@AryaKetanShCt

@AryaKetanShCt AryaKetanShCt commented Aug 6, 2026

Copy link
Copy Markdown

SUMMARY

A report or alert saved with a Slack channel name rather than a channel id validates cleanly, runs on schedule, and then never delivers.

ReportRecipientConfigJSONSchema.target is a bare fields.String(), and the only validator on ReportRecipientSchema begins:

if data.get("type") != ReportRecipientType.EMAIL.value:
    return

So email addresses are regex-checked and Slack targets are not checked at all. POST /api/v1/report/ accepts {"type": "SlackV2", "recipient_config_json": {"target": "data-alerts"}} and returns 201.

But SlackV2Notification.send() passes the target straight to files_upload_v2(channel=...), which requires a channel id and answers invalid_arguments for a name. The only signal is an error notification to the report's owner, long after the alert was created, and only if someone reads it.

The UI is unaffected because its picker submits ids from /api/v1/report/slack_channels/. The gap is the API.

This is not theoretical. On one instance 46 recipients had accumulated a channel name, 21 of them on active alerts, the oldest from 2023. Of the 19 distinct names, 5 still matched a live channel, 2 matched archived ones and the rest matched nothing at all, so most could not be repaired even by hand and 15 alerts had to be switched off.

FIX

Validate SlackV2 targets the way Email targets are already validated: every comma, semicolon or whitespace separated part must look like a channel id (^[CGD][A-Z0-9]{6,}$). The error names the offending part and says where to find the id.

The deprecated Slack v1 type is deliberately left alone. v1 sends with files_upload / chat_postMessage, both of which resolve a channel name, and slack.py notes that existing v1 recipients are auto-upgraded to SlackV2 on first send via update_report_schedule_slack_v2. Rejecting names for v1 would break that upgrade path and the v1 contract, and it would fail existing tests that create v1 recipients with names. Since v1 is removed next major, the validation applies only to the type that survives.

The message is deliberately explicit about why, because "invalid channel" reads like a typo when the real cause is that names work with Slack's older chat.postMessage and not with the upload API used for attachments.

TESTING INSTRUCTIONS

Six unit tests in tests/unit_tests/reports/schemas_test.py, following the existing email cases: a single id and multiple ids are accepted; a name, a mixed id-and-name target, and an empty target are rejected; and legacy Slack with a channel name is asserted accepted, pinning the carve-out. The mixed case asserts the message names the bad part and not the good one.

Verified against the schema loaded in a running instance:

type target result
SlackV2 C08CSCSDCSY accepted
SlackV2 data-alerts rejected
SlackV2 C08CSCSDCSY,data-alerts rejected
Slack #general accepted
Slack channel accepted
Email a@b.com accepted

Manually: POST /api/v1/report/ with a SlackV2 recipient whose target is a channel name now returns 400 instead of 201.

ADDITIONAL INFORMATION

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

@dosubot dosubot Bot added alert-reports Namespace | Anything related to the Alert & Reports feature change:backend Requires changing the backend labels Aug 6, 2026
@bito-code-review

bito-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #9bc9d3

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 604adaf..6e87dcf
    • superset/reports/schemas.py
    • tests/unit_tests/reports/schemas_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers a full AI review.

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

  • /resume - Resumes automatic reviews.

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

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

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

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/reports/schemas.py Outdated
Comment on lines +183 to +187
if data.get("type") not in (
ReportRecipientType.SLACK.value,
ReportRecipientType.SLACKV2.value,
):
return

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: The new validator rejects existing Slack V1 targets such as #general and channel, so the unchanged schema and API tests now fail and existing clients can no longer create or update legacy Slack recipients. This conflicts with the legacy notification path, which still accepts channel names and resolves them during the Slack V1-to-V2 upgrade. Either limit this validation to SlackV2, or migrate/resolve legacy names before applying the ID-only validation and update the affected tests and API contract together. [api mismatch]

Severity Level: Major ⚠️
- ❌ Legacy Slack API creation rejects previously supported channel names.
- ❌ Existing clients cannot update name-based Slack recipients.
- ⚠️ Runtime migration remains unreachable for newly submitted names.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/reports/schemas.py
**Line:** 183:187
**Comment:**
	*Api Mismatch: The new validator rejects existing Slack V1 targets such as `#general` and `channel`, so the unchanged schema and API tests now fail and existing clients can no longer create or update legacy Slack recipients. This conflicts with the legacy notification path, which still accepts channel names and resolves them during the Slack V1-to-V2 upgrade. Either limit this validation to `SlackV2`, or migrate/resolve legacy names before applying the ID-only validation and update the affected tests and API contract together.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch, and correct on all three counts. Fixed in the latest commits by limiting the validation to SlackV2.

Verifying before changing it, the deprecated v1 path really does accept names:

  • SlackNotification._get_channel() returns the raw target and sends via files_upload(channels=...) / chat_postMessage(channel=...), both of which resolve a channel name.
  • slack.py says so itself: "existing v1 recipients are auto-upgraded to SlackV2 on first send via update_report_schedule_slack_v2". Rejecting names at creation would have blocked the input that upgrade path exists to convert.

And it would have broken existing tests, which I should have run against before opening:

  • tests/unit_tests/reports/schemas_test.py::test_report_recipient_schema_slack_skips_email_validation loads {"type": "Slack", "target": "#general"} and asserts success.
  • tests/integration_tests/reports/api_tests.py creates ReportRecipientType.SLACK with {"target": "channel"} in three places.

The validator now returns early for anything that is not SlackV2, with a comment recording why. My test asserting v1 rejection is replaced by one asserting v1 acceptance, so the carve-out is pinned rather than incidental.

Re-checked against the real schema, loaded in a running instance:

type target result
SlackV2 C08CSCSDCSY accepted
SlackV2 data-alerts rejected
SlackV2 C08CSCSDCSY,data-alerts rejected
Slack #general accepted
Slack channel accepted
Slack C08CSCSDCSY accepted
Email a@b.com accepted

This also lines up with v1 being removed next major: the validation applies only to the type that survives, and v1 recipients keep flowing through the auto-upgrade untouched.

@bito-code-review

Copy link
Copy Markdown
Contributor

The flagged issue is correct. The new validator in superset/reports/schemas.py enforces Slack channel IDs for both Slack and SlackV2 types, which breaks legacy Slack recipients that rely on channel names. To resolve this, the validation should be restricted to SlackV2 or updated to handle legacy name resolution.

To implement this fix, update the validate_slack_recipients method to only apply the ID-only validation when the type is SlackV2:

    @validates_schema
    def validate_slack_recipients(self, data: dict[str, Any], **kwargs: Any) -> None:
        if data.get("type") != ReportRecipientType.SLACKV2.value:
            return

        target = ((data.get("recipient_config_json") or {}).get("target") or "").strip()
        # ... (rest of the validation logic)

Would you like me to fetch all other comments on this PR to validate and implement fixes for them as well?

superset/reports/schemas.py

@validates_schema
    def validate_slack_recipients(self, data: dict[str, Any], **kwargs: Any) -> None:
        if data.get("type") != ReportRecipientType.SLACKV2.value:
            return

        target = ((data.get("recipient_config_json") or {}).get("target") or "").strip()

@bito-code-review

bito-code-review Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #fa5f18

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 6e87dcf..c0801ab
    • superset/reports/schemas.py
    • tests/unit_tests/reports/schemas_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers a full AI review.

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

  • /resume - Resumes automatic reviews.

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

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

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

Documentation & Help

AI Code Review powered by Bito Logo

@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 33.33333% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.73%. Comparing base (ba09f39) to head (c0801ab).
⚠️ Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
superset/reports/schemas.py 33.33% 7 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42850      +/-   ##
==========================================
- Coverage   65.73%   65.73%   -0.01%     
==========================================
  Files        2843     2843              
  Lines      162659   162678      +19     
  Branches    37239    37242       +3     
==========================================
+ Hits       106926   106929       +3     
- Misses      53641    53655      +14     
- Partials     2092     2094       +2     
Flag Coverage Δ
hive 38.00% <25.00%> (-0.01%) ⬇️
mysql 57.79% <33.33%> (-0.01%) ⬇️
postgres 57.84% <33.33%> (-0.01%) ⬇️
presto 39.92% <25.00%> (-0.01%) ⬇️
python 59.20% <33.33%> (-0.02%) ⬇️
sqlite 57.47% <33.33%> (-0.01%) ⬇️
unit 100.00% <ø> (ø)

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

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

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

@AryaKetanShCt

Copy link
Copy Markdown
Author

Addressed the coverage report as well.

Patch coverage was 33% because the flags Codecov aggregates (python, postgres, mysql, …) come from the integration suite, and my tests were unit-only — the unit flag shows <ø>, so none of the new lines were attributed. The validator was tested, just not by anything Codecov was measuring.

Added test_create_report_schedule_slack_v2_requires_channel_id to tests/integration_tests/reports/api_tests.py, which drives the real POST /api/v1/report/ path:

  • a channel name → 400, and the message names the offending value
  • a mixed id,name target → 400, naming only the bad part
  • an empty target → 400
  • two channel ids → 201
  • deprecated Slack v1 with a channel name → 201, pinning the carve-out at the API layer as well as the schema layer

That last case is worth having in the integration suite specifically, since three existing tests in this file already create v1 recipients with {"target": "channel"} and must keep passing.

The unit tests stay as they are — they cover the branch logic cheaply; the integration test covers the wiring and the coverage flags.

@netlify

netlify Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

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

QR Code

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

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

@bito-code-review

bito-code-review Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #9d490b

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: c0801ab..9100f62
    • tests/integration_tests/reports/api_tests.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

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

  • /review - Manually triggers a full AI review.

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

  • /resume - Resumes automatic reviews.

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

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

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

Documentation & Help

AI Code Review powered by Bito Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

alert-reports Namespace | Anything related to the Alert & Reports feature change:backend Requires changing the backend size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant