@taskforcehq/taskforce 0.3.329 → 0.3.332

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 (363) hide show
  1. package/README.md +7 -2
  2. package/dist/Taskforce.module.css +290 -45
  3. package/dist/components/features/AiProfilesModule.js +3 -5
  4. package/dist/components/features/TaskSettings.js +70 -14
  5. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  6. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  7. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
  8. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
  9. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  10. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  11. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  12. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  13. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  14. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  15. package/dist/components/features/planning/PlanningModule.js +15 -3
  16. package/dist/components/features/planning/planningMetadata.d.ts +10 -0
  17. package/dist/components/features/planning/planningMetadata.js +8 -0
  18. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  19. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  20. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  21. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  22. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  23. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  24. package/dist/components/views/StandaloneLayout.js +62 -27
  25. package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
  26. package/dist/components/views/panels/PlanningDrawer.js +12 -8
  27. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  28. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  29. package/dist/config/envSchema.js +55 -1
  30. package/dist/core/McpTokenService.d.ts +25 -1
  31. package/dist/core/McpTokenService.js +106 -15
  32. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  33. package/dist/core/TaskChecklistCommandService.js +83 -5
  34. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  35. package/dist/core/TaskLifecycleCommandService.js +6 -2
  36. package/dist/core/Taskforce.d.ts +43 -3
  37. package/dist/core/Taskforce.js +158 -7
  38. package/dist/core/types.d.ts +9 -0
  39. package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
  40. package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
  41. package/dist/documentReviews/commandService.d.ts +2 -1
  42. package/dist/documentReviews/commandService.js +6 -3
  43. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  44. package/dist/hooks/sync/orchestratorShared.js +2 -0
  45. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  46. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  47. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  48. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  49. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  50. package/dist/hooks/useSyncOrchestrator.js +111 -2
  51. package/dist/hooks/useTaskData.d.ts +31 -1
  52. package/dist/hooks/useTaskData.js +29 -7
  53. package/dist/hooks/useTaskMutations.d.ts +3 -1
  54. package/dist/hooks/useTaskMutations.js +46 -12
  55. package/dist/hooks/useTaskforce.d.ts +2 -0
  56. package/dist/hooks/useTaskforce.js +11 -2
  57. package/dist/mcp/clientRegistry.d.ts +2 -2
  58. package/dist/mcp/clientRegistry.js +1 -1
  59. package/dist/mcp/documentAssetRegistrar.js +9 -6
  60. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  61. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  62. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  63. package/dist/mcp/httpProtocolRouting.d.ts +11 -0
  64. package/dist/mcp/httpProtocolRouting.js +22 -0
  65. package/dist/mcp/localCliHealth.d.ts +2 -2
  66. package/dist/mcp/localCliHealth.js +2 -2
  67. package/dist/mcp/localServiceProxy.d.ts +1 -0
  68. package/dist/mcp/localServiceProxy.js +530 -68
  69. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  70. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  71. package/dist/mcp/runtime.d.ts +54 -79
  72. package/dist/mcp/runtime.js +408 -102
  73. package/dist/mcp/taskPlanningRegistrar.js +25 -6
  74. package/dist/mcp/toolProfiles.d.ts +2 -0
  75. package/dist/mcp/toolProfiles.js +11 -0
  76. package/dist/mcp/toolRegistry.d.ts +1 -0
  77. package/dist/mcp/toolRegistry.js +9 -8
  78. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  79. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  80. package/dist/migrations/taskSchemaMigrations.js +415 -0
  81. package/dist/runtime/appGates.d.ts +2 -1
  82. package/dist/runtime/appGates.js +7 -0
  83. package/dist/server/buildInfo.d.ts +1 -0
  84. package/dist/server/buildInfo.js +5 -1
  85. package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
  86. package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
  87. package/dist/server/index.d.ts +3 -0
  88. package/dist/server/index.js +108 -11
  89. package/dist/server/localDatabaseIdentity.js +4 -1
  90. package/dist/server/localServiceLease.js +2 -1
  91. package/dist/server/localServiceSessions.d.ts +14 -17
  92. package/dist/server/localServiceSessions.js +308 -94
  93. package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
  94. package/dist/server/routes/admin.d.ts +4 -0
  95. package/dist/server/routes/admin.js +126 -5
  96. package/dist/server/routes/agents.d.ts +7 -0
  97. package/dist/server/routes/agents.js +277 -24
  98. package/dist/server/routes/billing.js +5 -1
  99. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  100. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  101. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  102. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  103. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  104. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  105. package/dist/server/routes/githubReviewEvidence.js +116 -0
  106. package/dist/server/routes/localService.d.ts +15 -4
  107. package/dist/server/routes/localService.js +136 -40
  108. package/dist/server/routes/modelConnections.d.ts +24 -0
  109. package/dist/server/routes/modelConnections.js +205 -0
  110. package/dist/server/routes/shared.d.ts +22 -0
  111. package/dist/server/routes/shared.js +298 -182
  112. package/dist/server/routes/sync.js +1 -0
  113. package/dist/server/routes/syncAuxRoutes.js +5 -1
  114. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  115. package/dist/server/routes/syncPushRoutes.js +1 -0
  116. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  117. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  118. package/dist/server/routes/tasks.js +21 -2
  119. package/dist/server/routes/workflows.js +9 -1
  120. package/dist/server/routes.js +59 -0
  121. package/dist/service/localServiceCli.d.ts +2 -2
  122. package/dist/service/localServiceCli.js +4 -3
  123. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  124. package/dist/services/codexAppServerModelGateway.js +246 -21
  125. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  126. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  127. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  128. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  129. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  130. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  131. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  132. package/dist/services/executorPhaseAApprovalService.js +609 -0
  133. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  134. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  135. package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
  136. package/dist/services/executorPhaseAIssuerCore.js +402 -0
  137. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  138. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  139. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  140. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  141. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  142. package/dist/services/githubReviewEvidenceService.js +336 -0
  143. package/dist/services/modelGateway.d.ts +7 -0
  144. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  145. package/dist/services/modelProviderConnectionService.js +279 -0
  146. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  147. package/dist/services/modelProviderCredentialHome.js +271 -0
  148. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  149. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  150. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  151. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  152. package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
  153. package/dist/services/taskforceAgentMcpBridge.js +42 -29
  154. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  155. package/dist/shared/adminEdgeProxy.js +94 -0
  156. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  157. package/dist/shared/adminProxySessionCookies.js +86 -0
  158. package/dist/shared/aiProfileColors.d.ts +31 -1
  159. package/dist/shared/aiProfileColors.js +14 -6
  160. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  161. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  162. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  163. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  164. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  165. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  166. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  167. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  168. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  169. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  170. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  171. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  172. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  173. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  174. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  175. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  176. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  177. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  178. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  179. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  180. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  181. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  182. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  183. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  184. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  185. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  186. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  187. package/dist/shared/executorPhaseATiming.js +1 -0
  188. package/dist/shared/planningIdentity.js +1 -1
  189. package/dist/shared/productLogoKeys.d.ts +2 -0
  190. package/dist/shared/productLogoKeys.js +18 -0
  191. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  192. package/dist/shared/taskforceAgentDefinition.js +6 -9
  193. package/dist/shared/taskforceAgentModels.js +7 -3
  194. package/dist/shared/userFeatureGrants.d.ts +4 -0
  195. package/dist/shared/userFeatureGrants.js +7 -0
  196. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  197. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  198. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  199. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  200. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  201. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  202. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  203. package/dist/storage/modelProviderConnectionStore.js +446 -0
  204. package/dist/storage/postgresAdapter.d.ts +4 -0
  205. package/dist/storage/postgresAdapter.js +14 -1
  206. package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
  207. package/dist/storage/postgresRequestDiagnostics.js +15 -2
  208. package/dist/storage/postgresWorker.js +20 -2
  209. package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
  210. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  211. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  212. package/dist/storage/workflowStore.d.ts +2 -0
  213. package/dist/storage/workflowStore.js +39 -2
  214. package/dist/sync/cloudSyncApi.js +4 -2
  215. package/dist/sync/collaborationSyncState.js +5 -0
  216. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  217. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  218. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  219. package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
  220. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
  221. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  222. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  223. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  224. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  225. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  226. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  227. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  228. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  229. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  230. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  231. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  232. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  233. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  234. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  235. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  236. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  237. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  238. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
  239. package/dist/sync/syncApplyHandlers.d.ts +3 -0
  240. package/dist/sync/syncApplyHandlers.js +81 -15
  241. package/dist/sync/syncService.d.ts +15 -0
  242. package/dist/sync/syncService.js +83 -18
  243. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  244. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  245. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  246. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  247. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  248. package/dist/sync/v3/durableOperationReplay.js +18 -0
  249. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  250. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  251. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  252. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  253. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  254. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  255. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  256. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
  257. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
  258. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  259. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  260. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  261. package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
  262. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  263. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  264. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  265. package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
  266. package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
  267. package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
  268. package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
  269. package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
  270. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
  271. package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
  272. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
  273. package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
  274. package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
  275. package/dist/sync/v3/syncDurabilityStore.js +202 -8
  276. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  277. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  278. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  279. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  280. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  281. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  282. package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
  283. package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
  284. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  285. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  286. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  287. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  288. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  289. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
  290. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  291. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  292. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  293. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  294. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  295. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  296. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  297. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  298. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  299. package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
  300. package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
  301. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
  302. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
  303. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  304. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  305. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  306. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  307. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  308. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
  309. package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
  310. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  311. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  312. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  313. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  314. package/dist/sync/workspaceRepair.d.ts +5 -2
  315. package/dist/sync/workspaceRepair.js +161 -6
  316. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  317. package/dist/sync/workspaceSyncModel.js +35 -7
  318. package/dist/sync/workspaceSyncState.d.ts +1 -0
  319. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  320. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  321. package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
  322. package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
  323. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
  324. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
  325. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
  326. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
  327. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
  328. package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
  329. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
  330. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
  331. package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
  332. package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
  333. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  334. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
  335. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  336. package/dist/ui/assets/index-DSQINwt9.js +7 -0
  337. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  338. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  339. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  340. package/dist/ui/branding/logos/signature_dark.png +0 -0
  341. package/dist/ui/branding/logos/signature_light.png +0 -0
  342. package/dist/ui/index.html +3 -3
  343. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  344. package/dist/utils/httpSetCookie.d.ts +1 -0
  345. package/dist/utils/httpSetCookie.js +4 -1
  346. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  347. package/dist/utils/localRuntimeUrl.js +14 -0
  348. package/dist/utils/productLogoRegistry.d.ts +2 -0
  349. package/dist/utils/productLogoRegistry.js +36 -0
  350. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  351. package/dist/utils/syncStatusPresentation.js +17 -0
  352. package/dist/utils/taskEvents.d.ts +2 -0
  353. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  354. package/dist/utils/workspaceSyncPresentation.js +23 -17
  355. package/package.json +24 -4
  356. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  357. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  358. package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
  359. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  360. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  361. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  362. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  363. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -0,0 +1,402 @@
