feat: outgoing webhooks

Owners and admins can point a project at other systems: a signed JSON
POST (HMAC-SHA256 of the body) when tickets, comments, releases or sprints
change, filtered by event or family. Deliveries are retried a couple of
times, the last one is shown, and a ping can be sent from the settings.
Private addresses are refused unless WEBHOOKS_ALLOW_PRIVATE is set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 15:36:19 +02:00
parent 046d77c813
commit d43fc620e9
37 changed files with 3660 additions and 28 deletions

View File

@@ -275,6 +275,33 @@ export class SaveFilterInput {
criteria!: SavedFilterCriteriaInput;
}
@InputType()
export class CreateWebhookInput {
@Field(() => ID) @IsUUID() projectId!: string;
@Field() @IsUrl({ require_tld: false, require_protocol: true }) url!: string;
@Field(() => [String], { description: 'Event names, family.* or *' })
@IsArray()
@ArrayMaxSize(50)
@IsString({ each: true })
events!: string[];
}
@InputType()
export class UpdateWebhookInput {
@Field(() => ID) @IsUUID() webhookId!: string;
@Field({ nullable: true })
@IsOptional()
@IsUrl({ require_tld: false, require_protocol: true })
url?: string;
@Field(() => [String], { nullable: true })
@IsOptional()
@IsArray()
@ArrayMaxSize(50)
@IsString({ each: true })
events?: string[];
@Field({ nullable: true }) @IsOptional() @IsBoolean() active?: boolean;
}
@InputType()
export class RankIssueInput {
@Field(() => ID) @IsUUID() issueId!: string;