@porulle/core 0.10.8 → 0.13.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 (360) hide show
  1. package/dist/auth/auth-schema-guard.d.ts +2444 -0
  2. package/dist/auth/auth-schema-guard.d.ts.map +1 -0
  3. package/dist/auth/auth-schema-guard.js +113 -0
  4. package/dist/auth/auth-schema.d.ts +228 -0
  5. package/dist/auth/auth-schema.d.ts.map +1 -1
  6. package/dist/auth/auth-schema.js +24 -2
  7. package/dist/auth/middleware.d.ts +1 -0
  8. package/dist/auth/middleware.d.ts.map +1 -1
  9. package/dist/auth/middleware.js +13 -5
  10. package/dist/auth/org.d.ts +8 -2
  11. package/dist/auth/org.d.ts.map +1 -1
  12. package/dist/auth/org.js +12 -4
  13. package/dist/auth/organization-guard.d.ts +5 -0
  14. package/dist/auth/organization-guard.d.ts.map +1 -0
  15. package/dist/auth/organization-guard.js +124 -0
  16. package/dist/auth/permissions.d.ts +10 -0
  17. package/dist/auth/permissions.d.ts.map +1 -1
  18. package/dist/auth/permissions.js +31 -7
  19. package/dist/auth/role-authority.d.ts +44 -0
  20. package/dist/auth/role-authority.d.ts.map +1 -0
  21. package/dist/auth/role-authority.js +85 -0
  22. package/dist/auth/setup.d.ts.map +1 -1
  23. package/dist/auth/setup.js +17 -0
  24. package/dist/auth/strict-org-resolution.d.ts.map +1 -1
  25. package/dist/auth/strict-org-resolution.js +9 -1
  26. package/dist/auth/types.d.ts +1 -1
  27. package/dist/auth/types.d.ts.map +1 -1
  28. package/dist/config/defaults.d.ts.map +1 -1
  29. package/dist/config/defaults.js +2 -0
  30. package/dist/config/types.d.ts +33 -4
  31. package/dist/config/types.d.ts.map +1 -1
  32. package/dist/hooks/checkout.d.ts.map +1 -1
  33. package/dist/hooks/checkout.js +10 -9
  34. package/dist/index.d.ts +9 -6
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +5 -3
  37. package/dist/interfaces/rest/audit-middleware.d.ts.map +1 -1
  38. package/dist/interfaces/rest/audit-middleware.js +2 -0
  39. package/dist/interfaces/rest/customer-portal.d.ts.map +1 -1
  40. package/dist/interfaces/rest/customer-portal.js +9 -8
  41. package/dist/interfaces/rest/index.d.ts.map +1 -1
  42. package/dist/interfaces/rest/index.js +4 -0
  43. package/dist/interfaces/rest/route-coverage.d.ts +14 -0
  44. package/dist/interfaces/rest/route-coverage.d.ts.map +1 -0
  45. package/dist/interfaces/rest/route-coverage.js +81 -0
  46. package/dist/interfaces/rest/router.d.ts +7 -2
  47. package/dist/interfaces/rest/router.d.ts.map +1 -1
  48. package/dist/interfaces/rest/router.js +8 -4
  49. package/dist/interfaces/rest/routes/admin/compensation-failures.d.ts.map +1 -1
  50. package/dist/interfaces/rest/routes/admin/compensation-failures.js +7 -5
  51. package/dist/interfaces/rest/routes/admin/custom-field-proposals.d.ts +5 -0
  52. package/dist/interfaces/rest/routes/admin/custom-field-proposals.d.ts.map +1 -0
  53. package/dist/interfaces/rest/routes/admin/custom-field-proposals.js +22 -0
  54. package/dist/interfaces/rest/routes/admin/entity-field-definitions.d.ts +5 -0
  55. package/dist/interfaces/rest/routes/admin/entity-field-definitions.d.ts.map +1 -0
  56. package/dist/interfaces/rest/routes/admin/entity-field-definitions.js +39 -0
  57. package/dist/interfaces/rest/routes/admin/permissions.d.ts +1 -1
  58. package/dist/interfaces/rest/routes/admin/permissions.d.ts.map +1 -1
  59. package/dist/interfaces/rest/routes/admin/permissions.js +2 -0
  60. package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
  61. package/dist/interfaces/rest/routes/admin/staff.js +126 -66
  62. package/dist/interfaces/rest/routes/admin-jobs.js +3 -3
  63. package/dist/interfaces/rest/routes/audit.js +3 -3
  64. package/dist/interfaces/rest/routes/carts.d.ts.map +1 -1
  65. package/dist/interfaces/rest/routes/carts.js +13 -10
  66. package/dist/interfaces/rest/routes/catalog.d.ts.map +1 -1
  67. package/dist/interfaces/rest/routes/catalog.js +47 -4
  68. package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
  69. package/dist/interfaces/rest/routes/checkout.js +30 -35
  70. package/dist/interfaces/rest/routes/documents.d.ts.map +1 -1
  71. package/dist/interfaces/rest/routes/documents.js +10 -5
  72. package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
  73. package/dist/interfaces/rest/routes/inventory.js +2 -0
  74. package/dist/interfaces/rest/routes/media.d.ts.map +1 -1
  75. package/dist/interfaces/rest/routes/media.js +7 -3
  76. package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
  77. package/dist/interfaces/rest/routes/orders.js +26 -8
  78. package/dist/interfaces/rest/routes/pricing.js +2 -2
  79. package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
  80. package/dist/interfaces/rest/routes/promotions.js +13 -10
  81. package/dist/interfaces/rest/routes/search.d.ts.map +1 -1
  82. package/dist/interfaces/rest/routes/search.js +14 -1
  83. package/dist/interfaces/rest/schemas/admin-custom-field-proposals.d.ts +134 -0
  84. package/dist/interfaces/rest/schemas/admin-custom-field-proposals.d.ts.map +1 -0
  85. package/dist/interfaces/rest/schemas/admin-custom-field-proposals.js +26 -0
  86. package/dist/interfaces/rest/schemas/admin-entity-field-definitions.d.ts +592 -0
  87. package/dist/interfaces/rest/schemas/admin-entity-field-definitions.d.ts.map +1 -0
  88. package/dist/interfaces/rest/schemas/admin-entity-field-definitions.js +109 -0
  89. package/dist/interfaces/rest/schemas/carts.d.ts +7 -0
  90. package/dist/interfaces/rest/schemas/carts.d.ts.map +1 -1
  91. package/dist/interfaces/rest/schemas/catalog.d.ts +1364 -401
  92. package/dist/interfaces/rest/schemas/catalog.d.ts.map +1 -1
  93. package/dist/interfaces/rest/schemas/catalog.js +86 -0
  94. package/dist/interfaces/rest/schemas/customer-portal.d.ts +35 -0
  95. package/dist/interfaces/rest/schemas/customer-portal.d.ts.map +1 -1
  96. package/dist/interfaces/rest/schemas/orders.d.ts +204 -0
  97. package/dist/interfaces/rest/schemas/orders.d.ts.map +1 -1
  98. package/dist/interfaces/rest/schemas/pricing.d.ts +1 -0
  99. package/dist/interfaces/rest/schemas/pricing.d.ts.map +1 -1
  100. package/dist/interfaces/rest/schemas/responses.d.ts +71 -0
  101. package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
  102. package/dist/interfaces/rest/schemas/search.d.ts +1 -0
  103. package/dist/interfaces/rest/schemas/search.d.ts.map +1 -1
  104. package/dist/interfaces/rest/schemas/search.js +1 -0
  105. package/dist/interfaces/rest/utils.d.ts +15 -0
  106. package/dist/interfaces/rest/utils.d.ts.map +1 -1
  107. package/dist/interfaces/rest/utils.js +45 -2
  108. package/dist/kernel/compensation/executor.js +2 -2
  109. package/dist/kernel/database/tx-context.d.ts +8 -0
  110. package/dist/kernel/database/tx-context.d.ts.map +1 -1
  111. package/dist/kernel/database/tx-context.js +13 -0
  112. package/dist/kernel/hooks/create-context.d.ts +2 -0
  113. package/dist/kernel/hooks/create-context.d.ts.map +1 -1
  114. package/dist/kernel/hooks/create-context.js +1 -0
  115. package/dist/kernel/hooks/types.d.ts +2 -0
  116. package/dist/kernel/hooks/types.d.ts.map +1 -1
  117. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  118. package/dist/kernel/plugin/manifest.js +9 -5
  119. package/dist/modules/analytics/service.js +2 -2
  120. package/dist/modules/audit/service.js +3 -3
  121. package/dist/modules/cart/repository/index.d.ts +13 -7
  122. package/dist/modules/cart/repository/index.d.ts.map +1 -1
  123. package/dist/modules/cart/repository/index.js +16 -10
  124. package/dist/modules/cart/schema.d.ts +17 -0
  125. package/dist/modules/cart/schema.d.ts.map +1 -1
  126. package/dist/modules/cart/schema.js +4 -0
  127. package/dist/modules/cart/service.d.ts +22 -9
  128. package/dist/modules/cart/service.d.ts.map +1 -1
  129. package/dist/modules/cart/service.js +57 -33
  130. package/dist/modules/catalog/brand-service.js +7 -7
  131. package/dist/modules/catalog/category-service.js +7 -7
  132. package/dist/modules/catalog/entity-service.d.ts +19 -10
  133. package/dist/modules/catalog/entity-service.d.ts.map +1 -1
  134. package/dist/modules/catalog/entity-service.js +180 -51
  135. package/dist/modules/catalog/module.d.ts +6 -1
  136. package/dist/modules/catalog/module.d.ts.map +1 -1
  137. package/dist/modules/catalog/module.js +6 -1
  138. package/dist/modules/catalog/ownership.d.ts +5 -0
  139. package/dist/modules/catalog/ownership.d.ts.map +1 -0
  140. package/dist/modules/catalog/ownership.js +11 -0
  141. package/dist/modules/catalog/read-policy.d.ts +9 -0
  142. package/dist/modules/catalog/read-policy.d.ts.map +1 -0
  143. package/dist/modules/catalog/read-policy.js +8 -0
  144. package/dist/modules/catalog/repository/index.d.ts +55 -3
  145. package/dist/modules/catalog/repository/index.d.ts.map +1 -1
  146. package/dist/modules/catalog/repository/index.js +335 -6
  147. package/dist/modules/catalog/revision.d.ts +4 -0
  148. package/dist/modules/catalog/revision.d.ts.map +1 -0
  149. package/dist/modules/catalog/revision.js +33 -0
  150. package/dist/modules/catalog/schema.d.ts +979 -110
  151. package/dist/modules/catalog/schema.d.ts.map +1 -1
  152. package/dist/modules/catalog/schema.js +112 -2
  153. package/dist/modules/catalog/schemas.d.ts +2 -0
  154. package/dist/modules/catalog/schemas.d.ts.map +1 -1
  155. package/dist/modules/catalog/schemas.js +2 -0
  156. package/dist/modules/catalog/service.d.ts +80 -15
  157. package/dist/modules/catalog/service.d.ts.map +1 -1
  158. package/dist/modules/catalog/service.js +522 -14
  159. package/dist/modules/channels/adapter.d.ts +85 -0
  160. package/dist/modules/channels/adapter.d.ts.map +1 -1
  161. package/dist/modules/channels/adapter.js +9 -1
  162. package/dist/modules/customers/module.d.ts.map +1 -1
  163. package/dist/modules/customers/module.js +1 -0
  164. package/dist/modules/customers/service.d.ts +2 -0
  165. package/dist/modules/customers/service.d.ts.map +1 -1
  166. package/dist/modules/customers/service.js +21 -20
  167. package/dist/modules/documents/module.d.ts.map +1 -1
  168. package/dist/modules/documents/module.js +1 -0
  169. package/dist/modules/documents/service.d.ts +18 -4
  170. package/dist/modules/documents/service.d.ts.map +1 -1
  171. package/dist/modules/documents/service.js +54 -16
  172. package/dist/modules/fulfillment/module.d.ts.map +1 -1
  173. package/dist/modules/fulfillment/module.js +1 -0
  174. package/dist/modules/fulfillment/service.d.ts +2 -0
  175. package/dist/modules/fulfillment/service.d.ts.map +1 -1
  176. package/dist/modules/fulfillment/service.js +15 -6
  177. package/dist/modules/inventory/service.d.ts.map +1 -1
  178. package/dist/modules/inventory/service.js +15 -14
  179. package/dist/modules/media/module.d.ts +68 -0
  180. package/dist/modules/media/module.d.ts.map +1 -1
  181. package/dist/modules/media/module.js +2 -0
  182. package/dist/modules/media/schema.d.ts +70 -0
  183. package/dist/modules/media/schema.d.ts.map +1 -1
  184. package/dist/modules/media/schema.js +20 -2
  185. package/dist/modules/media/service.d.ts +8 -1
  186. package/dist/modules/media/service.d.ts.map +1 -1
  187. package/dist/modules/media/service.js +71 -23
  188. package/dist/modules/orders/guest-access.d.ts +27 -0
  189. package/dist/modules/orders/guest-access.d.ts.map +1 -0
  190. package/dist/modules/orders/guest-access.js +46 -0
  191. package/dist/modules/orders/module.d.ts.map +1 -1
  192. package/dist/modules/orders/module.js +1 -0
  193. package/dist/modules/orders/quote.d.ts.map +1 -1
  194. package/dist/modules/orders/quote.js +1 -0
  195. package/dist/modules/orders/repository/index.d.ts +1 -1
  196. package/dist/modules/orders/repository/index.d.ts.map +1 -1
  197. package/dist/modules/orders/repository/index.js +2 -2
  198. package/dist/modules/orders/schema.d.ts +17 -0
  199. package/dist/modules/orders/schema.d.ts.map +1 -1
  200. package/dist/modules/orders/schema.js +5 -3
  201. package/dist/modules/orders/service.d.ts +16 -7
  202. package/dist/modules/orders/service.d.ts.map +1 -1
  203. package/dist/modules/orders/service.js +184 -55
  204. package/dist/modules/pricing/module.d.ts.map +1 -1
  205. package/dist/modules/pricing/module.js +1 -0
  206. package/dist/modules/pricing/schema.d.ts +17 -0
  207. package/dist/modules/pricing/schema.d.ts.map +1 -1
  208. package/dist/modules/pricing/schema.js +1 -0
  209. package/dist/modules/pricing/schemas.d.ts +1 -0
  210. package/dist/modules/pricing/schemas.d.ts.map +1 -1
  211. package/dist/modules/pricing/schemas.js +1 -0
  212. package/dist/modules/pricing/service.d.ts +2 -0
  213. package/dist/modules/pricing/service.d.ts.map +1 -1
  214. package/dist/modules/pricing/service.js +18 -12
  215. package/dist/modules/promotions/module.d.ts.map +1 -1
  216. package/dist/modules/promotions/module.js +1 -0
  217. package/dist/modules/promotions/service.d.ts +3 -0
  218. package/dist/modules/promotions/service.d.ts.map +1 -1
  219. package/dist/modules/promotions/service.js +19 -11
  220. package/dist/modules/search/adapter.d.ts +8 -0
  221. package/dist/modules/search/adapter.d.ts.map +1 -1
  222. package/dist/modules/search/module.d.ts.map +1 -1
  223. package/dist/modules/search/module.js +3 -0
  224. package/dist/modules/search/service.d.ts +5 -0
  225. package/dist/modules/search/service.d.ts.map +1 -1
  226. package/dist/modules/search/service.js +131 -11
  227. package/dist/modules/settings/module.d.ts.map +1 -1
  228. package/dist/modules/settings/module.js +1 -0
  229. package/dist/modules/settings/service.d.ts +3 -0
  230. package/dist/modules/settings/service.d.ts.map +1 -1
  231. package/dist/modules/settings/service.js +6 -4
  232. package/dist/modules/shipping/service.js +9 -9
  233. package/dist/modules/tax/module.d.ts.map +1 -1
  234. package/dist/modules/tax/module.js +1 -0
  235. package/dist/modules/tax/service.d.ts +3 -0
  236. package/dist/modules/tax/service.d.ts.map +1 -1
  237. package/dist/modules/tax/service.js +11 -9
  238. package/dist/modules/webhooks/hook.js +2 -2
  239. package/dist/modules/webhooks/module.d.ts.map +1 -1
  240. package/dist/modules/webhooks/module.js +1 -0
  241. package/dist/modules/webhooks/service.d.ts +2 -0
  242. package/dist/modules/webhooks/service.d.ts.map +1 -1
  243. package/dist/modules/webhooks/service.js +4 -4
  244. package/dist/runtime/kernel-modules.d.ts +73 -0
  245. package/dist/runtime/kernel-modules.d.ts.map +1 -1
  246. package/dist/runtime/server.d.ts.map +1 -1
  247. package/dist/runtime/server.js +10 -2
  248. package/dist/test-utils/create-pglite-adapter.d.ts.map +1 -1
  249. package/dist/test-utils/create-pglite-adapter.js +35 -13
  250. package/dist/test-utils/create-test-config.d.ts.map +1 -1
  251. package/dist/test-utils/create-test-config.js +4 -0
  252. package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
  253. package/dist/test-utils/rest-api-test-utils.js +2 -0
  254. package/dist/test-utils/test-actors.js +2 -2
  255. package/dist/utils/id.d.ts +2 -0
  256. package/dist/utils/id.d.ts.map +1 -1
  257. package/dist/utils/id.js +11 -0
  258. package/package.json +6 -5
  259. package/src/auth/auth-schema-guard.ts +143 -0
  260. package/src/auth/auth-schema.ts +50 -19
  261. package/src/auth/middleware.ts +17 -5
  262. package/src/auth/org.ts +15 -3
  263. package/src/auth/organization-guard.ts +158 -0
  264. package/src/auth/permissions.ts +31 -8
  265. package/src/auth/role-authority.ts +107 -0
  266. package/src/auth/setup.ts +17 -0
  267. package/src/auth/strict-org-resolution.ts +7 -1
  268. package/src/auth/types.ts +1 -1
  269. package/src/config/defaults.ts +2 -0
  270. package/src/config/types.ts +32 -4
  271. package/src/hooks/checkout.ts +19 -12
  272. package/src/index.ts +30 -6
  273. package/src/interfaces/rest/audit-middleware.ts +2 -0
  274. package/src/interfaces/rest/customer-portal.ts +31 -24
  275. package/src/interfaces/rest/index.ts +4 -0
  276. package/src/interfaces/rest/route-coverage.ts +103 -0
  277. package/src/interfaces/rest/router.ts +16 -10
  278. package/src/interfaces/rest/routes/admin/compensation-failures.ts +8 -5
  279. package/src/interfaces/rest/routes/admin/custom-field-proposals.ts +37 -0
  280. package/src/interfaces/rest/routes/admin/entity-field-definitions.ts +89 -0
  281. package/src/interfaces/rest/routes/admin/permissions.ts +3 -1
  282. package/src/interfaces/rest/routes/admin/staff.ts +161 -72
  283. package/src/interfaces/rest/routes/admin-jobs.ts +3 -3
  284. package/src/interfaces/rest/routes/audit.ts +3 -3
  285. package/src/interfaces/rest/routes/carts.ts +17 -7
  286. package/src/interfaces/rest/routes/catalog.ts +96 -0
  287. package/src/interfaces/rest/routes/checkout.ts +41 -38
  288. package/src/interfaces/rest/routes/documents.ts +15 -1
  289. package/src/interfaces/rest/routes/inventory.ts +2 -0
  290. package/src/interfaces/rest/routes/media.ts +8 -3
  291. package/src/interfaces/rest/routes/orders.ts +27 -8
  292. package/src/interfaces/rest/routes/pricing.ts +2 -2
  293. package/src/interfaces/rest/routes/promotions.ts +12 -9
  294. package/src/interfaces/rest/routes/search.ts +19 -1
  295. package/src/interfaces/rest/schemas/admin-custom-field-proposals.ts +29 -0
  296. package/src/interfaces/rest/schemas/admin-entity-field-definitions.ts +120 -0
  297. package/src/interfaces/rest/schemas/catalog.ts +92 -0
  298. package/src/interfaces/rest/schemas/search.ts +2 -0
  299. package/src/interfaces/rest/utils.ts +61 -2
  300. package/src/kernel/compensation/executor.ts +2 -2
  301. package/src/kernel/database/tx-context.ts +25 -0
  302. package/src/kernel/hooks/create-context.ts +3 -0
  303. package/src/kernel/hooks/types.ts +2 -0
  304. package/src/kernel/plugin/manifest.ts +9 -5
  305. package/src/modules/analytics/service.ts +2 -2
  306. package/src/modules/audit/service.ts +3 -3
  307. package/src/modules/cart/repository/index.ts +22 -8
  308. package/src/modules/cart/schema.ts +4 -0
  309. package/src/modules/cart/service.ts +62 -27
  310. package/src/modules/catalog/brand-service.ts +7 -7
  311. package/src/modules/catalog/category-service.ts +7 -7
  312. package/src/modules/catalog/entity-service.ts +188 -53
  313. package/src/modules/catalog/module.ts +15 -0
  314. package/src/modules/catalog/ownership.ts +17 -0
  315. package/src/modules/catalog/read-policy.ts +16 -0
  316. package/src/modules/catalog/repository/index.ts +566 -4
  317. package/src/modules/catalog/revision.ts +35 -0
  318. package/src/modules/catalog/schema.ts +169 -1
  319. package/src/modules/catalog/schemas.ts +2 -0
  320. package/src/modules/catalog/service.ts +766 -26
  321. package/src/modules/channels/adapter.ts +107 -1
  322. package/src/modules/customers/module.ts +2 -0
  323. package/src/modules/customers/service.ts +23 -22
  324. package/src/modules/documents/module.ts +2 -0
  325. package/src/modules/documents/service.ts +74 -11
  326. package/src/modules/fulfillment/module.ts +2 -0
  327. package/src/modules/fulfillment/service.ts +17 -6
  328. package/src/modules/inventory/service.ts +15 -24
  329. package/src/modules/media/module.ts +2 -0
  330. package/src/modules/media/schema.ts +23 -2
  331. package/src/modules/media/service.ts +89 -28
  332. package/src/modules/orders/guest-access.ts +55 -0
  333. package/src/modules/orders/module.ts +1 -0
  334. package/src/modules/orders/quote.ts +1 -0
  335. package/src/modules/orders/repository/index.ts +2 -0
  336. package/src/modules/orders/schema.ts +5 -3
  337. package/src/modules/orders/service.ts +302 -52
  338. package/src/modules/pricing/module.ts +2 -0
  339. package/src/modules/pricing/schema.ts +1 -0
  340. package/src/modules/pricing/schemas.ts +1 -0
  341. package/src/modules/pricing/service.ts +21 -18
  342. package/src/modules/promotions/module.ts +2 -0
  343. package/src/modules/promotions/service.ts +25 -16
  344. package/src/modules/search/adapter.ts +8 -0
  345. package/src/modules/search/module.ts +3 -0
  346. package/src/modules/search/service.ts +142 -12
  347. package/src/modules/settings/module.ts +2 -0
  348. package/src/modules/settings/service.ts +8 -4
  349. package/src/modules/shipping/service.ts +9 -9
  350. package/src/modules/tax/module.ts +1 -0
  351. package/src/modules/tax/service.ts +13 -9
  352. package/src/modules/webhooks/hook.ts +2 -2
  353. package/src/modules/webhooks/module.ts +2 -0
  354. package/src/modules/webhooks/service.ts +6 -4
  355. package/src/runtime/server.ts +16 -2
  356. package/src/test-utils/create-pglite-adapter.ts +34 -12
  357. package/src/test-utils/create-test-config.ts +10 -6
  358. package/src/test-utils/rest-api-test-utils.ts +2 -0
  359. package/src/test-utils/test-actors.ts +2 -2
  360. package/src/utils/id.ts +20 -0
