@cat-factory/integrations 0.6.0

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.
Files changed (242) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +68 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +84 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/modules/datadog/DatadogClient.d.ts +54 -0
  7. package/dist/modules/datadog/DatadogClient.d.ts.map +1 -0
  8. package/dist/modules/datadog/DatadogClient.js +132 -0
  9. package/dist/modules/datadog/DatadogClient.js.map +1 -0
  10. package/dist/modules/datadog/DatadogReleaseHealthProvider.d.ts +30 -0
  11. package/dist/modules/datadog/DatadogReleaseHealthProvider.d.ts.map +1 -0
  12. package/dist/modules/datadog/DatadogReleaseHealthProvider.js +101 -0
  13. package/dist/modules/datadog/DatadogReleaseHealthProvider.js.map +1 -0
  14. package/dist/modules/datadog/datadog.logic.d.ts +37 -0
  15. package/dist/modules/datadog/datadog.logic.d.ts.map +1 -0
  16. package/dist/modules/datadog/datadog.logic.js +90 -0
  17. package/dist/modules/datadog/datadog.logic.js.map +1 -0
  18. package/dist/modules/documents/ConfluenceProvider.d.ts +29 -0
  19. package/dist/modules/documents/ConfluenceProvider.d.ts.map +1 -0
  20. package/dist/modules/documents/ConfluenceProvider.js +180 -0
  21. package/dist/modules/documents/ConfluenceProvider.js.map +1 -0
  22. package/dist/modules/documents/DocumentConnectionService.d.ts +30 -0
  23. package/dist/modules/documents/DocumentConnectionService.d.ts.map +1 -0
  24. package/dist/modules/documents/DocumentConnectionService.js +69 -0
  25. package/dist/modules/documents/DocumentConnectionService.js.map +1 -0
  26. package/dist/modules/documents/DocumentImportService.d.ts +34 -0
  27. package/dist/modules/documents/DocumentImportService.d.ts.map +1 -0
  28. package/dist/modules/documents/DocumentImportService.js +83 -0
  29. package/dist/modules/documents/DocumentImportService.js.map +1 -0
  30. package/dist/modules/documents/DocumentLinkService.d.ts +31 -0
  31. package/dist/modules/documents/DocumentLinkService.d.ts.map +1 -0
  32. package/dist/modules/documents/DocumentLinkService.js +75 -0
  33. package/dist/modules/documents/DocumentLinkService.js.map +1 -0
  34. package/dist/modules/documents/DocumentPlannerService.d.ts +23 -0
  35. package/dist/modules/documents/DocumentPlannerService.d.ts.map +1 -0
  36. package/dist/modules/documents/DocumentPlannerService.js +96 -0
  37. package/dist/modules/documents/DocumentPlannerService.js.map +1 -0
  38. package/dist/modules/documents/GitHubDocsProvider.d.ts +42 -0
  39. package/dist/modules/documents/GitHubDocsProvider.d.ts.map +1 -0
  40. package/dist/modules/documents/GitHubDocsProvider.js +86 -0
  41. package/dist/modules/documents/GitHubDocsProvider.js.map +1 -0
  42. package/dist/modules/documents/NotionProvider.d.ts +32 -0
  43. package/dist/modules/documents/NotionProvider.d.ts.map +1 -0
  44. package/dist/modules/documents/NotionProvider.js +221 -0
  45. package/dist/modules/documents/NotionProvider.js.map +1 -0
  46. package/dist/modules/documents/confluence.logic.d.ts +37 -0
  47. package/dist/modules/documents/confluence.logic.d.ts.map +1 -0
  48. package/dist/modules/documents/confluence.logic.js +133 -0
  49. package/dist/modules/documents/confluence.logic.js.map +1 -0
  50. package/dist/modules/documents/documents.logic.d.ts +22 -0
  51. package/dist/modules/documents/documents.logic.d.ts.map +1 -0
  52. package/dist/modules/documents/documents.logic.js +138 -0
  53. package/dist/modules/documents/documents.logic.js.map +1 -0
  54. package/dist/modules/documents/github-docs.logic.d.ts +52 -0
  55. package/dist/modules/documents/github-docs.logic.d.ts.map +1 -0
  56. package/dist/modules/documents/github-docs.logic.js +94 -0
  57. package/dist/modules/documents/github-docs.logic.js.map +1 -0
  58. package/dist/modules/documents/notion.logic.d.ts +31 -0
  59. package/dist/modules/documents/notion.logic.d.ts.map +1 -0
  60. package/dist/modules/documents/notion.logic.js +142 -0
  61. package/dist/modules/documents/notion.logic.js.map +1 -0
  62. package/dist/modules/email/EmailConnectionService.d.ts +34 -0
  63. package/dist/modules/email/EmailConnectionService.d.ts.map +1 -0
  64. package/dist/modules/email/EmailConnectionService.js +82 -0
  65. package/dist/modules/email/EmailConnectionService.js.map +1 -0
  66. package/dist/modules/email/adapters.d.ts +39 -0
  67. package/dist/modules/email/adapters.d.ts.map +1 -0
  68. package/dist/modules/email/adapters.js +79 -0
  69. package/dist/modules/email/adapters.js.map +1 -0
  70. package/dist/modules/environments/EnvironmentConnectionService.d.ts +42 -0
  71. package/dist/modules/environments/EnvironmentConnectionService.d.ts.map +1 -0
  72. package/dist/modules/environments/EnvironmentConnectionService.js +120 -0
  73. package/dist/modules/environments/EnvironmentConnectionService.js.map +1 -0
  74. package/dist/modules/environments/EnvironmentProvisioningService.d.ts +56 -0
  75. package/dist/modules/environments/EnvironmentProvisioningService.d.ts.map +1 -0
  76. package/dist/modules/environments/EnvironmentProvisioningService.js +153 -0
  77. package/dist/modules/environments/EnvironmentProvisioningService.js.map +1 -0
  78. package/dist/modules/environments/EnvironmentTeardownService.d.ts +24 -0
  79. package/dist/modules/environments/EnvironmentTeardownService.d.ts.map +1 -0
  80. package/dist/modules/environments/EnvironmentTeardownService.js +54 -0
  81. package/dist/modules/environments/EnvironmentTeardownService.js.map +1 -0
  82. package/dist/modules/environments/HttpEnvironmentProvider.d.ts +30 -0
  83. package/dist/modules/environments/HttpEnvironmentProvider.d.ts.map +1 -0
  84. package/dist/modules/environments/HttpEnvironmentProvider.js +316 -0
  85. package/dist/modules/environments/HttpEnvironmentProvider.js.map +1 -0
  86. package/dist/modules/environments/environments.logic.d.ts +50 -0
  87. package/dist/modules/environments/environments.logic.d.ts.map +1 -0
  88. package/dist/modules/environments/environments.logic.js +257 -0
  89. package/dist/modules/environments/environments.logic.js.map +1 -0
  90. package/dist/modules/github/GitHubInstallationService.d.ts +66 -0
  91. package/dist/modules/github/GitHubInstallationService.d.ts.map +1 -0
  92. package/dist/modules/github/GitHubInstallationService.js +143 -0
  93. package/dist/modules/github/GitHubInstallationService.js.map +1 -0
  94. package/dist/modules/github/GitHubService.d.ts +29 -0
  95. package/dist/modules/github/GitHubService.d.ts.map +1 -0
  96. package/dist/modules/github/GitHubService.js +61 -0
  97. package/dist/modules/github/GitHubService.js.map +1 -0
  98. package/dist/modules/github/GitHubSyncService.d.ts +97 -0
  99. package/dist/modules/github/GitHubSyncService.d.ts.map +1 -0
  100. package/dist/modules/github/GitHubSyncService.js +241 -0
  101. package/dist/modules/github/GitHubSyncService.js.map +1 -0
  102. package/dist/modules/github/RepoProvisioningService.d.ts +26 -0
  103. package/dist/modules/github/RepoProvisioningService.d.ts.map +1 -0
  104. package/dist/modules/github/RepoProvisioningService.js +36 -0
  105. package/dist/modules/github/RepoProvisioningService.js.map +1 -0
  106. package/dist/modules/github/WebhookService.d.ts +28 -0
  107. package/dist/modules/github/WebhookService.d.ts.map +1 -0
  108. package/dist/modules/github/WebhookService.js +156 -0
  109. package/dist/modules/github/WebhookService.js.map +1 -0
  110. package/dist/modules/github/projection.logic.d.ts +95 -0
  111. package/dist/modules/github/projection.logic.d.ts.map +1 -0
  112. package/dist/modules/github/projection.logic.js +94 -0
  113. package/dist/modules/github/projection.logic.js.map +1 -0
  114. package/dist/modules/github/provisioning.logic.d.ts +11 -0
  115. package/dist/modules/github/provisioning.logic.d.ts.map +1 -0
  116. package/dist/modules/github/provisioning.logic.js +18 -0
  117. package/dist/modules/github/provisioning.logic.js.map +1 -0
  118. package/dist/modules/incident/incident.logic.d.ts +16 -0
  119. package/dist/modules/incident/incident.logic.d.ts.map +1 -0
  120. package/dist/modules/incident/incident.logic.js +23 -0
  121. package/dist/modules/incident/incident.logic.js.map +1 -0
  122. package/dist/modules/incidentio/IncidentIoEnrichmentProvider.d.ts +26 -0
  123. package/dist/modules/incidentio/IncidentIoEnrichmentProvider.d.ts.map +1 -0
  124. package/dist/modules/incidentio/IncidentIoEnrichmentProvider.js +84 -0
  125. package/dist/modules/incidentio/IncidentIoEnrichmentProvider.js.map +1 -0
  126. package/dist/modules/pagerduty/PagerDutyEnrichmentProvider.d.ts +27 -0
  127. package/dist/modules/pagerduty/PagerDutyEnrichmentProvider.d.ts.map +1 -0
  128. package/dist/modules/pagerduty/PagerDutyEnrichmentProvider.js +65 -0
  129. package/dist/modules/pagerduty/PagerDutyEnrichmentProvider.js.map +1 -0
  130. package/dist/modules/providers/ApiKeyService.d.ts +73 -0
  131. package/dist/modules/providers/ApiKeyService.d.ts.map +1 -0
  132. package/dist/modules/providers/ApiKeyService.js +122 -0
  133. package/dist/modules/providers/ApiKeyService.js.map +1 -0
  134. package/dist/modules/providers/LocalModelEndpointService.d.ts +52 -0
  135. package/dist/modules/providers/LocalModelEndpointService.d.ts.map +1 -0
  136. package/dist/modules/providers/LocalModelEndpointService.js +131 -0
  137. package/dist/modules/providers/LocalModelEndpointService.js.map +1 -0
  138. package/dist/modules/providers/PersonalSubscriptionService.d.ts +94 -0
  139. package/dist/modules/providers/PersonalSubscriptionService.d.ts.map +1 -0
  140. package/dist/modules/providers/PersonalSubscriptionService.js +218 -0
  141. package/dist/modules/providers/PersonalSubscriptionService.js.map +1 -0
  142. package/dist/modules/providers/ProviderSubscriptionService.d.ts +75 -0
  143. package/dist/modules/providers/ProviderSubscriptionService.d.ts.map +1 -0
  144. package/dist/modules/providers/ProviderSubscriptionService.js +130 -0
  145. package/dist/modules/providers/ProviderSubscriptionService.js.map +1 -0
  146. package/dist/modules/providers/localModelUrl.d.ts +7 -0
  147. package/dist/modules/providers/localModelUrl.d.ts.map +1 -0
  148. package/dist/modules/providers/localModelUrl.js +67 -0
  149. package/dist/modules/providers/localModelUrl.js.map +1 -0
  150. package/dist/modules/providers/providers.logic.d.ts +23 -0
  151. package/dist/modules/providers/providers.logic.d.ts.map +1 -0
  152. package/dist/modules/providers/providers.logic.js +46 -0
  153. package/dist/modules/providers/providers.logic.js.map +1 -0
  154. package/dist/modules/runners/HttpRunnerPoolProvider.d.ts +51 -0
  155. package/dist/modules/runners/HttpRunnerPoolProvider.d.ts.map +1 -0
  156. package/dist/modules/runners/HttpRunnerPoolProvider.js +304 -0
  157. package/dist/modules/runners/HttpRunnerPoolProvider.js.map +1 -0
  158. package/dist/modules/runners/RunnerPoolConnectionService.d.ts +47 -0
  159. package/dist/modules/runners/RunnerPoolConnectionService.d.ts.map +1 -0
  160. package/dist/modules/runners/RunnerPoolConnectionService.js +98 -0
  161. package/dist/modules/runners/RunnerPoolConnectionService.js.map +1 -0
  162. package/dist/modules/runners/RunnerPoolTransport.d.ts +11 -0
  163. package/dist/modules/runners/RunnerPoolTransport.d.ts.map +1 -0
  164. package/dist/modules/runners/RunnerPoolTransport.js +61 -0
  165. package/dist/modules/runners/RunnerPoolTransport.js.map +1 -0
  166. package/dist/modules/runners/runners.logic.d.ts +16 -0
  167. package/dist/modules/runners/runners.logic.d.ts.map +1 -0
  168. package/dist/modules/runners/runners.logic.js +52 -0
  169. package/dist/modules/runners/runners.logic.js.map +1 -0
  170. package/dist/modules/slack/SlackApiClient.d.ts +67 -0
  171. package/dist/modules/slack/SlackApiClient.d.ts.map +1 -0
  172. package/dist/modules/slack/SlackApiClient.js +132 -0
  173. package/dist/modules/slack/SlackApiClient.js.map +1 -0
  174. package/dist/modules/slack/SlackConnectionService.d.ts +41 -0
  175. package/dist/modules/slack/SlackConnectionService.d.ts.map +1 -0
  176. package/dist/modules/slack/SlackConnectionService.js +136 -0
  177. package/dist/modules/slack/SlackConnectionService.js.map +1 -0
  178. package/dist/modules/slack/SlackMemberMappingService.d.ts +17 -0
  179. package/dist/modules/slack/SlackMemberMappingService.d.ts.map +1 -0
  180. package/dist/modules/slack/SlackMemberMappingService.js +28 -0
  181. package/dist/modules/slack/SlackMemberMappingService.js.map +1 -0
  182. package/dist/modules/slack/SlackNotificationChannel.d.ts +45 -0
  183. package/dist/modules/slack/SlackNotificationChannel.d.ts.map +1 -0
  184. package/dist/modules/slack/SlackNotificationChannel.js +84 -0
  185. package/dist/modules/slack/SlackNotificationChannel.js.map +1 -0
  186. package/dist/modules/slack/SlackSettingsService.d.ts +16 -0
  187. package/dist/modules/slack/SlackSettingsService.d.ts.map +1 -0
  188. package/dist/modules/slack/SlackSettingsService.js +41 -0
  189. package/dist/modules/slack/SlackSettingsService.js.map +1 -0
  190. package/dist/modules/slack/slack.logic.d.ts +55 -0
  191. package/dist/modules/slack/slack.logic.d.ts.map +1 -0
  192. package/dist/modules/slack/slack.logic.js +149 -0
  193. package/dist/modules/slack/slack.logic.js.map +1 -0
  194. package/dist/modules/tasks/GitHubIssuesProvider.d.ts +50 -0
  195. package/dist/modules/tasks/GitHubIssuesProvider.d.ts.map +1 -0
  196. package/dist/modules/tasks/GitHubIssuesProvider.js +92 -0
  197. package/dist/modules/tasks/GitHubIssuesProvider.js.map +1 -0
  198. package/dist/modules/tasks/JiraProvider.d.ts +29 -0
  199. package/dist/modules/tasks/JiraProvider.d.ts.map +1 -0
  200. package/dist/modules/tasks/JiraProvider.js +114 -0
  201. package/dist/modules/tasks/JiraProvider.js.map +1 -0
  202. package/dist/modules/tasks/TaskConnectionService.d.ts +30 -0
  203. package/dist/modules/tasks/TaskConnectionService.d.ts.map +1 -0
  204. package/dist/modules/tasks/TaskConnectionService.js +69 -0
  205. package/dist/modules/tasks/TaskConnectionService.js.map +1 -0
  206. package/dist/modules/tasks/TaskImportService.d.ts +34 -0
  207. package/dist/modules/tasks/TaskImportService.d.ts.map +1 -0
  208. package/dist/modules/tasks/TaskImportService.js +96 -0
  209. package/dist/modules/tasks/TaskImportService.js.map +1 -0
  210. package/dist/modules/tasks/TaskLinkService.d.ts +30 -0
  211. package/dist/modules/tasks/TaskLinkService.d.ts.map +1 -0
  212. package/dist/modules/tasks/TaskLinkService.js +56 -0
  213. package/dist/modules/tasks/TaskLinkService.js.map +1 -0
  214. package/dist/modules/tasks/github-issues.logic.d.ts +35 -0
  215. package/dist/modules/tasks/github-issues.logic.d.ts.map +1 -0
  216. package/dist/modules/tasks/github-issues.logic.js +67 -0
  217. package/dist/modules/tasks/github-issues.logic.js.map +1 -0
  218. package/dist/modules/tasks/jira.logic.d.ts +28 -0
  219. package/dist/modules/tasks/jira.logic.d.ts.map +1 -0
  220. package/dist/modules/tasks/jira.logic.js +151 -0
  221. package/dist/modules/tasks/jira.logic.js.map +1 -0
  222. package/dist/modules/tasks/tasks.logic.d.ts +12 -0
  223. package/dist/modules/tasks/tasks.logic.d.ts.map +1 -0
  224. package/dist/modules/tasks/tasks.logic.js +17 -0
  225. package/dist/modules/tasks/tasks.logic.js.map +1 -0
  226. package/dist/modules/tracker/TicketTrackerService.d.ts +45 -0
  227. package/dist/modules/tracker/TicketTrackerService.d.ts.map +1 -0
  228. package/dist/modules/tracker/TicketTrackerService.js +52 -0
  229. package/dist/modules/tracker/TicketTrackerService.js.map +1 -0
  230. package/dist/modules/tracker/base64.d.ts +2 -0
  231. package/dist/modules/tracker/base64.d.ts.map +1 -0
  232. package/dist/modules/tracker/base64.js +18 -0
  233. package/dist/modules/tracker/base64.js.map +1 -0
  234. package/dist/modules/tracker/github.create.logic.d.ts +16 -0
  235. package/dist/modules/tracker/github.create.logic.d.ts.map +1 -0
  236. package/dist/modules/tracker/github.create.logic.js +25 -0
  237. package/dist/modules/tracker/github.create.logic.js.map +1 -0
  238. package/dist/modules/tracker/jira.create.logic.d.ts +31 -0
  239. package/dist/modules/tracker/jira.create.logic.d.ts.map +1 -0
  240. package/dist/modules/tracker/jira.create.logic.js +59 -0
  241. package/dist/modules/tracker/jira.create.logic.js.map +1 -0
  242. package/package.json +36 -0
