@nlabs/reaktor 1.18.0 → 1.20.0-reactorbox.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/README.md +290 -0
  2. package/docs/GENERATION.md +42 -16
  3. package/lib/actions/alfredFaq.js +1 -1
  4. package/lib/actions/analytics.js +1 -1
  5. package/lib/actions/apps.js +17 -2
  6. package/lib/actions/connections.js +1 -1
  7. package/lib/actions/content.js +1 -1
  8. package/lib/actions/contentGeneration.d.ts +22 -1
  9. package/lib/actions/contentGeneration.js +120 -32
  10. package/lib/actions/contentGenerationErrors.js +1 -1
  11. package/lib/actions/contentGenerationSources.d.ts +29 -0
  12. package/lib/actions/contentGenerationSources.js +103 -0
  13. package/lib/actions/conversations.js +1 -1
  14. package/lib/actions/crm.d.ts +6 -2
  15. package/lib/actions/crm.js +91 -12
  16. package/lib/actions/crmCanonicalOutcomes.d.ts +88 -0
  17. package/lib/actions/crmCanonicalOutcomes.js +398 -0
  18. package/lib/actions/crmCanonicalPolicy.d.ts +92 -0
  19. package/lib/actions/crmCanonicalPolicy.js +104 -0
  20. package/lib/actions/crmCheckoutRecovery.d.ts +72 -0
  21. package/lib/actions/crmCheckoutRecovery.js +413 -0
  22. package/lib/actions/crmCheckoutRecoveryPolicy.d.ts +38 -0
  23. package/lib/actions/crmCheckoutRecoveryPolicy.js +61 -0
  24. package/lib/actions/crmDeliveryEvents.d.ts +24 -0
  25. package/lib/actions/crmDeliveryEvents.js +207 -0
  26. package/lib/actions/crmDeliveryEvidence.d.ts +17 -0
  27. package/lib/actions/crmDeliveryEvidence.js +58 -0
  28. package/lib/actions/crmExecution.d.ts +125 -0
  29. package/lib/actions/crmExecution.js +830 -0
  30. package/lib/actions/crmFinancialEvidence.d.ts +12 -0
  31. package/lib/actions/crmFinancialEvidence.js +60 -0
  32. package/lib/actions/crmInsights.d.ts +60 -0
  33. package/lib/actions/crmInsights.js +225 -0
  34. package/lib/actions/crmLeadFollowups.d.ts +66 -0
  35. package/lib/actions/crmLeadFollowups.js +209 -0
  36. package/lib/actions/crmOutcomes.d.ts +106 -0
  37. package/lib/actions/crmOutcomes.js +289 -0
  38. package/lib/actions/crmRecoveryRetention.d.ts +13 -0
  39. package/lib/actions/crmRecoveryRetention.js +163 -0
  40. package/lib/actions/crmReminderDispatch.d.ts +10 -0
  41. package/lib/actions/crmReminderDispatch.js +65 -0
  42. package/lib/actions/crmSourceOwnership.d.ts +7 -0
  43. package/lib/actions/crmSourceOwnership.js +27 -0
  44. package/lib/actions/crmSupportInsights.d.ts +18 -0
  45. package/lib/actions/crmSupportInsights.js +47 -0
  46. package/lib/actions/crmWinback.d.ts +71 -0
  47. package/lib/actions/crmWinback.js +347 -0
  48. package/lib/actions/crmWinbackConsent.d.ts +29 -0
  49. package/lib/actions/crmWinbackConsent.js +158 -0
  50. package/lib/actions/crmWinbackPolicy.d.ts +33 -0
  51. package/lib/actions/crmWinbackPolicy.js +115 -0
  52. package/lib/actions/crmWinbackShopSource.d.ts +15 -0
  53. package/lib/actions/crmWinbackShopSource.js +63 -0
  54. package/lib/actions/crud.js +1 -1
  55. package/lib/actions/databaseAccounts.js +1 -1
  56. package/lib/actions/databaseProvisioningLease.js +1 -1
  57. package/lib/actions/dynamodb.js +1 -1
  58. package/lib/actions/email.d.ts +4 -1
  59. package/lib/actions/email.js +25 -3
  60. package/lib/actions/files.js +1 -1
  61. package/lib/actions/flags.js +1 -1
  62. package/lib/actions/geminiVideo.js +1 -1
  63. package/lib/actions/groups.js +1 -1
  64. package/lib/actions/higgsfield.js +1 -1
  65. package/lib/actions/imageGeneration.js +1 -1
  66. package/lib/actions/images.js +1 -1
  67. package/lib/actions/index.d.ts +56 -0
  68. package/lib/actions/index.js +42 -1
  69. package/lib/actions/ios.js +1 -1
  70. package/lib/actions/locations.js +1 -1
  71. package/lib/actions/merchantAccountExperiment.d.ts +50 -0
  72. package/lib/actions/merchantAccountExperiment.js +424 -0
  73. package/lib/actions/merchantAccountExperimentConfig.d.ts +7 -0
  74. package/lib/actions/merchantAccountExperimentConfig.js +32 -0
  75. package/lib/actions/merchantAccountExperimentHost.d.ts +69 -0
  76. package/lib/actions/merchantAccountExperimentHost.js +92 -0
  77. package/lib/actions/merchantAccountExperimentPolicy.d.ts +66 -0
  78. package/lib/actions/merchantAccountExperimentPolicy.js +121 -0
  79. package/lib/actions/merchantAccountExperimentRelay.d.ts +10 -0
  80. package/lib/actions/merchantAccountExperimentRelay.js +75 -0
  81. package/lib/actions/merchantCalendar.d.ts +34 -0
  82. package/lib/actions/merchantCalendar.js +119 -0
  83. package/lib/actions/merchantCalendarBookings.d.ts +17 -0
  84. package/lib/actions/merchantCalendarBookings.js +113 -0
  85. package/lib/actions/merchantCalendarDelegation.d.ts +80 -0
  86. package/lib/actions/merchantCalendarDelegation.js +353 -0
  87. package/lib/actions/merchantCalendarDiscovery.d.ts +38 -0
  88. package/lib/actions/merchantCalendarDiscovery.js +124 -0
  89. package/lib/actions/merchantCalendarEventHost.d.ts +105 -0
  90. package/lib/actions/merchantCalendarEventHost.js +16 -0
  91. package/lib/actions/merchantCalendarEventPrivacy.d.ts +7 -0
  92. package/lib/actions/merchantCalendarEventPrivacy.js +70 -0
  93. package/lib/actions/merchantCalendarEventRepository.d.ts +121 -0
  94. package/lib/actions/merchantCalendarEventRepository.js +295 -0
  95. package/lib/actions/merchantCalendarEventTransport.d.ts +65 -0
  96. package/lib/actions/merchantCalendarEventTransport.js +132 -0
  97. package/lib/actions/merchantCalendarEvents.d.ts +172 -0
  98. package/lib/actions/merchantCalendarEvents.js +365 -0
  99. package/lib/actions/merchantCalendarInvitationConsent.d.ts +28 -0
  100. package/lib/actions/merchantCalendarInvitationConsent.js +118 -0
  101. package/lib/actions/merchantCalendarManagedSource.d.ts +22 -0
  102. package/lib/actions/merchantCalendarManagedSource.js +24 -0
  103. package/lib/actions/merchantCalendarOAuth.d.ts +92 -0
  104. package/lib/actions/merchantCalendarOAuth.js +502 -0
  105. package/lib/actions/merchantCalendarOAuthConfig.d.ts +4 -0
  106. package/lib/actions/merchantCalendarOAuthConfig.js +30 -0
  107. package/lib/actions/merchantCalendarOAuthRepository.d.ts +57 -0
  108. package/lib/actions/merchantCalendarOAuthRepository.js +108 -0
  109. package/lib/actions/merchantCalendarOAuthTransport.d.ts +4 -0
  110. package/lib/actions/merchantCalendarOAuthTransport.js +25 -0
  111. package/lib/actions/merchantCalendarScopes.d.ts +4 -0
  112. package/lib/actions/merchantCalendarScopes.js +31 -0
  113. package/lib/actions/merchantFinance.d.ts +65 -0
  114. package/lib/actions/merchantFinance.js +244 -0
  115. package/lib/actions/merchantFinanceProvider.d.ts +57 -0
  116. package/lib/actions/merchantFinanceProvider.js +180 -0
  117. package/lib/actions/merchantOperations.d.ts +94 -0
  118. package/lib/actions/merchantOperations.js +489 -0
  119. package/lib/actions/messages.js +1 -1
  120. package/lib/actions/notifications.js +1 -1
  121. package/lib/actions/ollamaGeneration.js +1 -1
  122. package/lib/actions/openaiResponseSession.js +1 -1
  123. package/lib/actions/payments.js +1 -1
  124. package/lib/actions/personas.js +1 -1
  125. package/lib/actions/phoneSupport.js +1 -1
  126. package/lib/actions/posts.js +1 -1
  127. package/lib/actions/providerCredentials.d.ts +35 -0
  128. package/lib/actions/providerCredentials.js +166 -0
  129. package/lib/actions/query.js +1 -1
  130. package/lib/actions/reactions.js +1 -1
  131. package/lib/actions/rum.js +1 -1
  132. package/lib/actions/s3.d.ts +10 -7
  133. package/lib/actions/s3.js +59 -14
  134. package/lib/actions/search.js +1 -1
  135. package/lib/actions/sms.js +1 -1
  136. package/lib/actions/statistics.js +1 -1
  137. package/lib/actions/subscriptions.js +1 -1
  138. package/lib/actions/supportChannelSources.d.ts +66 -0
  139. package/lib/actions/supportChannelSources.js +183 -0
  140. package/lib/actions/supportCommerce.d.ts +62 -0
  141. package/lib/actions/supportCommerce.js +252 -0
  142. package/lib/actions/supportConnect.d.ts +39 -0
  143. package/lib/actions/supportConnect.js +224 -0
  144. package/lib/actions/supportContext.d.ts +31 -0
  145. package/lib/actions/supportContext.js +88 -0
  146. package/lib/actions/supportConversation.d.ts +102 -0
  147. package/lib/actions/supportConversation.js +100 -0
  148. package/lib/actions/supportEmailEvents.d.ts +20 -0
  149. package/lib/actions/supportEmailEvents.js +130 -0
  150. package/lib/actions/supportEmailHandoff.d.ts +114 -0
  151. package/lib/actions/supportEmailHandoff.js +356 -0
  152. package/lib/actions/supportOperations.d.ts +32 -0
  153. package/lib/actions/supportOperations.js +74 -0
  154. package/lib/actions/supportPolicy.d.ts +9 -0
  155. package/lib/actions/supportPolicy.js +44 -0
  156. package/lib/actions/supportPurposeConsent.d.ts +32 -0
  157. package/lib/actions/supportPurposeConsent.js +196 -0
  158. package/lib/actions/supportPurposePrivacy.d.ts +15 -0
  159. package/lib/actions/supportPurposePrivacy.js +181 -0
  160. package/lib/actions/supportSemanticReview.d.ts +64 -0
  161. package/lib/actions/supportSemanticReview.js +239 -0
  162. package/lib/actions/tags.js +1 -1
  163. package/lib/actions/users.js +22 -3
  164. package/lib/actions/videoGeneration.js +1 -1
  165. package/lib/actions/videos.js +1 -1
  166. package/lib/adapters/arangoAdapter.js +1 -1
  167. package/lib/adapters/contentAdapter.js +1 -1
  168. package/lib/adapters/fileAdapter.js +1 -1
  169. package/lib/adapters/geminiGenerationAdapter.js +1 -1
  170. package/lib/adapters/higgsfieldAdapter.js +1 -1
  171. package/lib/adapters/higgsfieldModelCatalog.js +1 -1
  172. package/lib/adapters/higgsfieldModels.js +1 -1
  173. package/lib/adapters/imageAdapter.js +1 -1
  174. package/lib/adapters/imageGenerationAdapter.js +1 -1
  175. package/lib/adapters/index.js +1 -1
  176. package/lib/adapters/messageAdapter.js +1 -1
  177. package/lib/adapters/postAdapter.js +1 -1
  178. package/lib/adapters/reaktorAdapter.js +1 -1
  179. package/lib/adapters/tagAdapter.js +1 -1
  180. package/lib/adapters/userAdapter.js +1 -1
  181. package/lib/assistant/core.js +1 -1
  182. package/lib/assistant/faq.js +1 -1
  183. package/lib/assistant/faqCore.js +1 -1
  184. package/lib/assistant/index.js +1 -1
  185. package/lib/assistant/service.js +1 -1
  186. package/lib/config.js +1 -1
  187. package/lib/constants/collections.d.ts +2 -1
  188. package/lib/constants/collections.js +2 -1
  189. package/lib/durableChat/conversations.js +1 -1
  190. package/lib/durableChat/errors.js +1 -1
  191. package/lib/durableChat/events.js +1 -1
  192. package/lib/durableChat/index.js +1 -1
  193. package/lib/durableChat/membership.js +1 -1
  194. package/lib/durableChat/messageTypes.js +1 -1
  195. package/lib/durableChat/messages.js +1 -1
  196. package/lib/durableChat/transaction.js +1 -1
  197. package/lib/durableChat/types.js +1 -1
  198. package/lib/handlers/graphqlHandler.js +1 -1
  199. package/lib/index.js +1 -1
  200. package/lib/lambdas/actions/websockets.js +1 -1
  201. package/lib/lambdas/authorizer.js +1 -1
  202. package/lib/lambdas/connection.js +1 -1
  203. package/lib/lambdas/utils/message.js +1 -1
  204. package/lib/lambdas/utils/websocket.js +1 -1
  205. package/lib/mocks/conversation.js +1 -1
  206. package/lib/mocks/file.js +1 -1
  207. package/lib/mocks/group.js +1 -1
  208. package/lib/mocks/image.js +1 -1
  209. package/lib/mocks/post.js +1 -1
  210. package/lib/mocks/tag.js +1 -1
  211. package/lib/mocks/user.js +1 -1
  212. package/lib/mocks/video.js +1 -1
  213. package/lib/mutations/analytics/analytics.js +1 -1
  214. package/lib/mutations/content/content.js +1 -1
  215. package/lib/mutations/crm/crm.js +395 -7
  216. package/lib/mutations/events/events.js +1 -1
  217. package/lib/mutations/flags/flags.js +1 -1
  218. package/lib/mutations/groups/groups.js +1 -1
  219. package/lib/mutations/higgsfield/higgsfield.js +1 -1
  220. package/lib/mutations/images/images.js +1 -1
  221. package/lib/mutations/index.js +1 -1
  222. package/lib/mutations/locations/locations.js +1 -1
  223. package/lib/mutations/messages/messages.js +1 -1
  224. package/lib/mutations/personas/personas.js +1 -1
  225. package/lib/mutations/posts/posts.js +1 -1
  226. package/lib/mutations/reactions/reactions.js +1 -1
  227. package/lib/mutations/rum/rum.js +1 -1
  228. package/lib/mutations/statistics/statistics.js +1 -1
  229. package/lib/mutations/subscriptions/subscriptions.js +1 -1
  230. package/lib/mutations/tags/tags.js +1 -1
  231. package/lib/mutations/users/users.js +1 -1
  232. package/lib/mutations/videos/videos.js +1 -1
  233. package/lib/nativePush/graphql.js +1 -1
  234. package/lib/nativePush/index.js +1 -1
  235. package/lib/nativePush/migrations.js +1 -1
  236. package/lib/nativePush/nativePushContract.fixture.js +1 -1
  237. package/lib/nativePush/payload.js +1 -1
  238. package/lib/nativePush/repository.js +1 -1
  239. package/lib/nativePush/service.js +1 -1
  240. package/lib/nativePush/snsProvider.js +1 -1
  241. package/lib/nativePush/types.js +1 -1
  242. package/lib/objectTypes/analytics.js +1 -1
  243. package/lib/objectTypes/app.js +1 -1
  244. package/lib/objectTypes/bankAccount.js +1 -1
  245. package/lib/objectTypes/connection.js +1 -1
  246. package/lib/objectTypes/content.js +1 -1
  247. package/lib/objectTypes/contentGeneration.js +1 -1
  248. package/lib/objectTypes/conversation.js +1 -1
  249. package/lib/objectTypes/creditCard.js +1 -1
  250. package/lib/objectTypes/crm.js +1 -1
  251. package/lib/objectTypes/document.js +1 -1
  252. package/lib/objectTypes/error.js +1 -1
  253. package/lib/objectTypes/event.js +1 -1
  254. package/lib/objectTypes/external.js +1 -1
  255. package/lib/objectTypes/file.js +1 -1
  256. package/lib/objectTypes/filter.js +1 -1
  257. package/lib/objectTypes/flag.js +1 -1
  258. package/lib/objectTypes/group.js +1 -1
  259. package/lib/objectTypes/higgsfield.js +1 -1
  260. package/lib/objectTypes/iapSubscription.js +1 -1
  261. package/lib/objectTypes/image.js +1 -1
  262. package/lib/objectTypes/imageGeneration.js +1 -1
  263. package/lib/objectTypes/index.js +1 -1
  264. package/lib/objectTypes/location.js +1 -1
  265. package/lib/objectTypes/message.js +1 -1
  266. package/lib/objectTypes/passcode.js +1 -1
  267. package/lib/objectTypes/persona.js +1 -1
  268. package/lib/objectTypes/plan.js +1 -1
  269. package/lib/objectTypes/post.js +1 -1
  270. package/lib/objectTypes/query.js +1 -1
  271. package/lib/objectTypes/reaction.js +1 -1
  272. package/lib/objectTypes/relation.js +1 -1
  273. package/lib/objectTypes/rum.js +1 -1
  274. package/lib/objectTypes/search.js +1 -1
  275. package/lib/objectTypes/statistics.js +1 -1
  276. package/lib/objectTypes/subscription.js +1 -1
  277. package/lib/objectTypes/tag.js +1 -1
  278. package/lib/objectTypes/user.js +1 -1
  279. package/lib/objectTypes/video.js +1 -1
  280. package/lib/objectTypes/videoGeneration.js +1 -1
  281. package/lib/organizations/accountLifecycle.js +1 -1
  282. package/lib/organizations/authorization.js +1 -1
  283. package/lib/organizations/billing.js +1 -1
  284. package/lib/organizations/billingProvider.js +1 -1
  285. package/lib/organizations/billingUpdates.js +1 -1
  286. package/lib/organizations/index.js +1 -1
  287. package/lib/organizations/mail.js +1 -1
  288. package/lib/organizations/memberDirectory.js +1 -1
  289. package/lib/organizations/membership.js +1 -1
  290. package/lib/organizations/passwordRecovery.js +1 -1
  291. package/lib/organizations/plans.js +1 -1
  292. package/lib/organizations/providerPagination.js +1 -1
  293. package/lib/organizations/reconciliation.js +1 -1
  294. package/lib/organizations/signup.js +1 -1
  295. package/lib/organizations/store.js +1 -1
  296. package/lib/organizations/types.js +1 -1
  297. package/lib/organizations/verification.js +1 -1
  298. package/lib/queries/analytics/analytics.js +1 -1
  299. package/lib/queries/content/content.js +1 -1
  300. package/lib/queries/crm/crm.js +251 -5
  301. package/lib/queries/events/events.js +1 -1
  302. package/lib/queries/flags/flags.js +1 -1
  303. package/lib/queries/groups/groups.js +1 -1
  304. package/lib/queries/higgsfield/higgsfield.js +1 -1
  305. package/lib/queries/images/images.js +1 -1
  306. package/lib/queries/index.js +1 -1
  307. package/lib/queries/locations/locations.js +1 -1
  308. package/lib/queries/messages/messages.js +1 -1
  309. package/lib/queries/personas/personas.js +1 -1
  310. package/lib/queries/posts/posts.js +1 -1
  311. package/lib/queries/query/query.js +1 -1
  312. package/lib/queries/reactions/reactions.js +1 -1
  313. package/lib/queries/statistics/statistics.js +1 -1
  314. package/lib/queries/subscriptions/subscriptions.js +1 -1
  315. package/lib/queries/tags/tags.js +1 -1
  316. package/lib/queries/users/users.js +1 -1
  317. package/lib/queries/videos/videos.js +1 -1
  318. package/lib/templates/email/layout.js +1 -1
  319. package/lib/templates/email/passwordForgot.js +1 -1
  320. package/lib/templates/email/passwordRecovery.js +1 -1
  321. package/lib/templates/email/verifyEmail.js +1 -1
  322. package/lib/templates/email/welcome.js +1 -1
  323. package/lib/templates/sms/passwordForgot.js +1 -1
  324. package/lib/templates/sms/passwordRecovery.js +1 -1
  325. package/lib/templates/sms/verifyEmail.js +1 -1
  326. package/lib/templates/sms/verifyPhone.js +1 -1
  327. package/lib/templates/sms/welcome.js +1 -1
  328. package/lib/types/analytics.types.js +1 -1
  329. package/lib/types/apps.types.js +1 -1
  330. package/lib/types/arangodb.types.js +1 -1
  331. package/lib/types/auth.types.d.ts +2 -0
  332. package/lib/types/auth.types.js +1 -1
  333. package/lib/types/connections.types.js +1 -1
  334. package/lib/types/content.types.js +1 -1
  335. package/lib/types/conversations.types.js +1 -1
  336. package/lib/types/crm.types.d.ts +6 -0
  337. package/lib/types/crm.types.js +1 -1
  338. package/lib/types/databaseCredentials.types.js +1 -1
  339. package/lib/types/email.types.js +1 -1
  340. package/lib/types/error.types.js +1 -1
  341. package/lib/types/files.types.js +1 -1
  342. package/lib/types/flags.types.js +1 -1
  343. package/lib/types/google.types.js +1 -1
  344. package/lib/types/groups.types.js +1 -1
  345. package/lib/types/images.types.js +1 -1
  346. package/lib/types/index.js +1 -1
  347. package/lib/types/locations.types.js +1 -1
  348. package/lib/types/messages.types.js +1 -1
  349. package/lib/types/notifications.types.js +1 -1
  350. package/lib/types/payments.types.js +1 -1
  351. package/lib/types/personas.types.js +1 -1
  352. package/lib/types/posts.types.js +1 -1
  353. package/lib/types/rum.types.js +1 -1
  354. package/lib/types/statistics.types.js +1 -1
  355. package/lib/types/tags.types.js +1 -1
  356. package/lib/types/users.types.d.ts +2 -0
  357. package/lib/types/users.types.js +1 -1
  358. package/lib/types/videos.types.js +1 -1
  359. package/lib/types/websockets.types.js +1 -1
  360. package/lib/upload.js +1 -1
  361. package/lib/utils/adapterUtils.js +1 -1
  362. package/lib/utils/analyticsUtils.js +1 -1
  363. package/lib/utils/appContext.js +1 -1
  364. package/lib/utils/aqlHelpers.js +1 -1
  365. package/lib/utils/arangodbUtils.js +1 -1
  366. package/lib/utils/authUtils.js +17 -1
  367. package/lib/utils/awsUtils.js +1 -1
  368. package/lib/utils/collectionRegistry.js +1 -1
  369. package/lib/utils/contextUtils.js +1 -1
  370. package/lib/utils/databaseCredentials.js +1 -1
  371. package/lib/utils/dbI18n.example.js +1 -1
  372. package/lib/utils/dbI18n.js +1 -1
  373. package/lib/utils/generationCallback.js +1 -1
  374. package/lib/utils/googleTranslate.js +1 -1
  375. package/lib/utils/graphqlUtils.d.ts +2 -0
  376. package/lib/utils/graphqlUtils.js +1 -1
  377. package/lib/utils/imageUtils.js +1 -1
  378. package/lib/utils/index.js +1 -1
  379. package/lib/utils/languageDetection.js +1 -1
  380. package/lib/utils/localeUtils.example.js +1 -1
  381. package/lib/utils/localeUtils.js +1 -1
  382. package/lib/utils/mediaAccess.js +1 -1
  383. package/lib/utils/middlewareUtils.js +1 -1
  384. package/lib/utils/nodeRealtime.js +1 -1
  385. package/lib/utils/opaqueToken.js +1 -1
  386. package/lib/utils/queryBuilder.js +1 -1
  387. package/lib/utils/schemaUtils.js +1 -1
  388. package/lib/utils/secretDatabase.js +1 -1
  389. package/lib/utils/sessionUtils.js +1 -1
  390. package/lib/utils/stripeUtils.js +1 -1
  391. package/lib/utils/templateUtils.js +1 -1
  392. package/lib/utils/testUtils.js +1 -1
  393. package/lib/utils/translationQueue.example.js +1 -1
  394. package/lib/utils/translationQueue.js +1 -1
  395. package/lib/videoProcessing.js +1 -1
  396. package/package.json +8 -6