@@ -1,5 +1,5 @@
1
1
  import type { CommerceConfig } from "../../config/types.js";
2
- import { resolveOrgId } from "../../auth/org.js";
2
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
3
3
  import type { Actor } from "../../auth/types.js";
4
4
  import { CommerceNotFoundError, CommerceValidationError } from "../../kernel/errors.js";
5
5
  import { Err, Ok, type Result } from "../../kernel/result.js";
@@ -147,7 +147,7 @@ export class ShippingService {
147
147
  if (input.countries.length === 0) {
148
148
  return Err(new CommerceValidationError("A shipping zone requires at least one country (\"*\" matches any)."));
149
149
  }
150
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
150
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
151
151
  const zone = await this.deps.repository.createZone(
152
152
  {
153
153
  organizationId: orgId,
@@ -163,7 +163,7 @@ export class ShippingService {
163
163
  }
164
164
 
165
165
  async listZones(actor?: Actor | null, ctx?: TxContext): Promise<Result<ShippingZone[]>> {
166
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
166
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
167
167
  return Ok(await this.deps.repository.findZones(orgId, ctx));
168
168
  }
169
169
 
@@ -179,7 +179,7 @@ export class ShippingService {
179
179
  actor?: Actor | null,
180
180
  ctx?: TxContext,
181
181
  ): Promise<Result<ShippingZone>> {
182
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
182
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
183
183
  const existing = await this.deps.repository.findZoneById(orgId, id, ctx);
184
184
  if (!existing) return Err(new CommerceNotFoundError("Shipping zone not found."));
185
185
  const updated = await this.deps.repository.updateZone(
@@ -201,7 +201,7 @@ export class ShippingService {
201
201
  }
202
202
 
203
203
  async deleteZone(id: string, actor?: Actor | null, ctx?: TxContext): Promise<Result<{ deleted: true }>> {
204
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
204
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
205
205
  const existing = await this.deps.repository.findZoneById(orgId, id, ctx);
206
206
  if (!existing) return Err(new CommerceNotFoundError("Shipping zone not found."));
207
207
  await this.deps.repository.deleteZone(id, ctx);
@@ -224,7 +224,7 @@ export class ShippingService {
224
224
  actor?: Actor | null,
225
225
  ctx?: TxContext,
226
226
  ): Promise<Result<ShippingRate>> {
227
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
227
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
228
228
  const zone = await this.deps.repository.findZoneById(orgId, input.zoneId, ctx);
229
229
  if (!zone) return Err(new CommerceNotFoundError("Shipping zone not found."));
230
230
  const rate = await this.deps.repository.createRate(
@@ -251,7 +251,7 @@ export class ShippingService {
251
251
  actor?: Actor | null,
252
252
  ctx?: TxContext,
253
253
  ): Promise<Result<ShippingRate[]>> {
254
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
254
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
255
255
  return Ok(
256
256
  await this.deps.repository.findRates(
257
257
  orgId,
@@ -277,7 +277,7 @@ export class ShippingService {
277
277
  actor?: Actor | null,
278
278
  ctx?: TxContext,
279
279
  ): Promise<Result<ShippingRate>> {
280
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
280
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
281
281
  const existing = await this.deps.repository.findRateById(orgId, id, ctx);
282
282
  if (!existing) return Err(new CommerceNotFoundError("Shipping rate not found."));
283
283
  const updated = await this.deps.repository.updateRate(
@@ -301,7 +301,7 @@ export class ShippingService {
301
301
  }
302
302
 
303
303
  async deleteRate(id: string, actor?: Actor | null, ctx?: TxContext): Promise<Result<{ deleted: true }>> {
304
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
304
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
305
305
  const existing = await this.deps.repository.findRateById(orgId, id, ctx);
306
306
  if (!existing) return Err(new CommerceNotFoundError("Shipping rate not found."));
307
307
  await this.deps.repository.deleteRate(id, ctx);
@@ -16,5 +16,6 @@ export const taxModule = defineModule<
16
16
  new TaxService({
17
17
  adapter: (deps.config as CommerceConfig).tax?.adapter,
18
18
  repository: new TaxRatesRepository(deps.db.db as DrizzleDatabase),
19
+ config: deps.config as CommerceConfig,
19
20
  }),
20
21
  });
@@ -1,5 +1,6 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  import type { Actor } from "../../auth/types.js";
3
+ import type { CommerceConfig } from "../../config/types.js";
3
4
  import type { TxContext } from "../../kernel/database/tx-context.js";
4
5
  import { CommerceNotFoundError, CommerceValidationError } from "../../kernel/errors.js";
5
6
  import { Err, Ok, type Result } from "../../kernel/result.js";
@@ -15,15 +16,18 @@ import type { TaxClass, TaxRate, TaxRatesRepository } from "./repository/index.j
15
16
  interface TaxServiceDeps {
16
17
  adapter: TaxAdapter | undefined;
17
18
  repository?: TaxRatesRepository;
19
+ config: CommerceConfig;
18
20
  }
19
21
 
20
22
  export class TaxService {
21
23
  private adapter: TaxAdapter | undefined;
22
24
  private repository: TaxRatesRepository | undefined;
25
+ private config: CommerceConfig;
23
26
 
24
27
  constructor(deps: TaxServiceDeps) {
25
28
  this.adapter = deps.adapter;
26
29
  this.repository = deps.repository;
30
+ this.config = deps.config;
27
31
  }
28
32
 
29
33
  /**
@@ -176,7 +180,7 @@ export class TaxService {
176
180
  if (input.rateBps < 0) {
177
181
  return Err(new CommerceValidationError("rateBps must be non-negative."));
178
182
  }
179
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
183
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
180
184
  if (input.isDefault) await repo.value.clearDefaultClass(orgId, ctx);
181
185
  const created = await repo.value.createClass(
182
186
  {
@@ -194,7 +198,7 @@ export class TaxService {
194
198
  async listTaxClasses(actor?: Actor | null, ctx?: TxContext): Promise<Result<TaxClass[]>> {
195
199
  const repo = this.requireRepository();
196
200
  if (!repo.ok) return repo;
197
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
201
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
198
202
  return Ok(await repo.value.findAllClasses(orgId, ctx));
199
203
  }
200
204
 
@@ -206,7 +210,7 @@ export class TaxService {
206
210
  ): Promise<Result<TaxClass>> {
207
211
  const repo = this.requireRepository();
208
212
  if (!repo.ok) return repo;
209
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
213
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
210
214
  const existing = await repo.value.findClassById(orgId, id, ctx);
211
215
  if (!existing) return Err(new CommerceNotFoundError("Tax class not found."));
212
216
  if (patch.isDefault) await repo.value.clearDefaultClass(orgId, ctx);
@@ -226,7 +230,7 @@ export class TaxService {
226
230
  async deleteTaxClass(id: string, actor?: Actor | null, ctx?: TxContext): Promise<Result<{ deleted: true }>> {
227
231
  const repo = this.requireRepository();
228
232
  if (!repo.ok) return repo;
229
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
233
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
230
234
  const existing = await repo.value.findClassById(orgId, id, ctx);
231
235
  if (!existing) return Err(new CommerceNotFoundError("Tax class not found."));
232
236
  await repo.value.deleteClass(id, ctx);
@@ -297,7 +301,7 @@ export class TaxService {
297
301
  if (input.rateBps < 0) {
298
302
  return Err(new CommerceValidationError("rateBps must be non-negative."));
299
303
  }
300
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
304
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
301
305
  const rate = await repo.value.create(
302
306
  {
303
307
  organizationId: orgId,
@@ -317,7 +321,7 @@ export class TaxService {
317
321
  async listTaxRates(actor?: Actor | null, ctx?: TxContext): Promise<Result<TaxRate[]>> {
318
322
  const repo = this.requireRepository();
319
323
  if (!repo.ok) return repo;
320
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
324
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
321
325
  return Ok(await repo.value.findAll(orgId, ctx));
322
326
  }
323
327
 
@@ -337,7 +341,7 @@ export class TaxService {
337
341
  ): Promise<Result<TaxRate>> {
338
342
  const repo = this.requireRepository();
339
343
  if (!repo.ok) return repo;
340
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
344
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
341
345
  const existing = await repo.value.findById(orgId, id, ctx);
342
346
  if (!existing) return Err(new CommerceNotFoundError("Tax rate not found."));
343
347
  const updated = await repo.value.update(
@@ -361,7 +365,7 @@ export class TaxService {
361
365
  async deleteTaxRate(id: string, actor?: Actor | null, ctx?: TxContext): Promise<Result<{ deleted: true }>> {
362
366
  const repo = this.requireRepository();
363
367
  if (!repo.ok) return repo;
364
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
368
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
365
369
  const existing = await repo.value.findById(orgId, id, ctx);
366
370
  if (!existing) return Err(new CommerceNotFoundError("Tax rate not found."));
367
371
  await repo.value.delete(id, ctx);
@@ -1,4 +1,4 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  import type { AfterHook } from "../../kernel/hooks/types.js";
3
3
 
4
4
  /**
@@ -20,7 +20,7 @@ export const deliverWebhooks: AfterHook<unknown> = async ({ result, operation, c
20
20
  // VAPT r2 (codex) finding: fan-out queried ALL endpoints across the
21
21
  // database, so Tenant B's webhooks fired on Tenant A's events —
22
22
  // payload-level cross-tenant data leak. Now scoped to the actor's org.
23
- const orgId = resolveOrgId(context.actor);
23
+ const orgId = resolveOrgIdForCommerce(context.actor, context.commerceConfig);
24
24
 
25
25
  const endpoints = await webhooksService.getEndpointsForEvent(eventName, orgId);
26
26
  if (!endpoints.ok) return;
@@ -1,3 +1,4 @@
1
+ import type { CommerceConfig } from "../../config/types.js";
1
2
  import { defineModule } from "../../kernel/module/index.js";
2
3
  import type { DrizzleDatabase } from "../../kernel/database/drizzle-db.js";
3
4
  import { WebhooksRepository } from "./repository/index.js";
@@ -18,5 +19,6 @@ export const webhooksModule = defineModule({
18
19
  service: (deps) =>
19
20
  new WebhookService({
20
21
  repository: new WebhooksRepository(deps.db.db as DrizzleDatabase),
22
+ config: deps.config as CommerceConfig,
21
23
  }),
22
24
  });
@@ -1,5 +1,6 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  import type { Actor } from "../../auth/types.js";
3
+ import type { CommerceConfig } from "../../config/types.js";
3
4
  import { CommerceNotFoundError, CommerceValidationError } from "../../kernel/errors.js";
4
5
  import { Err, Ok, type Result } from "../../kernel/result.js";
5
6
  import type { TxContext } from "../../kernel/database/tx-context.js";
@@ -49,6 +50,7 @@ function isPrivateUrl(urlStr: string): boolean {
49
50
 
50
51
  interface WebhookServiceDeps {
51
52
  repository: WebhooksRepository;
53
+ config: CommerceConfig;
52
54
  }
53
55
 
54
56
  export class WebhookService {
@@ -76,7 +78,7 @@ export class WebhookService {
76
78
  );
77
79
  }
78
80
 
79
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
81
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
80
82
 
81
83
  const endpoint = await this.repo.createEndpoint(
82
84
  {
@@ -96,7 +98,7 @@ export class WebhookService {
96
98
  actor?: Actor | null,
97
99
  ctx?: TxContext,
98
100
  ): Promise<Result<WebhookEndpoint[]>> {
99
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
101
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
100
102
  const endpoints = await this.repo.findAllEndpoints(orgId, ctx);
101
103
  return Ok(endpoints);
102
104
  }
@@ -106,7 +108,7 @@ export class WebhookService {
106
108
  actor?: Actor | null,
107
109
  ctx?: TxContext,
108
110
  ): Promise<Result<void>> {
109
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
111
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
110
112
  const existing = await this.repo.findEndpointById(id, orgId, ctx);
111
113
  if (!existing) {
112
114
  return Err(new CommerceNotFoundError("Webhook endpoint not found."));
@@ -11,6 +11,8 @@ import type { Actor } from "../auth/types.js";
11
11
  import type { AuthInstance } from "../auth/setup.js";
12
12
  import type { CommerceConfig } from "../config/types.js";
13
13
  import { authMiddleware } from "../auth/middleware.js";
14
+ import { organizationGuard } from "../auth/organization-guard.js";
15
+ import type { DrizzleDatabase } from "../kernel/database/drizzle-db.js";
14
16
  import { CommerceCsrfError } from "../kernel/errors.js";
15
17
  import { createRestRoutes } from "../interfaces/rest/index.js";
16
18
  import { createCustomerPortalRoutes } from "../interfaces/rest/customer-portal.js";
@@ -20,6 +22,8 @@ import { createLogger, type Logger } from "./logger.js";
20
22
  import { createCommerce, type CommerceInstance } from "./commerce.js";
21
23
  import { rewriteCommerceAliasRequest } from "./url-alias-rewrite.js";
22
24
  import { mapErrorToResponse } from "../kernel/error-mapper.js";
25
+ import { assertRouteCoverage } from "../interfaces/rest/route-coverage.js";
26
+ import { markRoutePermissionGuard } from "../interfaces/rest/utils.js";
23
27
 
24
28
  type ServerEnv = {
25
29
  Variables: {
@@ -320,6 +324,14 @@ export async function createServer(config: CommerceConfig) {
320
324
  }
321
325
 
322
326
  // ─── Auth ──────────────────────────────────────────────────────────
327
+ // Better Auth's organization endpoints are mounted below but governed here:
328
+ // `admin/staff.ts` owns membership, and this guard keeps the plugin's own
329
+ // paths from minting members outside those rules.
330
+ app.use(
331
+ "/api/auth/organization/*",
332
+ organizationGuard(kernel.database.db as DrizzleDatabase, config),
333
+ );
334
+
323
335
  app.use("/api/auth/*", async (c, next) => {
324
336
  if (c.req.path.startsWith("/api/auth/pos/")) {
325
337
  await next();
@@ -433,7 +445,7 @@ export async function createServer(config: CommerceConfig) {
433
445
  // Strategy 1: Built-in cron endpoint for serverless deployments.
434
446
  // Point Vercel Cron or Cloudflare Cron Trigger at GET /api/jobs/run
435
447
  // Optional query params: ?queue=emails&limit=20
436
- app.get("/api/jobs/run", async (c) => {
448
+ app.get("/api/jobs/run", markRoutePermissionGuard(async (c) => {
437
449
  // Always require admin — cron triggers must authenticate
438
450
  const actor = c.get("actor") as { permissions?: string[] } | null;
439
451
  if (!actor?.permissions?.includes("*:*")) {
@@ -450,7 +462,7 @@ export async function createServer(config: CommerceConfig) {
450
462
  logger.error({ err }, "Job runner endpoint failed");
451
463
  return c.json({ error: { code: "INTERNAL_ERROR", message: "Job processing failed" } }, 500);
452
464
  }
453
- });
465
+ }));
454
466
 
455
467
  // Strategy 2: In-process polling for long-running servers (ECS, Cloud Run, Docker).
456
468
  // Enable via config.jobs.autorun.enabled = true
@@ -488,6 +500,8 @@ export async function createServer(config: CommerceConfig) {
488
500
  }
489
501
  }
490
502
 
503
+ assertRouteCoverage(app);
504
+
491
505
  const dispatchFetch = app.fetch.bind(app);
492
506
  app.fetch = ((input: RequestInfo | URL, env?: unknown, executionCtx?: unknown) => {
493
507
  const req = input instanceof Request ? input : new Request(input);
@@ -82,20 +82,42 @@ export async function createPGliteTestAdapter(): Promise<{
82
82
  /**
83
83
  * PGlite-compatible transaction wrapper.
84
84
  *
85
- * Drizzle's transaction() method can hang with PGlite due to how
86
- * the adapter manages transaction state. This implementation uses
87
- * manual BEGIN/COMMIT control which works more reliably.
85
+ * Drizzle's transaction() method can hang with PGlite due to how the adapter
86
+ * manages transaction state, so this drives BEGIN/COMMIT manually.
87
+ *
88
+ * PGlite is a single connection, so two transaction bodies awaiting
89
+ * concurrently would otherwise interleave their statements between one
90
+ * BEGIN and one COMMIT — the second BEGIN is a no-op Postgres only warns
91
+ * about. Merged that way, two callers share a snapshot and hold each other's
92
+ * row locks, so an isolation bug reads as if the guard failed. Bodies are
93
+ * queued instead, which is what a connection pool would do to two
94
+ * transactions competing for the same rows.
95
+ *
96
+ * A nested call joins the transaction already open rather than deadlocking
97
+ * on the queue; without savepoints that is the only sound reading.
88
98
  */
99
+ let transactionQueue: Promise<unknown> = Promise.resolve();
100
+ let inTransaction = false;
101
+
89
102
  async function transaction<T>(fn: (tx: unknown) => Promise<T>): Promise<T> {
90
- await pg.exec("BEGIN");
91
- try {
92
- const result = await fn(db);
93
- await pg.exec("COMMIT");
94
- return result;
95
- } catch (error) {
96
- await pg.exec("ROLLBACK");
97
- throw error;
98
- }
103
+ if (inTransaction) return fn(db);
104
+
105
+ const run = transactionQueue.then(async () => {
106
+ inTransaction = true;
107
+ await pg.exec("BEGIN");
108
+ try {
109
+ const result = await fn(db);
110
+ await pg.exec("COMMIT");
111
+ return result;
112
+ } catch (error) {
113
+ await pg.exec("ROLLBACK");
114
+ throw error;
115
+ } finally {
116
+ inTransaction = false;
117
+ }
118
+ });
119
+ transactionQueue = run.catch(() => undefined);
120
+ return run as Promise<T>;
99
121
  }
100
122
 
101
123
  const adapter: DatabaseAdapter = {
@@ -78,11 +78,13 @@ export async function createTestConfig(
78
78
  "catalog:update",
79
79
  "catalog:delete",
80
80
  "catalog:read",
81
+ "catalog:read:unpublished",
81
82
  "inventory:adjust",
82
83
  "orders:create",
83
84
  "orders:read",
84
85
  "orders:update",
85
86
  "orders:manage",
87
+ "orders:create:on-behalf",
86
88
  "cart:create",
87
89
  "cart:update",
88
90
  "customers:update:self",
@@ -91,14 +93,16 @@ export async function createTestConfig(
91
93
  ai_agent: {
92
94
  permissions: [
93
95
  "catalog:read",
96
+ "catalog:read:unpublished",
94
97
  "catalog:create",
95
98
  "inventory:read",
96
- "inventory:adjust",
97
- "orders:read",
98
- "cart:create",
99
- "cart:update",
100
- ],
101
- },
99
+ "inventory:adjust",
100
+ "orders:read",
101
+ "orders:create:on-behalf",
102
+ "cart:create",
103
+ "cart:update",
104
+ ],
105
+ },
102
106
  },
103
107
  customerPermissions: [
104
108
  "catalog:read",
@@ -158,9 +158,11 @@ export const testActor: Actor = {
158
158
  "catalog:create",
159
159
  "catalog:update",
160
160
  "catalog:read",
161
+ "catalog:read:unpublished",
161
162
  "inventory:adjust",
162
163
  "inventory:read",
163
164
  "orders:create",
165
+ "orders:create:on-behalf",
164
166
  "orders:read",
165
167
  "orders:update",
166
168
  "orders:manage",
@@ -31,8 +31,8 @@ export const testStaffActor: Actor = {
31
31
  organizationId: TEST_ORG_ID,
32
32
  role: "staff",
33
33
  permissions: [
34
- "catalog:read", "catalog:create", "catalog:update",
35
- "inventory:adjust", "orders:read", "orders:create", "orders:update", "orders:manage",
34
+ "catalog:read", "catalog:read:unpublished", "catalog:create", "catalog:update",
35
+ "inventory:adjust", "orders:read", "orders:create", "orders:create:on-behalf", "orders:update", "orders:manage",
36
36
  ],
37
37
  };
38
38
 
package/src/utils/id.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { Actor } from "../auth/types.js";
2
+
1
3
  export function makeId(): string {
2
4
  return crypto.randomUUID();
3
5
  }
@@ -12,3 +14,21 @@ export async function makeDeterministicId(value: string): Promise<string> {
12
14
  const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
13
15
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14
16
  }
17
+
18
+ export async function makeIdempotencyScope(
19
+ actor: Actor | null | undefined,
20
+ guestCredential?: string,
21
+ fallbackBinding?: string,
22
+ ): Promise<string> {
23
+ const binding = actor?.userId
24
+ ? `actor:${actor.type}:${actor.userId}`
25
+ : guestCredential
26
+ ? `guest:${guestCredential}`
27
+ : fallbackBinding
28
+ ? `resource:${fallbackBinding}`
29
+ : "anonymous";
30
+ const digest = new Uint8Array(
31
+ await crypto.subtle.digest("SHA-256", new TextEncoder().encode(binding)),
32
+ );
33
+ return [...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("");
34
+ }