@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
@@ -1,19 +1,12 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest';
2
- import type { JWE, VC } from '@learncard/types';
2
+ import type { JWE } from '@learncard/types';
3
3
  import type { IssuedCredential } from '../../types/credential';
4
4
 
5
- const mocks = vi.hoisted(() => ({ createOne: vi.fn(async input => input) }));
5
+ const mocks = vi.hoisted(() => ({ createOne: vi.fn() }));
6
6
  vi.mock('@models', () => ({ Credential: { createOne: mocks.createOne } }));
7
7
 
8
8
  import { storeCredential } from './create';
9
9
 
10
- const statusEntry = {
11
- id: 'https://network.example/status/1#42',
12
- type: 'BitstringStatusListEntry' as const,
13
- statusPurpose: 'revocation' as const,
14
- statusListIndex: '42',
15
- statusListCredential: 'https://network.example/status/1',
16
- };
17
10
  const createJwe = (): JWE => ({
18
11
  protected: 'header',
19
12
  iv: 'iv',
@@ -21,121 +14,15 @@ const createJwe = (): JWE => ({
21
14
  tag: 'tag',
22
15
  recipients: [],
23
16
  });
24
- const createVc = (): VC => ({
25
- '@context': ['https://www.w3.org/2018/credentials/v1'],
26
- type: ['VerifiableCredential'],
27
- issuer: 'did:example:issuer',
28
- issuanceDate: '2026-01-01T00:00:00Z',
29
- credentialSubject: { id: 'did:example:subject' },
30
- proof: {
31
- type: 'Ed25519Signature2020',
32
- created: '2026-01-01T00:00:00Z',
33
- proofPurpose: 'assertionMethod',
34
- verificationMethod: 'did:example:issuer#key-1',
35
- proofValue: 'existing-signature',
36
- },
37
- });
38
17
 
39
18
  describe('credential status storage', () => {
40
19
  beforeEach(() => {
41
- vi.restoreAllMocks();
42
20
  vi.clearAllMocks();
43
21
  });
44
22
 
45
- it('persists public status coordinates after serializing an issuance result', async () => {
46
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
47
- const jwe = createJwe();
48
- const issued: IssuedCredential = {
49
- kind: 'issued-credential',
50
- credential: jwe,
51
- statusEntries: [statusEntry],
52
- };
53
- await storeCredential(JSON.parse(JSON.stringify(issued)));
54
- expect(mocks.createOne).toHaveBeenCalledWith(
55
- expect.objectContaining({
56
- credential: JSON.stringify(jwe),
57
- statusEntries: JSON.stringify([statusEntry]),
58
- })
59
- );
60
- expect(warn).not.toHaveBeenCalled();
61
- });
62
-
63
- it('warns when a client-encrypted JWE has no metadata, without logging its payload', async () => {
64
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
65
- const original = createJwe();
66
- const jwe = { ...original };
67
- await storeCredential(jwe);
68
- expect(warn).toHaveBeenCalledExactlyOnceWith(
69
- expect.stringContaining('Encrypted credential has no status metadata'),
70
- { credentialId: expect.any(String) }
71
- );
72
- expect(mocks.createOne.mock.calls[0]![0].statusEntries).toBeUndefined();
73
- expect(mocks.createOne.mock.calls[0]![0].credential).toBe(JSON.stringify(jwe));
74
- });
75
-
76
23
  it('rejects internal issuance results that lost their status metadata before writing', async () => {
77
24
  const issued = { kind: 'issued-credential', credential: createJwe() } as IssuedCredential;
78
25
  await expect(storeCredential(issued)).rejects.toThrow();
79
26
  expect(mocks.createOne).not.toHaveBeenCalled();
80
27
  });
81
-
82
- it.each([undefined, []])(
83
- 'warns for a pre-signed plaintext VC with missing or empty status (%j) and preserves its signature',
84
- async credentialStatus => {
85
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
86
- const credential = { ...createVc(), credentialStatus };
87
- const stored = await storeCredential(credential);
88
- expect(warn).toHaveBeenCalledExactlyOnceWith(
89
- expect.stringContaining('Plaintext credential has no status metadata'),
90
- { credentialId: stored.id }
91
- );
92
- expect(stored.credential).toBe(JSON.stringify(credential));
93
- expect(stored.statusEntries).toBeUndefined();
94
- }
95
- );
96
-
97
- it.each([statusEntry, [statusEntry]])(
98
- 'does not warn for a plaintext VC with embedded status entries (%j)',
99
- async credentialStatus => {
100
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
101
- const credential = { ...createVc(), credentialStatus };
102
- const stored = await storeCredential(credential);
103
- expect(warn).not.toHaveBeenCalled();
104
- expect(stored.credential).toBe(JSON.stringify(credential));
105
- }
106
- );
107
-
108
- it.each([
109
- ['Encrypted', createJwe()],
110
- ['Plaintext', createVc()],
111
- ] as const)(
112
- 'warns for %s VC v1 issuance with empty status metadata',
113
- async (kind, credential) => {
114
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
115
- const stored = await storeCredential({
116
- kind: 'issued-credential',
117
- credential,
118
- statusEntries: [],
119
- });
120
- expect(warn).toHaveBeenCalledExactlyOnceWith(
121
- expect.stringContaining(`${kind} credential has no status metadata`),
122
- { credentialId: stored.id }
123
- );
124
- expect(stored.credential).toBe(JSON.stringify(credential));
125
- expect(stored.statusEntries).toBeUndefined();
126
- }
127
- );
128
-
129
- it('does not treat a wire JWE with extra envelope-like fields as trusted issuance metadata', async () => {
130
- vi.spyOn(console, 'warn').mockImplementation(() => {});
131
- const jwe = {
132
- ...createJwe(),
133
- kind: 'issued-credential',
134
- credential: createJwe(),
135
- statusEntries: [statusEntry],
136
- };
137
- await storeCredential(jwe);
138
- expect(mocks.createOne.mock.calls[0]![0].statusEntries).toBeUndefined();
139
- expect(mocks.createOne.mock.calls[0]![0].credential).toBe(JSON.stringify(jwe));
140
- });
141
28
  });
@@ -1,4 +1,5 @@
1
1
  import { BitstringStatusListEntryValidator, UnsignedVC, VC, JWE } from '@learncard/types';
2
+ import type { Transaction } from 'neo4j-driver';
2
3
  import { v4 as uuid } from 'uuid';
3
4
  import { getBitstringStatusListEntries, isEncrypted } from '@learncard/helpers';
4
5
  import { isIssuedCredential } from '@helpers/issuedCredentialStatus.helpers';
@@ -7,7 +8,8 @@ import type { IssuedCredential } from 'types/credential';
7
8
  import { Credential, CredentialInstance } from '@models';
8
9
 
9
10
  export const storeCredential = async (
10
- input: UnsignedVC | VC | JWE | IssuedCredential
11
+ input: UnsignedVC | VC | JWE | IssuedCredential,
12
+ transaction?: Transaction
11
13
  ): Promise<CredentialInstance> => {
12
14
  const id = uuid();
13
15
 
@@ -28,9 +30,12 @@ export const storeCredential = async (
28
30
  { credentialId: id }
29
31
  );
30
32
  }
31
- return Credential.createOne({
32
- id,
33
- credential: JSON.stringify(credential),
34
- ...(statusEntries?.length ? { statusEntries: JSON.stringify(statusEntries) } : {}),
35
- });
33
+ return Credential.createOne(
34
+ {
35
+ id,
36
+ credential: JSON.stringify(credential),
37
+ ...(statusEntries?.length ? { statusEntries: JSON.stringify(statusEntries) } : {}),
38
+ },
39
+ transaction ? { session: transaction } : undefined
40
+ );
36
41
  };
@@ -1,4 +1,6 @@
1
+ import { termsReferralSnapshotCypher } from '@helpers/consent-referral.helpers';
1
2
  import { QueryBuilder, BindParam } from 'neogma';
3
+ import type { Transaction } from 'neo4j-driver';
2
4
  import { v4 as uuid } from 'uuid';
3
5
 
4
6
  import {
@@ -24,7 +26,8 @@ export const createSentCredentialRelationship = async (
24
26
  credential: CredentialInstance,
25
27
  metadata?: Record<string, unknown>,
26
28
  activityId?: string,
27
- integrationId?: string
29
+ integrationId?: string,
30
+ transaction?: Transaction
28
31
  ): Promise<void> => {
29
32
  const properties = flattenObject({
30
33
  to: to.profileId,
@@ -57,12 +60,10 @@ export const createSentCredentialRelationship = async (
57
60
  ],
58
61
  })
59
62
  .create(
60
- `(profile)-[r:${
61
- Profile.getRelationshipByAlias('credentialSent').name
62
- }]->(credential)`
63
+ `(profile)-[r:${Profile.getRelationshipByAlias('credentialSent').name}]->(credential)`
63
64
  )
64
65
  .set('r = $params')
65
- .run();
66
+ .run(transaction);
66
67
 
67
68
  // If the issuer is an AppStoreListing, additionally write the
68
69
  // AppStoreListing -> CREDENTIAL_SENT -> Credential edge so that
@@ -91,7 +92,7 @@ export const createSentCredentialRelationship = async (
91
92
  }]->(credential)`
92
93
  )
93
94
  .set('r = $params')
94
- .run();
95
+ .run(transaction);
95
96
  }
96
97
  };
97
98
 
@@ -139,7 +140,8 @@ export const createReceivedCredentialRelationship = async (
139
140
  to: ProfileType,
140
141
  from: ProfileType | { listing_id: string },
141
142
  credential: CredentialInstance,
142
- metadata?: Record<string, unknown>
143
+ metadata?: Record<string, unknown>,
144
+ transaction?: Transaction
143
145
  ): Promise<void> => {
144
146
  const fromId = 'profileId' in from ? from.profileId : from.listing_id;
145
147
  const properties = flattenObject({
@@ -165,12 +167,13 @@ export const createReceivedCredentialRelationship = async (
165
167
  }]->(profile)`
166
168
  )
167
169
  .set('r = $params')
168
- .run();
170
+ .run(transaction);
169
171
  };
