@openlup/platform 0.0.0 → 0.16.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 (395) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/LICENSE +204 -0
  3. package/README.md +471 -1
  4. package/dist/bff/dispatch.d.ts +27 -0
  5. package/dist/bff/dispatch.js +47 -0
  6. package/dist/bff/envelope.d.ts +46 -0
  7. package/dist/bff/envelope.js +80 -0
  8. package/dist/bff/health.d.ts +24 -0
  9. package/dist/bff/health.js +19 -0
  10. package/dist/bff/index.d.ts +6 -0
  11. package/dist/bff/index.js +6 -0
  12. package/dist/bff/lazyRoute.d.ts +4 -0
  13. package/dist/bff/lazyRoute.js +13 -0
  14. package/dist/bff/requestContext.d.ts +17 -0
  15. package/dist/bff/requestContext.js +26 -0
  16. package/dist/bff/routerRewrite.d.ts +2 -0
  17. package/dist/bff/routerRewrite.js +31 -0
  18. package/dist/blob/binding.d.ts +16 -0
  19. package/dist/blob/binding.js +37 -0
  20. package/dist/blob/filesystem.d.ts +8 -0
  21. package/dist/blob/filesystem.js +71 -0
  22. package/dist/blob/index.d.ts +6 -0
  23. package/dist/blob/index.js +6 -0
  24. package/dist/blob/s3.d.ts +32 -0
  25. package/dist/blob/s3.js +56 -0
  26. package/dist/blob/s3Client.d.ts +25 -0
  27. package/dist/blob/s3Client.js +76 -0
  28. package/dist/blob/supabase.d.ts +40 -0
  29. package/dist/blob/supabase.js +59 -0
  30. package/dist/blob/vercel.d.ts +63 -0
  31. package/dist/blob/vercel.js +69 -0
  32. package/dist/composition/composeBundle.d.ts +47 -0
  33. package/dist/composition/composeBundle.js +45 -0
  34. package/dist/composition/httpBinding.d.ts +8 -0
  35. package/dist/composition/httpBinding.js +18 -0
  36. package/dist/composition/index.d.ts +3 -0
  37. package/dist/composition/index.js +3 -0
  38. package/dist/composition/nodeHost.d.ts +103 -0
  39. package/dist/composition/nodeHost.js +145 -0
  40. package/dist/data/binding.d.ts +34 -0
  41. package/dist/data/binding.js +92 -0
  42. package/dist/data/index.d.ts +5 -0
  43. package/dist/data/index.js +5 -0
  44. package/dist/data/postgresGateway.d.ts +42 -0
  45. package/dist/data/postgresGateway.js +135 -0
  46. package/dist/data/queryBuilder.d.ts +54 -0
  47. package/dist/data/queryBuilder.js +240 -0
  48. package/dist/data/queryBuilderSql.d.ts +76 -0
  49. package/dist/data/queryBuilderSql.js +145 -0
  50. package/dist/data/supabaseClientFactory.d.ts +34 -0
  51. package/dist/data/supabaseClientFactory.js +56 -0
  52. package/dist/data/supabaseGateway.d.ts +22 -0
  53. package/dist/data/supabaseGateway.js +49 -0
  54. package/dist/http/deadline.d.ts +20 -0
  55. package/dist/http/deadline.js +93 -0
  56. package/dist/http/index.d.ts +6 -0
  57. package/dist/http/index.js +5 -0
  58. package/dist/http/requestAdapter.d.ts +38 -0
  59. package/dist/http/requestAdapter.js +203 -0
  60. package/dist/http/runtime.d.ts +83 -0
  61. package/dist/http/runtime.js +199 -0
  62. package/dist/http/security.d.ts +44 -0
  63. package/dist/http/security.js +114 -0
  64. package/dist/http/staticAssets.d.ts +3 -0
  65. package/dist/http/staticAssets.js +42 -0
  66. package/dist/http/types.d.ts +23 -0
  67. package/dist/http/types.js +6 -0
  68. package/dist/identity/adminAuthBinding.d.ts +28 -0
  69. package/dist/identity/adminAuthBinding.js +66 -0
  70. package/dist/identity/adminAuthorization.d.ts +34 -0
  71. package/dist/identity/adminAuthorization.js +72 -0
  72. package/dist/identity/adminContracts.d.ts +70 -0
  73. package/dist/identity/adminContracts.js +43 -0
  74. package/dist/identity/adminMagicLinkHandler.d.ts +39 -0
  75. package/dist/identity/adminMagicLinkHandler.js +94 -0
  76. package/dist/identity/adminMeHandler.d.ts +15 -0
  77. package/dist/identity/adminMeHandler.js +49 -0
  78. package/dist/identity/adminPreflight.d.ts +16 -0
  79. package/dist/identity/adminPreflight.js +38 -0
  80. package/dist/identity/adminUserActionPorts.d.ts +31 -0
  81. package/dist/identity/adminUserActionPorts.js +51 -0
  82. package/dist/identity/adminUserHandlers.d.ts +38 -0
  83. package/dist/identity/adminUserHandlers.js +140 -0
  84. package/dist/identity/authVerifyUrl.d.ts +6 -0
  85. package/dist/identity/authVerifyUrl.js +54 -0
  86. package/dist/identity/contracts/contracts.d.ts +8 -0
  87. package/dist/identity/contracts/contracts.js +2 -0
  88. package/dist/identity/contracts/emailTrust.d.ts +3 -0
  89. package/dist/identity/contracts/emailTrust.js +4 -0
  90. package/dist/identity/contracts/index.d.ts +8 -0
  91. package/dist/identity/contracts/index.js +8 -0
  92. package/dist/identity/contracts/oidc.d.ts +3 -0
  93. package/dist/identity/contracts/oidc.js +9 -0
  94. package/dist/identity/contracts/operatorAuth.d.ts +35 -0
  95. package/dist/identity/contracts/operatorAuth.js +53 -0
  96. package/dist/identity/contracts/operatorInvitations.d.ts +37 -0
  97. package/dist/identity/contracts/operatorInvitations.js +1 -0
  98. package/dist/identity/contracts/ports.d.ts +22 -0
  99. package/dist/identity/contracts/ports.js +1 -0
  100. package/dist/identity/contracts/privacy.d.ts +62 -0
  101. package/dist/identity/contracts/privacy.js +99 -0
  102. package/dist/identity/contracts/providerList.d.ts +3 -0
  103. package/dist/identity/contracts/providerList.js +11 -0
  104. package/dist/identity/contracts/types.d.ts +16 -0
  105. package/dist/identity/contracts/types.js +4 -0
  106. package/dist/identity/contribution.d.ts +8 -0
  107. package/dist/identity/contribution.js +22 -0
  108. package/dist/identity/customerAuth.d.ts +8 -0
  109. package/dist/identity/customerAuth.js +1 -0
  110. package/dist/identity/customerAuthorization.d.ts +5 -0
  111. package/dist/identity/customerAuthorization.js +22 -0
  112. package/dist/identity/customerContracts.d.ts +42 -0
  113. package/dist/identity/customerContracts.js +43 -0
  114. package/dist/identity/customerIdentityBinding.d.ts +44 -0
  115. package/dist/identity/customerIdentityBinding.js +60 -0
  116. package/dist/identity/customerIdentityVerifier.d.ts +8 -0
  117. package/dist/identity/customerIdentityVerifier.js +101 -0
  118. package/dist/identity/customerMagicLinkHandler.d.ts +38 -0
  119. package/dist/identity/customerMagicLinkHandler.js +115 -0
  120. package/dist/identity/customerMeHandler.d.ts +11 -0
  121. package/dist/identity/customerMeHandler.js +46 -0
  122. package/dist/identity/customerPorts.d.ts +4 -0
  123. package/dist/identity/customerPorts.js +1 -0
  124. package/dist/identity/customerSessionBinding.d.ts +38 -0
  125. package/dist/identity/customerSessionBinding.js +80 -0
  126. package/dist/identity/customerSessionIssuer.d.ts +10 -0
  127. package/dist/identity/customerSessionIssuer.js +57 -0
  128. package/dist/identity/customerVerifyOtpHandler.d.ts +8 -0
  129. package/dist/identity/customerVerifyOtpHandler.js +41 -0
  130. package/dist/identity/directOperatorInvitationStore.d.ts +19 -0
  131. package/dist/identity/directOperatorInvitationStore.js +193 -0
  132. package/dist/identity/emailTrustPolicy.d.ts +14 -0
  133. package/dist/identity/emailTrustPolicy.js +16 -0
  134. package/dist/identity/identityPersonalDataContributor.d.ts +7 -0
  135. package/dist/identity/identityPersonalDataContributor.js +46 -0
  136. package/dist/identity/identityReadiness.d.ts +10 -0
  137. package/dist/identity/identityReadiness.js +25 -0
  138. package/dist/identity/index.d.ts +67 -0
  139. package/dist/identity/index.js +66 -0
  140. package/dist/identity/inviteAdminUserUseCase.d.ts +89 -0
  141. package/dist/identity/inviteAdminUserUseCase.js +75 -0
  142. package/dist/identity/jwtLibrary.d.ts +54 -0
  143. package/dist/identity/jwtLibrary.js +1 -0
  144. package/dist/identity/machineActorWriteFence.d.ts +4 -0
  145. package/dist/identity/machineActorWriteFence.js +13 -0
  146. package/dist/identity/magicLinkPorts.d.ts +28 -0
  147. package/dist/identity/magicLinkPorts.js +1 -0
  148. package/dist/identity/managedAccountLinkStore.d.ts +2 -0
  149. package/dist/identity/managedAccountLinkStore.js +93 -0
  150. package/dist/identity/managedAdminAuthVerifier.d.ts +7 -0
  151. package/dist/identity/managedAdminAuthVerifier.js +27 -0
  152. package/dist/identity/managedAdminUserGateways.d.ts +123 -0
  153. package/dist/identity/managedAdminUserGateways.js +127 -0
  154. package/dist/identity/managedClient.d.ts +90 -0
  155. package/dist/identity/managedClient.js +10 -0
  156. package/dist/identity/managedClientAuthLink.d.ts +3 -0
  157. package/dist/identity/managedClientAuthLink.js +115 -0
  158. package/dist/identity/managedCustomerMe.d.ts +13 -0
  159. package/dist/identity/managedCustomerMe.js +30 -0
  160. package/dist/identity/managedEmailTrustPolicy.d.ts +11 -0
  161. package/dist/identity/managedEmailTrustPolicy.js +105 -0
  162. package/dist/identity/managedIdentityVerifier.d.ts +2 -0
  163. package/dist/identity/managedIdentityVerifier.js +16 -0
  164. package/dist/identity/managedPrivacy.d.ts +4 -0
  165. package/dist/identity/managedPrivacy.js +39 -0
  166. package/dist/identity/messages.d.ts +29 -0
  167. package/dist/identity/messages.js +39 -0
  168. package/dist/identity/oidcIdentityVerifier.d.ts +45 -0
  169. package/dist/identity/oidcIdentityVerifier.js +309 -0
  170. package/dist/identity/oidcPrincipal.d.ts +2 -0
  171. package/dist/identity/oidcPrincipal.js +10 -0
  172. package/dist/identity/operatorAdminAuth.d.ts +6 -0
  173. package/dist/identity/operatorAdminAuth.js +13 -0
  174. package/dist/identity/operatorAuthHandlers.d.ts +18 -0
  175. package/dist/identity/operatorAuthHandlers.js +71 -0
  176. package/dist/identity/operatorIdentityVerifier.d.ts +8 -0
  177. package/dist/identity/operatorIdentityVerifier.js +19 -0
  178. package/dist/identity/operatorInvitationLifecycle.d.ts +7 -0
  179. package/dist/identity/operatorInvitationLifecycle.js +15 -0
  180. package/dist/identity/operatorInvitationPorts.d.ts +31 -0
  181. package/dist/identity/operatorInvitationPorts.js +1 -0
  182. package/dist/identity/operatorPorts.d.ts +37 -0
  183. package/dist/identity/operatorPorts.js +1 -0
  184. package/dist/identity/operatorSession.d.ts +13 -0
  185. package/dist/identity/operatorSession.js +31 -0
  186. package/dist/identity/operatorTokenAdminAuth.d.ts +15 -0
  187. package/dist/identity/operatorTokenAdminAuth.js +50 -0
  188. package/dist/identity/personalDataRegistry.d.ts +4 -0
  189. package/dist/identity/personalDataRegistry.js +11 -0
  190. package/dist/identity/platformAdminAuth.d.ts +15 -0
  191. package/dist/identity/platformAdminAuth.js +1 -0
  192. package/dist/identity/ports.d.ts +127 -0
  193. package/dist/identity/ports.js +38 -0
  194. package/dist/identity/postgresAccountLinkStore.d.ts +7 -0
  195. package/dist/identity/postgresAccountLinkStore.js +52 -0
  196. package/dist/identity/postgresCustomerMe.d.ts +3 -0
  197. package/dist/identity/postgresCustomerMe.js +21 -0
  198. package/dist/identity/postgresCustomerRecovery.d.ts +11 -0
  199. package/dist/identity/postgresCustomerRecovery.js +57 -0
  200. package/dist/identity/postgresOperatorIdentity.d.ts +5 -0
  201. package/dist/identity/postgresOperatorIdentity.js +137 -0
  202. package/dist/identity/postgresPrivacy.d.ts +7 -0
  203. package/dist/identity/postgresPrivacy.js +126 -0
  204. package/dist/identity/privacyHandlers.d.ts +10 -0
  205. package/dist/identity/privacyHandlers.js +35 -0
  206. package/dist/identity/privacyPorts.d.ts +72 -0
  207. package/dist/identity/privacyPorts.js +8 -0
  208. package/dist/identity/privacyUseCases.d.ts +5 -0
  209. package/dist/identity/privacyUseCases.js +55 -0
  210. package/dist/identity/reconcileAccountForPrincipal.d.ts +20 -0
  211. package/dist/identity/reconcileAccountForPrincipal.js +66 -0
  212. package/dist/identity/reconcileAccountHandler.d.ts +11 -0
  213. package/dist/identity/reconcileAccountHandler.js +30 -0
  214. package/dist/identity/removeAdminUserUseCase.d.ts +31 -0
  215. package/dist/identity/removeAdminUserUseCase.js +60 -0
  216. package/dist/identity/response.d.ts +3 -0
  217. package/dist/identity/response.js +2 -0
  218. package/dist/identity/sql.d.ts +44 -0
  219. package/dist/identity/sql.js +10 -0
  220. package/dist/job-ledger/index.d.ts +5 -0
  221. package/dist/job-ledger/index.js +3 -0
  222. package/dist/job-ledger/ports.d.ts +10 -0
  223. package/dist/job-ledger/ports.js +7 -0
  224. package/dist/job-ledger/postgres.d.ts +10 -0
  225. package/dist/job-ledger/postgres.js +101 -0
  226. package/dist/job-ledger/sql.d.ts +7 -0
  227. package/dist/job-ledger/sql.js +10 -0
  228. package/dist/job-ledger/supabase.d.ts +77 -0
  229. package/dist/job-ledger/supabase.js +202 -0
  230. package/dist/kernel/index.d.ts +1 -0
  231. package/dist/kernel/index.js +1 -0
  232. package/dist/kernel/platformKernel.d.ts +34 -0
  233. package/dist/kernel/platformKernel.js +115 -0
  234. package/dist/migrations/index.d.ts +1 -0
  235. package/dist/migrations/index.js +1 -0
  236. package/dist/migrations/postgresRunner.d.ts +50 -0
  237. package/dist/migrations/postgresRunner.js +176 -0
  238. package/dist/scheduler/advisoryLock.d.ts +44 -0
  239. package/dist/scheduler/advisoryLock.js +114 -0
  240. package/dist/scheduler/cronGuard.d.ts +10 -0
  241. package/dist/scheduler/cronGuard.js +19 -0
  242. package/dist/scheduler/cronSecret.d.ts +5 -0
  243. package/dist/scheduler/cronSecret.js +23 -0
  244. package/dist/scheduler/handlers.d.ts +9 -0
  245. package/dist/scheduler/handlers.js +10 -0
  246. package/dist/scheduler/httpEntry.d.ts +16 -0
  247. package/dist/scheduler/httpEntry.js +31 -0
  248. package/dist/scheduler/index.d.ts +9 -0
  249. package/dist/scheduler/index.js +9 -0
  250. package/dist/scheduler/jobRegistry.d.ts +21 -0
  251. package/dist/scheduler/jobRegistry.js +39 -0
  252. package/dist/scheduler/jobs.d.ts +48 -0
  253. package/dist/scheduler/jobs.js +92 -0
  254. package/dist/scheduler/nodeScheduler.d.ts +42 -0
  255. package/dist/scheduler/nodeScheduler.js +73 -0
  256. package/dist/scheduler/vercelScheduler.d.ts +29 -0
  257. package/dist/scheduler/vercelScheduler.js +51 -0
  258. package/package.json +116 -3
  259. package/release-gates.json +143 -0
  260. package/sql/20260809150000_job_run_ledger.sql +301 -0
  261. package/sql/20260809150001_job_run_ledger_v3.sql +70 -0
  262. package/sql/20260810180001_self_host_actor_auth.sql +40 -0
  263. package/sql/20260810204057_customer_identity_read.sql +31 -0
  264. package/sql/20260814090000_customer_selfservice_recovery.sql +477 -0
  265. package/sql/20260901143000_admin_membership_authority_foundation.sql +234 -0
  266. package/sql/20261018120000_identity_operator_invitations.sql +42 -0
  267. package/sql/20261018180000_identity_operator_challenges.sql +56 -0
  268. package/sql/20261018190000_identity_privacy_erasures.sql +15 -0
  269. package/src/bff/dispatch.ts +81 -0
  270. package/src/bff/envelope.ts +142 -0
  271. package/src/bff/health.ts +37 -0
  272. package/src/bff/index.ts +30 -0
  273. package/src/bff/lazyRoute.ts +28 -0
  274. package/src/bff/requestContext.ts +48 -0
  275. package/src/bff/routerRewrite.ts +38 -0
  276. package/src/blob/binding.ts +55 -0
  277. package/src/blob/filesystem.ts +86 -0
  278. package/src/blob/index.ts +17 -0
  279. package/src/blob/s3.ts +87 -0
  280. package/src/blob/s3Client.ts +91 -0
  281. package/src/blob/supabase.ts +88 -0
  282. package/src/blob/vercel.ts +127 -0
  283. package/src/composition/composeBundle.ts +109 -0
  284. package/src/composition/httpBinding.ts +30 -0
  285. package/src/composition/index.ts +17 -0
  286. package/src/composition/nodeHost.ts +289 -0
  287. package/src/data/binding.ts +157 -0
  288. package/src/data/index.ts +33 -0
  289. package/src/data/postgresGateway.ts +186 -0
  290. package/src/data/queryBuilder.ts +300 -0
  291. package/src/data/queryBuilderSql.ts +183 -0
  292. package/src/data/supabaseClientFactory.ts +92 -0
  293. package/src/data/supabaseGateway.ts +76 -0
  294. package/src/http/deadline.ts +117 -0
  295. package/src/http/index.ts +36 -0
  296. package/src/http/requestAdapter.ts +215 -0
  297. package/src/http/runtime.ts +319 -0
  298. package/src/http/security.ts +155 -0
  299. package/src/http/staticAssets.ts +42 -0
  300. package/src/http/types.ts +31 -0
  301. package/src/identity/adminAuthBinding.ts +76 -0
  302. package/src/identity/adminAuthorization.ts +106 -0
  303. package/src/identity/adminContracts.ts +52 -0
  304. package/src/identity/adminMagicLinkHandler.ts +132 -0
  305. package/src/identity/adminMeHandler.ts +64 -0
  306. package/src/identity/adminPreflight.ts +46 -0
  307. package/src/identity/adminUserActionPorts.ts +78 -0
  308. package/src/identity/adminUserHandlers.ts +174 -0
  309. package/src/identity/authVerifyUrl.ts +56 -0
  310. package/src/identity/contracts/contracts.ts +15 -0
  311. package/src/identity/contracts/emailTrust.ts +5 -0
  312. package/src/identity/contracts/index.ts +8 -0
  313. package/src/identity/contracts/oidc.ts +10 -0
  314. package/src/identity/contracts/operatorAuth.ts +61 -0
  315. package/src/identity/contracts/operatorInvitations.ts +32 -0
  316. package/src/identity/contracts/ports.ts +25 -0
  317. package/src/identity/contracts/privacy.ts +86 -0
  318. package/src/identity/contracts/providerList.ts +13 -0
  319. package/src/identity/contracts/types.ts +25 -0
  320. package/src/identity/contribution.ts +29 -0
  321. package/src/identity/customerAuth.ts +3 -0
  322. package/src/identity/customerAuthorization.ts +38 -0
  323. package/src/identity/customerContracts.ts +52 -0
  324. package/src/identity/customerIdentityBinding.ts +125 -0
  325. package/src/identity/customerIdentityVerifier.ts +141 -0
  326. package/src/identity/customerMagicLinkHandler.ts +171 -0
  327. package/src/identity/customerMeHandler.ts +64 -0
  328. package/src/identity/customerPorts.ts +2 -0
  329. package/src/identity/customerSessionBinding.ts +114 -0
  330. package/src/identity/customerSessionIssuer.ts +71 -0
  331. package/src/identity/customerVerifyOtpHandler.ts +44 -0
  332. package/src/identity/directOperatorInvitationStore.ts +178 -0
  333. package/src/identity/emailTrustPolicy.ts +16 -0
  334. package/src/identity/identityPersonalDataContributor.ts +48 -0
  335. package/src/identity/identityReadiness.ts +26 -0
  336. package/src/identity/index.ts +69 -0
  337. package/src/identity/inviteAdminUserUseCase.ts +134 -0
  338. package/src/identity/jwtLibrary.ts +24 -0
  339. package/src/identity/machineActorWriteFence.ts +19 -0
  340. package/src/identity/magicLinkPorts.ts +7 -0
  341. package/src/identity/managedAccountLinkStore.ts +105 -0
  342. package/src/identity/managedAdminAuthVerifier.ts +40 -0
  343. package/src/identity/managedAdminUserGateways.ts +164 -0
  344. package/src/identity/managedClient.ts +58 -0
  345. package/src/identity/managedClientAuthLink.ts +120 -0
  346. package/src/identity/managedCustomerMe.ts +52 -0
  347. package/src/identity/managedEmailTrustPolicy.ts +90 -0
  348. package/src/identity/managedIdentityVerifier.ts +20 -0
  349. package/src/identity/managedPrivacy.ts +37 -0
  350. package/src/identity/messages.ts +41 -0
  351. package/src/identity/oidcIdentityVerifier.ts +229 -0
  352. package/src/identity/oidcPrincipal.ts +10 -0
  353. package/src/identity/operatorAdminAuth.ts +14 -0
  354. package/src/identity/operatorAuthHandlers.ts +52 -0
  355. package/src/identity/operatorIdentityVerifier.ts +19 -0
  356. package/src/identity/operatorInvitationLifecycle.ts +14 -0
  357. package/src/identity/operatorInvitationPorts.ts +11 -0
  358. package/src/identity/operatorPorts.ts +11 -0
  359. package/src/identity/operatorSession.ts +30 -0
  360. package/src/identity/operatorTokenAdminAuth.ts +79 -0
  361. package/src/identity/personalDataRegistry.ts +8 -0
  362. package/src/identity/platformAdminAuth.ts +7 -0
  363. package/src/identity/ports.ts +158 -0
  364. package/src/identity/postgresAccountLinkStore.ts +49 -0
  365. package/src/identity/postgresCustomerMe.ts +33 -0
  366. package/src/identity/postgresCustomerRecovery.ts +72 -0
  367. package/src/identity/postgresOperatorIdentity.ts +123 -0
  368. package/src/identity/postgresPrivacy.ts +117 -0
  369. package/src/identity/privacyHandlers.ts +33 -0
  370. package/src/identity/privacyPorts.ts +52 -0
  371. package/src/identity/privacyUseCases.ts +48 -0
  372. package/src/identity/reconcileAccountForPrincipal.ts +99 -0
  373. package/src/identity/reconcileAccountHandler.ts +36 -0
  374. package/src/identity/removeAdminUserUseCase.ts +85 -0
  375. package/src/identity/response.ts +3 -0
  376. package/src/identity/sql.ts +10 -0
  377. package/src/job-ledger/index.ts +25 -0
  378. package/src/job-ledger/ports.ts +27 -0
  379. package/src/job-ledger/postgres.ts +121 -0
  380. package/src/job-ledger/sql.ts +12 -0
  381. package/src/job-ledger/supabase.ts +294 -0
  382. package/src/kernel/index.ts +17 -0
  383. package/src/kernel/platformKernel.ts +153 -0
  384. package/src/migrations/index.ts +10 -0
  385. package/src/migrations/postgresRunner.ts +255 -0
  386. package/src/scheduler/advisoryLock.ts +145 -0
  387. package/src/scheduler/cronGuard.ts +30 -0
  388. package/src/scheduler/cronSecret.ts +26 -0
  389. package/src/scheduler/handlers.ts +24 -0
  390. package/src/scheduler/httpEntry.ts +49 -0
  391. package/src/scheduler/index.ts +47 -0
  392. package/src/scheduler/jobRegistry.ts +57 -0
  393. package/src/scheduler/jobs.ts +119 -0
  394. package/src/scheduler/nodeScheduler.ts +123 -0
  395. package/src/scheduler/vercelScheduler.ts +71 -0
