feat: filter webhooks per project, board, and account

Adds optional project, board, and acting-user scope to each webhook so
events from a specific board or project can be routed to a single
endpoint without an external automation tool in the middle (closes
#1457).

A webhook now fires for an event only when every set scope matches:
empty scope still means "fire for everything", keeping existing
webhooks working unchanged. Scope filtering is centralized in the
sendWebhooks helper, which auto-derives projectId/boardId from the
event payload, so existing call sites are untouched.
This commit is contained in:
Symon
2026-05-02 10:31:30 +03:00
parent a8dcd7cef3
commit 05979a460f
12 changed files with 446 additions and 131 deletions
+23
View File
@@ -30,6 +30,21 @@
* type: string
* description: Unique identifier for the webhook
* example: "1357158568008091264"
* projectId:
* type: string
* nullable: true
* description: Optional project scope; webhook fires only for events within this project
* example: "1357158568008091264"
* boardId:
* type: string
* nullable: true
* description: Optional board scope; webhook fires only for events within this board
* example: "1357158568008091264"
* userId:
* type: string
* nullable: true
* description: Optional acting-user scope; webhook fires only for events triggered by this user
* example: "1357158568008091264"
* name:
* type: string
* description: Name/title of the webhook
@@ -200,9 +215,17 @@ module.exports = {
// ╠═╣╚═╗╚═╗║ ║║ ║╠═╣ ║ ║║ ║║║║╚═╗
// ╩ ╩╚═╝╚═╝╚═╝╚═╝╩╩ ╩ ╩ ╩╚═╝╝╚╝╚═╝
projectId: {
model: 'Project',
columnName: 'project_id',
},
boardId: {
model: 'Board',
columnName: 'board_id',
},
userId: {
model: 'User',
columnName: 'user_id',
},
},
};