170
172
 
171
173
  export const setDefaultClaimedRole = async (
172
174
  profile: ProfileType,
173
- credential: CredentialInstance
175
+ credential: CredentialInstance,
176
+ transaction?: Transaction
174
177
  ): Promise<void> => {
175
178
  await new QueryBuilder()
176
179
  .match({
@@ -200,7 +203,10 @@ export const setDefaultClaimedRole = async (
200
203
  { identifier: 'boost' },
201
204
  ],
202
205
  })
203
- .run();
206
+ .run(transaction);
207
+
208
+ // An enclosing transaction invalidates caches only after its writes commit.
209
+ if (transaction) return;
204
210
 
205
211
  try {
206
212
  const boostId = await getBoostIdForCredentialInstance(credential);
@@ -239,6 +245,7 @@ export const createCredentialIssuedViaContractRelationship = async (
239
245
  { identifier: 'terms' },
240
246
  ],
241
247
  })
248
+ .raw(termsReferralSnapshotCypher())
242
249
  .with('transaction')
243
250
  .match({
244
251
  model: Credential,
@@ -1,4 +1,5 @@
1
1
  import { QueryBuilder, BindParam } from 'neogma';
2
+ import type { Transaction } from 'neo4j-driver';
2
3
  import { Profile, InboxCredential } from '@models';
3
4
 
4
5
  export const createDeliveredRelationship = async (
@@ -8,19 +9,23 @@ export const createDeliveredRelationship = async (
8
9
  deliveryMethod: string = 'direct'
9
10
  ): Promise<boolean> => {
10
11
  const timestamp = new Date().toISOString();
11
-
12
- const result = await new QueryBuilder(new BindParam({
13
- profileId,
14
- inboxCredentialId,
15
- timestamp,
16
- recipientDid,
17
- deliveryMethod
18
- }))
12
+
13
+ const result = await new QueryBuilder(
14
+ new BindParam({
15
+ profileId,
16
+ inboxCredentialId,
17
+ timestamp,
18
+ recipientDid,
19
+ deliveryMethod,
20
+ })
21
+ )
19
22
  .match({ model: Profile, identifier: 'profile' })
20
23
  .where('profile.profileId = $profileId')
21
24
  .match({ model: InboxCredential, identifier: 'inboxCredential' })
22
25
  .where('inboxCredential.id = $inboxCredentialId')
23
- .create('(profile)-[:DELIVERED_INBOX_CREDENTIAL { timestamp: $timestamp, recipientDid: $recipientDid, deliveryMethod: $deliveryMethod }]->(inboxCredential)')
26
+ .create(
27
+ '(profile)-[:DELIVERED_INBOX_CREDENTIAL { timestamp: $timestamp, recipientDid: $recipientDid, deliveryMethod: $deliveryMethod }]->(inboxCredential)'
28
+ )
24
29
  .return('profile')
25
30
  .run();
26
31
 
@@ -30,23 +35,28 @@ export const createDeliveredRelationship = async (
30
35
  export const createClaimedRelationship = async (
31
36
  profileId: string,
32
37
  inboxCredentialId: string,
33
- claimToken: string
38
+ claimToken: string,
39
+ transaction?: Transaction
34
40
  ): Promise<boolean> => {
35
41
  const timestamp = new Date().toISOString();
36
-
37
- const result = await new QueryBuilder(new BindParam({
38
- profileId,
39
- inboxCredentialId,
40
- timestamp,
41
- claimToken
42
- }))
43
- .match({ model: Profile, identifier: 'profile'})
42
+
43
+ const result = await new QueryBuilder(
44
+ new BindParam({
45
+ profileId,
46
+ inboxCredentialId,
47
+ timestamp,
48
+ claimToken,
49
+ })
50
+ )
51
+ .match({ model: Profile, identifier: 'profile' })
44
52
  .where('profile.profileId = $profileId')
45
- .match({ model: InboxCredential, identifier: 'inboxCredential'})
53
+ .match({ model: InboxCredential, identifier: 'inboxCredential' })
46
54
  .where('inboxCredential.id = $inboxCredentialId')
47
- .create('(profile)-[:CLAIMED_INBOX_CREDENTIAL { timestamp: $timestamp, claimToken: $claimToken }]->(inboxCredential)')
55
+ .create(
56
+ '(profile)-[:CLAIMED_INBOX_CREDENTIAL { timestamp: $timestamp, claimToken: $claimToken }]->(inboxCredential)'
57
+ )
48
58
  .return('profile')
49
- .run();
59
+ .run(transaction);
50
60
 
51
61
  return result.records.length > 0;
52
62
  };
@@ -58,19 +68,23 @@ export const createEmailSentRelationship = async (
58
68
  token: string
59
69
  ): Promise<boolean> => {
60
70
  const timestamp = new Date().toISOString();
61
-
62
- const result = await new QueryBuilder(new BindParam({
63
- profileDid,
64
- inboxCredentialId,
65
- timestamp,
66
- emailAddress,
67
- token
68
- }))
71
+
72
+ const result = await new QueryBuilder(
73
+ new BindParam({
74
+ profileDid,
75
+ inboxCredentialId,
76
+ timestamp,
77
+ emailAddress,
78
+ token,
79
+ })
80
+ )
69
81
  .match({ model: Profile, identifier: 'profile' })
70
82
  .where('profile.did = $profileDid')
71
83
  .match({ model: InboxCredential, identifier: 'inboxCredential' })
72
84
  .where('inboxCredential.id = $inboxCredentialId')
73
- .create('(profile)-[:SENT_EMAIL { timestamp: $timestamp, emailAddress: $emailAddress, token: $token }]->(inboxCredential)')
85
+ .create(
86
+ '(profile)-[:SENT_EMAIL { timestamp: $timestamp, emailAddress: $emailAddress, token: $token }]->(inboxCredential)'
87
+ )
74
88
  .return('profile')
75
89
  .run();
76
90
 
@@ -85,20 +99,24 @@ export const createWebhookSentRelationship = async (
85
99
  response?: string
86
100
  ): Promise<boolean> => {
87
101
  const timestamp = new Date().toISOString();
88
-
89
- const result = await new QueryBuilder(new BindParam({
90
- profileDid,
91
- inboxCredentialId,
92
- timestamp,
93
- url,
94
- status,
95
- response: response || null
96
- }))
102
+
103
+ const result = await new QueryBuilder(
104
+ new BindParam({
105
+ profileDid,
106
+ inboxCredentialId,
107
+ timestamp,
108
+ url,
109
+ status,
110
+ response: response || null,
111
+ })
112
+ )
97
113
  .match({ model: Profile, identifier: 'profile' })
98
114
  .where('profile.did = $profileDid')
99
115
  .match({ model: InboxCredential, identifier: 'inboxCredential' })
100
116
  .where('inboxCredential.id = $inboxCredentialId')
101
- .create('(profile)-[:SENT_WEBHOOK { timestamp: $timestamp, url: $url, status: $status, response: $response }]->(inboxCredential)')
117
+ .create(
118
+ '(profile)-[:SENT_WEBHOOK { timestamp: $timestamp, url: $url, status: $status, response: $response }]->(inboxCredential)'
119
+ )
102
120
  .return('profile')
103
121
  .run();
104
122
 
@@ -110,19 +128,23 @@ export const createExpiredRelationship = async (
110
128
  inboxCredentialId: string
111
129
  ): Promise<boolean> => {
112
130
  const timestamp = new Date().toISOString();
113
-
114
- const result = await new QueryBuilder(new BindParam({
115
- profileDid,
116
- inboxCredentialId,
117
- timestamp
118
- }))
131
+
132
+ const result = await new QueryBuilder(
133
+ new BindParam({
134
+ profileDid,
135
+ inboxCredentialId,
136
+ timestamp,
137
+ })
138
+ )
119
139
  .match({ model: Profile, identifier: 'profile' })
120
140
  .where('profile.did = $profileDid')
121
141
  .match({ model: InboxCredential, identifier: 'inboxCredential' })
122
142
  .where('inboxCredential.id = $inboxCredentialId')
123
- .create('(profile)-[:EXPIRED_INBOX_CREDENTIAL { timestamp: $timestamp }]->(inboxCredential)')
143
+ .create(
144
+ '(profile)-[:EXPIRED_INBOX_CREDENTIAL { timestamp: $timestamp }]->(inboxCredential)'
145
+ )
124
146
  .return('profile')
125
147
  .run();
126
148
 
127
149
  return result.records.length > 0;
128
- };
150
+ };
@@ -1,4 +1,5 @@
1
1
  import { QueryBuilder, BindParam } from 'neogma';
2
+ import type { Transaction } from 'neo4j-driver';
2
3
  import { InboxCredential } from '@models';
3
4
  import { InboxCredentialType } from '@learncard/types';
4
5
  import { flattenObject, inflateObject } from '@helpers/objects.helpers';
@@ -31,7 +32,8 @@ export const updateInboxCredential = async (
31
32
  export const finalizeAndWipeInboxCredential = async (
32
33
  id: string,
33
34
  delivery: InboxDelivery,
34
- { isAccepted = true }: { isAccepted?: boolean } = {}
35
+ { isAccepted = true }: { isAccepted?: boolean } = {},
36
+ transaction?: Transaction
35
37
  ): Promise<InboxCredentialType | null> => {
36
38
  const result = await new QueryBuilder(
37
39
  new BindParam({
@@ -64,7 +66,7 @@ export const finalizeAndWipeInboxCredential = async (
64
66
  )
65
67
  .return('inboxCredential')
66
68
  .limit(1)
67
- .run();
69
+ .run(transaction);
68
70
 
69
71
  const inboxCredential = result.records[0]?.get('inboxCredential')?.properties;
70
72
  return inboxCredential
@@ -14,6 +14,12 @@ import { PresentationType } from 'types/presentation';
14
14
  import { ProfileType } from 'types/profile';
15
15
  import { convertQueryResultToPropertiesObjectArray } from '@helpers/neo4j.helpers';
16
16
  import { getIdFromUri } from '@helpers/uri.helpers';
17
+ import { inflateObject } from '@helpers/objects.helpers';
18
+
19
+ const inflateRelationshipProperties = (
20
+ properties: Record<string, unknown>
21
+ ): Record<string, unknown> & { metadata?: Record<string, unknown> } =>
22
+ inflateObject(properties) as Record<string, unknown> & { metadata?: Record<string, unknown> };
17
23
 
18
24
  export const getPresentationById = async (id: string): Promise<PresentationInstance | null> => {
19
25
  return Presentation.findOne({ where: { id } });
@@ -56,8 +62,8 @@ export const getReceivedPresentationsForProfile = async (
56
62
  const query =
57
63
  from && from.length > 0
58
64
  ? matchQuery.where(
59
- new Where({ source: { profileId: { [Op.in]: from } } }, matchQuery.getBindParam())
60
- )
65
+ new Where({ source: { profileId: { [Op.in]: from } } }, matchQuery.getBindParam())
66
+ )
61
67
  : matchQuery;
62
68
 
63
69
  const results = convertQueryResultToPropertiesObjectArray<{
@@ -66,13 +72,22 @@ export const getReceivedPresentationsForProfile = async (
66
72
  received: PresentationRelationships['presentationReceived']['RelationshipProperties'];
67
73
  }>(await query.return('sent, presentation, received').limit(limit).run());
68
74
 
69
- return results.map(({ sent, presentation, received }) => ({
70
- uri: getPresentationUri(presentation.id, domain),
71
- to: sent.to,
72
- from: received.from,
73
- sent: sent.date,
74
- received: received.date,
75
- }));
75
+ return results.map(({ sent, presentation, received }) => {
76
+ const sentProps = inflateRelationshipProperties(sent as unknown as Record<string, unknown>);
77
+ const receivedProps = inflateRelationshipProperties(
78
+ received as unknown as Record<string, unknown>
79
+ );
80
+
81
+ return {
82
+ uri: getPresentationUri(presentation.id, domain),
83
+ to: sentProps.to as string,
84
+ from: receivedProps.from as string,
85
+ sent: sentProps.date as string,
86
+ received: receivedProps.date as string,
87
+ metadata: (receivedProps.metadata ?? sentProps.metadata) as
88
+ Record<string, unknown> | undefined,
89
+ };
90
+ });
76
91
  };
77
92
 
78
93
  export const getSentPresentationsForProfile = async (
@@ -101,8 +116,8 @@ export const getSentPresentationsForProfile = async (
101
116
  const whereQuery =
102
117
  to && to.length > 0
103
118
  ? matchQuery.where(
104
- new Where({ sent: { to: { [Op.in]: to } } }, matchQuery.getBindParam())
105
- )
119
+ new Where({ sent: { to: { [Op.in]: to } } }, matchQuery.getBindParam())
120
+ )
106
121
  : matchQuery;
107
122
 
108
123
  const query = whereQuery.match({
@@ -124,13 +139,22 @@ export const getSentPresentationsForProfile = async (
124
139
  received?: PresentationRelationships['presentationReceived']['RelationshipProperties'];
125
140
  }>(await query.return('source, sent, presentation, received').limit(limit).run());
126
141
 
127
- return results.map(({ source, sent, presentation, received }) => ({
128
- uri: getPresentationUri(presentation.id, domain),
129
- to: sent.to,
130
- from: source.profileId,
131
- sent: sent.date,
132
- received: received?.date,
133
- }));
142
+ return results.map(({ source, sent, presentation, received }) => {
143
+ const sentProps = inflateRelationshipProperties(sent as unknown as Record<string, unknown>);
144
+ const receivedProps = received
145
+ ? inflateRelationshipProperties(received as unknown as Record<string, unknown>)
146
+ : undefined;
147
+
148
+ return {
149
+ uri: getPresentationUri(presentation.id, domain),
150
+ to: sentProps.to as string,
151
+ from: source.profileId,
152
+ sent: sentProps.date as string,
153
+ received: receivedProps?.date as string | undefined,
154
+ metadata: (sentProps.metadata ?? receivedProps?.metadata) as
155
+ Record<string, unknown> | undefined,
156
+ };
157
+ });
134
158
  };
135
159
 
136
160
  export const getIncomingPresentationsForProfile = async (
@@ -168,7 +192,8 @@ export const getIncomingPresentationsForProfile = async (
168
192
  })
169
193
  // Don't return presentations that have been accepted
170
194
  .where(
171
- `NOT (presentation)-[:PRESENTATION_RECEIVED]->()${whereFrom ? `AND ${whereFrom.getStatement('text')}` : ''
195
+ `NOT (presentation)-[:PRESENTATION_RECEIVED]->()${
196
+ whereFrom ? `AND ${whereFrom.getStatement('text')}` : ''
172
197
  }`
173
198
  )
174
199
  .return('source, relationship, presentation')
@@ -176,10 +201,17 @@ export const getIncomingPresentationsForProfile = async (
176
201
  .run()
177
202
  );
178
203
 
179
- return results.map(({ source, relationship, presentation }) => ({
180
- uri: getPresentationUri(presentation.id, domain),
181
- to: relationship.to,
182
- from: source.profileId,
183
- sent: relationship.date,
184
- }));
204
+ return results.map(({ source, relationship, presentation }) => {
205
+ const relationshipProps = inflateRelationshipProperties(
206
+ relationship as unknown as Record<string, unknown>
207
+ );
208
+
209
+ return {
210
+ uri: getPresentationUri(presentation.id, domain),
211
+ to: relationshipProps.to as string,
212
+ from: source.profileId,
213
+ sent: relationshipProps.date as string,
214
+ metadata: relationshipProps.metadata,
215
+ };
216
+ });
185
217
  };
@@ -1,26 +1,69 @@
1
- import { PresentationInstance, Profile } from '@models';
1
+ import { BindParam, QueryBuilder } from 'neogma';
2
+
3
+ import { Presentation, PresentationInstance, Profile } from '@models';
4
+ import { flattenObject } from '@helpers/objects.helpers';
2
5
  import { ProfileType } from 'types/profile';
3
6
 
4
7
  export const createSentPresentationRelationship = async (
5
8
  from: ProfileType,
6
9
  to: ProfileType,
7
- presentation: PresentationInstance
10
+ presentation: PresentationInstance,
11
+ metadata?: Record<string, unknown>
8
12
  ): Promise<void> => {
9
- await Profile.relateTo({
10
- alias: 'presentationSent',
11
- where: { source: { profileId: from.profileId }, target: { id: presentation.id } },
12
- properties: { to: to.profileId, date: new Date().toISOString() },
13
+ const properties = flattenObject({
14
+ to: to.profileId,
15
+ date: new Date().toISOString(),
16
+ ...(metadata ? { metadata } : {}),
13
17
  });
18
+
19
+ await new QueryBuilder(new BindParam({ params: properties }))
20
+ .match({
21
+ related: [
22
+ { model: Profile, where: { profileId: from.profileId }, identifier: 'profile' },
23
+ ],
24
+ })
25
+ .match({
26
+ related: [
27
+ { model: Presentation, where: { id: presentation.id }, identifier: 'presentation' },
28
+ ],
29
+ })
30
+ .create(
31
+ `(profile)-[relationship:${
32
+ Profile.getRelationshipByAlias('presentationSent').name
33
+ }]->(presentation)`
34
+ )
35
+ .set('relationship = $params')
36
+ .run();
14
37
  };
15
38
 
16
39
  export const createReceivedPresentationRelationship = async (
17
40
  to: ProfileType,
18
41
  from: ProfileType,
19
- presentation: PresentationInstance
42
+ presentation: PresentationInstance,
43
+ metadata?: Record<string, unknown>
20
44
  ): Promise<void> => {
21
- await presentation.relateTo({
22
- alias: 'presentationReceived',
23
- where: { profileId: to.profileId },
24
- properties: { from: from.profileId, date: new Date().toISOString() },
45
+ const properties = flattenObject({
46
+ from: from.profileId,
47
+ date: new Date().toISOString(),
48
+ ...(metadata ? { metadata } : {}),
25
49
  });
50
+
51
+ await new QueryBuilder(new BindParam({ params: properties }))
52
+ .match({
53
+ related: [
54
+ { model: Presentation, where: { id: presentation.id }, identifier: 'presentation' },
55
+ ],
56
+ })
57
+ .match({
58
+ related: [
59
+ { model: Profile, where: { profileId: to.profileId }, identifier: 'profile' },
60
+ ],
61
+ })
62
+ .create(
63
+ `(presentation)-[relationship:${
64
+ Presentation.getRelationshipByAlias('presentationReceived').name
65
+ }]->(profile)`
66
+ )
67
+ .set('relationship = $params')
68
+ .run();
26
69
  };