@@ -0,0 +1,477 @@
1
+ -- Portable customer self-service recovery forward.
2
+ --
3
+ -- This delta closes the reference bundle's identity-issuance gap and connects
4
+ -- an authenticated customer to two portable recovery actions: communication
5
+ -- consent and repayment of their own still-open order through the existing
6
+ -- captured settlement rail. It stores challenge and recovery token hashes,
7
+ -- never raw credentials, message bodies, recipient addresses, provider
8
+ -- payloads or payment-method artifacts.
9
+ --
10
+ -- The application owns challenge delivery and ES256 signing. PostgreSQL owns
11
+ -- single consumption, principal linking, actor ownership, preference history,
12
+ -- order-token authority and settlement idempotency. The only direct payment
13
+ -- action is the already-published provider-neutral settlement; no gateway,
14
+ -- webhook, saved-card or provider-attempt record is fabricated here.
15
+ --
16
+ -- openlup:allow-security-definer: the three authenticated actor wrappers derive
17
+ -- the principal only from auth.uid() and expose fixed response shapes without
18
+ -- granting customer table DML.
19
+ -- openlup:allow-grant: authenticated receives EXECUTE only on the bounded
20
+ -- preference read/write and recovery-token issue wrappers.
21
+ -- openlup:allow-rls: preference state and events are actor-owned; tables remain
22
+ -- inaccessible and the wrappers are the only customer surface.
23
+
24
+ CREATE TABLE public.customer_identity_challenges (
25
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
26
+ client_id uuid NOT NULL REFERENCES public.clients(id) ON DELETE CASCADE,
27
+ principal_id uuid NOT NULL,
28
+ email_fingerprint text NOT NULL,
29
+ token_hash text NOT NULL,
30
+ expires_at timestamptz NOT NULL,
31
+ used_at timestamptz,
32
+ created_at timestamptz NOT NULL DEFAULT now(),
33
+ CONSTRAINT customer_identity_challenges_email_fingerprint_check
34
+ CHECK (email_fingerprint ~ '^[0-9a-f]{64}$'),
35
+ CONSTRAINT customer_identity_challenges_token_hash_check
36
+ CHECK (token_hash ~ '^[0-9a-f]{64}$'),
37
+ CONSTRAINT customer_identity_challenges_expiry_check CHECK (expires_at > created_at),
38
+ CONSTRAINT customer_identity_challenges_token_hash_key UNIQUE (token_hash)
39
+ );
40
+
41
+ CREATE INDEX customer_identity_challenges_client_created_idx
42
+ ON public.customer_identity_challenges (client_id, created_at DESC);
43
+
44
+ CREATE TABLE public.customer_communication_preferences (
45
+ principal_id uuid PRIMARY KEY,
46
+ marketing_newsletter_consent boolean NOT NULL DEFAULT false,
47
+ revision integer NOT NULL DEFAULT 1,
48
+ updated_at timestamptz NOT NULL DEFAULT now(),
49
+ CONSTRAINT customer_communication_preferences_revision_check CHECK (revision > 0)
50
+ );
51
+
52
+ CREATE TABLE public.customer_communication_preference_events (
53
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
54
+ principal_id uuid NOT NULL,
55
+ revision integer NOT NULL,
56
+ marketing_newsletter_consent boolean NOT NULL,
57
+ occurred_at timestamptz NOT NULL DEFAULT now(),
58
+ CONSTRAINT customer_communication_preference_events_revision_check CHECK (revision > 0),
59
+ CONSTRAINT customer_communication_preference_events_principal_revision_key
60
+ UNIQUE (principal_id, revision)
61
+ );
62
+
63
+ CREATE TABLE public.commerce_checkout_recovery_tokens (
64
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
65
+ order_id uuid NOT NULL REFERENCES public.commerce_orders(id) ON DELETE CASCADE,
66
+ client_id uuid NOT NULL REFERENCES public.clients(id) ON DELETE CASCADE,
67
+ token_hash text NOT NULL,
68
+ expires_at timestamptz NOT NULL,
69
+ revoked_at timestamptz,
70
+ created_at timestamptz NOT NULL DEFAULT now(),
71
+ CONSTRAINT commerce_checkout_recovery_tokens_token_hash_check
72
+ CHECK (token_hash ~ '^[0-9a-f]{64}$'),
73
+ CONSTRAINT commerce_checkout_recovery_tokens_expiry_check CHECK (expires_at > created_at),
74
+ CONSTRAINT commerce_checkout_recovery_tokens_token_hash_key UNIQUE (token_hash)
75
+ );
76
+
77
+ CREATE UNIQUE INDEX commerce_checkout_recovery_tokens_active_order_idx
78
+ ON public.commerce_checkout_recovery_tokens (order_id)
79
+ WHERE revoked_at IS NULL;
80
+
81
+ ALTER TABLE public.customer_communication_preferences ENABLE ROW LEVEL SECURITY;
82
+ ALTER TABLE public.customer_communication_preference_events ENABLE ROW LEVEL SECURITY;
83
+
84
+ REVOKE ALL ON TABLE public.customer_identity_challenges FROM PUBLIC, anon, authenticated;
85
+ REVOKE ALL ON TABLE public.customer_communication_preferences FROM PUBLIC, anon, authenticated;
86
+ REVOKE ALL ON TABLE public.customer_communication_preference_events FROM PUBLIC, anon, authenticated;
87
+ REVOKE ALL ON TABLE public.commerce_checkout_recovery_tokens FROM PUBLIC, anon, authenticated;
88
+
89
+ CREATE FUNCTION public.customer_identity_challenge_issue(
90
+ p_email text,
91
+ p_token_hash text,
92
+ p_expires_at timestamptz,
93
+ p_now timestamptz DEFAULT now()
94
+ )
95
+ RETURNS jsonb
96
+ LANGUAGE plpgsql
97
+ SET search_path = public, pg_catalog
98
+ AS $$
99
+ DECLARE
100
+ v_client public.clients%ROWTYPE;
101
+ v_principal_id uuid;
102
+ v_challenge_id uuid;
103
+ v_email text;
104
+ BEGIN
105
+ v_email := lower(btrim(COALESCE(p_email, '')));
106
+ IF char_length(v_email) < 3 OR char_length(v_email) > 320
107
+ OR p_token_hash !~ '^[0-9a-f]{64}$'
108
+ OR p_expires_at <= p_now OR p_expires_at > p_now + interval '30 minutes' THEN
109
+ RAISE EXCEPTION 'customer_identity_challenge_invalid_input' USING ERRCODE = '22023';
110
+ END IF;
111
+
112
+ SELECT * INTO v_client FROM public.clients
113
+ WHERE lower(email) = v_email
114
+ LIMIT 1;
115
+ IF NOT FOUND THEN
116
+ RETURN jsonb_build_object('deliverable', false);
117
+ END IF;
118
+
119
+ IF EXISTS (
120
+ SELECT 1 FROM public.customer_identity_challenges
121
+ WHERE client_id = v_client.id AND created_at > p_now - interval '60 seconds'
122
+ ) THEN
123
+ RETURN jsonb_build_object('deliverable', false);
124
+ END IF;
125
+
126
+ v_principal_id := COALESCE(v_client.principal_id, gen_random_uuid());
127
+ INSERT INTO public.customer_identity_challenges
128
+ (client_id, principal_id, email_fingerprint, token_hash, expires_at, created_at)
129
+ VALUES (
130
+ v_client.id,
131
+ v_principal_id,
132
+ encode(sha256(convert_to(v_email, 'UTF8')), 'hex'),
133
+ p_token_hash,
134
+ p_expires_at,
135
+ p_now
136
+ )
137
+ RETURNING id INTO v_challenge_id;
138
+
139
+ RETURN jsonb_build_object('deliverable', true, 'challengeId', v_challenge_id);
140
+ END;
141
+ $$;
142
+
143
+ CREATE FUNCTION public.customer_identity_challenge_redeem(
144
+ p_token_hash text,
145
+ p_now timestamptz DEFAULT now()
146
+ )
147
+ RETURNS jsonb
148
+ LANGUAGE plpgsql
149
+ SET search_path = public, pg_catalog
150
+ AS $$
151
+ DECLARE
152
+ v_challenge public.customer_identity_challenges%ROWTYPE;
153
+ v_current_principal uuid;
154
+ BEGIN
155
+ IF p_token_hash !~ '^[0-9a-f]{64}$' THEN RETURN NULL; END IF;
156
+
157
+ SELECT * INTO v_challenge FROM public.customer_identity_challenges
158
+ WHERE token_hash = p_token_hash FOR UPDATE;
159
+ IF NOT FOUND OR v_challenge.used_at IS NOT NULL OR v_challenge.expires_at <= p_now THEN
160
+ RETURN NULL;
161
+ END IF;
162
+
163
+ SELECT principal_id INTO v_current_principal FROM public.clients
164
+ WHERE id = v_challenge.client_id FOR UPDATE;
165
+ IF v_current_principal IS NOT NULL AND v_current_principal <> v_challenge.principal_id THEN
166
+ RAISE EXCEPTION 'customer_identity_principal_conflict' USING ERRCODE = '23505';
167
+ END IF;
168
+
169
+ UPDATE public.clients
170
+ SET principal_id = v_challenge.principal_id, updated_at = p_now
171
+ WHERE id = v_challenge.client_id;
172
+ UPDATE public.customer_identity_challenges SET used_at = p_now WHERE id = v_challenge.id;
173
+ RETURN jsonb_build_object(
174
+ 'principalId', v_challenge.principal_id,
175
+ 'email', lower((SELECT email FROM public.clients WHERE id = v_challenge.client_id)));
176
+ END;
177
+ $$;
178
+
179
+ CREATE FUNCTION public.customer_communication_preferences_as_actor()
180
+ RETURNS jsonb
181
+ LANGUAGE sql
182
+ STABLE
183
+ SECURITY DEFINER
184
+ SET search_path = public, auth, pg_catalog
185
+ AS $$
186
+ SELECT CASE WHEN client.id IS NULL THEN NULL ELSE jsonb_build_object(
187
+ 'contractVersion', 'customer.communication_preferences.v1',
188
+ 'contact', jsonb_build_object('contactId', client.id, 'email', lower(client.email)),
189
+ 'marketingNewsletter', jsonb_build_object(
190
+ 'purpose', 'marketing_newsletter',
191
+ 'state', CASE
192
+ WHEN preference.principal_id IS NULL THEN 'unknown'
193
+ WHEN preference.marketing_newsletter_consent THEN 'granted'
194
+ ELSE 'denied'
195
+ END,
196
+ 'granted', COALESCE(preference.marketing_newsletter_consent, false),
197
+ 'source', CASE WHEN preference.principal_id IS NULL THEN NULL ELSE 'customer_communication_preferences' END,
198
+ 'reason', CASE
199
+ WHEN preference.principal_id IS NULL THEN NULL
200
+ WHEN preference.marketing_newsletter_consent THEN 'customer_self_service_grant'
201
+ ELSE 'customer_self_service_denial'
202
+ END,
203
+ 'capturedAt', preference.updated_at,
204
+ 'updatedAt', preference.updated_at)) END
205
+ FROM (SELECT auth.uid() AS principal_id) actor
206
+ LEFT JOIN public.clients client ON client.principal_id = actor.principal_id
207
+ LEFT JOIN public.customer_communication_preferences preference
208
+ ON preference.principal_id = actor.principal_id;
209
+ $$;
210
+
211
+ CREATE FUNCTION public.customer_communication_preferences_set_as_actor(
212
+ p_marketing_newsletter_consent boolean,
213
+ p_now timestamptz DEFAULT now()
214
+ )
215
+ RETURNS jsonb
216
+ LANGUAGE plpgsql
217
+ SECURITY DEFINER
218
+ SET search_path = public, auth, pg_catalog
219
+ AS $$
220
+ DECLARE
221
+ v_principal_id uuid := auth.uid();
222
+ v_revision integer;
223
+ BEGIN
224
+ IF v_principal_id IS NULL OR NOT EXISTS (
225
+ SELECT 1 FROM public.clients WHERE principal_id = v_principal_id
226
+ ) THEN
227
+ RETURN NULL;
228
+ END IF;
229
+
230
+ INSERT INTO public.customer_communication_preferences
231
+ (principal_id, marketing_newsletter_consent, revision, updated_at)
232
+ VALUES (v_principal_id, p_marketing_newsletter_consent, 1, p_now)
233
+ ON CONFLICT (principal_id) DO UPDATE
234
+ SET marketing_newsletter_consent = EXCLUDED.marketing_newsletter_consent,
235
+ revision = CASE
236
+ WHEN public.customer_communication_preferences.marketing_newsletter_consent
237
+ IS DISTINCT FROM EXCLUDED.marketing_newsletter_consent
238
+ THEN public.customer_communication_preferences.revision + 1
239
+ ELSE public.customer_communication_preferences.revision
240
+ END,
241
+ updated_at = CASE
242
+ WHEN public.customer_communication_preferences.marketing_newsletter_consent
243
+ IS DISTINCT FROM EXCLUDED.marketing_newsletter_consent
244
+ THEN EXCLUDED.updated_at
245
+ ELSE public.customer_communication_preferences.updated_at
246
+ END
247
+ RETURNING revision INTO v_revision;
248
+
249
+ INSERT INTO public.customer_communication_preference_events
250
+ (principal_id, revision, marketing_newsletter_consent, occurred_at)
251
+ VALUES (v_principal_id, v_revision, p_marketing_newsletter_consent, p_now)
252
+ ON CONFLICT (principal_id, revision) DO NOTHING;
253
+
254
+ RETURN public.customer_communication_preferences_as_actor();
255
+ END;
256
+ $$;
257
+
258
+ CREATE FUNCTION public.customer_checkout_recovery_token_issue_as_actor(
259
+ p_order_id uuid,
260
+ p_token_hash text,
261
+ p_expires_at timestamptz,
262
+ p_now timestamptz DEFAULT now()
263
+ )
264
+ RETURNS uuid
265
+ LANGUAGE plpgsql
266
+ SECURITY DEFINER
267
+ SET search_path = public, auth, pg_catalog
268
+ AS $$
269
+ DECLARE
270
+ v_client_id uuid;
271
+ v_token_id uuid;
272
+ BEGIN
273
+ IF auth.uid() IS NULL OR p_token_hash !~ '^[0-9a-f]{64}$'
274
+ OR p_expires_at <= p_now OR p_expires_at > p_now + interval '24 hours' THEN
275
+ RAISE EXCEPTION 'customer_checkout_recovery_invalid_input' USING ERRCODE = '22023';
276
+ END IF;
277
+
278
+ SELECT order_row.client_id INTO v_client_id
279
+ FROM public.commerce_orders order_row
280
+ JOIN public.clients client ON client.id = order_row.client_id
281
+ WHERE order_row.id = p_order_id
282
+ AND order_row.status = 'pending_payment'
283
+ AND client.principal_id = auth.uid()
284
+ FOR UPDATE OF order_row;
285
+ IF NOT FOUND OR v_client_id IS NULL THEN
286
+ RAISE EXCEPTION 'customer_checkout_recovery_order_not_recoverable' USING ERRCODE = '22023';
287
+ END IF;
288
+
289
+ UPDATE public.commerce_checkout_recovery_tokens
290
+ SET revoked_at = p_now
291
+ WHERE order_id = p_order_id AND revoked_at IS NULL;
292
+ INSERT INTO public.commerce_checkout_recovery_tokens
293
+ (order_id, client_id, token_hash, expires_at, created_at)
294
+ VALUES (p_order_id, v_client_id, p_token_hash, p_expires_at, p_now)
295
+ RETURNING id INTO v_token_id;
296
+ RETURN v_token_id;
297
+ END;
298
+ $$;
299
+
300
+ CREATE FUNCTION public.customer_checkout_recovery_find_as_actor(
301
+ p_order_id uuid DEFAULT NULL,
302
+ p_subscription_id uuid DEFAULT NULL
303
+ )
304
+ RETURNS jsonb
305
+ LANGUAGE sql
306
+ STABLE
307
+ SECURITY DEFINER
308
+ SET search_path = public, auth, pg_catalog
309
+ AS $$
310
+ SELECT jsonb_build_object(
311
+ 'orderId', order_row.id,
312
+ 'createdAt', order_row.created_at,
313
+ 'mode', CASE WHEN order_row.subscription_cycle_id IS NULL THEN 'one_time_order' ELSE 'subscription_cycle' END,
314
+ 'subscriptionId', cycle.subscription_id,
315
+ 'clientHasLiveOrPendingSubscription', EXISTS (
316
+ SELECT 1 FROM public.subscriptions active_subscription
317
+ WHERE active_subscription.client_id = order_row.client_id
318
+ AND active_subscription.status IN ('active', 'paused')))
319
+ FROM public.commerce_orders order_row
320
+ JOIN public.clients client ON client.id = order_row.client_id
321
+ LEFT JOIN public.subscription_cycles cycle ON cycle.id = order_row.subscription_cycle_id
322
+ WHERE client.principal_id = auth.uid()
323
+ AND order_row.status = 'pending_payment'
324
+ AND ((p_order_id IS NOT NULL AND order_row.id = p_order_id)
325
+ OR (p_order_id IS NULL AND p_subscription_id IS NOT NULL AND cycle.subscription_id = p_subscription_id))
326
+ ORDER BY order_row.created_at DESC
327
+ LIMIT 1;
328
+ $$;
329
+
330
+ CREATE FUNCTION public.customer_has_live_subscription_as_actor()
331
+ RETURNS boolean
332
+ LANGUAGE sql
333
+ STABLE
334
+ SECURITY DEFINER
335
+ SET search_path = public, auth, pg_catalog
336
+ AS $$
337
+ SELECT EXISTS (
338
+ SELECT 1 FROM public.subscriptions subscription
339
+ JOIN public.clients client ON client.id = subscription.client_id
340
+ WHERE client.principal_id = auth.uid()
341
+ AND subscription.status IN ('active', 'paused'));
342
+ $$;
343
+
344
+ CREATE FUNCTION public.customer_checkout_recovery_token_inspect(
345
+ p_token_hash text,
346
+ p_now timestamptz DEFAULT now()
347
+ )
348
+ RETURNS jsonb
349
+ LANGUAGE sql
350
+ STABLE
351
+ SET search_path = public, pg_catalog
352
+ AS $$
353
+ SELECT jsonb_build_object(
354
+ 'tokenId', token.id,
355
+ 'orderId', token.order_id,
356
+ 'clientId', token.client_id,
357
+ 'mode', CASE WHEN order_row.subscription_cycle_id IS NULL THEN 'one_time_order' ELSE 'subscription_cycle' END,
358
+ 'status', order_row.status,
359
+ 'subscriptionId', cycle.subscription_id,
360
+ 'tokenState', CASE
361
+ WHEN token.revoked_at IS NOT NULL THEN 'revoked'
362
+ WHEN token.expires_at <= p_now THEN 'expired'
363
+ WHEN order_row.status <> 'pending_payment' THEN 'consumed'
364
+ ELSE 'active'
365
+ END)
366
+ FROM public.commerce_checkout_recovery_tokens token
367
+ JOIN public.commerce_orders order_row ON order_row.id = token.order_id
368
+ LEFT JOIN public.subscription_cycles cycle ON cycle.id = order_row.subscription_cycle_id
369
+ WHERE token.token_hash = p_token_hash;
370
+ $$;
371
+
372
+ CREATE FUNCTION public.customer_checkout_recovery_order(p_order_id uuid)
373
+ RETURNS jsonb
374
+ LANGUAGE sql
375
+ STABLE
376
+ SET search_path = public, pg_catalog
377
+ AS $$
378
+ SELECT jsonb_build_object(
379
+ 'orderId', order_row.id,
380
+ 'clientId', order_row.client_id,
381
+ 'status', order_row.status,
382
+ 'mode', CASE WHEN order_row.subscription_cycle_id IS NULL THEN 'one_time_order' ELSE 'subscription_cycle' END,
383
+ 'totalMinor', order_row.total_amount_minor,
384
+ 'currency', order_row.currency_code,
385
+ 'createdAt', order_row.created_at,
386
+ 'subscriptionId', cycle.subscription_id,
387
+ 'subscriptionCycleId', order_row.subscription_cycle_id,
388
+ 'paymentIntentId', intent.id,
389
+ 'paymentIntentStatus', CASE intent.status
390
+ WHEN 'created' THEN 'pending'
391
+ WHEN 'settled' THEN 'succeeded'
392
+ ELSE 'failed'
393
+ END,
394
+ 'customerEmail', client.email)
395
+ FROM public.commerce_orders order_row
396
+ JOIN public.clients client ON client.id = order_row.client_id
397
+ LEFT JOIN public.subscription_cycles cycle ON cycle.id = order_row.subscription_cycle_id
398
+ LEFT JOIN public.commerce_settlement_intents intent ON intent.order_id = order_row.id
399
+ WHERE order_row.id = p_order_id;
400
+ $$;
401
+
402
+ CREATE FUNCTION public.customer_checkout_recovery_settle(
403
+ p_token_hash text,
404
+ p_idempotency_key text,
405
+ p_now timestamptz DEFAULT now()
406
+ )
407
+ RETURNS jsonb
408
+ LANGUAGE plpgsql
409
+ SET search_path = public, pg_catalog
410
+ AS $$
411
+ DECLARE
412
+ v_token public.commerce_checkout_recovery_tokens%ROWTYPE;
413
+ v_order public.commerce_orders%ROWTYPE;
414
+ v_intent public.commerce_settlement_intents%ROWTYPE;
415
+ v_result jsonb;
416
+ v_external_ref text;
417
+ BEGIN
418
+ IF p_token_hash !~ '^[0-9a-f]{64}$'
419
+ OR char_length(btrim(COALESCE(p_idempotency_key, ''))) < 8 THEN
420
+ RAISE EXCEPTION 'customer_checkout_recovery_settle_invalid_input' USING ERRCODE = '22023';
421
+ END IF;
422
+
423
+ SELECT * INTO v_token FROM public.commerce_checkout_recovery_tokens
424
+ WHERE token_hash = p_token_hash FOR UPDATE;
425
+ IF NOT FOUND OR v_token.revoked_at IS NOT NULL OR v_token.expires_at <= p_now THEN
426
+ RAISE EXCEPTION 'customer_checkout_recovery_token_invalid' USING ERRCODE = '22023';
427
+ END IF;
428
+
429
+ SELECT * INTO v_order FROM public.commerce_orders
430
+ WHERE id = v_token.order_id FOR UPDATE;
431
+ IF NOT FOUND THEN
432
+ RAISE EXCEPTION 'customer_checkout_recovery_order_not_recoverable' USING ERRCODE = '22023';
433
+ END IF;
434
+
435
+ SELECT * INTO v_intent FROM public.commerce_settlement_intents
436
+ WHERE order_id = v_order.id FOR UPDATE;
437
+ IF NOT FOUND THEN
438
+ RAISE EXCEPTION 'customer_checkout_recovery_intent_not_recoverable' USING ERRCODE = '22023';
439
+ END IF;
440
+
441
+ v_external_ref := 'captured-' || v_intent.id::text;
442
+ -- The lower rail reads its append-only transition before checking current
443
+ -- intent/order state. That preserves an exact-key replay after a successful
444
+ -- first call while a different key still fails closed on the settled order.
445
+ v_result := public.commerce_record_settlement(
446
+ p_idempotency_key || ':settle', v_intent.id, 'succeeded', v_external_ref,
447
+ jsonb_build_object('source', 'customer.checkout_recovery.v1'), p_now);
448
+
449
+ RETURN jsonb_build_object(
450
+ 'orderId', v_order.id,
451
+ 'paymentIntentId', v_intent.id,
452
+ 'clientId', v_token.client_id,
453
+ 'status', 'paid',
454
+ 'paymentAttemptId', NULL,
455
+ 'provider', 'hidden_rehearsal',
456
+ 'providerPaymentId', v_external_ref,
457
+ 'clientAction', jsonb_build_object('kind', 'none'),
458
+ 'replayed', COALESCE((v_result->>'replayed')::boolean, false));
459
+ END;
460
+ $$;
461
+
462
+ REVOKE ALL ON FUNCTION public.customer_identity_challenge_issue(text, text, timestamptz, timestamptz) FROM PUBLIC, anon, authenticated;
463
+ REVOKE ALL ON FUNCTION public.customer_identity_challenge_redeem(text, timestamptz) FROM PUBLIC, anon, authenticated;
464
+ REVOKE ALL ON FUNCTION public.customer_checkout_recovery_token_inspect(text, timestamptz) FROM PUBLIC, anon, authenticated;
465
+ REVOKE ALL ON FUNCTION public.customer_checkout_recovery_order(uuid) FROM PUBLIC, anon, authenticated;
466
+ REVOKE ALL ON FUNCTION public.customer_checkout_recovery_settle(text, text, timestamptz) FROM PUBLIC, anon, authenticated;
467
+ REVOKE ALL ON FUNCTION public.customer_communication_preferences_as_actor() FROM PUBLIC, anon, authenticated;
468
+ REVOKE ALL ON FUNCTION public.customer_communication_preferences_set_as_actor(boolean, timestamptz) FROM PUBLIC, anon, authenticated;
469
+ REVOKE ALL ON FUNCTION public.customer_checkout_recovery_token_issue_as_actor(uuid, text, timestamptz, timestamptz) FROM PUBLIC, anon, authenticated;
470
+ REVOKE ALL ON FUNCTION public.customer_checkout_recovery_find_as_actor(uuid, uuid) FROM PUBLIC, anon, authenticated;
471
+ REVOKE ALL ON FUNCTION public.customer_has_live_subscription_as_actor() FROM PUBLIC, anon, authenticated;
472
+
473
+ GRANT EXECUTE ON FUNCTION public.customer_communication_preferences_as_actor() TO authenticated;
474
+ GRANT EXECUTE ON FUNCTION public.customer_communication_preferences_set_as_actor(boolean, timestamptz) TO authenticated;
475
+ GRANT EXECUTE ON FUNCTION public.customer_checkout_recovery_token_issue_as_actor(uuid, text, timestamptz, timestamptz) TO authenticated;
476
+ GRANT EXECUTE ON FUNCTION public.customer_checkout_recovery_find_as_actor(uuid, uuid) TO authenticated;
477
+ GRANT EXECUTE ON FUNCTION public.customer_has_live_subscription_as_actor() TO authenticated;