@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,123 @@
1
+ import type { AdminUserInviteRole } from "./inviteAdminUserUseCase.js";
2
+ import type { ManagedOperatorMembershipResult, OperatorInvitationConflict } from "./contracts/operatorInvitations.js";
3
+ import type { InviteAdminUserGateway } from "./inviteAdminUserUseCase.js";
4
+ import type { RemoveAdminUserGateway } from "./removeAdminUserUseCase.js";
5
+ interface InviteAdminUserQuery {
6
+ insert(row: {
7
+ id: string;
8
+ email: string;
9
+ role: AdminUserInviteRole;
10
+ membership_state: "active";
11
+ membership_provenance: "invitation";
12
+ membership_accepted_at: string;
13
+ }): PromiseLike<{
14
+ error: {
15
+ code?: string;
16
+ message?: string;
17
+ } | null;
18
+ }>;
19
+ select(columns: string): {
20
+ eq(column: string, value: string): {
21
+ maybeSingle(): PromiseLike<{
22
+ data: {
23
+ id: string;
24
+ role?: string;
25
+ membership_state?: string;
26
+ is_machine_actor?: boolean | null;
27
+ } | null;
28
+ error?: unknown;
29
+ }>;
30
+ };
31
+ };
32
+ }
33
+ export interface InviteAdminUserClient {
34
+ auth: {
35
+ getUser(token: string): PromiseLike<{
36
+ data: {
37
+ user: {
38
+ id: string;
39
+ } | null;
40
+ };
41
+ error: unknown;
42
+ }>;
43
+ admin: {
44
+ listUsers(options: {
45
+ page: number;
46
+ perPage: number;
47
+ }): PromiseLike<{
48
+ data: {
49
+ users: Array<{
50
+ id: string;
51
+ email?: string | null;
52
+ }>;
53
+ nextPage?: number | null;
54
+ } | null;
55
+ error: unknown;
56
+ }>;
57
+ inviteUserByEmail(email: string, options: {
58
+ redirectTo: string;
59
+ }): PromiseLike<{
60
+ data: {
61
+ user: {
62
+ id: string;
63
+ } | null;
64
+ };
65
+ error: {
66
+ message: string;
67
+ } | null;
68
+ }>;
69
+ };
70
+ };
71
+ from(table: "admin_users"): InviteAdminUserQuery;
72
+ }
73
+ interface RemoveAdminUserQuery {
74
+ select(columns: string): {
75
+ eq(column: string, value: string): RemoveAdminUserQueryResult;
76
+ };
77
+ }
78
+ interface RemoveAdminUserQueryResult {
79
+ eq(column: string, value: string): RemoveAdminUserQueryResult;
80
+ maybeSingle(): PromiseLike<{
81
+ data: {
82
+ id: string;
83
+ role: string;
84
+ } | null;
85
+ error: {
86
+ message: string;
87
+ } | null;
88
+ }>;
89
+ }
90
+ export interface RemoveAdminUserClient {
91
+ auth: {
92
+ getUser(token: string): PromiseLike<{
93
+ data: {
94
+ user: {
95
+ id: string;
96
+ } | null;
97
+ };
98
+ error: unknown;
99
+ }>;
100
+ };
101
+ from(table: "admin_users"): RemoveAdminUserQuery;
102
+ rpc(fn: "admin_revoke_admin_user", args: {
103
+ p_target: string;
104
+ p_reason: string | null;
105
+ }): PromiseLike<{
106
+ error: {
107
+ message: string;
108
+ } | null;
109
+ }>;
110
+ }
111
+ export declare function createInviteAdminUserGateway(clientFactory: () => InviteAdminUserClient): InviteAdminUserGateway & {
112
+ activateMembership(input: {
113
+ principalId: string;
114
+ email: string;
115
+ role: AdminUserInviteRole;
116
+ }): Promise<ManagedOperatorMembershipResult | {
117
+ code: OperatorInvitationConflict;
118
+ }>;
119
+ };
120
+ export declare function createRemoveAdminUserGateway(clientFactory: () => RemoveAdminUserClient): RemoveAdminUserGateway;
121
+ /** Managed eligibility depends only on active native membership and known roles. */
122
+ export declare function managedOperatorMagicLinkEligibility(rawClient: unknown, email: string): Promise<"eligible" | "not_allowlisted" | "role_not_allowed">;
123
+ export {};
@@ -0,0 +1,127 @@
1
+ export function createInviteAdminUserGateway(clientFactory) {
2
+ let client = null;
3
+ const getClient = () => client ??= clientFactory();
4
+ async function membership(principalId) {
5
+ const { data, error } = await getClient().from("admin_users").select("id, role, membership_state, is_machine_actor").eq("id", principalId).maybeSingle();
6
+ if (error)
7
+ throw error;
8
+ return data;
9
+ }
10
+ function existing(row, role) {
11
+ if (row.is_machine_actor !== false)
12
+ return { code: "IDENTITY_CONFLICT" };
13
+ if (row.membership_state === "revoked")
14
+ return { code: "MANAGED_REINVITE_UNSUPPORTED" };
15
+ if (row.membership_state !== "active")
16
+ return { code: "IDENTITY_CONFLICT" };
17
+ if (row.role !== role)
18
+ return { code: "INVITATION_ROLE_CONFLICT" };
19
+ return { principalId: row.id, role, membershipState: "active", code: "ALREADY_ACTIVE" };
20
+ }
21
+ return {
22
+ async activateMembership(input) {
23
+ const before = await membership(input.principalId);
24
+ if (before)
25
+ return existing(before, input.role);
26
+ const { error } = await getClient().from("admin_users").insert({ id: input.principalId, email: input.email, role: input.role,
27
+ membership_state: "active", membership_provenance: "invitation", membership_accepted_at: new Date().toISOString() });
28
+ if (error) {
29
+ if (error.code !== "23505")
30
+ throw error;
31
+ const raced = await membership(input.principalId);
32
+ if (!raced)
33
+ throw error;
34
+ return existing(raced, input.role);
35
+ }
36
+ return { principalId: input.principalId, role: input.role, membershipState: "active", code: "MEMBERSHIP_CREATED" };
37
+ },
38
+ async getUser(accessToken) {
39
+ const { data, error } = await getClient().auth.getUser(accessToken);
40
+ return { user: data?.user ?? null, error };
41
+ },
42
+ async findAdminUser(userId) {
43
+ const { data, error } = await getClient()
44
+ .from("admin_users")
45
+ .select("id, role, membership_state, is_machine_actor")
46
+ .eq("id", userId)
47
+ .maybeSingle();
48
+ if (error)
49
+ throw error;
50
+ return data && typeof data.role === "string" && typeof data.membership_state === "string" ? { id: data.id, role: data.role, membership_state: data.membership_state, is_machine_actor: data.is_machine_actor !== false } : null;
51
+ },
52
+ async findAdminUserByEmail(email) {
53
+ const { data, error } = await getClient()
54
+ .from("admin_users")
55
+ .select("id")
56
+ .eq("email", email)
57
+ .maybeSingle();
58
+ if (error)
59
+ throw error;
60
+ return data ? { id: data.id } : null;
61
+ },
62
+ async findAuthUserByEmail(email) {
63
+ const normalizedEmail = email.trim().toLowerCase();
64
+ const perPage = 1000;
65
+ const maxUsers = 5000;
66
+ let page = 1;
67
+ let scanned = 0;
68
+ while (scanned < maxUsers) {
69
+ const { data, error } = await getClient().auth.admin.listUsers({ page, perPage });
70
+ if (error)
71
+ throw error;
72
+ const users = data?.users ?? [];
73
+ const match = users.find((user) => (user.email ?? "").trim().toLowerCase() === normalizedEmail);
74
+ if (match)
75
+ return { id: match.id, email: match.email };
76
+ scanned += users.length;
77
+ if (!data?.nextPage)
78
+ return null;
79
+ page = data.nextPage;
80
+ }
81
+ throw new Error("auth_user_lookup_cap_exceeded");
82
+ },
83
+ async inviteAuthUser(input) {
84
+ const { data, error } = await getClient().auth.admin.inviteUserByEmail(input.email, {
85
+ redirectTo: input.redirectTo,
86
+ });
87
+ return { user: data.user, error };
88
+ },
89
+ };
90
+ }
91
+ export function createRemoveAdminUserGateway(clientFactory) {
92
+ let client = null;
93
+ const getClient = () => client ??= clientFactory();
94
+ return {
95
+ async getUser(accessToken) {
96
+ const { data, error } = await getClient().auth.getUser(accessToken);
97
+ return { user: data?.user ?? null, error };
98
+ },
99
+ async findAdminUser(userId) {
100
+ const { data, error } = await getClient()
101
+ .from("admin_users")
102
+ .select("id, role")
103
+ .eq("id", userId)
104
+ .eq("membership_state", "active")
105
+ .maybeSingle();
106
+ if (error)
107
+ throw error;
108
+ return data;
109
+ },
110
+ async revokeAdminUser(userId) {
111
+ return await getClient().rpc("admin_revoke_admin_user", {
112
+ p_target: userId,
113
+ p_reason: null,
114
+ });
115
+ },
116
+ };
117
+ }
118
+ /** Managed eligibility depends only on active native membership and known roles. */
119
+ export async function managedOperatorMagicLinkEligibility(rawClient, email) {
120
+ const client = rawClient;
121
+ const { data, error } = await client.from("admin_users").select("id, role").eq("email", email.trim().toLowerCase()).eq("membership_state", "active").maybeSingle();
122
+ if (error)
123
+ throw error;
124
+ if (!data)
125
+ return "not_allowlisted";
126
+ return data.role === "admin" || data.role === "distributor" ? "eligible" : "role_not_allowed";
127
+ }
@@ -0,0 +1,90 @@
1
+ import type { SupabaseCreateClient } from "../data/index.js";
2
+ export interface ManagedIdentityUser {
3
+ id: string;
4
+ email?: string | null;
5
+ email_confirmed_at?: string | null;
6
+ user_metadata?: Record<string, unknown> | null;
7
+ }
8
+ export interface ManagedIdentityRow {
9
+ id: string;
10
+ email?: string | null;
11
+ auth_user_id?: string | null;
12
+ role?: string | null;
13
+ is_machine_actor?: boolean | null;
14
+ membership_state?: string;
15
+ }
16
+ export interface ManagedIdentityQuery extends PromiseLike<{
17
+ data: ManagedIdentityRow[] | null;
18
+ error: unknown;
19
+ }> {
20
+ select(columns: string): ManagedIdentityQuery;
21
+ eq(column: string, value: string): ManagedIdentityQuery;
22
+ filter(column: string, operator: "imatch", value: string): ManagedIdentityQuery;
23
+ is(column: string, value: null): ManagedIdentityQuery;
24
+ order(column: string, options: {
25
+ ascending: boolean;
26
+ }): ManagedIdentityQuery;
27
+ limit(count: number): ManagedIdentityQuery;
28
+ maybeSingle(): PromiseLike<{
29
+ data: ManagedIdentityRow | null;
30
+ error: unknown;
31
+ }>;
32
+ single(): PromiseLike<{
33
+ data: ManagedIdentityRow | null;
34
+ error: unknown;
35
+ }>;
36
+ }
37
+ export interface ManagedIdentityTable {
38
+ select(columns: string): ManagedIdentityQuery;
39
+ update(value: Record<string, unknown>): ManagedIdentityQuery;
40
+ insert(value: Record<string, unknown>): ManagedIdentityQuery;
41
+ }
42
+ /** Only the methods consumed by the identity adapters; the host owns the SDK. */
43
+ export interface ManagedIdentityClient {
44
+ from(table: string): ManagedIdentityTable;
45
+ auth: {
46
+ getUser(token: string): PromiseLike<{
47
+ data: {
48
+ user: ManagedIdentityUser | null;
49
+ };
50
+ error: unknown;
51
+ }>;
52
+ admin: {
53
+ listUsers(options: {
54
+ page: number;
55
+ perPage: number;
56
+ }): PromiseLike<{
57
+ data: {
58
+ users: ManagedIdentityUser[];
59
+ nextPage?: number | null;
60
+ };
61
+ error: unknown;
62
+ }>;
63
+ getUserById(id: string): PromiseLike<{
64
+ data: {
65
+ user: ManagedIdentityUser | null;
66
+ };
67
+ error: unknown;
68
+ }>;
69
+ createUser(input: {
70
+ email: string;
71
+ email_confirm: boolean;
72
+ }): PromiseLike<{
73
+ data: {
74
+ user: ManagedIdentityUser | null;
75
+ };
76
+ error: unknown;
77
+ }>;
78
+ };
79
+ };
80
+ }
81
+ export declare function createManagedIdentityClients(createClient: SupabaseCreateClient): {
82
+ actor: (env: {
83
+ url: string;
84
+ anonKey: string;
85
+ }, accessToken: string | null) => ManagedIdentityClient;
86
+ service: (env: {
87
+ url: string;
88
+ serviceRoleKey: string;
89
+ }) => ManagedIdentityClient;
90
+ };
@@ -0,0 +1,10 @@
1
+ export function createManagedIdentityClients(createClient) {
2
+ const actor = (env, accessToken) => createClient(env.url, env.anonKey, {
3
+ auth: { persistSession: false, autoRefreshToken: false },
4
+ global: { headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {} },
5
+ });
6
+ const service = (env) => createClient(env.url, env.serviceRoleKey, {
7
+ auth: { persistSession: false, autoRefreshToken: false },
8
+ });
9
+ return { actor, service };
10
+ }
@@ -0,0 +1,3 @@
1
+ import type { EmailTrustPolicy } from "./emailTrustPolicy.js";
2
+ import type { ClientAuthLinkStore } from "./ports.js";
3
+ export declare function createSupabaseClientAuthLinkStore(rawClient: unknown, emailTrustPolicy: EmailTrustPolicy): ClientAuthLinkStore;
@@ -0,0 +1,115 @@
1
+ export function createSupabaseClientAuthLinkStore(rawClient, emailTrustPolicy) {
2
+ const client = rawClient;
3
+ return {
4
+ emailTrustPolicy,
5
+ async findClientByEmail(email) {
6
+ const rows = await findManagedContactsByEmail(client, email, true);
7
+ const row = rows[0];
8
+ if (!row)
9
+ return null;
10
+ return { id: row.id, authUserId: row.auth_user_id ?? null };
11
+ },
12
+ async findAuthUserIdByEmail(email) {
13
+ const perPage = 1000;
14
+ const maxUsers = 5000;
15
+ let page = 1;
16
+ let scanned = 0;
17
+ while (scanned < maxUsers) {
18
+ const { data, error } = await client.auth.admin.listUsers({ page, perPage });
19
+ if (error)
20
+ throw error;
21
+ const users = data.users;
22
+ const match = users.find((u) => (u.email ?? "").trim().toLowerCase() === email);
23
+ if (match)
24
+ return match.id;
25
+ scanned += users.length;
26
+ const nextPage = "nextPage" in data ? data.nextPage : null;
27
+ if (!nextPage)
28
+ return null;
29
+ page = nextPage;
30
+ }
31
+ throw new Error("auth_user_lookup_cap_exceeded");
32
+ },
33
+ async findAuthUserEmailById(authUserId) {
34
+ const { data, error } = await client.auth.admin.getUserById(authUserId);
35
+ if (error)
36
+ throw error;
37
+ return data.user?.email ?? null;
38
+ },
39
+ async createAuthUser(email) {
40
+ const { data, error } = await client.auth.admin.createUser({
41
+ email,
42
+ email_confirm: false,
43
+ });
44
+ if (error && isAlreadyRegistered(error))
45
+ return null;
46
+ if (error)
47
+ throw error;
48
+ if (!data.user)
49
+ throw new Error("createUser returned no user");
50
+ return data.user.id;
51
+ },
52
+ async findAdminIdentity(authUserId) {
53
+ const { data, error } = await client
54
+ .from("admin_users")
55
+ .select("id, is_machine_actor")
56
+ .eq("id", authUserId)
57
+ .maybeSingle();
58
+ if (error)
59
+ throw error;
60
+ if (!data)
61
+ return null;
62
+ return { isMachineActor: data.is_machine_actor !== false };
63
+ },
64
+ async setClientAuthUserId(clientId, authUserId) {
65
+ const { data, error } = await client
66
+ .from("clients")
67
+ .update({ auth_user_id: authUserId })
68
+ .eq("id", clientId)
69
+ .is("auth_user_id", null)
70
+ .select("auth_user_id")
71
+ .maybeSingle();
72
+ if (error)
73
+ throw error;
74
+ if (data?.auth_user_id === authUserId) {
75
+ return { ok: true, alreadyLinked: false };
76
+ }
77
+ const { data: current, error: currentError } = await client
78
+ .from("clients")
79
+ .select("auth_user_id")
80
+ .eq("id", clientId)
81
+ .maybeSingle();
82
+ if (currentError)
83
+ throw currentError;
84
+ if (current?.auth_user_id === authUserId) {
85
+ return { ok: true, alreadyLinked: true };
86
+ }
87
+ return {
88
+ ok: false,
89
+ code: "CLIENT_AUTH_LINK_CONFLICT",
90
+ existingAuthUserId: current?.auth_user_id ?? null,
91
+ };
92
+ },
93
+ };
94
+ }
95
+ function isAlreadyRegistered(error) {
96
+ const failure = (error ?? {});
97
+ if (failure.code === "email_exists" || failure.code === "user_already_exists")
98
+ return true;
99
+ return failure.status === 422 && typeof failure.message === "string"
100
+ && /already (been )?registered/i.test(failure.message);
101
+ }
102
+ async function findManagedContactsByEmail(client, email, oldestFirst) {
103
+ const normalized = email.trim().toLowerCase();
104
+ // Escaping bounds the database prefilter; Unicode regex folding can still
105
+ // widen it, so only exact normalized addresses may cross this boundary.
106
+ let query = client.from("clients")
107
+ .select("id, email, auth_user_id")
108
+ .filter("email", "imatch", `^${normalized.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&")}$`);
109
+ if (oldestFirst)
110
+ query = query.order("created_at", { ascending: true });
111
+ const { data, error } = await query.limit(10);
112
+ if (error)
113
+ throw error;
114
+ return (data ?? []).filter((row) => row.email?.trim().toLowerCase() === normalized);
115
+ }
@@ -0,0 +1,13 @@
1
+ import type { CustomerMeResponse } from "./customerContracts.js";
2
+ import type { CustomerMePort } from "./customerPorts.js";
3
+ type LinkedCustomerRow = {
4
+ id: string;
5
+ email: string;
6
+ first_name: string | null;
7
+ last_name: string | null;
8
+ phone: string | null;
9
+ lifecycle_stage: CustomerMeResponse["lifecycleStage"];
10
+ };
11
+ export declare function readLinkedCustomer(rawClient: unknown, userId: string, includePhone?: boolean): Promise<LinkedCustomerRow | null>;
12
+ export declare function createSupabaseCustomerMePort(rawClient: unknown): CustomerMePort;
13
+ export {};
@@ -0,0 +1,30 @@
1
+ export async function readLinkedCustomer(rawClient, userId, includePhone = false) {
2
+ const client = rawClient;
3
+ const { data, error } = await client
4
+ .from("clients")
5
+ .select(includePhone
6
+ ? "id, email, first_name, last_name, phone, lifecycle_stage"
7
+ : "id, email, first_name, last_name, lifecycle_stage")
8
+ .eq("auth_user_id", userId)
9
+ .maybeSingle();
10
+ if (error)
11
+ throw error;
12
+ return data;
13
+ }
14
+ export function createSupabaseCustomerMePort(rawClient) {
15
+ const client = rawClient;
16
+ return {
17
+ async getCustomerMe(userId) {
18
+ const data = await readLinkedCustomer(client, userId);
19
+ if (!data)
20
+ return null;
21
+ return {
22
+ clientId: data.id,
23
+ email: data.email,
24
+ firstName: data.first_name,
25
+ lastName: data.last_name,
26
+ lifecycleStage: data.lifecycle_stage,
27
+ };
28
+ },
29
+ };
30
+ }
@@ -0,0 +1,11 @@
1
+ import type { EmailTrustPolicy } from "./emailTrustPolicy.js";
2
+ /** Server-side assertion by the adopter, never a provider certification. */
3
+ export declare function parseEmailVerifyingProviders(value: string): readonly string[];
4
+ /** One immutable origin/key/allowlist binding; import and construction perform no I/O. */
5
+ export declare function createManagedEmailTrustPolicy(options: {
6
+ authBaseUrl: string;
7
+ publicKey: string;
8
+ emailVerifyingProviders?: readonly string[];
9
+ fetch?: typeof globalThis.fetch;
10
+ now?: () => number;
11
+ }): EmailTrustPolicy;
@@ -0,0 +1,105 @@
1
+ const unavailable = { trusted: false, code: "EMAIL_TRUST_SETTINGS_UNAVAILABLE" };
2
+ const refused = { trusted: false, code: "EMAIL_TRUST_ENVELOPE_REFUSED" };
3
+ const providerId = /^[a-z][a-z0-9_-]*$/;
4
+ /** Server-side assertion by the adopter, never a provider certification. */
5
+ export function parseEmailVerifyingProviders(value) {
6
+ if (!value.trim())
7
+ return [];
8
+ const entries = value.split(",").map(entry => entry.trim().toLowerCase());
9
+ if (entries.some(entry => !providerId.test(entry)))
10
+ throw new Error("Invalid email-verifying provider declaration");
11
+ return [...new Set(entries)].sort();
12
+ }
13
+ /** One immutable origin/key/allowlist binding; import and construction perform no I/O. */
14
+ export function createManagedEmailTrustPolicy(options) {
15
+ const origin = new URL(options.authBaseUrl);
16
+ if (!["http:", "https:"].includes(origin.protocol) || origin.username || origin.password
17
+ || origin.pathname !== "/" || origin.search || origin.hash || !options.publicKey.trim()) {
18
+ throw new Error("Invalid identity email-trust configuration");
19
+ }
20
+ const url = new URL("/auth/v1/settings", origin);
21
+ const publicKey = options.publicKey;
22
+ const allowed = new Set(parseEmailVerifyingProviders((options.emailVerifyingProviders ?? []).join(",")));
23
+ const fetchSettings = options.fetch ?? globalThis.fetch;
24
+ const now = options.now ?? Date.now;
25
+ let cached;
26
+ let inFlight;
27
+ function decode(value) {
28
+ if (!value || typeof value !== "object" || Array.isArray(value))
29
+ return unavailable;
30
+ const { mailer_autoconfirm: automatic, external } = value;
31
+ if (typeof automatic !== "boolean" || !external || typeof external !== "object" || Array.isArray(external))
32
+ return unavailable;
33
+ const entries = Object.entries(external);
34
+ if (entries.some(([key, enabled]) => !providerId.test(key) || typeof enabled !== "boolean"))
35
+ return unavailable;
36
+ if (automatic || entries.some(([key, enabled]) => enabled && key !== "email" && !allowed.has(key)))
37
+ return refused;
38
+ return { trusted: true };
39
+ }
40
+ async function load() {
41
+ const controller = new AbortController();
42
+ let timer;
43
+ const deadline = new Promise((_, reject) => {
44
+ timer = setTimeout(() => { controller.abort(); reject(new Error("Identity settings deadline")); }, 3000);
45
+ });
46
+ async function read() {
47
+ const response = await fetchSettings(url, {
48
+ headers: { apikey: publicKey }, redirect: "error", signal: controller.signal,
49
+ });
50
+ if (!response.ok || response.redirected || !response.body)
51
+ return unavailable;
52
+ const reader = response.body.getReader();
53
+ let bytes = 0;
54
+ const chunks = [];
55
+ try {
56
+ while (true) {
57
+ const chunk = await reader.read();
58
+ if (chunk.done)
59
+ break;
60
+ bytes += chunk.value.byteLength;
61
+ if (bytes > 65536) {
62
+ controller.abort();
63
+ void reader.cancel().catch(() => { });
64
+ return unavailable;
65
+ }
66
+ chunks.push(chunk.value);
67
+ }
68
+ }
69
+ finally {
70
+ reader.releaseLock();
71
+ }
72
+ const body = new Uint8Array(bytes);
73
+ let offset = 0;
74
+ for (const chunk of chunks) {
75
+ body.set(chunk, offset);
76
+ offset += chunk.byteLength;
77
+ }
78
+ return decode(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(body)));
79
+ }
80
+ try {
81
+ return await Promise.race([read(), deadline]);
82
+ }
83
+ catch {
84
+ return unavailable;
85
+ }
86
+ finally {
87
+ controller.abort();
88
+ clearTimeout(timer);
89
+ }
90
+ }
91
+ return {
92
+ async assess() {
93
+ if (cached && now() < cached.expires)
94
+ return cached.result;
95
+ if (!inFlight) {
96
+ inFlight = load().then(result => {
97
+ const ttl = !result.trusted && result.code === "EMAIL_TRUST_SETTINGS_UNAVAILABLE" ? 5000 : 60000;
98
+ cached = { result, expires: now() + ttl };
99
+ return result;
100
+ }).finally(() => { inFlight = undefined; });
101
+ }
102
+ return inFlight;
103
+ },
104
+ };
105
+ }
@@ -0,0 +1,2 @@
1
+ import type { IdentityVerifierPort } from "./ports.js";
2
+ export declare function createSupabaseIdentityVerifier(rawClient: unknown): IdentityVerifierPort;
@@ -0,0 +1,16 @@
1
+ export function createSupabaseIdentityVerifier(rawClient) {
2
+ const client = rawClient;
3
+ return {
4
+ async verifyAccessToken(accessToken) {
5
+ const { data, error } = await client.auth.getUser(accessToken);
6
+ if (error || !data.user)
7
+ return null;
8
+ const user = data.user;
9
+ return {
10
+ principalId: user.id,
11
+ email: user.email ?? null,
12
+ emailVerified: Boolean(user.email_confirmed_at),
13
+ };
14
+ },
15
+ };
16
+ }
@@ -0,0 +1,4 @@
1
+ import type { ManagedIdentityClient } from "./managedClient.js";
2
+ import { type PrivacyStore } from "./privacyPorts.js";
3
+ /** Reads only committed service projections. No managed write or provider delete is composed. */
4
+ export declare function createManagedPrivacyStore(): PrivacyStore<ManagedIdentityClient>;