@generacy-ai/generacy-plugin-jira 0.0.0-preview-20260304013206
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/dist/client.d.ts +81 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +163 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/operations/comments.d.ts +35 -0
- package/dist/operations/comments.d.ts.map +1 -0
- package/dist/operations/comments.js +128 -0
- package/dist/operations/comments.js.map +1 -0
- package/dist/operations/custom-fields.d.ts +48 -0
- package/dist/operations/custom-fields.d.ts.map +1 -0
- package/dist/operations/custom-fields.js +184 -0
- package/dist/operations/custom-fields.js.map +1 -0
- package/dist/operations/issues.d.ts +34 -0
- package/dist/operations/issues.d.ts.map +1 -0
- package/dist/operations/issues.js +215 -0
- package/dist/operations/issues.js.map +1 -0
- package/dist/operations/search.d.ts +47 -0
- package/dist/operations/search.d.ts.map +1 -0
- package/dist/operations/search.js +174 -0
- package/dist/operations/search.js.map +1 -0
- package/dist/operations/sprints.d.ts +54 -0
- package/dist/operations/sprints.d.ts.map +1 -0
- package/dist/operations/sprints.js +196 -0
- package/dist/operations/sprints.js.map +1 -0
- package/dist/operations/transitions.d.ts +41 -0
- package/dist/operations/transitions.d.ts.map +1 -0
- package/dist/operations/transitions.js +135 -0
- package/dist/operations/transitions.js.map +1 -0
- package/dist/plugin.d.ts +221 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +403 -0
- package/dist/plugin.js.map +1 -0
- package/dist/types/config.d.ts +149 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +33 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/custom-fields.d.ts +48 -0
- package/dist/types/custom-fields.d.ts.map +1 -0
- package/dist/types/custom-fields.js +2 -0
- package/dist/types/custom-fields.js.map +1 -0
- package/dist/types/events.d.ts +250 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/issues.d.ts +139 -0
- package/dist/types/issues.d.ts.map +1 -0
- package/dist/types/issues.js +2 -0
- package/dist/types/issues.js.map +1 -0
- package/dist/types/projects.d.ts +48 -0
- package/dist/types/projects.d.ts.map +1 -0
- package/dist/types/projects.js +2 -0
- package/dist/types/projects.js.map +1 -0
- package/dist/types/sprints.d.ts +26 -0
- package/dist/types/sprints.d.ts.map +1 -0
- package/dist/types/sprints.js +2 -0
- package/dist/types/sprints.js.map +1 -0
- package/dist/types/workflows.d.ts +60 -0
- package/dist/types/workflows.d.ts.map +1 -0
- package/dist/types/workflows.js +2 -0
- package/dist/types/workflows.js.map +1 -0
- package/dist/utils/adf.d.ts +26 -0
- package/dist/utils/adf.d.ts.map +1 -0
- package/dist/utils/adf.js +104 -0
- package/dist/utils/adf.js.map +1 -0
- package/dist/utils/errors.d.ts +60 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +117 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/jql-builder.d.ts +148 -0
- package/dist/utils/jql-builder.d.ts.map +1 -0
- package/dist/utils/jql-builder.js +264 -0
- package/dist/utils/jql-builder.js.map +1 -0
- package/dist/utils/validation.d.ts +31 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +75 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/webhooks/handler.d.ts +80 -0
- package/dist/webhooks/handler.d.ts.map +1 -0
- package/dist/webhooks/handler.js +130 -0
- package/dist/webhooks/handler.js.map +1 -0
- package/dist/webhooks/parser.d.ts +34 -0
- package/dist/webhooks/parser.d.ts.map +1 -0
- package/dist/webhooks/parser.js +155 -0
- package/dist/webhooks/parser.js.map +1 -0
- package/dist/webhooks/types.d.ts +94 -0
- package/dist/webhooks/types.d.ts.map +1 -0
- package/dist/webhooks/types.js +2 -0
- package/dist/webhooks/types.js.map +1 -0
- package/dist/webhooks/verify.d.ts +53 -0
- package/dist/webhooks/verify.d.ts.map +1 -0
- package/dist/webhooks/verify.js +140 -0
- package/dist/webhooks/verify.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a raw webhook payload into a typed event
|
|
3
|
+
*/
|
|
4
|
+
export function parseWebhookPayload(payload) {
|
|
5
|
+
if (!payload || typeof payload !== 'object') {
|
|
6
|
+
throw new Error('Invalid webhook payload: expected object');
|
|
7
|
+
}
|
|
8
|
+
const data = payload;
|
|
9
|
+
if (!data.webhookEvent || typeof data.webhookEvent !== 'string') {
|
|
10
|
+
throw new Error('Invalid webhook payload: missing webhookEvent');
|
|
11
|
+
}
|
|
12
|
+
// The payload structure varies by event type, but we can cast safely
|
|
13
|
+
// since Jira sends consistent payloads per event type
|
|
14
|
+
return data;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Extract changes from a changelog
|
|
18
|
+
*/
|
|
19
|
+
export function extractChanges(changelog) {
|
|
20
|
+
return changelog?.items ?? [];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if a specific field was changed
|
|
24
|
+
*/
|
|
25
|
+
export function hasFieldChange(changelog, fieldName) {
|
|
26
|
+
return extractChanges(changelog).some((item) => item.field.toLowerCase() === fieldName.toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the change for a specific field
|
|
30
|
+
*/
|
|
31
|
+
export function getFieldChange(changelog, fieldName) {
|
|
32
|
+
return extractChanges(changelog).find((item) => item.field.toLowerCase() === fieldName.toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Determine the action type from an issue event
|
|
36
|
+
*/
|
|
37
|
+
function determineIssueActionType(event) {
|
|
38
|
+
if (event.webhookEvent === 'jira:issue_created') {
|
|
39
|
+
return 'issue_created';
|
|
40
|
+
}
|
|
41
|
+
if (event.webhookEvent === 'jira:issue_deleted') {
|
|
42
|
+
return 'issue_deleted';
|
|
43
|
+
}
|
|
44
|
+
// For updates, check what changed
|
|
45
|
+
if (hasFieldChange(event.changelog, 'status')) {
|
|
46
|
+
return 'issue_transitioned';
|
|
47
|
+
}
|
|
48
|
+
if (hasFieldChange(event.changelog, 'assignee')) {
|
|
49
|
+
const assigneeChange = getFieldChange(event.changelog, 'assignee');
|
|
50
|
+
if (assigneeChange?.to === null || assigneeChange?.toString === null) {
|
|
51
|
+
return 'issue_unassigned';
|
|
52
|
+
}
|
|
53
|
+
return 'issue_assigned';
|
|
54
|
+
}
|
|
55
|
+
if (hasFieldChange(event.changelog, 'priority')) {
|
|
56
|
+
return 'priority_changed';
|
|
57
|
+
}
|
|
58
|
+
if (hasFieldChange(event.changelog, 'labels')) {
|
|
59
|
+
return 'labels_changed';
|
|
60
|
+
}
|
|
61
|
+
return 'issue_updated';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Determine the action type from a comment event
|
|
65
|
+
*/
|
|
66
|
+
function determineCommentActionType(event) {
|
|
67
|
+
switch (event.webhookEvent) {
|
|
68
|
+
case 'comment_created':
|
|
69
|
+
return 'comment_added';
|
|
70
|
+
case 'comment_updated':
|
|
71
|
+
return 'comment_updated';
|
|
72
|
+
case 'comment_deleted':
|
|
73
|
+
return 'comment_deleted';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parse webhook event into a normalized action
|
|
78
|
+
*/
|
|
79
|
+
export function parseWebhookAction(event) {
|
|
80
|
+
const base = {
|
|
81
|
+
type: 'unknown',
|
|
82
|
+
timestamp: new Date(event.timestamp),
|
|
83
|
+
userId: event.user?.accountId,
|
|
84
|
+
userDisplayName: event.user?.displayName,
|
|
85
|
+
};
|
|
86
|
+
// Handle issue events
|
|
87
|
+
if (event.webhookEvent.startsWith('jira:issue_')) {
|
|
88
|
+
const issueEvent = event;
|
|
89
|
+
const action = {
|
|
90
|
+
...base,
|
|
91
|
+
type: determineIssueActionType(issueEvent),
|
|
92
|
+
issueKey: issueEvent.issue?.key,
|
|
93
|
+
issueId: issueEvent.issue?.id,
|
|
94
|
+
changes: extractChanges(issueEvent.changelog),
|
|
95
|
+
};
|
|
96
|
+
// Add status transition details
|
|
97
|
+
if (action.type === 'issue_transitioned') {
|
|
98
|
+
const statusChange = getFieldChange(issueEvent.changelog, 'status');
|
|
99
|
+
action.previousStatus = statusChange?.fromString ?? undefined;
|
|
100
|
+
action.newStatus = statusChange?.toString ?? undefined;
|
|
101
|
+
}
|
|
102
|
+
// Add assignee details
|
|
103
|
+
if (action.type === 'issue_assigned' || action.type === 'issue_unassigned') {
|
|
104
|
+
const assigneeChange = getFieldChange(issueEvent.changelog, 'assignee');
|
|
105
|
+
action.previousAssignee = assigneeChange?.fromString ?? undefined;
|
|
106
|
+
action.newAssignee = assigneeChange?.toString ?? undefined;
|
|
107
|
+
}
|
|
108
|
+
return action;
|
|
109
|
+
}
|
|
110
|
+
// Handle comment events
|
|
111
|
+
if (event.webhookEvent.startsWith('comment_')) {
|
|
112
|
+
const commentEvent = event;
|
|
113
|
+
return {
|
|
114
|
+
...base,
|
|
115
|
+
type: determineCommentActionType(commentEvent),
|
|
116
|
+
issueKey: commentEvent.issue?.key,
|
|
117
|
+
issueId: commentEvent.issue?.id,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// Handle sprint events
|
|
121
|
+
if (event.webhookEvent.startsWith('sprint_')) {
|
|
122
|
+
switch (event.webhookEvent) {
|
|
123
|
+
case 'sprint_started':
|
|
124
|
+
return { ...base, type: 'sprint_started' };
|
|
125
|
+
case 'sprint_closed':
|
|
126
|
+
return { ...base, type: 'sprint_closed' };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return base;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if an event is for a specific issue
|
|
133
|
+
*/
|
|
134
|
+
export function isEventForIssue(event, issueKey) {
|
|
135
|
+
if ('issue' in event && event.issue) {
|
|
136
|
+
return event.issue.key === issueKey;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if an event involves a specific user
|
|
142
|
+
*/
|
|
143
|
+
export function isEventByUser(event, accountId) {
|
|
144
|
+
return event.user?.accountId === accountId;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get the issue key from any webhook event
|
|
148
|
+
*/
|
|
149
|
+
export function getIssueKeyFromEvent(event) {
|
|
150
|
+
if ('issue' in event && event.issue) {
|
|
151
|
+
return event.issue.key;
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/webhooks/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { JiraUser, JiraIssue } from '../types/issues.js';
|
|
2
|
+
import type { JiraComment } from '../types/events.js';
|
|
3
|
+
import type { Sprint } from '../types/sprints.js';
|
|
4
|
+
/**
|
|
5
|
+
* Jira webhook event types
|
|
6
|
+
*/
|
|
7
|
+
export type JiraEventType = 'jira:issue_created' | 'jira:issue_updated' | 'jira:issue_deleted' | 'comment_created' | 'comment_updated' | 'comment_deleted' | 'sprint_created' | 'sprint_updated' | 'sprint_started' | 'sprint_closed' | 'issuelink_created' | 'issuelink_deleted' | 'worklog_created' | 'worklog_updated' | 'worklog_deleted';
|
|
8
|
+
/**
|
|
9
|
+
* Changelog item for tracking field changes
|
|
10
|
+
*/
|
|
11
|
+
export interface ChangelogItem {
|
|
12
|
+
field: string;
|
|
13
|
+
fieldtype: string;
|
|
14
|
+
fieldId: string;
|
|
15
|
+
from: string | null;
|
|
16
|
+
fromString: string | null;
|
|
17
|
+
to: string | null;
|
|
18
|
+
toString: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Changelog for issue updates
|
|
22
|
+
*/
|
|
23
|
+
export interface Changelog {
|
|
24
|
+
id: string;
|
|
25
|
+
items: ChangelogItem[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Base webhook event structure
|
|
29
|
+
*/
|
|
30
|
+
export interface JiraWebhookEventBase {
|
|
31
|
+
webhookEvent: JiraEventType;
|
|
32
|
+
timestamp: number;
|
|
33
|
+
user: JiraUser;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Issue-related webhook events
|
|
37
|
+
*/
|
|
38
|
+
export interface JiraIssueEvent extends JiraWebhookEventBase {
|
|
39
|
+
webhookEvent: 'jira:issue_created' | 'jira:issue_updated' | 'jira:issue_deleted';
|
|
40
|
+
issue: JiraIssue;
|
|
41
|
+
changelog?: Changelog;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Comment-related webhook events
|
|
45
|
+
*/
|
|
46
|
+
export interface JiraCommentEvent extends JiraWebhookEventBase {
|
|
47
|
+
webhookEvent: 'comment_created' | 'comment_updated' | 'comment_deleted';
|
|
48
|
+
issue: JiraIssue;
|
|
49
|
+
comment: JiraComment;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Sprint-related webhook events
|
|
53
|
+
*/
|
|
54
|
+
export interface JiraSprintEvent extends JiraWebhookEventBase {
|
|
55
|
+
webhookEvent: 'sprint_created' | 'sprint_updated' | 'sprint_started' | 'sprint_closed';
|
|
56
|
+
sprint: Sprint;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Union type for all webhook events
|
|
60
|
+
*/
|
|
61
|
+
export type JiraWebhookEvent = JiraIssueEvent | JiraCommentEvent | JiraSprintEvent;
|
|
62
|
+
/**
|
|
63
|
+
* Parsed webhook action types
|
|
64
|
+
*/
|
|
65
|
+
export type WebhookActionType = 'issue_created' | 'issue_updated' | 'issue_deleted' | 'issue_assigned' | 'issue_unassigned' | 'issue_transitioned' | 'comment_added' | 'comment_updated' | 'comment_deleted' | 'sprint_started' | 'sprint_closed' | 'priority_changed' | 'labels_changed' | 'unknown';
|
|
66
|
+
/**
|
|
67
|
+
* Parsed webhook action with details
|
|
68
|
+
*/
|
|
69
|
+
export interface WebhookAction {
|
|
70
|
+
type: WebhookActionType;
|
|
71
|
+
issueKey?: string;
|
|
72
|
+
issueId?: string;
|
|
73
|
+
userId?: string;
|
|
74
|
+
userDisplayName?: string;
|
|
75
|
+
timestamp: Date;
|
|
76
|
+
changes?: ChangelogItem[];
|
|
77
|
+
previousStatus?: string;
|
|
78
|
+
newStatus?: string;
|
|
79
|
+
previousAssignee?: string;
|
|
80
|
+
newAssignee?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Webhook handler callback signature
|
|
84
|
+
*/
|
|
85
|
+
export type WebhookHandler = (event: JiraWebhookEvent, action: WebhookAction) => Promise<void> | void;
|
|
86
|
+
/**
|
|
87
|
+
* Webhook handler registration
|
|
88
|
+
*/
|
|
89
|
+
export interface WebhookHandlerRegistration {
|
|
90
|
+
eventTypes: JiraEventType[];
|
|
91
|
+
actionTypes?: WebhookActionType[];
|
|
92
|
+
handler: WebhookHandler;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/webhooks/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webhooks/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification result
|
|
3
|
+
*/
|
|
4
|
+
export interface VerificationResult {
|
|
5
|
+
valid: boolean;
|
|
6
|
+
reason?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Options for webhook verification
|
|
10
|
+
*/
|
|
11
|
+
export interface VerifyOptions {
|
|
12
|
+
/** The webhook secret configured in Jira */
|
|
13
|
+
secret: string;
|
|
14
|
+
/** The raw request body as a string */
|
|
15
|
+
body: string;
|
|
16
|
+
/** The signature from the X-Hub-Signature header (if using HMAC) */
|
|
17
|
+
signature?: string;
|
|
18
|
+
/** List of allowed IP addresses or CIDR ranges (Atlassian IPs) */
|
|
19
|
+
allowedIps?: string[];
|
|
20
|
+
/** The IP address of the request origin */
|
|
21
|
+
sourceIp?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Atlassian Cloud outbound IP ranges
|
|
25
|
+
* These should be periodically updated from:
|
|
26
|
+
* https://support.atlassian.com/organization-administration/docs/ip-addresses-and-domains-for-atlassian-cloud-products/
|
|
27
|
+
*/
|
|
28
|
+
export declare const ATLASSIAN_IP_RANGES: string[];
|
|
29
|
+
/**
|
|
30
|
+
* Verify webhook signature using HMAC-SHA256
|
|
31
|
+
*/
|
|
32
|
+
export declare function verifySignature(body: string, signature: string, secret: string): VerificationResult;
|
|
33
|
+
/**
|
|
34
|
+
* Verify that the source IP is from Atlassian
|
|
35
|
+
*/
|
|
36
|
+
export declare function verifySourceIp(ip: string, allowedRanges?: string[]): VerificationResult;
|
|
37
|
+
/**
|
|
38
|
+
* Comprehensive webhook verification
|
|
39
|
+
*/
|
|
40
|
+
export declare function verifyWebhook(options: VerifyOptions): VerificationResult;
|
|
41
|
+
/**
|
|
42
|
+
* Create a verification middleware for Express-like frameworks
|
|
43
|
+
*/
|
|
44
|
+
export declare function createVerificationMiddleware(secret: string): (req: {
|
|
45
|
+
body: string;
|
|
46
|
+
headers: Record<string, string>;
|
|
47
|
+
ip?: string;
|
|
48
|
+
}, res: {
|
|
49
|
+
status: (code: number) => {
|
|
50
|
+
send: (msg: string) => void;
|
|
51
|
+
};
|
|
52
|
+
}, next: () => void) => void;
|
|
53
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/webhooks/verify.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,UAU/B,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,kBAAkB,CAuCpB;AAkCD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,MAAM,EACV,aAAa,GAAE,MAAM,EAAwB,GAC5C,kBAAkB,CAgBpB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,kBAAkB,CAqBxE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,IAEvD,KAAK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EACnE,KAAK;IAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAA;CAAE,EAClE,MAAM,MAAM,IAAI,KACf,IAAI,CAiBR"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Atlassian Cloud outbound IP ranges
|
|
4
|
+
* These should be periodically updated from:
|
|
5
|
+
* https://support.atlassian.com/organization-administration/docs/ip-addresses-and-domains-for-atlassian-cloud-products/
|
|
6
|
+
*/
|
|
7
|
+
export const ATLASSIAN_IP_RANGES = [
|
|
8
|
+
'13.52.5.96/28',
|
|
9
|
+
'13.236.8.224/28',
|
|
10
|
+
'18.136.214.96/28',
|
|
11
|
+
'18.184.99.224/28',
|
|
12
|
+
'18.234.32.224/28',
|
|
13
|
+
'18.246.31.224/28',
|
|
14
|
+
'52.215.192.224/28',
|
|
15
|
+
'104.192.136.0/21',
|
|
16
|
+
'185.166.140.0/22',
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Verify webhook signature using HMAC-SHA256
|
|
20
|
+
*/
|
|
21
|
+
export function verifySignature(body, signature, secret) {
|
|
22
|
+
if (!signature) {
|
|
23
|
+
return { valid: false, reason: 'Missing signature header' };
|
|
24
|
+
}
|
|
25
|
+
if (!secret) {
|
|
26
|
+
return { valid: false, reason: 'Missing webhook secret' };
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
// Jira uses sha256= prefix similar to GitHub
|
|
30
|
+
const expectedPrefix = 'sha256=';
|
|
31
|
+
if (!signature.startsWith(expectedPrefix)) {
|
|
32
|
+
return { valid: false, reason: 'Invalid signature format' };
|
|
33
|
+
}
|
|
34
|
+
const providedHash = signature.slice(expectedPrefix.length);
|
|
35
|
+
const hmac = createHmac('sha256', secret);
|
|
36
|
+
hmac.update(body);
|
|
37
|
+
const expectedHash = hmac.digest('hex');
|
|
38
|
+
// Use timing-safe comparison
|
|
39
|
+
const providedBuffer = Buffer.from(providedHash, 'hex');
|
|
40
|
+
const expectedBuffer = Buffer.from(expectedHash, 'hex');
|
|
41
|
+
if (providedBuffer.length !== expectedBuffer.length) {
|
|
42
|
+
return { valid: false, reason: 'Signature mismatch' };
|
|
43
|
+
}
|
|
44
|
+
const valid = timingSafeEqual(providedBuffer, expectedBuffer);
|
|
45
|
+
return valid
|
|
46
|
+
? { valid: true }
|
|
47
|
+
: { valid: false, reason: 'Signature mismatch' };
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
valid: false,
|
|
52
|
+
reason: `Verification error: ${error instanceof Error ? error.message : String(error)}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if an IP address is within a CIDR range
|
|
58
|
+
*/
|
|
59
|
+
function isIpInRange(ip, cidr) {
|
|
60
|
+
const [rangeIp, prefixLength] = cidr.split('/');
|
|
61
|
+
if (!rangeIp || !prefixLength) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const prefix = parseInt(prefixLength, 10);
|
|
65
|
+
const ipParts = ip.split('.').map(Number);
|
|
66
|
+
const rangeParts = rangeIp.split('.').map(Number);
|
|
67
|
+
if (ipParts.length !== 4 || rangeParts.length !== 4) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
// Convert to 32-bit integers
|
|
71
|
+
const ipInt = (ipParts[0] << 24) | (ipParts[1] << 16) | (ipParts[2] << 8) | ipParts[3];
|
|
72
|
+
const rangeInt = (rangeParts[0] << 24) |
|
|
73
|
+
(rangeParts[1] << 16) |
|
|
74
|
+
(rangeParts[2] << 8) |
|
|
75
|
+
rangeParts[3];
|
|
76
|
+
// Create mask
|
|
77
|
+
const mask = prefix === 0 ? 0 : -1 << (32 - prefix);
|
|
78
|
+
return (ipInt & mask) === (rangeInt & mask);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Verify that the source IP is from Atlassian
|
|
82
|
+
*/
|
|
83
|
+
export function verifySourceIp(ip, allowedRanges = ATLASSIAN_IP_RANGES) {
|
|
84
|
+
if (!ip) {
|
|
85
|
+
return { valid: false, reason: 'Missing source IP' };
|
|
86
|
+
}
|
|
87
|
+
const isAllowed = allowedRanges.some((range) => {
|
|
88
|
+
// Handle both single IPs and CIDR ranges
|
|
89
|
+
if (range.includes('/')) {
|
|
90
|
+
return isIpInRange(ip, range);
|
|
91
|
+
}
|
|
92
|
+
return ip === range;
|
|
93
|
+
});
|
|
94
|
+
return isAllowed
|
|
95
|
+
? { valid: true }
|
|
96
|
+
: { valid: false, reason: `IP ${ip} not in allowed ranges` };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Comprehensive webhook verification
|
|
100
|
+
*/
|
|
101
|
+
export function verifyWebhook(options) {
|
|
102
|
+
const { secret, body, signature, allowedIps, sourceIp } = options;
|
|
103
|
+
// Verify signature if provided
|
|
104
|
+
if (signature && secret) {
|
|
105
|
+
const signatureResult = verifySignature(body, signature, secret);
|
|
106
|
+
if (!signatureResult.valid) {
|
|
107
|
+
return signatureResult;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Verify source IP if checking is requested
|
|
111
|
+
if (allowedIps && sourceIp) {
|
|
112
|
+
const ipResult = verifySourceIp(sourceIp, allowedIps);
|
|
113
|
+
if (!ipResult.valid) {
|
|
114
|
+
return ipResult;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// If no verification was requested or all passed
|
|
118
|
+
return { valid: true };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Create a verification middleware for Express-like frameworks
|
|
122
|
+
*/
|
|
123
|
+
export function createVerificationMiddleware(secret) {
|
|
124
|
+
return (req, res, next) => {
|
|
125
|
+
const signature = req.headers['x-hub-signature-256'] ?? req.headers['x-hub-signature'];
|
|
126
|
+
const result = verifyWebhook({
|
|
127
|
+
secret,
|
|
128
|
+
body: req.body,
|
|
129
|
+
signature,
|
|
130
|
+
sourceIp: req.ip,
|
|
131
|
+
allowedIps: ATLASSIAN_IP_RANGES,
|
|
132
|
+
});
|
|
133
|
+
if (!result.valid) {
|
|
134
|
+
res.status(401).send(`Webhook verification failed: ${result.reason}`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
next();
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/webhooks/verify.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@generacy-ai/generacy-plugin-jira",
|
|
3
|
+
"version": "0.0.0-preview-20260304013206",
|
|
4
|
+
"description": "Atlassian Jira integration plugin for Generacy",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"generacy",
|
|
19
|
+
"jira",
|
|
20
|
+
"atlassian",
|
|
21
|
+
"plugin",
|
|
22
|
+
"issues",
|
|
23
|
+
"automation"
|
|
24
|
+
],
|
|
25
|
+
"author": "Generacy AI",
|
|
26
|
+
"license": "Apache-2.0",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/generacy-ai/generacy.git",
|
|
30
|
+
"directory": "packages/jira"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@generacy-ai/latency": "^0.1.0",
|
|
37
|
+
"@generacy-ai/latency-plugin-issue-tracker": "^0.1.0",
|
|
38
|
+
"jira.js": "^4.0.1",
|
|
39
|
+
"zod": "^3.23.8"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^22.10.2",
|
|
43
|
+
"typescript": "^5.7.2",
|
|
44
|
+
"vitest": "^3.2.4"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsc",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
54
|
+
"lint": "eslint src",
|
|
55
|
+
"typecheck": "tsc --noEmit",
|
|
56
|
+
"clean": "rm -rf dist"
|
|
57
|
+
}
|
|
58
|
+
}
|