@learncard/network-brain-service 3.19.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/.env.example +47 -82
  2. package/AGENTS.md +52 -0
  3. package/CHANGELOG.md +147 -0
  4. package/README.md +51 -2
  5. package/bootstrapLambda.test.ts +72 -0
  6. package/config/config.dev.json +29 -0
  7. package/config/config.example.json +29 -0
  8. package/config/config.json +1 -0
  9. package/config/config.production.json +29 -0
  10. package/config/config.scouts.dev.json +24 -0
  11. package/config/config.scouts.production.json +24 -0
  12. package/contractEventsLambda.ts +18 -0
  13. package/contractEventsLambdaApp.ts +19 -0
  14. package/didWebLambda.ts +13 -18
  15. package/didWebLambdaApp.ts +22 -0
  16. package/dist/accesslayer/app-manifest-version/create.d.ts +10 -0
  17. package/dist/accesslayer/app-manifest-version/create.d.ts.map +1 -0
  18. package/dist/accesslayer/app-manifest-version/read.d.ts +11 -0
  19. package/dist/accesslayer/app-manifest-version/read.d.ts.map +1 -0
  20. package/dist/accesslayer/app-manifest-version/update.d.ts +7 -0
  21. package/dist/accesslayer/app-manifest-version/update.d.ts.map +1 -0
  22. package/dist/accesslayer/app-store-listing/read.d.ts +2 -1
  23. package/dist/accesslayer/app-store-listing/read.d.ts.map +1 -1
  24. package/dist/accesslayer/app-store-listing/relationships/create.d.ts +1 -0
  25. package/dist/accesslayer/app-store-listing/relationships/create.d.ts.map +1 -1
  26. package/dist/accesslayer/app-store-listing/relationships/read.d.ts +2 -0
  27. package/dist/accesslayer/app-store-listing/relationships/read.d.ts.map +1 -1
  28. package/dist/accesslayer/app-store-listing/update.d.ts +1 -0
  29. package/dist/accesslayer/app-store-listing/update.d.ts.map +1 -1
  30. package/dist/accesslayer/boost/relationships/create.d.ts +2 -1
  31. package/dist/accesslayer/boost/relationships/create.d.ts.map +1 -1
  32. package/dist/accesslayer/consentflowcontract/create.d.ts +9 -1
  33. package/dist/accesslayer/consentflowcontract/create.d.ts.map +1 -1
  34. package/dist/accesslayer/consentflowcontract/read.d.ts +34 -3
  35. package/dist/accesslayer/consentflowcontract/read.d.ts.map +1 -1
  36. package/dist/accesslayer/consentflowcontract/relationships/create.d.ts +4 -1
  37. package/dist/accesslayer/consentflowcontract/relationships/create.d.ts.map +1 -1
  38. package/dist/accesslayer/consentflowcontract/relationships/delete.d.ts.map +1 -1
  39. package/dist/accesslayer/consentflowcontract/relationships/read.d.ts +3 -2
  40. package/dist/accesslayer/consentflowcontract/relationships/read.d.ts.map +1 -1
  41. package/dist/accesslayer/consentflowcontract/relationships/recipients.d.ts +12 -0
  42. package/dist/accesslayer/consentflowcontract/relationships/recipients.d.ts.map +1 -0
  43. package/dist/accesslayer/consentflowcontract/relationships/smartResume.d.ts +12 -0
  44. package/dist/accesslayer/consentflowcontract/relationships/smartResume.d.ts.map +1 -0
  45. package/dist/accesslayer/consentflowcontract/relationships/update.d.ts +8 -5
  46. package/dist/accesslayer/consentflowcontract/relationships/update.d.ts.map +1 -1
  47. package/dist/accesslayer/credential/create.d.ts +2 -1
  48. package/dist/accesslayer/credential/create.d.ts.map +1 -1
  49. package/dist/accesslayer/credential/relationships/create.d.ts +4 -3
  50. package/dist/accesslayer/credential/relationships/create.d.ts.map +1 -1
  51. package/dist/accesslayer/inbox-credential/relationships/create.d.ts +2 -1
  52. package/dist/accesslayer/inbox-credential/relationships/create.d.ts.map +1 -1
  53. package/dist/accesslayer/inbox-credential/update.d.ts +2 -1
  54. package/dist/accesslayer/inbox-credential/update.d.ts.map +1 -1
  55. package/dist/accesslayer/presentation/read.d.ts.map +1 -1
  56. package/dist/accesslayer/presentation/relationships/create.d.ts +2 -2
  57. package/dist/accesslayer/presentation/relationships/create.d.ts.map +1 -1
  58. package/dist/accesslayer/presentation/relationships/read.d.ts.map +1 -1
  59. package/dist/accesslayer/share-link/abandon.d.ts +3 -0
  60. package/dist/accesslayer/share-link/abandon.d.ts.map +1 -0
  61. package/dist/accesslayer/share-link/attachment.d.ts +37 -0
  62. package/dist/accesslayer/share-link/attachment.d.ts.map +1 -0
  63. package/dist/accesslayer/share-link/cleanup.d.ts +6 -0
  64. package/dist/accesslayer/share-link/cleanup.d.ts.map +1 -0
  65. package/dist/accesslayer/share-link/errors.d.ts +8 -0
  66. package/dist/accesslayer/share-link/errors.d.ts.map +1 -0
  67. package/dist/accesslayer/share-link/finalize.d.ts +3 -0
  68. package/dist/accesslayer/share-link/finalize.d.ts.map +1 -0
  69. package/dist/accesslayer/share-link/helpers.d.ts +59 -0
  70. package/dist/accesslayer/share-link/helpers.d.ts.map +1 -0
  71. package/dist/accesslayer/share-link/index.d.ts +12 -0
  72. package/dist/accesslayer/share-link/index.d.ts.map +1 -0
  73. package/dist/accesslayer/share-link/list.d.ts +5 -0
  74. package/dist/accesslayer/share-link/list.d.ts.map +1 -0
  75. package/dist/accesslayer/share-link/read.d.ts +5 -0
  76. package/dist/accesslayer/share-link/read.d.ts.map +1 -0
  77. package/dist/accesslayer/share-link/receipt.d.ts +11 -0
  78. package/dist/accesslayer/share-link/receipt.d.ts.map +1 -0
  79. package/dist/accesslayer/share-link/recovery.d.ts +6 -0
  80. package/dist/accesslayer/share-link/recovery.d.ts.map +1 -0
  81. package/dist/accesslayer/share-link/reserve.d.ts +4 -0
  82. package/dist/accesslayer/share-link/reserve.d.ts.map +1 -0
  83. package/dist/accesslayer/share-link/revoke.d.ts +3 -0
  84. package/dist/accesslayer/share-link/revoke.d.ts.map +1 -0
  85. package/dist/accesslayer/share-link/transaction-execution.d.ts +18 -0
  86. package/dist/accesslayer/share-link/transaction-execution.d.ts.map +1 -0
  87. package/dist/accesslayer/share-link/transaction.d.ts +15 -0
  88. package/dist/accesslayer/share-link/transaction.d.ts.map +1 -0
  89. package/dist/accesslayer/share-link/types.d.ts +375 -0
  90. package/dist/accesslayer/share-link/types.d.ts.map +1 -0
  91. package/dist/app.d.ts +4 -0
  92. package/dist/app.d.ts.map +1 -1
  93. package/dist/cache/app-store.caches.d.ts +49 -0
  94. package/dist/cache/app-store.caches.d.ts.map +1 -1
  95. package/dist/config/applyDockerStageConfig.d.ts +2 -0
  96. package/dist/config/applyDockerStageConfig.d.ts.map +1 -0
  97. package/dist/config/environment.d.ts +14 -0
  98. package/dist/config/environment.d.ts.map +1 -1
  99. package/dist/config/serverlessFunctionEnv.test.d.ts +2 -0
  100. package/dist/config/serverlessFunctionEnv.test.d.ts.map +1 -0
  101. package/dist/config/stageConfig.d.ts +112 -0
  102. package/dist/config/stageConfig.d.ts.map +1 -0
  103. package/dist/config/stageConfig.test.d.ts +2 -0
  104. package/dist/config/stageConfig.test.d.ts.map +1 -0
  105. package/dist/constants/auth-grant.d.ts +2 -0
  106. package/dist/constants/auth-grant.d.ts.map +1 -1
  107. package/dist/didkit_wasm_bg.wasm +0 -0
  108. package/dist/docker-entry.d.ts +1 -1
  109. package/dist/docker-entry.d.ts.map +1 -1
  110. package/dist/helpers/app-manifest.helpers.d.ts +5 -0
  111. package/dist/helpers/app-manifest.helpers.d.ts.map +1 -0
  112. package/dist/helpers/boost.helpers.d.ts.map +1 -1
  113. package/dist/helpers/claim-hooks.helpers.d.ts +2 -1
  114. package/dist/helpers/claim-hooks.helpers.d.ts.map +1 -1
  115. package/dist/helpers/consent-referral.helpers.d.ts +2 -0
  116. package/dist/helpers/consent-referral.helpers.d.ts.map +1 -0
  117. package/dist/helpers/consent-scopes.helpers.d.ts +7 -0
  118. package/dist/helpers/consent-scopes.helpers.d.ts.map +1 -0
  119. package/dist/helpers/contract-event-maintenance.helpers.d.ts +3 -0
  120. package/dist/helpers/contract-event-maintenance.helpers.d.ts.map +1 -0
  121. package/dist/helpers/contract-events.helpers.d.ts +25 -0
  122. package/dist/helpers/contract-events.helpers.d.ts.map +1 -0
  123. package/dist/helpers/contract-requests.helpers.d.ts +19 -0
  124. package/dist/helpers/contract-requests.helpers.d.ts.map +1 -0
  125. package/dist/helpers/credentialSubject.helpers.d.ts +3 -0
  126. package/dist/helpers/credentialSubject.helpers.d.ts.map +1 -0
  127. package/dist/helpers/credentialSubject.helpers.test.d.ts +2 -0
  128. package/dist/helpers/credentialSubject.helpers.test.d.ts.map +1 -0
  129. package/dist/helpers/finalize-inbox.helpers.d.ts +3 -3
  130. package/dist/helpers/finalize-inbox.helpers.d.ts.map +1 -1
  131. package/dist/helpers/inbox.helpers.d.ts.map +1 -1
  132. package/dist/helpers/inline-template.helpers.d.ts +45 -0
  133. package/dist/helpers/inline-template.helpers.d.ts.map +1 -0
  134. package/dist/helpers/notificationMessages.d.ts +1 -1
  135. package/dist/helpers/notificationMessages.d.ts.map +1 -1
  136. package/dist/helpers/notificationQueue.helpers.d.ts.map +1 -1
  137. package/dist/helpers/notifications.helpers.d.ts +6 -0
  138. package/dist/helpers/notifications.helpers.d.ts.map +1 -1
  139. package/dist/helpers/presentation-metadata.d.ts +4 -0
  140. package/dist/helpers/presentation-metadata.d.ts.map +1 -0
  141. package/dist/helpers/presentation.helpers.d.ts +1 -1
  142. package/dist/helpers/presentation.helpers.d.ts.map +1 -1
  143. package/dist/helpers/profile.helpers.d.ts +2 -0
  144. package/dist/helpers/profile.helpers.d.ts.map +1 -1
  145. package/dist/helpers/share-content-client/adapters.d.ts +10 -0
  146. package/dist/helpers/share-content-client/adapters.d.ts.map +1 -0
  147. package/dist/helpers/share-content-client/canonical.d.ts +7 -0
  148. package/dist/helpers/share-content-client/canonical.d.ts.map +1 -0
  149. package/dist/helpers/share-content-client/client.d.ts +5 -0
  150. package/dist/helpers/share-content-client/client.d.ts.map +1 -0
  151. package/dist/helpers/share-content-client/config.d.ts +11 -0
  152. package/dist/helpers/share-content-client/config.d.ts.map +1 -0
  153. package/dist/helpers/share-content-client/index.d.ts +6 -0
  154. package/dist/helpers/share-content-client/index.d.ts.map +1 -0
  155. package/dist/helpers/share-content-client/responses.d.ts +16 -0
  156. package/dist/helpers/share-content-client/responses.d.ts.map +1 -0
  157. package/dist/helpers/share-content-client/types.d.ts +145 -0
  158. package/dist/helpers/share-content-client/types.d.ts.map +1 -0
  159. package/dist/helpers/share-link-attachment-access.d.ts +4 -0
  160. package/dist/helpers/share-link-attachment-access.d.ts.map +1 -0
  161. package/dist/helpers/share-link-attachment.d.ts +18 -0
  162. package/dist/helpers/share-link-attachment.d.ts.map +1 -0
  163. package/dist/helpers/share-link-coordinator/attachment-stat.d.ts +5 -0
  164. package/dist/helpers/share-link-coordinator/attachment-stat.d.ts.map +1 -0
  165. package/dist/helpers/share-link-coordinator/budget-helpers.d.ts +5 -0
  166. package/dist/helpers/share-link-coordinator/budget-helpers.d.ts.map +1 -0
  167. package/dist/helpers/share-link-coordinator/cleanup-runner.d.ts +3 -0
  168. package/dist/helpers/share-link-coordinator/cleanup-runner.d.ts.map +1 -0
  169. package/dist/helpers/share-link-coordinator/coordinator.d.ts +4 -0
  170. package/dist/helpers/share-link-coordinator/coordinator.d.ts.map +1 -0
  171. package/dist/helpers/share-link-coordinator/index.d.ts +5 -0
  172. package/dist/helpers/share-link-coordinator/index.d.ts.map +1 -0
  173. package/dist/helpers/share-link-coordinator/recovery-runner.d.ts +9 -0
  174. package/dist/helpers/share-link-coordinator/recovery-runner.d.ts.map +1 -0
  175. package/dist/helpers/share-link-coordinator/runtime.d.ts +11 -0
  176. package/dist/helpers/share-link-coordinator/runtime.d.ts.map +1 -0
  177. package/dist/helpers/share-link-coordinator/stat.d.ts +4 -0
  178. package/dist/helpers/share-link-coordinator/stat.d.ts.map +1 -0
  179. package/dist/helpers/share-link-coordinator/types.d.ts +160 -0
  180. package/dist/helpers/share-link-coordinator/types.d.ts.map +1 -0
  181. package/dist/helpers/share-link-lifecycle/index.d.ts +5 -0
  182. package/dist/helpers/share-link-lifecycle/index.d.ts.map +1 -0
  183. package/dist/helpers/share-link-lifecycle/lease.helpers.d.ts +4 -0
  184. package/dist/helpers/share-link-lifecycle/lease.helpers.d.ts.map +1 -0
  185. package/dist/helpers/share-link-lifecycle/recovery.helpers.d.ts +21 -0
  186. package/dist/helpers/share-link-lifecycle/recovery.helpers.d.ts.map +1 -0
  187. package/dist/helpers/share-link-lifecycle/request-hash.helpers.d.ts +9 -0
  188. package/dist/helpers/share-link-lifecycle/request-hash.helpers.d.ts.map +1 -0
  189. package/dist/helpers/share-link-lifecycle/types.d.ts +14 -0
  190. package/dist/helpers/share-link-lifecycle/types.d.ts.map +1 -0
  191. package/dist/helpers/share-link-maintenance/budget.d.ts +12 -0
  192. package/dist/helpers/share-link-maintenance/budget.d.ts.map +1 -0
  193. package/dist/helpers/share-link-maintenance/config.d.ts +48 -0
  194. package/dist/helpers/share-link-maintenance/config.d.ts.map +1 -0
  195. package/dist/helpers/share-link-maintenance/index.d.ts +8 -0
  196. package/dist/helpers/share-link-maintenance/index.d.ts.map +1 -0
  197. package/dist/helpers/share-link-maintenance/runner.d.ts +20 -0
  198. package/dist/helpers/share-link-maintenance/runner.d.ts.map +1 -0
  199. package/dist/helpers/share-link-maintenance/runtime.d.ts +38 -0
  200. package/dist/helpers/share-link-maintenance/runtime.d.ts.map +1 -0
  201. package/dist/helpers/share-link-maintenance/scheduler.d.ts +18 -0
  202. package/dist/helpers/share-link-maintenance/scheduler.d.ts.map +1 -0
  203. package/dist/helpers/share-link-maintenance/telemetry.d.ts +5 -0
  204. package/dist/helpers/share-link-maintenance/telemetry.d.ts.map +1 -0
  205. package/dist/helpers/share-link-maintenance/types.d.ts +56 -0
  206. package/dist/helpers/share-link-maintenance/types.d.ts.map +1 -0
  207. package/dist/helpers/share-link-owner/config.d.ts +16 -0
  208. package/dist/helpers/share-link-owner/config.d.ts.map +1 -0
  209. package/dist/helpers/share-link-owner/diagnostics.d.ts +26 -0
  210. package/dist/helpers/share-link-owner/diagnostics.d.ts.map +1 -0
  211. package/dist/helpers/share-link-owner/lazy-initializer.d.ts +2 -0
  212. package/dist/helpers/share-link-owner/lazy-initializer.d.ts.map +1 -0
  213. package/dist/helpers/share-link-owner-projection.d.ts +4 -0
  214. package/dist/helpers/share-link-owner-projection.d.ts.map +1 -0
  215. package/dist/helpers/share-link-passcode-abuse.d.ts +2 -0
  216. package/dist/helpers/share-link-passcode-abuse.d.ts.map +1 -0
  217. package/dist/helpers/share-link-passcode.d.ts +6 -0
  218. package/dist/helpers/share-link-passcode.d.ts.map +1 -0
  219. package/dist/helpers/share-link-policy/index.d.ts +4 -0
  220. package/dist/helpers/share-link-policy/index.d.ts.map +1 -0
  221. package/dist/helpers/share-link-policy/production.d.ts +11 -0
  222. package/dist/helpers/share-link-policy/production.d.ts.map +1 -0
  223. package/dist/helpers/share-link-policy/resolver.d.ts +6 -0
  224. package/dist/helpers/share-link-policy/resolver.d.ts.map +1 -0
  225. package/dist/helpers/share-link-policy/types.d.ts +22 -0
  226. package/dist/helpers/share-link-policy/types.d.ts.map +1 -0
  227. package/dist/helpers/share-link-public/config.d.ts +13 -0
  228. package/dist/helpers/share-link-public/config.d.ts.map +1 -0
  229. package/dist/helpers/share-link-view-notification.d.ts +2 -0
  230. package/dist/helpers/share-link-view-notification.d.ts.map +1 -0
  231. package/dist/helpers/signingAuthority.helpers.d.ts.map +1 -1
  232. package/dist/helpers/smartResume.helpers.d.ts +3 -0
  233. package/dist/helpers/smartResume.helpers.d.ts.map +1 -0
  234. package/dist/index.js +2 -2
  235. package/dist/models/AppManifestVersion.d.ts +20 -0
  236. package/dist/models/AppManifestVersion.d.ts.map +1 -0
  237. package/dist/models/AppStoreListing.d.ts +13 -0
  238. package/dist/models/AppStoreListing.d.ts.map +1 -1
  239. package/dist/models/ConsentFlowContract.d.ts +13 -2
  240. package/dist/models/ConsentFlowContract.d.ts.map +1 -1
  241. package/dist/models/ConsentFlowTerms.d.ts.map +1 -1
  242. package/dist/models/ConsentFlowTransaction.d.ts.map +1 -1
  243. package/dist/models/Integration.d.ts +2 -0
  244. package/dist/models/Integration.d.ts.map +1 -1
  245. package/dist/models/Presentation.d.ts +2 -0
  246. package/dist/models/Presentation.d.ts.map +1 -1
  247. package/dist/models/Profile.d.ts +2 -0
  248. package/dist/models/Profile.d.ts.map +1 -1
  249. package/dist/models/ShareLink.d.ts +46 -0
  250. package/dist/models/ShareLink.d.ts.map +1 -0
  251. package/dist/models/ShareViewReceipt.d.ts +22 -0
  252. package/dist/models/ShareViewReceipt.d.ts.map +1 -0
  253. package/dist/models/index.d.ts +2 -0
  254. package/dist/models/index.d.ts.map +1 -1
  255. package/dist/models/share-link-constraints.d.ts +3 -0
  256. package/dist/models/share-link-constraints.d.ts.map +1 -0
  257. package/dist/openapi.d.ts +1 -1
  258. package/dist/openapi.d.ts.map +1 -1
  259. package/dist/public-share-link-http.d.ts +4 -0
  260. package/dist/public-share-link-http.d.ts.map +1 -0
  261. package/dist/routes/app-store.d.ts +619 -0
  262. package/dist/routes/app-store.d.ts.map +1 -1
  263. package/dist/routes/boosts.d.ts +2 -2
  264. package/dist/routes/boosts.d.ts.map +1 -1
  265. package/dist/routes/contracts.d.ts +148 -5
  266. package/dist/routes/contracts.d.ts.map +1 -1
  267. package/dist/routes/credentials.d.ts +35 -1
  268. package/dist/routes/credentials.d.ts.map +1 -1
  269. package/dist/routes/inbox.d.ts +52 -2
  270. package/dist/routes/inbox.d.ts.map +1 -1
  271. package/dist/routes/index.d.ts +153 -0
  272. package/dist/routes/index.d.ts.map +1 -1
  273. package/dist/routes/presentations.d.ts +1 -0
  274. package/dist/routes/presentations.d.ts.map +1 -1
  275. package/dist/routes/profile-manager.d.ts.map +1 -1
  276. package/dist/routes/profiles.d.ts.map +1 -1
  277. package/dist/routes/public-share-links.d.ts +285 -0
  278. package/dist/routes/public-share-links.d.ts.map +1 -0
  279. package/dist/routes/share-links.d.ts +1005 -0
  280. package/dist/routes/share-links.d.ts.map +1 -0
  281. package/dist/routes/test.d.ts +5 -0
  282. package/dist/routes/test.d.ts.map +1 -1
  283. package/dist/routes/workflows.d.ts.map +1 -1
  284. package/dist/services/delivery/adapters/postmark.adapter.d.ts.map +1 -1
  285. package/dist/types/app-manifest.d.ts +339 -0
  286. package/dist/types/app-manifest.d.ts.map +1 -0
  287. package/dist/types/app-store-listing.d.ts +34 -0
  288. package/dist/types/app-store-listing.d.ts.map +1 -1
  289. package/dist/types/consentflowcontract.d.ts +31 -4
  290. package/dist/types/consentflowcontract.d.ts.map +1 -1
  291. package/dist/types/credential-refresh.d.ts +1 -1
  292. package/esbuildPlugins.cjs +1 -0
  293. package/lambda.ts +49 -192
  294. package/lambdaApp.ts +203 -0
  295. package/package.json +25 -17
  296. package/scripts/export-openapi.ts +20 -0
  297. package/scripts/offline-schema-environment.ts +18 -0
  298. package/scripts/seed-demo-persona.ts +425 -0
  299. package/scripts/verify-python-contracts.ts +72 -0
  300. package/serverless-local.yml +3 -6
  301. package/serverless.function-env.cjs +50 -0
  302. package/serverless.local.yml +0 -1
  303. package/serverless.yml +44 -55
  304. package/shareLinkMaintenanceLambda.ts +18 -0
  305. package/shareLinkMaintenanceLambdaApp.ts +50 -0
  306. package/src/accesslayer/app-manifest-version/create.ts +57 -0
  307. package/src/accesslayer/app-manifest-version/read.ts +129 -0
  308. package/src/accesslayer/app-manifest-version/update.ts +61 -0
  309. package/src/accesslayer/app-store-listing/read.ts +6 -0
  310. package/src/accesslayer/app-store-listing/relationships/create.ts +20 -0
  311. package/src/accesslayer/app-store-listing/relationships/read.ts +24 -1
  312. package/src/accesslayer/app-store-listing/update.ts +15 -0
  313. package/src/accesslayer/boost/relationships/create.ts +8 -2
  314. package/src/accesslayer/consentflowcontract/create.ts +81 -8
  315. package/src/accesslayer/consentflowcontract/read.ts +84 -10
  316. package/src/accesslayer/consentflowcontract/relationships/create.ts +125 -109
  317. package/src/accesslayer/consentflowcontract/relationships/delete.ts +1 -0
  318. package/src/accesslayer/consentflowcontract/relationships/read.ts +184 -108
  319. package/src/accesslayer/consentflowcontract/relationships/recipients.ts +125 -0
  320. package/src/accesslayer/consentflowcontract/relationships/smartResume.ts +125 -0
  321. package/src/accesslayer/consentflowcontract/relationships/update.ts +255 -217
  322. package/src/accesslayer/credential/create.test.ts +2 -115
  323. package/src/accesslayer/credential/create.ts +11 -6
  324. package/src/accesslayer/credential/relationships/create.ts +17 -10
  325. package/src/accesslayer/inbox-credential/relationships/create.ts +70 -48
  326. package/src/accesslayer/inbox-credential/update.ts +4 -2
  327. package/src/accesslayer/presentation/read.ts +57 -25
  328. package/src/accesslayer/presentation/relationships/create.ts +54 -11
  329. package/src/accesslayer/presentation/relationships/read.ts +21 -6
  330. package/src/accesslayer/share-link/abandon.ts +120 -0
  331. package/src/accesslayer/share-link/attachment.ts +360 -0
  332. package/src/accesslayer/share-link/cleanup.ts +271 -0
  333. package/src/accesslayer/share-link/errors.ts +32 -0
  334. package/src/accesslayer/share-link/finalize.ts +313 -0
  335. package/src/accesslayer/share-link/helpers.ts +450 -0
  336. package/src/accesslayer/share-link/index.ts +11 -0
  337. package/src/accesslayer/share-link/list.ts +162 -0
  338. package/src/accesslayer/share-link/read.ts +107 -0
  339. package/src/accesslayer/share-link/receipt.ts +548 -0
  340. package/src/accesslayer/share-link/recovery.ts +565 -0
  341. package/src/accesslayer/share-link/reserve.ts +763 -0
  342. package/src/accesslayer/share-link/revoke.ts +232 -0
  343. package/src/accesslayer/share-link/transaction-execution.ts +72 -0
  344. package/src/accesslayer/share-link/transaction.ts +126 -0
  345. package/src/accesslayer/share-link/types.ts +606 -0
  346. package/src/app.ts +6 -0
  347. package/src/cache/app-store.caches.ts +35 -0
  348. package/src/config/applyDockerStageConfig.ts +6 -0
  349. package/src/config/environment.test.ts +17 -12
  350. package/src/config/environment.ts +15 -0
  351. package/src/config/serverlessFunctionEnv.test.ts +105 -0
  352. package/src/config/stageConfig.test.ts +25 -0
  353. package/src/config/stageConfig.ts +24 -0
  354. package/src/constants/auth-grant.ts +5 -0
  355. package/src/docker-entry.ts +81 -0
  356. package/src/helpers/app-manifest.helpers.ts +185 -0
  357. package/src/helpers/boost.helpers.ts +4 -31
  358. package/src/helpers/claim-hooks.helpers.ts +20 -7
  359. package/src/helpers/consent-referral.helpers.ts +6 -0
  360. package/src/helpers/consent-scopes.helpers.ts +58 -0
  361. package/src/helpers/contract-event-maintenance.helpers.ts +43 -0
  362. package/src/helpers/contract-events.helpers.ts +540 -0
  363. package/src/helpers/contract-requests.helpers.ts +211 -0
  364. package/src/helpers/credentialSubject.helpers.test.ts +114 -0
  365. package/src/helpers/credentialSubject.helpers.ts +40 -0
  366. package/src/helpers/finalize-inbox.helpers.ts +163 -44
  367. package/src/helpers/inbox.helpers.ts +58 -70
  368. package/src/helpers/inline-template.helpers.ts +560 -0
  369. package/src/helpers/notificationMessages.ts +77 -1
  370. package/src/helpers/notificationQueue.helpers.ts +23 -5
  371. package/src/helpers/notifications.helpers.ts +25 -1
  372. package/src/helpers/presentation-metadata.ts +41 -0
  373. package/src/helpers/presentation.helpers.ts +27 -20
  374. package/src/helpers/profile.helpers.ts +13 -0
  375. package/src/helpers/share-content-client/adapters.ts +55 -0
  376. package/src/helpers/share-content-client/canonical.ts +25 -0
  377. package/src/helpers/share-content-client/client.ts +440 -0
  378. package/src/helpers/share-content-client/config.ts +189 -0
  379. package/src/helpers/share-content-client/index.ts +27 -0
  380. package/src/helpers/share-content-client/responses.ts +273 -0
  381. package/src/helpers/share-content-client/types.ts +253 -0
  382. package/src/helpers/share-link-attachment-access.ts +87 -0
  383. package/src/helpers/share-link-attachment.ts +115 -0
  384. package/src/helpers/share-link-coordinator/attachment-stat.ts +41 -0
  385. package/src/helpers/share-link-coordinator/budget-helpers.ts +53 -0
  386. package/src/helpers/share-link-coordinator/cleanup-runner.ts +286 -0
  387. package/src/helpers/share-link-coordinator/coordinator.ts +727 -0
  388. package/src/helpers/share-link-coordinator/index.ts +8 -0
  389. package/src/helpers/share-link-coordinator/recovery-runner.ts +443 -0
  390. package/src/helpers/share-link-coordinator/runtime.ts +88 -0
  391. package/src/helpers/share-link-coordinator/stat.ts +30 -0
  392. package/src/helpers/share-link-coordinator/types.ts +353 -0
  393. package/src/helpers/share-link-lifecycle/index.ts +4 -0
  394. package/src/helpers/share-link-lifecycle/lease.helpers.ts +35 -0
  395. package/src/helpers/share-link-lifecycle/recovery.helpers.ts +173 -0
  396. package/src/helpers/share-link-lifecycle/request-hash.helpers.ts +130 -0
  397. package/src/helpers/share-link-lifecycle/types.ts +58 -0
  398. package/src/helpers/share-link-maintenance/budget.ts +63 -0
  399. package/src/helpers/share-link-maintenance/config.ts +312 -0
  400. package/src/helpers/share-link-maintenance/index.ts +24 -0
  401. package/src/helpers/share-link-maintenance/runner.ts +251 -0
  402. package/src/helpers/share-link-maintenance/runtime.ts +340 -0
  403. package/src/helpers/share-link-maintenance/scheduler.ts +126 -0
  404. package/src/helpers/share-link-maintenance/telemetry.ts +73 -0
  405. package/src/helpers/share-link-maintenance/types.ts +91 -0
  406. package/src/helpers/share-link-owner/config.ts +48 -0
  407. package/src/helpers/share-link-owner/diagnostics.ts +89 -0
  408. package/src/helpers/share-link-owner/lazy-initializer.ts +29 -0
  409. package/src/helpers/share-link-owner-projection.ts +54 -0
  410. package/src/helpers/share-link-passcode-abuse.ts +36 -0
  411. package/src/helpers/share-link-passcode.ts +47 -0
  412. package/src/helpers/share-link-policy/index.ts +7 -0
  413. package/src/helpers/share-link-policy/production.ts +108 -0
  414. package/src/helpers/share-link-policy/resolver.ts +113 -0
  415. package/src/helpers/share-link-policy/types.ts +56 -0
  416. package/src/helpers/share-link-public/config.ts +41 -0
  417. package/src/helpers/share-link-view-notification.ts +18 -0
  418. package/src/helpers/signingAuthority.helpers.ts +23 -14
  419. package/src/helpers/smartResume.helpers.ts +123 -0
  420. package/src/models/AppManifestVersion.ts +43 -0
  421. package/src/models/AppStoreListing.ts +32 -0
  422. package/src/models/ConsentFlowContract.ts +34 -3
  423. package/src/models/ConsentFlowTerms.ts +10 -0
  424. package/src/models/ConsentFlowTransaction.ts +3 -0
  425. package/src/models/Integration.ts +2 -0
  426. package/src/models/Presentation.ts +2 -2
  427. package/src/models/Profile.ts +3 -2
  428. package/src/models/ShareLink.ts +134 -0
  429. package/src/models/ShareViewReceipt.ts +69 -0
  430. package/src/models/index.ts +25 -0
  431. package/src/models/share-link-constraints.ts +98 -0
  432. package/src/openapi.ts +44 -8
  433. package/src/public-share-link-http.ts +49 -0
  434. package/src/routes/app-store.ts +1056 -38
  435. package/src/routes/boosts.ts +14 -25
  436. package/src/routes/contracts.ts +384 -273
  437. package/src/routes/inbox.ts +4 -2
  438. package/src/routes/index.ts +142 -44
  439. package/src/routes/presentations.ts +19 -3
  440. package/src/routes/profile-manager.ts +29 -2
  441. package/src/routes/profiles.ts +29 -6
  442. package/src/routes/public-share-links.ts +983 -0
  443. package/src/routes/share-links.ts +709 -0
  444. package/src/routes/workflows.ts +3 -2
  445. package/src/services/delivery/adapters/postmark.adapter.ts +4 -1
  446. package/src/types/app-manifest.ts +28 -0
  447. package/src/types/app-store-listing.ts +13 -0
  448. package/src/types/consentflowcontract.ts +25 -4
  449. package/test/app-manifest.helpers.spec.ts +170 -0
  450. package/test/app-manifest.routes.spec.ts +299 -0
  451. package/test/app-store-listing-updates.spec.ts +236 -0
  452. package/test/app-store-listing.spec.ts +65 -3
  453. package/test/consent-data-boundaries.spec.ts +352 -0
  454. package/test/consent-recipients.spec.ts +513 -0
  455. package/test/consent-scopes.helpers.spec.ts +67 -0
  456. package/test/consentflow.spec.ts +63 -2
  457. package/test/contract-requests.spec.ts +1588 -0
  458. package/test/credential-storage.neo4j.spec.ts +122 -0
  459. package/test/dids.spec.ts +10 -1
  460. package/test/guardian-gated-routes.spec.ts +49 -0
  461. package/test/helpers/share-link-fixtures.ts +94 -0
  462. package/test/inbox-security.e2e.ts +26 -10
  463. package/test/inbox.spec.ts +184 -8
  464. package/test/inline-template.helpers.spec.ts +49 -0
  465. package/test/managed-recipient-inbox.spec.ts +152 -0
  466. package/test/notificationMessages.spec.ts +13 -0
  467. package/test/openapi.spec.ts +14 -53
  468. package/test/presentations.spec.ts +54 -6
  469. package/test/profiles.spec.ts +97 -1
  470. package/test/share-content-client.contract.spec.ts +365 -0
  471. package/test/share-content-client.unit.spec.ts +462 -0
  472. package/test/share-link-abuse.unit.spec.ts +65 -0
  473. package/test/share-link-attachment.neo4j.spec.ts +262 -0
  474. package/test/share-link-attachment.unit.spec.ts +244 -0
  475. package/test/share-link-coordinator.neo4j.spec.ts +684 -0
  476. package/test/share-link-coordinator.unit.spec.ts +990 -0
  477. package/test/share-link-dependency-diagnostics.unit.spec.ts +127 -0
  478. package/test/share-link-lifecycle.neo4j.spec.ts +1411 -0
  479. package/test/share-link-lifecycle.unit.spec.ts +205 -0
  480. package/test/share-link-list-cursor.unit.spec.ts +86 -0
  481. package/test/share-link-list.neo4j.spec.ts +324 -0
  482. package/test/share-link-maintenance.neo4j.spec.ts +355 -0
  483. package/test/share-link-maintenance.unit.spec.ts +1140 -0
  484. package/test/share-link-owner-policy.unit.spec.ts +210 -0
  485. package/test/share-link-owner-route.unit.spec.ts +820 -0
  486. package/test/share-link-owner-runtime.unit.spec.ts +102 -0
  487. package/test/share-link-passcode.unit.spec.ts +29 -0
  488. package/test/share-link-policy.unit.spec.ts +149 -0
  489. package/test/share-link-presentation-metadata.unit.spec.ts +49 -0
  490. package/test/share-link-production-policy.unit.spec.ts +126 -0
  491. package/test/share-link-public-config.unit.spec.ts +64 -0
  492. package/test/share-link-public-http-adapter.unit.spec.ts +315 -0
  493. package/test/share-link-public-route.unit.spec.ts +1079 -0
  494. package/test/share-link-receipt.neo4j.spec.ts +943 -0
  495. package/test/share-link-recovery.neo4j.spec.ts +935 -0
  496. package/test/share-link-recovery.unit.spec.ts +726 -0
  497. package/test/share-link-service-policy.neo4j.spec.ts +403 -0
  498. package/test/signing-authority-encryption.spec.ts +75 -0
  499. package/test/smart-resume-consent.spec.ts +233 -0
  500. package/test/smart-resume-upload.spec.ts +65 -0
  501. package/tsconfig.build.json +1 -1
  502. package/tsconfig.json +1 -0
  503. package/vitest.config.ts +14 -0
  504. package/vitest.inbox-e2e.config.ts +2 -0
  505. package/vitest.share-links-neo4j.config.ts +19 -0
  506. package/vitest.share-links-unit.config.ts +28 -0
  507. package/workerLambda.test.ts +100 -0
