fix(alerts): send the destination-kind descriptors to the account page#314
Merged
Merged
Conversation
#311) The Type dropdown on /account rendered zero options, so no alert destination could be created from the UI. routes/ui.py passes `destination_kinds` into the account.html context and senders/base.py:kind_descriptors documents itself as feeding "both the GET /api/alerts/destination-kinds endpoint and the account-page JSON island" — but the island only serialised destinations/rules/extensions/alert_log. So `data.destination_kinds` was undefined in accountPrefs, `destinationKinds` fell back to [], and `x-for="k in destinationKinds"` produced no <option>s. The blast radius is wider than the dropdown: selectedKind resolves to null, so kindConfigFields returns [] and the kind-specific config fields never render, targetLabel degrades to "Target", and the availability warning is suppressed. Slack/Teams/email/Jira/ServiceNow destinations were unreachable from the UI. Fix is the one missing key in the island. The page never calls the API endpoint, so the endpoint's own tests could not have caught this — the new tests assert on the rendered island and that it matches kind_descriptors() exactly, which is the contract that drifted. Verified in a browser against the dev app: all six kinds populate and selecting ServiceNow renders its instance-base-URL field. Zero console errors.
- CHANGELOG: the #311 Type-dropdown regression under Fixed, including why an endpoint test could not have caught it. - .claude/rules/frontend.md: the island is a hand-maintained contract — adding a key to the route context is only half the change. A context key the template never serialises reaches nothing, and the component's `|| []` fallback hides it with no error and a green suite. Assert on the rendered island, not the API.
Contributor
There was a problem hiding this comment.
IcebergAutoReview
Verdict: approve
The one-key JSON-island fix correctly restores destination descriptors to the account-page component. It uses the existing sender registry as the source of truth and includes focused rendered-response regression coverage. No blocking correctness or security issues found.
Findings
- No blocking findings.
Validation
- Inspected the complete main...HEAD diff and verified HEAD is directly based on local main.
- Traced destination descriptors through sender registry → UI route context → Jinja JSON island → Alpine component.
- Attempted focused pytest file; unavailable locally because the read-only checkout prevented uv from creating
.venv, while system pytest lackedpytest_asyncio. Current-head CI is green.
Residual risks / optional notes
- Minor documentation drift: the account.js header comment still lists only the four original island fields, and new documentation cites #311 rather than the fixing issue #313. Neither affects runtime behavior.
Automated review by Codex 178b3d3f765a using IcebergAutoReview.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #313
The bug
The Type dropdown on
/account→ New destination renders zero options, sono alert destination can be created from the UI. Shipped with #311; present on
main.Cause
routes/ui.pypassesdestination_kindsinto the account-page context, andapp/senders/base.py:kind_descriptorsdocuments itself as feeding "both theGET /api/alerts/destination-kindsendpoint and the account-page JSON island".The
account-dataisland only serialiseddestinations/rules/extensions/alert_log.So
data.destination_kindswasundefined,destinationKindsfell back to[], andx-for="k in destinationKinds"produced no<option>s.Blast radius
Wider than the dropdown —
selectedKindresolves tonull, sokindConfigFieldsreturns
[](no kind-specific config fields render),targetLabeldegrades to a generic"Target", and the availability warning is suppressed. Slack / Teams / email / Jira /
ServiceNow destinations were unreachable from the UI. The JSON API is unaffected.
Fix
One missing key in the island literal.
Why the existing tests passed
The page reads the island; it never calls the API endpoint. The endpoint's own tests
therefore prove nothing about it. The new tests assert on the rendered island and that
it matches
kind_descriptors()exactly — the contract that drifted.Verification
tests/test_account_destination_kinds.py; confirmed failing againstthe pre-fix template and passing after.
ruff check/ruff format --checkclean.(
Webhook, Slack, Microsoft Teams, Email (SMTP), Jira, ServiceNow) and selectingServiceNow renders its instance-base-URL field. Zero console errors.
Docs
CHANGELOG.mdunder Fixed..claude/rules/frontend.md: the island is a hand-maintained contract — adding a key tothe route context is only half the change, and the component's
|| []fallback hides theomission with no error and a green suite.
🤖 Generated with Claude Code