@taskforcehq/taskforce 0.3.328 → 0.3.330

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 (485) hide show
  1. package/dist/Taskforce.module.css +523 -79
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AiProfilesModule.js +3 -5
  8. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  9. package/dist/components/features/TaskSettings.d.ts +12 -1
  10. package/dist/components/features/TaskSettings.js +217 -54
  11. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  12. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  13. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  14. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  15. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  16. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  17. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  18. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  19. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  20. package/dist/components/features/planning/PlanningModule.js +2 -5
  21. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  22. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  23. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  24. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  25. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  26. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  27. package/dist/components/features/taskforceAgentEditorModel.js +5 -1
  28. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  29. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +65 -10
  32. package/dist/components/task/TaskImageReviews.js +14 -5
  33. package/dist/components/task/TaskKanban.d.ts +6 -1
  34. package/dist/components/task/TaskKanban.js +152 -6
  35. package/dist/components/task/TaskList.d.ts +5 -0
  36. package/dist/components/task/TaskList.js +3 -3
  37. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  38. package/dist/components/ui/PasswordInput.d.ts +6 -0
  39. package/dist/components/ui/PasswordInput.js +11 -0
  40. package/dist/components/ui/TopNoticeLayer.js +1 -1
  41. package/dist/components/views/AppShellHeader.js +32 -11
  42. package/dist/components/views/PlanComparisonPage.js +12 -0
  43. package/dist/components/views/StandaloneLayout.js +32 -55
  44. package/dist/components/views/WidgetView.js +3 -3
  45. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  46. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  47. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  48. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  49. package/dist/config/envSchema.js +60 -1
  50. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  51. package/dist/config/localServiceRuntimeContract.js +135 -0
  52. package/dist/core/AiProfileService.js +46 -8
  53. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  54. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  55. package/dist/core/McpTokenService.d.ts +23 -1
  56. package/dist/core/McpTokenService.js +93 -10
  57. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  58. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  59. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  60. package/dist/core/TaskChecklistCommandService.js +83 -5
  61. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  62. package/dist/core/TaskLifecycleCommandService.js +6 -2
  63. package/dist/core/Taskforce.d.ts +94 -2
  64. package/dist/core/Taskforce.js +760 -36
  65. package/dist/core/types.d.ts +14 -0
  66. package/dist/documentReviews/commandService.d.ts +2 -1
  67. package/dist/documentReviews/commandService.js +6 -3
  68. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  69. package/dist/hooks/sync/orchestratorShared.js +2 -0
  70. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  71. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  72. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  73. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  74. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  75. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  76. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  77. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  78. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  79. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  80. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  81. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  82. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  83. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  84. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  85. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  86. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  87. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  88. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  89. package/dist/hooks/ui/useSettingsModel.js +13 -2
  90. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  91. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  92. package/dist/hooks/useFilterSort.d.ts +7 -3
  93. package/dist/hooks/useFilterSort.js +15 -5
  94. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  95. package/dist/hooks/useSyncOrchestrator.js +111 -2
  96. package/dist/hooks/useTaskData.d.ts +40 -1
  97. package/dist/hooks/useTaskData.js +240 -9
  98. package/dist/hooks/useTaskMutations.d.ts +12 -2
  99. package/dist/hooks/useTaskMutations.js +266 -52
  100. package/dist/hooks/useTaskforce.d.ts +39 -9
  101. package/dist/hooks/useTaskforce.js +359 -40
  102. package/dist/hooks/useUiNotice.d.ts +4 -0
  103. package/dist/hooks/useUiNotice.js +4 -0
  104. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  105. package/dist/mcp/clientRegistry.d.ts +2 -2
  106. package/dist/mcp/clientRegistry.js +1 -1
  107. package/dist/mcp/documentAssetRegistrar.js +53 -41
  108. package/dist/mcp/documentHelpers.d.ts +1 -0
  109. package/dist/mcp/documentHelpers.js +7 -3
  110. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  111. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  112. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  113. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  114. package/dist/mcp/httpProtocolRouting.js +19 -0
  115. package/dist/mcp/localCliHealth.d.ts +2 -2
  116. package/dist/mcp/localCliHealth.js +2 -2
  117. package/dist/mcp/localServiceProxy.d.ts +1 -0
  118. package/dist/mcp/localServiceProxy.js +530 -68
  119. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  120. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  121. package/dist/mcp/runtime.d.ts +54 -79
  122. package/dist/mcp/runtime.js +556 -139
  123. package/dist/mcp/taskPlanningRegistrar.js +64 -42
  124. package/dist/mcp/toolCallCompatibility.js +38 -1
  125. package/dist/mcp/toolCatalog.d.ts +1 -0
  126. package/dist/mcp/toolProfiles.d.ts +2 -0
  127. package/dist/mcp/toolProfiles.js +10 -0
  128. package/dist/mcp/toolRegistry.d.ts +1 -0
  129. package/dist/mcp/toolRegistry.js +1 -0
  130. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  131. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  132. package/dist/migrations/taskSchemaMigrations.js +427 -0
  133. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  134. package/dist/runtime/appGateDefinitions.js +6 -6
  135. package/dist/runtime/appGates.d.ts +13 -13
  136. package/dist/runtime/appGates.js +36 -13
  137. package/dist/runtime/nodeAppGates.d.ts +8 -0
  138. package/dist/runtime/nodeAppGates.js +27 -0
  139. package/dist/server/cloudCollectionRead.d.ts +1 -1
  140. package/dist/server/cloudCollectionRead.js +2 -2
  141. package/dist/server/index.d.ts +6 -0
  142. package/dist/server/index.js +123 -14
  143. package/dist/server/localDatabaseIdentity.js +4 -1
  144. package/dist/server/localServiceLease.d.ts +3 -0
  145. package/dist/server/localServiceLease.js +11 -2
  146. package/dist/server/localServiceSessions.d.ts +14 -17
  147. package/dist/server/localServiceSessions.js +308 -94
  148. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
  149. package/dist/server/rateLimit.d.ts +1 -0
  150. package/dist/server/rateLimit.js +4 -0
  151. package/dist/server/realtimeSyncWs.js +36 -12
  152. package/dist/server/routes/admin.d.ts +4 -0
  153. package/dist/server/routes/admin.js +113 -3
  154. package/dist/server/routes/agentRoles.js +3 -2
  155. package/dist/server/routes/agentSkills.js +3 -2
  156. package/dist/server/routes/agents.d.ts +7 -0
  157. package/dist/server/routes/agents.js +394 -39
  158. package/dist/server/routes/annotatedAttachments.js +3 -2
  159. package/dist/server/routes/auth.js +3 -1
  160. package/dist/server/routes/billing.js +5 -1
  161. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  162. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  163. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  164. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  165. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  166. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  167. package/dist/server/routes/githubReviewEvidence.js +116 -0
  168. package/dist/server/routes/localService.d.ts +15 -4
  169. package/dist/server/routes/localService.js +138 -40
  170. package/dist/server/routes/modelConnections.d.ts +24 -0
  171. package/dist/server/routes/modelConnections.js +205 -0
  172. package/dist/server/routes/primitives.d.ts +2 -0
  173. package/dist/server/routes/shared.d.ts +19 -0
  174. package/dist/server/routes/shared.js +95 -19
  175. package/dist/server/routes/sync.js +1 -0
  176. package/dist/server/routes/syncAuxRoutes.js +9 -2
  177. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  178. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  179. package/dist/server/routes/syncPushRoutes.js +1 -0
  180. package/dist/server/routes/syncV3FeedRoutes.js +27 -16
  181. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  182. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  183. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  184. package/dist/server/routes/syncV3OperationRoutes.js +45 -9
  185. package/dist/server/routes/tasks.js +124 -13
  186. package/dist/server/routes/workflows.js +9 -1
  187. package/dist/server/routes/workspaces.js +43 -1
  188. package/dist/server/routes.js +59 -0
  189. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  190. package/dist/server/workspaceDeletionAdmission.js +50 -0
  191. package/dist/service/localServiceCli.js +16 -0
  192. package/dist/service/localServiceClientLifecycle.js +36 -10
  193. package/dist/services/codexAppServerModelGateway.d.ts +161 -0
  194. package/dist/services/codexAppServerModelGateway.js +663 -0
  195. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  196. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  197. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  198. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  199. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  200. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  201. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  202. package/dist/services/executorPhaseAApprovalService.js +609 -0
  203. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  204. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  205. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  206. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  207. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  208. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  209. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  210. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  211. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  212. package/dist/services/githubReviewEvidenceService.js +336 -0
  213. package/dist/services/modelGateway.d.ts +7 -0
  214. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  215. package/dist/services/modelProviderConnectionService.js +279 -0
  216. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  217. package/dist/services/modelProviderCredentialHome.js +271 -0
  218. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  219. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  220. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  221. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  222. package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
  223. package/dist/services/taskforceAgentMcpBridge.js +30 -27
  224. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  225. package/dist/shared/adminEdgeProxy.js +94 -0
  226. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  227. package/dist/shared/adminProxySessionCookies.js +86 -0
  228. package/dist/shared/aiProfileColors.d.ts +31 -1
  229. package/dist/shared/aiProfileColors.js +14 -6
  230. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  231. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  232. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  233. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  234. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  235. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  236. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  237. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  238. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  239. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  240. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  241. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  242. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  243. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  244. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  245. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  246. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  247. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  248. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  249. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  250. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  251. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  252. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  253. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  254. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  255. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  256. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  257. package/dist/shared/executorPhaseATiming.js +1 -0
  258. package/dist/shared/planningIdentity.js +1 -1
  259. package/dist/shared/productLogoKeys.d.ts +2 -0
  260. package/dist/shared/productLogoKeys.js +18 -0
  261. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  262. package/dist/shared/taskforceAgentDefinition.js +6 -3
  263. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  264. package/dist/shared/taskforceAgentModels.js +36 -3
  265. package/dist/shared/userFeatureGrants.d.ts +4 -0
  266. package/dist/shared/userFeatureGrants.js +7 -0
  267. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  268. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  269. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  270. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  271. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  272. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  273. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  274. package/dist/storage/modelProviderConnectionStore.js +446 -0
  275. package/dist/storage/postgresAdapter.d.ts +24 -3
  276. package/dist/storage/postgresAdapter.js +117 -14
  277. package/dist/storage/postgresWorker.js +22 -5
  278. package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
  279. package/dist/storage/postgresWorkerProtocol.js +30 -0
  280. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  281. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  282. package/dist/sync/cloudSyncApi.d.ts +4 -1
  283. package/dist/sync/cloudSyncApi.js +7 -2
  284. package/dist/sync/contentSyncState.d.ts +1 -1
  285. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  286. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
  287. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  288. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  289. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  290. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  291. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  292. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  293. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  294. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  295. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  296. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  297. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  298. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  299. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  300. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  301. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  302. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  303. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  304. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  305. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  306. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  307. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  308. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  309. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  310. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
  311. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  312. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  313. package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
  314. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  315. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  316. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  317. package/dist/sync/syncApplyHandlers.js +10 -1
  318. package/dist/sync/syncService.d.ts +17 -0
  319. package/dist/sync/syncService.js +87 -19
  320. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  321. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  322. package/dist/sync/v3/combinedFeedCapability.js +8 -0
  323. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  324. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  325. package/dist/sync/v3/durableOperationReplay.js +18 -0
  326. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  327. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
  328. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
  329. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
  330. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  331. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  332. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  333. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  334. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
  335. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  336. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  337. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  338. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  339. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  340. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  341. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  342. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  343. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  344. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  345. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  346. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  347. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  348. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  349. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  350. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  351. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  352. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  353. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  354. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  355. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
  356. package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
  357. package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
  358. package/dist/sync/v3/syncDurabilityStore.js +199 -13
  359. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  360. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  361. package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
  362. package/dist/sync/v3/taskChecklistMutationService.js +48 -1
  363. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  364. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  365. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  366. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  367. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  368. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  369. package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
  370. package/dist/sync/v3/taskStatusMutationService.js +123 -3
  371. package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
  372. package/dist/sync/v3/workflowAssignmentSync.js +30 -0
  373. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  374. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  375. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  376. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  377. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  378. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  379. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  380. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  381. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  382. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  383. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
  384. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  385. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  386. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
  387. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
  388. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
  389. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
  390. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
  391. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
  392. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
  393. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
  394. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
  395. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  396. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  397. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  398. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  399. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  400. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  401. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  402. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  403. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  404. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  405. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  406. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
  407. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
  408. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
  409. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  410. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  411. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  412. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  413. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  414. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  415. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  416. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  417. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  418. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  419. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  420. package/dist/sync/workspacePullFeed.js +2 -1
  421. package/dist/sync/workspaceRepair.d.ts +8 -2
  422. package/dist/sync/workspaceRepair.js +222 -6
  423. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  424. package/dist/sync/workspaceSyncModel.js +35 -7
  425. package/dist/sync/workspaceSyncState.d.ts +1 -0
  426. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  427. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  428. package/dist/types.d.ts +47 -1
  429. package/dist/types.js +6 -0
  430. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  431. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  432. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
  433. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  434. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  435. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
  436. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  437. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  438. package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
  439. package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
  440. package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
  441. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  442. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  443. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  444. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  445. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  446. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  447. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
  448. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  449. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  450. package/dist/ui/branding/logos/signature_dark.png +0 -0
  451. package/dist/ui/branding/logos/signature_light.png +0 -0
  452. package/dist/ui/index.html +3 -3
  453. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  454. package/dist/utils/httpSetCookie.d.ts +1 -0
  455. package/dist/utils/httpSetCookie.js +4 -1
  456. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  457. package/dist/utils/localRuntimeUrl.js +14 -0
  458. package/dist/utils/productLogoRegistry.d.ts +2 -0
  459. package/dist/utils/productLogoRegistry.js +36 -0
  460. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  461. package/dist/utils/syncStatusPresentation.js +17 -0
  462. package/dist/utils/taskActivity.d.ts +3 -2
  463. package/dist/utils/taskActivity.js +19 -2
  464. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  465. package/dist/utils/taskEditorReconciliation.js +217 -0
  466. package/dist/utils/taskEvents.d.ts +2 -0
  467. package/dist/utils/taskNormalization.d.ts +1 -0
  468. package/dist/utils/taskNormalization.js +39 -0
  469. package/dist/utils/taskSearch.js +2 -2
  470. package/dist/utils/uiNotice.d.ts +4 -0
  471. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  472. package/dist/utils/workspaceSyncPresentation.js +23 -17
  473. package/package.json +36 -6
  474. package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
  475. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  476. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  477. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  478. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  479. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  480. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  481. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  482. package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
  483. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  484. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  485. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -0,0 +1,158 @@