package/serverless.yml CHANGED
@@ -138,61 +138,20 @@ provider:
138
138
  timeout: 29
139
139
  stage: ${opt:stage, "dev"}
140
140
  region: ${opt:region, "us-east-1"}
141
- environment:
142
- PORT: ${env:PORT, 3000}
143
- INBOX_DELETE_EXPIRED_RECORDS: ${env:INBOX_DELETE_EXPIRED_RECORDS, "false"}
144
- LAMBDA_STAGE: ${opt:stage, "dev"}
145
- INBOX_BATCH_ITEMS_PER_HOUR: ${env:INBOX_BATCH_ITEMS_PER_HOUR, '10000'}
146
- SEED: ${env:SEED}
147
- DOMAIN_NAME: ${env:DOMAIN_NAME}
148
- CLIENT_APP_DOMAIN_NAME: ${env:CLIENT_APP_DOMAIN_NAME}
149
- NOTIFICATIONS_SERVICE_WEBHOOK_URL: ${env:NOTIFICATIONS_SERVICE_WEBHOOK_URL}
150
- NEO4J_URI: ${env:NEO4J_URI}
151
- NEO4J_USERNAME: ${env:NEO4J_USERNAME}
152
- NEO4J_PASSWORD: ${env:NEO4J_PASSWORD}
153
- POSTMARK_API_KEY: ${env:POSTMARK_API_KEY}
154
- POSTMARK_FROM_EMAIL: ${env:POSTMARK_FROM_EMAIL}
155
- MESSAGEBIRD_AUTH_TOKEN: ${env:MESSAGEBIRD_AUTH_TOKEN}
156
- MESSAGEBIRD_ORIGINATOR: ${env:MESSAGEBIRD_ORIGINATOR}
157
- TRUSTED_ISSUERS_WHITELIST: ${env:TRUSTED_ISSUERS_WHITELIST, ""}
158
- TRUSTED_BRAIN_SERVICES: ${env:TRUSTED_BRAIN_SERVICES, ""}
159
- BRAIN_SERVICE_REGISTRY_URL: ${env:BRAIN_SERVICE_REGISTRY_URL, ""}
160
- DCC_KNOWN_REGISTRIES_URL: ${env:DCC_KNOWN_REGISTRIES_URL, ""}
161
- SENTRY_DSN: ${env:SENTRY_DSN}
162
- SENTRY_ENV: ${env:SENTRY_ENV}
163
- SENTRY_AUTH_TOKEN: ${env:SENTRY_AUTH_TOKEN}
164
- SENTRY_ORG: ${env:SENTRY_ORG}
165
- SENTRY_PROJECT: ${env:SENTRY_PROJECT}
166
- REDIS_HOST:
167
- 'Fn::GetAtt': [ElasticCacheCluster, RedisEndpoint.Address]
168
- REDIS_PORT:
169
- 'Fn::GetAtt': [ElasticCacheCluster, RedisEndpoint.Port]
170
- NOTIFICATIONS_QUEUE_URL: ${construct:notifications-queue.queueUrl}
171
- INBOX_QUEUE_URL: ${construct:inbox-queue.queueUrl}
172
- SKILL_EMBEDDING_GOOGLE_API_KEY: ${env:SKILL_EMBEDDING_GOOGLE_API_KEY, ""}
173
- SKILL_EMBEDDING_GOOGLE_MODEL: ${env:SKILL_EMBEDDING_GOOGLE_MODEL, "gemini-embedding-001"}
174
- SKILL_EMBEDDING_BATCH_SIZE: ${env:SKILL_EMBEDDING_BATCH_SIZE, "25"}
175
- SKILL_EMBEDDING_BACKFILL_ON_STARTUP: ${env:SKILL_EMBEDDING_BACKFILL_ON_STARTUP, "false"}
176
- SKILL_EMBEDDING_BACKFILL_LOCK_TTL_SECONDS: ${env:SKILL_EMBEDDING_BACKFILL_LOCK_TTL_SECONDS, "900"}
177
- SKILL_EMBEDDING_BACKFILL_PAGE_SIZE: ${env:SKILL_EMBEDDING_BACKFILL_PAGE_SIZE, "100"}
178
- SKILL_EMBEDDING_BACKFILL_BATCH_SIZE: ${env:SKILL_EMBEDDING_BACKFILL_BATCH_SIZE, "50"}
179
- SMART_RESUME_CLIENT_ID: ${env:SMART_RESUME_CLIENT_ID, ""}
180
- SMART_RESUME_ACCESS_KEY: ${env:SMART_RESUME_ACCESS_KEY, ""}
181
- SMART_RESUME_CONTRACT_URI: ${env:SMART_RESUME_CONTRACT_URI, ""}
182
- LOGIN_PROVIDER_DID: ${env:LOGIN_PROVIDER_DID, ""}
183
- OIDC_TRUSTED_ISSUERS: ${env:OIDC_TRUSTED_ISSUERS, ""}
184
- OIDC_EXPECTED_AUDIENCE: ${env:OIDC_EXPECTED_AUDIENCE, ""}
185
- APP_STORE_ADMIN_PROFILE_IDS: ${env:APP_STORE_ADMIN_PROFILE_IDS, ""}
186
- APP_BRAND: ${env:APP_BRAND, 'scouts'}
187
- # LC-1644 perf bench (admin-only). Optional — if unset, the bench still runs
188
- # but emits no PostHog events. POSTHOG_HOST falls back to the helper's default
189
- # (https://us.i.posthog.com).
190
- POSTHOG_API_KEY: ${env:POSTHOG_API_KEY, ""}
191
- POSTHOG_HOST: ${env:POSTHOG_HOST, ""}
192
- GIT_SHA: ${env:GIT_SHA, ""}
193
- CREDENTIAL_REFRESH_ENABLED: ${env:CREDENTIAL_REFRESH_ENABLED, "false"}
194
- CREDENTIAL_REFRESH_DIGEST_SECRET: ${env:CREDENTIAL_REFRESH_DIGEST_SECRET, ""}
195
- CREDENTIAL_REFRESH_NOTIFICATION_WINDOW_HOURS: ${env:CREDENTIAL_REFRESH_NOTIFICATION_WINDOW_HOURS, "24"}
141
+ # Every function shares the default execution role. Grant it read access to the stage's
142
+ # runtime-secrets bundle only; the id itself is passed through RUNTIME_SECRETS_ID.
143
+ iam:
144
+ role:
145
+ statements:
146
+ - Effect: Allow
147
+ Action: secretsmanager:GetSecretValue
148
+ Resource:
149
+ Fn::Sub: arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:brain-service/${sls:stage}/runtime-secrets-*
150
+ # Bundle mode emits only infra (Redis/queue CF intrinsics, the bundle pointer and the
151
+ # deploy commit); fallback mode retains the existing GitHub credential secrets. Non-secret
152
+ # per-stage tuning, allowlists and OIDC/share-link config are applied from checked-in stage
153
+ # config at cold start, never forwarded here. LAMBDA_STAGE comes from the CLI stage option.
154
+ environment: ${file(./serverless.function-env.cjs):provider}
196
155
  tracing:
