@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
@@ -14,16 +14,27 @@ export type ConsentFlowRelationships = {
14
14
  { signingAuthorityEndpoint: string; signingAuthorityName: string; issuer?: string }
15
15
  >;
16
16
  canWrite: ModelRelatedNodesI<typeof Profile, ProfileInstance>;
17
+ sharesDataWith: ModelRelatedNodesI<typeof Profile, ProfileInstance>;
17
18
  relatedTo: ModelRelatedNodesI<typeof Boost, BoostInstance>;
18
19
  requestedFor: ModelRelatedNodesI<
19
20
  typeof Profile,
20
21
  ProfileInstance,
21
22
  {
22
- status: 'pending' | 'accepted' | 'denied';
23
+ status: 'pending' | 'accepted' | 'denied' | 'cancelled';
24
+ requestId?: string;
25
+ requestedBy?: string;
26
+ externalReferenceId?: string;
27
+ message?: string;
28
+ requestedAt?: string;
23
29
  readStatus?: 'unseen' | 'seen' | null;
24
30
  },
25
31
  {
26
- status: 'pending' | 'accepted' | 'denied';
32
+ status: 'pending' | 'accepted' | 'denied' | 'cancelled';
33
+ requestId?: string;
34
+ requestedBy?: string;
35
+ externalReferenceId?: string;
36
+ message?: string;
37
+ requestedAt?: string;
27
38
  readStatus?: 'unseen' | 'seen' | null;
28
39
  }
29
40
  >;
@@ -47,6 +58,8 @@ export const ConsentFlowContract = ModelFactory<FlatDbContractType, ConsentFlowR
47
58
  createdAt: { type: 'string', required: true },
48
59
  updatedAt: { type: 'string', required: true },
49
60
  expiresAt: { type: 'string', required: false },
61
+ audienceVersion: { type: 'number', required: false },
62
+ hasConsented: { type: 'boolean', required: false },
50
63
  } as any,
51
64
  relationships: {
52
65
  createdBy: { model: Profile, direction: 'out', name: 'CREATED_BY' },
@@ -70,17 +83,35 @@ export const ConsentFlowContract = ModelFactory<FlatDbContractType, ConsentFlowR
70
83
  },
71
84
  },
72
85
  canWrite: { model: Profile, direction: 'out', name: 'CAN_WRITE' },
86
+ sharesDataWith: { model: Profile, direction: 'out', name: 'SHARES_DATA_WITH' },
73
87
  relatedTo: { model: Boost, direction: 'out', name: 'RELATED_TO' },