1
+ import { createHash, createPublicKey, sign } from 'node:crypto';
2
+ import { canonicalizeExecutorPhaseAJson, } from '../shared/executorPhaseAApprovalReceipt.js';
3
+ import { executorPhaseAIssuerRedemptionAuditSha256, executorPhaseAIssuerRedemptionIntentSha256, verifyExecutorPhaseAIssuerProof, EXECUTOR_PHASE_A_ISSUER_REDEMPTION_RESPONSE_PAYLOAD_SCHEMA, } from '../shared/executorPhaseAIssuerContracts.js';
4
+ import { verifyExecutorPhaseARunCapabilityArtifact, verifyExecutorPhaseAWorkloadGrantBundle, } from '../shared/executorPhaseARunAuthorization.js';
5
+ import { assertExecutorPhaseASchema } from '../shared/executorPhaseASchemaValidation.js';
6
+ import { ExecutorPhaseARunAuthorizationError, } from '../storage/executorPhaseARunAuthorizationStore.js';
7
+ export class ExecutorPhaseAIssuerRedemptionError extends Error {
8
+ statusCode;
9
+ code;
10
+ constructor(message, statusCode = 400, code = 'executor_phase_a_issuer_redemption_invalid') {
11
+ super(message);
12
+ this.statusCode = statusCode;
13
+ this.code = code;
14
+ this.name = 'ExecutorPhaseAIssuerRedemptionError';
15
+ }
16
+ }
17
+ function publicKeyFingerprint(publicKey) {
18
+ return createHash('sha256').update(publicKey.export({ format: 'der', type: 'spki' })).digest('hex');
19
+ }
20
+ function parseArtifactPublicKey(trusted) {
21
+ const validFrom = Date.parse(trusted.validFrom);
22
+ const validUntil = Date.parse(trusted.validUntil);
23
+ if (!Number.isFinite(validFrom) || !Number.isFinite(validUntil) || validUntil <= validFrom) {
24
+ throw new ExecutorPhaseAIssuerRedemptionError('The Cloud authorization artifact key lifetime is invalid.', 403);
25
+ }
26
+ const encoded = Buffer.from(trusted.publicKeySpkiBase64, 'base64');
27
+ if (encoded.toString('base64') !== trusted.publicKeySpkiBase64) {
28
+ throw new ExecutorPhaseAIssuerRedemptionError('The Cloud authorization artifact key is not canonical.', 403);
29
+ }
30
+ const publicKey = createPublicKey({ key: encoded, format: 'der', type: 'spki' });
31
+ if (publicKey.asymmetricKeyType !== 'ed25519') {
32
+ throw new ExecutorPhaseAIssuerRedemptionError('The Cloud authorization artifact key is not Ed25519.', 403);
33
+ }
34
+ return publicKey;
35
+ }
36
+ function resolveArtifactKey(keys, keyId, now) {
37
+ const trusted = keys.find((key) => key.keyId === keyId);
38
+ const validFrom = trusted ? Date.parse(trusted.validFrom) : Number.NaN;
39
+ const validUntil = trusted ? Date.parse(trusted.validUntil) : Number.NaN;
40
+ if (!trusted || trusted.status === 'disabled'
41
+ || validFrom > now.getTime() || now.getTime() >= validUntil) {
42
+ throw new ExecutorPhaseAIssuerRedemptionError('The Cloud authorization artifact key is not trusted.', 403);
43
+ }
44
+ return parseArtifactPublicKey(trusted);
45
+ }
46
+ function brokerPublicKey(encoded) {
47
+ try {
48
+ const key = createPublicKey({ key: Buffer.from(encoded, 'base64'), format: 'der', type: 'spki' });
49
+ if (key.asymmetricKeyType !== 'ed25519')
50
+ throw new Error('wrong key type');
51
+ return key;
52
+ }
53
+ catch {
54
+ throw new ExecutorPhaseAIssuerRedemptionError('The capability broker key is invalid.', 403);
55
+ }
56
+ }
57
+ export class ExecutorPhaseAIssuerRedemptionService {
58
+ options;
59
+ constructor(options) {
60
+ this.options = options;
61
+ if (options.responseSigning.privateKey.asymmetricKeyType !== 'ed25519') {
62
+ throw new Error('The issuer redemption response key must be Ed25519.');
63
+ }
64
+ const artifactKeyIds = new Set();
65
+ const artifactFingerprints = new Set();
66
+ for (const key of options.approvalPolicy.keys) {
67
+ if (artifactKeyIds.has(key.keyId))
68
+ throw new Error('The Phase A artifact trust policy contains a duplicate key ID.');
69
+ artifactKeyIds.add(key.keyId);
70
+ const publicKey = parseArtifactPublicKey(key);
71
+ artifactFingerprints.add(publicKeyFingerprint(publicKey));
72
+ }
73
+ const responseKeyIds = new Set();
74
+ const responseFingerprints = new Set();
75
+ for (const key of options.responseKeys) {
76
+ if (key.publicKey.asymmetricKeyType !== 'ed25519') {
77
+ throw new Error('The issuer redemption response trust keys must be unique Ed25519 keys.');
78
+ }
79
+ const fingerprint = publicKeyFingerprint(key.publicKey);
80
+ if (responseKeyIds.has(key.keyId) || responseFingerprints.has(fingerprint)) {
81
+ throw new Error('The issuer redemption response trust keys must be unique Ed25519 keys.');
82
+ }
83
+ responseKeyIds.add(key.keyId);
84
+ responseFingerprints.add(fingerprint);
85
+ }
86
+ if ([...responseKeyIds].some((keyId) => artifactKeyIds.has(keyId))
87
+ || [...responseFingerprints].some((fingerprint) => artifactFingerprints.has(fingerprint))) {
88
+ throw new Error('Phase A artifact and redemption-response trust keys must be disjoint.');
89
+ }
90
+ const publicKey = createPublicKey(options.responseSigning.privateKey);
91
+ const trusted = options.responseKeys.find((key) => key.keyId === options.responseSigning.keyId && key.status === 'active');
92
+ if (!trusted || !publicKey.equals(trusted.publicKey)) {
93
+ throw new Error('The issuer redemption response key must match one active Cloud trust key.');
94
+ }
95
+ }
96
+ redeem(request) {
97
+ const now = this.options.now?.() || new Date();
98
+ try {
99
+ assertExecutorPhaseASchema('issuerRedemptionRequest', request);
100
+ verifyExecutorPhaseAIssuerProof(request, this.options.issuerProofKeys, now);
101
+ const artifactKeyIds = [
102
+ request.approvalReceipt.envelope.keyId,
103
+ request.runCapability.envelope.keyId,
104
+ request.workloadGrant.envelope.keyId,
105
+ ];
106
+ if (new Set(artifactKeyIds).size !== 1) {
107
+ throw new TypeError('The Cloud authorization artifacts use different trust keys.');
108
+ }
109
+ const cloudPublicKey = resolveArtifactKey(this.options.approvalPolicy.keys, artifactKeyIds[0], now);
110
+ const verifiedCapability = verifyExecutorPhaseARunCapabilityArtifact(request.runCapability, request.approvalReceipt, cloudPublicKey, now);
111
+ if (request.approvalReceipt.payload.issuer !== this.options.approvalPolicy.issuer
112
+ || request.approvalReceipt.payload.audience !== this.options.approvalPolicy.audience
113
+ || request.approvalReceipt.payload.environment !== this.options.approvalPolicy.environment
114
+ || request.approvalReceipt.payload.workspaceId !== this.options.approvalPolicy.workspaceId
115
+ || request.approvalReceipt.payload.taskId !== this.options.approvalPolicy.taskId) {
116
+ throw new TypeError('The approval receipt is outside the frozen Phase A authority.');
117
+ }
118
+ const verifiedBundle = verifyExecutorPhaseAWorkloadGrantBundle(request.workloadGrant, verifiedCapability, request.senderProof, request.brokerRequestSha256, request.expectedPolicySha256, cloudPublicKey, brokerPublicKey(verifiedCapability.payload.brokerPublicKeySpkiBase64), now);
119
+ const redeemedAt = now.toISOString();
120
+ const auditInput = {
121
+ requestId: request.requestId,
122
+ grantId: verifiedBundle.grant.payload.grantId,
123
+ grantSha256: verifiedBundle.grantSha256,
124
+ senderProofSha256: verifiedBundle.senderProofSha256,
125
+ redeemedAt,
126
+ };
127
+ const payload = {
128
+ schema: EXECUTOR_PHASE_A_ISSUER_REDEMPTION_RESPONSE_PAYLOAD_SCHEMA,
129
+ decision: 'redeemed',
130
+ ...auditInput,
131
+ auditSha256: executorPhaseAIssuerRedemptionAuditSha256(auditInput),
132
+ };
133
+ const payloadBytes = canonicalizeExecutorPhaseAJson(payload);
134
+ const response = {
135
+ payload,
136
+ envelope: {
137
+ algorithm: 'Ed25519',
138
+ keyId: this.options.responseSigning.keyId,
139
+ payloadSha256: createHash('sha256').update(payloadBytes).digest('hex'),
140
+ signature: sign(null, payloadBytes, this.options.responseSigning.privateKey).toString('base64url'),
141
+ },
142
+ };
143
+ assertExecutorPhaseASchema('issuerRedemptionResponse', response);
144
+ const responseBytes = canonicalizeExecutorPhaseAJson(response);
145
+ const responseSha256 = createHash('sha256').update(responseBytes).digest('hex');
146
+ const persisted = this.options.store.redeemVerifiedGrant(verifiedBundle, request.requestId, executorPhaseAIssuerRedemptionIntentSha256(request), responseBytes, responseSha256, redeemedAt);
147
+ return { bytes: persisted.bytes, digest: persisted.digest, created: persisted.created };
148
+ }
149
+ catch (error) {
150
+ if (error instanceof ExecutorPhaseAIssuerRedemptionError)
151
+ throw error;
152
+ const statusCode = error instanceof TypeError || error instanceof ExecutorPhaseARunAuthorizationError
153
+ ? 403
154
+ : Number(error?.statusCode) || 500;
155
+ throw new ExecutorPhaseAIssuerRedemptionError(statusCode >= 500 ? 'Issuer redemption failed internally.' : String(error?.message || 'Issuer redemption failed.'), statusCode, statusCode >= 500 ? 'executor_phase_a_issuer_redemption_internal' : 'executor_phase_a_issuer_redemption_denied');
156
+ }
157
+ }
158
+ }
@@ -0,0 +1,14 @@
1
+ import type { TaskforceCore } from '../core/Taskforce.js';
2
+ import { GitHubReviewEvidenceInstallationStore } from '../storage/githubReviewEvidenceInstallationStore.js';
3
+ import { GitHubReviewEvidenceService, type GitHubReviewAppConfig } from './githubReviewEvidenceService.js';
4
+ export declare function createGitHubReviewEvidenceRuntime(core: TaskforceCore, options?: {
5
+ config?: GitHubReviewAppConfig | null;
6
+ fetchImpl?: typeof fetch;
7
+ apiBaseUrl?: string;
8
+ timeoutMs?: number;
9
+ now?: () => Date;
10
+ }): {
11
+ configured: boolean;
12
+ store: GitHubReviewEvidenceInstallationStore;
13
+ verifier: GitHubReviewEvidenceService;
14
+ };
@@ -0,0 +1,30 @@
1
+ import { GitHubReviewEvidenceInstallationStore } from '../storage/githubReviewEvidenceInstallationStore.js';
2
+ import { GitHubReviewEvidenceService, resolveGitHubReviewAppConfig, } from './githubReviewEvidenceService.js';
3
+ export function createGitHubReviewEvidenceRuntime(core, options = {}) {
4
+ const store = new GitHubReviewEvidenceInstallationStore(core.getDatabaseAdapter(), core.getTenantId(), options.now);
5
+ const config = options.config === undefined ? resolveGitHubReviewAppConfig() : options.config;
6
+ const verifier = new GitHubReviewEvidenceService({
7
+ config,
8
+ getBinding: (workspaceId) => store.get(workspaceId),
9
+ fetchImpl: options.fetchImpl,
10
+ apiBaseUrl: options.apiBaseUrl,
11
+ timeoutMs: options.timeoutMs,
12
+ now: options.now,
13
+ audit: (event) => {
14
+ try {
15
+ const { action, workspaceId, ...details } = event;
16
+ core.addAdminAuditLog({
17
+ action,
18
+ actorUserId: 'system',
19
+ actorRole: 'system',
20
+ workspaceId,
21
+ details,
22
+ });
23
+ }
24
+ catch {
25
+ // Verification must not change outcome when audit persistence is unavailable.
26
+ }
27
+ },
28
+ });
29
+ return { configured: config !== null, store, verifier };
30
+ }
@@ -0,0 +1,93 @@
1
+ import type { GitHubReviewEvidenceInstallationBinding } from '../storage/githubReviewEvidenceInstallationStore.js';
2
+ export type GitHubReviewEvidenceErrorCode = 'github_app_not_configured' | 'github_installation_not_bound' | 'github_installation_unavailable' | 'github_installation_revoked' | 'github_permission_denied' | 'github_rate_limited' | 'github_repository_unavailable' | 'github_evidence_mismatch' | 'github_pull_request_not_reviewable' | 'github_request_timed_out';
3
+ export declare class GitHubReviewEvidenceError extends Error {
4
+ readonly code: GitHubReviewEvidenceErrorCode;
5
+ readonly statusCode: number;
6
+ readonly retryAfterSeconds: number | null;
7
+ constructor(message: string, code: GitHubReviewEvidenceErrorCode, statusCode: number, retryAfterSeconds?: number | null);
8
+ }
9
+ export interface GitHubReviewAppConfig {
10
+ appId: string;
11
+ privateKey: string;
12
+ }
13
+ export interface GitHubInstallationInspection {
14
+ installationId: string;
15
+ accountId: string;
16
+ accountLogin: string;
17
+ accountType: string;
18
+ repositorySelection: string;
19
+ }
20
+ export interface GitHubReviewEvidenceRequest {
21
+ workspaceId: string;
22
+ repositoryFullName: string;
23
+ commitSha: string;
24
+ pullRequestNumber: number;
25
+ expectedBaseRef?: string | null;
26
+ expectedHeadRef?: string | null;
27
+ integrationBranch?: string | null;
28
+ }
29
+ export interface VerifiedGitHubReviewEvidence {
30
+ repository: {
31
+ id: string;
32
+ fullName: string;
33
+ private: boolean;
34
+ defaultBranch: string;
35
+ };
36
+ commit: {
37
+ sha: string;
38
+ };
39
+ pullRequest: {
40
+ number: number;
41
+ state: string;
42
+ merged: boolean;
43
+ mergeCommitSha: string | null;
44
+ head: {
45
+ ref: string;
46
+ sha: string;
47
+ };
48
+ base: {
49
+ ref: string;
50
+ sha: string;
51
+ };
52
+ };
53
+ integration: {
54
+ branch: string;
55
+ comparisonStatus: 'ahead' | 'identical';
56
+ containsCommit: true;
57
+ } | null;
58
+ verifiedAt: string;
59
+ }
60
+ export interface GitHubReviewEvidenceVerifier {
61
+ verify(request: GitHubReviewEvidenceRequest): Promise<VerifiedGitHubReviewEvidence>;
62
+ }
63
+ interface GitHubReviewEvidenceServiceOptions {
64
+ config: GitHubReviewAppConfig | null;
65
+ getBinding: (workspaceId: string) => GitHubReviewEvidenceInstallationBinding | null;
66
+ fetchImpl?: typeof fetch;
67
+ apiBaseUrl?: string;
68
+ timeoutMs?: number;
69
+ now?: () => Date;
70
+ audit?: (event: {
71
+ action: 'github.review-evidence.verify.succeeded' | 'github.review-evidence.verify.failed';
72
+ workspaceId: string;
73
+ repositoryFullName: string;
74
+ commitSha: string;
75
+ pullRequestNumber: number;
76
+ code?: GitHubReviewEvidenceErrorCode;
77
+ }) => void;
78
+ }
79
+ export declare function resolveGitHubReviewAppConfig(env?: NodeJS.ProcessEnv): GitHubReviewAppConfig | null;
80
+ export declare class GitHubReviewEvidenceService implements GitHubReviewEvidenceVerifier {
81
+ private readonly options;
82
+ private readonly fetchImpl;
83
+ private readonly apiBaseUrl;
84
+ private readonly timeoutMs;
85
+ private readonly now;
86
+ constructor(options: GitHubReviewEvidenceServiceOptions);
87
+ private requireConfig;
88
+ private requestJson;
89
+ inspectInstallation(installationId: string): Promise<GitHubInstallationInspection>;
90
+ private mintRepositoryToken;
91
+ verify(request: GitHubReviewEvidenceRequest): Promise<VerifiedGitHubReviewEvidence>;
92
+ }
93
+ export {};
@@ -0,0 +1,336 @@
1
+ import { sign } from 'crypto';
2
+ const DEFAULT_API_BASE_URL = 'https://api.github.com';
3
+ const API_VERSION = '2026-03-10';
4
+ const DEFAULT_TIMEOUT_MS = 10_000;
5
+ const MAX_GITHUB_RESPONSE_BYTES = 2 * 1024 * 1024;
6
+ export class GitHubReviewEvidenceError extends Error {
7
+ code;
8
+ statusCode;
9
+ retryAfterSeconds;
10
+ constructor(message, code, statusCode, retryAfterSeconds = null) {
11
+ super(message);
12
+ this.code = code;
13
+ this.statusCode = statusCode;
14
+ this.retryAfterSeconds = retryAfterSeconds;
15
+ this.name = 'GitHubReviewEvidenceError';
16
+ }
17
+ }
18
+ export function resolveGitHubReviewAppConfig(env = process.env) {
19
+ const appId = String(env.TASKFORCE_GITHUB_REVIEW_APP_ID || '').trim();
20
+ const encodedPrivateKey = String(env.TASKFORCE_GITHUB_REVIEW_APP_PRIVATE_KEY_BASE64 || '').trim();
21
+ const privateKey = encodedPrivateKey ? Buffer.from(encodedPrivateKey, 'base64').toString('utf8') : '';
22
+ return appId && privateKey ? { appId, privateKey } : null;
23
+ }
24
+ function createAppJwt(config, now) {
25
+ const issuedAt = Math.floor(now.getTime() / 1_000) - 60;
26
+ const header = Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })).toString('base64url');
27
+ const payload = Buffer.from(JSON.stringify({
28
+ iat: issuedAt,
29
+ exp: issuedAt + 9 * 60,
30
+ iss: config.appId,
31
+ })).toString('base64url');
32
+ const signingInput = `${header}.${payload}`;
33
+ try {
34
+ const signature = sign('RSA-SHA256', Buffer.from(signingInput), config.privateKey).toString('base64url');
35
+ return `${signingInput}.${signature}`;
36
+ }
37
+ catch {
38
+ throw new GitHubReviewEvidenceError('GitHub review verification is not configured correctly.', 'github_app_not_configured', 503);
39
+ }
40
+ }
41
+ function requiredString(value, label, maxLength = 255) {
42
+ const normalized = String(value || '').trim();
43
+ if (!normalized || normalized.length > maxLength || /[\u0000-\u001f\u007f]/.test(normalized)) {
44
+ throw new GitHubReviewEvidenceError(`${label} is invalid.`, 'github_evidence_mismatch', 400);
45
+ }
46
+ return normalized;
47
+ }
48
+ function normalizeRepositoryFullName(value) {
49
+ const fullName = requiredString(value, 'repositoryFullName', 201);
50
+ const parts = fullName.split('/');
51
+ if (parts.length !== 2 || !/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})$/.test(parts[0]) || !/^[A-Za-z0-9._-]{1,100}$/.test(parts[1])) {
52
+ throw new GitHubReviewEvidenceError('repositoryFullName is invalid.', 'github_evidence_mismatch', 400);
53
+ }
54
+ return { owner: parts[0], name: parts[1], fullName };
55
+ }
56
+ function normalizeSha(value) {
57
+ const sha = String(value || '').trim().toLowerCase();
58
+ if (!/^[0-9a-f]{40}$/.test(sha)) {
59
+ throw new GitHubReviewEvidenceError('commitSha must be a full 40-character SHA.', 'github_evidence_mismatch', 400);
60
+ }
61
+ return sha;
62
+ }
63
+ function retryAfterSeconds(response) {
64
+ const raw = Number(response.headers.get('retry-after'));
65
+ if (Number.isFinite(raw) && raw > 0)
66
+ return Math.ceil(raw);
67
+ const reset = Number(response.headers.get('x-ratelimit-reset'));
68
+ if (Number.isFinite(reset) && reset > 0)
69
+ return Math.max(1, Math.ceil(reset - Date.now() / 1_000));
70
+ return null;
71
+ }
72
+ function mapGitHubHttpError(response, installationRequest) {
73
+ if (response.status === 401) {
74
+ return new GitHubReviewEvidenceError('The GitHub App installation is no longer authorized.', 'github_installation_revoked', 503);
75
+ }
76
+ if (response.status === 429
77
+ || (response.status === 403 && (response.headers.get('x-ratelimit-remaining') === '0'
78
+ || response.headers.has('retry-after')))) {
79
+ return new GitHubReviewEvidenceError('GitHub verification is temporarily rate limited.', 'github_rate_limited', 503, retryAfterSeconds(response));
80
+ }
81
+ if (response.status === 403) {
82
+ return new GitHubReviewEvidenceError('The GitHub App installation lacks a required read permission.', 'github_permission_denied', 503);
83
+ }
84
+ if (response.status === 404) {
85
+ if (installationRequest) {
86
+ return new GitHubReviewEvidenceError('The GitHub App installation is no longer authorized.', 'github_installation_revoked', 503);
87
+ }
88
+ return new GitHubReviewEvidenceError('The repository or evidence is unavailable to this GitHub App installation.', 'github_repository_unavailable', 422);
89
+ }
90
+ if (response.status === 422) {
91
+ return new GitHubReviewEvidenceError('The repository or evidence is unavailable to this GitHub App installation.', 'github_repository_unavailable', 422);
92
+ }
93
+ return new GitHubReviewEvidenceError('GitHub verification is temporarily unavailable.', 'github_installation_unavailable', 503);
94
+ }
95
+ async function readBoundedJson(response) {
96
+ const contentLength = Number(response.headers.get('content-length'));
97
+ if (Number.isFinite(contentLength) && contentLength > MAX_GITHUB_RESPONSE_BYTES) {
98
+ throw new GitHubReviewEvidenceError('GitHub returned an invalid verification response.', 'github_installation_unavailable', 503);
99
+ }
100
+ if (!response.body) {
101
+ throw new GitHubReviewEvidenceError('GitHub returned an invalid verification response.', 'github_installation_unavailable', 503);
102
+ }
103
+ const reader = response.body.getReader();
104
+ const chunks = [];
105
+ let size = 0;
106
+ try {
107
+ while (true) {
108
+ const { value, done } = await reader.read();
109
+ if (done)
110
+ break;
111
+ if (!value)
112
+ continue;
113
+ size += value.byteLength;
114
+ if (size > MAX_GITHUB_RESPONSE_BYTES) {
115
+ await reader.cancel();
116
+ throw new GitHubReviewEvidenceError('GitHub returned an invalid verification response.', 'github_installation_unavailable', 503);
117
+ }
118
+ chunks.push(value);
119
+ }
120
+ const body = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk))).toString('utf8');
121
+ return JSON.parse(body);
122
+ }
123
+ catch (error) {
124
+ if (error instanceof GitHubReviewEvidenceError)
125
+ throw error;
126
+ throw new GitHubReviewEvidenceError('GitHub returned an invalid verification response.', 'github_installation_unavailable', 503);
127
+ }
128
+ finally {
129
+ reader.releaseLock();
130
+ }
131
+ }
132
+ export class GitHubReviewEvidenceService {
133
+ options;
134
+ fetchImpl;
135
+ apiBaseUrl;
136
+ timeoutMs;
137
+ now;
138
+ constructor(options) {
139
+ this.options = options;
140
+ this.fetchImpl = options.fetchImpl || fetch;
141
+ this.apiBaseUrl = String(options.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\/$/, '');
142
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
143
+ this.now = options.now || (() => new Date());
144
+ }
145
+ requireConfig() {
146
+ if (!this.options.config) {
147
+ throw new GitHubReviewEvidenceError('GitHub review verification is not configured.', 'github_app_not_configured', 503);
148
+ }
149
+ return this.options.config;
150
+ }
151
+ async requestJson(path, init, installationRequest = false) {
152
+ const controller = new AbortController();
153
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
154
+ try {
155
+ const response = await this.fetchImpl(`${this.apiBaseUrl}${path}`, {
156
+ ...init,
157
+ signal: controller.signal,
158
+ headers: {
159
+ Accept: 'application/vnd.github+json',
160
+ 'X-GitHub-Api-Version': API_VERSION,
161
+ 'User-Agent': 'taskforce-review-evidence',
162
+ ...(init.headers || {}),
163
+ },
164
+ });
165
+ if (!response.ok)
166
+ throw mapGitHubHttpError(response, installationRequest);
167
+ return await readBoundedJson(response);
168
+ }
169
+ catch (error) {
170
+ if (error instanceof GitHubReviewEvidenceError)
171
+ throw error;
172
+ if (error?.name === 'AbortError') {
173
+ throw new GitHubReviewEvidenceError('GitHub verification timed out.', 'github_request_timed_out', 503);
174
+ }
175
+ throw new GitHubReviewEvidenceError('GitHub verification is temporarily unavailable.', 'github_installation_unavailable', 503);
176
+ }
177
+ finally {
178
+ clearTimeout(timeout);
179
+ }
180
+ }
181
+ async inspectInstallation(installationId) {
182
+ const config = this.requireConfig();
183
+ const normalizedInstallationId = String(installationId || '').trim();
184
+ if (!/^\d+$/.test(normalizedInstallationId)) {
185
+ throw new GitHubReviewEvidenceError('installationId must be a numeric GitHub installation ID.', 'github_evidence_mismatch', 400);
186
+ }
187
+ const response = await this.requestJson(`/app/installations/${normalizedInstallationId}`, {
188
+ method: 'GET',
189
+ headers: { Authorization: `Bearer ${createAppJwt(config, this.now())}` },
190
+ }, true);
191
+ if (response.suspended_at) {
192
+ throw new GitHubReviewEvidenceError('The GitHub App installation is suspended.', 'github_installation_revoked', 503);
193
+ }
194
+ const permissions = response.permissions || {};
195
+ if (permissions.contents !== 'read' || permissions.pull_requests !== 'read' || permissions.metadata !== 'read') {
196
+ throw new GitHubReviewEvidenceError('The GitHub App installation lacks required read permissions.', 'github_permission_denied', 503);
197
+ }
198
+ const accountId = String(response.account?.id || '').trim();
199
+ const accountLogin = String(response.account?.login || '').trim();
200
+ if (!accountId || !accountLogin) {
201
+ throw new GitHubReviewEvidenceError('The GitHub App installation metadata is incomplete.', 'github_installation_unavailable', 503);
202
+ }
203
+ return {
204
+ installationId: String(response.id || normalizedInstallationId),
205
+ accountId,
206
+ accountLogin,
207
+ accountType: String(response.account?.type || 'unknown'),
208
+ repositorySelection: String(response.repository_selection || 'selected'),
209
+ };
210
+ }
211
+ async mintRepositoryToken(binding, repositoryName) {
212
+ const config = this.requireConfig();
213
+ const response = await this.requestJson(`/app/installations/${binding.installationId}/access_tokens`, {
214
+ method: 'POST',
215
+ headers: {
216
+ Authorization: `Bearer ${createAppJwt(config, this.now())}`,
217
+ 'Content-Type': 'application/json',
218
+ },
219
+ body: JSON.stringify({
220
+ repositories: [repositoryName],
221
+ permissions: { metadata: 'read', contents: 'read', pull_requests: 'read' },
222
+ }),
223
+ }, true);
224
+ const token = String(response.token || '').trim();
225
+ if (!token) {
226
+ throw new GitHubReviewEvidenceError('GitHub did not issue an installation token.', 'github_installation_unavailable', 503);
227
+ }
228
+ return token;
229
+ }
230
+ async verify(request) {
231
+ const workspaceId = requiredString(request.workspaceId, 'workspaceId');
232
+ const repository = normalizeRepositoryFullName(request.repositoryFullName);
233
+ const commitSha = normalizeSha(request.commitSha);
234
+ const pullRequestNumber = Number(request.pullRequestNumber);
235
+ if (!Number.isSafeInteger(pullRequestNumber) || pullRequestNumber < 1) {
236
+ throw new GitHubReviewEvidenceError('pullRequestNumber must be a positive integer.', 'github_evidence_mismatch', 400);
237
+ }
238
+ try {
239
+ const binding = this.options.getBinding(workspaceId);
240
+ if (!binding) {
241
+ throw new GitHubReviewEvidenceError('This workspace has no GitHub App installation binding.', 'github_installation_not_bound', 409);
242
+ }
243
+ const token = await this.mintRepositoryToken(binding, repository.name);
244
+ const authorization = { Authorization: `Bearer ${token}` };
245
+ const repoPath = `/repos/${encodeURIComponent(repository.owner)}/${encodeURIComponent(repository.name)}`;
246
+ const [repo, commit, pullRequest] = await Promise.all([
247
+ this.requestJson(repoPath, { method: 'GET', headers: authorization }),
248
+ this.requestJson(`${repoPath}/commits/${commitSha}`, { method: 'GET', headers: authorization }),
249
+ this.requestJson(`${repoPath}/pulls/${pullRequestNumber}`, { method: 'GET', headers: authorization }),
250
+ ]);
251
+ const actualRepo = String(repo.full_name || '').trim();
252
+ const actualCommitSha = String(commit.sha || '').trim().toLowerCase();
253
+ const headSha = String(pullRequest.head?.sha || '').trim().toLowerCase();
254
+ const headRef = String(pullRequest.head?.ref || '').trim();
255
+ const baseRef = String(pullRequest.base?.ref || '').trim();
256
+ const baseSha = String(pullRequest.base?.sha || '').trim().toLowerCase();
257
+ const headRepo = String(pullRequest.head?.repo?.full_name || '').trim();
258
+ const baseRepo = String(pullRequest.base?.repo?.full_name || '').trim();
259
+ if (actualRepo.toLowerCase() !== repository.fullName.toLowerCase()
260
+ || actualCommitSha !== commitSha
261
+ || Number(pullRequest.number) !== pullRequestNumber
262
+ || headSha !== commitSha
263
+ || headRepo.toLowerCase() !== repository.fullName.toLowerCase()
264
+ || baseRepo.toLowerCase() !== repository.fullName.toLowerCase()
265
+ || !/^[0-9a-f]{40}$/.test(baseSha)) {
266
+ throw new GitHubReviewEvidenceError('GitHub repository, commit, or pull-request evidence does not match the requested immutable identity.', 'github_evidence_mismatch', 422);
267
+ }
268
+ if (request.expectedHeadRef && headRef !== requiredString(request.expectedHeadRef, 'expectedHeadRef')) {
269
+ throw new GitHubReviewEvidenceError('The pull-request head branch does not match the expected branch.', 'github_evidence_mismatch', 422);
270
+ }
271
+ if (request.expectedBaseRef && baseRef !== requiredString(request.expectedBaseRef, 'expectedBaseRef')) {
272
+ throw new GitHubReviewEvidenceError('The pull-request base branch does not match the expected branch.', 'github_evidence_mismatch', 422);
273
+ }
274
+ const state = String(pullRequest.state || '').trim().toLowerCase();
275
+ const merged = pullRequest.merged === true;
276
+ if (state === 'closed' && !merged) {
277
+ throw new GitHubReviewEvidenceError('A closed, unmerged pull request is not valid review evidence.', 'github_pull_request_not_reviewable', 422);
278
+ }
279
+ let integration = null;
280
+ if (request.integrationBranch) {
281
+ const branch = requiredString(request.integrationBranch, 'integrationBranch');
282
+ const comparison = await this.requestJson(`${repoPath}/compare/${commitSha}...${encodeURIComponent(branch)}`, { method: 'GET', headers: authorization });
283
+ const comparisonStatus = String(comparison.status || '').trim().toLowerCase();
284
+ if (comparisonStatus !== 'ahead' && comparisonStatus !== 'identical') {
285
+ throw new GitHubReviewEvidenceError('The requested commit is not reachable from the integration branch.', 'github_evidence_mismatch', 422);
286
+ }
287
+ integration = {
288
+ branch,
289
+ comparisonStatus,
290
+ containsCommit: true,
291
+ };
292
+ }
293
+ const result = {
294
+ repository: {
295
+ id: String(repo.id || ''),
296
+ fullName: actualRepo,
297
+ private: repo.private === true,
298
+ defaultBranch: String(repo.default_branch || ''),
299
+ },
300
+ commit: { sha: actualCommitSha },
301
+ pullRequest: {
302
+ number: Number(pullRequest.number || pullRequestNumber),
303
+ state,
304
+ merged,
305
+ mergeCommitSha: pullRequest.merge_commit_sha ? String(pullRequest.merge_commit_sha).toLowerCase() : null,
306
+ head: { ref: headRef, sha: headSha },
307
+ base: { ref: baseRef, sha: baseSha },
308
+ },
309
+ integration,
310
+ verifiedAt: this.now().toISOString(),
311
+ };
312
+ this.options.audit?.({
313
+ action: 'github.review-evidence.verify.succeeded',
314
+ workspaceId,
315
+ repositoryFullName: repository.fullName,
316
+ commitSha,
317
+ pullRequestNumber,
318
+ });
319
+ return result;
320
+ }
321
+ catch (error) {
322
+ const normalized = error instanceof GitHubReviewEvidenceError
323
+ ? error
324
+ : new GitHubReviewEvidenceError('GitHub verification is temporarily unavailable.', 'github_installation_unavailable', 503);
325
+ this.options.audit?.({
326
+ action: 'github.review-evidence.verify.failed',
327
+ workspaceId,
328
+ repositoryFullName: repository.fullName,
329
+ commitSha,
330
+ pullRequestNumber,
331
+ code: normalized.code,
332
+ });
333
+ throw normalized;
334
+ }
335
+ }
336
+ }
@@ -11,6 +11,7 @@ export interface ModelGatewaySelection {
11
11
  actorUserId?: string | null;
12
12
  connectionScope?: TaskforceAgentConnectionScope;
13
13
  connectionId?: string | null;
14
+ connectionOwnerUserId?: string | null;
14
15
  }
15
16
  export interface ModelProviderCredentialResolution {
16
17
  source: TaskforceAgentModelSource;
@@ -76,6 +77,12 @@ export interface ModelGatewayGenerateResult {
76
77
  stopReason?: string;
77
78
  usage?: ModelGatewayUsage;
78
79
  latencyMs?: number;
80
+ sourceMetadata?: {
81
+ modelSource: TaskforceAgentModelSource;
82
+ connectionScope?: TaskforceAgentConnectionScope;
83
+ providerKey: string;
84
+ billable: boolean;
85
+ };
79
86
  }
80
87
  export interface ModelGateway {
81
88
  generate(input: ModelGatewayGenerateInput): Promise<ModelGatewayGenerateResult>;