@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
@@ -768,8 +768,10 @@ export const inboxRouter = t.router({
768
768
  claimed: z.number(),
769
769
  errors: z.number(),
770
770
  guardianPending: z.number(),
771
- verifiableCredentials: z.array(VCValidator),
772
- deliveries: z.array(z.object({ id: z.string(), credential: VCValidator })),
771
+ verifiableCredentials: z.array(VCValidator.or(JWEValidator)),
772
+ deliveries: z.array(
773
+ z.object({ id: z.string(), credential: VCValidator.or(JWEValidator) })
774
+ ),
773
775
  })
774
776
  )
775
777
  .mutation(async ({ ctx }) => {
@@ -11,6 +11,7 @@ import jwtDecode from 'jwt-decode';
11
11
  import * as Sentry from '@sentry/serverless';
12
12
  import { ACT_AS_HEADER, AUTH_GRANT_AUDIENCE_DOMAIN_PREFIX } from '@learncard/types';
13
13
  import { ContactMethodType } from '@learncard/types';
14
+ import { MAX_SHARE_LINK_REQUEST_BYTES, utf8ByteLength } from '@learncard/types';
14
15
 
15
16
  import { RegExpTransformer } from '@learncard/helpers';
16
17
  import { resolveTenantFromRequest, type ResolvedTenant } from '@learncard/email-templates';
@@ -22,6 +23,7 @@ import {
22
23
  } from '@accesslayer/profile/relationships/read';
23
24
  import { getDidWeb } from '@helpers/did.helpers';
24
25
  import { getEmptyLearnCard, isServersDidWebDID } from '@helpers/learnCard.helpers';
26
+ import { isServiceProfileExemptFromGuardianship } from '@helpers/profile.helpers';
25
27
  import { invalidateChallengeForDid, isChallengeValidForDid } from '@cache/challenges';
26
28
  import { ProfileType } from 'types/profile';
27
29
  import { getProfileManagerById } from '@accesslayer/profile-manager/read';
@@ -217,14 +219,93 @@ export const createContext = async (
217
219
  return { domain, tenant, _guardianApprovalToken, sourceIp, actAs };
218
220
  };
219
221
 
220
- export const openRoute = t.procedure
221
- .use(t.middleware(Sentry.Handlers.trpcMiddleware({ attachRpcInput: true }) as any))
222
- .use(({ ctx, next, path }) => {
223
- Sentry.configureScope(scope => {
224
- scope.setTransactionName(`trpc-${path}`);
225
- });
226
- return next({ ctx });
222
+ const sentryTransactionNameMiddleware = t.middleware(({ ctx, next, path }) => {
223
+ Sentry.configureScope(scope => {
224
+ scope.setTransactionName(`trpc-${path}`);
227
225
  });
226
+ return next({ ctx });
227
+ });
228
+
229
+ // Sentry's tRPC middleware type predates this repo's generic context. Cast
230
+ // through the tRPC builder's expected parameter type instead of `any`.
231
+ type SentryTrpcMiddleware = Parameters<typeof t.middleware>[0];
232
+
233
+ const sentryInputCaptureMiddleware = Sentry.Handlers.trpcMiddleware({
234
+ attachRpcInput: true,
235
+ }) as unknown as SentryTrpcMiddleware;
236
+
237
+ const sentryNoInputCaptureMiddleware = Sentry.Handlers.trpcMiddleware({
238
+ attachRpcInput: false,
239
+ }) as unknown as SentryTrpcMiddleware;
240
+
241
+ /**
242
+ * Complete-request byte bound for owner share-link routes, enforced on the RAW
243
+ * input before Zod parsing/stripping. Individual field validators cannot bound a
244
+ * request whose unknown or duplicate fields are stripped first, so this measures
245
+ * the whole serialized body (UTF-8) and fails closed over the shared 1 MiB cap.
246
+ *
247
+ * It is composed into the base so it runs before authentication and before any
248
+ * input parser, and can never be skipped by a malformed or unauthenticated call.
249
+ */
250
+ const enforceShareLinkRequestByteBound = t.middleware(async ({ ctx, next, getRawInput }) => {
251
+ const raw = await getRawInput();
252
+
253
+ let bytes: number;
254
+ if (raw === undefined || raw === null) {
255
+ bytes = 0;
256
+ } else if (typeof raw === 'string') {
257
+ bytes = utf8ByteLength(raw);
258
+ } else {
259
+ let serialized: string;
260
+ try {
261
+ serialized = JSON.stringify(raw);
262
+ } catch {
263
+ throw new TRPCError({ code: 'BAD_REQUEST', message: 'invalid share-link request' });
264
+ }
265
+ bytes = utf8ByteLength(serialized);
266
+ }
267
+
268
+ if (bytes > MAX_SHARE_LINK_REQUEST_BYTES) {
269
+ throw new TRPCError({
270
+ code: 'PAYLOAD_TOO_LARGE',
271
+ message: 'share-link request exceeds the 1 MiB limit',
272
+ });
273
+ }
274
+
275
+ return next({ ctx });
276
+ });
277
+
278
+ export const openRoute = t.procedure
279
+ .use(t.middleware(sentryInputCaptureMiddleware))
280
+ .use(sentryTransactionNameMiddleware);
281
+
282
+ /**
283
+ * LC-2187 public share-link paths must never be cached by an intermediary or a
284
+ * browser. tRPC has no per-procedure header API, so the actual HTTP adapters
285
+ * (Fastify and Lambda, both tRPC and OpenAPI) apply `Cache-Control` from the
286
+ * resolved procedure path through this single helper.
287
+ */
288
+ export const PUBLIC_SHARE_LINK_ROUTE_PREFIX = 'publicShareLinks.';
289
+
290
+ export const publicShareLinkCacheControlHeaders = (
291
+ paths: readonly string[] | undefined
292
+ ): Record<string, string> =>
293
+ (paths ?? []).some(path => path.startsWith(PUBLIC_SHARE_LINK_ROUTE_PREFIX))
294
+ ? { 'Cache-Control': 'private, no-store' }
295
+ : {};
296
+
297
+ /**
298
+ * Route base for procedures whose input carries owner-private material (titles,
299
+ * notes, ciphertext envelopes, recovery JWEs) and whose error paths must not
300
+ * attach raw request bodies to Sentry. It runs the same Sentry error/transaction
301
+ * handling but with input attachment disabled, so no branch — malformed,
302
+ * unauthenticated or failing — can capture the payload, and it enforces the
303
+ * complete-request byte bound before input parsing.
304
+ */
305
+ export const openRouteWithoutInputCapture = t.procedure
306
+ .use(t.middleware(sentryNoInputCaptureMiddleware))
307
+ .use(sentryTransactionNameMiddleware)
308
+ .use(enforceShareLinkRequestByteBound);
228
309
 
229
310
  export const resolveProfileFromContextDid = async (
230
311
  didFromContext: string | undefined,
@@ -316,27 +397,33 @@ const resolveActAs = async (
316
397
  return { ...user, profile: target, did: target.did, onBehalfOf: profile.profileId };
317
398
  };
318
399
 
319
- export const didRoute = openRoute.use(async ({ ctx, next }) => {
320
- if (!ctx.user?.did) {
321
- throw new TRPCError({ code: 'UNAUTHORIZED' });
322
- }
400
+ const withDid = (base: typeof openRoute) =>
401
+ base.use(async ({ ctx, next }) => {
402
+ if (!ctx.user?.did) {
403
+ throw new TRPCError({ code: 'UNAUTHORIZED' });
404
+ }
323
405
 
324
- const profile = await resolveProfileFromContextDid(ctx.user.did, ctx.domain);
406
+ const profile = await resolveProfileFromContextDid(ctx.user.did, ctx.domain);
325
407
 
326
- if (profile) Sentry.setUser({ id: profile.profileId, username: profile.displayName });
408
+ if (profile) Sentry.setUser({ id: profile.profileId, username: profile.displayName });
327
409
 
328
- const user = ctx.user.isChallengeValid
329
- ? await resolveActAs({ ...ctx.user, profile }, ctx.actAs, ctx.domain)
330
- : { ...ctx.user, profile };
410
+ const user = ctx.user.isChallengeValid
411
+ ? await resolveActAs({ ...ctx.user, profile }, ctx.actAs, ctx.domain)
412
+ : { ...ctx.user, profile };
331
413
 
332
- return next({ ctx: { ...ctx, user } });
333
- });
414
+ return next({ ctx: { ...ctx, user } });
415
+ });
334
416
 
335
- export const didAndChallengeRoute = didRoute.use(({ ctx, next }) => {
336
- if (!ctx.user?.isChallengeValid) throw new TRPCError({ code: 'UNAUTHORIZED' });
417
+ export const didRoute = withDid(openRoute);
337
418
 
338
- return next({ ctx: { ...ctx, user: ctx.user } });
339
- });
419
+ const withChallenge = (base: typeof didRoute) =>
420
+ base.use(({ ctx, next }) => {
421
+ if (!ctx.user?.isChallengeValid) throw new TRPCError({ code: 'UNAUTHORIZED' });
422
+
423
+ return next({ ctx: { ...ctx, user: ctx.user } });
424
+ });
425
+
426
+ export const didAndChallengeRoute = withChallenge(didRoute);
340
427
 
341
428
  export const scopedRoute = didAndChallengeRoute.use(({ ctx, next, meta }) => {
342
429
  if (!meta?.requiredScope) {
@@ -370,33 +457,41 @@ export const openProfileRoute = didRoute.use(async ({ ctx, next }) => {
370
457
  return next({ ctx: { ...ctx, user: { ...ctx.user, profile } } });
371
458
  });
372
459
 
373
- export const profileRoute = didAndChallengeRoute.use(async ({ ctx, next, meta }) => {
374
- const { profile } = ctx.user;
460
+ const withProfile = (base: typeof didAndChallengeRoute) =>
461
+ base.use(async ({ ctx, next, meta }) => {
462
+ const { profile } = ctx.user;
375
463
 
376
- if (!profile) {
377
- throw new TRPCError({
378
- code: 'NOT_FOUND',
379
- message: 'Profile not found. Please make a profile!',
380
- });
381
- }
464
+ if (!profile) {
465
+ throw new TRPCError({
466
+ code: 'NOT_FOUND',
467
+ message: 'Profile not found. Please make a profile!',
468
+ });
469
+ }
382
470
 
383
- if (!meta?.requiredScope) {
384
- return next({ ctx: { ...ctx, user: { ...ctx.user, profile } } });
385
- }
471
+ if (!meta?.requiredScope) {
472
+ return next({ ctx: { ...ctx, user: { ...ctx.user, profile } } });
473
+ }
386
474
 
387
- const userScope = ctx.user?.scope || AUTH_GRANT_NO_ACCESS_SCOPE;
475
+ const userScope = ctx.user?.scope || AUTH_GRANT_NO_ACCESS_SCOPE;
388
476
 
389
- const hasRequiredScope = userHasRequiredScopes(userScope, meta.requiredScope);
477
+ const hasRequiredScope = userHasRequiredScopes(userScope, meta.requiredScope);
390
478
 
391
- if (!hasRequiredScope) {
392
- throw new TRPCError({
393
- code: 'UNAUTHORIZED',
394
- message: `This operation requires ${meta.requiredScope} scope`,
395
- });
396
- }
479
+ if (!hasRequiredScope) {
480
+ throw new TRPCError({
481
+ code: 'UNAUTHORIZED',
482
+ message: `This operation requires ${meta.requiredScope} scope`,
483
+ });
484
+ }
397
485
 
398
- return next({ ctx: { ...ctx, user: { ...ctx.user, profile } } });
399
- });
486
+ return next({ ctx: { ...ctx, user: { ...ctx.user, profile } } });
487
+ });
488
+
489
+ export const profileRoute = withProfile(didAndChallengeRoute);
490
+
491
+ /** Same auth chain, composed on a base that never attaches private RPC input to Sentry. */
492
+ export const didRouteWithoutInputCapture = withDid(openRouteWithoutInputCapture);
493
+ export const didAndChallengeRouteWithoutInputCapture = withChallenge(didRouteWithoutInputCapture);
494
+ export const profileRouteWithoutInputCapture = withProfile(didAndChallengeRouteWithoutInputCapture);
400
495
 
401
496
  export const openProfileManagerRoute = openRoute.use(async ({ ctx, next }) => {
402
497
  if (!ctx.user?.did) throw new TRPCError({ code: 'UNAUTHORIZED' });
@@ -460,7 +555,10 @@ const GUARDIAN_APPROVAL_CLOCK_SKEW_SECONDS = 60;
460
555
  export const guardianGatedRoute = profileRoute.use(async ({ ctx, next }) => {
461
556
  const { profile } = ctx.user;
462
557
  const guardianApprovalToken = ctx._guardianApprovalToken;
463
- const isChildAccount = await isProfileManaged(profile.profileId);
558
+ // Service profiles (orgs) are managed for admin purposes, not guardianship.
559
+ const isChildAccount =
560
+ !isServiceProfileExemptFromGuardianship(profile.isServiceProfile, profile.type) &&
561
+ (await isProfileManaged(profile.profileId));
464
562
  let guardianIdentity: { profileId: string; did: string } | undefined;
465
563
 
466
564
  if (isChildAccount && guardianApprovalToken) {
@@ -16,6 +16,10 @@ import { getPresentationOwner } from '@accesslayer/presentation/relationships/re
16
16
  import { deletePresentation } from '@accesslayer/presentation/delete';
17
17
  import { isRelationshipBlocked } from '@helpers/connection.helpers';
18
18
  import { getProfileIdFromString } from '@helpers/did.helpers';
19
+ import {
20
+ assertPresentationMetadataRecipient,
21
+ PresentationMetadataValidator,
22
+ } from '@helpers/presentation-metadata';
19
23
 
20
24
  export const presentationsRouter = t.router({
21
25
  sendPresentation: profileRoute
@@ -31,11 +35,17 @@ export const presentationsRouter = t.router({
31
35
  },
32
36
  requiredScope: 'presentations:write',
33
37
  })
34
- .input(z.object({ profileId: z.string(), presentation: VPValidator.or(JWEValidator) }))
38
+ .input(
39
+ z.object({
40
+ profileId: z.string(),
41
+ presentation: VPValidator.or(JWEValidator),
42
+ metadata: PresentationMetadataValidator.optional(),
43
+ })
44
+ )
35
45
  .output(z.string())
36
46
  .mutation(async ({ ctx, input }) => {
37
47
  const { profile } = ctx.user;
38
- const { profileId, presentation } = input;
48
+ const { profileId, presentation, metadata } = input;
39
49
 
40
50
  const resolvedProfileId = await getProfileIdFromString(profileId, ctx.domain);
41
51
  if (!resolvedProfileId) {
@@ -52,7 +62,13 @@ export const presentationsRouter = t.router({
52
62
  });
53
63
  }
54
64
 
55
- return sendPresentation(profile, targetProfile, presentation, ctx.domain);
65
+ assertPresentationMetadataRecipient(
66
+ metadata,
67
+ profile.profileId,
68
+ targetProfile.profileId
69
+ );
70
+
71
+ return sendPresentation(profile, targetProfile, presentation, ctx.domain, metadata);
56
72
  }),
57
73
 
58
74
  acceptPresentation: profileRoute
@@ -18,13 +18,18 @@ import { checkIfProfileExists } from '@accesslayer/profile/read';
18
18
  import { ProfileManagerType, ProfileManagerValidator } from 'types/profile-manager';
19
19
  import { getLearnCard } from '@helpers/learnCard.helpers';
20
20
  import { createProfile } from '@accesslayer/profile/create';
21
+ import { PublicProfileIdValidator } from '@helpers/profile.helpers';
21
22
  import { createManagesRelationship } from '@accesslayer/profile-manager/relationships/create';
22
23
  import { deleteManagesRelationship } from '@accesslayer/profile-manager/relationships/delete';
23
24
  import { getBoostByUri } from '@accesslayer/boost/read';
24
- import { getManagedProfiles, getProfilesManagedByProfile } from '@accesslayer/profile-manager/relationships/read';
25
+ import {
26
+ getManagedProfiles,
27
+ getProfilesManagedByProfile,
28
+ } from '@accesslayer/profile-manager/relationships/read';
25
29
  import { getProfilesThatManageAProfile } from '@accesslayer/profile/relationships/read';
26
30
  import { updateProfileManager } from '@accesslayer/profile-manager/update';
27
31
  import { getProfileManagerById } from '@accesslayer/profile-manager/read';
32
+ import { ProfileManager } from '@models';
28
33
 
29
34
  export const profileManagersRouter = t.router({
30
35
  createProfileManager: profileRoute
@@ -115,9 +120,31 @@ export const profileManagersRouter = t.router({
115
120
  },
116
121
  requiredScope: 'profileManagers:write',
117
122
  })
118
- .input(LCNProfileValidator.omit({ did: true }))
123
+ .input(
124
+ LCNProfileValidator.omit({ did: true }).extend({
125
+ profileId: PublicProfileIdValidator,
126
+ })
127
+ )
119
128
  .output(z.string())
120
129
  .mutation(async ({ input, ctx }) => {
130
+ // Org onboarding also uses this API. Only the persisted Family parent
131
+ // (or an explicit child type), not a client service flag, defines a child path.
132
+ if (input.isServiceProfile) {
133
+ const parents = await ProfileManager.findRelationships({
134
+ alias: 'childOf',
135
+ where: { source: { id: ctx.user.manager.id } },
136
+ });
137
+ if (
138
+ input.type === 'child' ||
139
+ parents.some(({ target }) => target.category === 'Family')
140
+ ) {
141
+ throw new TRPCError({
142
+ code: 'BAD_REQUEST',
143
+ message: 'Child profiles cannot be service profiles.',
144
+ });
145
+ }
146
+ }
147
+
121
148
  const profileExists = await checkIfProfileExists(input);
122
149
 
123
150
  if (profileExists) {
@@ -67,7 +67,7 @@ import { ProfileType, SigningAuthorityForUserValidator } from 'types/profile';
67
67
 
68
68
  import { t, openRoute, didAndChallengeRoute, profileRoute, didRoute } from '@routes';
69
69
 
70
- import { transformProfileId } from '@helpers/profile.helpers';
70
+ import { PublicProfileIdValidator, transformProfileId } from '@helpers/profile.helpers';
71
71
  import { deleteDidDocForProfile } from '@cache/did-docs';
72
72
  import {
73
73
  isInviteAlreadySetForProfile,
@@ -102,7 +102,7 @@ import { createProfileContactMethodRelationship } from '@accesslayer/contact-met
102
102
  import { deleteAllProfileContactMethodRelationshipsExceptForProfileId } from '@accesslayer/contact-method/relationships/delete';
103
103
 
104
104
  const UpdateProfileInputValidator = z.object({
105
- profileId: z.string().optional(),
105
+ profileId: PublicProfileIdValidator.optional(),
106
106
  displayName: z.string().optional(),
107
107
  shortBio: z.string().optional(),
108
108
  bio: z.string().optional(),
@@ -154,7 +154,10 @@ export const profilesRouter = t.router({
154
154
  LCNProfileValidator.omit({
155
155
  did: true,
156
156
  isServiceProfile: true,
157
- }).extend({ authToken: z.string().optional() })
157
+ }).extend({
158
+ profileId: PublicProfileIdValidator,
159
+ authToken: z.string().optional(),
160
+ })
158
161
  )
159
162
  .output(z.string())
160
163
  .mutation(async ({ input, ctx }) => {
@@ -243,7 +246,11 @@ export const profilesRouter = t.router({
243
246
  },
244
247
  requiredScope: 'profiles:write',
245
248
  })
246
- .input(LCNProfileValidator.omit({ did: true, isServiceProfile: true }))
249
+ .input(
250
+ LCNProfileValidator.omit({ did: true, isServiceProfile: true }).extend({
251
+ profileId: PublicProfileIdValidator,
252
+ })
253
+ )
247
254
  .output(z.string())
248
255
  .mutation(async ({ input, ctx }) => {
249
256
  const profileExists = await checkIfProfileExists({ ...input, did: ctx.user.did });
@@ -281,7 +288,11 @@ export const profilesRouter = t.router({
281
288
  },
282
289
  requiredScope: 'profiles:write',
283
290
  })
284
- .input(LCNProfileValidator.omit({ did: true, isServiceProfile: true }))
291
+ .input(
292
+ LCNProfileValidator.omit({ did: true, isServiceProfile: true }).extend({
293
+ profileId: PublicProfileIdValidator,
294
+ })
295
+ )
285
296
  .output(z.string())
286
297
  .mutation(async ({ input, ctx }) => {
287
298
  const { profileId } = input;
@@ -498,7 +509,7 @@ export const profilesRouter = t.router({
498
509
  } = input;
499
510
 
500
511
  const _selfProfile = ctx.user?.did ? await getProfileByDid(ctx.user.did) : null;
501
- const selfProfile = includeSelf ? null : _selfProfile ?? null;
512
+ const selfProfile = includeSelf ? null : (_selfProfile ?? null);
502
513
 
503
514
  const blacklist =
504
515
  (_selfProfile && (await getBlockedAndBlockedByIds(_selfProfile))) || [];
@@ -563,6 +574,18 @@ export const profilesRouter = t.router({
563
574
  .output(z.boolean())
564
575
  .mutation(async ({ input, ctx }) => {
565
576
  const { profile } = ctx.user;
577
+ if (
578
+ profile.isServiceProfile === true &&
579
+ profile.type === 'child' &&
580
+ typeof input.type === 'string' &&
581
+ input.type !== 'child'
582
+ ) {
583
+ throw new TRPCError({
584
+ code: 'BAD_REQUEST',
585
+ message:
586
+ 'A service profile explicitly typed as a child cannot change profile type.',
587
+ });
588
+ }
566
589
 
567
590
  const {
568
591
  profileId,