1
+ import { createHash, createPublicKey, verify } from 'node:crypto';
2
+ import { canonicalizeExecutorPhaseAJson, } from '../shared/executorPhaseAApprovalReceipt.js';
3
+ import { executorPhaseAIssuerProofSignedBytes, executorPhaseAIssuerRedemptionAuditSha256, executorPhaseAIssuerRedemptionIntentSha256, EXECUTOR_PHASE_A_ISSUER_PROOF_PAYLOAD_SCHEMA, EXECUTOR_PHASE_A_ISSUER_PROOF_SCHEMA, EXECUTOR_PHASE_A_ISSUER_PROOF_TYPE, EXECUTOR_PHASE_A_ISSUER_REDEMPTION_PATH, EXECUTOR_PHASE_A_ISSUER_REDEMPTION_REQUEST_SCHEMA, } from '../shared/executorPhaseAIssuerContracts.js';
4
+ import { executorPhaseASourceIdentity, verifyExecutorPhaseARunCapabilityArtifact, verifyExecutorPhaseAWorkloadGrantBundle, } from '../shared/executorPhaseARunAuthorization.js';
5
+ import { assertExecutorPhaseASchema } from '../shared/executorPhaseASchemaValidation.js';
6
+ import { EXECUTOR_PHASE_A_CROSS_SERVICE_CLOCK_SKEW_MS } from '../shared/executorPhaseATiming.js';
7
+ const JWT_TTL_SECONDS = 120;
8
+ const RETIRING_KEY_OVERLAP_MS = 15 * 60 * 1000;
9
+ export const EXECUTOR_PHASE_A_OIDC_PUBLIC_CACHE_MAX_AGE_SECONDS = 300;
10
+ const TRANSITIVE_TAG_KEYS = [
11
+ 'TaskforceRun',
12
+ 'TaskforceReceipt',
13
+ 'TaskforcePhase',
14
+ 'TaskforceWorkspaceHash',
15
+ 'TaskforceSource',
16
+ ];
17
+ const verifiedWorkloadJwtClaimsBrand = Symbol('verifiedExecutorPhaseAWorkloadJwtClaims');
18
+ const verifiedWorkloadJwtClaims = new WeakSet();
19
+ function timestamp(value, field) {
20
+ const parsed = Date.parse(value);
21
+ if (!Number.isFinite(parsed))
22
+ throw new TypeError(`${field} is invalid.`);
23
+ return parsed;
24
+ }
25
+ function sha256(value) {
26
+ return createHash('sha256').update(canonicalizeExecutorPhaseAJson(value)).digest('hex');
27
+ }
28
+ function assertRsa2048(publicKey) {
29
+ if (publicKey.asymmetricKeyType !== 'rsa')
30
+ throw new TypeError('The OIDC signing key must be RSA.');
31
+ const details = publicKey.asymmetricKeyDetails;
32
+ if (details?.modulusLength !== 2048)
33
+ throw new TypeError('The OIDC signing key must be RSA-2048.');
34
+ const jwk = publicKey.export({ format: 'jwk' });
35
+ if (jwk.kty !== 'RSA' || !jwk.n || !jwk.e || jwk.d)
36
+ throw new TypeError('The OIDC public key is not a public RSA JWK.');
37
+ return jwk;
38
+ }
39
+ export function buildExecutorPhaseAOidcJwks(keys, now = new Date()) {
40
+ const nowMs = now.getTime();
41
+ const active = keys.filter((key) => key.status === 'active');
42
+ const disabled = keys.filter((key) => key.status === 'disabled');
43
+ if (active.length !== 1
44
+ || disabled.length > 1
45
+ || timestamp(active[0].validFrom, 'key.validFrom') > nowMs
46
+ || nowMs >= timestamp(active[0].validUntil, 'key.validUntil')
47
+ || new Set(keys.map((key) => key.keyId)).size !== keys.length) {
48
+ throw new TypeError('The OIDC keyring must contain exactly one current active key, at most one disabled staging key, and no key-ID reuse.');
49
+ }
50
+ for (const key of keys) {
51
+ if (key.status === 'retiring') {
52
+ if (!key.lastIssuedAt || !key.publishUntil
53
+ || timestamp(key.validFrom, 'key.validFrom') > nowMs
54
+ || timestamp(key.publishUntil, 'key.publishUntil') < timestamp(key.lastIssuedAt, 'key.lastIssuedAt') + RETIRING_KEY_OVERLAP_MS) {
55
+ throw new TypeError('A retiring OIDC key must retain the required publication overlap.');
56
+ }
57
+ }
58
+ if (key.status === 'removed' && key.lastIssuedAt
59
+ && (!key.publishUntil || timestamp(key.publishUntil, 'key.publishUntil') < timestamp(key.lastIssuedAt, 'key.lastIssuedAt') + RETIRING_KEY_OVERLAP_MS)) {
60
+ throw new TypeError('A removed OIDC key did not retain the required publication overlap.');
61
+ }
62
+ }
63
+ const staging = keys.filter((key) => key.status === 'disabled'
64
+ && key.lastIssuedAt === null
65
+ && key.publishUntil !== null
66
+ && nowMs < timestamp(key.publishUntil, 'key.publishUntil')
67
+ && nowMs < timestamp(key.validUntil, 'key.validUntil'));
68
+ const retiring = keys.filter((key) => key.status === 'retiring'
69
+ && nowMs < timestamp(key.publishUntil, 'key.publishUntil'));
70
+ if (staging.length + retiring.length > 1) {
71
+ throw new TypeError('JWKS may publish only one disabled staging or retiring secondary key.');
72
+ }
73
+ const published = [active[0], ...staging, ...retiring];
74
+ if (published.length > 2)
75
+ throw new TypeError('JWKS must publish one active key and at most one secondary key.');
76
+ return {
77
+ keys: published.map((key) => {
78
+ const jwk = assertRsa2048(key.publicKey);
79
+ return { kty: 'RSA', n: jwk.n, e: jwk.e, use: 'sig', alg: 'RS256', kid: key.keyId };
80
+ }),
81
+ };
82
+ }
83
+ export function buildExecutorPhaseAOidcDiscovery(issuer) {
84
+ const origin = new URL(issuer);
85
+ if (origin.protocol !== 'https:' || origin.origin !== issuer)
86
+ throw new TypeError('The OIDC issuer must be an HTTPS origin.');
87
+ return {
88
+ issuer,
89
+ jwks_uri: `${issuer}/.well-known/jwks.json`,
90
+ response_types_supported: ['id_token'],
91
+ subject_types_supported: ['public'],
92
+ id_token_signing_alg_values_supported: ['RS256'],
93
+ };
94
+ }
95
+ export function buildExecutorPhaseAWorkloadJwtClaims(bundle, issuer, audience, tokenId, now) {
96
+ if (!/^token-[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/.test(tokenId))
97
+ throw new TypeError('The workload token ID is invalid.');
98
+ const capability = bundle.capability.payload;
99
+ const grant = bundle.grant.payload;
100
+ if (issuer !== capability.oidcIssuer || audience !== capability.oidcAudience) {
101
+ throw new TypeError('The JWT authority differs from the verified capability.');
102
+ }
103
+ const issuedAt = Math.floor(now.getTime() / 1000);
104
+ const deadline = Math.floor(Math.min(timestamp(grant.expiresAt, 'grant.expiresAt'), timestamp(grant.phase === 'cleanup' ? capability.cleanupDeadline : capability.mutationDeadline, 'phaseDeadline')) / 1000);
105
+ const expiresAt = Math.min(issuedAt + JWT_TTL_SECONDS, deadline);
106
+ if (expiresAt <= issuedAt)
107
+ throw new TypeError('The workload JWT has no remaining authorized lifetime.');
108
+ const runDigest = createHash('sha256').update(capability.runId, 'utf8').digest('base64url');
109
+ const claims = {
110
+ iss: issuer,
111
+ aud: audience,
112
+ sub: `tfr:${runDigest}:${grant.phase}`,
113
+ iat: issuedAt,
114
+ nbf: issuedAt,
115
+ exp: expiresAt,
116
+ jti: tokenId,
117
+ 'https://aws.amazon.com/source_identity': executorPhaseASourceIdentity(capability.runId, grant.phase),
118
+ 'https://aws.amazon.com/tags': {
119
+ principal_tags: {
120
+ TaskforceRun: [grant.sessionTags.TaskforceRun],
121
+ TaskforceReceipt: [grant.sessionTags.TaskforceReceipt],
122
+ TaskforcePhase: [grant.sessionTags.TaskforcePhase],
123
+ TaskforceWorkspaceHash: [grant.sessionTags.TaskforceWorkspaceHash],
124
+ TaskforceSource: [grant.sessionTags.TaskforceSource],
125
+ },
126
+ transitive_tag_keys: TRANSITIVE_TAG_KEYS,
127
+ },
128
+ taskforce: {
129
+ schema: 'taskforce.executor-phase-a-workload-jwt-claims/v1',
130
+ receiptId: capability.receiptId,
131
+ receiptSha256: capability.receiptSha256,
132
+ workspaceId: capability.workspaceId,
133
+ taskId: capability.taskId,
134
+ runId: capability.runId,
135
+ sourceCommit: capability.sourceCommit,
136
+ accountId: capability.accountId,
137
+ region: capability.region,
138
+ availabilityZone: capability.availabilityZone,
139
+ logicalEnvelopeSha256: capability.logicalEnvelopeSha256,
140
+ budgetsSha256: capability.budgetsSha256,
141
+ roleArn: grant.roleArn,
142
+ brokerKeyFingerprint: capability.brokerKeyFingerprint,
143
+ grantId: grant.grantId,
144
+ grantSha256: bundle.grantSha256,
145
+ senderProofSha256: bundle.senderProofSha256,
146
+ },
147
+ };
148
+ assertExecutorPhaseASchema('workloadJwtClaims', claims);
149
+ return claims;
150
+ }
151
+ export async function signExecutorPhaseAWorkloadJwt(claims, signer) {
152
+ assertExecutorPhaseASchema('workloadJwtClaims', claims);
153
+ const header = { alg: 'RS256', kid: signer.keyId, typ: 'JWT' };
154
+ const signingInput = `${canonicalizeExecutorPhaseAJson(header).toString('base64url')}.${canonicalizeExecutorPhaseAJson(claims).toString('base64url')}`;
155
+ const signature = await signer.sign(Buffer.from(signingInput, 'ascii'));
156
+ if (signature.length !== 256)
157
+ throw new TypeError('The OIDC signer returned a non-RSA-2048 signature.');
158
+ return `${signingInput}.${signature.toString('base64url')}`;
159
+ }
160
+ function decodeCanonicalJwtSegment(segment, field) {
161
+ if (!/^[A-Za-z0-9_-]+$/.test(segment))
162
+ throw new TypeError(`The workload JWT ${field} is not base64url.`);
163
+ const bytes = Buffer.from(segment, 'base64url');
164
+ if (bytes.toString('base64url') !== segment)
165
+ throw new TypeError(`The workload JWT ${field} is not canonical base64url.`);
166
+ let value;
167
+ try {
168
+ value = JSON.parse(bytes.toString('utf8'));
169
+ }
170
+ catch {
171
+ throw new TypeError(`The workload JWT ${field} is not valid JSON.`);
172
+ }
173
+ if (canonicalizeExecutorPhaseAJson(value).toString('base64url') !== segment) {
174
+ throw new TypeError(`The workload JWT ${field} is not canonical JSON.`);
175
+ }
176
+ return value;
177
+ }
178
+ export function verifyExecutorPhaseAWorkloadJwt(jwt, bundle, keys, now = new Date()) {
179
+ if (jwt.length > 16_384)
180
+ throw new TypeError('The workload JWT exceeds the maximum size.');
181
+ const segments = jwt.split('.');
182
+ if (segments.length !== 3)
183
+ throw new TypeError('The workload JWT must contain exactly three segments.');
184
+ const [headerSegment, payloadSegment, signatureSegment] = segments;
185
+ const header = decodeCanonicalJwtSegment(headerSegment, 'header');
186
+ if (!header || typeof header !== 'object' || Array.isArray(header)
187
+ || Object.keys(header).sort().join(',') !== 'alg,kid,typ'
188
+ || header.alg !== 'RS256'
189
+ || header.typ !== 'JWT'
190
+ || typeof header.kid !== 'string') {
191
+ throw new TypeError('The workload JWT header is invalid.');
192
+ }
193
+ const key = keys.find((candidate) => candidate.keyId === header.kid);
194
+ const signature = Buffer.from(signatureSegment, 'base64url');
195
+ const nowMs = now.getTime();
196
+ if (new Set(keys.map((candidate) => candidate.keyId)).size !== keys.length
197
+ || !key || (key.status !== 'active' && key.status !== 'retiring')
198
+ || nowMs < timestamp(key.validFrom, 'key.validFrom')
199
+ || nowMs >= timestamp(key.validUntil, 'key.validUntil') || key.publicKey.asymmetricKeyType !== 'rsa'
200
+ || key.publicKey.asymmetricKeyDetails?.modulusLength !== 2048
201
+ || !/^[A-Za-z0-9_-]+$/.test(signatureSegment)
202
+ || signature.length !== 256 || signature.toString('base64url') !== signatureSegment
203
+ || !verify('RSA-SHA256', Buffer.from(`${headerSegment}.${payloadSegment}`, 'ascii'), key.publicKey, signature)) {
204
+ throw new TypeError('The workload JWT signature or signing key is invalid.');
205
+ }
206
+ const claims = decodeCanonicalJwtSegment(payloadSegment, 'payload');
207
+ assertExecutorPhaseASchema('workloadJwtClaims', claims);
208
+ const capability = bundle.capability.payload;
209
+ const grant = bundle.grant.payload;
210
+ const nowSeconds = Math.floor(now.getTime() / 1000);
211
+ const skewSeconds = EXECUTOR_PHASE_A_CROSS_SERVICE_CLOCK_SKEW_MS / 1000;
212
+ const grantIssuedAt = Math.floor(timestamp(grant.issuedAt, 'grant.issuedAt') / 1000);
213
+ const grantExpiresAt = Math.floor(timestamp(grant.expiresAt, 'grant.expiresAt') / 1000);
214
+ const phaseDeadline = Math.floor(timestamp(grant.phase === 'cleanup' ? capability.cleanupDeadline : capability.mutationDeadline, 'phaseDeadline') / 1000);
215
+ const runDigest = createHash('sha256').update(capability.runId, 'utf8').digest('base64url');
216
+ const tags = claims['https://aws.amazon.com/tags'];
217
+ const expectedTags = grant.sessionTags;
218
+ if (claims.iss !== capability.oidcIssuer || claims.aud !== capability.oidcAudience
219
+ || claims.sub !== `tfr:${runDigest}:${grant.phase}`
220
+ || claims['https://aws.amazon.com/source_identity'] !== executorPhaseASourceIdentity(capability.runId, grant.phase)
221
+ || claims.iat < grantIssuedAt - skewSeconds || claims.iat > nowSeconds + skewSeconds
222
+ || claims.nbf !== claims.iat
223
+ || nowSeconds >= claims.exp + skewSeconds || claims.exp <= claims.iat || claims.exp - claims.iat > JWT_TTL_SECONDS
224
+ || claims.exp > grantExpiresAt || claims.exp > phaseDeadline
225
+ || tags.principal_tags.TaskforceRun[0] !== expectedTags.TaskforceRun
226
+ || tags.principal_tags.TaskforceReceipt[0] !== expectedTags.TaskforceReceipt
227
+ || tags.principal_tags.TaskforcePhase[0] !== expectedTags.TaskforcePhase
228
+ || tags.principal_tags.TaskforceWorkspaceHash[0] !== expectedTags.TaskforceWorkspaceHash
229
+ || tags.principal_tags.TaskforceSource[0] !== expectedTags.TaskforceSource
230
+ || claims.taskforce.receiptId !== capability.receiptId
231
+ || claims.taskforce.receiptSha256 !== capability.receiptSha256
232
+ || claims.taskforce.workspaceId !== capability.workspaceId
233
+ || claims.taskforce.taskId !== capability.taskId
234
+ || claims.taskforce.runId !== capability.runId
235
+ || claims.taskforce.sourceCommit !== capability.sourceCommit
236
+ || claims.taskforce.accountId !== capability.accountId
237
+ || claims.taskforce.region !== capability.region
238
+ || claims.taskforce.availabilityZone !== capability.availabilityZone
239
+ || claims.taskforce.logicalEnvelopeSha256 !== capability.logicalEnvelopeSha256
240
+ || claims.taskforce.budgetsSha256 !== capability.budgetsSha256
241
+ || claims.taskforce.roleArn !== grant.roleArn
242
+ || claims.taskforce.brokerKeyFingerprint !== capability.brokerKeyFingerprint
243
+ || claims.taskforce.grantId !== grant.grantId
244
+ || claims.taskforce.grantSha256 !== bundle.grantSha256
245
+ || claims.taskforce.senderProofSha256 !== bundle.senderProofSha256) {
246
+ throw new TypeError('The workload JWT claims differ from the verified grant.');
247
+ }
248
+ const verified = structuredClone(claims);
249
+ const freeze = (value) => {
250
+ if (!value || typeof value !== 'object' || Object.isFrozen(value))
251
+ return;
252
+ for (const child of Object.values(value))
253
+ freeze(child);
254
+ Object.freeze(value);
255
+ };
256
+ freeze(verified);
257
+ verifiedWorkloadJwtClaims.add(verified);
258
+ return verified;
259
+ }
260
+ export function assertVerifiedExecutorPhaseAWorkloadJwtClaims(claims) {
261
+ if (!claims || typeof claims !== 'object' || !verifiedWorkloadJwtClaims.has(claims)) {
262
+ throw new TypeError('The broker requires runtime-verified workload JWT claims.');
263
+ }
264
+ }
265
+ function verifyRedemptionResponse(response, request, cloudKeys, now) {
266
+ assertExecutorPhaseASchema('issuerRedemptionResponse', response);
267
+ const trustedKey = cloudKeys.find((key) => key.keyId === response.envelope.keyId && key.status !== 'disabled');
268
+ if (!trustedKey || trustedKey.publicKey.asymmetricKeyType !== 'ed25519') {
269
+ throw new TypeError('Taskforce Cloud used an untrusted redemption-response key.');
270
+ }
271
+ const payloadBytes = canonicalizeExecutorPhaseAJson(response.payload);
272
+ const signature = Buffer.from(response.envelope.signature, 'base64url');
273
+ const redeemedAt = timestamp(response.payload.redeemedAt, 'response.redeemedAt');
274
+ const proofIssuedAt = timestamp(request.issuerProof.payload.issuedAt, 'issuerProof.issuedAt');
275
+ const proofExpiresAt = timestamp(request.issuerProof.payload.expiresAt, 'issuerProof.expiresAt');
276
+ if (response.payload.requestId !== request.requestId
277
+ || response.payload.grantId !== request.workloadGrant.payload.grantId
278
+ || response.payload.grantSha256 !== sha256(request.workloadGrant)
279
+ || response.payload.senderProofSha256 !== sha256(request.senderProof)
280
+ || response.payload.auditSha256 !== executorPhaseAIssuerRedemptionAuditSha256({
281
+ requestId: response.payload.requestId,
282
+ grantId: response.payload.grantId,
283
+ grantSha256: response.payload.grantSha256,
284
+ senderProofSha256: response.payload.senderProofSha256,
285
+ redeemedAt: response.payload.redeemedAt,
286
+ })
287
+ || redeemedAt < proofIssuedAt - EXECUTOR_PHASE_A_CROSS_SERVICE_CLOCK_SKEW_MS
288
+ || redeemedAt > now.getTime() + EXECUTOR_PHASE_A_CROSS_SERVICE_CLOCK_SKEW_MS
289
+ || redeemedAt >= proofExpiresAt + EXECUTOR_PHASE_A_CROSS_SERVICE_CLOCK_SKEW_MS
290
+ || response.envelope.payloadSha256 !== createHash('sha256').update(payloadBytes).digest('hex')
291
+ || signature.length !== 64 || !verify(null, payloadBytes, trustedKey.publicKey, signature)) {
292
+ throw new TypeError('Taskforce Cloud returned an invalid issuer redemption decision.');
293
+ }
294
+ }
295
+ export class ExecutorPhaseAIssuerCore {
296
+ options;
297
+ constructor(options) {
298
+ this.options = options;
299
+ }
300
+ async issue(input) {
301
+ const now = this.options.now?.() || new Date();
302
+ let grantId = input.workloadGrant.payload.grantId;
303
+ let acquired = false;
304
+ let redemptionConfirmed = false;
305
+ try {
306
+ const verifiedCapability = verifyExecutorPhaseARunCapabilityArtifact(input.runCapability, input.approvalReceipt, this.options.cloudArtifactPublicKey, now);
307
+ const brokerPublicKey = createPublicKey({
308
+ key: Buffer.from(verifiedCapability.payload.brokerPublicKeySpkiBase64, 'base64'),
309
+ format: 'der',
310
+ type: 'spki',
311
+ });
312
+ const intentShape = {
313
+ ...input,
314
+ issuerProof: {},
315
+ schema: EXECUTOR_PHASE_A_ISSUER_REDEMPTION_REQUEST_SCHEMA,
316
+ };
317
+ const requestSha256 = executorPhaseAIssuerRedemptionIntentSha256(intentShape);
318
+ const bundle = verifyExecutorPhaseAWorkloadGrantBundle(input.workloadGrant, verifiedCapability, input.senderProof, input.brokerRequestSha256, input.expectedPolicySha256, this.options.cloudArtifactPublicKey, brokerPublicKey, now);
319
+ const tokenId = this.options.randomId('token');
320
+ const claims = buildExecutorPhaseAWorkloadJwtClaims(bundle, this.options.issuer, this.options.audience, tokenId, now);
321
+ const acquireResult = await this.options.stateStore.acquire({
322
+ grantId,
323
+ grantSha256: bundle.grantSha256,
324
+ senderProofSha256: bundle.senderProofSha256,
325
+ requestId: input.requestId,
326
+ createdAt: now.toISOString(),
327
+ });
328
+ if (acquireResult !== 'acquired')
329
+ throw new TypeError('The workload grant already has terminal issuer state.');
330
+ acquired = true;
331
+ const proofPayload = {
332
+ schema: EXECUTOR_PHASE_A_ISSUER_PROOF_PAYLOAD_SCHEMA,
333
+ method: 'POST',
334
+ path: EXECUTOR_PHASE_A_ISSUER_REDEMPTION_PATH,
335
+ requestSha256,
336
+ grantId,
337
+ grantSha256: bundle.grantSha256,
338
+ senderProofSha256: bundle.senderProofSha256,
339
+ requestId: input.requestId,
340
+ issuedAt: now.toISOString(),
341
+ expiresAt: new Date(now.getTime() + 60_000).toISOString(),
342
+ };
343
+ const signedProofBytes = executorPhaseAIssuerProofSignedBytes(proofPayload);
344
+ const proofSignature = await this.options.issuerProofSigner.sign(signedProofBytes);
345
+ if (proofSignature.length !== 256)
346
+ throw new TypeError('The issuer proof signer returned a non-RSA-2048 signature.');
347
+ const request = {
348
+ schema: EXECUTOR_PHASE_A_ISSUER_REDEMPTION_REQUEST_SCHEMA,
349
+ requestId: input.requestId,
350
+ approvalReceipt: input.approvalReceipt,
351
+ runCapability: input.runCapability,
352
+ workloadGrant: input.workloadGrant,
353
+ senderProof: input.senderProof,
354
+ brokerRequestSha256: input.brokerRequestSha256,
355
+ expectedPolicySha256: input.expectedPolicySha256,
356
+ issuerProof: {
357
+ payload: proofPayload,
358
+ envelope: {
359
+ schema: EXECUTOR_PHASE_A_ISSUER_PROOF_SCHEMA,
360
+ typ: EXECUTOR_PHASE_A_ISSUER_PROOF_TYPE,
361
+ algorithm: 'RS256',
362
+ keyId: this.options.issuerProofSigner.keyId,
363
+ payloadSha256: createHash('sha256').update(signedProofBytes).digest('hex'),
364
+ signature: proofSignature.toString('base64url'),
365
+ },
366
+ },
367
+ };
368
+ assertExecutorPhaseASchema('issuerRedemptionRequest', request);
369
+ const response = await this.options.redeem(request);
370
+ verifyRedemptionResponse(response, request, this.options.cloudResponseKeys, this.options.now?.() || now);
371
+ redemptionConfirmed = true;
372
+ const jwt = await signExecutorPhaseAWorkloadJwt(claims, this.options.oidcSigner);
373
+ await this.options.stateStore.markSigned({
374
+ grantId,
375
+ tokenId,
376
+ kmsKeyId: this.options.oidcSigner.keyId,
377
+ updatedAt: (this.options.now?.() || now).toISOString(),
378
+ });
379
+ return jwt;
380
+ }
381
+ catch (error) {
382
+ if (acquired) {
383
+ const updatedAt = (this.options.now?.() || now).toISOString();
384
+ if (redemptionConfirmed) {
385
+ await this.options.stateStore.markFailed({
386
+ grantId,
387
+ errorCategory: error instanceof TypeError ? 'invalid_artifact' : 'issuer_failure',
388
+ updatedAt,
389
+ }).catch(() => undefined);
390
+ }
391
+ else {
392
+ await this.options.stateStore.releasePending({
393
+ grantId,
394
+ requestId: input.requestId,
395
+ updatedAt,
396
+ }).catch(() => undefined);
397
+ }
398
+ }
399
+ throw error;
400
+ }
401
+ }
402
+ }
@@ -0,0 +1,34 @@
1
+ import { type KeyObject } from 'node:crypto';
2
+ import { type ExecutorPhaseAApprovalTrustPolicy } from '../shared/executorPhaseAApprovalReceipt.js';
3
+ import { type ExecutorPhaseAIssuerProofTrustKey, type ExecutorPhaseAIssuerRedemptionRequest } from '../shared/executorPhaseAIssuerContracts.js';
4
+ import { type ExecutorPhaseARunAuthorizationStore } from '../storage/executorPhaseARunAuthorizationStore.js';
5
+ export declare class ExecutorPhaseAIssuerRedemptionError extends Error {
6
+ readonly statusCode: number;
7
+ readonly code: string;
8
+ constructor(message: string, statusCode?: number, code?: string);
9
+ }
10
+ export interface ExecutorPhaseAIssuerRedemptionCloudKey {
11
+ keyId: string;
12
+ publicKey: KeyObject;
13
+ status: 'active' | 'retiring' | 'disabled';
14
+ }
15
+ export interface ExecutorPhaseAIssuerRedemptionSigningConfig {
16
+ keyId: string;
17
+ privateKey: KeyObject;
18
+ }
19
+ export declare class ExecutorPhaseAIssuerRedemptionService {
20
+ private readonly options;
21
+ constructor(options: {
22
+ store: ExecutorPhaseARunAuthorizationStore;
23
+ responseKeys: readonly ExecutorPhaseAIssuerRedemptionCloudKey[];
24
+ issuerProofKeys: readonly ExecutorPhaseAIssuerProofTrustKey[];
25
+ responseSigning: ExecutorPhaseAIssuerRedemptionSigningConfig;
26
+ approvalPolicy: ExecutorPhaseAApprovalTrustPolicy;
27
+ now?: () => Date;
28
+ });
29
+ redeem(request: ExecutorPhaseAIssuerRedemptionRequest): {
30
+ bytes: Buffer;
31
+ digest: string;
32
+ created: boolean;
33
+ };
34
+ }
@@ -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
+ }