197
156
  apiGateway: true
198
157
  lambda: true
@@ -244,6 +203,36 @@ functions:
244
203
  rate: rate(1 day)
245
204
  enabled: true
246
205
 
206
+ # Retry durable consent notification intents once per minute.
207
+ contractEvents:
208
+ handler: contractEventsLambda.contractEventsHandler
209
+ timeout: 60
210
+ reservedConcurrency: 1
211
+ vpc:
212
+ securityGroupIds:
213
+ - 'Fn::GetAtt': [ServerlessSecurityGroup, GroupId]
214
+ subnetIds:
215
+ - Ref: PrivateSubnetA
216
+ events:
217
+ - schedule: rate(1 minute)
218
+
219
+ # LC-2187 share-link recovery + cleanup. Dedicated entrypoint (no lambda.ts
220
+ # import-time work). Runs automatically with valid service configuration;
221
+ # absent wiring remains inert and partial wiring fails closed. The cadence
222
+ # matches the default Docker maintenance interval (5 minutes).
223
+ shareLinkMaintenance:
224
+ handler: shareLinkMaintenanceLambda.shareLinkMaintenanceHandler
225
+ timeout: 300
226
+ vpc:
227
+ securityGroupIds:
228
+ - 'Fn::GetAtt': [ServerlessSecurityGroup, GroupId]
229
+ subnetIds:
230
+ - Ref: PrivateSubnetA
231
+ events:
232
+ - schedule:
233
+ rate: rate(5 minutes)
234
+ enabled: true
235
+
247
236
  trpc:
