@learncard/network-brain-service 3.19.0 → 3.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/.env.example +34 -2
  2. package/CHANGELOG.md +38 -0
  3. package/README.md +42 -0
  4. package/dist/accesslayer/consentflowcontract/relationships/create.d.ts.map +1 -1
  5. package/dist/accesslayer/consentflowcontract/relationships/update.d.ts.map +1 -1
  6. package/dist/accesslayer/presentation/read.d.ts.map +1 -1
  7. package/dist/accesslayer/presentation/relationships/create.d.ts +2 -2
  8. package/dist/accesslayer/presentation/relationships/create.d.ts.map +1 -1
  9. package/dist/accesslayer/presentation/relationships/read.d.ts.map +1 -1
  10. package/dist/accesslayer/share-link/abandon.d.ts +3 -0
  11. package/dist/accesslayer/share-link/abandon.d.ts.map +1 -0
  12. package/dist/accesslayer/share-link/cleanup.d.ts +6 -0
  13. package/dist/accesslayer/share-link/cleanup.d.ts.map +1 -0
  14. package/dist/accesslayer/share-link/errors.d.ts +8 -0
  15. package/dist/accesslayer/share-link/errors.d.ts.map +1 -0
  16. package/dist/accesslayer/share-link/finalize.d.ts +3 -0
  17. package/dist/accesslayer/share-link/finalize.d.ts.map +1 -0
  18. package/dist/accesslayer/share-link/helpers.d.ts +56 -0
  19. package/dist/accesslayer/share-link/helpers.d.ts.map +1 -0
  20. package/dist/accesslayer/share-link/index.d.ts +12 -0
  21. package/dist/accesslayer/share-link/index.d.ts.map +1 -0
  22. package/dist/accesslayer/share-link/list.d.ts +5 -0
  23. package/dist/accesslayer/share-link/list.d.ts.map +1 -0
  24. package/dist/accesslayer/share-link/read.d.ts +5 -0
  25. package/dist/accesslayer/share-link/read.d.ts.map +1 -0
  26. package/dist/accesslayer/share-link/receipt.d.ts +11 -0
  27. package/dist/accesslayer/share-link/receipt.d.ts.map +1 -0
  28. package/dist/accesslayer/share-link/recovery.d.ts +6 -0
  29. package/dist/accesslayer/share-link/recovery.d.ts.map +1 -0
  30. package/dist/accesslayer/share-link/reserve.d.ts +4 -0
  31. package/dist/accesslayer/share-link/reserve.d.ts.map +1 -0
  32. package/dist/accesslayer/share-link/revoke.d.ts +3 -0
  33. package/dist/accesslayer/share-link/revoke.d.ts.map +1 -0
  34. package/dist/accesslayer/share-link/transaction-execution.d.ts +18 -0
  35. package/dist/accesslayer/share-link/transaction-execution.d.ts.map +1 -0
  36. package/dist/accesslayer/share-link/transaction.d.ts +15 -0
  37. package/dist/accesslayer/share-link/transaction.d.ts.map +1 -0
  38. package/dist/accesslayer/share-link/types.d.ts +370 -0
  39. package/dist/accesslayer/share-link/types.d.ts.map +1 -0
  40. package/dist/app.d.ts +4 -0
  41. package/dist/app.d.ts.map +1 -1
  42. package/dist/config/environment.d.ts +9 -0
  43. package/dist/config/environment.d.ts.map +1 -1
  44. package/dist/constants/auth-grant.d.ts +2 -0
  45. package/dist/constants/auth-grant.d.ts.map +1 -1
  46. package/dist/helpers/boost.helpers.d.ts.map +1 -1
  47. package/dist/helpers/credentialSubject.helpers.d.ts +3 -0
  48. package/dist/helpers/credentialSubject.helpers.d.ts.map +1 -0
  49. package/dist/helpers/credentialSubject.helpers.test.d.ts +2 -0
  50. package/dist/helpers/credentialSubject.helpers.test.d.ts.map +1 -0
  51. package/dist/helpers/inbox.helpers.d.ts.map +1 -1
  52. package/dist/helpers/notificationMessages.d.ts +1 -1
  53. package/dist/helpers/notificationMessages.d.ts.map +1 -1
  54. package/dist/helpers/presentation-metadata.d.ts +4 -0
  55. package/dist/helpers/presentation-metadata.d.ts.map +1 -0
  56. package/dist/helpers/presentation.helpers.d.ts +1 -1
  57. package/dist/helpers/presentation.helpers.d.ts.map +1 -1
  58. package/dist/helpers/profile.helpers.d.ts +1 -0
  59. package/dist/helpers/profile.helpers.d.ts.map +1 -1
  60. package/dist/helpers/share-content-client/adapters.d.ts +10 -0
  61. package/dist/helpers/share-content-client/adapters.d.ts.map +1 -0
  62. package/dist/helpers/share-content-client/canonical.d.ts +7 -0
  63. package/dist/helpers/share-content-client/canonical.d.ts.map +1 -0
  64. package/dist/helpers/share-content-client/client.d.ts +5 -0
  65. package/dist/helpers/share-content-client/client.d.ts.map +1 -0
  66. package/dist/helpers/share-content-client/config.d.ts +11 -0
  67. package/dist/helpers/share-content-client/config.d.ts.map +1 -0
  68. package/dist/helpers/share-content-client/index.d.ts +6 -0
  69. package/dist/helpers/share-content-client/index.d.ts.map +1 -0
  70. package/dist/helpers/share-content-client/responses.d.ts +16 -0
  71. package/dist/helpers/share-content-client/responses.d.ts.map +1 -0
  72. package/dist/helpers/share-content-client/types.d.ts +145 -0
  73. package/dist/helpers/share-content-client/types.d.ts.map +1 -0
  74. package/dist/helpers/share-link-coordinator/budget-helpers.d.ts +5 -0
  75. package/dist/helpers/share-link-coordinator/budget-helpers.d.ts.map +1 -0
  76. package/dist/helpers/share-link-coordinator/cleanup-runner.d.ts +3 -0
  77. package/dist/helpers/share-link-coordinator/cleanup-runner.d.ts.map +1 -0
  78. package/dist/helpers/share-link-coordinator/coordinator.d.ts +4 -0
  79. package/dist/helpers/share-link-coordinator/coordinator.d.ts.map +1 -0
  80. package/dist/helpers/share-link-coordinator/index.d.ts +5 -0
  81. package/dist/helpers/share-link-coordinator/index.d.ts.map +1 -0
  82. package/dist/helpers/share-link-coordinator/recovery-runner.d.ts +9 -0
  83. package/dist/helpers/share-link-coordinator/recovery-runner.d.ts.map +1 -0
  84. package/dist/helpers/share-link-coordinator/runtime.d.ts +11 -0
  85. package/dist/helpers/share-link-coordinator/runtime.d.ts.map +1 -0
  86. package/dist/helpers/share-link-coordinator/stat.d.ts +4 -0
  87. package/dist/helpers/share-link-coordinator/stat.d.ts.map +1 -0
  88. package/dist/helpers/share-link-coordinator/types.d.ts +160 -0
  89. package/dist/helpers/share-link-coordinator/types.d.ts.map +1 -0
  90. package/dist/helpers/share-link-lifecycle/index.d.ts +5 -0
  91. package/dist/helpers/share-link-lifecycle/index.d.ts.map +1 -0
  92. package/dist/helpers/share-link-lifecycle/lease.helpers.d.ts +4 -0
  93. package/dist/helpers/share-link-lifecycle/lease.helpers.d.ts.map +1 -0
  94. package/dist/helpers/share-link-lifecycle/recovery.helpers.d.ts +21 -0
  95. package/dist/helpers/share-link-lifecycle/recovery.helpers.d.ts.map +1 -0
  96. package/dist/helpers/share-link-lifecycle/request-hash.helpers.d.ts +9 -0
  97. package/dist/helpers/share-link-lifecycle/request-hash.helpers.d.ts.map +1 -0
  98. package/dist/helpers/share-link-lifecycle/types.d.ts +14 -0
  99. package/dist/helpers/share-link-lifecycle/types.d.ts.map +1 -0
  100. package/dist/helpers/share-link-maintenance/budget.d.ts +12 -0
  101. package/dist/helpers/share-link-maintenance/budget.d.ts.map +1 -0
  102. package/dist/helpers/share-link-maintenance/config.d.ts +48 -0
  103. package/dist/helpers/share-link-maintenance/config.d.ts.map +1 -0
  104. package/dist/helpers/share-link-maintenance/index.d.ts +8 -0
  105. package/dist/helpers/share-link-maintenance/index.d.ts.map +1 -0
  106. package/dist/helpers/share-link-maintenance/runner.d.ts +19 -0
  107. package/dist/helpers/share-link-maintenance/runner.d.ts.map +1 -0
  108. package/dist/helpers/share-link-maintenance/runtime.d.ts +36 -0
  109. package/dist/helpers/share-link-maintenance/runtime.d.ts.map +1 -0
  110. package/dist/helpers/share-link-maintenance/scheduler.d.ts +18 -0
  111. package/dist/helpers/share-link-maintenance/scheduler.d.ts.map +1 -0
  112. package/dist/helpers/share-link-maintenance/telemetry.d.ts +5 -0
  113. package/dist/helpers/share-link-maintenance/telemetry.d.ts.map +1 -0
  114. package/dist/helpers/share-link-maintenance/types.d.ts +53 -0
  115. package/dist/helpers/share-link-maintenance/types.d.ts.map +1 -0
  116. package/dist/helpers/share-link-owner/config.d.ts +16 -0
  117. package/dist/helpers/share-link-owner/config.d.ts.map +1 -0
  118. package/dist/helpers/share-link-owner/diagnostics.d.ts +26 -0
  119. package/dist/helpers/share-link-owner/diagnostics.d.ts.map +1 -0
  120. package/dist/helpers/share-link-owner/lazy-initializer.d.ts +2 -0
  121. package/dist/helpers/share-link-owner/lazy-initializer.d.ts.map +1 -0
  122. package/dist/helpers/share-link-owner-projection.d.ts +4 -0
  123. package/dist/helpers/share-link-owner-projection.d.ts.map +1 -0
  124. package/dist/helpers/share-link-passcode-abuse.d.ts +2 -0
  125. package/dist/helpers/share-link-passcode-abuse.d.ts.map +1 -0
  126. package/dist/helpers/share-link-passcode.d.ts +6 -0
  127. package/dist/helpers/share-link-passcode.d.ts.map +1 -0
  128. package/dist/helpers/share-link-policy/index.d.ts +4 -0
  129. package/dist/helpers/share-link-policy/index.d.ts.map +1 -0
  130. package/dist/helpers/share-link-policy/production.d.ts +13 -0
  131. package/dist/helpers/share-link-policy/production.d.ts.map +1 -0
  132. package/dist/helpers/share-link-policy/resolver.d.ts +6 -0
  133. package/dist/helpers/share-link-policy/resolver.d.ts.map +1 -0
  134. package/dist/helpers/share-link-policy/types.d.ts +16 -0
  135. package/dist/helpers/share-link-policy/types.d.ts.map +1 -0
  136. package/dist/helpers/share-link-public/config.d.ts +13 -0
  137. package/dist/helpers/share-link-public/config.d.ts.map +1 -0
  138. package/dist/helpers/share-link-view-notification.d.ts +2 -0
  139. package/dist/helpers/share-link-view-notification.d.ts.map +1 -0
  140. package/dist/index.js +2 -2
  141. package/dist/models/Presentation.d.ts +2 -0
  142. package/dist/models/Presentation.d.ts.map +1 -1
  143. package/dist/models/Profile.d.ts +2 -0
  144. package/dist/models/Profile.d.ts.map +1 -1
  145. package/dist/models/ShareLink.d.ts +44 -0
  146. package/dist/models/ShareLink.d.ts.map +1 -0
  147. package/dist/models/ShareViewReceipt.d.ts +22 -0
  148. package/dist/models/ShareViewReceipt.d.ts.map +1 -0
  149. package/dist/models/index.d.ts +1 -0
  150. package/dist/models/index.d.ts.map +1 -1
  151. package/dist/models/share-link-constraints.d.ts +3 -0
  152. package/dist/models/share-link-constraints.d.ts.map +1 -0
  153. package/dist/public-share-link-http.d.ts +4 -0
  154. package/dist/public-share-link-http.d.ts.map +1 -0
  155. package/dist/routes/app-store.d.ts.map +1 -1
  156. package/dist/routes/boosts.d.ts.map +1 -1
  157. package/dist/routes/contracts.d.ts +2 -2
  158. package/dist/routes/contracts.d.ts.map +1 -1
  159. package/dist/routes/credentials.d.ts +1 -1
  160. package/dist/routes/index.d.ts +153 -0
  161. package/dist/routes/index.d.ts.map +1 -1
  162. package/dist/routes/presentations.d.ts +1 -0
  163. package/dist/routes/presentations.d.ts.map +1 -1
  164. package/dist/routes/profile-manager.d.ts.map +1 -1
  165. package/dist/routes/profiles.d.ts.map +1 -1
  166. package/dist/routes/public-share-links.d.ts +230 -0
  167. package/dist/routes/public-share-links.d.ts.map +1 -0
  168. package/dist/routes/share-links.d.ts +844 -0
  169. package/dist/routes/share-links.d.ts.map +1 -0
  170. package/dist/services/delivery/adapters/postmark.adapter.d.ts.map +1 -1
  171. package/dist/types/consentflowcontract.d.ts +1 -1
  172. package/lambda.ts +4 -1
  173. package/package.json +22 -16
  174. package/scripts/seed-demo-persona.ts +425 -0
  175. package/serverless.yml +36 -0
  176. package/shareLinkMaintenanceLambda.ts +49 -0
  177. package/src/accesslayer/consentflowcontract/relationships/create.ts +9 -16
  178. package/src/accesslayer/consentflowcontract/relationships/update.ts +15 -28
  179. package/src/accesslayer/presentation/read.ts +57 -25
  180. package/src/accesslayer/presentation/relationships/create.ts +54 -11
  181. package/src/accesslayer/presentation/relationships/read.ts +21 -6
  182. package/src/accesslayer/share-link/abandon.ts +100 -0
  183. package/src/accesslayer/share-link/cleanup.ts +271 -0
  184. package/src/accesslayer/share-link/errors.ts +32 -0
  185. package/src/accesslayer/share-link/finalize.ts +265 -0
  186. package/src/accesslayer/share-link/helpers.ts +419 -0
  187. package/src/accesslayer/share-link/index.ts +11 -0
  188. package/src/accesslayer/share-link/list.ts +162 -0
  189. package/src/accesslayer/share-link/read.ts +107 -0
  190. package/src/accesslayer/share-link/receipt.ts +548 -0
  191. package/src/accesslayer/share-link/recovery.ts +545 -0
  192. package/src/accesslayer/share-link/reserve.ts +684 -0
  193. package/src/accesslayer/share-link/revoke.ts +197 -0
  194. package/src/accesslayer/share-link/transaction-execution.ts +72 -0
  195. package/src/accesslayer/share-link/transaction.ts +126 -0
  196. package/src/accesslayer/share-link/types.ts +601 -0
  197. package/src/app.ts +6 -0
  198. package/src/config/environment.ts +14 -0
  199. package/src/constants/auth-grant.ts +5 -0
  200. package/src/docker-entry.ts +57 -0
  201. package/src/helpers/boost.helpers.ts +4 -31
  202. package/src/helpers/credentialSubject.helpers.test.ts +114 -0
  203. package/src/helpers/credentialSubject.helpers.ts +40 -0
  204. package/src/helpers/inbox.helpers.ts +7 -4
  205. package/src/helpers/notificationMessages.ts +18 -1
  206. package/src/helpers/presentation-metadata.ts +41 -0
  207. package/src/helpers/presentation.helpers.ts +27 -20
  208. package/src/helpers/profile.helpers.ts +7 -0
  209. package/src/helpers/share-content-client/adapters.ts +55 -0
  210. package/src/helpers/share-content-client/canonical.ts +25 -0
  211. package/src/helpers/share-content-client/client.ts +440 -0
  212. package/src/helpers/share-content-client/config.ts +189 -0
  213. package/src/helpers/share-content-client/index.ts +27 -0
  214. package/src/helpers/share-content-client/responses.ts +273 -0
  215. package/src/helpers/share-content-client/types.ts +253 -0
  216. package/src/helpers/share-link-coordinator/budget-helpers.ts +53 -0
  217. package/src/helpers/share-link-coordinator/cleanup-runner.ts +286 -0
  218. package/src/helpers/share-link-coordinator/coordinator.ts +714 -0
  219. package/src/helpers/share-link-coordinator/index.ts +8 -0
  220. package/src/helpers/share-link-coordinator/recovery-runner.ts +428 -0
  221. package/src/helpers/share-link-coordinator/runtime.ts +88 -0
  222. package/src/helpers/share-link-coordinator/stat.ts +30 -0
  223. package/src/helpers/share-link-coordinator/types.ts +353 -0
  224. package/src/helpers/share-link-lifecycle/index.ts +4 -0
  225. package/src/helpers/share-link-lifecycle/lease.helpers.ts +35 -0
  226. package/src/helpers/share-link-lifecycle/recovery.helpers.ts +173 -0
  227. package/src/helpers/share-link-lifecycle/request-hash.helpers.ts +130 -0
  228. package/src/helpers/share-link-lifecycle/types.ts +58 -0
  229. package/src/helpers/share-link-maintenance/budget.ts +63 -0
  230. package/src/helpers/share-link-maintenance/config.ts +312 -0
  231. package/src/helpers/share-link-maintenance/index.ts +24 -0
  232. package/src/helpers/share-link-maintenance/runner.ts +223 -0
  233. package/src/helpers/share-link-maintenance/runtime.ts +334 -0
  234. package/src/helpers/share-link-maintenance/scheduler.ts +126 -0
  235. package/src/helpers/share-link-maintenance/telemetry.ts +70 -0
  236. package/src/helpers/share-link-maintenance/types.ts +89 -0
  237. package/src/helpers/share-link-owner/config.ts +48 -0
  238. package/src/helpers/share-link-owner/diagnostics.ts +89 -0
  239. package/src/helpers/share-link-owner/lazy-initializer.ts +29 -0
  240. package/src/helpers/share-link-owner-projection.ts +52 -0
  241. package/src/helpers/share-link-passcode-abuse.ts +36 -0
  242. package/src/helpers/share-link-passcode.ts +47 -0
  243. package/src/helpers/share-link-policy/index.ts +7 -0
  244. package/src/helpers/share-link-policy/production.ts +88 -0
  245. package/src/helpers/share-link-policy/resolver.ts +108 -0
  246. package/src/helpers/share-link-policy/types.ts +48 -0
  247. package/src/helpers/share-link-public/config.ts +41 -0
  248. package/src/helpers/share-link-view-notification.ts +18 -0
  249. package/src/models/Presentation.ts +2 -2
  250. package/src/models/Profile.ts +3 -2
  251. package/src/models/ShareLink.ts +130 -0
  252. package/src/models/ShareViewReceipt.ts +69 -0
  253. package/src/models/index.ts +2 -0
  254. package/src/models/share-link-constraints.ts +93 -0
  255. package/src/public-share-link-http.ts +49 -0
  256. package/src/routes/app-store.ts +2 -11
  257. package/src/routes/boosts.ts +2 -11
  258. package/src/routes/contracts.ts +2 -11
  259. package/src/routes/index.ts +139 -44
  260. package/src/routes/presentations.ts +19 -3
  261. package/src/routes/profile-manager.ts +10 -2
  262. package/src/routes/profiles.ts +17 -6
  263. package/src/routes/public-share-links.ts +814 -0
  264. package/src/routes/share-links.ts +640 -0
  265. package/src/services/delivery/adapters/postmark.adapter.ts +4 -1
  266. package/test/dids.spec.ts +10 -1
  267. package/test/guardian-gated-routes.spec.ts +13 -0
  268. package/test/helpers/share-link-fixtures.ts +94 -0
  269. package/test/managed-recipient-inbox.spec.ts +130 -0
  270. package/test/notificationMessages.spec.ts +13 -0
  271. package/test/openapi.spec.ts +20 -0
  272. package/test/presentations.spec.ts +54 -6
  273. package/test/profiles.spec.ts +67 -1
  274. package/test/share-content-client.contract.spec.ts +365 -0
  275. package/test/share-content-client.unit.spec.ts +462 -0
  276. package/test/share-link-abuse.unit.spec.ts +65 -0
  277. package/test/share-link-coordinator.neo4j.spec.ts +684 -0
  278. package/test/share-link-coordinator.unit.spec.ts +990 -0
  279. package/test/share-link-dependency-diagnostics.unit.spec.ts +127 -0
  280. package/test/share-link-lifecycle.neo4j.spec.ts +1268 -0
  281. package/test/share-link-lifecycle.unit.spec.ts +205 -0
  282. package/test/share-link-list-cursor.unit.spec.ts +86 -0
  283. package/test/share-link-list.neo4j.spec.ts +324 -0
  284. package/test/share-link-maintenance.neo4j.spec.ts +355 -0
  285. package/test/share-link-maintenance.unit.spec.ts +1113 -0
  286. package/test/share-link-owner-policy.unit.spec.ts +210 -0
  287. package/test/share-link-owner-route.unit.spec.ts +752 -0
  288. package/test/share-link-owner-runtime.unit.spec.ts +102 -0
  289. package/test/share-link-passcode.unit.spec.ts +29 -0
  290. package/test/share-link-policy.unit.spec.ts +135 -0
  291. package/test/share-link-presentation-metadata.unit.spec.ts +49 -0
  292. package/test/share-link-production-policy.unit.spec.ts +77 -0
  293. package/test/share-link-public-config.unit.spec.ts +64 -0
  294. package/test/share-link-public-http-adapter.unit.spec.ts +315 -0
  295. package/test/share-link-public-route.unit.spec.ts +800 -0
  296. package/test/share-link-receipt.neo4j.spec.ts +943 -0
  297. package/test/share-link-recovery.neo4j.spec.ts +935 -0
  298. package/test/share-link-recovery.unit.spec.ts +726 -0
  299. package/vitest.config.ts +1 -0
  300. package/vitest.share-links-neo4j.config.ts +19 -0
  301. package/vitest.share-links-unit.config.ts +28 -0
@@ -23,8 +23,8 @@ import { reconsentTerms, upsertRequestedForRelationship } from './update';
23
23
  import { addNotificationToQueue } from '@helpers/notifications.helpers';
24
24
  import { getNotificationMessage } from '@helpers/notificationMessages';
25
25
  import { resolveRecipientLocale } from '@helpers/getRecipientLocale.helpers';
26
- import { sendBoost } from '@helpers/boost.helpers';
27
- import { getBoostUri } from '@helpers/boost.helpers';
26
+ import { getBoostUri, sendBoost } from '@helpers/boost.helpers';
27
+ import { setCredentialSubjectIds } from '@helpers/credentialSubject.helpers';
28
28
  import { getDidWeb } from '@helpers/did.helpers';
29
29
  import { getSigningAuthorityForUserByName } from '@accesslayer/signing-authority/relationships/read';
30
30
  import { issueCredentialWithSigningAuthority } from '@helpers/signingAuthority.helpers';
@@ -238,22 +238,15 @@ export const consentToContract = async (
238
238
 
239
239
  boostCredential.issuer = { id: contractOwnerSigningAuthority.relationship.did };
240
240
 
241
- boostCredential.boostId = getBoostUri(boost.target.id, domain);
242
-
243
- if (Array.isArray(boostCredential.credentialSubject)) {
244
- boostCredential.credentialSubject = boostCredential.credentialSubject.map(
245
- subject => ({
246
- ...subject,
247
- id: getDidWeb(domain, consenter.profileId),
248
- })
249
- );
250
- } else {
251
- boostCredential.credentialSubject.id = getDidWeb(
252
- domain,
253
- consenter.profileId
254
- );
241
+ if (boostCredential.type.includes('BoostCredential')) {
242
+ boostCredential.boostId = getBoostUri(boost.target.id, domain);
255
243
  }
256
244
 
245
+ setCredentialSubjectIds(
246
+ boostCredential,
247
+ getDidWeb(domain, consenter.profileId)
248
+ );
249
+
257
250
  // Inject OBv3 skill alignments based on boost's framework/skills
258
251
  await injectObv3AlignmentsIntoCredentialForBoost(
259
252
  boostCredential,
@@ -17,6 +17,7 @@ import { getNotificationMessage } from '@helpers/notificationMessages';
17
17
  import { resolveRecipientLocale } from '@helpers/getRecipientLocale.helpers';
18
18
  import { DbContractType, DbTermsType } from 'types/consentflowcontract';
19
19
  import { getBoostUri, sendBoost } from '@helpers/boost.helpers';
20
+ import { setCredentialSubjectIds } from '@helpers/credentialSubject.helpers';
20
21
  import { getDidWeb } from '@helpers/did.helpers';
21
22
  import { getSigningAuthorityForUserByName } from '@accesslayer/signing-authority/relationships/read';
22
23
  import { issueCredentialWithSigningAuthority } from '@helpers/signingAuthority.helpers';
@@ -154,22 +155,15 @@ export const reconsentTerms = async (
154
155
  // Set the issuer and subject
155
156
  boostCredential.issuer = { id: contractOwnerSigningAuthority.relationship.did };
156
157
 
157
- boostCredential.boostId = getBoostUri(boost.dataValues.id, domain);
158
-
159
- if (Array.isArray(boostCredential.credentialSubject)) {
160
- boostCredential.credentialSubject = boostCredential.credentialSubject.map(
161
- subject => ({
162
- ...subject,
163
- id: getDidWeb(domain, relationship.consenter.profileId),
164
- })
165
- );
166
- } else {
167
- boostCredential.credentialSubject.id = getDidWeb(
168
- domain,
169
- relationship.consenter.profileId
170
- );
158
+ if (boostCredential.type.includes('BoostCredential')) {
159
+ boostCredential.boostId = getBoostUri(boost.dataValues.id, domain);
171
160
  }
172
161
 
162
+ setCredentialSubjectIds(
163
+ boostCredential,
164
+ getDidWeb(domain, relationship.consenter.profileId)
165
+ );
166
+
173
167
  // Issue the credential using contract owner's signing authority
174
168
  // Inject OBv3 skill alignments based on boost's framework/skills
175
169
  await injectObv3AlignmentsIntoCredentialForBoost(
@@ -384,22 +378,15 @@ export const updateTerms = async (
384
378
  // Set the issuer and subject
385
379
  boostCredential.issuer = { id: contractOwnerSigningAuthority.relationship.did };
386
380
 
387
- boostCredential.boostId = getBoostUri(boost.target.id, domain);
388
-
389
- if (Array.isArray(boostCredential.credentialSubject)) {
390
- boostCredential.credentialSubject = boostCredential.credentialSubject.map(
391
- subject => ({
392
- ...subject,
393
- id: getDidWeb(domain, relationship.consenter.profileId),
394
- })
395
- );
396
- } else {
397
- boostCredential.credentialSubject.id = getDidWeb(
398
- domain,
399
- relationship.consenter.profileId
400
- );
381
+ if (boostCredential.type.includes('BoostCredential')) {
382
+ boostCredential.boostId = getBoostUri(boost.target.id, domain);
401
383
  }
402
384
 
385
+ setCredentialSubjectIds(
386
+ boostCredential,
387
+ getDidWeb(domain, relationship.consenter.profileId)
388
+ );
389
+
403
390
  // Issue the credential using contract owner's signing authority
404
391
  // Inject OBv3 skill alignments based on boost's framework/skills
405
392
  await injectObv3AlignmentsIntoCredentialForBoost(
@@ -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
  };
@@ -2,15 +2,26 @@ import { inflateObject } from '@helpers/objects.helpers';
2
2
  import { Presentation, PresentationInstance, Profile, ProfileRelationships } from '@models';
3
3
  import { ProfileType } from 'types/profile';
4
4
 
5
+ const relationshipProperties = (value: unknown): Record<string, unknown> => {
6
+ if (value && typeof value === 'object' && 'dataValues' in value) {
7
+ const { dataValues } = value as { dataValues?: unknown };
8
+ if (dataValues && typeof dataValues === 'object') {
9
+ return dataValues as Record<string, unknown>;
10
+ }
11
+ }
12
+
13
+ return value as Record<string, unknown>;
14
+ };
15
+
5
16
  export const getPresentationSentToProfile = async (
6
17
  id: string,
7
18
  to: ProfileType
8
19
  ): Promise<
9
20
  | {
10
- source: ProfileType;
11
- relationship: ProfileRelationships['presentationSent']['RelationshipProperties'];
12
- target: PresentationInstance;
13
- }
21
+ source: ProfileType;
22
+ relationship: ProfileRelationships['presentationSent']['RelationshipProperties'];
23
+ target: PresentationInstance;
24
+ }
14
25
  | undefined
15
26
  > => {
16
27
  const data = (
@@ -22,7 +33,11 @@ export const getPresentationSentToProfile = async (
22
33
 
23
34
  if (!data) return undefined;
24
35
 
25
- return { ...data, source: inflateObject(data.source.dataValues as any) };
36
+ return {
37
+ ...data,
38
+ source: inflateObject(data.source.dataValues as unknown as Record<string, unknown>),
39
+ relationship: inflateObject(relationshipProperties(data.relationship)),
40
+ };
26
41
  };
27
42
 
28
43
  export const getPresentationOwner = async (
@@ -39,7 +54,7 @@ export const getPresentationOwner = async (
39
54
 
40
55
  if (!owner) return undefined;
41
56
 
42
- return inflateObject<ProfileType>(owner.dataValues as any);
57
+ return inflateObject(owner.dataValues as unknown as Record<string, unknown>) as ProfileType;
43
58
  };
44
59
 
45
60
  export const getPresentationReceivedByProfile = async (
@@ -0,0 +1,100 @@
1
+ import { ensureShareLinkConstraints } from '../../models/share-link-constraints';
2
+ import { failShareLink } from './errors';
3
+ import {
4
+ deleteReservation,
5
+ enqueueCleanupJob,
6
+ lockShare,
7
+ markOperationAbandoned,
8
+ readReservation,
9
+ toShareLinkRecord,
10
+ toShareLinkReservationRecord,
11
+ } from './helpers';
12
+ import { withShareLinkTransaction } from './transaction';
13
+ import type { AbandonReservationInput, AbandonReservationResult } from './types';
14
+
15
+ /**
16
+ * Irreversibly abandons a reservation.
17
+ *
18
+ * The operation transitions to cleanup-only: its exact immutable object is queued
19
+ * for tracked cleanup and the reservation is deleted, so a late finalize for the
20
+ * same operation is rejected. A stale worker can never abandon a newer reservation
21
+ * because the operation id (and, when supplied, generation/lease owner) must match.
22
+ *
23
+ * When the reservation is already gone but the share records this operation as the
24
+ * committed one, abandon reports `already_finalized` instead of pretending to have
25
+ * cleaned up live content.
26
+ */
27
+ export const abandonReservation = async (
28
+ input: AbandonReservationInput
29
+ ): Promise<AbandonReservationResult> => {
30
+ await ensureShareLinkConstraints();
31
+
32
+ const now = input.now ?? new Date();
33
+ const nowIso = now.toISOString();
34
+
35
+ return withShareLinkTransaction(async tx => {
36
+ const lockedProps = await lockShare(tx, input.shareId);
37
+
38
+ if (!lockedProps) {
39
+ failShareLink('NOT_FOUND', 'share not found');
40
+ }
41
+
42
+ const share = toShareLinkRecord(lockedProps);
43
+
44
+ if (share.namespace !== input.namespace || share.ownerProfileId !== input.ownerProfileId) {
45
+ failShareLink('NOT_FOUND', 'share not found');
46
+ }
47
+
48
+ const reservationProps = await readReservation(tx, input.shareId);
49
+
50
+ if (!reservationProps) {
51
+ if (share.lastOperationId === input.operationId) {
52
+ return { outcome: 'already_finalized', share };
53
+ }
54
+
55
+ return { outcome: 'already_absent' };
56
+ }
57
+
58
+ const reservation = toShareLinkReservationRecord(reservationProps);
59
+
60
+ if (reservation.operationId !== input.operationId) {
61
+ return { outcome: 'already_absent' };
62
+ }
63
+
64
+ if (input.generation !== undefined && reservation.generation !== input.generation) {
65
+ return { outcome: 'already_absent' };
66
+ }
67
+
68
+ if (input.leaseOwner !== undefined && reservation.leaseOwner !== input.leaseOwner) {
69
+ return { outcome: 'already_absent' };
70
+ }
71
+
72
+ let cleanupQueuedFor: string | null = null;
73
+
74
+ if (reservation.objectRef) {
75
+ await enqueueCleanupJob(tx, {
76
+ objectRef: reservation.objectRef,
77
+ operationId: reservation.operationId,
78
+ namespace: reservation.namespace,
79
+ ownerProfileId: reservation.ownerProfileId,
80
+ shareId: reservation.shareId,
81
+ contentVersion: reservation.contentVersion ?? reservation.baseContentVersion,
82
+ reason: 'abandoned',
83
+ now: nowIso,
84
+ });
85
+
86
+ cleanupQueuedFor = reservation.objectRef;
87
+ }
88
+
89
+ await markOperationAbandoned(tx, {
90
+ namespace: reservation.namespace,
91
+ ownerProfileId: reservation.ownerProfileId,
92
+ opKind: reservation.opKind,
93
+ clientRequestId: reservation.clientRequestId,
94
+ now: nowIso,
95
+ });
96
+ await deleteReservation(tx, input.shareId);
97
+
98
+ return { outcome: 'abandoned', cleanupQueuedFor };
99
+ });
100
+ };