feat(tools): added smtp, sendgrid, mailgun, linkedin, fixed permissions in context menu#2133
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile OverviewGreptile SummaryThis PR introduces four major tool integrations and fixes critical permission vulnerabilities in the workflow management system. The new integrations include LinkedIn for social media posting and profile access, SendGrid for email marketing with comprehensive template and contact management, Mailgun for transactional email with domain operations, and SMTP for generic email server connectivity. These additions significantly expand the platform's communication capabilities beyond the existing Gmail integration. The PR also addresses security issues in the context menu permissions system by adding proper authorization checks to workflow and folder operations. Components now verify user edit permissions before allowing rename, duplicate, export, and delete operations, preventing unauthorized access to sensitive workspace content. The implementation follows established architectural patterns with proper OAuth integration for LinkedIn, API key-based authentication for email services, and consistent tool configuration structures. Each integration includes comprehensive documentation, proper TypeScript definitions, and follows the project's modular organization with dedicated directories for each service provider. Important Files Changed
Confidence score: 2/5
|
| cc?: string | ||
| bcc?: string | ||
| replyTo?: string | ||
| attachments?: any[] |
There was a problem hiding this comment.
style: any[] type should be replaced with a more specific type for type safety
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/smtp/types.ts
Line: 24:24
Comment:
**style:** `any[]` type should be replaced with a more specific type for type safety
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| @@ -0,0 +1,11 @@ | |||
| // Message Operations | |||
There was a problem hiding this comment.
style: Comment is misleading - this exports domain and mailing list operations in addition to message operations
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/mailgun/index.ts
Line: 1:1
Comment:
**style:** Comment is misleading - this exports domain and mailing list operations in addition to message operations
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| body: (params) => { | ||
| return { | ||
| body: JSON.stringify({ | ||
| query: params.query, | ||
| }), | ||
| } | ||
| }, |
There was a problem hiding this comment.
logic: The body function should return the JSON string directly, not an object with a body property. Based on the established pattern in other tools, this should be JSON.stringify({ query: params.query })
| body: (params) => { | |
| return { | |
| body: JSON.stringify({ | |
| query: params.query, | |
| }), | |
| } | |
| }, | |
| body: (params) => JSON.stringify({ | |
| query: params.query, | |
| }), |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/search_contacts.ts
Line: 33:39
Comment:
**logic:** The body function should return the JSON string directly, not an object with a body property. Based on the established pattern in other tools, this should be `JSON.stringify({ query: params.query })`
```suggestion
body: (params) => JSON.stringify({
query: params.query,
}),
```
How can I resolve this? If you propose a fix, please make it concise.| body: (params) => { | ||
| return { | ||
| body: JSON.stringify({ | ||
| name: params.name, | ||
| }), | ||
| } | ||
| }, |
There was a problem hiding this comment.
logic: The body function incorrectly wraps the JSON payload in a body object. The fetch API expects the body to be directly returned as a string or object, not wrapped.
| body: (params) => { | |
| return { | |
| body: JSON.stringify({ | |
| name: params.name, | |
| }), | |
| } | |
| }, | |
| body: (params) => { | |
| return JSON.stringify({ | |
| name: params.name, | |
| }) | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/create_list.ts
Line: 32:38
Comment:
**logic:** The body function incorrectly wraps the JSON payload in a `body` object. The fetch API expects the body to be directly returned as a string or object, not wrapped.
```suggestion
body: (params) => {
return JSON.stringify({
name: params.name,
})
}
```
How can I resolve this? If you propose a fix, please make it concise.| body: (params) => { | ||
| return { | ||
| body: JSON.stringify({ | ||
| name: params.name, | ||
| generation: params.generation || 'dynamic', | ||
| }), | ||
| } | ||
| }, |
There was a problem hiding this comment.
logic: The body function should return the object directly, not wrapped in another body property. This structure will likely cause API request failures.
| body: (params) => { | |
| return { | |
| body: JSON.stringify({ | |
| name: params.name, | |
| generation: params.generation || 'dynamic', | |
| }), | |
| } | |
| }, | |
| body: (params) => ({ | |
| name: params.name, | |
| generation: params.generation || 'dynamic', | |
| }), |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/create_template.ts
Line: 38:45
Comment:
**logic:** The body function should return the object directly, not wrapped in another body property. This structure will likely cause API request failures.
```suggestion
body: (params) => ({
name: params.name,
generation: params.generation || 'dynamic',
}),
```
How can I resolve this? If you propose a fix, please make it concise.| id: profile.sub, | ||
| name: profile.name || 'LinkedIn User', | ||
| email: profile.email || `${profile.sub}@linkedin.user`, | ||
| emailVerified: profile.email_verified || true, |
There was a problem hiding this comment.
logic: Defaulting email_verified to true when profile.email_verified is falsy could create security issues with unverified email addresses.
| emailVerified: profile.email_verified || true, | |
| emailVerified: profile.email_verified ?? false, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/lib/auth.ts
Line: 1626:1626
Comment:
**logic:** Defaulting `email_verified` to `true` when profile.email_verified is falsy could create security issues with unverified email addresses.
```suggestion
emailVerified: profile.email_verified ?? false,
```
How can I resolve this? If you propose a fix, please make it concise.| 'Content-Type': 'application/json', | ||
| }), | ||
| body: (params) => { | ||
| const personalizations: any = { |
There was a problem hiding this comment.
style: Using any type reduces type safety. Consider defining a proper interface for personalizations structure.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/send_mail.ts
Line: 111:111
Comment:
**style:** Using `any` type reduces type safety. Consider defining a proper interface for personalizations structure.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| } | ||
| } | ||
|
|
||
| const mailBody: any = { |
There was a problem hiding this comment.
style: Another any type usage. Consider defining a SendGridMailBody interface for better type safety.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/send_mail.ts
Line: 139:139
Comment:
**style:** Another `any` type usage. Consider defining a SendGridMailBody interface for better type safety.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| const contact: any = { | ||
| email: params.email, | ||
| } | ||
|
|
||
| if (params.firstName) contact.first_name = params.firstName | ||
| if (params.lastName) contact.last_name = params.lastName | ||
|
|
||
| if (params.customFields) { | ||
| const customFields = | ||
| typeof params.customFields === 'string' | ||
| ? JSON.parse(params.customFields) | ||
| : params.customFields | ||
| Object.assign(contact, customFields) | ||
| } | ||
|
|
||
| const body: any = { |
There was a problem hiding this comment.
style: Consider creating proper TypeScript interfaces instead of using any types
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/add_contact.ts
Line: 58:73
Comment:
**style:** Consider creating proper TypeScript interfaces instead of using `any` types
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| email: params?.email || '', | ||
| firstName: params?.firstName, | ||
| lastName: params?.lastName, |
There was a problem hiding this comment.
style: Unnecessary optional chaining since params is always provided in this context
| email: params?.email || '', | |
| firstName: params?.firstName, | |
| lastName: params?.lastName, | |
| email: params.email, | |
| firstName: params.firstName, | |
| lastName: params.lastName, |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/add_contact.ts
Line: 97:99
Comment:
**style:** Unnecessary optional chaining since params is always provided in this context
```suggestion
email: params.email,
firstName: params.firstName,
lastName: params.lastName,
```
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| return { | ||
| success: true, | ||
| output: { | ||
| success: true, |
There was a problem hiding this comment.
style: Redundant success: true field since the parent object already has success: true at line 36
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/mailgun/list_domains.ts
Line: 38:38
Comment:
**style:** Redundant `success: true` field since the parent object already has `success: true` at line 36
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| return { | ||
| success: true, | ||
| output: { | ||
| success: true, |
There was a problem hiding this comment.
style: Redundant success: true field since it's already present at line 67
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/mailgun/list_messages.ts
Line: 69:69
Comment:
**style:** Redundant `success: true` field since it's already present at line 67
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| formData.append('access_level', params.accessLevel) | ||
| } | ||
|
|
||
| return { body: formData } |
There was a problem hiding this comment.
logic: The body function should return the FormData directly, not wrapped in an object with a body property. Based on the framework patterns, this should be return formData
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/mailgun/create_mailing_list.ts
Line: 66:66
Comment:
**logic:** The body function should return the FormData directly, not wrapped in an object with a `body` property. Based on the framework patterns, this should be `return formData`
How can I resolve this? If you propose a fix, please make it concise.| formData.append('subscribed', params.subscribed ? 'yes' : 'no') | ||
| } | ||
|
|
||
| return { body: formData } |
There was a problem hiding this comment.
logic: The body function should return the FormData directly, not wrapped in a body object. Based on the established pattern in other tools, this should return formData directly.
| return { body: formData } | |
| return formData |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/mailgun/add_list_member.ts
Line: 69:69
Comment:
**logic:** The body function should return the FormData directly, not wrapped in a `body` object. Based on the established pattern in other tools, this should return `formData` directly.
```suggestion
return formData
```
How can I resolve this? If you propose a fix, please make it concise.| outputs: { | ||
| success: { type: 'boolean', description: 'Operation success status' }, | ||
| postId: { type: 'string', description: 'Created post ID' }, | ||
| profile: { type: 'json', description: 'LinkedIn profile information' }, | ||
| error: { type: 'string', description: 'Error message if operation failed' }, | ||
| }, |
There was a problem hiding this comment.
style: The output schema includes both post and profile fields, but only one set will be relevant per operation. Consider documenting which outputs apply to which operations or creating operation-specific output types. Should the output schema be more specific about which fields are populated for each operation type?
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/blocks/blocks/linkedin.ts
Line: 106:111
Comment:
**style:** The output schema includes both post and profile fields, but only one set will be relevant per operation. Consider documenting which outputs apply to which operations or creating operation-specific output types. Should the output schema be more specific about which fields are populated for each operation type?
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| body.plain_content = params.plainContent | ||
| } | ||
|
|
||
| return { body: JSON.stringify(body) } |
There was a problem hiding this comment.
logic: The body function should return the JSON string directly, not wrapped in a body property. This structure will cause API request failures.
| return { body: JSON.stringify(body) } | |
| return JSON.stringify(body) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/create_template_version.ts
Line: 80:80
Comment:
**logic:** The body function should return the JSON string directly, not wrapped in a body property. This structure will cause API request failures.
```suggestion
return JSON.stringify(body)
```
How can I resolve this? If you propose a fix, please make it concise.| const body: any = { | ||
| name: params.name, | ||
| subject: params.subject, | ||
| active: params.active !== undefined ? params.active : 1, |
There was a problem hiding this comment.
logic: Inconsistent boolean handling - params.active is boolean but defaulting to number 1. Should use boolean true/false consistently throughout. Should the SendGrid API accept boolean values or does it specifically require 1/0 integers?
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/create_template_version.ts
Line: 69:69
Comment:
**logic:** Inconsistent boolean handling - params.active is boolean but defaulting to number 1. Should use boolean true/false consistently throughout. Should the SendGrid API accept boolean values or does it specifically require 1/0 integers?
How can I resolve this? If you propose a fix, please make it concise.| body.list_ids = params.listIds.split(',').map((id) => id.trim()) | ||
| } | ||
|
|
||
| return { body: JSON.stringify(body) } |
There was a problem hiding this comment.
logic: The body function should return the JSON string directly, not wrapped in a body object. Based on the established pattern in other tools like Gmail, this should be return JSON.stringify(body)
| return { body: JSON.stringify(body) } | |
| return JSON.stringify(body) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/add_contact.ts
Line: 81:81
Comment:
**logic:** The body function should return the JSON string directly, not wrapped in a `body` object. Based on the established pattern in other tools like Gmail, this should be `return JSON.stringify(body)`
```suggestion
return JSON.stringify(body)
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
incorrect, stripe & mailgun follow the same pattern
| apiKey: { | ||
| type: 'string', | ||
| required: true, | ||
| visibility: 'user-only', |
There was a problem hiding this comment.
style: API key should be marked as hidden visibility instead of user-only to follow security best practices established in other tools like Gmail
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/sendgrid/add_contact.ts
Line: 14:14
Comment:
**style:** API key should be marked as `hidden` visibility instead of `user-only` to follow security best practices established in other tools like Gmail
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
incorrect, it is correctly marked as user-only since the user can only provide it, not injected by the LLM at runtime
| export interface LinkedInProfile { | ||
| sub: string | ||
| name: string | ||
| given_name: string | ||
| family_name: string | ||
| email?: string | ||
| picture?: string | ||
| email_verified?: boolean | ||
| } | ||
|
|
||
| export interface LinkedInPost { | ||
| author: string // URN format: urn:li:person:abc123 | ||
| lifecycleState: 'PUBLISHED' | ||
| specificContent: { | ||
| 'com.linkedin.ugc.ShareContent': { | ||
| shareCommentary: { | ||
| text: string | ||
| } | ||
| shareMediaCategory: 'NONE' | 'ARTICLE' | 'IMAGE' | ||
| media?: Array<{ | ||
| status: 'READY' | ||
| description: { | ||
| text: string | ||
| } | ||
| media: string // URN format | ||
| title: { | ||
| text: string | ||
| } | ||
| }> | ||
| } | ||
| } | ||
| visibility: { | ||
| 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' | 'CONNECTIONS' | ||
| } | ||
| } | ||
|
|
||
| export type LinkedInResponse = { | ||
| success: boolean | ||
| output: { | ||
| postId?: string | ||
| profile?: { | ||
| id: string | ||
| name: string | ||
| email?: string | ||
| picture?: string | ||
| } | ||
| } | ||
| error?: string | ||
| } |
There was a problem hiding this comment.
style: Missing TSDoc documentation for all exported interfaces and types. Project coding standards require TSDoc comments for public interfaces.
| export interface LinkedInProfile { | |
| sub: string | |
| name: string | |
| given_name: string | |
| family_name: string | |
| email?: string | |
| picture?: string | |
| email_verified?: boolean | |
| } | |
| export interface LinkedInPost { | |
| author: string // URN format: urn:li:person:abc123 | |
| lifecycleState: 'PUBLISHED' | |
| specificContent: { | |
| 'com.linkedin.ugc.ShareContent': { | |
| shareCommentary: { | |
| text: string | |
| } | |
| shareMediaCategory: 'NONE' | 'ARTICLE' | 'IMAGE' | |
| media?: Array<{ | |
| status: 'READY' | |
| description: { | |
| text: string | |
| } | |
| media: string // URN format | |
| title: { | |
| text: string | |
| } | |
| }> | |
| } | |
| } | |
| visibility: { | |
| 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' | 'CONNECTIONS' | |
| } | |
| } | |
| export type LinkedInResponse = { | |
| success: boolean | |
| output: { | |
| postId?: string | |
| profile?: { | |
| id: string | |
| name: string | |
| email?: string | |
| picture?: string | |
| } | |
| } | |
| error?: string | |
| } | |
| /** | |
| * LinkedIn user profile information from OAuth authentication. | |
| */ | |
| export interface LinkedInProfile { | |
| sub: string | |
| name: string | |
| given_name: string | |
| family_name: string | |
| email?: string | |
| picture?: string | |
| email_verified?: boolean | |
| } | |
| /** | |
| * LinkedIn post structure for UGC (User Generated Content) API. | |
| * Used when creating posts via LinkedIn's sharing API. | |
| */ | |
| export interface LinkedInPost { | |
| author: string // URN format: urn:li:person:abc123 | |
| lifecycleState: 'PUBLISHED' | |
| specificContent: { | |
| 'com.linkedin.ugc.ShareContent': { | |
| shareCommentary: { | |
| text: string | |
| } | |
| shareMediaCategory: 'NONE' | 'ARTICLE' | 'IMAGE' | |
| media?: Array<{ | |
| status: 'READY' | |
| description: { | |
| text: string | |
| } | |
| media: string // URN format | |
| title: { | |
| text: string | |
| } | |
| }> | |
| } | |
| } | |
| visibility: { | |
| 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' | 'CONNECTIONS' | |
| } | |
| } | |
| /** | |
| * Response format for LinkedIn API operations. | |
| * Contains operation result and any error information. | |
| */ | |
| export type LinkedInResponse = { | |
| success: boolean | |
| output: { | |
| postId?: string | |
| profile?: { | |
| id: string | |
| name: string | |
| email?: string | |
| picture?: string | |
| } | |
| } | |
| error?: string | |
| } |
Context Used: Context from dashboard - .cursorrules (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/tools/linkedin/types.ts
Line: 1:49
Comment:
**style:** Missing TSDoc documentation for all exported interfaces and types. Project coding standards require TSDoc comments for public interfaces.
```suggestion
/**
* LinkedIn user profile information from OAuth authentication.
*/
export interface LinkedInProfile {
sub: string
name: string
given_name: string
family_name: string
email?: string
picture?: string
email_verified?: boolean
}
/**
* LinkedIn post structure for UGC (User Generated Content) API.
* Used when creating posts via LinkedIn's sharing API.
*/
export interface LinkedInPost {
author: string // URN format: urn:li:person:abc123
lifecycleState: 'PUBLISHED'
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text: string
}
shareMediaCategory: 'NONE' | 'ARTICLE' | 'IMAGE'
media?: Array<{
status: 'READY'
description: {
text: string
}
media: string // URN format
title: {
text: string
}
}>
}
}
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' | 'CONNECTIONS'
}
}
/**
* Response format for LinkedIn API operations.
* Contains operation result and any error information.
*/
export type LinkedInResponse = {
success: boolean
output: {
postId?: string
profile?: {
id: string
name: string
email?: string
picture?: string
}
}
error?: string
}
```
**Context Used:** Context from `dashboard` - .cursorrules ([source](https://app.greptile.com/review/custom-context?memory=493a526c-5c62-4263-a434-6a91d855febe))
How can I resolve this? If you propose a fix, please make it concise.… sendgrid, linkedin, more tools (#2148) * feat(tools): added smtp, sendgrid, mailgun, linkedin, fixed permissions in context menu (#2133) * feat(tools): added twilio sendgrid integration * feat(tools): added smtp, sendgrid, mailgun, fixed permissions in context menu * added top level mocks for sporadically failing tests * incr type safety * fix(team-plans): track departed member usage so value not lost (#2118) * fix(team-plans): track departed member usage so value not lost * reset usage to 0 when they leave team * prep merge with stagig * regen migrations * fix org invite + ws selection' --------- Co-authored-by: Waleed <walif6@gmail.com> * feat(i18n): update translations (#2134) Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com> * feat(creators): add verification for creators (#2135) * feat(tools): added apify block/tools (#2136) * feat(tools): added apify * cleanup * feat(i18n): update translations (#2137) Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com> * feat(env): added more optional env var examples (#2138) * feat(statuspage): added statuspage, updated list of tools in footer, renamed routes (#2139) * feat(statuspage): added statuspage, updated list of tools in footer, renamed routes * ack PR comments * feat(tools): add generic search tool (#2140) * feat(i18n): update translations (#2141) * fix(sdks): bump sdk versions (#2142) * fix(webhooks): count test webhooks towards usage limit (#2143) * fix(bill): add requestId to webhook processing (#2144) * improvement(subflow): remove all associated edges when moving a block into a subflow (#2145) * improvement(subflow): remove all associated edges when moving a block into a subflow * ack PR comments * fix(polling): mark webhook failed on webhook trigger errors (#2146) * fix(deps): declare core transient deps explicitly (#2147) * fix(deps): declare core transient deps explicitly * ack PR comments --------- Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com> Co-authored-by: waleedlatif1 <waleedlatif1@users.noreply.github.com>
…, nullable forwardingNumber Review + final pre-merge audit fixes: - Trigger apiKey/phoneNumbers subblocks collided with the block's tool apiKey state key — rename to triggerApiKey/triggerPhoneNumbers (per the namespacing rule from #2133) and read them in the webhook handler - edit_message: the API returns 204 No Content when editing an already-deleted message; guard the empty body instead of throwing on response.json() - list_phone_numbers: mark forwardingNumber output nullable (returns null) - check_rcs: tighten address hint (RCS is phone-only, not email) - regenerated docs
) * feat(linq): audit fixes + native auto-registering webhook trigger Tools/block audit (validated against the live Linq partner API + OpenAPI spec): - create_chat: read the sent message from top-level response.message (was always null) - get_message/edit_message: expose canonical deliveryStatus; mark is_delivered/is_read deprecated - send_message: fall back to from_handle.service/preferred_service for service output - list_phone_numbers: migrate deprecated health_status to reputation; add forwardingNumber; guard JSON parse - check_imessage/check_rcs: guard response.json() parse - mark_chat_read: note 1:1-only / group no-op behavior Native webhook trigger (auto register + deregister): - 6 triggers (message received/delivered/failed/read, reaction added, all-events) - Standard Webhooks signature verification (HMAC-SHA256, whsec_ secret) - createSubscription/deleteSubscription manage the Linq subscription lifecycle - event_id idempotency; full 27-value WebhookEventType enum for all-events - regenerated docs * refactor(linq): drop phantom create_chat response path, complete deliveryStatus enum doc Final validation against the raw Linq OpenAPI spec confirmed the sent message is at chat.message (CreateChatResult exposes only chat), so the data.message fallback was dead code. Also list all 7 DeliveryStatus values in the send_message output description. * fix(linq): namespace trigger credential keys, handle edit_message 204, nullable forwardingNumber Review + final pre-merge audit fixes: - Trigger apiKey/phoneNumbers subblocks collided with the block's tool apiKey state key — rename to triggerApiKey/triggerPhoneNumbers (per the namespacing rule from #2133) and read them in the webhook handler - edit_message: the API returns 204 No Content when editing an already-deleted message; guard the empty body instead of throwing on response.json() - list_phone_numbers: mark forwardingNumber output nullable (returns null) - check_rcs: tighten address hint (RCS is phone-only, not email) - regenerated docs * fix(linq): read triggerApiKey in webhook deleteSubscription deleteSubscription still read config.apiKey after the credential rename, so undeploy would skip the DELETE and orphan the Linq subscription. Match createSubscription's triggerApiKey key. * fix(linq): mark list_phone_numbers healthStatus output nullable healthStatus returns null when Linq omits reputation/health_status; declare nullable: true to match the runtime value (same as forwardingNumber). * fix(linq): mark nullable list_webhook_subscriptions item fields phoneNumbers/createdAt/updatedAt are null-coerced by mapWebhookSubscription; declare nullable: true on the array-item schema to match runtime (consistent with the top-level webhook outputs' optional flags).
Summary
Type of Change
Testing
Tested manually.
Checklist