@@ -0,0 +1,183 @@
1
+ /* eslint-disable no-underscore-dangle -- Native source document revisions. */ import { aql } from 'arangojs';
2
+ import { createHash, randomUUID } from 'node:crypto';
3
+ import { scopeContextToApp } from '../utils/appContext.js';
4
+ import { useDb } from '../utils/arangodbUtils.js';
5
+ import { requireCrmAdministrator } from './crm.js';
6
+ import { ensureOwnerExecutionCollection } from './crmExecution.js';
7
+ export const supportChannelCollections = [
8
+ 'supportChannelSources',
9
+ 'supportChannelBindings',
10
+ 'supportChannelEvents',
11
+ 'supportChannelTombstones'
12
+ ];
13
+ export const supportChannelHash = (value)=>createHash('sha256').update(JSON.stringify(value)).digest('hex');
14
+ export const supportChannelId = (value)=>typeof value === 'string' && /^[\w.-]{1,160}$/.test(value);
15
+ export const validSupportConnectSource = (source, appId, at)=>Boolean(source && source.appId === appId && source.enabled === true && supportChannelId(source.sourceId) && supportChannelId(source._rev) && source.databaseName && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(source.generation) && Number.isSafeInteger(source.expiresAt) && source.expiresAt > at && /^arn:aws(?:-[a-z]+)?:connect:[a-z0-9-]+:\d{12}:instance\/[a-f0-9-]{36}$/.test(source.instanceArn) && /^arn:aws(?:-[a-z]+)?:iam::\d{12}:role\/[\w+=,.@-]{1,64}$/.test(source.allowedCallerRoleArn) && source.instanceArn.split(':')[1] === source.allowedCallerRoleArn.split(':')[1] && source.instanceArn.split(':')[4] === source.allowedCallerRoleArn.split(':')[4]);
16
+ export const readSupportChannelTicket = async (context, appId, ticketId)=>{
17
+ const scoped = await scopeContextToApp(context, appId);
18
+ const row = await useDb(scoped.databaseName).query(aql`LET ticket = DOCUMENT('supportTickets', ${ticketId})
19
+ LET user = ticket ? DOCUMENT('users', ticket.userId) : null
20
+ RETURN {ticket: ticket ? {_key: ticket._key, _rev: ticket._rev, appId: ticket.appId,
21
+ deleted: ticket.deleted, userId: ticket.userId, status: ticket.status} : null,
22
+ user: user ? {_key: user._key, _rev: user._rev, appId: user.appId, deleted: user.deleted} : null}`).then((cursor)=>cursor.next());
23
+ if (!row?.ticket || !row.user || row.ticket._key !== ticketId || !supportChannelId(row.user._key) || row.ticket.appId !== appId || row.user.appId !== appId || row.ticket.deleted === true || row.user.deleted === true || row.ticket.userId !== row.user._key || !supportChannelId(row.ticket._rev) || !supportChannelId(row.user._rev) || ![
24
+ 'submitted',
25
+ 'open',
26
+ 'in_progress',
27
+ 'waiting_on_customer',
28
+ 'waiting_on_internal'
29
+ ].includes(row.ticket.status)) {
30
+ throw new Error('support_channel_ticket_hold');
31
+ }
32
+ return {
33
+ databaseName: scoped.databaseName,
34
+ ticket: row.ticket,
35
+ user: row.user
36
+ };
37
+ };
38
+ const setup = async (context)=>{
39
+ const db = useDb(context.databaseName);
40
+ await Promise.all(supportChannelCollections.map((name)=>ensureOwnerExecutionCollection(db, name)));
41
+ return db;
42
+ };
43
+ /** Administrator-reviewed source declaration. No AWS credentials or automatic intake/send authority. */ export const configureSupportConnectSource = async (context, input, now = Date.now)=>{
44
+ requireCrmAdministrator(context);
45
+ if (!input || Object.keys(input).some((key)=>![
46
+ 'allowedCallerRoleArn',
47
+ 'appId',
48
+ 'enabled',
49
+ 'expectedRevision',
50
+ 'expiresAt',
51
+ 'instanceArn',
52
+ 'sourceId'
53
+ ].includes(key)) || !supportChannelId(input.appId) || !supportChannelId(input.sourceId) || typeof input.enabled !== 'boolean' || !Number.isSafeInteger(input.expiresAt) || input.expiresAt <= now() || input.expiresAt - now() > 30 * 86400000 || input.expectedRevision !== undefined && !supportChannelId(input.expectedRevision)) {
54
+ throw new Error('invalid_support_channel_source');
55
+ }
56
+ const scoped = await scopeContextToApp(context, input.appId);
57
+ const candidate = {
58
+ ...input,
59
+ _key: supportChannelHash([
60
+ input.appId,
61
+ input.sourceId
62
+ ]),
63
+ _rev: 'candidate',
64
+ databaseName: scoped.databaseName,
65
+ enabled: true,
66
+ generation: randomUUID(),
67
+ modifiedAt: now()
68
+ };
69
+ if (!validSupportConnectSource(candidate, input.appId, now())) {
70
+ throw new Error('invalid_support_channel_source');
71
+ }
72
+ const db = await setup(context);
73
+ const { _rev: _revision, expectedRevision, ...stored } = {
74
+ ...candidate,
75
+ enabled: input.enabled
76
+ };
77
+ const result = await db.query(expectedRevision ? aql`LET prior = DOCUMENT('supportChannelSources', ${candidate._key})
78
+ FILTER prior._rev == ${expectedRevision}
79
+ REPLACE {_key: ${candidate._key}, _rev: ${expectedRevision}} WITH ${stored}
80
+ IN supportChannelSources OPTIONS {ignoreRevs: false} RETURN NEW` : aql`INSERT ${stored} IN supportChannelSources RETURN NEW`).then((cursor)=>cursor.next());
81
+ if (!result) {
82
+ throw new Error('support_channel_source_changed');
83
+ }
84
+ return {
85
+ appId: input.appId,
86
+ enabled: result.enabled,
87
+ expiresAt: result.expiresAt,
88
+ revision: result._rev,
89
+ sourceId: input.sourceId
90
+ };
91
+ };
92
+ /** Explicit association; a contact's existence is subsequently checked with Connect, never by email or phone. */ export const bindSupportConnectConversation = async (context, input, now = Date.now)=>{
93
+ requireCrmAdministrator(context);
94
+ if (!input || Object.keys(input).sort().join(',') !== 'appId,contactId,expiresAt,sourceId,sourceRevision,ticketId,ticketRevision' || ![
95
+ input.appId,
96
+ input.sourceId,
97
+ input.sourceRevision,
98
+ input.ticketId,
99
+ input.ticketRevision
100
+ ].every(supportChannelId) || !/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(input.contactId) || !Number.isSafeInteger(input.expiresAt) || input.expiresAt <= now()) {
101
+ throw new Error('invalid_support_channel_binding');
102
+ }
103
+ const db = await setup(context);
104
+ const source = await db.query(aql`RETURN DOCUMENT('supportChannelSources', ${supportChannelHash([
105
+ input.appId,
106
+ input.sourceId
107
+ ])})`).then((cursor)=>cursor.next());
108
+ const row = await readSupportChannelTicket(context, input.appId, input.ticketId);
109
+ if (!validSupportConnectSource(source, input.appId, now()) || source._rev !== input.sourceRevision || source.databaseName !== row.databaseName || row.ticket._rev !== input.ticketRevision || input.expiresAt > source.expiresAt) {
110
+ throw new Error('support_channel_binding_hold');
111
+ }
112
+ const tombstoneKey = supportChannelHash([
113
+ input.appId,
114
+ input.sourceId,
115
+ input.contactId
116
+ ]);
117
+ const binding = {
118
+ ...input,
119
+ _key: supportChannelHash([
120
+ source.generation,
121
+ input.contactId
122
+ ]),
123
+ generation: source.generation,
124
+ nativeUserId: row.user._key,
125
+ nativeUserRevision: row.user._rev,
126
+ tombstoneKey
127
+ };
128
+ const result = await db.query(aql`LET current = DOCUMENT('supportChannelSources', ${source._key})
129
+ LET tombstone = DOCUMENT('supportChannelTombstones', ${tombstoneKey})
130
+ LET prior = DOCUMENT('supportChannelBindings', ${binding._key})
131
+ LET matching = (FOR item IN supportChannelBindings FILTER item.appId == ${input.appId}
132
+ AND item.sourceId == ${input.sourceId} AND item.generation == ${source.generation}
133
+ AND item.contactId == ${input.contactId} LIMIT 2 RETURN item._key)
134
+ FILTER LENGTH(matching) == 0 OR (LENGTH(matching) == 1 AND matching[0] == ${binding._key})
135
+ FILTER current._rev == ${source._rev} AND current.enabled == true AND current.expiresAt > ${now()}
136
+ AND tombstone == null AND (prior == null OR prior == MERGE(${binding}, {_id: prior._id, _rev: prior._rev}))
137
+ UPSERT {_key: ${binding._key}} INSERT ${binding} UPDATE {} IN supportChannelBindings RETURN NEW`).then((cursor)=>cursor.next());
138
+ if (!result) {
139
+ throw new Error('support_channel_binding_changed');
140
+ }
141
+ return {
142
+ appId: input.appId,
143
+ bindingId: result._key,
144
+ expiresAt: result.expiresAt,
145
+ revision: result._rev,
146
+ sourceId: input.sourceId,
147
+ ticketId: input.ticketId,
148
+ ticketRevision: input.ticketRevision
149
+ };
150
+ };
151
+ /** Administrative privacy erasure keeps an opaque tombstone to prevent old contact evidence being recreated. */ export const eraseSupportConnectEvidence = async (context, input, now = Date.now)=>{
152
+ requireCrmAdministrator(context);
153
+ if (!input || Object.keys(input).sort().join(',') !== 'appId,bindingId' || !supportChannelId(input.appId) || !/^[a-f0-9]{64}$/.test(input.bindingId)) {
154
+ throw new Error('invalid_support_channel_erasure');
155
+ }
156
+ await scopeContextToApp(context, input.appId);
157
+ const db = await setup(context);
158
+ const transaction = await db.beginTransaction({
159
+ exclusive: [
160
+ ...supportChannelCollections
161
+ ]
162
+ });
163
+ try {
164
+ const result = await transaction.step(()=>db.query(aql`LET binding = DOCUMENT('supportChannelBindings', ${input.bindingId})
165
+ FILTER binding.appId == ${input.appId}
166
+ LET removed = (FOR event IN supportChannelEvents FILTER event.bindingId == ${input.bindingId}
167
+ REMOVE event IN supportChannelEvents RETURN OLD._key)
168
+ UPSERT {_key: binding.tombstoneKey} INSERT {_key: binding.tombstoneKey, appId: ${input.appId}, erasedAt: ${now()}}
169
+ UPDATE {} IN supportChannelTombstones
170
+ REPLACE binding WITH {_key: binding._key, appId: binding.appId, erasedAt: ${now()},
171
+ tombstoneKey: binding.tombstoneKey} IN supportChannelBindings RETURN {erased: true}`)).then((cursor)=>cursor.next());
172
+ if (!result) {
173
+ throw new Error('support_channel_binding_hold');
174
+ }
175
+ await transaction.commit();
176
+ return result;
177
+ } catch (error) {
178
+ await transaction.abort();
179
+ throw error;
180
+ }
181
+ };
182
+
183
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvYWN0aW9ucy9zdXBwb3J0Q2hhbm5lbFNvdXJjZXMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tdW5kZXJzY29yZS1kYW5nbGUgLS0gTmF0aXZlIHNvdXJjZSBkb2N1bWVudCByZXZpc2lvbnMuICovXG5pbXBvcnQge2FxbH0gZnJvbSAnYXJhbmdvanMnO1xuaW1wb3J0IHtjcmVhdGVIYXNoLCByYW5kb21VVUlEfSBmcm9tICdub2RlOmNyeXB0byc7XG5cbmltcG9ydCB7c2NvcGVDb250ZXh0VG9BcHB9IGZyb20gJy4uL3V0aWxzL2FwcENvbnRleHQuanMnO1xuaW1wb3J0IHt1c2VEYn0gZnJvbSAnLi4vdXRpbHMvYXJhbmdvZGJVdGlscy5qcyc7XG5pbXBvcnQge3JlcXVpcmVDcm1BZG1pbmlzdHJhdG9yfSBmcm9tICcuL2NybS5qcyc7XG5pbXBvcnQge2Vuc3VyZU93bmVyRXhlY3V0aW9uQ29sbGVjdGlvbn0gZnJvbSAnLi9jcm1FeGVjdXRpb24uanMnO1xuXG5pbXBvcnQgdHlwZSB7QXBpQ29udGV4dH0gZnJvbSAnLi4vdHlwZXMvYXV0aC50eXBlcy5qcyc7XG5cbmV4cG9ydCBjb25zdCBzdXBwb3J0Q2hhbm5lbENvbGxlY3Rpb25zID0gWydzdXBwb3J0Q2hhbm5lbFNvdXJjZXMnLCAnc3VwcG9ydENoYW5uZWxCaW5kaW5ncycsXG4gICdzdXBwb3J0Q2hhbm5lbEV2ZW50cycsICdzdXBwb3J0Q2hhbm5lbFRvbWJzdG9uZXMnXSBhcyBjb25zdDtcbmV4cG9ydCBjb25zdCBzdXBwb3J0Q2hhbm5lbEhhc2ggPSAodmFsdWU6IHVua25vd24pOiBzdHJpbmcgPT4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKEpTT04uc3RyaW5naWZ5KHZhbHVlKSkuZGlnZXN0KCdoZXgnKTtcbmV4cG9ydCBjb25zdCBzdXBwb3J0Q2hhbm5lbElkID0gKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgc3RyaW5nID0+IHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgL15bXFx3Li1dezEsMTYwfSQvLnRlc3QodmFsdWUpO1xuZXhwb3J0IGludGVyZmFjZSBTdXBwb3J0Q29ubmVjdFNvdXJjZUlucHV0IHtcbiAgYWxsb3dlZENhbGxlclJvbGVBcm46IHN0cmluZztcbiAgYXBwSWQ6IHN0cmluZztcbiAgZW5hYmxlZDogYm9vbGVhbjtcbiAgZXhwZWN0ZWRSZXZpc2lvbj86IHN0cmluZztcbiAgZXhwaXJlc0F0OiBudW1iZXI7XG4gIGluc3RhbmNlQXJuOiBzdHJpbmc7XG4gIHNvdXJjZUlkOiBzdHJpbmc7XG59XG5leHBvcnQgaW50ZXJmYWNlIFN1cHBvcnRDb25uZWN0U291cmNlIGV4dGVuZHMgU3VwcG9ydENvbm5lY3RTb3VyY2VJbnB1dCB7XG4gIF9rZXk6IHN0cmluZztcbiAgX3Jldjogc3RyaW5nO1xuICBkYXRhYmFzZU5hbWU6IHN0cmluZztcbiAgZ2VuZXJhdGlvbjogc3RyaW5nO1xuICBtb2RpZmllZEF0OiBudW1iZXI7XG59XG5leHBvcnQgaW50ZXJmYWNlIFN1cHBvcnRDb25uZWN0QmluZGluZ0lucHV0IHtcbiAgYXBwSWQ6IHN0cmluZztcbiAgY29udGFjdElkOiBzdHJpbmc7XG4gIGV4cGlyZXNBdDogbnVtYmVyO1xuICBzb3VyY2VJZDogc3RyaW5nO1xuICBzb3VyY2VSZXZpc2lvbjogc3RyaW5nO1xuICB0aWNrZXRJZDogc3RyaW5nO1xuICB0aWNrZXRSZXZpc2lvbjogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBTdXBwb3J0Q29ubmVjdEJpbmRpbmcgZXh0ZW5kcyBTdXBwb3J0Q29ubmVjdEJpbmRpbmdJbnB1dCB7XG4gIF9rZXk6IHN0cmluZztcbiAgX3Jldjogc3RyaW5nO1xuICBnZW5lcmF0aW9uOiBzdHJpbmc7XG4gIG5hdGl2ZVVzZXJJZDogc3RyaW5nO1xuICBuYXRpdmVVc2VyUmV2aXNpb246IHN0cmluZztcbiAgdG9tYnN0b25lS2V5OiBzdHJpbmc7XG59XG5leHBvcnQgY29uc3QgdmFsaWRTdXBwb3J0Q29ubmVjdFNvdXJjZSA9IChzb3VyY2U6IFN1cHBvcnRDb25uZWN0U291cmNlIHwgdW5kZWZpbmVkLCBhcHBJZDogc3RyaW5nLCBhdDogbnVtYmVyKVxuOiBzb3VyY2UgaXMgU3VwcG9ydENvbm5lY3RTb3VyY2UgPT4gQm9vbGVhbihzb3VyY2UgJiYgc291cmNlLmFwcElkID09PSBhcHBJZCAmJiBzb3VyY2UuZW5hYmxlZCA9PT0gdHJ1ZVxuICAmJiBzdXBwb3J0Q2hhbm5lbElkKHNvdXJjZS5zb3VyY2VJZCkgJiYgc3VwcG9ydENoYW5uZWxJZChzb3VyY2UuX3JldikgJiYgc291cmNlLmRhdGFiYXNlTmFtZVxuICAmJiAvXlthLWYwLTldezh9LVthLWYwLTldezR9LVthLWYwLTldezR9LVthLWYwLTldezR9LVthLWYwLTldezEyfSQvLnRlc3Qoc291cmNlLmdlbmVyYXRpb24pICYmIE51bWJlci5pc1NhZmVJbnRlZ2VyKHNvdXJjZS5leHBpcmVzQXQpICYmIHNvdXJjZS5leHBpcmVzQXQgPiBhdFxuICAmJiAvXmFybjphd3MoPzotW2Etel0rKT86Y29ubmVjdDpbYS16MC05LV0rOlxcZHsxMn06aW5zdGFuY2VcXC9bYS1mMC05LV17MzZ9JC8udGVzdChzb3VyY2UuaW5zdGFuY2VBcm4pXG4gICYmIC9eYXJuOmF3cyg/Oi1bYS16XSspPzppYW06OlxcZHsxMn06cm9sZVxcL1tcXHcrPSwuQC1dezEsNjR9JC8udGVzdChzb3VyY2UuYWxsb3dlZENhbGxlclJvbGVBcm4pXG4gICYmIHNvdXJjZS5pbnN0YW5jZUFybi5zcGxpdCgnOicpWzFdID09PSBzb3VyY2UuYWxsb3dlZENhbGxlclJvbGVBcm4uc3BsaXQoJzonKVsxXVxuICAmJiBzb3VyY2UuaW5zdGFuY2VBcm4uc3BsaXQoJzonKVs0XSA9PT0gc291cmNlLmFsbG93ZWRDYWxsZXJSb2xlQXJuLnNwbGl0KCc6JylbNF0pO1xuZXhwb3J0IGNvbnN0IHJlYWRTdXBwb3J0Q2hhbm5lbFRpY2tldCA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCBhcHBJZDogc3RyaW5nLCB0aWNrZXRJZDogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IHNjb3BlZCA9IGF3YWl0IHNjb3BlQ29udGV4dFRvQXBwKGNvbnRleHQsIGFwcElkKTtcbiAgY29uc3Qgcm93ID0gYXdhaXQgdXNlRGIoc2NvcGVkLmRhdGFiYXNlTmFtZSkucXVlcnkoYXFsYExFVCB0aWNrZXQgPSBET0NVTUVOVCgnc3VwcG9ydFRpY2tldHMnLCAke3RpY2tldElkfSlcbiAgICBMRVQgdXNlciA9IHRpY2tldCA/IERPQ1VNRU5UKCd1c2VycycsIHRpY2tldC51c2VySWQpIDogbnVsbFxuICAgIFJFVFVSTiB7dGlja2V0OiB0aWNrZXQgPyB7X2tleTogdGlja2V0Ll9rZXksIF9yZXY6IHRpY2tldC5fcmV2LCBhcHBJZDogdGlja2V0LmFwcElkLFxuICAgICAgZGVsZXRlZDogdGlja2V0LmRlbGV0ZWQsIHVzZXJJZDogdGlja2V0LnVzZXJJZCwgc3RhdHVzOiB0aWNrZXQuc3RhdHVzfSA6IG51bGwsXG4gICAgICB1c2VyOiB1c2VyID8ge19rZXk6IHVzZXIuX2tleSwgX3JldjogdXNlci5fcmV2LCBhcHBJZDogdXNlci5hcHBJZCwgZGVsZXRlZDogdXNlci5kZWxldGVkfSA6IG51bGx9YClcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKTtcbiAgaWYoIXJvdz8udGlja2V0IHx8ICFyb3cudXNlciB8fCByb3cudGlja2V0Ll9rZXkgIT09IHRpY2tldElkIHx8ICFzdXBwb3J0Q2hhbm5lbElkKHJvdy51c2VyLl9rZXkpXG4gICAgfHwgcm93LnRpY2tldC5hcHBJZCAhPT0gYXBwSWQgfHwgcm93LnVzZXIuYXBwSWQgIT09IGFwcElkXG4gICAgfHwgcm93LnRpY2tldC5kZWxldGVkID09PSB0cnVlIHx8IHJvdy51c2VyLmRlbGV0ZWQgPT09IHRydWUgfHwgcm93LnRpY2tldC51c2VySWQgIT09IHJvdy51c2VyLl9rZXlcbiAgICB8fCAhc3VwcG9ydENoYW5uZWxJZChyb3cudGlja2V0Ll9yZXYpIHx8ICFzdXBwb3J0Q2hhbm5lbElkKHJvdy51c2VyLl9yZXYpXG4gICAgfHwgIVsnc3VibWl0dGVkJywgJ29wZW4nLCAnaW5fcHJvZ3Jlc3MnLCAnd2FpdGluZ19vbl9jdXN0b21lcicsICd3YWl0aW5nX29uX2ludGVybmFsJ10uaW5jbHVkZXMocm93LnRpY2tldC5zdGF0dXMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdXBwb3J0X2NoYW5uZWxfdGlja2V0X2hvbGQnKTtcbiAgfVxuICByZXR1cm4ge2RhdGFiYXNlTmFtZTogc2NvcGVkLmRhdGFiYXNlTmFtZSwgdGlja2V0OiByb3cudGlja2V0LCB1c2VyOiByb3cudXNlcn07XG59O1xuY29uc3Qgc2V0dXAgPSBhc3luYyAoY29udGV4dDogQXBpQ29udGV4dCkgPT4ge1xuICBjb25zdCBkYiA9IHVzZURiKGNvbnRleHQuZGF0YWJhc2VOYW1lKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwoc3VwcG9ydENoYW5uZWxDb2xsZWN0aW9ucy5tYXAoKG5hbWUpID0+IGVuc3VyZU93bmVyRXhlY3V0aW9uQ29sbGVjdGlvbihkYiwgbmFtZSkpKTtcbiAgcmV0dXJuIGRiO1xufTtcbi8qKiBBZG1pbmlzdHJhdG9yLXJldmlld2VkIHNvdXJjZSBkZWNsYXJhdGlvbi4gTm8gQVdTIGNyZWRlbnRpYWxzIG9yIGF1dG9tYXRpYyBpbnRha2Uvc2VuZCBhdXRob3JpdHkuICovXG5leHBvcnQgY29uc3QgY29uZmlndXJlU3VwcG9ydENvbm5lY3RTb3VyY2UgPSBhc3luYyAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsIGlucHV0OiBTdXBwb3J0Q29ubmVjdFNvdXJjZUlucHV0LCBub3cgPSBEYXRlLm5vd1xuKSA9PiB7XG4gIHJlcXVpcmVDcm1BZG1pbmlzdHJhdG9yKGNvbnRleHQpO1xuICBpZighaW5wdXQgfHwgT2JqZWN0LmtleXMoaW5wdXQpLnNvbWUoKGtleSkgPT4gIVsnYWxsb3dlZENhbGxlclJvbGVBcm4nLCAnYXBwSWQnLCAnZW5hYmxlZCcsICdleHBlY3RlZFJldmlzaW9uJyxcbiAgICAnZXhwaXJlc0F0JywgJ2luc3RhbmNlQXJuJywgJ3NvdXJjZUlkJ10uaW5jbHVkZXMoa2V5KSkgfHwgIXN1cHBvcnRDaGFubmVsSWQoaW5wdXQuYXBwSWQpXG4gICAgfHwgIXN1cHBvcnRDaGFubmVsSWQoaW5wdXQuc291cmNlSWQpIHx8IHR5cGVvZiBpbnB1dC5lbmFibGVkICE9PSAnYm9vbGVhbidcbiAgICB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoaW5wdXQuZXhwaXJlc0F0KSB8fCBpbnB1dC5leHBpcmVzQXQgPD0gbm93KCkgfHwgaW5wdXQuZXhwaXJlc0F0IC0gbm93KCkgPiAzMCAqIDg2NDAwMDAwXG4gICAgfHwgKGlucHV0LmV4cGVjdGVkUmV2aXNpb24gIT09IHVuZGVmaW5lZCAmJiAhc3VwcG9ydENoYW5uZWxJZChpbnB1dC5leHBlY3RlZFJldmlzaW9uKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWRfc3VwcG9ydF9jaGFubmVsX3NvdXJjZScpO1xuICB9XG4gIGNvbnN0IHNjb3BlZCA9IGF3YWl0IHNjb3BlQ29udGV4dFRvQXBwKGNvbnRleHQsIGlucHV0LmFwcElkKTtcbiAgY29uc3QgY2FuZGlkYXRlID0gey4uLmlucHV0LCBfa2V5OiBzdXBwb3J0Q2hhbm5lbEhhc2goW2lucHV0LmFwcElkLCBpbnB1dC5zb3VyY2VJZF0pLCBfcmV2OiAnY2FuZGlkYXRlJyxcbiAgICBkYXRhYmFzZU5hbWU6IHNjb3BlZC5kYXRhYmFzZU5hbWUhLCBlbmFibGVkOiB0cnVlLCBnZW5lcmF0aW9uOiByYW5kb21VVUlEKCksIG1vZGlmaWVkQXQ6IG5vdygpfTtcbiAgaWYoIXZhbGlkU3VwcG9ydENvbm5lY3RTb3VyY2UoY2FuZGlkYXRlLCBpbnB1dC5hcHBJZCwgbm93KCkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX3N1cHBvcnRfY2hhbm5lbF9zb3VyY2UnKTtcbiAgfVxuICBjb25zdCBkYiA9IGF3YWl0IHNldHVwKGNvbnRleHQpO1xuICBjb25zdCB7X3JldjogX3JldmlzaW9uLCBleHBlY3RlZFJldmlzaW9uLCAuLi5zdG9yZWR9ID0gey4uLmNhbmRpZGF0ZSwgZW5hYmxlZDogaW5wdXQuZW5hYmxlZH07XG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRiLnF1ZXJ5KGV4cGVjdGVkUmV2aXNpb24gPyBhcWxgTEVUIHByaW9yID0gRE9DVU1FTlQoJ3N1cHBvcnRDaGFubmVsU291cmNlcycsICR7Y2FuZGlkYXRlLl9rZXl9KVxuICAgIEZJTFRFUiBwcmlvci5fcmV2ID09ICR7ZXhwZWN0ZWRSZXZpc2lvbn1cbiAgICBSRVBMQUNFIHtfa2V5OiAke2NhbmRpZGF0ZS5fa2V5fSwgX3JldjogJHtleHBlY3RlZFJldmlzaW9ufX0gV0lUSCAke3N0b3JlZH1cbiAgICAgIElOIHN1cHBvcnRDaGFubmVsU291cmNlcyBPUFRJT05TIHtpZ25vcmVSZXZzOiBmYWxzZX0gUkVUVVJOIE5FV2BcbiAgICA6IGFxbGBJTlNFUlQgJHtzdG9yZWR9IElOIHN1cHBvcnRDaGFubmVsU291cmNlcyBSRVRVUk4gTkVXYClcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKTtcbiAgaWYoIXJlc3VsdCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc3VwcG9ydF9jaGFubmVsX3NvdXJjZV9jaGFuZ2VkJyk7XG4gIH1cbiAgcmV0dXJuIHthcHBJZDogaW5wdXQuYXBwSWQsIGVuYWJsZWQ6IHJlc3VsdC5lbmFibGVkLCBleHBpcmVzQXQ6IHJlc3VsdC5leHBpcmVzQXQsXG4gICAgcmV2aXNpb246IHJlc3VsdC5fcmV2LCBzb3VyY2VJZDogaW5wdXQuc291cmNlSWR9O1xufTtcbi8qKiBFeHBsaWNpdCBhc3NvY2lhdGlvbjsgYSBjb250YWN0J3MgZXhpc3RlbmNlIGlzIHN1YnNlcXVlbnRseSBjaGVja2VkIHdpdGggQ29ubmVjdCwgbmV2ZXIgYnkgZW1haWwgb3IgcGhvbmUuICovXG5leHBvcnQgY29uc3QgYmluZFN1cHBvcnRDb25uZWN0Q29udmVyc2F0aW9uID0gYXN5bmMgKFxuICBjb250ZXh0OiBBcGlDb250ZXh0LCBpbnB1dDogU3VwcG9ydENvbm5lY3RCaW5kaW5nSW5wdXQsIG5vdyA9IERhdGUubm93XG4pID0+IHtcbiAgcmVxdWlyZUNybUFkbWluaXN0cmF0b3IoY29udGV4dCk7XG4gIGlmKCFpbnB1dCB8fCBPYmplY3Qua2V5cyhpbnB1dCkuc29ydCgpLmpvaW4oJywnKSAhPT0gJ2FwcElkLGNvbnRhY3RJZCxleHBpcmVzQXQsc291cmNlSWQsc291cmNlUmV2aXNpb24sdGlja2V0SWQsdGlja2V0UmV2aXNpb24nXG4gICAgfHwgIVtpbnB1dC5hcHBJZCwgaW5wdXQuc291cmNlSWQsIGlucHV0LnNvdXJjZVJldmlzaW9uLCBpbnB1dC50aWNrZXRJZCwgaW5wdXQudGlja2V0UmV2aXNpb25dXG4gICAgICAuZXZlcnkoc3VwcG9ydENoYW5uZWxJZClcbiAgICB8fCAhL15bYS1mMC05XXs4fS1bYS1mMC05XXs0fS1bYS1mMC05XXs0fS1bYS1mMC05XXs0fS1bYS1mMC05XXsxMn0kLy50ZXN0KGlucHV0LmNvbnRhY3RJZCkgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKGlucHV0LmV4cGlyZXNBdCkgfHwgaW5wdXQuZXhwaXJlc0F0IDw9IG5vdygpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX3N1cHBvcnRfY2hhbm5lbF9iaW5kaW5nJyk7XG4gIH1cbiAgY29uc3QgZGIgPSBhd2FpdCBzZXR1cChjb250ZXh0KTtcbiAgY29uc3Qgc291cmNlID0gYXdhaXQgZGIucXVlcnkoYXFsYFJFVFVSTiBET0NVTUVOVCgnc3VwcG9ydENoYW5uZWxTb3VyY2VzJywgJHtzdXBwb3J0Q2hhbm5lbEhhc2goW2lucHV0LmFwcElkLCBpbnB1dC5zb3VyY2VJZF0pfSlgKVxuICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpIGFzIFN1cHBvcnRDb25uZWN0U291cmNlIHwgdW5kZWZpbmVkO1xuICBjb25zdCByb3cgPSBhd2FpdCByZWFkU3VwcG9ydENoYW5uZWxUaWNrZXQoY29udGV4dCwgaW5wdXQuYXBwSWQsIGlucHV0LnRpY2tldElkKTtcbiAgaWYoIXZhbGlkU3VwcG9ydENvbm5lY3RTb3VyY2Uoc291cmNlLCBpbnB1dC5hcHBJZCwgbm93KCkpIHx8IHNvdXJjZS5fcmV2ICE9PSBpbnB1dC5zb3VyY2VSZXZpc2lvblxuICAgIHx8IHNvdXJjZS5kYXRhYmFzZU5hbWUgIT09IHJvdy5kYXRhYmFzZU5hbWUgfHwgcm93LnRpY2tldC5fcmV2ICE9PSBpbnB1dC50aWNrZXRSZXZpc2lvblxuICAgIHx8IGlucHV0LmV4cGlyZXNBdCA+IHNvdXJjZS5leHBpcmVzQXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N1cHBvcnRfY2hhbm5lbF9iaW5kaW5nX2hvbGQnKTtcbiAgfVxuICBjb25zdCB0b21ic3RvbmVLZXkgPSBzdXBwb3J0Q2hhbm5lbEhhc2goW2lucHV0LmFwcElkLCBpbnB1dC5zb3VyY2VJZCwgaW5wdXQuY29udGFjdElkXSk7XG4gIGNvbnN0IGJpbmRpbmcgPSB7Li4uaW5wdXQsIF9rZXk6IHN1cHBvcnRDaGFubmVsSGFzaChbc291cmNlLmdlbmVyYXRpb24sIGlucHV0LmNvbnRhY3RJZF0pLFxuICAgIGdlbmVyYXRpb246IHNvdXJjZS5nZW5lcmF0aW9uLCBuYXRpdmVVc2VySWQ6IHJvdy51c2VyLl9rZXksIG5hdGl2ZVVzZXJSZXZpc2lvbjogcm93LnVzZXIuX3JldiwgdG9tYnN0b25lS2V5fTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZGIucXVlcnkoYXFsYExFVCBjdXJyZW50ID0gRE9DVU1FTlQoJ3N1cHBvcnRDaGFubmVsU291cmNlcycsICR7c291cmNlLl9rZXl9KVxuICAgIExFVCB0b21ic3RvbmUgPSBET0NVTUVOVCgnc3VwcG9ydENoYW5uZWxUb21ic3RvbmVzJywgJHt0b21ic3RvbmVLZXl9KVxuICAgIExFVCBwcmlvciA9IERPQ1VNRU5UKCdzdXBwb3J0Q2hhbm5lbEJpbmRpbmdzJywgJHtiaW5kaW5nLl9rZXl9KVxuICAgIExFVCBtYXRjaGluZyA9IChGT1IgaXRlbSBJTiBzdXBwb3J0Q2hhbm5lbEJpbmRpbmdzIEZJTFRFUiBpdGVtLmFwcElkID09ICR7aW5wdXQuYXBwSWR9XG4gICAgICBBTkQgaXRlbS5zb3VyY2VJZCA9PSAke2lucHV0LnNvdXJjZUlkfSBBTkQgaXRlbS5nZW5lcmF0aW9uID09ICR7c291cmNlLmdlbmVyYXRpb259XG4gICAgICBBTkQgaXRlbS5jb250YWN0SWQgPT0gJHtpbnB1dC5jb250YWN0SWR9IExJTUlUIDIgUkVUVVJOIGl0ZW0uX2tleSlcbiAgICBGSUxURVIgTEVOR1RIKG1hdGNoaW5nKSA9PSAwIE9SIChMRU5HVEgobWF0Y2hpbmcpID09IDEgQU5EIG1hdGNoaW5nWzBdID09ICR7YmluZGluZy5fa2V5fSlcbiAgICBGSUxURVIgY3VycmVudC5fcmV2ID09ICR7c291cmNlLl9yZXZ9IEFORCBjdXJyZW50LmVuYWJsZWQgPT0gdHJ1ZSBBTkQgY3VycmVudC5leHBpcmVzQXQgPiAke25vdygpfVxuICAgICAgQU5EIHRvbWJzdG9uZSA9PSBudWxsIEFORCAocHJpb3IgPT0gbnVsbCBPUiBwcmlvciA9PSBNRVJHRSgke2JpbmRpbmd9LCB7X2lkOiBwcmlvci5faWQsIF9yZXY6IHByaW9yLl9yZXZ9KSlcbiAgICBVUFNFUlQge19rZXk6ICR7YmluZGluZy5fa2V5fX0gSU5TRVJUICR7YmluZGluZ30gVVBEQVRFIHt9IElOIHN1cHBvcnRDaGFubmVsQmluZGluZ3MgUkVUVVJOIE5FV2ApXG4gICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSk7XG4gIGlmKCFyZXN1bHQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N1cHBvcnRfY2hhbm5lbF9iaW5kaW5nX2NoYW5nZWQnKTtcbiAgfVxuICByZXR1cm4ge2FwcElkOiBpbnB1dC5hcHBJZCwgYmluZGluZ0lkOiByZXN1bHQuX2tleSwgZXhwaXJlc0F0OiByZXN1bHQuZXhwaXJlc0F0LFxuICAgIHJldmlzaW9uOiByZXN1bHQuX3Jldiwgc291cmNlSWQ6IGlucHV0LnNvdXJjZUlkLCB0aWNrZXRJZDogaW5wdXQudGlja2V0SWQsIHRpY2tldFJldmlzaW9uOiBpbnB1dC50aWNrZXRSZXZpc2lvbn07XG59O1xuLyoqIEFkbWluaXN0cmF0aXZlIHByaXZhY3kgZXJhc3VyZSBrZWVwcyBhbiBvcGFxdWUgdG9tYnN0b25lIHRvIHByZXZlbnQgb2xkIGNvbnRhY3QgZXZpZGVuY2UgYmVpbmcgcmVjcmVhdGVkLiAqL1xuZXhwb3J0IGNvbnN0IGVyYXNlU3VwcG9ydENvbm5lY3RFdmlkZW5jZSA9IGFzeW5jIChcbiAgY29udGV4dDogQXBpQ29udGV4dCwgaW5wdXQ6IHthcHBJZDogc3RyaW5nOyBiaW5kaW5nSWQ6IHN0cmluZ30sIG5vdyA9IERhdGUubm93XG4pID0+IHtcbiAgcmVxdWlyZUNybUFkbWluaXN0cmF0b3IoY29udGV4dCk7XG4gIGlmKCFpbnB1dCB8fCBPYmplY3Qua2V5cyhpbnB1dCkuc29ydCgpLmpvaW4oJywnKSAhPT0gJ2FwcElkLGJpbmRpbmdJZCdcbiAgICB8fCAhc3VwcG9ydENoYW5uZWxJZChpbnB1dC5hcHBJZCkgfHwgIS9eW2EtZjAtOV17NjR9JC8udGVzdChpbnB1dC5iaW5kaW5nSWQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX3N1cHBvcnRfY2hhbm5lbF9lcmFzdXJlJyk7XG4gIH1cbiAgYXdhaXQgc2NvcGVDb250ZXh0VG9BcHAoY29udGV4dCwgaW5wdXQuYXBwSWQpO1xuICBjb25zdCBkYiA9IGF3YWl0IHNldHVwKGNvbnRleHQpO1xuICBjb25zdCB0cmFuc2FjdGlvbiA9IGF3YWl0IGRiLmJlZ2luVHJhbnNhY3Rpb24oe2V4Y2x1c2l2ZTogWy4uLnN1cHBvcnRDaGFubmVsQ29sbGVjdGlvbnNdfSk7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdHJhbnNhY3Rpb24uc3RlcCgoKSA9PiBkYi5xdWVyeShhcWxgTEVUIGJpbmRpbmcgPSBET0NVTUVOVCgnc3VwcG9ydENoYW5uZWxCaW5kaW5ncycsICR7aW5wdXQuYmluZGluZ0lkfSlcbiAgICAgIEZJTFRFUiBiaW5kaW5nLmFwcElkID09ICR7aW5wdXQuYXBwSWR9XG4gICAgICBMRVQgcmVtb3ZlZCA9IChGT1IgZXZlbnQgSU4gc3VwcG9ydENoYW5uZWxFdmVudHMgRklMVEVSIGV2ZW50LmJpbmRpbmdJZCA9PSAke2lucHV0LmJpbmRpbmdJZH1cbiAgICAgICAgUkVNT1ZFIGV2ZW50IElOIHN1cHBvcnRDaGFubmVsRXZlbnRzIFJFVFVSTiBPTEQuX2tleSlcbiAgICAgIFVQU0VSVCB7X2tleTogYmluZGluZy50b21ic3RvbmVLZXl9IElOU0VSVCB7X2tleTogYmluZGluZy50b21ic3RvbmVLZXksIGFwcElkOiAke2lucHV0LmFwcElkfSwgZXJhc2VkQXQ6ICR7bm93KCl9fVxuICAgICAgICBVUERBVEUge30gSU4gc3VwcG9ydENoYW5uZWxUb21ic3RvbmVzXG4gICAgICBSRVBMQUNFIGJpbmRpbmcgV0lUSCB7X2tleTogYmluZGluZy5fa2V5LCBhcHBJZDogYmluZGluZy5hcHBJZCwgZXJhc2VkQXQ6ICR7bm93KCl9LFxuICAgICAgICB0b21ic3RvbmVLZXk6IGJpbmRpbmcudG9tYnN0b25lS2V5fSBJTiBzdXBwb3J0Q2hhbm5lbEJpbmRpbmdzIFJFVFVSTiB7ZXJhc2VkOiB0cnVlfWApKVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSk7XG4gICAgaWYoIXJlc3VsdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzdXBwb3J0X2NoYW5uZWxfYmluZGluZ19ob2xkJyk7XG4gICAgfVxuICAgIGF3YWl0IHRyYW5zYWN0aW9uLmNvbW1pdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBhd2FpdCB0cmFuc2FjdGlvbi5hYm9ydCgpO1xuICAgIHRocm93IGVycm9yO1xuICB9XG59O1xuIl0sIm5hbWVzIjpbImFxbCIsImNyZWF0ZUhhc2giLCJyYW5kb21VVUlEIiwic2NvcGVDb250ZXh0VG9BcHAiLCJ1c2VEYiIsInJlcXVpcmVDcm1BZG1pbmlzdHJhdG9yIiwiZW5zdXJlT3duZXJFeGVjdXRpb25Db2xsZWN0aW9uIiwic3VwcG9ydENoYW5uZWxDb2xsZWN0aW9ucyIsInN1cHBvcnRDaGFubmVsSGFzaCIsInZhbHVlIiwidXBkYXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsImRpZ2VzdCIsInN1cHBvcnRDaGFubmVsSWQiLCJ0ZXN0IiwidmFsaWRTdXBwb3J0Q29ubmVjdFNvdXJjZSIsInNvdXJjZSIsImFwcElkIiwiYXQiLCJCb29sZWFuIiwiZW5hYmxlZCIsInNvdXJjZUlkIiwiX3JldiIsImRhdGFiYXNlTmFtZSIsImdlbmVyYXRpb24iLCJOdW1iZXIiLCJpc1NhZmVJbnRlZ2VyIiwiZXhwaXJlc0F0IiwiaW5zdGFuY2VBcm4iLCJhbGxvd2VkQ2FsbGVyUm9sZUFybiIsInNwbGl0IiwicmVhZFN1cHBvcnRDaGFubmVsVGlja2V0IiwiY29udGV4dCIsInRpY2tldElkIiwic2NvcGVkIiwicm93IiwicXVlcnkiLCJ0aGVuIiwiY3Vyc29yIiwibmV4dCIsInRpY2tldCIsInVzZXIiLCJfa2V5IiwiZGVsZXRlZCIsInVzZXJJZCIsImluY2x1ZGVzIiwic3RhdHVzIiwiRXJyb3IiLCJzZXR1cCIsImRiIiwiUHJvbWlzZSIsImFsbCIsIm1hcCIsIm5hbWUiLCJjb25maWd1cmVTdXBwb3J0Q29ubmVjdFNvdXJjZSIsImlucHV0Iiwibm93IiwiRGF0ZSIsIk9iamVjdCIsImtleXMiLCJzb21lIiwia2V5IiwiZXhwZWN0ZWRSZXZpc2lvbiIsInVuZGVmaW5lZCIsImNhbmRpZGF0ZSIsIm1vZGlmaWVkQXQiLCJfcmV2aXNpb24iLCJzdG9yZWQiLCJyZXN1bHQiLCJyZXZpc2lvbiIsImJpbmRTdXBwb3J0Q29ubmVjdENvbnZlcnNhdGlvbiIsInNvcnQiLCJqb2luIiwic291cmNlUmV2aXNpb24iLCJ0aWNrZXRSZXZpc2lvbiIsImV2ZXJ5IiwiY29udGFjdElkIiwidG9tYnN0b25lS2V5IiwiYmluZGluZyIsIm5hdGl2ZVVzZXJJZCIsIm5hdGl2ZVVzZXJSZXZpc2lvbiIsImJpbmRpbmdJZCIsImVyYXNlU3VwcG9ydENvbm5lY3RFdmlkZW5jZSIsInRyYW5zYWN0aW9uIiwiYmVnaW5UcmFuc2FjdGlvbiIsImV4Y2x1c2l2ZSIsInN0ZXAiLCJjb21taXQiLCJlcnJvciIsImFib3J0Il0sIm1hcHBpbmdzIjoiQUFBQSw0RUFBNEUsR0FDNUUsU0FBUUEsR0FBRyxRQUFPLFdBQVc7QUFDN0IsU0FBUUMsVUFBVSxFQUFFQyxVQUFVLFFBQU8sY0FBYztBQUVuRCxTQUFRQyxpQkFBaUIsUUFBTyx5QkFBeUI7QUFDekQsU0FBUUMsS0FBSyxRQUFPLDRCQUE0QjtBQUNoRCxTQUFRQyx1QkFBdUIsUUFBTyxXQUFXO0FBQ2pELFNBQVFDLDhCQUE4QixRQUFPLG9CQUFvQjtBQUlqRSxPQUFPLE1BQU1DLDRCQUE0QjtJQUFDO0lBQXlCO0lBQ2pFO0lBQXdCO0NBQTJCLENBQVU7QUFDL0QsT0FBTyxNQUFNQyxxQkFBcUIsQ0FBQ0MsUUFBMkJSLFdBQVcsVUFBVVMsTUFBTSxDQUFDQyxLQUFLQyxTQUFTLENBQUNILFFBQVFJLE1BQU0sQ0FBQyxPQUFPO0FBQy9ILE9BQU8sTUFBTUMsbUJBQW1CLENBQUNMLFFBQW9DLE9BQU9BLFVBQVUsWUFBWSxrQkFBa0JNLElBQUksQ0FBQ04sT0FBTztBQWtDaEksT0FBTyxNQUFNTyw0QkFBNEIsQ0FBQ0MsUUFBMENDLE9BQWVDLEtBQy9EQyxRQUFRSCxVQUFVQSxPQUFPQyxLQUFLLEtBQUtBLFNBQVNELE9BQU9JLE9BQU8sS0FBSyxRQUM5RlAsaUJBQWlCRyxPQUFPSyxRQUFRLEtBQUtSLGlCQUFpQkcsT0FBT00sSUFBSSxLQUFLTixPQUFPTyxZQUFZLElBQ3pGLGlFQUFpRVQsSUFBSSxDQUFDRSxPQUFPUSxVQUFVLEtBQUtDLE9BQU9DLGFBQWEs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
@@ -0,0 +1,62 @@
1
+ import { z } from 'zod';
2
+ import type { RequestImplementation } from '@nlabs/rip-hunter/http';
3
+ import type { ApiContext } from '../types/auth.types.js';
4
+ declare const sourceSchema: z.ZodObject<{
5
+ appId: z.ZodString;
6
+ bindings: z.ZodArray<z.ZodObject<{
7
+ nativeOrderId: z.ZodString;
8
+ shopifyOrderId: z.ZodString;
9
+ }, z.core.$strict>>;
10
+ customersAccessApproved: z.ZodLiteral<true>;
11
+ expiresAt: z.ZodNumber;
12
+ id: z.ZodString;
13
+ ordersAccessApproved: z.ZodLiteral<true>;
14
+ ownerId: z.ZodString;
15
+ revision: z.ZodString;
16
+ shop: z.ZodString;
17
+ shopId: z.ZodString;
18
+ token: z.ZodString;
19
+ }, z.core.$strict>;
20
+ export type SupportCommerceSource = z.infer<typeof sourceSchema>;
21
+ export interface SupportCommerceInput {
22
+ appId: string;
23
+ orderId: string;
24
+ orderRevision: string;
25
+ sourceId: string;
26
+ ticketId: string;
27
+ ticketRevision: string;
28
+ }
29
+ export interface SupportCommerceObservation {
30
+ appId: string;
31
+ bindingRevision: string;
32
+ generatedAt: number;
33
+ order: {
34
+ financialStatus: string;
35
+ fulfillmentStatus: string;
36
+ id: string;
37
+ nativeId: string;
38
+ updatedAt: string;
39
+ };
40
+ providerRevision: string;
41
+ provenance: 'verified_shopify_native_record_association';
42
+ schemaVersion: 'support_commerce_v1';
43
+ shop: {
44
+ domain: string;
45
+ id: string;
46
+ };
47
+ sourceId: string;
48
+ sourceRevision: string;
49
+ ticketId: string;
50
+ ticketRevision: string;
51
+ validUntil: number;
52
+ }
53
+ /** Explicit reviewed source/order whitelist. Other purposes do not transfer protected-data approvals. */
54
+ export declare const supportCommerceSources: (raw?: string) => SupportCommerceSource[];
55
+ export declare const SUPPORT_COMMERCE_QUERY = "query SupportCommerceOrder($id: ID!) {\n shop { id myshopifyDomain }\n currentAppInstallation { accessScopes { handle } }\n order(id: $id) { id customer { id } updatedAt displayFinancialStatus displayFulfillmentStatus }\n}";
56
+ /** Read-only native association. No email matching, association mutation or inferred settlement. */
57
+ export declare const readSupportCommerce: (context: ApiContext, input: SupportCommerceInput, options?: {
58
+ now?: () => number;
59
+ requestImplementation?: RequestImplementation;
60
+ sources?: () => readonly SupportCommerceSource[];
61
+ }) => Promise<SupportCommerceObservation>;
62
+ export {};
@@ -0,0 +1,252 @@
1
+ /* eslint-disable no-underscore-dangle -- Exact native document and graph revision proofs. */ import { httpRequest, readBinaryResponse } from '@nlabs/rip-hunter/http';
2
+ import { aql } from 'arangojs';
3
+ import { z } from 'zod';
4
+ import { scopeContextToApp } from '../utils/appContext.js';
5
+ import { useDb } from '../utils/arangodbUtils.js';
6
+ import { crmCanonicalDigest as digest } from './crmCanonicalPolicy.js';
7
+ import { authorizeCrmExecutionGrant } from './crmExecution.js';
8
+ const id = z.string().regex(/^[\w.-]{1,160}$/);
9
+ const orderId = z.string().regex(/^gid:\/\/shopify\/Order\/\d+$/);
10
+ const shopId = z.string().regex(/^gid:\/\/shopify\/Shop\/\d+$/);
11
+ const sourceSchema = z.object({
12
+ appId: id,
13
+ bindings: z.array(z.object({
14
+ nativeOrderId: id,
15
+ shopifyOrderId: orderId
16
+ }).strict()).min(1).max(100),
17
+ customersAccessApproved: z.literal(true),
18
+ expiresAt: z.number().int().positive(),
19
+ id,
20
+ ordersAccessApproved: z.literal(true),
21
+ ownerId: id,
22
+ revision: id,
23
+ shop: z.string().regex(/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/),
24
+ shopId,
25
+ token: z.string().min(1).max(4096)
26
+ }).strict();
27
+ /** Explicit reviewed source/order whitelist. Other purposes do not transfer protected-data approvals. */ export const supportCommerceSources = (raw = process.env.SUPPORT_COMMERCE_SOURCES)=>{
28
+ if (!raw) {
29
+ return [];
30
+ }
31
+ try {
32
+ const sources = z.array(sourceSchema).max(100).parse(JSON.parse(raw));
33
+ if (new Set(sources.map((source)=>source.id)).size !== sources.length || sources.some((source)=>new Set(source.bindings.map((binding)=>binding.nativeOrderId)).size !== source.bindings.length)) {
34
+ throw new Error('ambiguous');
35
+ }
36
+ return sources;
37
+ } catch {
38
+ throw new Error('support_commerce_source_configuration_hold');
39
+ }
40
+ };
41
+ export const SUPPORT_COMMERCE_QUERY = `query SupportCommerceOrder($id: ID!) {
42
+ shop { id myshopifyDomain }
43
+ currentAppInstallation { accessScopes { handle } }
44
+ order(id: $id) { id customer { id } updatedAt displayFinancialStatus displayFulfillmentStatus }
45
+ }`;
46
+ const providerSchema = z.object({
47
+ currentAppInstallation: z.object({
48
+ accessScopes: z.array(z.object({
49
+ handle: z.string()
50
+ })).max(100)
51
+ }),
52
+ order: z.object({
53
+ customer: z.object({
54
+ id: z.string().regex(/^gid:\/\/shopify\/Customer\/\d+$/)
55
+ }),
56
+ displayFinancialStatus: z.enum([
57
+ 'AUTHORIZED',
58
+ 'EXPIRED',
59
+ 'PAID',
60
+ 'PARTIALLY_PAID',
61
+ 'PARTIALLY_REFUNDED',
62
+ 'PENDING',
63
+ 'REFUNDED',
64
+ 'VOIDED'
65
+ ]),
66
+ displayFulfillmentStatus: z.enum([
67
+ 'FULFILLED',
68
+ 'IN_PROGRESS',
69
+ 'ON_HOLD',
70
+ 'OPEN',
71
+ 'PARTIALLY_FULFILLED',
72
+ 'PENDING_FULFILLMENT',
73
+ 'REQUEST_DECLINED',
74
+ 'RESTOCKED',
75
+ 'SCHEDULED',
76
+ 'UNFULFILLED'
77
+ ]),
78
+ id: orderId,
79
+ updatedAt: z.string().datetime({
80
+ offset: true
81
+ })
82
+ }).strict(),
83
+ shop: z.object({
84
+ id: shopId,
85
+ myshopifyDomain: z.string()
86
+ }).strict()
87
+ }).strict();
88
+ const external = (value, type)=>{
89
+ if (typeof value !== 'string') {
90
+ return undefined;
91
+ }
92
+ if (/^\d+$/.test(value)) {
93
+ return `gid://shopify/${type}/${value}`;
94
+ }
95
+ return new RegExp(`^gid://shopify/${type}/\\d+$`).test(value) ? value : undefined;
96
+ };
97
+ /** Read-only native association. No email matching, association mutation or inferred settlement. */ export const readSupportCommerce = async (context, input, options = {})=>{
98
+ if (!z.object({
99
+ appId: id,
100
+ orderId: id,
101
+ orderRevision: id,
102
+ sourceId: id,
103
+ ticketId: id,
104
+ ticketRevision: id
105
+ }).strict().safeParse(input).success) {
106
+ throw new Error('invalid_support_commerce_input');
107
+ }
108
+ const selection = structuredClone(input);
109
+ const now = options.now || Date.now;
110
+ const sources = options.sources || supportCommerceSources;
111
+ const authority = async ()=>{
112
+ const grant = await authorizeCrmExecutionGrant(context, selection.appId, 'support:commerce', now());
113
+ await authorizeCrmExecutionGrant(context, selection.appId, 'support:read', now());
114
+ const scoped = await scopeContextToApp(context, selection.appId);
115
+ const matches = sources().filter((source)=>source.id === selection.sourceId);
116
+ const source = matches[0];
117
+ const binding = source?.bindings.find((value)=>value.nativeOrderId === selection.orderId);
118
+ if (matches.length !== 1 || !sourceSchema.safeParse(source).success || source.appId !== selection.appId || source.ownerId !== grant.ownerId || source.expiresAt <= now() || !binding || source.bindings.filter((value)=>value.nativeOrderId === selection.orderId).length !== 1 || scoped.databaseName !== grant.databaseName) {
119
+ throw new Error('support_commerce_authority_hold');
120
+ }
121
+ const db = useDb(grant.databaseName);
122
+ const row = await db.query(aql`LET ticket = DOCUMENT('supportTickets', ${selection.ticketId})
123
+ LET user = ticket ? DOCUMENT('users', ticket.userId) : null
124
+ LET order = DOCUMENT('customerOrders', ${selection.orderId})
125
+ LET currentConsent = (FOR record IN supportPurposeConsents
126
+ FILTER record.appId == ${selection.appId} AND record.userId == user._key
127
+ AND record.purpose == 'support_commerce' LIMIT 2 RETURN record)
128
+ LET ticketEdges = (FOR edge IN hasSupportTicket FILTER edge._to == CONCAT('supportTickets/', ${selection.ticketId})
129
+ LIMIT 2 RETURN {from: edge._from, revision: edge._rev})
130
+ LET orderEdges = (FOR edge IN hasCustomerOrder FILTER edge._to == CONCAT('customerOrders/', ${selection.orderId})
131
+ LIMIT 2 RETURN {from: edge._from, revision: edge._rev})
132
+ RETURN {ticket: ticket ? {_key: ticket._key, _rev: ticket._rev, appId: ticket.appId, deleted: ticket.deleted,
133
+ shopifyOrderId: ticket.shopifyOrderId, status: ticket.status, userId: ticket.userId} : null,
134
+ user: user ? {_key: user._key, _rev: user._rev, active: user.active, appId: user.appId,
135
+ crmAnalyticsSuppressed: user.crmAnalyticsSuppressed, deleted: user.deleted,
136
+ shopifyCustomerId: user.shopifyCustomerId} : null,
137
+ order: order ? {_key: order._key, _rev: order._rev, appId: order.appId, deleted: order.deleted,
138
+ shopifyCustomerId: order.shopifyCustomerId, shopifyOrderId: order.shopifyOrderId, userId: order.userId} : null,
139
+ consents: currentConsent, orderEdges, ticketEdges}`).then((cursor)=>cursor.next());
140
+ const { ticket, user, order, consents, orderEdges, ticketEdges } = row || {};
141
+ const active = (record)=>Boolean(record && id.safeParse(record._key).success && id.safeParse(record._rev).success && record.appId === selection.appId && record.deleted !== true);
142
+ const consent = Array.isArray(consents) && consents.length === 1 ? consents[0] : undefined;
143
+ if (!active(ticket) || !active(user) || !active(order) || ticket._key !== selection.ticketId || ticket._rev !== selection.ticketRevision || order._key !== selection.orderId || order._rev !== selection.orderRevision || user.active === false || user.crmAnalyticsSuppressed === true || ticket.userId !== user._key || order.userId !== user._key || ![
144
+ 'submitted',
145
+ 'open',
146
+ 'in_progress',
147
+ 'waiting_on_customer',
148
+ 'waiting_on_internal'
149
+ ].includes(ticket.status) || external(ticket.shopifyOrderId, 'Order') !== binding.shopifyOrderId || external(order.shopifyOrderId, 'Order') !== binding.shopifyOrderId || !external(user.shopifyCustomerId, 'Customer') || external(order.shopifyCustomerId, 'Customer') !== external(user.shopifyCustomerId, 'Customer') || !consent || consent.appId !== selection.appId || consent.userId !== user._key || consent.purpose !== 'support_commerce' || consent._key !== digest([
150
+ selection.appId,
151
+ user._key,
152
+ 'support_commerce'
153
+ ]) || !id.safeParse(consent._rev).success || consent.source !== 'authenticated_customer' || consent.status !== 'active' || !Number.isSafeInteger(consent.at) || consent.at > now() || !Number.isSafeInteger(consent.expiresAt) || consent.expiresAt <= now() || ![
154
+ orderEdges,
155
+ ticketEdges
156
+ ].every((edges)=>Array.isArray(edges) && edges.length === 1 && edges[0].from === `users/${user._key}` && id.safeParse(edges[0].revision).success)) {
157
+ throw new Error('support_commerce_native_identity_or_consent_hold');
158
+ }
159
+ return {
160
+ binding,
161
+ consent,
162
+ grant,
163
+ identity: digest([
164
+ grant.id,
165
+ grant.hash,
166
+ grant.databaseName,
167
+ source,
168
+ row
169
+ ]),
170
+ row,
171
+ source
172
+ };
173
+ };
174
+ const initial = await authority();
175
+ const deadline = now() + 15000;
176
+ const current = await authority();
177
+ if (current.identity !== initial.identity || now() >= deadline) {
178
+ throw new Error('support_commerce_source_changed');
179
+ }
180
+ let data;
181
+ try {
182
+ const response = await httpRequest(`https://${initial.source.shop}/admin/api/2026-10/graphql.json`, {
183
+ body: JSON.stringify({
184
+ query: SUPPORT_COMMERCE_QUERY,
185
+ variables: {
186
+ id: initial.binding.shopifyOrderId
187
+ }
188
+ }),
189
+ headers: {
190
+ 'Content-Type': 'application/json',
191
+ 'X-Shopify-Access-Token': initial.source.token
192
+ },
193
+ method: 'POST',
194
+ redirect: 'error',
195
+ requestImplementation: options.requestImplementation,
196
+ timeout: Math.max(1, deadline - now())
197
+ }, async (response)=>{
198
+ if (response.status !== 200 || response.redirected) {
199
+ throw new Error('provider');
200
+ }
201
+ const bytes = await readBinaryResponse(response, 1048576);
202
+ const envelope = z.object({
203
+ data: providerSchema,
204
+ errors: z.array(z.unknown()).max(100).optional()
205
+ }).strict().parse(JSON.parse(new TextDecoder().decode(bytes)));
206
+ if (envelope.errors?.length) {
207
+ throw new Error('provider');
208
+ }
209
+ return envelope.data;
210
+ });
211
+ data = response;
212
+ } catch {
213
+ throw new Error('support_commerce_provider_read_hold');
214
+ }
215
+ if (data.shop.id !== initial.source.shopId || data.shop.myshopifyDomain !== initial.source.shop || ![
216
+ 'read_orders',
217
+ 'read_customers'
218
+ ].every((scope)=>data.currentAppInstallation.accessScopes.some((entry)=>entry.handle === scope)) || data.order.id !== initial.binding.shopifyOrderId || data.order.customer.id !== external(initial.row.user.shopifyCustomerId, 'Customer') || Date.parse(data.order.updatedAt) > now()) {
219
+ throw new Error('support_commerce_provider_identity_hold');
220
+ }
221
+ const latest = await authority();
222
+ if (latest.identity !== initial.identity || now() >= deadline) {
223
+ throw new Error('support_commerce_source_changed');
224
+ }
225
+ const generatedAt = now();
226
+ return {
227
+ appId: selection.appId,
228
+ bindingRevision: digest(initial.row),
229
+ generatedAt,
230
+ order: {
231
+ financialStatus: data.order.displayFinancialStatus,
232
+ fulfillmentStatus: data.order.displayFulfillmentStatus,
233
+ id: data.order.id,
234
+ nativeId: selection.orderId,
235
+ updatedAt: data.order.updatedAt
236
+ },
237
+ provenance: 'verified_shopify_native_record_association',
238
+ providerRevision: digest(data),
239
+ schemaVersion: 'support_commerce_v1',
240
+ shop: {
241
+ domain: data.shop.myshopifyDomain,
242
+ id: data.shop.id
243
+ },
244
+ sourceId: selection.sourceId,
245
+ sourceRevision: digest(initial.source),
246
+ ticketId: selection.ticketId,
247
+ ticketRevision: selection.ticketRevision,
248
+ validUntil: Math.min(generatedAt + 300000, latest.grant.expires, latest.consent.expiresAt, latest.source.expiresAt)
249
+ };
250
+ };
251
+
252
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi90bXAvcmVhY3RvcmJveC1zdXBwb3J0LWNvbW1lcmNlLWZyZWV6ZS0yMDI2MTAwOC9pbnB1dC9hY3Rpb25zL3N1cHBvcnRDb21tZXJjZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby11bmRlcnNjb3JlLWRhbmdsZSAtLSBFeGFjdCBuYXRpdmUgZG9jdW1lbnQgYW5kIGdyYXBoIHJldmlzaW9uIHByb29mcy4gKi9cbmltcG9ydCB7aHR0cFJlcXVlc3QsIHJlYWRCaW5hcnlSZXNwb25zZX0gZnJvbSAnQG5sYWJzL3JpcC1odW50ZXIvaHR0cCc7XG5pbXBvcnQge2FxbH0gZnJvbSAnYXJhbmdvanMnO1xuaW1wb3J0IHt6fSBmcm9tICd6b2QnO1xuXG5pbXBvcnQge3Njb3BlQ29udGV4dFRvQXBwfSBmcm9tICcuLi91dGlscy9hcHBDb250ZXh0LmpzJztcbmltcG9ydCB7dXNlRGJ9IGZyb20gJy4uL3V0aWxzL2FyYW5nb2RiVXRpbHMuanMnO1xuaW1wb3J0IHtjcm1DYW5vbmljYWxEaWdlc3QgYXMgZGlnZXN0fSBmcm9tICcuL2NybUNhbm9uaWNhbFBvbGljeS5qcyc7XG5pbXBvcnQge2F1dGhvcml6ZUNybUV4ZWN1dGlvbkdyYW50fSBmcm9tICcuL2NybUV4ZWN1dGlvbi5qcyc7XG5cbmltcG9ydCB0eXBlIHtSZXF1ZXN0SW1wbGVtZW50YXRpb259IGZyb20gJ0BubGFicy9yaXAtaHVudGVyL2h0dHAnO1xuaW1wb3J0IHR5cGUge0FwaUNvbnRleHR9IGZyb20gJy4uL3R5cGVzL2F1dGgudHlwZXMuanMnO1xuXG5jb25zdCBpZCA9IHouc3RyaW5nKCkucmVnZXgoL15bXFx3Li1dezEsMTYwfSQvKTtcbmNvbnN0IG9yZGVySWQgPSB6LnN0cmluZygpLnJlZ2V4KC9eZ2lkOlxcL1xcL3Nob3BpZnlcXC9PcmRlclxcL1xcZCskLyk7XG5jb25zdCBzaG9wSWQgPSB6LnN0cmluZygpLnJlZ2V4KC9eZ2lkOlxcL1xcL3Nob3BpZnlcXC9TaG9wXFwvXFxkKyQvKTtcbmNvbnN0IHNvdXJjZVNjaGVtYSA9IHoub2JqZWN0KHthcHBJZDogaWQsXG4gIGJpbmRpbmdzOiB6LmFycmF5KHoub2JqZWN0KHtuYXRpdmVPcmRlcklkOiBpZCwgc2hvcGlmeU9yZGVySWQ6IG9yZGVySWR9KS5zdHJpY3QoKSkubWluKDEpLm1heCgxMDApLFxuICBjdXN0b21lcnNBY2Nlc3NBcHByb3ZlZDogei5saXRlcmFsKHRydWUpLCBleHBpcmVzQXQ6IHoubnVtYmVyKCkuaW50KCkucG9zaXRpdmUoKSwgaWQsXG4gIG9yZGVyc0FjY2Vzc0FwcHJvdmVkOiB6LmxpdGVyYWwodHJ1ZSksIG93bmVySWQ6IGlkLCByZXZpc2lvbjogaWQsXG4gIHNob3A6IHouc3RyaW5nKCkucmVnZXgoL15bYS16MC05XVthLXowLTktXSpcXC5teXNob3BpZnlcXC5jb20kLyksIHNob3BJZCxcbiAgdG9rZW46IHouc3RyaW5nKCkubWluKDEpLm1heCg0MDk2KX0pLnN0cmljdCgpO1xuZXhwb3J0IHR5cGUgU3VwcG9ydENvbW1lcmNlU291cmNlID0gei5pbmZlcjx0eXBlb2Ygc291cmNlU2NoZW1hPjtcbmV4cG9ydCBpbnRlcmZhY2UgU3VwcG9ydENvbW1lcmNlSW5wdXQge1xuICBhcHBJZDogc3RyaW5nOyBvcmRlcklkOiBzdHJpbmc7IG9yZGVyUmV2aXNpb246IHN0cmluZzsgc291cmNlSWQ6IHN0cmluZzsgdGlja2V0SWQ6IHN0cmluZzsgdGlja2V0UmV2aXNpb246IHN0cmluZztcbn1cbmV4cG9ydCBpbnRlcmZhY2UgU3VwcG9ydENvbW1lcmNlT2JzZXJ2YXRpb24ge1xuICBhcHBJZDogc3RyaW5nO1xuICBiaW5kaW5nUmV2aXNpb246IHN0cmluZztcbiAgZ2VuZXJhdGVkQXQ6IG51bWJlcjtcbiAgb3JkZXI6IHtmaW5hbmNpYWxTdGF0dXM6IHN0cmluZzsgZnVsZmlsbG1lbnRTdGF0dXM6IHN0cmluZzsgaWQ6IHN0cmluZzsgbmF0aXZlSWQ6IHN0cmluZzsgdXBkYXRlZEF0OiBzdHJpbmd9O1xuICBwcm92aWRlclJldmlzaW9uOiBzdHJpbmc7XG4gIHByb3ZlbmFuY2U6ICd2ZXJpZmllZF9zaG9waWZ5X25hdGl2ZV9yZWNvcmRfYXNzb2NpYXRpb24nO1xuICBzY2hlbWFWZXJzaW9uOiAnc3VwcG9ydF9jb21tZXJjZV92MSc7XG4gIHNob3A6IHtkb21haW46IHN0cmluZzsgaWQ6IHN0cmluZ307XG4gIHNvdXJjZUlkOiBzdHJpbmc7XG4gIHNvdXJjZVJldmlzaW9uOiBzdHJpbmc7XG4gIHRpY2tldElkOiBzdHJpbmc7XG4gIHRpY2tldFJldmlzaW9uOiBzdHJpbmc7XG4gIHZhbGlkVW50aWw6IG51bWJlcjtcbn1cbi8qKiBFeHBsaWNpdCByZXZpZXdlZCBzb3VyY2Uvb3JkZXIgd2hpdGVsaXN0LiBPdGhlciBwdXJwb3NlcyBkbyBub3QgdHJhbnNmZXIgcHJvdGVjdGVkLWRhdGEgYXBwcm92YWxzLiAqL1xuZXhwb3J0IGNvbnN0IHN1cHBvcnRDb21tZXJjZVNvdXJjZXMgPSAocmF3ID0gcHJvY2Vzcy5lbnYuU1VQUE9SVF9DT01NRVJDRV9TT1VSQ0VTKTogU3VwcG9ydENvbW1lcmNlU291cmNlW10gPT4ge1xuICBpZighcmF3KSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHRyeSB7XG4gICAgY29uc3Qgc291cmNlcyA9IHouYXJyYXkoc291cmNlU2NoZW1hKS5tYXgoMTAwKS5wYXJzZShKU09OLnBhcnNlKHJhdykpO1xuICAgIGlmKG5ldyBTZXQoc291cmNlcy5tYXAoKHNvdXJjZSkgPT4gc291cmNlLmlkKSkuc2l6ZSAhPT0gc291cmNlcy5sZW5ndGhcbiAgICAgIHx8IHNvdXJjZXMuc29tZSgoc291cmNlKSA9PiBuZXcgU2V0KHNvdXJjZS5iaW5kaW5ncy5tYXAoKGJpbmRpbmcpID0+IGJpbmRpbmcubmF0aXZlT3JkZXJJZCkpLnNpemVcbiAgICAgICAgIT09IHNvdXJjZS5iaW5kaW5ncy5sZW5ndGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FtYmlndW91cycpO1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlcztcbiAgfSBjYXRjaHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N1cHBvcnRfY29tbWVyY2Vfc291cmNlX2NvbmZpZ3VyYXRpb25faG9sZCcpO1xuICB9XG59O1xuZXhwb3J0IGNvbnN0IFNVUFBPUlRfQ09NTUVSQ0VfUVVFUlkgPSBgcXVlcnkgU3VwcG9ydENvbW1lcmNlT3JkZXIoJGlkOiBJRCEpIHtcbiAgc2hvcCB7IGlkIG15c2hvcGlmeURvbWFpbiB9XG4gIGN1cnJlbnRBcHBJbnN0YWxsYXRpb24geyBhY2Nlc3NTY29wZXMgeyBoYW5kbGUgfSB9XG4gIG9yZGVyKGlkOiAkaWQpIHsgaWQgY3VzdG9tZXIgeyBpZCB9IHVwZGF0ZWRBdCBkaXNwbGF5RmluYW5jaWFsU3RhdHVzIGRpc3BsYXlGdWxmaWxsbWVudFN0YXR1cyB9XG59YDtcbmNvbnN0IHByb3ZpZGVyU2NoZW1hID0gei5vYmplY3Qoe2N1cnJlbnRBcHBJbnN0YWxsYXRpb246IHoub2JqZWN0KHthY2Nlc3NTY29wZXM6XG4gIHouYXJyYXkoei5vYmplY3Qoe2hhbmRsZTogei5zdHJpbmcoKX0pKS5tYXgoMTAwKX0pLCBvcmRlcjogei5vYmplY3Qoe2N1c3RvbWVyOlxuICB6Lm9iamVjdCh7aWQ6IHouc3RyaW5nKCkucmVnZXgoL15naWQ6XFwvXFwvc2hvcGlmeVxcL0N1c3RvbWVyXFwvXFxkKyQvKX0pLFxuZGlzcGxheUZpbmFuY2lhbFN0YXR1czogei5lbnVtKFsnQVVUSE9SSVpFRCcsICdFWFBJUkVEJywgJ1BBSUQnLCAnUEFSVElBTExZX1BBSUQnLCAnUEFSVElBTExZX1JFRlVOREVEJyxcbiAgJ1BFTkRJTkcnLCAnUkVGVU5ERUQnLCAnVk9JREVEJ10pLFxuZGlzcGxheUZ1bGZpbGxtZW50U3RhdHVzOiB6LmVudW0oWydGVUxGSUxMRUQnLCAnSU5fUFJPR1JFU1MnLCAnT05fSE9MRCcsICdPUEVOJywgJ1BBUlRJQUxMWV9GVUxGSUxMRUQnLFxuICAnUEVORElOR19GVUxGSUxMTUVOVCcsICdSRVFVRVNUX0RFQ0xJTkVEJywgJ1JFU1RPQ0tFRCcsICdTQ0hFRFVMRUQnLCAnVU5GVUxGSUxMRUQnXSksXG5pZDogb3JkZXJJZCwgdXBkYXRlZEF0OiB6LnN0cmluZygpLmRhdGV0aW1lKHtvZmZzZXQ6IHRydWV9KX0pLnN0cmljdCgpLFxuc2hvcDogei5vYmplY3Qoe2lkOiBzaG9wSWQsIG15c2hvcGlmeURvbWFpbjogei5zdHJpbmcoKX0pLnN0cmljdCgpfSkuc3RyaWN0KCk7XG5jb25zdCBleHRlcm5hbCA9ICh2YWx1ZTogdW5rbm93biwgdHlwZTogJ0N1c3RvbWVyJyB8ICdPcmRlcicpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICBpZih0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBpZigvXlxcZCskLy50ZXN0KHZhbHVlKSkge1xuICAgIHJldHVybiBgZ2lkOi8vc2hvcGlmeS8ke3R5cGV9LyR7dmFsdWV9YDtcbiAgfVxuICByZXR1cm4gbmV3IFJlZ0V4cChgXmdpZDovL3Nob3BpZnkvJHt0eXBlfS9cXFxcZCskYCkudGVzdCh2YWx1ZSkgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbn07XG4vKiogUmVhZC1vbmx5IG5hdGl2ZSBhc3NvY2lhdGlvbi4gTm8gZW1haWwgbWF0Y2hpbmcsIGFzc29jaWF0aW9uIG11dGF0aW9uIG9yIGluZmVycmVkIHNldHRsZW1lbnQuICovXG5leHBvcnQgY29uc3QgcmVhZFN1cHBvcnRDb21tZXJjZSA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCBpbnB1dDogU3VwcG9ydENvbW1lcmNlSW5wdXQsIG9wdGlvbnM6IHtcbiAgbm93PzogKCkgPT4gbnVtYmVyOyByZXF1ZXN0SW1wbGVtZW50YXRpb24/OiBSZXF1ZXN0SW1wbGVtZW50YXRpb247IHNvdXJjZXM/OiAoKSA9PiByZWFkb25seSBTdXBwb3J0Q29tbWVyY2VTb3VyY2VbXTtcbn0gPSB7fSk6IFByb21pc2U8U3VwcG9ydENvbW1lcmNlT2JzZXJ2YXRpb24+ID0+IHtcbiAgaWYoIXoub2JqZWN0KHthcHBJZDogaWQsIG9yZGVySWQ6IGlkLCBvcmRlclJldmlzaW9uOiBpZCwgc291cmNlSWQ6IGlkLCB0aWNrZXRJZDogaWQsXG4gICAgdGlja2V0UmV2aXNpb246IGlkfSkuc3RyaWN0KCkuc2FmZVBhcnNlKGlucHV0KS5zdWNjZXNzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX3N1cHBvcnRfY29tbWVyY2VfaW5wdXQnKTtcbiAgfVxuICBjb25zdCBzZWxlY3Rpb24gPSBzdHJ1Y3R1cmVkQ2xvbmUoaW5wdXQpO1xuICBjb25zdCBub3cgPSBvcHRpb25zLm5vdyB8fCBEYXRlLm5vdztcbiAgY29uc3Qgc291cmNlcyA9IG9wdGlvbnMuc291cmNlcyB8fCBzdXBwb3J0Q29tbWVyY2VTb3VyY2VzO1xuICBjb25zdCBhdXRob3JpdHkgPSBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZ3JhbnQgPSBhd2FpdCBhdXRob3JpemVDcm1FeGVjdXRpb25HcmFudChjb250ZXh0LCBzZWxlY3Rpb24uYXBwSWQsICdzdXBwb3J0OmNvbW1lcmNlJywgbm93KCkpO1xuICAgIGF3YWl0IGF1dGhvcml6ZUNybUV4ZWN1dGlvbkdyYW50KGNvbnRleHQsIHNlbGVjdGlvbi5hcHBJZCwgJ3N1cHBvcnQ6cmVhZCcsIG5vdygpKTtcbiAgICBjb25zdCBzY29wZWQgPSBhd2FpdCBzY29wZUNvbnRleHRUb0FwcChjb250ZXh0LCBzZWxlY3Rpb24uYXBwSWQpO1xuICAgIGNvbnN0IG1hdGNoZXMgPSBzb3VyY2VzKCkuZmlsdGVyKChzb3VyY2UpID0+IHNvdXJjZS5pZCA9PT0gc2VsZWN0aW9uLnNvdXJjZUlkKTtcbiAgICBjb25zdCBzb3VyY2UgPSBtYXRjaGVzWzBdO1xuICAgIGNvbnN0IGJpbmRpbmcgPSBzb3VyY2U/LmJpbmRpbmdzLmZpbmQoKHZhbHVlKSA9PiB2YWx1ZS5uYXRpdmVPcmRlcklkID09PSBzZWxlY3Rpb24ub3JkZXJJZCk7XG4gICAgaWYobWF0Y2hlcy5sZW5ndGggIT09IDEgfHwgIXNvdXJjZVNjaGVtYS5zYWZlUGFyc2Uoc291cmNlKS5zdWNjZXNzIHx8IHNvdXJjZS5hcHBJZCAhPT0gc2VsZWN0aW9uLmFwcElkXG4gICAgICB8fCBzb3VyY2Uub3duZXJJZCAhPT0gZ3JhbnQub3duZXJJZCB8fCBzb3VyY2UuZXhwaXJlc0F0IDw9IG5vdygpIHx8ICFiaW5kaW5nXG4gICAgICB8fCBzb3VyY2UuYmluZGluZ3MuZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWUubmF0aXZlT3JkZXJJZCA9PT0gc2VsZWN0aW9uLm9yZGVySWQpLmxlbmd0aCAhPT0gMVxuICAgICAgfHwgc2NvcGVkLmRhdGFiYXNlTmFtZSAhPT0gZ3JhbnQuZGF0YWJhc2VOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N1cHBvcnRfY29tbWVyY2VfYXV0aG9yaXR5X2hvbGQnKTtcbiAgICB9XG4gICAgY29uc3QgZGIgPSB1c2VEYihncmFudC5kYXRhYmFzZU5hbWUpO1xuICAgIGNvbnN0IHJvdyA9IGF3YWl0IGRiLnF1ZXJ5KGFxbGBMRVQgdGlja2V0ID0gRE9DVU1FTlQoJ3N1cHBvcnRUaWNrZXRzJywgJHtzZWxlY3Rpb24udGlja2V0SWR9KVxuICAgICAgTEVUIHVzZXIgPSB0aWNrZXQgPyBET0NVTUVOVCgndXNlcnMnLCB0aWNrZXQudXNlcklkKSA6IG51bGxcbiAgICAgIExFVCBvcmRlciA9IERPQ1VNRU5UKCdjdXN0b21lck9yZGVycycsICR7c2VsZWN0aW9uLm9yZGVySWR9KVxuICAgICAgTEVUIGN1cnJlbnRDb25zZW50ID0gKEZPUiByZWNvcmQgSU4gc3VwcG9ydFB1cnBvc2VDb25zZW50c1xuICAgICAgICBGSUxURVIgcmVjb3JkLmFwcElkID09ICR7c2VsZWN0aW9uLmFwcElkfSBBTkQgcmVjb3JkLnVzZXJJZCA9PSB1c2VyLl9rZXlcbiAgICAgICAgICBBTkQgcmVjb3JkLnB1cnBvc2UgPT0gJ3N1cHBvcnRfY29tbWVyY2UnIExJTUlUIDIgUkVUVVJOIHJlY29yZClcbiAgICAgIExFVCB0aWNrZXRFZGdlcyA9IChGT1IgZWRnZSBJTiBoYXNTdXBwb3J0VGlja2V0IEZJTFRFUiBlZGdlLl90byA9PSBDT05DQVQoJ3N1cHBvcnRUaWNrZXRzLycsICR7c2VsZWN0aW9uLnRpY2tldElkfSlcbiAgICAgICAgTElNSVQgMiBSRVRVUk4ge2Zyb206IGVkZ2UuX2Zyb20sIHJldmlzaW9uOiBlZGdlLl9yZXZ9KVxuICAgICAgTEVUIG9yZGVyRWRnZXMgPSAoRk9SIGVkZ2UgSU4gaGFzQ3VzdG9tZXJPcmRlciBGSUxURVIgZWRnZS5fdG8gPT0gQ09OQ0FUKCdjdXN0b21lck9yZGVycy8nLCAke3NlbGVjdGlvbi5vcmRlcklkfSlcbiAgICAgICAgTElNSVQgMiBSRVRVUk4ge2Zyb206IGVkZ2UuX2Zyb20sIHJldmlzaW9uOiBlZGdlLl9yZXZ9KVxuICAgICAgUkVUVVJOIHt0aWNrZXQ6IHRpY2tldCA/IHtfa2V5OiB0aWNrZXQuX2tleSwgX3JldjogdGlja2V0Ll9yZXYsIGFwcElkOiB0aWNrZXQuYXBwSWQsIGRlbGV0ZWQ6IHRpY2tldC5kZWxldGVkLFxuICAgICAgICBzaG9waWZ5T3JkZXJJZDogdGlja2V0LnNob3BpZnlPcmRlcklkLCBzdGF0dXM6IHRpY2tldC5zdGF0dXMsIHVzZXJJZDogdGlja2V0LnVzZXJJZH0gOiBudWxsLFxuICAgICAgICB1c2VyOiB1c2VyID8ge19rZXk6IHVzZXIuX2tleSwgX3JldjogdXNlci5fcmV2LCBhY3RpdmU6IHVzZXIuYWN0aXZlLCBhcHBJZDogdXNlci5hcHBJZCxcbiAgICAgICAgICBjcm1BbmFseXRpY3NTdXBwcmVzc2VkOiB1c2VyLmNybUFuYWx5dGljc1N1cHByZXNzZWQsIGRlbGV0ZWQ6IHVzZXIuZGVsZXRlZCxcbiAgICAgICAgICBzaG9waWZ5Q3VzdG9tZXJJZDogdXNlci5zaG9waWZ5Q3VzdG9tZXJJZH0gOiBudWxsLFxuICAgICAgICBvcmRlcjogb3JkZXIgPyB7X2tleTogb3JkZXIuX2tleSwgX3Jldjogb3JkZXIuX3JldiwgYXBwSWQ6IG9yZGVyLmFwcElkLCBkZWxldGVkOiBvcmRlci5kZWxldGVkLFxuICAgICAgICAgIHNob3BpZnlDdXN0b21lcklkOiBvcmRlci5zaG9waWZ5Q3VzdG9tZXJJZCwgc2hvcGlmeU9yZGVySWQ6IG9yZGVyLnNob3BpZnlPcmRlcklkLCB1c2VySWQ6IG9yZGVyLnVzZXJJZH0gOiBudWxsLFxuICAgICAgICBjb25zZW50czogY3VycmVudENvbnNlbnQsIG9yZGVyRWRnZXMsIHRpY2tldEVkZ2VzfWApLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSkgYXMgYW55O1xuICAgIGNvbnN0IHt0aWNrZXQsIHVzZXIsIG9yZGVyLCBjb25zZW50cywgb3JkZXJFZGdlcywgdGlja2V0RWRnZXN9ID0gcm93IHx8IHt9O1xuICAgIGNvbnN0IGFjdGl2ZSA9IChyZWNvcmQ6IGFueSk6IGJvb2xlYW4gPT4gQm9vbGVhbihyZWNvcmQgJiYgaWQuc2FmZVBhcnNlKHJlY29yZC5fa2V5KS5zdWNjZXNzXG4gICAgICAmJiBpZC5zYWZlUGFyc2UocmVjb3JkLl9yZXYpLnN1Y2Nlc3MgJiYgcmVjb3JkLmFwcElkID09PSBzZWxlY3Rpb24uYXBwSWQgJiYgcmVjb3JkLmRlbGV0ZWQgIT09IHRydWUpO1xuICAgIGNvbnN0IGNvbnNlbnQgPSBBcnJheS5pc0FycmF5KGNvbnNlbnRzKSAmJiBjb25zZW50cy5sZW5ndGggPT09IDEgPyBjb25zZW50c1swXSA6IHVuZGVmaW5lZDtcbiAgICBpZighYWN0aXZlKHRpY2tldCkgfHwgIWFjdGl2ZSh1c2VyKSB8fCAhYWN0aXZlKG9yZGVyKSB8fCB0aWNrZXQuX2tleSAhPT0gc2VsZWN0aW9uLnRpY2tldElkXG4gICAgICB8fCB0aWNrZXQuX3JldiAhPT0gc2VsZWN0aW9uLnRpY2tldFJldmlzaW9uIHx8IG9yZGVyLl9rZXkgIT09IHNlbGVjdGlvbi5vcmRlcklkXG4gICAgICB8fCBvcmRlci5fcmV2ICE9PSBzZWxlY3Rpb24ub3JkZXJSZXZpc2lvbiB8fCB1c2VyLmFjdGl2ZSA9PT0gZmFsc2UgfHwgdXNlci5jcm1BbmFseXRpY3NTdXBwcmVzc2VkID09PSB0cnVlXG4gICAgICB8fCB0aWNrZXQudXNlcklkICE9PSB1c2VyLl9rZXkgfHwgb3JkZXIudXNlcklkICE9PSB1c2VyLl9rZXlcbiAgICAgIHx8ICFbJ3N1Ym1pdHRlZCcsICdvcGVuJywgJ2luX3Byb2dyZXNzJywgJ3dhaXRpbmdfb25fY3VzdG9tZXInLCAnd2FpdGluZ19vbl9pbnRlcm5hbCddLmluY2x1ZGVzKHRpY2tldC5zdGF0dXMpXG4gICAgICB8fCBleHRlcm5hbCh0aWNrZXQuc2hvcGlmeU9yZGVySWQsICdPcmRlcicpICE9PSBiaW5kaW5nLnNob3BpZnlPcmRlcklkXG4gICAgICB8fCBleHRlcm5hbChvcmRlci5zaG9waWZ5T3JkZXJJZCwgJ09yZGVyJykgIT09IGJpbmRpbmcuc2hvcGlmeU9yZGVySWRcbiAgICAgIHx8ICFleHRlcm5hbCh1c2VyLnNob3BpZnlDdXN0b21lcklkLCAnQ3VzdG9tZXInKVxuICAgICAgfHwgZXh0ZXJuYWwob3JkZXIuc2hvcGlmeUN1c3RvbWVySWQsICdDdXN0b21lcicpICE9PSBleHRlcm5hbCh1c2VyLnNob3BpZnlDdXN0b21lcklkLCAnQ3VzdG9tZXInKVxuICAgICAgfHwgIWNvbnNlbnQgfHwgY29uc2VudC5hcHBJZCAhPT0gc2VsZWN0aW9uLmFwcElkIHx8IGNvbnNlbnQudXNlcklkICE9PSB1c2VyLl9rZXlcbiAgICAgIHx8IGNvbnNlbnQucHVycG9zZSAhPT0gJ3N1cHBvcnRfY29tbWVyY2UnIHx8IGNvbnNlbnQuX2tleSAhPT0gZGlnZXN0KFtzZWxlY3Rpb24uYXBwSWQsIHVzZXIuX2tleSwgJ3N1cHBvcnRfY29tbWVyY2UnXSlcbiAgICAgIHx8ICFpZC5zYWZlUGFyc2UoY29uc2VudC5fcmV2KS5zdWNjZXNzIHx8IGNvbnNlbnQuc291cmNlICE9PSAnYXV0aGVudGljYXRlZF9jdXN0b21lcidcbiAgICAgIHx8IGNvbnNlbnQuc3RhdHVzICE9PSAnYWN0aXZlJyB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoY29uc2VudC5hdCkgfHwgY29uc2VudC5hdCA+IG5vdygpXG4gICAgICB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoY29uc2VudC5leHBpcmVzQXQpIHx8IGNvbnNlbnQuZXhwaXJlc0F0IDw9IG5vdygpXG4gICAgICB8fCAhW29yZGVyRWRnZXMsIHRpY2tldEVkZ2VzXS5ldmVyeSgoZWRnZXMpID0+IEFycmF5LmlzQXJyYXkoZWRnZXMpICYmIGVkZ2VzLmxlbmd0aCA9PT0gMVxuICAgICAgICAmJiBlZGdlc1swXS5mcm9tID09PSBgdXNlcnMvJHt1c2VyLl9rZXl9YCAmJiBpZC5zYWZlUGFyc2UoZWRnZXNbMF0ucmV2aXNpb24pLnN1Y2Nlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N1cHBvcnRfY29tbWVyY2VfbmF0aXZlX2lkZW50aXR5X29yX2NvbnNlbnRfaG9sZCcpO1xuICAgIH1cbiAgICByZXR1cm4ge2JpbmRpbmcsIGNvbnNlbnQsIGdyYW50LCBpZGVudGl0eTogZGlnZXN0KFtncmFudC5pZCwgZ3JhbnQuaGFzaCwgZ3JhbnQuZGF0YWJhc2VOYW1lLCBzb3VyY2UsIHJvd10pLFxuICAgICAgcm93LCBzb3VyY2V9O1xuICB9O1xuICBjb25zdCBpbml0aWFsID0gYXdhaXQgYXV0aG9yaXR5KCk7XG4gIGNvbnN0IGRlYWRsaW5lID0gbm93KCkgKyAxNTAwMDtcbiAgY29uc3QgY3VycmVudCA9IGF3YWl0IGF1dGhvcml0eSgpO1xuICBpZihjdXJyZW50LmlkZW50aXR5ICE9PSBpbml0aWFsLmlkZW50aXR5IHx8IG5vdygpID49IGRlYWRsaW5lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdXBwb3J0X2NvbW1lcmNlX3NvdXJjZV9jaGFuZ2VkJyk7XG4gIH1cbiAgbGV0IGRhdGE6IHouaW5mZXI8dHlwZW9mIHByb3ZpZGVyU2NoZW1hPjtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGh0dHBSZXF1ZXN0KGBodHRwczovLyR7aW5pdGlhbC5zb3VyY2Uuc2hvcH0vYWRtaW4vYXBpLzIwMjYtMTAvZ3JhcGhxbC5qc29uYCwge1xuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe3F1ZXJ5OiBTVVBQT1JUX0NPTU1FUkNFX1FVRVJZLCB2YXJpYWJsZXM6IHtpZDogaW5pdGlhbC5iaW5kaW5nLnNob3BpZnlPcmRlcklkfX0pLFxuICAgICAgaGVhZGVyczogeydDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsICdYLVNob3BpZnktQWNjZXNzLVRva2VuJzogaW5pdGlhbC5zb3VyY2UudG9rZW59LCBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIHJlZGlyZWN0OiAnZXJyb3InLCByZXF1ZXN0SW1wbGVtZW50YXRpb246IG9wdGlvbnMucmVxdWVzdEltcGxlbWVudGF0aW9uLFxuICAgICAgdGltZW91dDogTWF0aC5tYXgoMSwgZGVhZGxpbmUgLSBub3coKSlcbiAgICB9LCBhc3luYyAocmVzcG9uc2UpID0+IHtcbiAgICAgIGlmKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwIHx8IHJlc3BvbnNlLnJlZGlyZWN0ZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwcm92aWRlcicpO1xuICAgICAgfVxuICAgICAgY29uc3QgYnl0ZXMgPSBhd2FpdCByZWFkQmluYXJ5UmVzcG9uc2UocmVzcG9uc2UsIDEwNDg1NzYpO1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSB6Lm9iamVjdCh7ZGF0YTogcHJvdmlkZXJTY2hlbWEsIGVycm9yczogei5hcnJheSh6LnVua25vd24oKSkubWF4KDEwMCkub3B0aW9uYWwoKX0pXG4gICAgICAgIC5zdHJpY3QoKS5wYXJzZShKU09OLnBhcnNlKG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShieXRlcykpKTtcbiAgICAgIGlmKGVudmVsb3BlLmVycm9ycz8ubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncHJvdmlkZXInKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBlbnZlbG9wZS5kYXRhO1xuICAgIH0pO1xuICAgIGRhdGEgPSByZXNwb25zZTtcbiAgfSBjYXRjaHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N1cHBvcnRfY29tbWVyY2VfcHJvdmlkZXJfcmVhZF9ob2xkJyk7XG4gIH1cbiAgaWYoZGF0YS5zaG9wLmlkICE9PSBpbml0aWFsLnNvdXJjZS5zaG9wSWQgfHwgZGF0YS5zaG9wLm15c2hvcGlmeURvbWFpbiAhPT0gaW5pdGlhbC5zb3VyY2Uuc2hvcFxuICAgIHx8ICFbJ3JlYWRfb3JkZXJzJywgJ3JlYWRfY3VzdG9tZXJzJ10uZXZlcnkoKHNjb3BlKSA9PlxuICAgICAgZGF0YS5jdXJyZW50QXBwSW5zdGFsbGF0aW9uLmFjY2Vzc1Njb3Blcy5zb21lKChlbnRyeSkgPT4gZW50cnkuaGFuZGxlID09PSBzY29wZSkpXG4gICAgfHwgZGF0YS5vcmRlci5pZCAhPT0gaW5pdGlhbC5iaW5kaW5nLnNob3BpZnlPcmRlcklkXG4gICAgfHwgZGF0YS5vcmRlci5jdXN0b21lci5pZCAhPT0gZXh0ZXJuYWwoaW5pdGlhbC5yb3cudXNlci5zaG9waWZ5Q3VzdG9tZXJJZCwgJ0N1c3RvbWVyJylcbiAgICB8fCBEYXRlLnBhcnNlKGRhdGEub3JkZXIudXBkYXRlZEF0KSA+IG5vdygpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdXBwb3J0X2NvbW1lcmNlX3Byb3ZpZGVyX2lkZW50aXR5X2hvbGQnKTtcbiAgfVxuICBjb25zdCBsYXRlc3QgPSBhd2FpdCBhdXRob3JpdHkoKTtcbiAgaWYobGF0ZXN0LmlkZW50aXR5ICE9PSBpbml0aWFsLmlkZW50aXR5IHx8IG5vdygpID49IGRlYWRsaW5lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdXBwb3J0X2NvbW1lcmNlX3NvdXJjZV9jaGFuZ2VkJyk7XG4gIH1cbiAgY29uc3QgZ2VuZXJhdGVkQXQgPSBub3coKTtcbiAgcmV0dXJuIHthcHBJZDogc2VsZWN0aW9uLmFwcElkLCBiaW5kaW5nUmV2aXNpb246IGRpZ2VzdChpbml0aWFsLnJvdyksIGdlbmVyYXRlZEF0LFxuICAgIG9yZGVyOiB7ZmluYW5jaWFsU3RhdHVzOiBkYXRhLm9yZGVyLmRpc3BsYXlGaW5hbmNpYWxTdGF0dXMsIGZ1bGZpbGxtZW50U3RhdHVzOiBkYXRhLm9yZGVyLmRpc3BsYXlGdWxmaWxsbWVudFN0YXR1cyxcbiAgICAgIGlkOiBkYXRhLm9yZGVyLmlkLCBuYXRpdmVJZDogc2VsZWN0aW9uLm9yZGVySWQsIHVwZGF0ZWRBdDogZGF0YS5vcmRlci51cGRhdGVkQXR9LFxuICAgIHByb3ZlbmFuY2U6ICd2ZXJpZmllZF9zaG9waWZ5X25hdGl2ZV9yZWNvcmRfYXNzb2NpYXRpb24nLCBwcm92aWRlclJldmlzaW9uOiBkaWdlc3QoZGF0YSksXG4gICAgc2NoZW1hVmVyc2lvbjogJ3N1cHBvcnRfY29tbWVyY2VfdjEnLCBzaG9wOiB7ZG9tYWluOiBkYXRhLnNob3AubXlzaG9waWZ5RG9tYWluLCBpZDogZGF0YS5zaG9wLmlkfSxcbiAgICBzb3VyY2VJZDogc2VsZWN0aW9uLnNvdXJjZUlkLCBzb3VyY2VSZXZpc2lvbjogZGlnZXN0KGluaXRpYWwuc291cmNlKSwgdGlja2V0SWQ6IHNlbGVjdGlvbi50aWNrZXRJZCxcbiAgICB0aWNrZXRSZXZpc2lvbjogc2VsZWN0aW9uLnRpY2tldFJldmlzaW9uLFxuICAgIHZhbGlkVW50aWw6IE1hdGgubWluKGdlbmVyYXRlZEF0ICsgMzAwMDAwLCBsYXRlc3QuZ3JhbnQuZXhwaXJlcywgbGF0ZXN0LmNvbnNlbnQuZXhwaXJlc0F0LFxuICAgICAgbGF0ZXN0LnNvdXJjZS5leHBpcmVzQXQpfTtcbn07XG4iXSwibmFtZXMiOlsiaHR0cFJlcXVlc3QiLCJyZWFkQmluYXJ5UmVzcG9uc2UiLCJhcWwiLCJ6Iiwic2NvcGVDb250ZXh0VG9BcHAiLCJ1c2VEYiIsImNybUNhbm9uaWNhbERpZ2VzdCIsImRpZ2VzdCIsImF1dGhvcml6ZUNybUV4ZWN1dGlvbkdyYW50IiwiaWQiLCJzdHJpbmciLCJyZWdleCIsIm9yZGVySWQiLCJzaG9wSWQiLCJzb3VyY2VTY2hlbWEiLCJvYmplY3QiLCJhcHBJZCIsImJpbmRpbmdzIiwiYXJyYXkiLCJuYXRpdmVPcmRlcklkIiwic2hvcGlmeU9yZGVySWQiLCJzdHJpY3QiLCJtaW4iLCJtYXgiLCJjdXN0b21lcnNBY2Nlc3NBcHByb3ZlZCIsImxpdGVyYWwiLCJleHBpcmVzQXQiLCJudW1iZXIiLCJpbnQiLCJwb3NpdGl2ZSIsIm9yZGVyc0FjY2Vzc0FwcHJvdmVkIiwib3duZXJJZCIsInJldmlzaW9uIiwic2hvcCIsInRva2VuIiwic3VwcG9ydENvbW1lcmNlU291cmNlcyIsInJhdyIsInByb2Nlc3MiLCJlbnYiLCJTVVBQT1JUX0NPTU1FUkNFX1NPVVJDRVMiLCJzb3VyY2VzIiwicGFyc2UiLCJKU09OIiwiU2V0IiwibWFwIiwic291cmNlIiwic2l6ZSIsImxlbmd0aCIsInNvbWUiLCJiaW5kaW5nIiwiRXJyb3IiLCJTVVBQT1JUX0NPTU1FUkNFX1FVRVJZIiwicHJvdmlkZXJTY2hlbWEiLCJjdXJyZW50QXBwSW5zdGFsbGF0aW9uIiwiYWNjZXNzU2NvcGVzIiwiaGFuZGxlIiwib3JkZXIiLCJjdXN0b21lciIsImRpc3BsYXlGaW5hbmNpYWxTdGF0dXMiLCJlbnVtIiwiZGlzcGxheUZ1bGZpbGxtZW50U3RhdHVzIiwidXBkYXRlZEF0IiwiZGF0ZXRpbWUiLCJvZmZzZXQiLCJteXNob3BpZnlEb21haW4iLCJleHRlcm5hbCIsInZhbHVlIiwidHlwZSIsInVuZGVmaW5lZCIsInRlc3QiLCJSZWdFeHAiLCJyZWFkU3VwcG9ydENvbW1lcmNlIiwiY29udGV4dCIsImlucHV0Iiwib3B0aW9ucyIsIm9yZGVyUmV2aXNpb24iLCJzb3VyY2VJZCIsInRpY2tldElkIiwidGlja2V0UmV2aXNpb24iLCJzYWZlUGFyc2UiLCJzdWNjZXNzIiwic2VsZWN0aW9uIiwic3RydWN0dXJlZENsb25lIiwibm93IiwiRGF0ZSIsImF1dGhvcml0eSIsImdyYW50Iiwic2NvcGVkIiwibWF0Y2hlcyIsImZpbHRlciIsImZpbmQiLCJkYXRhYmFzZU5hbWUiLCJkYiIsInJvdyIsInF1ZXJ5IiwidGhlbiIsImN1cnNvciIsIm5leHQiLCJ0aWNrZXQiLCJ1c2VyIiwiY29uc2VudHMiLCJvcmRlckVkZ2VzIiwidGlja2V0RWRnZXMiLCJhY3RpdmUiLCJyZWNvcmQiLCJCb29sZWFuIiwiX2tleSIsIl9yZXYiLCJkZWxldGVkIiwiY29uc2VudCIsIkFycmF5IiwiaXNBcnJheSIsImNybUFuYWx5dGljc1N1cHByZXNzZWQiLCJ1c2VySWQiLCJpbmNsdWRlcyIsInN0YXR1cyIsInNob3BpZnlDdXN0b21lcklkIiwicHVycG9zZSIsIk51bWJlciIsImlzU2FmZUludGVnZXIiLCJhdCIsImV2ZXJ5IiwiZWRnZXMiLCJmcm9tIiwiaWRlbnRpdHkiLCJoYXNoIiwiaW5pdGlhbCIsImRlYWRsaW5lIiwiY3VycmVudCIsImRhdGEiLCJyZXNwb25zZSIsImJvZHkiLCJzdHJpbmdpZnkiLCJ2YXJpYWJsZXMiLCJoZWFkZXJzIiwibWV0aG9kIiwicmVkaXJlY3QiLCJyZXF1ZXN0SW1wbGVtZW50YXRpb24iLCJ0aW1lb3V0IiwiTWF0aCIsInJlZGlyZWN0ZWQiLCJieXRlcyIsImVudmVsb3BlIiwiZXJyb3JzIiwidW5rbm93biIsIm9wdGlvbmFsIiwiVGV4dERlY29kZXIiLCJkZWNvZGUiLCJzY29wZSIsImVudHJ5IiwibGF0ZXN0IiwiZ2VuZXJhdGVkQXQiLCJiaW5kaW5nUmV2aXNpb24iLCJmaW5hbmNpYWxTdGF0dXMiLCJmdWxmaWxsbWVudFN0YXR1cyIsIm5hdGl2ZUlkIiwicHJvdmVuYW5jZSIsInByb3ZpZGVyUmV2aXNpb24iLCJzY2hlbWFWZXJzaW9uIiwiZG9tYWluIiwic291cmNlUmV2aXNpb24iLCJ2YWxpZFVudGlsIiwiZXhwaXJlcyJdLCJtYXBwaW5ncyI6IkFBQUEsMkZBQTJGLEdBQzNGLFNBQVFBLFdBQVcsRUFBRUMsa0JBQWtCLFFBQU8seUJBQXlCO0FBQ3ZFLFNBQVFDLEdBQUcsUUFBTyxXQUFXO0FBQzdCLFNBQVFDLENBQUMsUUFB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
@@ -0,0 +1,39 @@
1
+ import { ConnectClient } from '@aws-sdk/client-connect';
2
+ import type { ApiContext } from '../types/auth.types.js';
3
+ export interface SupportConnectIngressInput {
4
+ appId: string;
5
+ bindingId: string;
6
+ contactId: string;
7
+ kind: 'contact_observed' | 'contact_ended';
8
+ sourceId: string;
9
+ }
10
+ export interface SupportConnectReadInput {
11
+ appId: string;
12
+ sourceId: string;
13
+ ticketId: string;
14
+ ticketRevision: string;
15
+ }
16
+ export interface SupportConnectEvidence {
17
+ appId: string;
18
+ channel: 'voice';
19
+ generatedAt: number;
20
+ milestones: {
21
+ kind: SupportConnectIngressInput['kind'];
22
+ occurredAt: number;
23
+ }[];
24
+ provenance: 'aws_connect_contact_metadata';
25
+ schemaVersion: 'support_connect_metadata_v1';
26
+ sourceId: string;
27
+ ticketId: string;
28
+ ticketRevision: string;
29
+ validUntil: number;
30
+ }
31
+ /** Host-only ingress. trustedIamPrincipal MUST originate from an AWS_IAM gateway route,
32
+ * never a body/header/GraphQL argument. */
33
+ export declare const ingestSupportConnectMetadata: (context: ApiContext, input: SupportConnectIngressInput, trustedIamPrincipal: string, now?: () => number, client?: Pick<ConnectClient, 'send'>) => Promise<{
34
+ duplicate: boolean;
35
+ kind: SupportConnectIngressInput['kind'];
36
+ occurredAt: number;
37
+ }>;
38
+ /** Ordinary current read authority; provider contact IDs, principals, identities and raw responses are excluded. */
39
+ export declare const readSupportConnectEvidence: (context: ApiContext, input: SupportConnectReadInput, now?: () => number) => Promise<SupportConnectEvidence>;