devchain-cli 0.22.1 → 0.23.1

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 (249) hide show
  1. package/dist/drizzle/0077_familiar_morbius.sql +6 -0
  2. package/dist/drizzle/0078_preserve_legacy_connection_ownership.sql +180 -0
  3. package/dist/drizzle/0079_premium_forgotten_one.sql +18 -0
  4. package/dist/drizzle/0080_lethal_thunderbolt_ross.sql +49 -0
  5. package/dist/drizzle/0081_early_kronos.sql +58 -0
  6. package/dist/drizzle/0082_huge_black_queen.sql +14 -0
  7. package/dist/drizzle/meta/0077_snapshot.json +6957 -0
  8. package/dist/drizzle/meta/0078_snapshot.json +6957 -0
  9. package/dist/drizzle/meta/0079_snapshot.json +7093 -0
  10. package/dist/drizzle/meta/0080_snapshot.json +7241 -0
  11. package/dist/drizzle/meta/0081_snapshot.json +7482 -0
  12. package/dist/drizzle/meta/0082_snapshot.json +7571 -0
  13. package/dist/drizzle/meta/_journal.json +42 -0
  14. package/dist/node_modules/@devchain/shared/tsconfig.tsbuildinfo +1 -1
  15. package/dist/server/common/errors/error-types.d.ts +7 -0
  16. package/dist/server/common/errors/error-types.js +7 -1
  17. package/dist/server/common/errors/error-types.js.map +1 -1
  18. package/dist/server/modules/epic-time/controllers/agent-time-buffer.controller.d.ts +9 -0
  19. package/dist/server/modules/epic-time/controllers/agent-time-buffer.controller.js +90 -0
  20. package/dist/server/modules/epic-time/controllers/agent-time-buffer.controller.js.map +1 -0
  21. package/dist/server/modules/epic-time/controllers/external-estimate-log.controller.d.ts +12 -0
  22. package/dist/server/modules/epic-time/controllers/external-estimate-log.controller.js +322 -0
  23. package/dist/server/modules/epic-time/controllers/external-estimate-log.controller.js.map +1 -0
  24. package/dist/server/modules/epic-time/epic-time-store.module.d.ts +2 -0
  25. package/dist/server/modules/epic-time/epic-time-store.module.js +23 -0
  26. package/dist/server/modules/epic-time/epic-time-store.module.js.map +1 -0
  27. package/dist/server/modules/epic-time/epic-time.module.js +10 -6
  28. package/dist/server/modules/epic-time/epic-time.module.js.map +1 -1
  29. package/dist/server/modules/epic-time/models/epic-time-daily-allocator.d.ts +30 -0
  30. package/dist/server/modules/epic-time/models/epic-time-daily-allocator.js +125 -0
  31. package/dist/server/modules/epic-time/models/epic-time-daily-allocator.js.map +1 -0
  32. package/dist/server/modules/epic-time/models/epic-time-local-day.d.ts +9 -0
  33. package/dist/server/modules/epic-time/models/epic-time-local-day.js +164 -0
  34. package/dist/server/modules/epic-time/models/epic-time-local-day.js.map +1 -0
  35. package/dist/server/modules/epic-time/models/epic-time.models.d.ts +147 -0
  36. package/dist/server/modules/epic-time/models/epic-time.models.js +2 -0
  37. package/dist/server/modules/epic-time/models/epic-time.models.js.map +1 -1
  38. package/dist/server/modules/epic-time/services/agent-time-accounting.service.d.ts +1 -0
  39. package/dist/server/modules/epic-time/services/agent-time-accounting.service.js +31 -8
  40. package/dist/server/modules/epic-time/services/agent-time-accounting.service.js.map +1 -1
  41. package/dist/server/modules/epic-time/services/epic-estimate-logging.service.d.ts +37 -0
  42. package/dist/server/modules/epic-time/services/epic-estimate-logging.service.js +716 -0
  43. package/dist/server/modules/epic-time/services/epic-estimate-logging.service.js.map +1 -0
  44. package/dist/server/modules/epic-time/services/epic-time.service.d.ts +13 -3
  45. package/dist/server/modules/epic-time/services/epic-time.service.js +162 -69
  46. package/dist/server/modules/epic-time/services/epic-time.service.js.map +1 -1
  47. package/dist/server/modules/epic-time/services/epic-time.store.d.ts +50 -3
  48. package/dist/server/modules/epic-time/services/epic-time.store.js +705 -146
  49. package/dist/server/modules/epic-time/services/epic-time.store.js.map +1 -1
  50. package/dist/server/modules/epics/controllers/epics.controller.d.ts +10 -1
  51. package/dist/server/modules/epics/controllers/epics.controller.js +108 -2
  52. package/dist/server/modules/epics/controllers/epics.controller.js.map +1 -1
  53. package/dist/server/modules/epics/epics.module.js +8 -2
  54. package/dist/server/modules/epics/epics.module.js.map +1 -1
  55. package/dist/server/modules/epics/models/epic-relations.models.d.ts +34 -0
  56. package/dist/server/modules/epics/models/epic-relations.models.js +16 -0
  57. package/dist/server/modules/epics/models/epic-relations.models.js.map +1 -0
  58. package/dist/server/modules/epics/services/epic-relation-target-resolver.d.ts +8 -0
  59. package/dist/server/modules/epics/services/epic-relation-target-resolver.js +37 -0
  60. package/dist/server/modules/epics/services/epic-relation-target-resolver.js.map +1 -0
  61. package/dist/server/modules/epics/services/epic-relations.service.d.ts +52 -0
  62. package/dist/server/modules/epics/services/epic-relations.service.js +135 -0
  63. package/dist/server/modules/epics/services/epic-relations.service.js.map +1 -0
  64. package/dist/server/modules/epics/services/epics.service.d.ts +9 -2
  65. package/dist/server/modules/epics/services/epics.service.js +115 -11
  66. package/dist/server/modules/epics/services/epics.service.js.map +1 -1
  67. package/dist/server/modules/events/catalog/broadcast-registry.js +16 -0
  68. package/dist/server/modules/events/catalog/broadcast-registry.js.map +1 -1
  69. package/dist/server/modules/events/catalog/epic.relations.invalidated.d.ts +12 -0
  70. package/dist/server/modules/events/catalog/epic.relations.invalidated.js +13 -0
  71. package/dist/server/modules/events/catalog/epic.relations.invalidated.js.map +1 -0
  72. package/dist/server/modules/events/catalog/epic.time.scope.invalidated.d.ts +12 -0
  73. package/dist/server/modules/events/catalog/epic.time.scope.invalidated.js +13 -0
  74. package/dist/server/modules/events/catalog/epic.time.scope.invalidated.js.map +1 -0
  75. package/dist/server/modules/events/catalog/index.d.ts +27 -4
  76. package/dist/server/modules/events/catalog/index.js +6 -0
  77. package/dist/server/modules/events/catalog/index.js.map +1 -1
  78. package/dist/server/modules/events/catalog/integration.connection.created.d.ts +4 -1
  79. package/dist/server/modules/events/catalog/integration.connection.created.js +5 -2
  80. package/dist/server/modules/events/catalog/integration.connection.created.js.map +1 -1
  81. package/dist/server/modules/events/catalog/integration.connection.deleted.d.ts +4 -1
  82. package/dist/server/modules/events/catalog/integration.connection.deleted.js +5 -2
  83. package/dist/server/modules/events/catalog/integration.connection.deleted.js.map +1 -1
  84. package/dist/server/modules/events/catalog/integration.connection.legacy.d.ts +85 -0
  85. package/dist/server/modules/events/catalog/integration.connection.legacy.js +41 -0
  86. package/dist/server/modules/events/catalog/integration.connection.legacy.js.map +1 -0
  87. package/dist/server/modules/events/catalog/integration.connection.updated.d.ts +4 -1
  88. package/dist/server/modules/events/catalog/integration.connection.updated.js +5 -2
  89. package/dist/server/modules/events/catalog/integration.connection.updated.js.map +1 -1
  90. package/dist/server/modules/events/services/committed-event-replay.d.ts +10 -0
  91. package/dist/server/modules/events/services/committed-event-replay.js +30 -0
  92. package/dist/server/modules/events/services/committed-event-replay.js.map +1 -0
  93. package/dist/server/modules/events/services/committed-event.store.d.ts +1 -0
  94. package/dist/server/modules/events/services/committed-event.store.js +12 -7
  95. package/dist/server/modules/events/services/committed-event.store.js.map +1 -1
  96. package/dist/server/modules/events/services/durable-event-registry.service.d.ts +9 -2
  97. package/dist/server/modules/events/services/durable-event-registry.service.js.map +1 -1
  98. package/dist/server/modules/external-integrations/adapters/clickup-external-task.provider.d.ts +7 -0
  99. package/dist/server/modules/external-integrations/adapters/clickup-external-task.provider.js +158 -50
  100. package/dist/server/modules/external-integrations/adapters/clickup-external-task.provider.js.map +1 -1
  101. package/dist/server/modules/external-integrations/adapters/jira-external-task.provider.d.ts +4 -0
  102. package/dist/server/modules/external-integrations/adapters/jira-external-task.provider.js +73 -33
  103. package/dist/server/modules/external-integrations/adapters/jira-external-task.provider.js.map +1 -1
  104. package/dist/server/modules/external-integrations/connections/integration-connections.controller.d.ts +6 -3
  105. package/dist/server/modules/external-integrations/connections/integration-connections.controller.js +67 -12
  106. package/dist/server/modules/external-integrations/connections/integration-connections.controller.js.map +1 -1
  107. package/dist/server/modules/external-integrations/connections/integration-connections.service.d.ts +35 -3
  108. package/dist/server/modules/external-integrations/connections/integration-connections.service.js +178 -17
  109. package/dist/server/modules/external-integrations/connections/integration-connections.service.js.map +1 -1
  110. package/dist/server/modules/external-integrations/connections/managed-subtask-sync.controller.d.ts +6 -3
  111. package/dist/server/modules/external-integrations/connections/managed-subtask-sync.controller.js +51 -11
  112. package/dist/server/modules/external-integrations/connections/managed-subtask-sync.controller.js.map +1 -1
  113. package/dist/server/modules/external-integrations/external-integrations.module.js +6 -1
  114. package/dist/server/modules/external-integrations/external-integrations.module.js.map +1 -1
  115. package/dist/server/modules/external-integrations/models/external-edit-session.models.d.ts +1 -0
  116. package/dist/server/modules/external-integrations/models/external-provider.models.d.ts +6 -2
  117. package/dist/server/modules/external-integrations/models/external-provider.models.js +2 -3
  118. package/dist/server/modules/external-integrations/models/external-provider.models.js.map +1 -1
  119. package/dist/server/modules/external-integrations/models/external-time-mutation.models.d.ts +33 -2
  120. package/dist/server/modules/external-integrations/models/external-time-mutation.models.js +14 -0
  121. package/dist/server/modules/external-integrations/models/external-time-mutation.models.js.map +1 -1
  122. package/dist/server/modules/external-integrations/my-work/external-edit-session.service.d.ts +10 -9
  123. package/dist/server/modules/external-integrations/my-work/external-edit-session.service.js +81 -46
  124. package/dist/server/modules/external-integrations/my-work/external-edit-session.service.js.map +1 -1
  125. package/dist/server/modules/external-integrations/my-work/external-my-work.controller.d.ts +22 -20
  126. package/dist/server/modules/external-integrations/my-work/external-my-work.controller.js +136 -64
  127. package/dist/server/modules/external-integrations/my-work/external-my-work.controller.js.map +1 -1
  128. package/dist/server/modules/external-integrations/my-work/external-my-work.openapi.d.ts +7 -0
  129. package/dist/server/modules/external-integrations/my-work/external-my-work.openapi.js +289 -4
  130. package/dist/server/modules/external-integrations/my-work/external-my-work.openapi.js.map +1 -1
  131. package/dist/server/modules/external-integrations/my-work/external-my-work.service.d.ts +12 -7
  132. package/dist/server/modules/external-integrations/my-work/external-my-work.service.js +114 -54
  133. package/dist/server/modules/external-integrations/my-work/external-my-work.service.js.map +1 -1
  134. package/dist/server/modules/external-integrations/my-work/external-time-mutation.service.d.ts +19 -6
  135. package/dist/server/modules/external-integrations/my-work/external-time-mutation.service.js +346 -46
  136. package/dist/server/modules/external-integrations/my-work/external-time-mutation.service.js.map +1 -1
  137. package/dist/server/modules/external-integrations/sessions/external-edit-session.store.d.ts +2 -1
  138. package/dist/server/modules/external-integrations/sessions/external-edit-session.store.js +3 -2
  139. package/dist/server/modules/external-integrations/sessions/external-edit-session.store.js.map +1 -1
  140. package/dist/server/modules/external-integrations/sessions/external-time-mutation.store.d.ts +6 -1
  141. package/dist/server/modules/external-integrations/sessions/external-time-mutation.store.js +19 -0
  142. package/dist/server/modules/external-integrations/sessions/external-time-mutation.store.js.map +1 -1
  143. package/dist/server/modules/external-integrations/sessions/provider-operation-gate.d.ts +15 -2
  144. package/dist/server/modules/external-integrations/sessions/provider-operation-gate.js +33 -6
  145. package/dist/server/modules/external-integrations/sessions/provider-operation-gate.js.map +1 -1
  146. package/dist/server/modules/external-integrations/subscribers/external-subtask-sync.subscriber.d.ts +13 -6
  147. package/dist/server/modules/external-integrations/subscribers/external-subtask-sync.subscriber.js +212 -75
  148. package/dist/server/modules/external-integrations/subscribers/external-subtask-sync.subscriber.js.map +1 -1
  149. package/dist/server/modules/external-integrations/subscribers/managed-subtask-content.d.ts +13 -4
  150. package/dist/server/modules/external-integrations/subscribers/managed-subtask-content.js +98 -0
  151. package/dist/server/modules/external-integrations/subscribers/managed-subtask-content.js.map +1 -1
  152. package/dist/server/modules/external-integrations/subscribers/managed-subtask-sync-health.service.d.ts +10 -4
  153. package/dist/server/modules/external-integrations/subscribers/managed-subtask-sync-health.service.js +57 -18
  154. package/dist/server/modules/external-integrations/subscribers/managed-subtask-sync-health.service.js.map +1 -1
  155. package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +139 -0
  156. package/dist/server/modules/mcp/dtos/mcp.dto.js +41 -1
  157. package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
  158. package/dist/server/modules/mcp/services/handlers/epic-context.d.ts +2 -0
  159. package/dist/server/modules/mcp/services/handlers/epic-tools.d.ts +4 -0
  160. package/dist/server/modules/mcp/services/handlers/epic-tools.js +275 -0
  161. package/dist/server/modules/mcp/services/handlers/epic-tools.js.map +1 -1
  162. package/dist/server/modules/mcp/services/mcp-tool-binding.registry.d.ts +2 -1
  163. package/dist/server/modules/mcp/services/mcp-tool-binding.registry.js +13 -8
  164. package/dist/server/modules/mcp/services/mcp-tool-binding.registry.js.map +1 -1
  165. package/dist/server/modules/mcp/services/testing/mcp-tool-binding-registry.fixture.d.ts +1 -1
  166. package/dist/server/modules/mcp/services/testing/mcp-tool-binding-registry.fixture.js +1 -1
  167. package/dist/server/modules/mcp/services/testing/mcp-tool-binding-registry.fixture.js.map +1 -1
  168. package/dist/server/modules/mcp/tool-descriptors/binding-types.d.ts +2 -0
  169. package/dist/server/modules/mcp/tool-descriptors/binding-types.js.map +1 -1
  170. package/dist/server/modules/mcp/tool-descriptors/epic.bindings.js +6 -0
  171. package/dist/server/modules/mcp/tool-descriptors/epic.bindings.js.map +1 -1
  172. package/dist/server/modules/mcp/tool-descriptors/epic.metadata.js +132 -0
  173. package/dist/server/modules/mcp/tool-descriptors/epic.metadata.js.map +1 -1
  174. package/dist/server/modules/projects/controllers/projects.controller.js +1 -4
  175. package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
  176. package/dist/server/modules/projects/projects.module.js +2 -0
  177. package/dist/server/modules/projects/projects.module.js.map +1 -1
  178. package/dist/server/modules/projects/services/projects.service.d.ts +4 -1
  179. package/dist/server/modules/projects/services/projects.service.js +23 -2
  180. package/dist/server/modules/projects/services/projects.service.js.map +1 -1
  181. package/dist/server/modules/providers/adapters/claude.adapter.d.ts +4 -2
  182. package/dist/server/modules/providers/adapters/claude.adapter.js +31 -0
  183. package/dist/server/modules/providers/adapters/claude.adapter.js.map +1 -1
  184. package/dist/server/modules/providers/services/provider-mcp-ensure.service.d.ts +7 -0
  185. package/dist/server/modules/providers/services/provider-mcp-ensure.service.js +69 -4
  186. package/dist/server/modules/providers/services/provider-mcp-ensure.service.js.map +1 -1
  187. package/dist/server/modules/session-reader/data/pricing.json +452 -56
  188. package/dist/server/modules/session-reader/services/session-reader.service.d.ts +2 -0
  189. package/dist/server/modules/session-reader/services/session-reader.service.js +85 -9
  190. package/dist/server/modules/session-reader/services/session-reader.service.js.map +1 -1
  191. package/dist/server/modules/session-reader/services/transcript-path-validator.service.js +8 -2
  192. package/dist/server/modules/session-reader/services/transcript-path-validator.service.js.map +1 -1
  193. package/dist/server/modules/session-reader/services/transcript-watcher.service.js +44 -17
  194. package/dist/server/modules/session-reader/services/transcript-watcher.service.js.map +1 -1
  195. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.d.ts +1 -0
  196. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js +1 -0
  197. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js.map +1 -1
  198. package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js +11 -1
  199. package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js.map +1 -1
  200. package/dist/server/modules/sessions/services/sessions.service.d.ts +3 -1
  201. package/dist/server/modules/sessions/services/sessions.service.js +36 -6
  202. package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
  203. package/dist/server/modules/sessions/sessions.module.js +2 -0
  204. package/dist/server/modules/sessions/sessions.module.js.map +1 -1
  205. package/dist/server/modules/sessions/utils/claude-config.d.ts +4 -1
  206. package/dist/server/modules/sessions/utils/claude-config.js +265 -60
  207. package/dist/server/modules/sessions/utils/claude-config.js.map +1 -1
  208. package/dist/server/modules/storage/db/schema.d.ts +1109 -98
  209. package/dist/server/modules/storage/db/schema.js +141 -3
  210. package/dist/server/modules/storage/db/schema.js.map +1 -1
  211. package/dist/server/modules/storage/db/sqlite-json.d.ts +1 -0
  212. package/dist/server/modules/storage/db/sqlite-json.js +4 -0
  213. package/dist/server/modules/storage/db/sqlite-json.js.map +1 -1
  214. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +58 -10
  215. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  216. package/dist/server/modules/storage/local/delegates/epic.delegate.d.ts +30 -5
  217. package/dist/server/modules/storage/local/delegates/epic.delegate.js +718 -14
  218. package/dist/server/modules/storage/local/delegates/epic.delegate.js.map +1 -1
  219. package/dist/server/modules/storage/local/delegates/external-estimate-log.delegate.d.ts +52 -0
  220. package/dist/server/modules/storage/local/delegates/external-estimate-log.delegate.js +659 -0
  221. package/dist/server/modules/storage/local/delegates/external-estimate-log.delegate.js.map +1 -0
  222. package/dist/server/modules/storage/local/delegates/external-managed-subtask.delegate.d.ts +2 -1
  223. package/dist/server/modules/storage/local/delegates/external-managed-subtask.delegate.js +17 -4
  224. package/dist/server/modules/storage/local/delegates/external-managed-subtask.delegate.js.map +1 -1
  225. package/dist/server/modules/storage/local/delegates/integration.delegate.d.ts +23 -8
  226. package/dist/server/modules/storage/local/delegates/integration.delegate.js +238 -52
  227. package/dist/server/modules/storage/local/delegates/integration.delegate.js.map +1 -1
  228. package/dist/server/modules/storage/local/delegates/project.delegate.d.ts +2 -0
  229. package/dist/server/modules/storage/local/delegates/project.delegate.js +180 -130
  230. package/dist/server/modules/storage/local/delegates/project.delegate.js.map +1 -1
  231. package/dist/server/modules/storage/local/local-storage.service.d.ts +45 -10
  232. package/dist/server/modules/storage/local/local-storage.service.js +99 -15
  233. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  234. package/dist/server/modules/storage/models/domain.models.d.ts +170 -0
  235. package/dist/server/modules/storage/models/domain.models.js +9 -0
  236. package/dist/server/modules/storage/models/domain.models.js.map +1 -1
  237. package/dist/server/templates/teams-dev.json +311 -301
  238. package/dist/server/tsconfig.tsbuildinfo +1 -1
  239. package/dist/server/ui/assets/{ExternalRichEditor-DMtnZIMZ.js → ExternalRichEditor-FwCAalXO.js} +1 -1
  240. package/dist/server/ui/assets/{ReviewDetailPage-BmyiM5IR.js → ReviewDetailPage-D8DVpsJm.js} +1 -1
  241. package/dist/server/ui/assets/{ReviewsPage-CQ87BMwT.js → ReviewsPage-DcWpRFbm.js} +1 -1
  242. package/dist/server/ui/assets/index-CV8ydm7w.css +32 -0
  243. package/dist/server/ui/assets/index-Cwe7LxcW.js +1197 -0
  244. package/dist/server/ui/assets/{useReviewSubscription-DjbEUzt4.js → useReviewSubscription-CYoSg-88.js} +1 -1
  245. package/dist/server/ui/index.html +2 -2
  246. package/dist/templates/teams-dev.json +311 -301
  247. package/package.json +20 -2
  248. package/dist/server/ui/assets/index-BX6Yze-A.js +0 -1177
  249. package/dist/server/ui/assets/index-qoQEv_u4.css +0 -32