@@ -0,0 +1,41 @@
1
+ import { requireWorkspace } from '@cat-factory/kernel';
2
+ import { defaultSlackSettings } from './slack.logic.js';
3
+ function toSettings(record) {
4
+ let routes = {};
5
+ try {
6
+ const parsed = JSON.parse(record.routesJson);
7
+ if (parsed && typeof parsed === 'object') {
8
+ routes = parsed;
9
+ }
10
+ }
11
+ catch {
12
+ routes = {};
13
+ }
14
+ return { routes, mentionsEnabled: record.mentionsEnabled, updatedAt: record.updatedAt };
15
+ }
16
+ export class SlackSettingsService {
17
+ deps;
18
+ constructor(deps) {
19
+ this.deps = deps;
20
+ }
21
+ /** A workspace's settings, falling back to the (no-op) defaults. */
22
+ async get(workspaceId) {
23
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
24
+ const record = await this.deps.slackSettingsRepository.getByWorkspace(workspaceId);
25
+ return record ? toSettings(record) : defaultSlackSettings(this.deps.clock.now());
26
+ }
27
+ /** Replace a workspace's routing settings. */
28
+ async update(workspaceId, input) {
29
+ await requireWorkspace(this.deps.workspaceRepository, workspaceId);
30
+ const updatedAt = this.deps.clock.now();
31
+ const record = {
32
+ workspaceId,
33
+ routesJson: JSON.stringify(input.routes),
34
+ mentionsEnabled: input.mentionsEnabled,
35
+ updatedAt,
36
+ };
37
+ await this.deps.slackSettingsRepository.upsert(record);
38
+ return { routes: input.routes, mentionsEnabled: input.mentionsEnabled, updatedAt };
39
+ }
40
+ }
41
+ //# sourceMappingURL=SlackSettingsService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlackSettingsService.js","sourceRoot":"","sources":["../../../src/modules/slack/SlackSettingsService.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAavD,SAAS,UAAU,CAAC,MAA2B;IAC7C,IAAI,MAAM,GAAwC,EAAE,CAAA;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAC5C,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACzC,MAAM,GAAG,MAA6C,CAAA;QACxD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,EAAE,CAAA;IACb,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAA;AACzF,CAAC;AAED,MAAM,OAAO,oBAAoB;IACF,IAAI;IAAjC,YAA6B,IAAsC;oBAAtC,IAAI;IAAqC,CAAC;IAEvE,oEAAoE;IACpE,KAAK,CAAC,GAAG,CAAC,WAAmB;QAC3B,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;QAClF,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;IAClF,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,MAAM,CACV,WAAmB,EACnB,KAA+B;QAE/B,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;QAClE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;QACvC,MAAM,MAAM,GAAwB;YAClC,WAAW;YACX,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;YACxC,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,SAAS;SACV,CAAA;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACtD,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,SAAS,EAAE,CAAA;IACpF,CAAC;CACF"}
@@ -0,0 +1,55 @@
1
+ import type { Notification, NotificationType, SlackMemberMappingEntry, SlackMemberRole, SlackNotificationSettings } from '@cat-factory/kernel';
2
+ /** HKDF domain-separation tag for the Slack bot-token cipher. */
3
+ export declare const SLACK_CIPHER_INFO = "cat-factory:slack";
4
+ /** The notification types Slack routing can target (mirrors the closed set). */
5
+ export declare const SLACK_ROUTABLE_TYPES: NotificationType[];
6
+ /** A mapping entry's role, defaulting to `engineering` when unset (legacy entries). */
7
+ export declare function resolveMemberRole(entry: SlackMemberMappingEntry): SlackMemberRole;
8
+ /**
9
+ * Who a notification @-mentions, by audience:
10
+ * - `roles` — every mapped member with one of these roles is mentioned.
11
+ * - `includeCreator`— also mention the task's creator (whoever they are).
12
+ *
13
+ * `requirement_review` is the product surface: product people are told to react to
14
+ * the findings, plus the creator. The engineering notifications target ONLY the
15
+ * creator — a build event is that person's to drive, not the whole workspace's (and
16
+ * product people, who don't care, are never pinged). A type with no policy mentions
17
+ * no one (still posts to its channel).
18
+ */
19
+ export interface MentionAudience {
20
+ roles: SlackMemberRole[];
21
+ includeCreator: boolean;
22
+ }
23
+ /** The mention audience for a notification type. */
24
+ export declare function mentionAudience(type: NotificationType): MentionAudience;
25
+ /**
26
+ * Resolve the Slack member ids to @-mention for a notification, given the account's
27
+ * member map and the (optional) GitHub id of the task creator. Members are matched
28
+ * by role; the creator is added when the audience calls for it AND they have a
29
+ * mapping. De-duplicated, preserving first-seen order (roles first, then creator).
30
+ */
31
+ export declare function resolveMentionTargets(type: NotificationType, mapping: SlackMemberMappingEntry[], creatorUserId: string | null | undefined): string[];
32
+ /**
33
+ * The default settings for a workspace that has never configured Slack: every
34
+ * type present but unrouted (empty channel) and disabled, mentions off. So a
35
+ * fresh workspace posts nothing until a human sets a channel.
36
+ */
37
+ export declare function defaultSlackSettings(updatedAt: number): SlackNotificationSettings;
38
+ /**
39
+ * Resolve the channel a notification should post to, or null when it must not
40
+ * post (no settings, type missing/disabled, or empty channel).
41
+ */
42
+ export declare function resolveRoute(settings: SlackNotificationSettings, type: NotificationType): string | null;
43
+ export interface SlackMessageBody {
44
+ channel: string;
45
+ text: string;
46
+ blocks: unknown[];
47
+ }
48
+ /**
49
+ * Render a notification into a Slack message. `mentions` are pre-resolved Slack
50
+ * member ids (already filtered to those configured); they are prefixed to the
51
+ * body as `<@id>` so the people are tagged. `text` is the notification fallback
52
+ * (for push/preview); `blocks` carry the rich layout.
53
+ */
54
+ export declare function renderNotificationMessage(notification: Notification, channel: string, mentions: string[]): SlackMessageBody;
55
+ //# sourceMappingURL=slack.logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/slack/slack.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,yBAAyB,EAE1B,MAAM,qBAAqB,CAAA;AAM5B,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,sBAAsB,CAAA;AAEpD,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,EAAE,gBAAgB,EAMlD,CAAA;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,eAAe,CAEjF;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,eAAe,EAAE,CAAA;IACxB,cAAc,EAAE,OAAO,CAAA;CACxB;AAeD,oDAAoD;AACpD,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,uBAAuB,EAAE,EAClC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,MAAM,EAAE,CAoBV;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,yBAAyB,CAUjF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,yBAAyB,EACnC,IAAI,EAAE,gBAAgB,GACrB,MAAM,GAAG,IAAI,CAKf;AAmBD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,OAAO,EAAE,CAAA;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAAE,GACjB,gBAAgB,CAwClB"}
@@ -0,0 +1,149 @@
1
+ // Pure helpers for the Slack notification transport: default settings, route
2
+ // resolution, audience/role targeting, and rendering a notification into a Slack
3
+ // `chat.postMessage` body. No I/O here — unit-testable and shared by both facades.
4
+ /** HKDF domain-separation tag for the Slack bot-token cipher. */
5
+ export const SLACK_CIPHER_INFO = 'cat-factory:slack';
6
+ /** The notification types Slack routing can target (mirrors the closed set). */
7
+ export const SLACK_ROUTABLE_TYPES = [
8
+ 'merge_review',
9
+ 'pipeline_complete',
10
+ 'ci_failed',
11
+ 'requirement_review',
12
+ 'release_regression',
13
+ ];
14
+ /** A mapping entry's role, defaulting to `engineering` when unset (legacy entries). */
15
+ export function resolveMemberRole(entry) {
16
+ return entry.role ?? 'engineering';
17
+ }
18
+ const MENTION_AUDIENCE = {
19
+ merge_review: { roles: [], includeCreator: true },
20
+ pipeline_complete: { roles: [], includeCreator: true },
21
+ ci_failed: { roles: [], includeCreator: true },
22
+ test_failed: { roles: [], includeCreator: true },
23
+ requirement_review: { roles: ['product'], includeCreator: true },
24
+ clarity_review: { roles: ['product'], includeCreator: true },
25
+ // A post-release regression is an operational event: tell the on-call engineers and
26
+ // the task's creator.
27
+ release_regression: { roles: ['engineering'], includeCreator: true },
28
+ decision_required: { roles: [], includeCreator: true },
29
+ };
30
+ /** The mention audience for a notification type. */
31
+ export function mentionAudience(type) {
32
+ return MENTION_AUDIENCE[type];
33
+ }
34
+ /**
35
+ * Resolve the Slack member ids to @-mention for a notification, given the account's
36
+ * member map and the (optional) GitHub id of the task creator. Members are matched
37
+ * by role; the creator is added when the audience calls for it AND they have a
38
+ * mapping. De-duplicated, preserving first-seen order (roles first, then creator).
39
+ */
40
+ export function resolveMentionTargets(type, mapping, creatorUserId) {
41
+ const audience = mentionAudience(type);
42
+ const ids = [];
43
+ const seen = new Set();
44
+ const add = (slackId) => {
45
+ if (!seen.has(slackId)) {
46
+ seen.add(slackId);
47
+ ids.push(slackId);
48
+ }
49
+ };
50
+ if (audience.roles.length > 0) {
51
+ for (const entry of mapping) {
52
+ if (audience.roles.includes(resolveMemberRole(entry)))
53
+ add(entry.slackUserId);
54
+ }
55
+ }
56
+ if (audience.includeCreator && creatorUserId != null) {
57
+ const creator = mapping.find((e) => e.userId === creatorUserId);
58
+ if (creator)
59
+ add(creator.slackUserId);
60
+ }
61
+ return ids;
62
+ }
63
+ /**
64
+ * The default settings for a workspace that has never configured Slack: every
65
+ * type present but unrouted (empty channel) and disabled, mentions off. So a
66
+ * fresh workspace posts nothing until a human sets a channel.
67
+ */
68
+ export function defaultSlackSettings(updatedAt) {
69
+ const routes = {};
70
+ for (const type of SLACK_ROUTABLE_TYPES) {
71
+ routes[type] = { enabled: false, channel: '' };
72
+ }
73
+ return {
74
+ routes: routes,
75
+ mentionsEnabled: false,
76
+ updatedAt,
77
+ };
78
+ }
79
+ /**
80
+ * Resolve the channel a notification should post to, or null when it must not
81
+ * post (no settings, type missing/disabled, or empty channel).
82
+ */
83
+ export function resolveRoute(settings, type) {
84
+ const route = settings.routes[type];
85
+ if (!route || !route.enabled)
86
+ return null;
87
+ const channel = route.channel.trim();
88
+ return channel.length > 0 ? channel : null;
89
+ }
90
+ /** A short per-type prefix so a Slack reader can triage at a glance. */
91
+ const TYPE_LABEL = {
92
+ merge_review: ':eyes: Merge review',
93
+ pipeline_complete: ':white_check_mark: Pipeline complete',
94
+ ci_failed: ':rotating_light: CI failed',
95
+ test_failed: ':rotating_light: Tests failed',
96
+ requirement_review: ':memo: Requirement review',
97
+ clarity_review: ':mag: Bug-report triage',
98
+ release_regression: ':rotating_light: Release regression',
99
+ decision_required: ':vertical_traffic_light: Decision needed',
100
+ };
101
+ /** Format a percentage from a 0..1 score for the assessment context line. */
102
+ function pct(score) {
103
+ return `${Math.round(score * 100)}%`;
104
+ }
105
+ /**
106
+ * Render a notification into a Slack message. `mentions` are pre-resolved Slack
107
+ * member ids (already filtered to those configured); they are prefixed to the
108
+ * body as `<@id>` so the people are tagged. `text` is the notification fallback
109
+ * (for push/preview); `blocks` carry the rich layout.
110
+ */
111
+ export function renderNotificationMessage(notification, channel, mentions) {
112
+ const label = TYPE_LABEL[notification.type];
113
+ const mentionPrefix = mentions.length ? `${mentions.map((id) => `<@${id}>`).join(' ')} ` : '';
114
+ const bodyLines = [`*${notification.title}*`];
115
+ if (notification.body)
116
+ bodyLines.push(notification.body);
117
+ const blocks = [
118
+ { type: 'section', text: { type: 'mrkdwn', text: `${label}` } },
119
+ { type: 'section', text: { type: 'mrkdwn', text: `${mentionPrefix}${bodyLines.join('\n')}` } },
120
+ ];
121
+ const contextElements = [];
122
+ const payload = notification.payload;
123
+ if (payload?.pipelineName) {
124
+ contextElements.push({ type: 'mrkdwn', text: `Pipeline: ${payload.pipelineName}` });
125
+ }
126
+ if (typeof payload?.findingCount === 'number') {
127
+ const n = payload.findingCount;
128
+ contextElements.push({ type: 'mrkdwn', text: `${n} open finding${n === 1 ? '' : 's'}` });
129
+ }
130
+ if (payload?.assessment) {
131
+ const a = payload.assessment;
132
+ contextElements.push({
133
+ type: 'mrkdwn',
134
+ text: `Complexity ${pct(a.complexity)} · Risk ${pct(a.risk)} · Impact ${pct(a.impact)}`,
135
+ });
136
+ }
137
+ if (payload?.prUrl) {
138
+ contextElements.push({ type: 'mrkdwn', text: `<${payload.prUrl}|View PR>` });
139
+ }
140
+ if (contextElements.length) {
141
+ blocks.push({ type: 'context', elements: contextElements });
142
+ }
143
+ return {
144
+ channel,
145
+ text: `${label}: ${notification.title}`,
146
+ blocks,
147
+ };
148
+ }
149
+ //# sourceMappingURL=slack.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.logic.js","sourceRoot":"","sources":["../../../src/modules/slack/slack.logic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { type GitHubClient, type GitHubInstallationRepository, type TaskContent, type TaskCredentials, type TaskSearchResult, type TaskSourceProvider, type NormalizedTaskConnection } from '@cat-factory/kernel';
2
+ export interface GitHubIssuesProviderDependencies {
3
+ githubClient: GitHubClient;
4
+ /** Resolves which installation owns a given repo owner (by account login). */
5
+ installations: GitHubInstallationRepository;
6
+ }
7
+ export declare class GitHubIssuesProvider implements TaskSourceProvider {
8
+ private readonly deps;
9
+ readonly kind: 'github';
10
+ readonly descriptor: {
11
+ source: "github" | "jira";
12
+ label: string;
13
+ icon: string;
14
+ credentialFields: {
15
+ key: string;
16
+ label: string;
17
+ help?: string | undefined;
18
+ placeholder?: string | undefined;
19
+ secret?: boolean | undefined;
20
+ }[];
21
+ refLabel: string;
22
+ refPlaceholder: string;
23
+ searchable?: boolean | undefined;
24
+ };
25
+ constructor(deps: GitHubIssuesProviderDependencies);
26
+ /**
27
+ * GitHub issues piggyback on the installed GitHub App, so there is nothing to
28
+ * validate or persist — the connection is a marker. Any supplied fields are
29
+ * ignored (the connect form has none).
30
+ */
31
+ normalizeConnection(_input: TaskCredentials): NormalizedTaskConnection;
32
+ parseRef(input: string): string | null;
33
+ fetchTask(_credentials: TaskCredentials, externalId: string): Promise<TaskContent>;
34
+ /**
35
+ * Search issues visible to *this workspace's* GitHub App installation. The
36
+ * installation token only sees its own account's repos, so scoping to the
37
+ * workspace's installation keeps results from leaking across tenants — a
38
+ * deployment may host many installations, but a workspace owns exactly one.
39
+ * Credentials are unused (the App authenticates), matching `fetchTask`.
40
+ */
41
+ search(_credentials: TaskCredentials, query: string, workspaceId: string): Promise<TaskSearchResult[]>;
42
+ /**
43
+ * Find the GitHub App installation whose account owns `owner`. The
44
+ * installation token for that account is what can read the repo's issues,
45
+ * regardless of which workspace triggered the import (one account → one
46
+ * installation, shared across that account's workspaces).
47
+ */
48
+ private resolveInstallationId;
49
+ }
50
+ //# sourceMappingURL=GitHubIssuesProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubIssuesProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/tasks/GitHubIssuesProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,4BAA4B,EACjC,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAA;AAiB5B,MAAM,WAAW,gCAAgC;IAC/C,YAAY,EAAE,YAAY,CAAA;IAC1B,8EAA8E;IAC9E,aAAa,EAAE,4BAA4B,CAAA;CAC5C;AAED,qBAAa,oBAAqB,YAAW,kBAAkB;IAIjD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;MAA2B;IAE9C,YAA6B,IAAI,EAAE,gCAAgC,EAAI;IAEvE;;;;OAIG;IACH,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,wBAAwB,CAErE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,SAAS,CAAC,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA0BvF;IAED;;;;;;OAMG;IACG,MAAM,CACV,YAAY,EAAE,eAAe,EAC7B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsB7B;IAED;;;;;OAKG;YACW,qBAAqB;CAUpC"}
@@ -0,0 +1,92 @@
1
+ import { ConflictError, ValidationError, } from '@cat-factory/kernel';
2
+ import { GITHUB_ISSUES_DESCRIPTOR } from './github-issues.logic.js';
3
+ import * as githubIssuesLogic from './github-issues.logic.js';
4
+ export class GitHubIssuesProvider {
5
+ deps;
6
+ kind = 'github';
7
+ descriptor = GITHUB_ISSUES_DESCRIPTOR;
8
+ constructor(deps) {
9
+ this.deps = deps;
10
+ }
11
+ /**
12
+ * GitHub issues piggyback on the installed GitHub App, so there is nothing to
13
+ * validate or persist — the connection is a marker. Any supplied fields are
14
+ * ignored (the connect form has none).
15
+ */
16
+ normalizeConnection(_input) {
17
+ return { credentials: {}, label: 'GitHub' };
18
+ }
19
+ parseRef(input) {
20
+ return githubIssuesLogic.parseGitHubIssueRef(input);
21
+ }
22
+ async fetchTask(_credentials, externalId) {
23
+ const id = githubIssuesLogic.parseGitHubIssueExternalId(externalId);
24
+ if (!id) {
25
+ throw new ValidationError(`"${externalId}" is not a valid GitHub issue reference`);
26
+ }
27
+ const installationId = await this.resolveInstallationId(id.owner);
28
+ const detail = await this.deps.githubClient.getIssue(installationId, { owner: id.owner, repo: id.repo }, id.number);
29
+ return {
30
+ externalId,
31
+ url: detail.url || githubIssuesLogic.githubIssueUrl(id),
32
+ title: detail.title,
33
+ // GitHub issues have no workflow status or type beyond open/closed; surface
34
+ // the state as the status and a constant type so the structured prompt
35
+ // rendering stays uniform across sources.
36
+ status: detail.state,
37
+ type: 'Issue',
38
+ assignee: detail.assignee,
39
+ priority: null,
40
+ labels: detail.labels,
41
+ description: detail.body,
42
+ comments: detail.comments,
43
+ };
44
+ }
45
+ /**
46
+ * Search issues visible to *this workspace's* GitHub App installation. The
47
+ * installation token only sees its own account's repos, so scoping to the
48
+ * workspace's installation keeps results from leaking across tenants — a
49
+ * deployment may host many installations, but a workspace owns exactly one.
50
+ * Credentials are unused (the App authenticates), matching `fetchTask`.
51
+ */
52
+ async search(_credentials, query, workspaceId) {
53
+ const installation = await this.deps.installations.getByWorkspace(workspaceId);
54
+ if (!installation)
55
+ return [];
56
+ const hits = await this.deps.githubClient
57
+ .searchIssues(installation.installationId, query, 20)
58
+ .catch(() => []);
59
+ const out = [];
60
+ const seen = new Set();
61
+ for (const hit of hits) {
62
+ const externalId = githubIssuesLogic.githubIssueExternalId(hit);
63
+ if (seen.has(externalId))
64
+ continue;
65
+ seen.add(externalId);
66
+ out.push({
67
+ source: 'github',
68
+ externalId,
69
+ title: hit.title,
70
+ url: hit.url,
71
+ status: hit.state,
72
+ excerpt: '',
73
+ });
74
+ }
75
+ return out.slice(0, 20);
76
+ }
77
+ /**
78
+ * Find the GitHub App installation whose account owns `owner`. The
79
+ * installation token for that account is what can read the repo's issues,
80
+ * regardless of which workspace triggered the import (one account → one
81
+ * installation, shared across that account's workspaces).
82
+ */
83
+ async resolveInstallationId(owner) {
84
+ const active = await this.deps.installations.listActive();
85
+ const match = active.find((i) => i.accountLogin.toLowerCase() === owner.toLowerCase());
86
+ if (!match) {
87
+ throw new ConflictError(`No GitHub App installation found for "${owner}". Install the GitHub App on that account to link its issues.`);
88
+ }
89
+ return match.installationId;
90
+ }
91
+ }
92
+ //# sourceMappingURL=GitHubIssuesProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubIssuesProvider.js","sourceRoot":"","sources":["../../../src/modules/tasks/GitHubIssuesProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type TaskContent, type TaskCredentials, type TaskSearchResult, type TaskSourceProvider, type NormalizedTaskConnection } from '@cat-factory/kernel';
2
+ /** Carries the HTTP status so callers can surface a meaningful error. */
3
+ export declare class JiraApiError extends Error {
4
+ readonly status: number;
5
+ constructor(status: number, message: string);
6
+ }
7
+ export declare class JiraProvider implements TaskSourceProvider {
8
+ readonly kind: 'jira';
9
+ readonly descriptor: {
10
+ source: "github" | "jira";
11
+ label: string;
12
+ icon: string;
13
+ credentialFields: {
14
+ key: string;
15
+ label: string;
16
+ help?: string | undefined;
17
+ placeholder?: string | undefined;
18
+ secret?: boolean | undefined;
19
+ }[];
20
+ refLabel: string;
21
+ refPlaceholder: string;
22
+ searchable?: boolean | undefined;
23
+ };
24
+ normalizeConnection(input: TaskCredentials): NormalizedTaskConnection;
25
+ parseRef(input: string): string | null;
26
+ fetchTask(credentials: TaskCredentials, externalId: string): Promise<TaskContent>;
27
+ search(credentials: TaskCredentials, query: string): Promise<TaskSearchResult[]>;
28
+ }
29
+ //# sourceMappingURL=JiraProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/tasks/JiraProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAA;AAkB5B,yEAAyE;AACzE,qBAAa,YAAa,SAAQ,KAAK;IAEnC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAIhB;CACF;AAsBD,qBAAa,YAAa,YAAW,kBAAkB;IACrD,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAS;IAC/B,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;MAAkB;IAErC,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,wBAAwB,CAepE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,SAAS,CAAC,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA4CtF;IAEK,MAAM,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6BrF;CACF"}
@@ -0,0 +1,114 @@
1
+ import { ValidationError, atlassianLogic, } from '@cat-factory/kernel';
2
+ import { JIRA_DESCRIPTOR } from './jira.logic.js';
3
+ import * as jiraLogic from './jira.logic.js';
4
+ // JiraProvider: the task-source provider for Jira Cloud. It authenticates with
5
+ // HTTP Basic (account email + API token, the same scheme as Confluence), fetches
6
+ // an issue via the REST v3 API, and maps it onto the structured TaskContent —
7
+ // converting the ADF description and comment bodies to the Markdown the generic
8
+ // excerpt/prompt logic consumes. All Jira-specific *pure* logic (ref parsing, ADF
9
+ // conversion) lives in `jira.logic` so it is unit-testable; this class is the thin
10
+ // `fetch` shell around it. No SDK — fetch + `btoa` suffice.
11
+ //
12
+ // Runtime-neutral: it depends only on the kernel ports + the shared pure logic and
13
+ // the global `fetch`/`btoa` (present on both runtimes), so the Cloudflare and the
14
+ // Node facade wire the SAME class (see CLAUDE.md "Keep the runtimes symmetric").
15
+ const USER_AGENT = 'cat-factory';
16
+ /** Carries the HTTP status so callers can surface a meaningful error. */
17
+ export class JiraApiError extends Error {
18
+ status;
19
+ constructor(status, message) {
20
+ super(message);
21
+ this.status = status;
22
+ this.name = 'JiraApiError';
23
+ }
24
+ }
25
+ export class JiraProvider {
26
+ kind = 'jira';
27
+ descriptor = JIRA_DESCRIPTOR;
28
+ normalizeConnection(input) {
29
+ const baseUrlRaw = input.baseUrl?.trim();
30
+ const accountEmail = input.accountEmail?.trim();
31
+ const apiToken = input.apiToken?.trim();
32
+ if (!baseUrlRaw || !accountEmail || !apiToken) {
33
+ throw new ValidationError('Jira requires a site URL, account email and API token');
34
+ }
35
+ const baseUrl = atlassianLogic.normalizeAtlassianBaseUrl(baseUrlRaw);
36
+ // Guard against SSRF: the stored base URL is later fetched with the
37
+ // workspace's credentials, so it must be a public https host.
38
+ atlassianLogic.assertSafeAtlassianBaseUrl(baseUrl);
39
+ return {
40
+ credentials: { baseUrl, accountEmail, apiToken },
41
+ label: baseUrl,
42
+ };
43
+ }
44
+ parseRef(input) {
45
+ return jiraLogic.parseJiraRef(input);
46
+ }
47
+ async fetchTask(credentials, externalId) {
48
+ const base = credentials.baseUrl.replace(/\/+$/, '');
49
+ const fields = 'summary,description,status,issuetype,assignee,priority,labels,comment';
50
+ const url = `${base}/rest/api/3/issue/${encodeURIComponent(externalId)}?fields=${fields}`;
51
+ const auth = btoa(`${credentials.accountEmail}:${credentials.apiToken}`);
52
+ const res = await fetch(url, {
53
+ method: 'GET',
54
+ headers: {
55
+ authorization: `Basic ${auth}`,
56
+ accept: 'application/json',
57
+ 'user-agent': USER_AGENT,
58
+ },
59
+ });
60
+ if (!res.ok) {
61
+ const text = await res.text().catch(() => '');
62
+ throw new JiraApiError(res.status, `Jira GET ${url} → ${res.status}: ${text.slice(0, 300)}`);
63
+ }
64
+ const json = (await res.json().catch(() => null));
65
+ if (!json || !json.key || !json.fields) {
66
+ throw new JiraApiError(502, `Jira returned an unexpected body for issue ${externalId}`);
67
+ }
68
+ const f = json.fields;
69
+ const comments = (f.comment?.comments ?? []).map((c) => ({
70
+ author: c.author?.displayName ?? '',
71
+ createdAt: c.created ?? '',
72
+ body: jiraLogic.adfToMarkdown(c.body),
73
+ }));
74
+ return {
75
+ externalId: json.key,
76
+ url: `${base}/browse/${json.key}`,
77
+ title: f.summary ?? '(untitled)',
78
+ status: f.status?.name ?? '',
79
+ type: f.issuetype?.name ?? '',
80
+ assignee: f.assignee?.displayName ?? null,
81
+ priority: f.priority?.name ?? null,
82
+ labels: Array.isArray(f.labels) ? f.labels : [],
83
+ description: jiraLogic.adfToMarkdown(f.description),
84
+ comments,
85
+ };
86
+ }
87
+ async search(credentials, query) {
88
+ const base = credentials.baseUrl.replace(/\/+$/, '');
89
+ // Re-validate the stored base before fetching with the workspace's credentials
90
+ // (defense-in-depth against a base that became unsafe since connect time).
91
+ atlassianLogic.assertSafeAtlassianBaseUrl(base);
92
+ const jql = encodeURIComponent(jiraLogic.buildJiraSearchJql(query));
93
+ // `/rest/api/3/search/jql` is the current enhanced-search endpoint; the legacy
94
+ // GET `/rest/api/3/search` was removed by Atlassian (May 2025). The `issues[]`
95
+ // response shape is unchanged, so `parseJiraSearchResults` still applies.
96
+ const url = `${base}/rest/api/3/search/jql?jql=${jql}&fields=summary,status&maxResults=20`;
97
+ const auth = btoa(`${credentials.accountEmail}:${credentials.apiToken}`);
98
+ const res = await fetch(url, {
99
+ method: 'GET',
100
+ headers: {
101
+ authorization: `Basic ${auth}`,
102
+ accept: 'application/json',
103
+ 'user-agent': USER_AGENT,
104
+ },
105
+ });
106
+ if (!res.ok) {
107
+ const text = await res.text().catch(() => '');
108
+ throw new JiraApiError(res.status, `Jira search ${url} → ${res.status}: ${text.slice(0, 300)}`);
109
+ }
110
+ const json = await res.json().catch(() => null);
111
+ return jiraLogic.parseJiraSearchResults(json, base);
112
+ }
113
+ }
114
+ //# sourceMappingURL=JiraProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraProvider.js","sourceRoot":"","sources":["../../../src/modules/tasks/JiraProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { Clock } from '@cat-factory/kernel';
2
+ import type { TaskConnectionRecord, TaskConnectionRepository } from '@cat-factory/kernel';
3
+ import type { TaskSourceRegistry } from '@cat-factory/kernel';
4
+ import type { TaskConnection, TaskSourceDescriptor, TaskSourceKind } from '@cat-factory/kernel';
5
+ import type { WorkspaceRepository } from '@cat-factory/kernel';
6
+ export interface TaskConnectionServiceDependencies {
7
+ taskConnectionRepository: TaskConnectionRepository;
8
+ registry: TaskSourceRegistry;
9
+ workspaceRepository: WorkspaceRepository;
10
+ clock: Clock;
11
+ }
12
+ export declare class TaskConnectionService {
13
+ private readonly deps;
14
+ constructor(deps: TaskConnectionServiceDependencies);
15
+ /** The descriptors of every configured source (drives the connect UI). */
16
+ listSources(): TaskSourceDescriptor[];
17
+ /** Resolve a provider for a source or throw if that source isn't configured. */
18
+ private requireProvider;
19
+ /** Connect (or re-connect) a workspace to a task source. */
20
+ connect(workspaceId: string, source: TaskSourceKind, credentials: Record<string, string>): Promise<TaskConnection>;
21
+ /** The workspace's current connection for a source, or null if not connected. */
22
+ getConnection(workspaceId: string, source: TaskSourceKind): Promise<TaskConnection | null>;
23
+ /** Every live connection the workspace holds, across sources. */
24
+ listConnections(workspaceId: string): Promise<TaskConnection[]>;
25
+ /** Resolve the live connection (with credentials) or throw if not connected. */
26
+ requireConnection(workspaceId: string, source: TaskSourceKind): Promise<TaskConnectionRecord>;
27
+ /** Disconnect a workspace from a source (tombstones the binding). */
28
+ disconnect(workspaceId: string, source: TaskSourceKind): Promise<void>;
29
+ }
30
+ //# sourceMappingURL=TaskConnectionService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskConnectionService.d.ts","sourceRoot":"","sources":["../../../src/modules/tasks/TaskConnectionService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AACzF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAG/F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAQ9D,MAAM,WAAW,iCAAiC;IAChD,wBAAwB,EAAE,wBAAwB,CAAA;IAClD,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,KAAK,EAAE,KAAK,CAAA;CACb;AAUD,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,iCAAiC,EAAI;IAExE,0EAA0E;IAC1E,WAAW,IAAI,oBAAoB,EAAE,CAEpC;IAED,gFAAgF;IAChF,OAAO,CAAC,eAAe;IAMvB,4DAA4D;IACtD,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,cAAc,CAAC,CAezB;IAED,iFAAiF;IAC3E,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAG/F;IAED,iEAAiE;IAC3D,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGpE;IAED,gFAAgF;IAC1E,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,oBAAoB,CAAC,CAM/B;IAED,qEAAqE;IAC/D,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;CACF"}