248
237
  handler: lambda.trpcHandler
249
238
  vpc:
@@ -0,0 +1,18 @@
1
+ import { bootstrapLambda } from '@learncard/service-config';
2
+
3
+ import { base, stages } from './src/config/stageConfig';
4
+
5
+ type ShareLinkMaintenanceApp = typeof import('./shareLinkMaintenanceLambdaApp');
6
+
7
+ const getApplication = bootstrapLambda<ShareLinkMaintenanceApp>({
8
+ base,
9
+ stages,
10
+ stage: process.env.AWS_LAMBDA_FUNCTION_NAME
11
+ ? process.env.LAMBDA_STAGE
12
+ : process.env.CONFIG_STAGE,
13
+ importApp: () => import('./shareLinkMaintenanceLambdaApp'),
14
+ });
15
+
16
+ export const shareLinkMaintenanceHandler = async (
17
+ ...args: Parameters<ShareLinkMaintenanceApp['shareLinkMaintenanceHandler']>
18
+ ) => (await getApplication()).shareLinkMaintenanceHandler(...args);
@@ -0,0 +1,50 @@
1
+ import type { Context } from 'aws-lambda';
2
+
3
+ import {
4
+ createShareLinkMaintenanceRuntime,
5
+ type ShareLinkMaintenanceRuntime,
6
+ } from './src/helpers/share-link-maintenance';
7
+
8
+ /**
9
+ * Dedicated LC-2187 share-link maintenance application module.
10
+ *
11
+ * It is imported lazily by the thin bootstrap entrypoint, after checked-in
12
+ * stage config has been applied, so no unrelated embedding backfill, tRPC
13
+ * router, Sentry input capture or inbox handler runs at import time. The only
14
+ * side effect is resolving the service and maintenance configuration; when it
15
+ * is absent or malformed the runtime is inert and the handler performs no
16
+ * graph, remote or signing work.
17
+ *
18
+ * The scheduled event payload is ignored entirely: it can never override the
19
+ * namespace, origin, audience or any other configuration, and it is never
20
+ * logged.
21
+ */
22
+
23
+ let runtime: ShareLinkMaintenanceRuntime | null = null;
24
+
25
+ const getRuntime = (): ShareLinkMaintenanceRuntime => {
26
+ if (runtime === null) {
27
+ runtime = createShareLinkMaintenanceRuntime({
28
+ rawEnvironment: process.env as Record<string, unknown>,
29
+ });
30
+ }
31
+
32
+ return runtime;
33
+ };
34
+
35
+ export const shareLinkMaintenanceHandler = async (
36
+ _event: unknown,
37
+ context?: Pick<Context, 'getRemainingTimeInMillis'>
38
+ ): Promise<{ status: string }> => {
39
+ const hasRemainingTime = typeof context?.getRemainingTimeInMillis === 'function';
40
+
41
+ const summary = await getRuntime().runOnce({
42
+ // Preserve the LIVE Lambda remaining-time source: the runtime samples it
43
+ // once, before dependency initialization, and anchors the invocation
44
+ // budget to that instant.
45
+ remainingTimeMs: hasRemainingTime ? () => context!.getRemainingTimeInMillis() : undefined,
46
+ });
47
+
48
+ // The runtime already emitted one aggregate-only allowlisted event.
49
+ return { status: summary.status };
50
+ };
@@ -0,0 +1,57 @@
1
+ import { BindParam, QueryBuilder } from 'neogma';
2
+ import { v4 as uuid } from 'uuid';
3
+
4
+ import { Integration, AppManifestVersion } from '@models';
5
+ import type { AppManifest } from '@learncard/types';
6
+
7
+ import type { AppManifestVersionType } from 'types/app-manifest';
8
+
9
+ import { readAppManifestVersionById } from './read';
10
+
11
+ export const createAppManifestVersion = async ({
12
+ integrationId,
13
+ version,
14
+ manifestHash,
15
+ manifest,
16
+ status = 'draft',
17
+ }: {
18
+ integrationId: string;
19
+ version: number;
20
+ manifestHash: string;
21
+ manifest: AppManifest;
22
+ status?: 'draft' | 'active' | 'superseded';
23
+ }): Promise<AppManifestVersionType> => {
24
+ const id = uuid();
25
+ const createdAt = new Date().toISOString();
26
+
27
+ await new QueryBuilder(
28
+ new BindParam({
29
+ integrationId,
30
+ params: {
31
+ id,
32
+ version,
33
+ manifestHash,
34
+ manifestJson: JSON.stringify(manifest),
35
+ status,
36
+ createdAt,
37
+ },
38
+ })
39
+ )
40
+ .match({ model: Integration, identifier: 'integration', where: { id: integrationId } })
41
+ .create({ model: AppManifestVersion, identifier: 'manifestVersion' })
42
+ .set('manifestVersion += $params')
43
+ .create(
44
+ `(integration)-[:${
45
+ Integration.getRelationshipByAlias('hasManifestVersion').name
46
+ }]->(manifestVersion)`
47
+ )
48
+ .run();
49
+
50
+ const created = await readAppManifestVersionById(id);
51
+
52
+ if (!created) {
53
+ throw new Error('Failed to create app manifest version');
54
+ }
55
+
56
+ return created;
57
+ };
@@ -0,0 +1,129 @@
1
+ import { neogma } from '@instance';
2
+
3
+ import { AppManifestVersionValidator } from '@learncard/types';
4
+
5
+ import type { AppManifestVersionType } from 'types/app-manifest';
6
+
7
+ const parseManifestVersionRecord = (
8
+ properties: Record<string, unknown>
9
+ ): AppManifestVersionType => {
10
+ const manifestJson = properties.manifestJson;
11
+ const rawVersion = properties.version as { toNumber?: () => number } | number;
12
+
13
+ if (typeof manifestJson !== 'string') {
14
+ throw new Error('AppManifestVersion.manifestJson is missing');
15
+ }
16
+
17
+ return AppManifestVersionValidator.parse({
18
+ id: properties.id,
19
+ version: typeof rawVersion === 'number' ? rawVersion : rawVersion?.toNumber?.(),
20
+ manifestHash: properties.manifestHash,
21
+ manifest: JSON.parse(manifestJson),
22
+ status: properties.status,
23
+ createdAt: properties.createdAt,
24
+ activatedAt: properties.activatedAt,
25
+ });
26
+ };
27
+
28
+ export const readAppManifestVersionById = async (
29
+ id: string
30
+ ): Promise<AppManifestVersionType | null> => {
31
+ const result = await neogma.queryRunner.run(
32
+ `MATCH (manifestVersion:AppManifestVersion {id: $id})
33
+ RETURN manifestVersion
34
+ LIMIT 1`,
35
+ { id }
36
+ );
37
+
38
+ const properties = result.records[0]?.get('manifestVersion')?.properties;
39
+
40
+ if (!properties) return null;
41
+
42
+ return parseManifestVersionRecord(properties as Record<string, unknown>);
43
+ };
44
+
45
+ export const getManifestVersionForIntegration = async (
46
+ integrationId: string,
47
+ version: number
48
+ ): Promise<AppManifestVersionType | null> => {
49
+ const result = await neogma.queryRunner.run(
50
+ `MATCH (:Integration {id: $integrationId})-[:HAS_MANIFEST_VERSION]->(manifestVersion:AppManifestVersion {version: $version})
51
+ RETURN manifestVersion
52
+ LIMIT 1`,
53
+ { integrationId, version }
54
+ );
55
+
56
+ const properties = result.records[0]?.get('manifestVersion')?.properties;
57
+
58
+ if (!properties) return null;
59
+
60
+ return parseManifestVersionRecord(properties as Record<string, unknown>);
61
+ };
62
+
63
+ export const getLatestManifestVersionForIntegration = async (
64
+ integrationId: string
65
+ ): Promise<AppManifestVersionType | null> => {
66
+ const result = await neogma.queryRunner.run(
67
+ `MATCH (:Integration {id: $integrationId})-[:HAS_MANIFEST_VERSION]->(manifestVersion:AppManifestVersion)
68
+ RETURN manifestVersion
69
+ ORDER BY manifestVersion.version DESC
70
+ LIMIT 1`,
71
+ { integrationId }
72
+ );
73
+
74
+ const properties = result.records[0]?.get('manifestVersion')?.properties;
75
+
76
+ if (!properties) return null;
77
+
78
+ return parseManifestVersionRecord(properties as Record<string, unknown>);
79
+ };
80
+
81
+ export const getActiveManifestVersionForIntegration = async (
82
+ integrationId: string
83
+ ): Promise<AppManifestVersionType | null> => {
84
+ const result = await neogma.queryRunner.run(
85
+ `MATCH (:Integration {id: $integrationId})-[:HAS_MANIFEST_VERSION]->(manifestVersion:AppManifestVersion {status: 'active'})
86
+ RETURN manifestVersion
87
+ ORDER BY manifestVersion.activatedAt DESC, manifestVersion.version DESC
88
+ LIMIT 1`,
89
+ { integrationId }
90
+ );
91
+
92
+ const properties = result.records[0]?.get('manifestVersion')?.properties;
93
+
94
+ if (!properties) return null;
95
+
96
+ return parseManifestVersionRecord(properties as Record<string, unknown>);
97
+ };
98
+
99
+ export const getManifestVersionsForIntegration = async (
100
+ integrationId: string,
101
+ { limit, cursor }: { limit: number; cursor?: string }
102
+ ): Promise<AppManifestVersionType[]> => {
103
+ const result = await neogma.queryRunner.run(
104
+ `MATCH (:Integration {id: $integrationId})-[:HAS_MANIFEST_VERSION]->(manifestVersion:AppManifestVersion)
105
+ ${cursor ? 'WHERE manifestVersion.version < toInteger($cursor)' : ''}
106
+ RETURN manifestVersion
107
+ ORDER BY manifestVersion.version DESC
108
+ LIMIT toInteger($limit)`,
109
+ { integrationId, cursor: cursor ?? null, limit }
110
+ );
111
+
112
+ return result.records.map(record => {
113
+ const properties = record.get('manifestVersion')?.properties as Record<string, unknown>;
114
+ return parseManifestVersionRecord(properties);
115
+ });
116
+ };
117
+
118
+ export const getListingIdForManifestVersion = async (id: string): Promise<string | null> => {
119
+ const result = await neogma.queryRunner.run(
120
+ `MATCH (listing:AppStoreListing)-[:USES_MANIFEST_VERSION]->(:AppManifestVersion {id: $id})
121
+ RETURN listing.listing_id AS listingId
122
+ LIMIT 1`,
123
+ { id }
124
+ );
125
+
126
+ const listingId = result.records[0]?.get('listingId');
127
+
128
+ return typeof listingId === 'string' ? listingId : null;
129
+ };
@@ -0,0 +1,61 @@
1
+ import { neogma } from '@instance';
2
+
3
+ export const updateAppManifestVersion = async (
4
+ id: string,
5
+ updates: Partial<{
6
+ status: 'draft' | 'active' | 'superseded';
7
+ activatedAt: string | null;
8
+ }>
9
+ ): Promise<boolean> => {
10
+ const setClauses: string[] = [];
11
+ const params: Record<string, unknown> = { id };
12
+
13
+ if (typeof updates.status !== 'undefined') {
14
+ params.status = updates.status;
15
+ setClauses.push('manifestVersion.status = $status');
16
+ }
17
+ if (typeof updates.activatedAt !== 'undefined') {
18
+ params.activatedAt = updates.activatedAt;
19
+ setClauses.push('manifestVersion.activatedAt = $activatedAt');
20
+ }
21
+
22
+ if (setClauses.length === 0) return true;
23
+
24
+ const result = await neogma.queryRunner.run(
25
+ `MATCH (manifestVersion:AppManifestVersion {id: $id})
26
+ SET ${setClauses.join(', ')}`,
27
+ params
28
+ );
29
+
30
+ return result.summary.updateStatistics.containsUpdates();
31
+ };
32
+
33
+ export const markManifestVersionsSuperseded = async (
34
+ integrationId: string,
35
+ exceptId: string
36
+ ): Promise<boolean> => {
37
+ const result = await neogma.queryRunner.run(
38
+ `MATCH (:Integration {id: $integrationId})-[:HAS_MANIFEST_VERSION]->(manifestVersion:AppManifestVersion)
39
+ WHERE manifestVersion.id <> $exceptId AND manifestVersion.status = 'active'
40
+ SET manifestVersion.status = 'superseded'`,
41
+ { integrationId, exceptId }
42
+ );
43
+
44
+ return result.summary.updateStatistics.containsUpdates();
45
+ };
46
+
47
+ export const associateListingWithManifestVersion = async (
48
+ listingId: string,
49
+ manifestVersionId: string
50
+ ): Promise<boolean> => {
51
+ await neogma.queryRunner.run(
52
+ `MATCH (listing:AppStoreListing {listing_id: $listingId})
53
+ MATCH (manifestVersion:AppManifestVersion {id: $manifestVersionId})
54
+ OPTIONAL MATCH (listing)-[existing:USES_MANIFEST_VERSION]->(:AppManifestVersion)
55
+ DELETE existing
56
+ MERGE (listing)-[:USES_MANIFEST_VERSION]->(manifestVersion)`,
57
+ { listingId, manifestVersionId }
58
+ );
59
+
60
+ return true;
61
+ };
@@ -244,16 +244,22 @@ export const getListedAppsWithSubmitter = async ({
244
244
  status,
245
245
  includeAllStatuses = false,
246
246
  excludeDemoted = true,
247
+ pendingUpdatesOnly = false,
247
248
  }: {
248
249
  limit: number;
249
250
  cursor?: string;
250
251
  status?: string;
251
252
  includeAllStatuses?: boolean;
252
253
  excludeDemoted?: boolean;
254
+ pendingUpdatesOnly?: boolean;
253
255
  }): Promise<ListingWithSubmitter[]> => {
254
256
  const whereClauses: string[] = [];
255
257
  const params: Record<string, any> = { limit: int(limit) };
256
258
 
259
+ if (pendingUpdatesOnly) {
260
+ whereClauses.push("listing.pending_update_status = 'PENDING_REVIEW'");
261
+ }
262
+
257
263
  if (status) {
258
264
  whereClauses.push('listing.app_listing_status = $status');
259
265
  params.status = status;
@@ -96,6 +96,26 @@ export const associateBoostWithListing = async (
96
96
  return true;
97
97
  };
98
98
 
99
+ export const associateConsentContractWithListing = async (
100
+ listingId: string,
101
+ contractId: string,
102
+ scopeHash: string
103
+ ): Promise<boolean> => {
104
+ await AppStoreListing.relateTo({
105
+ alias: 'hasConsentContract',
106
+ where: {
107
+ source: { listing_id: listingId },
108
+ target: { id: contractId },
109
+ },
110
+ properties: {
111
+ scopeHash,
112
+ createdAt: new Date().toISOString(),
113
+ },
114
+ });
115
+
116
+ return true;
117
+ };
118
+
99
119
  export const associateListingWithSigningAuthority = async (
100
120
  listingId: string,
101
121
  signingAuthorityEndpoint: string,
@@ -6,6 +6,8 @@ import { Boost, BoostInstance } from '@models';
6
6
  import { int } from 'neo4j-driver';
7
7
  import { getBoostUri } from '@helpers/boost.helpers';
8
8
  import { parseIntegration } from '@helpers/integrations.helpers';
9
+ import { getContractById } from '@accesslayer/consentflowcontract/read';
10
+ import type { DbContractType } from 'types/consentflowcontract';
9
11
 
10
12
  export const getIntegrationForListing = async (
11
13
  listingIdOrSlug: string
@@ -93,7 +95,9 @@ export const getBoostForListingByTemplateAlias = async (
93
95
  ): Promise<{ boost: BoostInstance; templateAlias: string; boostUri: string } | null> => {
94
96
  const result = await neogma.queryRunner.run(
95
97
  `MATCH (listing:AppStoreListing {listing_id: $listingId})-[r:HAS_BOOST {templateAlias: $templateAlias}]->(b:Boost)
96
- RETURN b.id AS id, r.templateAlias AS templateAlias`,
98
+ RETURN b.id AS id, r.templateAlias AS templateAlias
99
+ ORDER BY r.createdAt DESC
100
+ LIMIT 1`,
97
101
  { listingId, templateAlias }
98
102
  );
99
103
 
@@ -146,6 +150,25 @@ export const hasTemplateAliasForListing = async (
146
150
  return result.records[0]?.get('exists') ?? false;
147
151
  };
148
152
 
153
+ export const getConsentContractForListingByScopeHash = async (
154
+ listingId: string,
155
+ scopeHash: string
156
+ ): Promise<DbContractType | null> => {
157
+ const result = await neogma.queryRunner.run(
158
+ `MATCH (listing:AppStoreListing {listing_id: $listingId})
159
+ -[:HAS_CONSENT_CONTRACT {scopeHash: $scopeHash}]->(contract:ConsentFlowContract)
160
+ RETURN contract.id AS id
161
+ ORDER BY contract.createdAt ASC
162
+ LIMIT 1`,
163
+ { listingId, scopeHash }
164
+ );
165
+
166
+ const id = result.records[0]?.get('id');
167
+ if (typeof id !== 'string') return null;
168
+
169
+ return getContractById(id);
170
+ };
171
+
149
172
  export const getCredentialsSentByListingToProfile = async (
150
173
  listingId: string,
151
174
  profileId: string,
@@ -1,6 +1,7 @@
1
1
  import { QueryBuilder, BindParam } from 'neogma';
2
2
 
3
3
  import { AppStoreListing } from '@models';
4
+ import { neogma } from '@instance';
4
5
  import {
5
6
  FlatAppStoreListingType,
6
7
  AppStoreListingType,
@@ -50,6 +51,12 @@ export const updateAppStoreListing = async (
50
51
  updatesToPersist.submitted_at = updates.submitted_at;
51
52
  if (typeof updates.contact_email !== 'undefined')
52
53
  updatesToPersist.contact_email = updates.contact_email;
54
+ if (typeof updates.pending_update_json !== 'undefined')
55
+ updatesToPersist.pending_update_json = updates.pending_update_json;
56
+ if (typeof updates.pending_update_status !== 'undefined')
57
+ updatesToPersist.pending_update_status = updates.pending_update_status;
58
+ if (typeof updates.pending_update_submitted_at !== 'undefined')
59
+ updatesToPersist.pending_update_submitted_at = updates.pending_update_submitted_at;
53
60
 
54
61
  const params: Partial<FlatAppStoreListingType> = updatesToPersist;
55
62
 
@@ -67,3 +74,11 @@ export const updateAppStoreListing = async (
67
74
 
68
75
  return result.summary.updateStatistics.containsUpdates();
69
76
  };
77
+
78
+ export const clearPendingListingUpdate = async (listingId: string): Promise<void> => {
79
+ await neogma.queryRunner.run(
80
+ `MATCH (listing:AppStoreListing {listing_id: $listingId})
81
+ REMOVE listing.pending_update_json, listing.pending_update_status, listing.pending_update_submitted_at`,
82
+ { listingId }
83
+ );
84
+ };
@@ -1,4 +1,5 @@
1
1
  import { getAdminRole, getEmptyRole } from '@accesslayer/role/read';
2
+ import type { Transaction } from 'neo4j-driver';
2
3
  import { CredentialInstance, BoostInstance, AppStoreListingInstance } from '@models';
3
4
  import { neogma } from '@instance';
4
5
  import { ProfileType } from 'types/profile';
@@ -6,9 +7,14 @@ import { clearDidWebCacheForChildProfileManagers } from './update';
6
7
 
7
8
  export const createBoostInstanceOfRelationship = async (
8
9
  credential: CredentialInstance,
9
- boost: BoostInstance
10
+ boost: BoostInstance,
11
+ transaction?: Transaction
10
12
  ): Promise<void> => {
11
- await credential.relateTo({ alias: 'instanceOf', where: { id: boost.id } });
13
+ await credential.relateTo({
14
+ alias: 'instanceOf',
15
+ where: { id: boost.id },
16
+ session: transaction,
17
+ });
12
18
  };
13
19
 
14
20
  export const createReceivedCredentialRelationship = async (