@@ -6,7 +6,7 @@ export declare const MAX_TIME_OPERATION_ID_LENGTH = 128;
6
6
  export declare const TIME_OPERATION_ID_PATTERN: RegExp;
7
7
  export declare const TIME_CREATE_BASELINE_WINDOW_MS: number;
8
8
  export declare const TIME_ENTRY_START_TOLERANCE_MS = 90000;
9
- export type ExternalTimeMutationKind = 'create' | 'delete';
9
+ export type ExternalTimeMutationKind = 'create' | 'update' | 'delete';
10
10
  export type ExternalTimeMutationPhase = 'pending' | 'dispatched' | 'outcome_unknown' | 'succeeded' | 'failed' | 'already_deleted' | 'not_applied' | 'abandoned_unknown' | 'superseded';
11
11
  export declare const TERMINAL_TIME_MUTATION_PHASES: ReadonlySet<ExternalTimeMutationPhase>;
12
12
  export interface ExternalTimeMutationTuple {
@@ -23,6 +23,11 @@ export interface ExternalTimeCreateBaseline {
23
23
  matchingIds: string[];
24
24
  complete: boolean;
25
25
  }
26
+ export interface ExternalTimeUpdateBaseline {
27
+ startedAt: string;
28
+ durationMs: number;
29
+ noteFingerprint: string;
30
+ }
26
31
  export interface ExternalTimeMutationReceipt {
27
32
  operationId: string;
28
33
  kind: ExternalTimeMutationKind;
@@ -30,9 +35,18 @@ export interface ExternalTimeMutationReceipt {
30
35
  phase: ExternalTimeMutationPhase;
31
36
  remoteEntryId: string | null;
32
37
  baseline: ExternalTimeCreateBaseline | null;
38
+ updateBaseline: ExternalTimeUpdateBaseline | null;
33
39
  createdAt: number;
34
40
  updatedAt: number;
35
41
  }
42
+ export interface ExternalTimeOperationInspection {
43
+ operationId: string;
44
+ kind: ExternalTimeMutationKind;
45
+ tuple: Readonly<ExternalTimeMutationTuple>;
46
+ phase: ExternalTimeMutationPhase;
47
+ canVerify: boolean;
48
+ expiresAt: string;
49
+ }
36
50
  export interface ExternalTimeOperationReceiptView {
37
51
  operationId: string;
38
52
  kind: ExternalTimeMutationKind;
@@ -40,10 +54,17 @@ export interface ExternalTimeOperationReceiptView {
40
54
  remoteTaskId: string;
41
55
  remoteEntryId: string | null;
42
56
  phase: ExternalTimeMutationPhase;
57
+ canVerify: boolean;
43
58
  createdAt: string;
44
59
  updatedAt: string;
45
60
  expiresAt: string;
46
61
  }
62
+ export declare function timeOperationCanVerify(receipt: {
63
+ kind: ExternalTimeMutationKind;
64
+ phase: ExternalTimeMutationPhase;
65
+ baseline: ExternalTimeCreateBaseline | null;
66
+ updateBaseline: ExternalTimeUpdateBaseline | null;
67
+ }): boolean;
47
68
  export type ExternalTimeEntryCreateResult = {
48
69
  outcome: 'created';
49
70
  remoteEntryId: string | null;
@@ -66,7 +87,17 @@ export type ExternalTimeEntryDeleteResult = {
66
87
  outcome: 'outcome_unknown';
67
88
  receipt: ExternalTimeOperationReceiptView;
68
89
  };
69
- export type ExternalTimeOperationVerifyResolution = 'created' | 'deleted' | 'already_deleted' | 'not_applied' | 'completeness_not_provable' | 'unresolved' | 'connection_superseded' | 'verify_failed' | 'already_terminal';
90
+ export type ExternalTimeEntryUpdateResult = {
91
+ outcome: 'updated';
92
+ receipt: ExternalTimeOperationReceiptView;
93
+ } | {
94
+ outcome: 'not_applied';
95
+ receipt: ExternalTimeOperationReceiptView;
96
+ } | {
97
+ outcome: 'outcome_unknown';
98
+ receipt: ExternalTimeOperationReceiptView;
99
+ };
100
+ export type ExternalTimeOperationVerifyResolution = 'created' | 'updated' | 'deleted' | 'already_deleted' | 'not_applied' | 'completeness_not_provable' | 'unresolved' | 'connection_superseded' | 'verify_failed' | 'already_terminal';
70
101
  export interface ExternalTimeOperationVerifyResult {
71
102
  receipt: ExternalTimeOperationReceiptView;
72
103
  resolved: boolean;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TERMINAL_TIME_MUTATION_PHASES = exports.TIME_ENTRY_START_TOLERANCE_MS = exports.TIME_CREATE_BASELINE_WINDOW_MS = exports.TIME_OPERATION_ID_PATTERN = exports.MAX_TIME_OPERATION_ID_LENGTH = exports.TIME_OPERATION_MAX_RECEIPTS = exports.TIME_OPERATION_MAX_LIVE_RECEIPTS = exports.TIME_OPERATION_RECEIPT_TTL_MS = void 0;
4
+ exports.timeOperationCanVerify = timeOperationCanVerify;
4
5
  exports.TIME_OPERATION_RECEIPT_TTL_MS = 24 * 60 * 60 * 1_000;
5
6
  exports.TIME_OPERATION_MAX_LIVE_RECEIPTS = 32;
6
7
  exports.TIME_OPERATION_MAX_RECEIPTS = 256;
@@ -16,4 +17,17 @@ exports.TERMINAL_TIME_MUTATION_PHASES = new Set([
16
17
  'abandoned_unknown',
17
18
  'superseded',
18
19
  ]);
20
+ function timeOperationCanVerify(receipt) {
21
+ if (receipt.phase !== 'outcome_unknown') {
22
+ return false;
23
+ }
24
+ switch (receipt.kind) {
25
+ case 'create':
26
+ return receipt.baseline?.complete === true;
27
+ case 'update':
28
+ return receipt.updateBaseline !== null;
29
+ case 'delete':
30
+ return true;
31
+ }
32
+ }
19
33
  //# sourceMappingURL=external-time-mutation.models.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"external-time-mutation.models.js","sourceRoot":"","sources":["../../../../src/modules/external-integrations/models/external-time-mutation.models.ts"],"names":[],"mappings":";;;AAGa,QAAA,6BAA6B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;AACrD,QAAA,gCAAgC,GAAG,EAAE,CAAC;AACtC,QAAA,2BAA2B,GAAG,GAAG,CAAC;AAClC,QAAA,4BAA4B,GAAG,GAAG,CAAC;AACnC,QAAA,yBAAyB,GAAG,0BAA0B,CAAC;AAGvD,QAAA,8BAA8B,GAAG,EAAE,GAAG,MAAM,CAAC;AAG7C,QAAA,6BAA6B,GAAG,MAAM,CAAC;AAoBvC,QAAA,6BAA6B,GAA2C,IAAI,GAAG,CAAC;IAC3F,WAAW;IACX,QAAQ;IACR,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,YAAY;CACb,CAAC,CAAC"}
1
+ {"version":3,"file":"external-time-mutation.models.js","sourceRoot":"","sources":["../../../../src/modules/external-integrations/models/external-time-mutation.models.ts"],"names":[],"mappings":";;;AAiHA,wDAiBC;AA/HY,QAAA,6BAA6B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;AACrD,QAAA,gCAAgC,GAAG,EAAE,CAAC;AACtC,QAAA,2BAA2B,GAAG,GAAG,CAAC;AAClC,QAAA,4BAA4B,GAAG,GAAG,CAAC;AACnC,QAAA,yBAAyB,GAAG,0BAA0B,CAAC;AAGvD,QAAA,8BAA8B,GAAG,EAAE,GAAG,MAAM,CAAC;AAG7C,QAAA,6BAA6B,GAAG,MAAM,CAAC;AAoBvC,QAAA,6BAA6B,GAA2C,IAAI,GAAG,CAAC;IAC3F,WAAW;IACX,QAAQ;IACR,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,YAAY;CACb,CAAC,CAAC;AAyEH,SAAgB,sBAAsB,CAAC,OAKtC;IACC,IAAI,OAAO,CAAC,KAAK,KAAK,iBAAiB,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;QAC7C,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,cAAc,KAAK,IAAI,CAAC;QACzC,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -21,18 +21,18 @@ export declare class ExternalEditSessionService {
21
21
  private readonly store;
22
22
  private readonly capabilities;
23
23
  constructor(storage: StorageService, providers: ExternalTaskProviderRegistry, gate: ProviderOperationGate, store: ExternalEditSessionStore, capabilities?: ExternalRichCapabilityFlags);
24
- readRichDescription(provider: IntegrationProvider, remoteTaskId: string): Promise<ExternalRichDescriptionRead>;
25
- createDescriptionSession(provider: IntegrationProvider, remoteTaskId: string): Promise<ExternalEditSessionView>;
26
- createCommentEditSession(provider: IntegrationProvider, remoteTaskId: string, commentId: string, lookupToken: string | null): Promise<ExternalEditSessionView>;
27
- createCommentDeleteSession(provider: IntegrationProvider, remoteTaskId: string, commentId: string, pageProof: string | null): Promise<ExternalEditSessionView>;
28
- touchSession(sessionId: string): Promise<ExternalEditSessionView>;
29
- saveSession(sessionId: string, payload: ExternalRichDocumentV1, expectedRevision: number): Promise<ExternalSessionWriteOutcome>;
24
+ readRichDescription(projectId: string, provider: IntegrationProvider, remoteTaskId: string): Promise<ExternalRichDescriptionRead>;
25
+ createDescriptionSession(projectId: string, provider: IntegrationProvider, remoteTaskId: string): Promise<ExternalEditSessionView>;
26
+ createCommentEditSession(projectId: string, provider: IntegrationProvider, remoteTaskId: string, commentId: string, lookupToken: string | null): Promise<ExternalEditSessionView>;
27
+ createCommentDeleteSession(projectId: string, provider: IntegrationProvider, remoteTaskId: string, commentId: string, pageProof: string | null): Promise<ExternalEditSessionView>;
28
+ touchSession(projectId: string, sessionId: string): Promise<ExternalEditSessionView>;
29
+ saveSession(projectId: string, sessionId: string, payload: ExternalRichDocumentV1, expectedRevision: number): Promise<ExternalSessionWriteOutcome>;
30
30
  private saveDispatchPhase;
31
31
  private postWriteVerification;
32
32
  private freshContentFingerprint;
33
- reloadSession(sessionId: string): Promise<ExternalSessionReloadResult>;
34
- verifySession(sessionId: string): Promise<ExternalSessionVerifyResult>;
35
- executeCommentDelete(sessionId: string): Promise<ExternalCommentDeleteOutcome>;
33
+ reloadSession(projectId: string, sessionId: string): Promise<ExternalSessionReloadResult>;
34
+ verifySession(projectId: string, sessionId: string): Promise<ExternalSessionVerifyResult>;
35
+ executeCommentDelete(projectId: string, sessionId: string): Promise<ExternalCommentDeleteOutcome>;
36
36
  private createCommentSession;
37
37
  private parseProviderDescription;
38
38
  private parseProviderComment;
@@ -51,6 +51,7 @@ export declare class ExternalEditSessionService {
51
51
  private sessionFailure;
52
52
  private storeFailure;
53
53
  private notConnected;
54
+ private sessionBelongsToProject;
54
55
  private unsupported;
55
56
  private context;
56
57
  private scopeKey;
@@ -49,12 +49,12 @@ let ExternalEditSessionService = class ExternalEditSessionService {
49
49
  this.store = store;
50
50
  this.capabilities = capabilities;
51
51
  }
52
- async readRichDescription(provider, remoteTaskId) {
52
+ async readRichDescription(projectId, provider, remoteTaskId) {
53
53
  const adapter = this.providers.get(provider);
54
54
  if (!adapter.descriptionEdit) {
55
55
  throw this.unsupported(provider);
56
56
  }
57
- const { connection, credentials } = await this.loadStableConnection(provider);
57
+ const { connection, credentials } = await this.loadStableConnection(projectId, provider);
58
58
  const raw = await adapter.descriptionEdit.readDescription(credentials, this.context(connection), remoteTaskId);
59
59
  const parsed = this.parseProviderDescription(provider, raw);
60
60
  if (!parsed.supported) {
@@ -76,13 +76,13 @@ let ExternalEditSessionService = class ExternalEditSessionService {
76
76
  canDeleteOwnedComments: this.capabilities.ownedDelete,
77
77
  };
78
78
  }
79
- async createDescriptionSession(provider, remoteTaskId) {
79
+ async createDescriptionSession(projectId, provider, remoteTaskId) {
80
80
  this.requireRichEditCapability();
81
81
  const adapter = this.providers.get(provider);
82
82
  if (!adapter.descriptionEdit) {
83
83
  throw this.unsupported(provider);
84
84
  }
85
- const { connection, credentials } = await this.loadStableConnection(provider);
85
+ const { connection, credentials } = await this.loadStableConnection(projectId, provider);
86
86
  const raw = await adapter.descriptionEdit.readDescription(credentials, this.context(connection), remoteTaskId);
87
87
  const parsed = this.parseProviderDescription(provider, raw);
88
88
  if (!parsed.supported) {
@@ -94,6 +94,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
94
94
  const created = this.store.create({
95
95
  kind: 'description_edit',
96
96
  provider,
97
+ projectId,
97
98
  connectionId: connection.id,
98
99
  connectionGeneration: connection.generation,
99
100
  scopeKey: this.scopeKey(connection),
@@ -110,24 +111,30 @@ let ExternalEditSessionService = class ExternalEditSessionService {
110
111
  }
111
112
  return this.store.view(created.value);
112
113
  }
113
- async createCommentEditSession(provider, remoteTaskId, commentId, lookupToken) {
114
+ async createCommentEditSession(projectId, provider, remoteTaskId, commentId, lookupToken) {
114
115
  this.requireRichEditCapability();
115
- const { session } = await this.createCommentSession(provider, remoteTaskId, commentId, lookupToken, 'comment_edit');
116
+ const { session } = await this.createCommentSession(projectId, provider, remoteTaskId, commentId, lookupToken, 'comment_edit');
116
117
  return session;
117
118
  }
118
- async createCommentDeleteSession(provider, remoteTaskId, commentId, pageProof) {
119
+ async createCommentDeleteSession(projectId, provider, remoteTaskId, commentId, pageProof) {
119
120
  this.requireOwnedDeleteCapability();
120
- const { session } = await this.createCommentSession(provider, remoteTaskId, commentId, pageProof, 'comment_delete');
121
+ const { session } = await this.createCommentSession(projectId, provider, remoteTaskId, commentId, pageProof, 'comment_delete');
121
122
  return session;
122
123
  }
123
- async touchSession(sessionId) {
124
+ async touchSession(projectId, sessionId) {
125
+ await this.storage.getProject(projectId);
126
+ const current = this.store.get(sessionId);
127
+ if (!current.ok || !this.sessionBelongsToProject(projectId, current.value)) {
128
+ throw this.sessionFailure('session_not_found');
129
+ }
124
130
  const touched = this.store.touch(sessionId);
125
131
  if (!touched.ok) {
126
132
  throw this.sessionFailure(touched.reason);
127
133
  }
128
134
  return this.store.view(touched.value);
129
135
  }
130
- async saveSession(sessionId, payload, expectedRevision) {
136
+ async saveSession(projectId, sessionId, payload, expectedRevision) {
137
+ await this.storage.getProject(projectId);
131
138
  const canonical = (0, external_rich_document_1.canonicalizeRichDocument)(payload);
132
139
  if (canonical === null) {
133
140
  throw new error_types_1.ValidationError('The payload is outside the supported rich content set.', {
@@ -139,6 +146,9 @@ let ExternalEditSessionService = class ExternalEditSessionService {
139
146
  if (!initial.ok) {
140
147
  return this.writeRejected(null, this.writeFailure(initial.reason));
141
148
  }
149
+ if (!this.sessionBelongsToProject(projectId, initial.value)) {
150
+ return this.writeRejected(null, 'session_not_found');
151
+ }
142
152
  const kind = initial.value.kind;
143
153
  if (kind === 'comment_delete') {
144
154
  throw new error_types_1.ValidationError('The session does not support content saves.', {
@@ -149,7 +159,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
149
159
  const provider = initial.value.provider;
150
160
  let phase;
151
161
  try {
152
- phase = await this.gate.run(provider, () => this.saveDispatchPhase(sessionId, provider, kind, canonical, fingerprint, expectedRevision));
162
+ phase = await this.gate.run({ projectId, provider }, () => this.saveDispatchPhase(projectId, sessionId, provider, kind, canonical, fingerprint, expectedRevision));
153
163
  }
154
164
  catch (error) {
155
165
  if (error instanceof error_types_1.BusyError) {
@@ -166,16 +176,17 @@ let ExternalEditSessionService = class ExternalEditSessionService {
166
176
  ? this.writeRejected(null, 'session_not_found')
167
177
  : { outcome: 'outcome_unknown', session: view };
168
178
  }
169
- return this.postWriteVerification(sessionId, provider, kind, fingerprint, canonical);
179
+ return this.postWriteVerification(projectId, sessionId, provider, kind, fingerprint, canonical);
170
180
  }
171
- async saveDispatchPhase(sessionId, provider, kind, canonical, fingerprint, expectedRevision) {
181
+ async saveDispatchPhase(projectId, sessionId, provider, kind, canonical, fingerprint, expectedRevision) {
172
182
  const adapter = this.providers.get(provider);
173
- const connection = await this.storage.getIntegrationConnection(provider);
183
+ const connection = await this.storage.getIntegrationConnection({ projectId, provider });
174
184
  const session = this.store.get(sessionId);
175
185
  if (!session.ok) {
176
186
  return { phase: 'rejected', reason: this.writeFailure(session.reason) };
177
187
  }
178
188
  if (!connection ||
189
+ connection.projectId !== projectId ||
179
190
  connection.provider !== provider ||
180
191
  connection.id !== session.value.connectionId ||
181
192
  connection.generation !== session.value.connectionGeneration) {
@@ -189,7 +200,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
189
200
  if (!adapter.descriptionEdit) {
190
201
  throw this.unsupported(provider);
191
202
  }
192
- const raw = await adapter.descriptionEdit.readDescription((await this.storage.getIntegrationConnectionCredentials(provider)), context, session.value.remoteTaskId);
203
+ const raw = await adapter.descriptionEdit.readDescription((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), context, session.value.remoteTaskId);
193
204
  const parsed = this.parseProviderDescription(provider, raw);
194
205
  if (!parsed.supported) {
195
206
  this.store.applyVerifyOutcome(sessionId, 'diverged');
@@ -211,7 +222,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
211
222
  this.store.invalidate(sessionId);
212
223
  return { phase: 'rejected', reason: 'connection_superseded' };
213
224
  }
214
- const snapshot = await adapter.ownedMutations.findComment((await this.storage.getIntegrationConnectionCredentials(provider)), context, session.value.remoteTaskId, session.value.remoteCommentId, token.pageProof);
225
+ const snapshot = await adapter.ownedMutations.findComment((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), context, session.value.remoteTaskId, session.value.remoteCommentId, token.pageProof);
215
226
  if (snapshot === null) {
216
227
  this.store.invalidate(sessionId);
217
228
  return { phase: 'rejected', reason: 'target_gone' };
@@ -256,7 +267,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
256
267
  }
257
268
  const raw = 'ok' in emit && 'markdown' in emit ? emit.markdown : emit;
258
269
  try {
259
- await adapter.descriptionEdit.writeDescription((await this.storage.getIntegrationConnectionCredentials(provider)), context, session.value.remoteTaskId, raw);
270
+ await adapter.descriptionEdit.writeDescription((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), context, session.value.remoteTaskId, raw);
260
271
  }
261
272
  catch (error) {
262
273
  if (isUnknownOutcome(error)) {
@@ -268,7 +279,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
268
279
  }
269
280
  else {
270
281
  try {
271
- await adapter.ownedMutations.updateOwnedComment((await this.storage.getIntegrationConnectionCredentials(provider)), context, session.value.remoteTaskId, session.value.remoteCommentId, canonical, commentMetadata);
282
+ await adapter.ownedMutations.updateOwnedComment((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), context, session.value.remoteTaskId, session.value.remoteCommentId, canonical, commentMetadata);
272
283
  }
273
284
  catch (error) {
274
285
  if (isUnknownOutcome(error)) {
@@ -284,12 +295,12 @@ let ExternalEditSessionService = class ExternalEditSessionService {
284
295
  }
285
296
  return { phase: 'dispatched' };
286
297
  }
287
- async postWriteVerification(sessionId, provider, kind, pendingFingerprint, canonical) {
298
+ async postWriteVerification(projectId, sessionId, provider, kind, pendingFingerprint, canonical) {
288
299
  const session = this.store.get(sessionId);
289
300
  if (!session.ok) {
290
301
  return this.writeRejected(null, this.writeFailure(session.reason));
291
302
  }
292
- const read = await this.freshContentFingerprint(provider, kind, session.value);
303
+ const read = await this.freshContentFingerprint(projectId, provider, kind, session.value);
293
304
  if (read.generationChanged) {
294
305
  this.store.invalidate(sessionId);
295
306
  return { outcome: 'saved_unverified', session: this.currentView(sessionId) };
@@ -315,10 +326,11 @@ let ExternalEditSessionService = class ExternalEditSessionService {
315
326
  }
316
327
  return { outcome: 'saved_unverified', session: this.currentView(sessionId) };
317
328
  }
318
- async freshContentFingerprint(provider, kind, session) {
329
+ async freshContentFingerprint(projectId, provider, kind, session) {
319
330
  const adapter = this.providers.get(provider);
320
- const before = await this.storage.getIntegrationConnection(provider);
331
+ const before = await this.storage.getIntegrationConnection({ projectId, provider });
321
332
  if (!before ||
333
+ before.projectId !== projectId ||
322
334
  before.provider !== provider ||
323
335
  before.id !== session.connectionId ||
324
336
  before.generation !== session.connectionGeneration) {
@@ -330,7 +342,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
330
342
  if (!adapter.descriptionEdit) {
331
343
  throw this.unsupported(provider);
332
344
  }
333
- const raw = await adapter.descriptionEdit.readDescription((await this.storage.getIntegrationConnectionCredentials(provider)), this.context(before), session.remoteTaskId);
345
+ const raw = await adapter.descriptionEdit.readDescription((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), this.context(before), session.remoteTaskId);
334
346
  const parsed = this.parseProviderDescription(provider, raw);
335
347
  fingerprint = parsed.supported ? (0, external_rich_document_1.richDocumentFingerprint)(parsed.document) : null;
336
348
  }
@@ -341,7 +353,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
341
353
  const token = this.sessionLookupToken(session.providerMetadata.lookupToken ?? '');
342
354
  const snapshot = token === null
343
355
  ? null
344
- : await adapter.ownedMutations.findComment((await this.storage.getIntegrationConnectionCredentials(provider)), this.context(before), session.remoteTaskId, session.remoteCommentId, token.pageProof);
356
+ : await adapter.ownedMutations.findComment((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), this.context(before), session.remoteTaskId, session.remoteCommentId, token.pageProof);
345
357
  if (snapshot !== null) {
346
358
  const parsed = this.parseProviderComment(provider, snapshot.raw);
347
359
  fingerprint = parsed.supported ? (0, external_rich_document_1.richDocumentFingerprint)(parsed.document) : null;
@@ -351,8 +363,9 @@ let ExternalEditSessionService = class ExternalEditSessionService {
351
363
  catch {
352
364
  return { ok: false, fingerprint: null, generationChanged: false };
353
365
  }
354
- const after = await this.storage.getIntegrationConnection(provider);
366
+ const after = await this.storage.getIntegrationConnection({ projectId, provider });
355
367
  if (!after ||
368
+ after.projectId !== projectId ||
356
369
  after.provider !== provider ||
357
370
  after.id !== session.connectionId ||
358
371
  after.generation !== session.connectionGeneration) {
@@ -360,11 +373,15 @@ let ExternalEditSessionService = class ExternalEditSessionService {
360
373
  }
361
374
  return { ok: fingerprint !== null, fingerprint, generationChanged: false };
362
375
  }
363
- async reloadSession(sessionId) {
376
+ async reloadSession(projectId, sessionId) {
377
+ await this.storage.getProject(projectId);
364
378
  const session = this.store.get(sessionId);
365
379
  if (!session.ok) {
366
380
  throw this.sessionFailure(session.reason);
367
381
  }
382
+ if (!this.sessionBelongsToProject(projectId, session.value)) {
383
+ throw this.sessionFailure('session_not_found');
384
+ }
368
385
  if (session.value.kind === 'comment_delete') {
369
386
  throw new error_types_1.ValidationError('The session does not support reload.', {
370
387
  reason: 'wrong_session_kind',
@@ -372,7 +389,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
372
389
  }
373
390
  this.requireRichEditCapability();
374
391
  const provider = session.value.provider;
375
- const { connection, credentials } = await this.loadStableConnection(provider);
392
+ const { connection, credentials } = await this.loadStableConnection(projectId, provider);
376
393
  if (connection.id !== session.value.connectionId) {
377
394
  this.store.invalidate(sessionId);
378
395
  throw new error_types_1.ValidationError('The connection was replaced; the session is invalid.', {
@@ -432,15 +449,19 @@ let ExternalEditSessionService = class ExternalEditSessionService {
432
449
  }
433
450
  return { status: 'reloaded', session: this.store.view(reloaded.value) };
434
451
  }
435
- async verifySession(sessionId) {
452
+ async verifySession(projectId, sessionId) {
453
+ await this.storage.getProject(projectId);
436
454
  const session = this.store.get(sessionId);
437
455
  if (!session.ok) {
438
456
  return { session: null, remoteState: null, reason: this.verifyFailure(session.reason) };
439
457
  }
458
+ if (!this.sessionBelongsToProject(projectId, session.value)) {
459
+ return { session: null, remoteState: null, reason: 'session_not_found' };
460
+ }
440
461
  if (session.value.kind === 'comment_delete') {
441
- return this.verifyDeleteSession(session.value);
462
+ return this.verifyDeleteSession(projectId, session.value);
442
463
  }
443
- const read = await this.freshContentFingerprint(session.value.provider, session.value.kind, session.value);
464
+ const read = await this.freshContentFingerprint(projectId, session.value.provider, session.value.kind, session.value);
444
465
  if (read.generationChanged) {
445
466
  this.store.invalidate(sessionId);
446
467
  return this.verifyResult(sessionId, 'diverged');
@@ -466,7 +487,8 @@ let ExternalEditSessionService = class ExternalEditSessionService {
466
487
  const applied = this.store.applyVerifyOutcome(sessionId, 'diverged');
467
488
  return this.verifyResult(sessionId, applied.ok ? 'diverged' : null);
468
489
  }
469
- async executeCommentDelete(sessionId) {
490
+ async executeCommentDelete(projectId, sessionId) {
491
+ await this.storage.getProject(projectId);
470
492
  this.requireOwnedDeleteCapability();
471
493
  const session = this.store.get(sessionId);
472
494
  if (!session.ok) {
@@ -476,6 +498,9 @@ let ExternalEditSessionService = class ExternalEditSessionService {
476
498
  session: null,
477
499
  };
478
500
  }
501
+ if (!this.sessionBelongsToProject(projectId, session.value)) {
502
+ return { outcome: 'rejected', reason: 'session_not_found', session: null };
503
+ }
479
504
  if (session.value.kind !== 'comment_delete') {
480
505
  throw new error_types_1.ValidationError('The session does not support comment deletion.', {
481
506
  reason: 'wrong_session_kind',
@@ -487,9 +512,10 @@ let ExternalEditSessionService = class ExternalEditSessionService {
487
512
  throw this.unsupported(provider);
488
513
  }
489
514
  try {
490
- return await this.gate.run(provider, async () => {
491
- const connection = await this.storage.getIntegrationConnection(provider);
515
+ return await this.gate.run({ projectId, provider }, async () => {
516
+ const connection = await this.storage.getIntegrationConnection({ projectId, provider });
492
517
  if (!connection ||
518
+ connection.projectId !== projectId ||
493
519
  connection.provider !== provider ||
494
520
  connection.id !== session.value.connectionId ||
495
521
  connection.generation !== session.value.connectionGeneration) {
@@ -527,7 +553,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
527
553
  return this.deleteRejected(this.currentView(sessionId), this.deleteFailure('session_not_editable'));
528
554
  }
529
555
  try {
530
- await adapter.ownedMutations.deleteComment((await this.storage.getIntegrationConnectionCredentials(provider)), this.context(connection), session.value.remoteTaskId, session.value.remoteCommentId);
556
+ await adapter.ownedMutations.deleteComment((await this.storage.getIntegrationConnectionCredentials({ projectId, provider })), this.context(connection), session.value.remoteTaskId, session.value.remoteCommentId);
531
557
  }
532
558
  catch (error) {
533
559
  if (isProviderNotFound(error)) {
@@ -557,12 +583,12 @@ let ExternalEditSessionService = class ExternalEditSessionService {
557
583
  throw error;
558
584
  }
559
585
  }
560
- async createCommentSession(provider, remoteTaskId, commentId, lookupProof, kind) {
586
+ async createCommentSession(projectId, provider, remoteTaskId, commentId, lookupProof, kind) {
561
587
  const adapter = this.providers.get(provider);
562
588
  if (!adapter.ownedMutations) {
563
589
  throw this.unsupported(provider);
564
590
  }
565
- const { connection, credentials } = await this.loadStableConnection(provider);
591
+ const { connection, credentials } = await this.loadStableConnection(projectId, provider);
566
592
  const [ownerRemoteId, snapshot] = await Promise.all([
567
593
  adapter.ownedMutations.getCurrentOwnerRemoteId(credentials),
568
594
  adapter.ownedMutations.findComment(credentials, this.context(connection), remoteTaskId, commentId, lookupProof),
@@ -605,6 +631,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
605
631
  const created = this.store.create({
606
632
  kind,
607
633
  provider,
634
+ projectId,
608
635
  connectionId: connection.id,
609
636
  connectionGeneration: connection.generation,
610
637
  scopeKey: this.scopeKey(connection),
@@ -644,19 +671,22 @@ let ExternalEditSessionService = class ExternalEditSessionService {
644
671
  });
645
672
  }
646
673
  }
647
- async loadStableConnection(provider) {
674
+ async loadStableConnection(projectId, provider) {
675
+ await this.storage.getProject(projectId);
676
+ const identity = { projectId, provider };
648
677
  for (let attempt = 0; attempt < 3; attempt += 1) {
649
- const before = await this.storage.getIntegrationConnection(provider);
650
- if (!before || before.provider !== provider) {
651
- throw this.notConnected(provider);
678
+ const before = await this.storage.getIntegrationConnection(identity);
679
+ if (before?.projectId !== projectId || before.provider !== provider) {
680
+ throw this.notConnected(projectId, provider);
652
681
  }
653
- const credentials = await this.storage.getIntegrationConnectionCredentials(provider);
654
- const after = await this.storage.getIntegrationConnection(provider);
682
+ const credentials = await this.storage.getIntegrationConnectionCredentials(identity);
683
+ const after = await this.storage.getIntegrationConnection(identity);
655
684
  if (!credentials ||
656
685
  credentials.provider !== provider ||
657
686
  !after ||
687
+ after.projectId !== projectId ||
658
688
  after.provider !== provider) {
659
- throw this.notConnected(provider);
689
+ throw this.notConnected(projectId, provider);
660
690
  }
661
691
  if (before.id === after.id && before.generation === after.generation) {
662
692
  return { connection: after, credentials };
@@ -664,6 +694,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
664
694
  }
665
695
  throw new error_types_1.BusyError('Integration connection changed during the operation.', {
666
696
  provider,
697
+ projectId,
667
698
  reason: 'connection_changed',
668
699
  });
669
700
  }
@@ -679,7 +710,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
679
710
  reason: null,
680
711
  };
681
712
  }
682
- async verifyDeleteSession(session) {
713
+ async verifyDeleteSession(projectId, session) {
683
714
  const adapter = this.providers.get(session.provider);
684
715
  if (!adapter.ownedMutations) {
685
716
  throw this.unsupported(session.provider);
@@ -689,7 +720,7 @@ let ExternalEditSessionService = class ExternalEditSessionService {
689
720
  this.store.invalidate(session.sessionId);
690
721
  return this.verifyResult(session.sessionId, 'diverged');
691
722
  }
692
- const { connection, credentials } = await this.loadStableConnection(session.provider);
723
+ const { connection, credentials } = await this.loadStableConnection(projectId, session.provider);
693
724
  if (connection.id !== session.connectionId) {
694
725
  this.store.invalidate(session.sessionId);
695
726
  return this.verifyResult(session.sessionId, 'diverged');
@@ -741,12 +772,16 @@ let ExternalEditSessionService = class ExternalEditSessionService {
741
772
  reason: reason === 'baseline_too_large' ? 'baseline_too_large' : 'store_limit_exceeded',
742
773
  });
743
774
  }
744
- notConnected(provider) {
775
+ notConnected(projectId, provider) {
745
776
  return new error_types_1.ValidationError('Connect the integration before editing.', {
746
777
  provider,
778
+ projectId,
747
779
  reason: 'not_connected',
748
780
  });
749
781
  }
782
+ sessionBelongsToProject(projectId, session) {
783
+ return session.projectId === projectId;
784
+ }
750
785
  unsupported(provider) {
751
786
  return new error_types_1.ValidationError('The provider does not support this operation.', {
752
787
  provider,