Skip to content

fix: drop avatarUrl from Maple webhook create payload#318

Merged
Makisuo merged 1 commit intomainfrom
fix/maple-avatar-url-validation
Apr 26, 2026
Merged

fix: drop avatarUrl from Maple webhook create payload#318
Makisuo merged 1 commit intomainfrom
fix/maple-avatar-url-validation

Conversation

@Makisuo
Copy link
Copy Markdown
Collaborator

@Makisuo Makisuo commented Apr 26, 2026

Problem

Creating a Maple webhook from /{org}/settings/integrations/maple fails with:

```
{
"_tag": "Die",
"defect": "Avatar URL must point to an image\n at [\"avatarUrl\"]"
}
```

Root cause

The `channelWebhook.create` RPC validates `avatarUrl` by issuing an HTTP HEAD against the URL and asserting the response `Content-Type` starts with `image/` (packages/schema/src/avatar-url.ts:50). Brandfetch's CDN now redirects direct hits with `HTTP 302 → docs.brandfetch.com/.../hotlinking` (`text/html`), so the validator rejects the URL.

Fix

Drop `avatarUrl` from the create payload in maple-section.tsx. Two reasons this is safe:

  1. The bot identity that actually appears on posted messages is resolved by `IntegrationBotService.getOrCreateWebhookBotUser("maple", ...)`, which reads `WEBHOOK_BOT_CONFIGS.maple` for the avatar — unaffected by the create payload.
  2. The webhook record's `avatarUrl` field is only used as a fallback in the channel integrations settings list (one usage in routes/.../channels/$channelId/settings/integrations.tsx:262); the empty-state UI works fine.

Notes

  • The Brandfetch URL is still used for the inline icon in the section's own UI (rendered directly in <img>, no validation). If browsers also start blocking those, that's a separate UI fix.
  • The same hotlinking issue likely affects the existing OpenStatus and Railway integrations on a fresh create — left out of scope here since the original report is Maple-specific. Worth a follow-up sweep.

Test plan

  • Navigate to /{org}/settings/integrations/maple → click Add Channel → pick a channel → Connect Maple. Expect: webhook created, copy-URL panel appears, no "Avatar URL" error in the toast or console.
  • Post a Maple alert to the new webhook URL → confirm the message renders with the Maple bot identity (avatar + name from `WEBHOOK_BOT_CONFIGS.maple`).

🤖 Generated with Claude Code

The channelWebhook.create RPC validates avatarUrl by HEAD-fetching the URL
and asserting Content-Type starts with image/. Brandfetch's CDN now serves
a 302 redirect to its hotlinking guidelines (text/html) on direct hits, so
passing the Brandfetch icon URL fails validation:

  defect: "Avatar URL must point to an image\n  at [\"avatarUrl\"]"

The webhook record's avatarUrl is only used as a fallback in the channel
integrations settings list. The bot identity that actually appears on
posted messages is resolved via WEBHOOK_BOT_CONFIGS.maple by
IntegrationBotService.getOrCreateWebhookBotUser, which is unaffected by
the create payload. Dropping the field unblocks creation without changing
the rendered embed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hazel-docs Ready Ready Preview, Comment Apr 26, 2026 0:11am

@claude
Copy link
Copy Markdown

claude Bot commented Apr 26, 2026

Claude finished @Makisuo's task —— View job


PR Review Complete ✅

I've completed a comprehensive review of this pull request. Here's my analysis:

Todo List:

  • Read the modified file and understand the change
  • Examine avatar URL validation logic in schema
  • Review webhook bot configuration system
  • Check fallback usage in channel settings
  • Analyze potential security and performance implications
  • Assess need for test coverage
  • Provide comprehensive review feedback

Review Summary

This is a well-reasoned and safe fix for a specific validation issue. The change removes avatarUrl: mapleLogoUrl from the webhook creation payload in maple-section.tsx:67.

Code Quality: ✅ Excellent

  • Clean, minimal change: Single line removal with clear intent
  • Follows existing patterns: Consistent with other integration sections
  • Well-documented: Excellent PR description explaining the problem and solution

Root Cause Analysis: ✅ Correct

The issue stems from Brandfetch CDN changes:

  • Problem: packages/schema/src/avatar-url.ts:50-53 validates avatar URLs by checking Content-Type starts with image/
  • New behavior: Brandfetch now returns HTTP 302 → text/html for direct hits, failing validation
  • Solution: Remove avatarUrl from creation payload since bot identity comes from WEBHOOK_BOT_CONFIGS.maple

Architecture Understanding: ✅ Solid

The fix correctly identifies the separation of concerns:

  1. Webhook creation: Uses payload avatarUrl (now removed)
  2. Message rendering: Uses WEBHOOK_BOT_CONFIGS.maple.avatarUrl via IntegrationBotService.getOrCreateWebhookBotUser()
  3. UI fallback: Uses webhook record's avatarUrl field only in channel settings list (integrations.tsx:262)

Security: ✅ No concerns

  • Removes potentially problematic external URL validation
  • Bot identity still comes from trusted WEBHOOK_BOT_CONFIGS
  • No exposure of sensitive data

Performance: ✅ Improvement

  • Benefit: Eliminates HTTP HEAD request during webhook creation
  • No regression: Bot avatar still loads properly in messages
  • Brandfetch URLs: Still used for UI icons (rendered directly, no validation)

Test Coverage: ⚠️ Gap identified

Missing coverage: No automated tests found for Maple webhook creation flow. Consider adding:

// Example test case
describe('Maple webhook creation', () => {
  it('should create webhook without avatarUrl validation', async () => {
    // Test that creation succeeds without avatarUrl in payload
  })
})

Potential Issues: ✅ None identified

  • Consistency: OpenStatus and Railway integrations likely have the same Brandfetch hotlinking issue (noted in PR for follow-up)
  • UI degradation: Minimal - fallback in channel settings works fine with empty avatarUrl
  • Schema compatibility: RPC schema allows optional avatarUrl, so removal is safe

Recommendations:

  1. ✅ Approve and merge - This is a correct fix
  2. Follow-up: Address similar issues in OpenStatus/Railway integrations as mentioned
  3. Testing: Consider adding integration tests for webhook creation flows
  4. Monitoring: Watch for similar Brandfetch hotlinking issues in other components

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 26, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
hazel-app 4f525b8 Commit Preview URL

Branch Preview URL
Apr 26 2026, 12:12 PM

@Makisuo Makisuo merged commit 1a3a0c6 into main Apr 26, 2026
6 of 9 checks passed
@Makisuo Makisuo deleted the fix/maple-avatar-url-validation branch April 26, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant