@cat-factory/kernel 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 (318) hide show
  1. package/LICENSE +21 -0
  2. package/dist/domain/catalog.d.ts +36 -0
  3. package/dist/domain/catalog.d.ts.map +1 -0
  4. package/dist/domain/catalog.js +55 -0
  5. package/dist/domain/catalog.js.map +1 -0
  6. package/dist/domain/errors.d.ts +57 -0
  7. package/dist/domain/errors.d.ts.map +1 -0
  8. package/dist/domain/errors.js +60 -0
  9. package/dist/domain/errors.js.map +1 -0
  10. package/dist/domain/models.d.ts +204 -0
  11. package/dist/domain/models.d.ts.map +1 -0
  12. package/dist/domain/models.js +522 -0
  13. package/dist/domain/models.js.map +1 -0
  14. package/dist/domain/pipeline-registry.d.ts +19 -0
  15. package/dist/domain/pipeline-registry.d.ts.map +1 -0
  16. package/dist/domain/pipeline-registry.js +48 -0
  17. package/dist/domain/pipeline-registry.js.map +1 -0
  18. package/dist/domain/seed.d.ts +14 -0
  19. package/dist/domain/seed.d.ts.map +1 -0
  20. package/dist/domain/seed.js +369 -0
  21. package/dist/domain/seed.js.map +1 -0
  22. package/dist/domain/service-registration.d.ts +31 -0
  23. package/dist/domain/service-registration.d.ts.map +1 -0
  24. package/dist/domain/service-registration.js +37 -0
  25. package/dist/domain/service-registration.js.map +1 -0
  26. package/dist/domain/subtasks.logic.d.ts +6 -0
  27. package/dist/domain/subtasks.logic.d.ts.map +1 -0
  28. package/dist/domain/subtasks.logic.js +20 -0
  29. package/dist/domain/subtasks.logic.js.map +1 -0
  30. package/dist/domain/types.d.ts +2 -0
  31. package/dist/domain/types.d.ts.map +1 -0
  32. package/dist/domain/types.js +2 -0
  33. package/dist/domain/types.js.map +1 -0
  34. package/dist/index.d.ts +16 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +21 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/ports/account-repositories.d.ts +46 -0
  39. package/dist/ports/account-repositories.d.ts.map +1 -0
  40. package/dist/ports/account-repositories.js +2 -0
  41. package/dist/ports/account-repositories.js.map +1 -0
  42. package/dist/ports/agent-executor.d.ts +361 -0
  43. package/dist/ports/agent-executor.d.ts.map +1 -0
  44. package/dist/ports/agent-executor.js +8 -0
  45. package/dist/ports/agent-executor.js.map +1 -0
  46. package/dist/ports/agent-runs.d.ts +28 -0
  47. package/dist/ports/agent-runs.d.ts.map +1 -0
  48. package/dist/ports/agent-runs.js +2 -0
  49. package/dist/ports/agent-runs.js.map +1 -0
  50. package/dist/ports/board-operations.d.ts +15 -0
  51. package/dist/ports/board-operations.d.ts.map +1 -0
  52. package/dist/ports/board-operations.js +2 -0
  53. package/dist/ports/board-operations.js.map +1 -0
  54. package/dist/ports/board-scan-repositories.d.ts +23 -0
  55. package/dist/ports/board-scan-repositories.d.ts.map +1 -0
  56. package/dist/ports/board-scan-repositories.js +2 -0
  57. package/dist/ports/board-scan-repositories.js.map +1 -0
  58. package/dist/ports/bootstrap-repositories.d.ts +71 -0
  59. package/dist/ports/bootstrap-repositories.d.ts.map +1 -0
  60. package/dist/ports/bootstrap-repositories.js +2 -0
  61. package/dist/ports/bootstrap-repositories.js.map +1 -0
  62. package/dist/ports/bootstrap-runner.d.ts +20 -0
  63. package/dist/ports/bootstrap-runner.d.ts.map +1 -0
  64. package/dist/ports/bootstrap-runner.js +12 -0
  65. package/dist/ports/bootstrap-runner.js.map +1 -0
  66. package/dist/ports/ci-status.d.ts +23 -0
  67. package/dist/ports/ci-status.d.ts.map +1 -0
  68. package/dist/ports/ci-status.js +8 -0
  69. package/dist/ports/ci-status.js.map +1 -0
  70. package/dist/ports/clarity-review-repositories.d.ts +12 -0
  71. package/dist/ports/clarity-review-repositories.d.ts.map +1 -0
  72. package/dist/ports/clarity-review-repositories.js +2 -0
  73. package/dist/ports/clarity-review-repositories.js.map +1 -0
  74. package/dist/ports/consensus-repositories.d.ts +12 -0
  75. package/dist/ports/consensus-repositories.d.ts.map +1 -0
  76. package/dist/ports/consensus-repositories.js +2 -0
  77. package/dist/ports/consensus-repositories.js.map +1 -0
  78. package/dist/ports/document-repositories.d.ts +55 -0
  79. package/dist/ports/document-repositories.d.ts.map +1 -0
  80. package/dist/ports/document-repositories.js +2 -0
  81. package/dist/ports/document-repositories.js.map +1 -0
  82. package/dist/ports/document-source.d.ts +55 -0
  83. package/dist/ports/document-source.d.ts.map +1 -0
  84. package/dist/ports/document-source.js +2 -0
  85. package/dist/ports/document-source.js.map +1 -0
  86. package/dist/ports/email-sender.d.ts +42 -0
  87. package/dist/ports/email-sender.d.ts.map +1 -0
  88. package/dist/ports/email-sender.js +7 -0
  89. package/dist/ports/email-sender.js.map +1 -0
  90. package/dist/ports/environment-provider.d.ts +67 -0
  91. package/dist/ports/environment-provider.d.ts.map +1 -0
  92. package/dist/ports/environment-provider.js +2 -0
  93. package/dist/ports/environment-provider.js.map +1 -0
  94. package/dist/ports/environment-repositories.d.ts +64 -0
  95. package/dist/ports/environment-repositories.d.ts.map +1 -0
  96. package/dist/ports/environment-repositories.js +2 -0
  97. package/dist/ports/environment-repositories.js.map +1 -0
  98. package/dist/ports/execution-events.d.ts +72 -0
  99. package/dist/ports/execution-events.d.ts.map +1 -0
  100. package/dist/ports/execution-events.js +16 -0
  101. package/dist/ports/execution-events.js.map +1 -0
  102. package/dist/ports/fragment-repositories.d.ts +65 -0
  103. package/dist/ports/fragment-repositories.d.ts.map +1 -0
  104. package/dist/ports/fragment-repositories.js +2 -0
  105. package/dist/ports/fragment-repositories.js.map +1 -0
  106. package/dist/ports/fragment-selector.d.ts +64 -0
  107. package/dist/ports/fragment-selector.d.ts.map +1 -0
  108. package/dist/ports/fragment-selector.js +2 -0
  109. package/dist/ports/fragment-selector.js.map +1 -0
  110. package/dist/ports/github-client.d.ts +226 -0
  111. package/dist/ports/github-client.d.ts.map +1 -0
  112. package/dist/ports/github-client.js +2 -0
  113. package/dist/ports/github-client.js.map +1 -0
  114. package/dist/ports/github-provisioning.d.ts +47 -0
  115. package/dist/ports/github-provisioning.d.ts.map +1 -0
  116. package/dist/ports/github-provisioning.js +12 -0
  117. package/dist/ports/github-provisioning.js.map +1 -0
  118. package/dist/ports/github-repositories.d.ts +136 -0
  119. package/dist/ports/github-repositories.d.ts.map +1 -0
  120. package/dist/ports/github-repositories.js +2 -0
  121. package/dist/ports/github-repositories.js.map +1 -0
  122. package/dist/ports/incident-enrichment.d.ts +40 -0
  123. package/dist/ports/incident-enrichment.d.ts.map +1 -0
  124. package/dist/ports/incident-enrichment.js +30 -0
  125. package/dist/ports/incident-enrichment.js.map +1 -0
  126. package/dist/ports/index.d.ts +68 -0
  127. package/dist/ports/index.d.ts.map +1 -0
  128. package/dist/ports/index.js +11 -0
  129. package/dist/ports/index.js.map +1 -0
  130. package/dist/ports/invitation-repositories.d.ts +28 -0
  131. package/dist/ports/invitation-repositories.d.ts.map +1 -0
  132. package/dist/ports/invitation-repositories.js +2 -0
  133. package/dist/ports/invitation-repositories.js.map +1 -0
  134. package/dist/ports/llm-metrics.d.ts +142 -0
  135. package/dist/ports/llm-metrics.d.ts.map +1 -0
  136. package/dist/ports/llm-metrics.js +16 -0
  137. package/dist/ports/llm-metrics.js.map +1 -0
  138. package/dist/ports/llm-trace-sink.d.ts +84 -0
  139. package/dist/ports/llm-trace-sink.d.ts.map +1 -0
  140. package/dist/ports/llm-trace-sink.js +55 -0
  141. package/dist/ports/llm-trace-sink.js.map +1 -0
  142. package/dist/ports/local-model-repositories.d.ts +29 -0
  143. package/dist/ports/local-model-repositories.d.ts.map +1 -0
  144. package/dist/ports/local-model-repositories.js +2 -0
  145. package/dist/ports/local-model-repositories.js.map +1 -0
  146. package/dist/ports/merge-preset-repositories.d.ts +14 -0
  147. package/dist/ports/merge-preset-repositories.d.ts.map +1 -0
  148. package/dist/ports/merge-preset-repositories.js +2 -0
  149. package/dist/ports/merge-preset-repositories.js.map +1 -0
  150. package/dist/ports/model-default-repositories.d.ts +9 -0
  151. package/dist/ports/model-default-repositories.d.ts.map +1 -0
  152. package/dist/ports/model-default-repositories.js +6 -0
  153. package/dist/ports/model-default-repositories.js.map +1 -0
  154. package/dist/ports/model-provider.d.ts +69 -0
  155. package/dist/ports/model-provider.d.ts.map +1 -0
  156. package/dist/ports/model-provider.js +16 -0
  157. package/dist/ports/model-provider.js.map +1 -0
  158. package/dist/ports/notification-channel.d.ts +16 -0
  159. package/dist/ports/notification-channel.d.ts.map +1 -0
  160. package/dist/ports/notification-channel.js +22 -0
  161. package/dist/ports/notification-channel.js.map +1 -0
  162. package/dist/ports/notification-repositories.d.ts +15 -0
  163. package/dist/ports/notification-repositories.d.ts.map +1 -0
  164. package/dist/ports/notification-repositories.js +2 -0
  165. package/dist/ports/notification-repositories.js.map +1 -0
  166. package/dist/ports/password-hasher.d.ts +14 -0
  167. package/dist/ports/password-hasher.d.ts.map +1 -0
  168. package/dist/ports/password-hasher.js +9 -0
  169. package/dist/ports/password-hasher.js.map +1 -0
  170. package/dist/ports/personal-secret-cipher.d.ts +7 -0
  171. package/dist/ports/personal-secret-cipher.d.ts.map +1 -0
  172. package/dist/ports/personal-secret-cipher.js +12 -0
  173. package/dist/ports/personal-secret-cipher.js.map +1 -0
  174. package/dist/ports/personal-subscription-repositories.d.ts +72 -0
  175. package/dist/ports/personal-subscription-repositories.d.ts.map +1 -0
  176. package/dist/ports/personal-subscription-repositories.js +2 -0
  177. package/dist/ports/personal-subscription-repositories.js.map +1 -0
  178. package/dist/ports/pr-mergeability.d.ts +24 -0
  179. package/dist/ports/pr-mergeability.d.ts.map +1 -0
  180. package/dist/ports/pr-mergeability.js +7 -0
  181. package/dist/ports/pr-mergeability.js.map +1 -0
  182. package/dist/ports/pr-merger.d.ts +10 -0
  183. package/dist/ports/pr-merger.d.ts.map +1 -0
  184. package/dist/ports/pr-merger.js +8 -0
  185. package/dist/ports/pr-merger.js.map +1 -0
  186. package/dist/ports/provider-api-key-repositories.d.ts +71 -0
  187. package/dist/ports/provider-api-key-repositories.d.ts.map +1 -0
  188. package/dist/ports/provider-api-key-repositories.js +15 -0
  189. package/dist/ports/provider-api-key-repositories.js.map +1 -0
  190. package/dist/ports/provider-subscription-repositories.d.ts +51 -0
  191. package/dist/ports/provider-subscription-repositories.d.ts.map +1 -0
  192. package/dist/ports/provider-subscription-repositories.js +15 -0
  193. package/dist/ports/provider-subscription-repositories.js.map +1 -0
  194. package/dist/ports/recurring-repositories.d.ts +46 -0
  195. package/dist/ports/recurring-repositories.d.ts.map +1 -0
  196. package/dist/ports/recurring-repositories.js +2 -0
  197. package/dist/ports/recurring-repositories.js.map +1 -0
  198. package/dist/ports/release-health-repositories.d.ts +42 -0
  199. package/dist/ports/release-health-repositories.d.ts.map +1 -0
  200. package/dist/ports/release-health-repositories.js +6 -0
  201. package/dist/ports/release-health-repositories.js.map +1 -0
  202. package/dist/ports/release-health.d.ts +59 -0
  203. package/dist/ports/release-health.d.ts.map +1 -0
  204. package/dist/ports/release-health.js +8 -0
  205. package/dist/ports/release-health.js.map +1 -0
  206. package/dist/ports/repo-bootstrapper.d.ts +80 -0
  207. package/dist/ports/repo-bootstrapper.d.ts.map +1 -0
  208. package/dist/ports/repo-bootstrapper.js +2 -0
  209. package/dist/ports/repo-bootstrapper.js.map +1 -0
  210. package/dist/ports/repo-scanner.d.ts +22 -0
  211. package/dist/ports/repo-scanner.d.ts.map +1 -0
  212. package/dist/ports/repo-scanner.js +2 -0
  213. package/dist/ports/repo-scanner.js.map +1 -0
  214. package/dist/ports/repositories.d.ts +131 -0
  215. package/dist/ports/repositories.d.ts.map +1 -0
  216. package/dist/ports/repositories.js +2 -0
  217. package/dist/ports/repositories.js.map +1 -0
  218. package/dist/ports/requirement-review-repositories.d.ts +16 -0
  219. package/dist/ports/requirement-review-repositories.d.ts.map +1 -0
  220. package/dist/ports/requirement-review-repositories.js +2 -0
  221. package/dist/ports/requirement-review-repositories.js.map +1 -0
  222. package/dist/ports/runner-pool-provider.d.ts +25 -0
  223. package/dist/ports/runner-pool-provider.d.ts.map +1 -0
  224. package/dist/ports/runner-pool-provider.js +2 -0
  225. package/dist/ports/runner-pool-provider.js.map +1 -0
  226. package/dist/ports/runner-pool-repositories.d.ts +27 -0
  227. package/dist/ports/runner-pool-repositories.d.ts.map +1 -0
  228. package/dist/ports/runner-pool-repositories.js +7 -0
  229. package/dist/ports/runner-pool-repositories.js.map +1 -0
  230. package/dist/ports/runner-transport.d.ts +119 -0
  231. package/dist/ports/runner-transport.d.ts.map +1 -0
  232. package/dist/ports/runner-transport.js +2 -0
  233. package/dist/ports/runner-transport.js.map +1 -0
  234. package/dist/ports/runtime.d.ts +9 -0
  235. package/dist/ports/runtime.d.ts.map +1 -0
  236. package/dist/ports/runtime.js +5 -0
  237. package/dist/ports/runtime.js.map +1 -0
  238. package/dist/ports/sandbox-repositories.d.ts +39 -0
  239. package/dist/ports/sandbox-repositories.d.ts.map +1 -0
  240. package/dist/ports/sandbox-repositories.js +2 -0
  241. package/dist/ports/sandbox-repositories.js.map +1 -0
  242. package/dist/ports/secret-cipher.d.ts +7 -0
  243. package/dist/ports/secret-cipher.d.ts.map +1 -0
  244. package/dist/ports/secret-cipher.js +7 -0
  245. package/dist/ports/secret-cipher.js.map +1 -0
  246. package/dist/ports/service-fragment-default-repositories.d.ts +7 -0
  247. package/dist/ports/service-fragment-default-repositories.d.ts.map +1 -0
  248. package/dist/ports/service-fragment-default-repositories.js +6 -0
  249. package/dist/ports/service-fragment-default-repositories.js.map +1 -0
  250. package/dist/ports/service-repositories.d.ts +68 -0
  251. package/dist/ports/service-repositories.d.ts.map +1 -0
  252. package/dist/ports/service-repositories.js +2 -0
  253. package/dist/ports/service-repositories.js.map +1 -0
  254. package/dist/ports/slack-repositories.d.ts +61 -0
  255. package/dist/ports/slack-repositories.d.ts.map +1 -0
  256. package/dist/ports/slack-repositories.js +2 -0
  257. package/dist/ports/slack-repositories.js.map +1 -0
  258. package/dist/ports/task-repositories.d.ts +61 -0
  259. package/dist/ports/task-repositories.d.ts.map +1 -0
  260. package/dist/ports/task-repositories.js +2 -0
  261. package/dist/ports/task-repositories.js.map +1 -0
  262. package/dist/ports/task-source.d.ts +69 -0
  263. package/dist/ports/task-source.d.ts.map +1 -0
  264. package/dist/ports/task-source.js +2 -0
  265. package/dist/ports/task-source.js.map +1 -0
  266. package/dist/ports/ticket-tracker.d.ts +19 -0
  267. package/dist/ports/ticket-tracker.d.ts.map +1 -0
  268. package/dist/ports/ticket-tracker.js +8 -0
  269. package/dist/ports/ticket-tracker.js.map +1 -0
  270. package/dist/ports/token-usage.d.ts +37 -0
  271. package/dist/ports/token-usage.d.ts.map +1 -0
  272. package/dist/ports/token-usage.js +6 -0
  273. package/dist/ports/token-usage.js.map +1 -0
  274. package/dist/ports/tracker-settings-repositories.d.ts +6 -0
  275. package/dist/ports/tracker-settings-repositories.d.ts.map +1 -0
  276. package/dist/ports/tracker-settings-repositories.js +2 -0
  277. package/dist/ports/tracker-settings-repositories.js.map +1 -0
  278. package/dist/ports/url-safety-policy.d.ts +15 -0
  279. package/dist/ports/url-safety-policy.d.ts.map +1 -0
  280. package/dist/ports/url-safety-policy.js +13 -0
  281. package/dist/ports/url-safety-policy.js.map +1 -0
  282. package/dist/ports/user-repositories.d.ts +52 -0
  283. package/dist/ports/user-repositories.d.ts.map +1 -0
  284. package/dist/ports/user-repositories.js +13 -0
  285. package/dist/ports/user-repositories.js.map +1 -0
  286. package/dist/ports/webhook-verifier.d.ts +9 -0
  287. package/dist/ports/webhook-verifier.d.ts.map +1 -0
  288. package/dist/ports/webhook-verifier.js +8 -0
  289. package/dist/ports/webhook-verifier.js.map +1 -0
  290. package/dist/ports/work-runner.d.ts +19 -0
  291. package/dist/ports/work-runner.d.ts.map +1 -0
  292. package/dist/ports/work-runner.js +19 -0
  293. package/dist/ports/work-runner.js.map +1 -0
  294. package/dist/ports/workspace-settings-repositories.d.ts +8 -0
  295. package/dist/ports/workspace-settings-repositories.d.ts.map +1 -0
  296. package/dist/ports/workspace-settings-repositories.js +2 -0
  297. package/dist/ports/workspace-settings-repositories.js.map +1 -0
  298. package/dist/shared/atlassian.logic.d.ts +11 -0
  299. package/dist/shared/atlassian.logic.d.ts.map +1 -0
  300. package/dist/shared/atlassian.logic.js +148 -0
  301. package/dist/shared/atlassian.logic.js.map +1 -0
  302. package/dist/shared/markdown.logic.d.ts +5 -0
  303. package/dist/shared/markdown.logic.d.ts.map +1 -0
  304. package/dist/shared/markdown.logic.js +21 -0
  305. package/dist/shared/markdown.logic.js.map +1 -0
  306. package/dist/shared/source-registry.logic.d.ts +10 -0
  307. package/dist/shared/source-registry.logic.d.ts.map +1 -0
  308. package/dist/shared/source-registry.logic.js +17 -0
  309. package/dist/shared/source-registry.logic.js.map +1 -0
  310. package/dist/shared/tasks-prompt.logic.d.ts +16 -0
  311. package/dist/shared/tasks-prompt.logic.d.ts.map +1 -0
  312. package/dist/shared/tasks-prompt.logic.js +29 -0
  313. package/dist/shared/tasks-prompt.logic.js.map +1 -0
  314. package/dist/workspace-guard.d.ts +4 -0
  315. package/dist/workspace-guard.d.ts.map +1 -0
  316. package/dist/workspace-guard.js +5 -0
  317. package/dist/workspace-guard.js.map +1 -0
  318. package/package.json +32 -0
@@ -0,0 +1,37 @@
1
+ /** One metered LLM call. `costEstimate` is in the deployment's spend currency. */
2
+ export interface TokenUsageRecord {
3
+ id: string;
4
+ workspaceId: string;
5
+ executionId: string | null;
6
+ agentKind: string;
7
+ provider: string;
8
+ model: string;
9
+ inputTokens: number;
10
+ outputTokens: number;
11
+ /** Estimated cost of this call, priced at record time so history is stable. */
12
+ costEstimate: number;
13
+ /** When the call was metered (epoch ms). */
14
+ createdAt: number;
15
+ }
16
+ /** Aggregated usage over a time window, used to evaluate the budget. */
17
+ export interface TokenUsageTotals {
18
+ inputTokens: number;
19
+ outputTokens: number;
20
+ costEstimate: number;
21
+ }
22
+ export interface TokenUsageRepository {
23
+ /** Append a metered call. */
24
+ record(usage: TokenUsageRecord): Promise<void>;
25
+ /**
26
+ * Sum usage across all workspaces since `epochMs` (inclusive). The budget is
27
+ * org-wide, so this deliberately spans every workspace.
28
+ */
29
+ totalsSince(epochMs: number): Promise<TokenUsageTotals>;
30
+ /**
31
+ * Retention: delete rows older than `epochMs` (exclusive), returning how many
32
+ * were removed. The budget query only reads the current period, so pruning old
33
+ * history caps this append-only ledger without affecting spend gating.
34
+ */
35
+ deleteOlderThan(epochMs: number): Promise<number>;
36
+ }
37
+ //# sourceMappingURL=token-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../../src/ports/token-usage.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wEAAwE;AACxE,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,6BAA6B;IAC7B,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACvD;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CAClD"}
@@ -0,0 +1,6 @@
1
+ // Persistence port for the spend safeguard. Every LLM call's token usage is
2
+ // recorded here; the SpendService aggregates it over the current billing period
3
+ // to decide whether the configured budget has been exhausted. The domain
4
+ // depends only on this interface — the worker implements it against D1.
5
+ export {};
6
+ //# sourceMappingURL=token-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-usage.js","sourceRoot":"","sources":["../../src/ports/token-usage.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,gFAAgF;AAChF,yEAAyE;AACzE,wEAAwE"}
@@ -0,0 +1,6 @@
1
+ import type { TrackerSettings } from '../domain/types.js';
2
+ export interface TrackerSettingsRepository {
3
+ get(workspaceId: string): Promise<TrackerSettings | null>;
4
+ put(workspaceId: string, settings: TrackerSettings): Promise<void>;
5
+ }
6
+ //# sourceMappingURL=tracker-settings-repositories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker-settings-repositories.d.ts","sourceRoot":"","sources":["../../src/ports/tracker-settings-repositories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAMzD,MAAM,WAAW,yBAAyB;IACxC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAA;IACzD,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tracker-settings-repositories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker-settings-repositories.js","sourceRoot":"","sources":["../../src/ports/tracker-settings-repositories.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ export interface UrlSafetyPolicy {
2
+ /** Permitted URL schemes, lowercased, without the trailing colon (e.g. ['https']). */
3
+ schemes: readonly string[];
4
+ /**
5
+ * Hostnames exempt from the private/internal-host block. Each entry matches the URL
6
+ * hostname case-insensitively: an exact match (`kargo.corp`, `10.1.2.3`), or a dot
7
+ * suffix when it starts with `.` (`.internal` matches `a.b.internal`). An exempt host
8
+ * bypasses the loopback / link-local / RFC1918 / `.internal` / `.local` checks. Empty
9
+ * => no exemptions (the strict default).
10
+ */
11
+ allowHosts: readonly string[];
12
+ }
13
+ /** The default policy: https only, no private/internal hosts, no exemptions. */
14
+ export declare const STRICT_URL_SAFETY_POLICY: UrlSafetyPolicy;
15
+ //# sourceMappingURL=url-safety-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-safety-policy.d.ts","sourceRoot":"","sources":["../../src/ports/url-safety-policy.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B;;;;;;OAMG;IACH,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B;AAED,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAA"}
@@ -0,0 +1,13 @@
1
+ // Policy controlling which URLs an integration may fetch or expose. The default
2
+ // (STRICT_URL_SAFETY_POLICY) forbids non-https and every private/internal host,
3
+ // which is correct for an untrusted, manifest-described management API supplied by
4
+ // an arbitrary workspace. An operator running a TRUSTED in-house adapter (e.g. an
5
+ // internal ephemeral-environment platform reachable only on a private/VPN host) can
6
+ // widen it via the facade config to permit specific schemes/hosts. Shared by the
7
+ // environment-provisioning and runner-pool integrations.
8
+ /** The default policy: https only, no private/internal hosts, no exemptions. */
9
+ export const STRICT_URL_SAFETY_POLICY = {
10
+ schemes: ['https'],
11
+ allowHosts: [],
12
+ };
13
+ //# sourceMappingURL=url-safety-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-safety-policy.js","sourceRoot":"","sources":["../../src/ports/url-safety-policy.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,gFAAgF;AAChF,mFAAmF;AACnF,kFAAkF;AAClF,oFAAoF;AACpF,iFAAiF;AACjF,yDAAyD;AAezD,gFAAgF;AAChF,MAAM,CAAC,MAAM,wBAAwB,GAAoB;IACvD,OAAO,EAAE,CAAC,OAAO,CAAC;IAClB,UAAU,EAAE,EAAE;CACf,CAAA"}
@@ -0,0 +1,52 @@
1
+ /** The login providers an identity can come from. */
2
+ export type IdentityProvider = 'github' | 'password' | 'google';
3
+ /** The canonical user record. */
4
+ export interface UserRecord {
5
+ /** Generated `usr_*` id — the stable identity everything else references. */
6
+ id: string;
7
+ name: string | null;
8
+ /** Primary email (unique when present). Null for a GitHub-only user with no public email. */
9
+ email: string | null;
10
+ avatarUrl: string | null;
11
+ createdAt: number;
12
+ }
13
+ /**
14
+ * A linked login identity for a user. The pair `(provider, subject)` is unique —
15
+ * one external identity maps to exactly one user.
16
+ */
17
+ export interface UserIdentityRecord {
18
+ userId: string;
19
+ provider: IdentityProvider;
20
+ /**
21
+ * The provider's stable subject: the GitHub numeric id (as a string), the Google
22
+ * `sub`, or the lowercased email for a `password` identity.
23
+ */
24
+ subject: string;
25
+ /** PHC-format password hash for `provider: 'password'`; null otherwise. */
26
+ secret: string | null;
27
+ /** Provider-specific JSON metadata (github `{login, avatarUrl}`, google `{email}`). */
28
+ metadata: string | null;
29
+ createdAt: number;
30
+ }
31
+ export interface UserRepository {
32
+ get(id: string): Promise<UserRecord | null>;
33
+ create(user: UserRecord): Promise<void>;
34
+ update(id: string, patch: Partial<Pick<UserRecord, 'name' | 'email' | 'avatarUrl'>>): Promise<void>;
35
+ /** The user behind a linked identity, or null. */
36
+ findByIdentity(provider: IdentityProvider, subject: string): Promise<UserRecord | null>;
37
+ /**
38
+ * The user owning a primary email (case-insensitive), or null. Lets a verified
39
+ * second login provider (or password signup) attach to / be rejected against the
40
+ * existing person instead of colliding on the unique email index.
41
+ */
42
+ findByEmail(email: string): Promise<UserRecord | null>;
43
+ /** Bulk-load users by id (the member-roster enrichment; order not guaranteed). */
44
+ listByIds(ids: string[]): Promise<UserRecord[]>;
45
+ /** The raw identity row (carries the password `secret`), or null. */
46
+ getIdentity(provider: IdentityProvider, subject: string): Promise<UserIdentityRecord | null>;
47
+ /** Link an external identity to a user (idempotent on `(provider, subject)`). */
48
+ linkIdentity(identity: UserIdentityRecord): Promise<void>;
49
+ /** Every identity linked to a user. */
50
+ listIdentities(userId: string): Promise<UserIdentityRecord[]>;
51
+ }
52
+ //# sourceMappingURL=user-repositories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-repositories.d.ts","sourceRoot":"","sources":["../../src/ports/user-repositories.ts"],"names":[],"mappings":"AAYA,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAA;AAE/D,iCAAiC;AACjC,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,6FAA6F;IAC7F,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,gBAAgB,CAAA;IAC1B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,uFAAuF;IACvF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAC3C,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC,CAAC,GAC/D,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,kDAAkD;IAClD,cAAc,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IACvF;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IACtD,kFAAkF;IAClF,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;IAC/C,qEAAqE;IACrE,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAA;IAC5F,iFAAiF;IACjF,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,uCAAuC;IACvC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAA;CAC9D"}
@@ -0,0 +1,13 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Persistence ports for the user-identity layer. A `users` row is the canonical,
3
+ // runtime-neutral identity (generated `usr_*` id) that everything else keys off
4
+ // (memberships, block authorship, personal subscriptions). It is decoupled from
5
+ // GitHub: a user may sign in with GitHub, email/password, and/or Google, and each
6
+ // of those is a row in `user_identities` linked back to the same user.
7
+ //
8
+ // This is what lets a person without a GitHub account exist in the system — repo
9
+ // access is via the GitHub *App* installation token (system-level), never the
10
+ // user's own GitHub OAuth token, so a non-GitHub user can still read/write repos.
11
+ // ---------------------------------------------------------------------------
12
+ export {};
13
+ //# sourceMappingURL=user-repositories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-repositories.js","sourceRoot":"","sources":["../../src/ports/user-repositories.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,kFAAkF;AAClF,uEAAuE;AACvE,EAAE;AACF,iFAAiF;AACjF,8EAA8E;AAC9E,kFAAkF;AAClF,8EAA8E"}
@@ -0,0 +1,9 @@
1
+ export interface WebhookVerifier {
2
+ /**
3
+ * Verify `signatureHeader` (the raw `X-Hub-Signature-256` value, e.g.
4
+ * `sha256=...`) against the raw request body. Returns false for a missing or
5
+ * mismatched signature rather than throwing.
6
+ */
7
+ verify(rawBody: ArrayBuffer, signatureHeader: string | null): Promise<boolean>;
8
+ }
9
+ //# sourceMappingURL=webhook-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-verifier.d.ts","sourceRoot":"","sources":["../../src/ports/webhook-verifier.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC/E"}
@@ -0,0 +1,8 @@
1
+ // Port for verifying inbound GitHub webhook signatures. GitHub signs each
2
+ // delivery with HMAC-SHA-256 over the raw request body using the App's webhook
3
+ // secret, sending the digest in the `X-Hub-Signature-256` header. The worker
4
+ // implements this with Web Crypto (`crypto.subtle`); modelling it as a port keeps
5
+ // the WebhookService free of any crypto/runtime concern and lets tests toggle
6
+ // pass/fail with a fake.
7
+ export {};
8
+ //# sourceMappingURL=webhook-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-verifier.js","sourceRoot":"","sources":["../../src/ports/webhook-verifier.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,+EAA+E;AAC/E,6EAA6E;AAC7E,kFAAkF;AAClF,8EAA8E;AAC9E,yBAAyB"}
@@ -0,0 +1,19 @@
1
+ export interface WorkRunner {
2
+ /** Begin durable execution of a run. Idempotent on `executionId`. */
3
+ startRun(workspaceId: string, executionId: string): Promise<void>;
4
+ /** Signal a resolved decision to a parked run so it can continue. */
5
+ signalDecision(workspaceId: string, executionId: string, decisionId: string, choice: string): Promise<void>;
6
+ /** Best-effort cancel of the durable run. */
7
+ cancelRun(workspaceId: string, executionId: string): Promise<void>;
8
+ }
9
+ /**
10
+ * The default runner: it does nothing. With it wired, starting a run hands off to
11
+ * nobody — the integration tests rely on this and advance runs directly via
12
+ * `advanceInstance`.
13
+ */
14
+ export declare class NoopWorkRunner implements WorkRunner {
15
+ startRun(): Promise<void>;
16
+ signalDecision(): Promise<void>;
17
+ cancelRun(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=work-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-runner.d.ts","sourceRoot":"","sources":["../../src/ports/work-runner.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,qEAAqE;IACrE,cAAc,CACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAAA;IAChB,6CAA6C;IAC7C,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE;AAED;;;;GAIG;AACH,qBAAa,cAAe,YAAW,UAAU;IACzC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;IAC5B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;IAClC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG;CACpC"}
@@ -0,0 +1,19 @@
1
+ // Port for driving a run *durably* outside the request that started it. The
2
+ // execution engine calls this to hand a run off to a background worker (in the
3
+ // Cloudflare facade, a Workflows instance) so progress proceeds server-side
4
+ // without a browser open. Modelling it as a port keeps the engine free of any
5
+ // Cloudflare/Workflows concern. Concrete implementations:
6
+ // - NoopWorkRunner — the default; does nothing (tests advance runs directly)
7
+ // - WorkflowsWorkRunner — creates/signals a Cloudflare Workflows instance
8
+ // All methods must be idempotent on `executionId` so a retry or replay is safe.
9
+ /**
10
+ * The default runner: it does nothing. With it wired, starting a run hands off to
11
+ * nobody — the integration tests rely on this and advance runs directly via
12
+ * `advanceInstance`.
13
+ */
14
+ export class NoopWorkRunner {
15
+ async startRun() { }
16
+ async signalDecision() { }
17
+ async cancelRun() { }
18
+ }
19
+ //# sourceMappingURL=work-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work-runner.js","sourceRoot":"","sources":["../../src/ports/work-runner.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAC9E,0DAA0D;AAC1D,qFAAqF;AACrF,6EAA6E;AAC7E,gFAAgF;AAgBhF;;;;GAIG;AACH,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,QAAQ,KAAmB,CAAC;IAClC,KAAK,CAAC,cAAc,KAAmB,CAAC;IACxC,KAAK,CAAC,SAAS,KAAmB,CAAC;CACpC"}
@@ -0,0 +1,8 @@
1
+ import type { WorkspaceSettings } from '../domain/types.js';
2
+ export interface WorkspaceSettingsRepository {
3
+ /** A workspace's settings, or null if none have been persisted yet (caller seeds the default). */
4
+ get(workspaceId: string): Promise<WorkspaceSettings | null>;
5
+ /** Create or replace a workspace's settings. */
6
+ upsert(workspaceId: string, settings: WorkspaceSettings): Promise<void>;
7
+ }
8
+ //# sourceMappingURL=workspace-settings-repositories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-settings-repositories.d.ts","sourceRoot":"","sources":["../../src/ports/workspace-settings-repositories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAO3D,MAAM,WAAW,2BAA2B;IAC1C,kGAAkG;IAClG,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IAC3D,gDAAgD;IAChD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACxE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=workspace-settings-repositories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-settings-repositories.js","sourceRoot":"","sources":["../../src/ports/workspace-settings-repositories.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ /** Drop a trailing slash and a trailing `/wiki` so we can build paths uniformly. */
2
+ export declare function normalizeAtlassianBaseUrl(baseUrl: string): string;
3
+ /**
4
+ * Validate a (normalized) Atlassian base URL before it is stored and later
5
+ * fetched. Requires `https`, forbids embedded credentials, and rejects
6
+ * internal/private hosts. Throws {@link ValidationError} on anything unsafe.
7
+ *
8
+ * Parsed by hand (no `URL` global) so this stays in the platform-agnostic core.
9
+ */
10
+ export declare function assertSafeAtlassianBaseUrl(baseUrl: string): void;
11
+ //# sourceMappingURL=atlassian.logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atlassian.logic.d.ts","sourceRoot":"","sources":["../../src/shared/atlassian.logic.ts"],"names":[],"mappings":"AAQA,oFAAoF;AACpF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKjE;AA2FD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyBhE"}
@@ -0,0 +1,148 @@
1
+ import { ValidationError } from '../domain/errors.js';
2
+ // Shared, source-agnostic handling of an Atlassian Cloud site base URL, used by
3
+ // every provider that fetches `${baseUrl}/...` with a workspace's Basic-auth
4
+ // credentials (Confluence pages, Jira issues, …). Normalizing and SSRF-guarding
5
+ // the stored base URL lives here so each provider's pure logic delegates to one
6
+ // vetted implementation rather than copying it.
7
+ /** Drop a trailing slash and a trailing `/wiki` so we can build paths uniformly. */
8
+ export function normalizeAtlassianBaseUrl(baseUrl) {
9
+ return baseUrl
10
+ .trim()
11
+ .replace(/\/+$/, '')
12
+ .replace(/\/wiki$/i, '');
13
+ }
14
+ /** Whether a decoded IPv4 address is loopback / link-local (metadata) / RFC1918. */
15
+ function isPrivateV4(parts) {
16
+ const [a, b] = parts;
17
+ if (a === 127 || a === 0 || a === 10)
18
+ return true;
19
+ if (a === 169 && b === 254)
20
+ return true;
21
+ if (a === 192 && b === 168)
22
+ return true;
23
+ if (a === 172 && b >= 16 && b <= 31)
24
+ return true;
25
+ return false;
26
+ }
27
+ /** Parse a plain dotted-decimal IPv4 literal (each octet 0-255), or null. */
28
+ function decimalV4(host) {
29
+ const m = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
30
+ if (!m)
31
+ return null;
32
+ const a = Number(m[1]);
33
+ const b = Number(m[2]);
34
+ const c = Number(m[3]);
35
+ const d = Number(m[4]);
36
+ if (a > 255 || b > 255 || c > 255 || d > 255)
37
+ return null;
38
+ return [a, b, c, d];
39
+ }
40
+ /** Extract the embedded IPv4 of an IPv4-mapped IPv6 literal (`::ffff:…`), or null. */
41
+ function mappedV4(host) {
42
+ // ::ffff:a.b.c.d
43
+ const dotted = host.match(/^::ffff:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
44
+ if (dotted) {
45
+ const a = Number(dotted[1]);
46
+ const b = Number(dotted[2]);
47
+ const c = Number(dotted[3]);
48
+ const d = Number(dotted[4]);
49
+ if (a > 255 || b > 255 || c > 255 || d > 255)
50
+ return null;
51
+ return [a, b, c, d];
52
+ }
53
+ // ::ffff:hhhh:hhhh
54
+ const hex = host.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
55
+ if (hex) {
56
+ const hi = parseInt(hex[1] ?? '0', 16);
57
+ const lo = parseInt(hex[2] ?? '0', 16);
58
+ return [(hi >> 8) & 0xff, hi & 0xff, (lo >> 8) & 0xff, lo & 0xff];
59
+ }
60
+ return null;
61
+ }
62
+ /**
63
+ * Reject hostnames that point at the worker's own network rather than a public
64
+ * Atlassian Cloud site. A provider fetches `${baseUrl}/...` with the workspace's
65
+ * Basic-auth credentials, so an unvalidated base URL turns the worker into an
66
+ * SSRF proxy (and leaks the API token to an internal host). This is host-literal
67
+ * defence-in-depth — it does not stop DNS rebinding, but blocks the obvious
68
+ * internal targets (loopback, link-local/metadata, RFC1918) including the
69
+ * obfuscated encodings (bare integer, hex/octal octets, IPv4-mapped IPv6) that
70
+ * trivially bypass a naive dotted-decimal match.
71
+ */
72
+ function isBlockedAtlassianHost(hostname) {
73
+ const host = hostname.toLowerCase().replace(/^\[|\]$/g, '');
74
+ if (host === '')
75
+ return true;
76
+ if (host === 'localhost' || host.endsWith('.localhost'))
77
+ return true;
78
+ if (host.endsWith('.internal') || host.endsWith('.local'))
79
+ return true;
80
+ // IPv6 loopback / link-local / unique-local, plus IPv4-mapped IPv6.
81
+ if (host.includes(':')) {
82
+ if (host === '::1' || host === '::')
83
+ return true;
84
+ if (host.startsWith('fe80:') || host.startsWith('fc') || host.startsWith('fd'))
85
+ return true;
86
+ const mapped = mappedV4(host);
87
+ if (mapped)
88
+ return isPrivateV4(mapped);
89
+ return false;
90
+ }
91
+ // Obfuscated numeric IPv4 forms are never a legitimate public hostname.
92
+ // Bare integer (e.g. 2130706433 === 127.0.0.1).
93
+ if (/^\d+$/.test(host))
94
+ return true;
95
+ const labels = host.split('.');
96
+ for (const label of labels) {
97
+ if (/^0x[0-9a-f]+$/.test(label))
98
+ return true; // hex octet (0x7f)
99
+ if (/^0[0-9]+$/.test(label))
100
+ return true; // octal / leading-zero octet (0177)
101
+ }
102
+ // Standard dotted-decimal IPv4: public addresses pass, private ones blocked.
103
+ const v4 = decimalV4(host);
104
+ if (v4)
105
+ return isPrivateV4(v4);
106
+ // A purely numeric dotted host that is not a valid public dotted-decimal IPv4
107
+ // is some other IP encoding we cannot vouch for — reject when in doubt.
108
+ if (labels.length > 1 && labels.every((l) => /^\d+$/.test(l)))
109
+ return true;
110
+ return false;
111
+ }
112
+ /**
113
+ * Validate a (normalized) Atlassian base URL before it is stored and later
114
+ * fetched. Requires `https`, forbids embedded credentials, and rejects
115
+ * internal/private hosts. Throws {@link ValidationError} on anything unsafe.
116
+ *
117
+ * Parsed by hand (no `URL` global) so this stays in the platform-agnostic core.
118
+ */
119
+ export function assertSafeAtlassianBaseUrl(baseUrl) {
120
+ const invalid = () => new ValidationError(`Atlassian base URL is not a valid URL: '${baseUrl}'`);
121
+ const match = baseUrl.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/([^/?#]*)/);
122
+ if (!match)
123
+ throw invalid();
124
+ if (match[1].toLowerCase() !== 'https') {
125
+ throw new ValidationError('Atlassian base URL must use https');
126
+ }
127
+ const authority = match[2];
128
+ if (authority.includes('@')) {
129
+ throw new ValidationError('Atlassian base URL must not contain credentials');
130
+ }
131
+ // Drop an optional `:port`, handling a bracketed IPv6 literal (`[::1]:8443`).
132
+ let host;
133
+ if (authority.startsWith('[')) {
134
+ const end = authority.indexOf(']');
135
+ if (end === -1)
136
+ throw invalid();
137
+ host = authority.slice(1, end);
138
+ }
139
+ else {
140
+ host = authority.split(':')[0];
141
+ }
142
+ if (host === '')
143
+ throw invalid();
144
+ if (isBlockedAtlassianHost(host)) {
145
+ throw new ValidationError('Atlassian base URL must be a public host');
146
+ }
147
+ }
148
+ //# sourceMappingURL=atlassian.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atlassian.logic.js","sourceRoot":"","sources":["../../src/shared/atlassian.logic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Strip lightweight Markdown markers into collapsed plain text. */
2
+ export declare function markdownToText(markdown: string): string;
3
+ /** A short plain-text excerpt of a Markdown body, for list/preview rendering. */
4
+ export declare function buildExcerpt(markdown: string, max?: number): string;
5
+ //# sourceMappingURL=markdown.logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.logic.d.ts","sourceRoot":"","sources":["../../src/shared/markdown.logic.ts"],"names":[],"mappings":"AAKA,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CASvD;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAGhE"}
@@ -0,0 +1,21 @@
1
+ // Source-agnostic Markdown helpers shared by the integrations that normalize an
2
+ // external body to lightweight Markdown (document sources, task sources, …):
3
+ // collapsing the markers into plain text and deriving a short excerpt. Kept pure
4
+ // so they stay trivially testable and reusable across modules.
5
+ /** Strip lightweight Markdown markers into collapsed plain text. */
6
+ export function markdownToText(markdown) {
7
+ return markdown
8
+ .replace(/`{1,3}/g, '')
9
+ .replace(/^[ \t]*#{1,6}[ \t]+/gm, '')
10
+ .replace(/^[ \t]*[-*+][ \t]+/gm, '')
11
+ .replace(/[*_~>]/g, '')
12
+ .replace(/\[([^\]]*)\]\([^)]*\)/g, '$1')
13
+ .replace(/\s+/g, ' ')
14
+ .trim();
15
+ }
16
+ /** A short plain-text excerpt of a Markdown body, for list/preview rendering. */
17
+ export function buildExcerpt(markdown, max = 280) {
18
+ const text = markdownToText(markdown);
19
+ return text.length > max ? `${text.slice(0, max - 1).trimEnd()}…` : text;
20
+ }
21
+ //# sourceMappingURL=markdown.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.logic.js","sourceRoot":"","sources":["../../src/shared/markdown.logic.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,6EAA6E;AAC7E,iFAAiF;AACjF,+DAA+D;AAE/D,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,OAAO,QAAQ;SACZ,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC;SACpC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC;SACnC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC;SACvC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAA;AACX,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,GAAG,GAAG,GAAG;IACtD,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACrC,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;AAC1E,CAAC"}
@@ -0,0 +1,10 @@
1
+ /** Generic by-kind provider registry: look a provider up by its `kind`, or list them all. */
2
+ export declare class MapSourceRegistry<K, P extends {
3
+ kind: K;
4
+ }> {
5
+ private readonly byKind;
6
+ constructor(providers: P[]);
7
+ get(kind: K): P | undefined;
8
+ list(): P[];
9
+ }
10
+ //# sourceMappingURL=source-registry.logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-registry.logic.d.ts","sourceRoot":"","sources":["../../src/shared/source-registry.logic.ts"],"names":[],"mappings":"AAIA,6FAA6F;AAC7F,qBAAa,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAElC,YAAY,SAAS,EAAE,CAAC,EAAE,EAEzB;IAED,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAE1B;IAED,IAAI,IAAI,CAAC,EAAE,CAEV;CACF"}
@@ -0,0 +1,17 @@
1
+ // A trivial in-memory provider registry built from the wired providers, keyed by
2
+ // each provider's `kind`. Shared by the document- and task-source integrations,
3
+ // which only differ in the provider/kind types they carry.
4
+ /** Generic by-kind provider registry: look a provider up by its `kind`, or list them all. */
5
+ export class MapSourceRegistry {
6
+ byKind;
7
+ constructor(providers) {
8
+ this.byKind = new Map(providers.map((p) => [p.kind, p]));
9
+ }
10
+ get(kind) {
11
+ return this.byKind.get(kind);
12
+ }
13
+ list() {
14
+ return [...this.byKind.values()];
15
+ }
16
+ }
17
+ //# sourceMappingURL=source-registry.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-registry.logic.js","sourceRoot":"","sources":["../../src/shared/source-registry.logic.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,gFAAgF;AAChF,2DAA2D;AAE3D,6FAA6F;AAC7F,MAAM,OAAO,iBAAiB;IACX,MAAM,CAAW;IAElC,YAAY,SAAc;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC;IAED,GAAG,CAAC,IAAO;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;IAClC,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { TaskComment } from '../domain/types.js';
2
+ /** The plain shape the prompt renderer consumes (decoupled from the ports). */
3
+ export interface TaskContextView {
4
+ key: string;
5
+ url: string;
6
+ title: string;
7
+ status: string;
8
+ type: string;
9
+ assignee: string | null;
10
+ priority: string | null;
11
+ labels: string[];
12
+ description: string;
13
+ comments: TaskComment[];
14
+ }
15
+ export declare function renderTaskContext(view: TaskContextView): string;
16
+ //# sourceMappingURL=tasks-prompt.logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks-prompt.logic.d.ts","sourceRoot":"","sources":["../../src/shared/tasks-prompt.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAKrD,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,WAAW,EAAE,CAAA;CACxB;AAUD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAc/D"}
@@ -0,0 +1,29 @@
1
+ import { buildExcerpt } from './markdown.logic.js';
2
+ const MAX_CONTEXT_COMMENTS = 5;
3
+ function metadataLine(view) {
4
+ const parts = [`Status: ${view.status || '(unknown)'}`, `Type: ${view.type || '(unknown)'}`];
5
+ if (view.assignee)
6
+ parts.push(`Assignee: ${view.assignee}`);
7
+ if (view.priority)
8
+ parts.push(`Priority: ${view.priority}`);
9
+ if (view.labels.length)
10
+ parts.push(`Labels: ${view.labels.join(', ')}`);
11
+ return parts.join(' · ');
12
+ }
13
+ export function renderTaskContext(view) {
14
+ const lines = [`### [${view.key}] ${view.title} (${view.url})`, metadataLine(view)];
15
+ const description = view.description.trim();
16
+ if (description)
17
+ lines.push('', description);
18
+ const recent = view.comments.slice(-MAX_CONTEXT_COMMENTS);
19
+ if (recent.length) {
20
+ lines.push('', 'Recent comments:');
21
+ for (const c of recent) {
22
+ const who = c.author || 'unknown';
23
+ const when = c.createdAt ? ` (${c.createdAt.slice(0, 10)})` : '';
24
+ lines.push(`- ${who}${when}: ${buildExcerpt(c.body, 200)}`);
25
+ }
26
+ }
27
+ return lines.join('\n');
28
+ }
29
+ //# sourceMappingURL=tasks-prompt.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks-prompt.logic.js","sourceRoot":"","sources":["../../src/shared/tasks-prompt.logic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAElD,MAAM,oBAAoB,GAAG,CAAC,CAAA;AAgB9B,SAAS,YAAY,CAAC,IAAqB;IACzC,MAAM,KAAK,GAAG,CAAC,WAAW,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,EAAE,SAAS,IAAI,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAA;IAC5F,IAAI,IAAI,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC3D,IAAI,IAAI,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC3D,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACvE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAqB;IACrD,MAAM,KAAK,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;IACnF,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAA;IAC3C,IAAI,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAA;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAAC,CAAA;IACzD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAA;QAClC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,IAAI,SAAS,CAAA;YACjC,MAAM,IAAI,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;YAChE,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { WorkspaceRepository } from './ports/repositories.js';
2
+ import type { Workspace } from './domain/types.js';
3
+ export declare function requireWorkspace(repository: WorkspaceRepository, id: string): Promise<Workspace>;
4
+ //# sourceMappingURL=workspace-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-guard.d.ts","sourceRoot":"","sources":["../src/workspace-guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElD,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,mBAAmB,EAC/B,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,SAAS,CAAC,CAEpB"}
@@ -0,0 +1,5 @@
1
+ import { assertFound } from './domain/errors.js';
2
+ export async function requireWorkspace(repository, id) {
3
+ return assertFound(await repository.get(id), 'Workspace', id);
4
+ }
5
+ //# sourceMappingURL=workspace-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-guard.js","sourceRoot":"","sources":["../src/workspace-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAIhD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAA+B,EAC/B,EAAU;IAEV,OAAO,WAAW,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;AAC/D,CAAC"}