74
88
  requestedFor: {
75
89
  model: Profile,
76
90
  direction: 'out',
77
91
  name: 'REQUESTED_FOR',
78
92
  properties: {
93
+ requestId: {
94
+ property: 'requestId',
95
+ schema: { type: 'string', required: false },
96
+ },
97
+ requestedBy: {
98
+ property: 'requestedBy',
99
+ schema: { type: 'string', required: false },
100
+ },
101
+ externalReferenceId: {
102
+ property: 'externalReferenceId',
103
+ schema: { type: 'string', required: false },
104
+ },
105
+ message: { property: 'message', schema: { type: 'string', required: false } },
106
+ requestedAt: {
107
+ property: 'requestedAt',
108
+ schema: { type: 'string', required: false },
109
+ },
79
110
  status: {
80
111
  property: 'status',
81
112
  schema: {
82
113
  type: 'string',
83
- enum: ['pending', 'accepted', 'denied'],
114
+ enum: ['pending', 'accepted', 'denied', 'cancelled'],
84
115
  required: false,
85
116
  },
86
117
  },
@@ -19,10 +19,20 @@ export const ConsentFlowTerms = ModelFactory<FlatDbTermsType, ConsentFlowTermsRe
19
19
  {
20
20
  label: 'ConsentFlowTerms',
21
21
  schema: {
22
+ smartResumeFingerprint: { type: 'string', required: false },
23
+ smartResumePublicationStatus: { type: 'string', required: false },
24
+ smartResumeLeaseId: { type: 'string', required: false },
25
+ smartResumeLeaseUntil: { type: 'number', required: false },
26
+ smartResumeMutationVersion: { type: 'number', required: false },
27
+ smartResumeRedirectUrl: { type: 'string', required: false },
22
28
  id: { type: 'string', required: true },
29
+ 'referral.requestId': { type: 'string', required: false },
30
+ 'referral.requestedBy': { type: 'string', required: false },
31
+ 'referral.externalReferenceId': { type: 'string', required: false },
23
32
  status: { type: 'string', required: true },
24
33
  createdAt: { type: 'string', required: false },
25
34
  updatedAt: { type: 'string', required: false },
35
+ mutationVersion: { type: 'number', required: false },
26
36
  expiresAt: { type: 'string', required: false },
27
37
  oneTime: { type: 'boolean', required: false },
28
38
  deniedWriters: { type: 'string[]', required: false },
@@ -21,6 +21,9 @@ export const ConsentFlowTransaction = ModelFactory<
21
21
  label: 'ConsentFlowTransaction',
22
22
  schema: {
23
23
  id: { type: 'string', required: true },
24
+ 'referral.requestId': { type: 'string', required: false },
25
+ 'referral.requestedBy': { type: 'string', required: false },
26
+ 'referral.externalReferenceId': { type: 'string', required: false },
24
27
  status: { type: 'string', required: true },
25
28
  expiresAt: { type: 'string', required: false },
26
29
  oneTime: { type: 'boolean', required: false },
@@ -3,11 +3,13 @@ import { ModelFactory, ModelRelatedNodesI, NeogmaInstance } from 'neogma';
3
3
  import { neogma } from '@instance';
4
4
 
5
5
  import { Profile, ProfileInstance } from './Profile';
6
+ import type { AppManifestVersion, AppManifestVersionInstance } from './AppManifestVersion';
6
7
  import { FlatIntegrationType } from 'types/integration';
7
8
 
8
9
  export type IntegrationRelationships = {
9
10
  createdBy: ModelRelatedNodesI<typeof Profile, ProfileInstance>;
10
11
  publishesListing: ModelRelatedNodesI<any, any>;
12
+ hasManifestVersion: ModelRelatedNodesI<typeof AppManifestVersion, AppManifestVersionInstance>;
11
13
  };
12
14
 
13
15
  export type IntegrationInstance = NeogmaInstance<FlatIntegrationType, IntegrationRelationships>;
@@ -9,8 +9,8 @@ export type PresentationRelationships = {
9
9
  presentationReceived: ModelRelatedNodesI<
10
10
  { createOne: (typeof Profile)['createOne'] },
11
11
  ProfileInstance,
12
- { from: string; date: string },
13
- { from: string; date: string }
12
+ { from: string; date: string; metadata?: Record<string, unknown> },
13
+ { from: string; date: string; metadata?: Record<string, unknown> }
14
14
  >;
15
15
  };
16
16
 
@@ -75,8 +75,8 @@ export type ProfileRelationships = {
75
75
  presentationSent: ModelRelatedNodesI<
76
76
  typeof Presentation,
77
77
  PresentationInstance,
78
- { to: string; date: string },
79
- { to: string; date: string }
78
+ { to: string; date: string; metadata?: Record<string, unknown> },
79
+ { to: string; date: string; metadata?: Record<string, unknown> }
80
80
  >;
81
81
  usesSigningAuthority: ModelRelatedNodesI<
82
82
  typeof SigningAuthority,
@@ -238,6 +238,7 @@ export const Profile: any = ModelFactory<FlatProfileType, ProfileRelationships>(
238
238
  properties: {
239
239
  to: { property: 'to', schema: { type: 'string', required: true } },
240
240
  date: { property: 'date', schema: { type: 'string', required: true } },
241
+ metadata: { property: 'metadata', schema: { type: 'object', required: false } },
241
242
  },
242
243
  },
243
244
  usesSigningAuthority: {
@@ -0,0 +1,134 @@
1
+ import { ModelFactory, NeogmaInstance } from 'neogma';
2
+
3
+ import { neogma } from '@instance';
4
+
5
+ /** Lifecycle status of a share. Only `active` is ever served to a recipient. */
6
+ export type ShareLinkStatus = 'pending' | 'active' | 'stopped';
7
+
8
+ /**
9
+ * Whether the visible content pointer for a share is committed.
10
+ *
11
+ * `staging` means a reservation exists but the object is not visible yet;
12
+ * `content_missing` means Brain believes content should be visible but LearnCloud
13
+ * does not have it, so the share fails closed and is never served.
14
+ */
15
+ export type ShareContentState = 'staging' | 'finalized' | 'content_missing';
16
+
17
+ /**
18
+ * Persisted ShareLink metadata (LC-2187).
19
+ *
20
+ * This node is the only Brain-side source of truth for the *visible* content
21
+ * pointer. It stores an opaque immutable `activeObjectRef` plus content/recovery
22
+ * hashes and byte counts — never ciphertext, a raw private source URI or a key.
23
+ * The concrete encrypted envelope and owner recovery JWE live together in the
24
+ * dedicated LearnCloud collection keyed by the immutable object reference.
25
+ *
26
+ * `version` is the committed record revision used for optimistic concurrency; a
27
+ * reservation (`staging`) does not change it. `contentVersion` is the visible
28
+ * content revision and changes only when a replacement is finalized.
29
+ */
30
+ export type ShareLinkRecord = {
31
+ id: string;
32
+ namespace: string;
33
+ ownerProfileId: string;
34
+ version: number;
35
+ contentVersion: number;
36
+ attachmentId?: string | null;
37
+ attachmentChunkCount?: number | null;
38
+ /**
39
+ * Monotonic fence. Bumped on every reservation and on revoke; a worker may
40
+ * only finalize the reservation whose generation still equals this value.
41
+ */
42
+ generation: number;
43
+ status: ShareLinkStatus;
44
+ contentState: ShareContentState;
45
+ activeObjectRef: string | null;
46
+ activeObjectOperationId: string | null;
47
+ activeContentHash: string | null;
48
+ activeContentBytes: number | null;
49
+ activeRecoveryHash: string | null;
50
+ /** Operation binding: the operation id that produced the visible revision. */
51
+ lastOperationId: string | null;
52
+ /** Operation binding: the create request that first bound this share id. */
53
+ createdByClientRequestId: string | null;
54
+ title: string;
55
+ note: string | null;
56
+ selectedCount: number;
57
+ expiresAt: string | null;
58
+ stoppedAt: string | null;
59
+ viewCount: number;
60
+ lastViewedAt: string | null;
61
+ /** Argon2id PHC string. Plaintext passcodes are never persisted. */
62
+ passcodeHash?: string | null;
63
+ notifyOnView?: boolean;
64
+ minorPolicyIsMinor: boolean | null;
65
+ minorPolicyResolved: boolean;
66
+ minorPolicyDefaultExpiryDays: number;
67
+ minorPolicyViewCountingEnabled: boolean;
68
+ createdAt: string;
69
+ updatedAt: string;
70
+ };
71
+
72
+ /** Neo4j omits null properties; the repository maps missing values back to null. */
73
+ type ShareLinkProperties = { lockTick?: number } & {
74
+ [Key in keyof ShareLinkRecord]:
75
+ | Exclude<ShareLinkRecord[Key], null>
76
+ | (null extends ShareLinkRecord[Key] ? undefined : never);
77
+ };
78
+ export type ShareLinkInstance = NeogmaInstance<ShareLinkProperties, Record<string, never>>;
79
+
80
+ /**
81
+ * `:ShareLink` model registration. The repository writes this label with raw
82
+ * parameterized Cypher so it can hold the share write lock across read + write
83
+ * within one transaction; the model exists for schema/typed instance support and
84
+ * constraint registration.
85
+ */
86
+ export const ShareLink = ModelFactory<ShareLinkProperties, Record<string, never>>(
87
+ {
88
+ label: 'ShareLink',
89
+ schema: {
90
+ id: { type: 'string', required: true },
91
+ namespace: { type: 'string', required: true },
92
+ ownerProfileId: { type: 'string', required: true },
93
+ version: { type: 'number', required: true },
94
+ contentVersion: { type: 'number', required: true },
95
+ attachmentId: { type: 'string', required: false },
96
+ attachmentChunkCount: { type: 'number', required: false },
97
+ generation: { type: 'number', required: true },
98
+ status: { type: 'string', required: true, enum: ['pending', 'active', 'stopped'] },
99
+ contentState: {
100
+ type: 'string',
101
+ required: true,
102
+ enum: ['staging', 'finalized', 'content_missing'],
103
+ },
104
+ activeObjectRef: { type: 'string', required: false },
105
+ activeObjectOperationId: { type: 'string', required: false },
106
+ activeContentHash: { type: 'string', required: false },
107
+ activeContentBytes: { type: 'number', required: false },
108
+ activeRecoveryHash: { type: 'string', required: false },
109
+ lastOperationId: { type: 'string', required: false },
110
+ createdByClientRequestId: { type: 'string', required: false },
111
+ title: { type: 'string', required: true },
112
+ note: { type: 'string', required: false },
113
+ selectedCount: { type: 'number', required: true },
114
+ expiresAt: { type: 'string', required: false },
115
+ stoppedAt: { type: 'string', required: false },
116
+ viewCount: { type: 'number', required: true },
117
+ lastViewedAt: { type: 'string', required: false },
118
+ passcodeHash: { type: 'string', required: false },
119
+ // LC-2187 records created before opt-in alerts may omit this field.
120
+ notifyOnView: { type: 'boolean', required: false },
121
+ minorPolicyIsMinor: { type: 'boolean', required: false },
122
+ minorPolicyResolved: { type: 'boolean', required: true },
123
+ minorPolicyDefaultExpiryDays: { type: 'number', required: true },
124
+ minorPolicyViewCountingEnabled: { type: 'boolean', required: true },
125
+ createdAt: { type: 'string', required: true },
126
+ updatedAt: { type: 'string', required: true },
127
+ lockTick: { type: 'number', required: false },
128
+ },
129
+ primaryKeyField: 'id',
130
+ },
131
+ neogma
132
+ );
133
+
134
+ export default ShareLink;
@@ -0,0 +1,69 @@
1
+ import { ModelFactory, NeogmaInstance } from 'neogma';
2
+
3
+ import { neogma } from '@instance';
4
+
5
+ /**
6
+ * Persisted, short-lived view receipt (LC-2187 ADR-10).
7
+ *
8
+ * Only the hash of the opaque CSPRNG token is stored — never the token, a viewer
9
+ * identity, an IP, a fingerprint, a credential, a key or any request body. The
10
+ * node is bound to one immutable committed tuple
11
+ * `(namespace, ownerProfileId, shareId, contentVersion, objectRef, operationId)`
12
+ * so a receipt for a superseded revision can never count toward the current one.
13
+ *
14
+ * `consumedAt` is the single-use marker; `lockTick` exists only so a transaction
15
+ * can take a write lock on the receipt AFTER it holds the share write lock.
16
+ * `expiresAt` bounds retention and is indexed for one-shot pruning.
17
+ */
18
+ export type ShareViewReceiptRecord = {
19
+ receiptHash: string;
20
+ namespace: string;
21
+ ownerProfileId: string;
22
+ shareId: string;
23
+ contentVersion: number;
24
+ objectRef: string;
25
+ operationId: string;
26
+ createdAt: string;
27
+ expiresAt: string;
28
+ consumedAt: string | null;
29
+ };
30
+
31
+ type ShareViewReceiptProperties = { lockTick?: number } & {
32
+ [Key in keyof ShareViewReceiptRecord]:
33
+ | Exclude<ShareViewReceiptRecord[Key], null>
34
+ | (null extends ShareViewReceiptRecord[Key] ? undefined : never);
35
+ };
36
+
37
+ export type ShareViewReceiptInstance = NeogmaInstance<
38
+ ShareViewReceiptProperties,
39
+ Record<string, never>
40
+ >;
41
+
42
+ /**
43
+ * `:ShareViewReceipt` model registration. The repository writes this label with
44
+ * raw parameterized Cypher so consume + increment happen in one transaction with
45
+ * explicit share-then-receipt lock ordering; the model exists for schema and
46
+ * constraint registration.
47
+ */
48
+ export const ShareViewReceipt = ModelFactory<ShareViewReceiptProperties, Record<string, never>>(
49
+ {
50
+ label: 'ShareViewReceipt',
51
+ schema: {
52
+ receiptHash: { type: 'string', required: true },
53
+ namespace: { type: 'string', required: true },
54
+ ownerProfileId: { type: 'string', required: true },
55
+ shareId: { type: 'string', required: true },
56
+ contentVersion: { type: 'number', required: true },
57
+ objectRef: { type: 'string', required: true },
58
+ operationId: { type: 'string', required: true },
59
+ createdAt: { type: 'string', required: true },
60
+ expiresAt: { type: 'string', required: true },
61
+ consumedAt: { type: 'string', required: false },
62
+ lockTick: { type: 'number', required: false },
63
+ },
64
+ primaryKeyField: 'receiptHash',
65
+ },
66
+ neogma
67
+ );
68
+
69
+ export default ShareViewReceipt;
@@ -1,5 +1,6 @@
1
1
  import { environment } from '@environment';
2
2
  import { neogma } from '@instance';
3
+ import { contractEventMaintenanceSchema } from '@helpers/contract-event-maintenance.helpers';
3
4
 
4
5
  import { Boost } from './Boost';
5
6
  import { Profile } from './Profile';
@@ -11,6 +12,7 @@ import { Skill } from './Skill';
11
12
  import { Tag } from './Tag';
12
13
  import { AppStoreListing } from './AppStoreListing';
13
14
  import { Integration } from './Integration';
15
+ import { AppManifestVersion } from './AppManifestVersion';
14
16
  import { CredentialActivity } from './CredentialActivity';
15
17
  import { CredentialRefresh } from './CredentialRefresh';
16
18
  import { StatusList } from './StatusList';
@@ -69,6 +71,7 @@ Presentation.addRelationships({
69
71
  properties: {
70
72
  from: { property: 'from', schema: { type: 'string', required: true } },
71
73
  date: { property: 'date', schema: { type: 'string', required: true } },
74
+ metadata: { property: 'metadata', schema: { type: 'object', required: false } },
72
75
  },
73
76
  },
74
77
  });
@@ -91,6 +94,19 @@ Integration.addRelationships({
91
94
  direction: 'out',
92
95
  name: 'PUBLISHES_LISTING',
93
96
  },
97
+ hasManifestVersion: {
98
+ model: AppManifestVersion,
99
+ direction: 'out',
100
+ name: 'HAS_MANIFEST_VERSION',
101
+ },
102
+ });
103
+
104
+ AppStoreListing.addRelationships({
105
+ usesManifestVersion: {
106
+ model: AppManifestVersion,
107
+ direction: 'out',
108
+ name: 'USES_MANIFEST_VERSION',
109
+ },
94
110
  });
95
111
 
96
112
  Profile.addRelationships({
@@ -127,6 +143,9 @@ const shouldCreateIndices =
127
143
  environment.NODE_ENV === 'production' || !environment.NEO4J_SKIP_INDICES;
128
144
 
129
145
  const indexQueries = [
146
+ 'CREATE CONSTRAINT consent_event_id IF NOT EXISTS FOR (e:ConsentFlowEvent) REQUIRE e.id IS UNIQUE',
147
+ 'CREATE CONSTRAINT consent_delivery_id IF NOT EXISTS FOR (d:ConsentFlowEventDelivery) REQUIRE d.id IS UNIQUE',
148
+ ...contractEventMaintenanceSchema,
130
149
  'CREATE INDEX profileId_idx IF NOT EXISTS FOR (p:Profile) ON (p.profileId)',
131
150
  'CREATE INDEX profile_did_idx IF NOT EXISTS FOR (p:Profile) ON (p.did)',
132
151
  'CREATE TEXT INDEX profileId_text_idx IF NOT EXISTS FOR (n:Profile) ON (n.profileId)',
@@ -151,6 +170,10 @@ const indexQueries = [
151
170
  'CREATE INDEX claim_hook_updated_idx IF NOT EXISTS FOR (c:ClaimHook) ON (c.updatedAt)',
152
171
  'CREATE INDEX integration_id_idx IF NOT EXISTS FOR (i:Integration) ON (i.id)',
153
172
  'CREATE INDEX integration_publishablekey_idx IF NOT EXISTS FOR (i:Integration) ON (i.publishableKey)',
173
+ 'CREATE INDEX app_manifest_version_id_idx IF NOT EXISTS FOR (m:AppManifestVersion) ON (m.id)',
174
+ 'CREATE INDEX app_manifest_version_version_idx IF NOT EXISTS FOR (m:AppManifestVersion) ON (m.version)',
175
+ 'CREATE INDEX app_manifest_version_hash_idx IF NOT EXISTS FOR (m:AppManifestVersion) ON (m.manifestHash)',
176
+ 'CREATE INDEX app_manifest_version_status_idx IF NOT EXISTS FOR (m:AppManifestVersion) ON (m.status)',
154
177
  'CREATE INDEX skill_framework_id_idx IF NOT EXISTS FOR (f:SkillFramework) ON (f.id)',
155
178
  'CREATE TEXT INDEX skill_framework_name_text_idx IF NOT EXISTS FOR (f:SkillFramework) ON (f.name)',
156
179
  'CREATE INDEX skill_id_idx IF NOT EXISTS FOR (s:Skill) ON (s.id)',
@@ -253,7 +276,9 @@ export * from './SkillFramework';
253
276
  export * from './Skill';
254
277
  export * from './Tag';
255
278
  export * from './Integration';
279
+ export * from './AppManifestVersion';
256
280
  export * from './AppStoreListing';
257
281
  export * from './CredentialActivity';
258
282
  export * from './CredentialRefresh';
283
+ export * from './ShareLink';
259
284
  export * from './StatusList';
@@ -0,0 +1,98 @@
1
+ import { neogma } from '@instance';
2
+
3
+ /**
4
+ * Uniqueness rules required for the LC-2187 share lifecycle.
5
+ *
6
+ * A uniqueness constraint alone does not serialize two transactions consuming one
7
+ * reservation; the repository additionally holds a `:ShareLink` write lock before
8
+ * reading status/version/reservation state. These rules are the hard backstop that
9
+ * makes the resulting race fail closed instead of forking state.
10
+ */
11
+ const SHARE_LINK_CONSTRAINT_QUERIES = [
12
+ 'CREATE CONSTRAINT share_link_attachment_stage_key_unique IF NOT EXISTS FOR (a:ShareLinkAttachmentStage) REQUIRE (a.key) IS UNIQUE',
13
+ 'CREATE CONSTRAINT share_link_attachment_id_unique IF NOT EXISTS FOR (a:ShareLinkAttachmentStage) REQUIRE (a.attachmentId) IS UNIQUE',
14
+ 'CREATE CONSTRAINT share_attachment_owner_quota_key_unique IF NOT EXISTS FOR (q:ShareAttachmentOwnerQuota) REQUIRE (q.key) IS UNIQUE',
15
+ // A share id is globally unique across namespaces.
16
+ 'CREATE CONSTRAINT share_link_id_unique IF NOT EXISTS FOR (s:ShareLink) REQUIRE (s.id) IS UNIQUE',
17
+ // One idempotency record per (namespace, owner, operation kind, client request).
18
+ 'CREATE CONSTRAINT share_link_operation_key_unique IF NOT EXISTS FOR (o:ShareLinkOperation) REQUIRE (o.namespace, o.ownerProfileId, o.opKind, o.clientRequestId) IS UNIQUE',
19
+ // At most one in-flight reservation per share.
20
+ 'CREATE CONSTRAINT share_link_reservation_share_unique IF NOT EXISTS FOR (r:ShareLinkReservation) REQUIRE (r.shareId) IS UNIQUE',
21
+ // Cleanup is bound to exactly one immutable object reference.
22
+ 'CREATE CONSTRAINT share_content_cleanup_object_unique IF NOT EXISTS FOR (c:ShareContentCleanupJob) REQUIRE (c.objectRef) IS UNIQUE',
23
+ // One persisted receipt node per opaque token hash (the token itself is never stored).
24
+ 'CREATE CONSTRAINT share_view_receipt_hash_unique IF NOT EXISTS FOR (v:ShareViewReceipt) REQUIRE (v.receiptHash) IS UNIQUE',
25
+ ];
26
+
27
+ /**
28
+ * Non-unique indexes that keep the lifecycle queries bounded. Index creation is
29
+ * idempotent and shares the same readiness gate as the constraints.
30
+ */
31
+ const SHARE_LINK_INDEX_QUERIES = [
32
+ 'CREATE INDEX share_attachment_stage_owner_idx IF NOT EXISTS FOR (a:ShareLinkAttachmentStage) ON (a.namespace, a.ownerProfileId, a.status)',
33
+ 'CREATE INDEX share_attachment_stage_expiry_idx IF NOT EXISTS FOR (a:ShareLinkAttachmentStage) ON (a.namespace, a.status, a.expiresAt)',
34
+ 'CREATE INDEX share_link_ns_owner_idx IF NOT EXISTS FOR (s:ShareLink) ON (s.namespace, s.ownerProfileId)',
35
+ // Bounded owner-list keyset pagination: filters on the leading
36
+ // (namespace, ownerProfileId) prefix and orders by the immutable
37
+ // (createdAt, id) key without a full scan/sort.
38
+ 'CREATE INDEX share_link_ns_owner_created_idx IF NOT EXISTS FOR (s:ShareLink) ON (s.namespace, s.ownerProfileId, s.createdAt, s.id)',
39
+ 'CREATE INDEX share_link_status_idx IF NOT EXISTS FOR (s:ShareLink) ON (s.status)',
40
+ 'CREATE INDEX share_link_operation_operation_id_idx IF NOT EXISTS FOR (o:ShareLinkOperation) ON (o.operationId)',
41
+ 'CREATE INDEX share_link_operation_share_id_idx IF NOT EXISTS FOR (o:ShareLinkOperation) ON (o.shareId)',
42
+ 'CREATE INDEX share_link_reservation_lease_idx IF NOT EXISTS FOR (r:ShareLinkReservation) ON (r.leaseExpiresAt)',
43
+ // Bounded recovery discovery enumerates expired reservations for one namespace.
44
+ 'CREATE INDEX share_link_reservation_ns_lease_idx IF NOT EXISTS FOR (r:ShareLinkReservation) ON (r.namespace, r.leaseExpiresAt)',
45
+ 'CREATE INDEX share_content_cleanup_due_idx IF NOT EXISTS FOR (c:ShareContentCleanupJob) ON (c.status, c.nextAttemptAt)',
46
+ // One-shot receipt pruning is bounded by expiry/consumed state.
47
+ 'CREATE INDEX share_view_receipt_expiry_idx IF NOT EXISTS FOR (v:ShareViewReceipt) ON (v.expiresAt)',
48
+ 'CREATE INDEX share_view_receipt_share_idx IF NOT EXISTS FOR (v:ShareViewReceipt) ON (v.namespace, v.shareId)',
49
+ ];
50
+
51
+ type Neo4jSchemaError = {
52
+ code?: string;
53
+ };
54
+
55
+ const isEquivalentSchemaRuleRace = (error: unknown): boolean =>
56
+ (error as Neo4jSchemaError | undefined)?.code ===
57
+ 'Neo.ClientError.Schema.EquivalentSchemaRuleAlreadyExists';
58
+
59
+ const createShareLinkSchema = async (): Promise<void> => {
60
+ for (const query of [...SHARE_LINK_CONSTRAINT_QUERIES, ...SHARE_LINK_INDEX_QUERIES]) {
61
+ try {
62
+ await neogma.queryRunner.run(query);
63
+ } catch (error) {
64
+ // Concurrent service starts can both observe a missing rule before one
65
+ // wins creation. The losing CREATE is equivalent to the desired ready state.
66
+ if (!isEquivalentSchemaRuleRace(error)) throw error;
67
+ }
68
+ }
69
+ };
70
+
71
+ let constraintReadiness: Promise<void> | undefined;
72
+
73
+ /**
74
+ * Ensures the uniqueness rules and indexes required for the share lifecycle.
75
+ *
76
+ * Every public repository method awaits this before its transaction, so a caller
77
+ * can never observe the "constraints not initialized" window. Concurrent callers
78
+ * share one attempt; a failed attempt is cleared so a later request can retry
79
+ * instead of leaving the repository permanently unavailable.
80
+ */
81
+ export const ensureShareLinkConstraints = (): Promise<void> => {
82
+ if (!constraintReadiness) {
83
+ const pendingReadiness = createShareLinkSchema();
84
+ constraintReadiness = pendingReadiness;
85
+
86
+ void pendingReadiness.catch(() => {
87
+ if (constraintReadiness === pendingReadiness) constraintReadiness = undefined;
88
+ });
89
+ }
90
+
91
+ return constraintReadiness;
92
+ };
93
+
94
+ /** Exposed for focused tests that assert the exact schema statements. */
95
+ export const SHARE_LINK_SCHEMA_QUERIES = [
96
+ ...SHARE_LINK_CONSTRAINT_QUERIES,
97
+ ...SHARE_LINK_INDEX_QUERIES,
98
+ ] as const;
package/src/openapi.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { generateOpenApiDocument } from 'trpc-to-openapi';
2
- import express, { type Express } from 'express';
2
+ import express from 'express';
3
+ import type { Express } from 'express';
3
4
 
4
5
  import { appRouter } from './app';
5
6
 
@@ -43,20 +44,55 @@ if (publishRequestBody && !('$ref' in publishRequestBody)) {
43
44
  const publishSchema = publishRequestBody.content?.['application/json']?.schema;
44
45
 
45
46
  if (publishSchema && !('$ref' in publishSchema)) {
47
+ const properties = publishSchema.properties;
48
+ const signedCredential = properties?.signedCredential;
49
+ const credential = properties?.credential;
50
+ const signingAuthority = properties?.signingAuthority;
51
+
52
+ if (!properties?.refreshId || !signedCredential || !credential || !signingAuthority) {
53
+ throw new Error('Managed refresh publication schema is missing required properties');
54
+ }
55
+
56
+ const commonProperties = {
57
+ refreshId: properties.refreshId,
58
+ notifyHolder: properties.notifyHolder!,
59
+ updateSummary: properties.updateSummary!,
60
+ idempotencyKey: properties.idempotencyKey!,
61
+ };
62
+ // Generator 7.25.0 loses the OpenAPI 3.1 closed-object flag. Keep the
63
+ // template workaround scoped to these mutually exclusive request branches.
64
+ const closedPublicationBranch = {
65
+ additionalProperties: false,
66
+ 'x-python-forbid-extra': true,
67
+ } as const;
68
+
69
+ // Each branch must own its complete shape. Generators do not inherit the
70
+ // parent's properties into oneOf branches; enum also works in the pinned generator.
46
71
  publishSchema.oneOf = [
47
72
  {
48
- properties: { mode: { const: 'issuer-signed' } },
49
- required: ['signedCredential'],
50
- not: {
51
- anyOf: [{ required: ['credential'] }, { required: ['signingAuthority'] }],
73
+ type: 'object',
74
+ properties: {
75
+ ...commonProperties,
76
+ mode: { type: 'string', enum: ['issuer-signed'] },
77
+ signedCredential,
52
78
  },
79
+ required: ['refreshId', 'mode', 'signedCredential'],
80
+ ...closedPublicationBranch,
53
81
  },
54
82
  {
55
- properties: { mode: { const: 'signing-authority' } },
56
- required: ['credential', 'signingAuthority'],
57
- not: { required: ['signedCredential'] },
83
+ type: 'object',
84
+ properties: {
85
+ ...commonProperties,
86
+ mode: { type: 'string', enum: ['signing-authority'] },
87
+ credential,
88
+ signingAuthority,
89
+ },
90
+ required: ['refreshId', 'mode', 'credential', 'signingAuthority'],
91
+ ...closedPublicationBranch,
58
92
  },
59
93
  ];
94
+ delete publishSchema.properties;
95
+ delete publishSchema.required;
60
96
  }
61
97
  }
62
98
 
@@ -0,0 +1,49 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+
3
+ /**
4
+ * LC-2187 public share-link HTTP adapter seam.
5
+ *
6
+ * The Fastify OpenAPI adapter has no `responseMeta` hook, so the no-store
7
+ * contract for the anonymous public share-link routes is applied at the adapter
8
+ * boundary itself. This module is deliberately free of the server bootstrap
9
+ * (which listens on import) so a real Fastify instance can be exercised in
10
+ * tests without starting the application.
11
+ */
12
+
13
+ /**
14
+ * Prefixes that identify a mounted public share-link OpenAPI request.
15
+ *
16
+ * The trpc-to-openapi Fastify adapter rewrites `request.raw.url` by stripping
17
+ * its `/api` base path before the handler runs, so the `onSend` hook sees
18
+ * `/public/share-links/...` even though the client requested
19
+ * `/api/public/share-links/...`. Both forms are matched (with a path-boundary
20
+ * check) so a sibling route such as `/public/share-links-other` is not treated
21
+ * as public.
22
+ */
23
+ const PUBLIC_SHARE_LINK_PREFIXES = ['/api/public/share-links', '/public/share-links'] as const;
24
+
25
+ /** True for the mounted public share-link OpenAPI route prefix only. */
26
+ export const isPublicShareLinkOpenApiRequestUrl = (url: string | undefined): boolean => {
27
+ if (!url) return false;
28
+
29
+ const path = url.split('?')[0] ?? '';
30
+
31
+ return PUBLIC_SHARE_LINK_PREFIXES.some(
32
+ prefix => path === prefix || path.startsWith(`${prefix}/`)
33
+ );
34
+ };
35
+
36
+ /**
37
+ * Installs the adapter-boundary `Cache-Control: private, no-store` on every
38
+ * public share-link OpenAPI response, independent of any upstream cache layer.
39
+ * It is safe to register on any Fastify instance (tRPC-only test apps included).
40
+ */
41
+ export const registerPublicShareLinkNoStore = (app: FastifyInstance): void => {
42
+ app.addHook('onSend', async (request, reply, payload) => {
43
+ if (isPublicShareLinkOpenApiRequestUrl(request.raw.url)) {
44
+ reply.header('Cache-Control', 'private, no-store');
45
+ }
46
+
47
+ return payload;
48
+ });
49
+ };