@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,7 +1,11 @@
1
- import { resolveOrgId } from "../../auth/org.js";
2
- import { assertOwnership, assertPermission } from "../../auth/permissions.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
+ import { assertOwnership, assertPermission, hasPermission } from "../../auth/permissions.js";
3
3
  import type { Actor } from "../../auth/types.js";
4
+ import { defaultGuestOrderAccess } from "./guest-access.js";
5
+ import type { CommerceConfig } from "../../config/types.js";
6
+ import { isCatalogEntityVisible } from "../catalog/read-policy.js";
4
7
  import {
8
+ CommerceConflictError,
5
9
  CommerceForbiddenError,
6
10
  CommerceInvalidTransitionError,
7
11
  CommerceNotFoundError,
@@ -25,6 +29,7 @@ import {
25
29
  } from "../../kernel/state-machine/machine.js";
26
30
  import { Err, Ok, type Result } from "../../kernel/result.js";
27
31
  import { createLogger } from "../../utils/logger.js";
32
+ import { makeIdempotencyScope } from "../../utils/id.js";
28
33
  import { paginate, type Pagination } from "../../utils/pagination.js";
29
34
  import {
30
35
  withTransaction,
@@ -99,12 +104,20 @@ export interface ChangeStatusInput {
99
104
  export interface OrderServiceDeps {
100
105
  repository: OrdersRepository;
101
106
  hooks: HookRegistry;
107
+ config: CommerceConfig;
102
108
  services: Record<string, unknown>;
103
109
  /** Custom state machine. If provided, overrides the default order transitions. */
104
110
  stateMachine?: StateDefinition<string>;
105
111
  database: DatabaseAdapter;
106
112
  }
107
113
 
114
+ export interface CreateOrderOptions {
115
+ trustedPricing?: boolean;
116
+ stockPolicy?: "reserve" | "backorder";
117
+ /** Credential presented by a guest cart owner for idempotent replay. */
118
+ guestCredential?: string;
119
+ }
120
+
108
121
  export type HydratedOrder = Order & { lineItems: OrderLineItem[] };
109
122
  type OrderListResult = {
110
123
  items: HydratedOrder[];
@@ -126,6 +139,7 @@ function context(
126
139
  actor: Actor | null,
127
140
  services: Record<string, unknown>,
128
141
  database: DatabaseAdapter,
142
+ config: CommerceConfig,
129
143
  tx: unknown = null,
130
144
  ): HookContext {
131
145
  return createHookContext({
@@ -136,6 +150,7 @@ function context(
136
150
  ...(services.jobs ? { jobs: services.jobs as JobsAdapter } : {}),
137
151
  context: { moduleName: "orders" },
138
152
  database: { db: database.db as PluginDb },
153
+ commerceConfig: config,
139
154
  });
140
155
  }
141
156
 
@@ -182,14 +197,18 @@ export class OrderService {
182
197
  }
183
198
  }
184
199
  const catalog = this.deps.services.catalog as {
185
- getById(
200
+ getByIdForInternalUse(
186
201
  id: string,
187
- options: Record<string, unknown>,
188
- actor?: Actor | null,
202
+ organizationId: string,
203
+ options?: Record<string, unknown>,
189
204
  ctx?: TxContext,
190
205
  ): Promise<{
191
206
  ok: boolean;
192
- value?: { variants?: Array<{ id: string }> };
207
+ value?: {
208
+ status?: string;
209
+ isVisible?: boolean;
210
+ variants?: Array<{ id: string }>;
211
+ };
193
212
  }>;
194
213
  };
195
214
  const pricing = this.deps.services.pricing as {
@@ -210,13 +229,25 @@ export class OrderService {
210
229
  > = [];
211
230
  for (const item of input.lineItems) {
212
231
  // Org-integrity — the referenced entity must belong to this order's org.
213
- const owned = await catalog.getById(
232
+ // This is an internal invariant check, so it reads past the storefront
233
+ // visibility policy; unprivileged buyers are gated in the same branch.
234
+ const owned = await catalog.getByIdForInternalUse(
214
235
  item.entityId,
236
+ resolveOrgIdForCommerce(actor, this.deps.config),
215
237
  { includeVariants: item.variantId !== undefined },
216
- actor,
217
238
  ctx,
218
239
  );
219
- if (!owned.ok) {
240
+ if (
241
+ !owned.ok ||
242
+ !owned.value ||
243
+ !isCatalogEntityVisible(
244
+ {
245
+ status: owned.value?.status ?? "draft",
246
+ isVisible: owned.value?.isVisible ?? false,
247
+ },
248
+ actor,
249
+ )
250
+ ) {
220
251
  return Err(
221
252
  new CommerceValidationError(
222
253
  `Line item entity ${item.entityId} does not belong to this organization.`,
@@ -266,11 +297,180 @@ export class OrderService {
266
297
  return Ok(resolved);
267
298
  }
268
299
 
300
+ private async resolveCreateCustomerId(
301
+ requestedCustomerId: string | undefined,
302
+ actor: Actor | null,
303
+ ctx?: TxContext,
304
+ ): Promise<string | undefined> {
305
+ // API keys are the documented POS operator actor. Keep this as an actor
306
+ // type predicate so self-service user actors remain unable to choose a
307
+ // foreign customerId even when they are authenticated.
308
+ const isOperator = actor?.type === "api_key";
309
+ if (isOperator) {
310
+ if (requestedCustomerId === undefined) return undefined;
311
+ return this.resolveRequestedCustomerId(requestedCustomerId, actor, ctx);
312
+ }
313
+
314
+ if (hasPermission(actor, "orders:create:on-behalf")) {
315
+ if (requestedCustomerId === undefined) return undefined;
316
+ return this.resolveRequestedCustomerId(requestedCustomerId, actor, ctx);
317
+ }
318
+
319
+ // `orders:read:own` is the system's existing "this actor is a shopper"
320
+ // marker -- it is in DEFAULT_CUSTOMER_PERMISSIONS and guards the read-own
321
+ // order routes. Using it here decides *attribution*, which is a proxy and is
322
+ // deliberately a stopgap: the honest discriminator is caller intent, which a
323
+ // storefront route knows and this service cannot see.
324
+ //
325
+ // Known misclassification: a dual-hatted role holding `orders:read:own` for
326
+ // its own personal orders, plus `orders:create`, self-attributes a walk-in
327
+ // sale. The proxy is tolerable only because it fails narrow -- it can attach
328
+ // the actor's own profile or fall through to a guest order, never expose
329
+ // another principal's data.
330
+ if (!hasPermission(actor, "orders:read:own")) return undefined;
331
+ if (!actor?.userId) return undefined;
332
+ const customers = this.deps.services.customers as
333
+ | {
334
+ getByUserId(
335
+ userId: string,
336
+ actor?: Actor | null,
337
+ ctx?: TxContext,
338
+ ): Promise<{ ok: boolean; value?: { id: string } }>;
339
+ }
340
+ | undefined;
341
+ if (!customers?.getByUserId) return undefined;
342
+ const own = await customers.getByUserId(actor.userId, actor, ctx);
343
+ return own.ok ? own.value?.id : undefined;
344
+ }
345
+
346
+ private async resolveRequestedCustomerId(
347
+ requestedCustomerId: string,
348
+ actor: Actor | null,
349
+ ctx?: TxContext,
350
+ ): Promise<string> {
351
+ const customers = this.deps.services.customers as
352
+ | {
353
+ getById(
354
+ id: string,
355
+ actor?: Actor | null,
356
+ ctx?: TxContext,
357
+ ): Promise<{ ok: boolean; value?: { id: string } }>;
358
+ }
359
+ | undefined;
360
+ const customer = await customers?.getById(requestedCustomerId, actor, ctx);
361
+ if (!customer?.ok || !customer.value) {
362
+ throw new CommerceValidationError(
363
+ "customerId must reference a customer in this organization.",
364
+ );
365
+ }
366
+ return customer.value.id;
367
+ }
368
+
369
+ private async authorizeOrderRead(
370
+ order: Order,
371
+ actor: Actor | null,
372
+ ctx?: TxContext,
373
+ guestCredential?: string,
374
+ ): Promise<Result<void>> {
375
+ try {
376
+ if (
377
+ actor?.permissions.includes("orders:read") ||
378
+ actor?.permissions.includes("*:*")
379
+ ) {
380
+ // no-op
381
+ } else if (actor?.permissions.includes("orders:read:own")) {
382
+ if (order.customerId == null) {
383
+ const cartId =
384
+ typeof order.metadata?.cartId === "string"
385
+ ? order.metadata.cartId
386
+ : undefined;
387
+ const cart = this.deps.services.cart as
388
+ | {
389
+ getById(
390
+ id: string,
391
+ actor?: Actor | null,
392
+ ctx?: TxContext,
393
+ secret?: string,
394
+ ): Promise<{ ok: boolean }>;
395
+ }
396
+ | undefined;
397
+ if (!cartId || !guestCredential || !cart?.getById) {
398
+ throw new CommerceForbiddenError("You do not have access to this resource.");
399
+ }
400
+ const guestCart = await cart.getById(
401
+ cartId,
402
+ actor,
403
+ ctx,
404
+ guestCredential,
405
+ );
406
+ if (!guestCart.ok) {
407
+ throw new CommerceForbiddenError("You do not have access to this resource.");
408
+ }
409
+ // The secret is genuine, but a bearer credential with no lifetime
410
+ // reads this order forever — and a secret leaks far more easily than
411
+ // it is guessed. Bound it to a window after placement, and fail with
412
+ // the identical error so a stale window is not an oracle telling the
413
+ // caller their secret is valid.
414
+ const guestAccess =
415
+ this.deps.config.orders?.guestAccessStrategy ?? defaultGuestOrderAccess;
416
+ if (!guestAccess.canAccessOrder(order, new Date())) {
417
+ throw new CommerceForbiddenError("You do not have access to this resource.");
418
+ }
419
+ } else {
420
+ // Older integrations may have stored the auth user ID directly as
421
+ // customerId. Keep that valid ownership shape while resolving the
422
+ // normal auth-user -> customer-profile relationship below.
423
+ let ownerActor = actor;
424
+ if (actor.userId !== order.customerId) {
425
+ const customers = this.deps.services.customers as
426
+ | {
427
+ getByUserId(
428
+ userId: string,
429
+ actor?: Actor | null,
430
+ ctx?: TxContext,
431
+ ): Promise<{ ok: boolean; value?: { id: string } }>;
432
+ }
433
+ | undefined;
434
+ const profile = actor.userId && customers?.getByUserId
435
+ ? await customers.getByUserId(actor.userId, actor, ctx)
436
+ : { ok: false as const };
437
+ ownerActor = profile.ok
438
+ ? { ...actor, userId: profile.value!.id }
439
+ : actor;
440
+ }
441
+ assertOwnership(ownerActor, order.customerId);
442
+ }
443
+ } else {
444
+ assertPermission(actor, "orders:read");
445
+ }
446
+ } catch (error) {
447
+ return Err(toCommerceError(error));
448
+ }
449
+ return Ok(undefined);
450
+ }
451
+
452
+ private async authorizedReplay(
453
+ order: Order,
454
+ actor: Actor | null,
455
+ ctx?: TxContext,
456
+ guestCredential?: string,
457
+ ): Promise<Result<HydratedOrder>> {
458
+ const access = await this.authorizeOrderRead(order, actor, ctx, guestCredential);
459
+ if (!access.ok) {
460
+ return Err(
461
+ new CommerceConflictError(
462
+ "Idempotency key does not belong to this account.",
463
+ ),
464
+ );
465
+ }
466
+ return Ok(await this.hydrateOrder(order, ctx));
467
+ }
468
+
269
469
  async create(
270
470
  input: CreateOrderInput,
271
471
  actor: Actor | null,
272
472
  ctx?: TxContext,
273
- opts?: { trustedPricing?: boolean; stockPolicy?: "reserve" | "backorder" },
473
+ opts?: CreateOrderOptions,
274
474
  ): Promise<Result<HydratedOrder>> {
275
475
  if (opts?.stockPolicy === "reserve" && !ctx) {
276
476
  return withTransaction(this.deps.database, { actor }, (txCtx) =>
@@ -290,22 +490,49 @@ export class OrderService {
290
490
  );
291
491
  }
292
492
 
493
+ let resolvedCustomerId: string | undefined;
494
+ try {
495
+ resolvedCustomerId = await this.resolveCreateCustomerId(
496
+ input.customerId,
497
+ actor,
498
+ ctx,
499
+ );
500
+ } catch (error) {
501
+ return Err(toCommerceError(error));
502
+ }
503
+ const serviceInput: CreateOrderInput = {
504
+ ...input,
505
+ ...(resolvedCustomerId !== undefined
506
+ ? { customerId: resolvedCustomerId }
507
+ : {}),
508
+ };
509
+ if (resolvedCustomerId === undefined) delete serviceInput.customerId;
510
+
293
511
  const beforeHooks = this.deps.hooks.resolve(
294
512
  "orders.beforeCreate",
295
513
  ) as BeforeCreateOrderHook[];
296
514
  const afterHooks = this.deps.hooks.resolve(
297
515
  "orders.afterCreate",
298
516
  ) as AfterCreateOrderHook[];
299
- const hookCtx = context(actor, this.deps.services, this.deps.database, ctx?.tx);
517
+ const hookCtx = context(actor, this.deps.services, this.deps.database, this.deps.config, ctx?.tx);
300
518
 
301
519
  const processed = await runBeforeHooks(
302
520
  beforeHooks,
303
- input,
521
+ serviceInput,
304
522
  "create",
305
523
  hookCtx,
306
524
  );
307
525
 
308
- const orgId = resolveOrgId(actor);
526
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
527
+ const idempotencyScope = processed.idempotencyKey
528
+ ? await makeIdempotencyScope(
529
+ actor,
530
+ opts?.guestCredential,
531
+ typeof processed.metadata?.cartId === "string"
532
+ ? processed.metadata.cartId
533
+ : undefined,
534
+ )
535
+ : undefined;
309
536
 
310
537
  // Idempotent replay: offline POS queues and network retries re-submit the
311
538
  // same create — return the original order instead of double-creating.
@@ -313,10 +540,16 @@ export class OrderService {
313
540
  const existing = await this.repo.findByIdempotencyKey(
314
541
  orgId,
315
542
  processed.idempotencyKey,
543
+ idempotencyScope!,
316
544
  ctx,
317
545
  );
318
546
  if (existing) {
319
- return Ok(await this.hydrateOrder(existing, ctx));
547
+ return this.authorizedReplay(
548
+ existing,
549
+ actor,
550
+ ctx,
551
+ opts?.guestCredential,
552
+ );
320
553
  }
321
554
  }
322
555
 
@@ -394,6 +627,7 @@ export class OrderService {
394
627
  ...(processed.paymentIntentId != null ? { paymentIntentId: processed.paymentIntentId } : {}),
395
628
  ...(processed.paymentMethodId != null ? { paymentMethodId: processed.paymentMethodId } : {}),
396
629
  ...(processed.idempotencyKey != null ? { idempotencyKey: processed.idempotencyKey } : {}),
630
+ ...(idempotencyScope !== undefined ? { idempotencyScope } : {}),
397
631
  metadata: processed.metadata ?? {},
398
632
  placedAt: new Date(),
399
633
  ...(processed.customerId !== undefined
@@ -408,9 +642,17 @@ export class OrderService {
408
642
  const winner = await this.repo.findByIdempotencyKey(
409
643
  orgId,
410
644
  processed.idempotencyKey,
645
+ idempotencyScope!,
411
646
  ctx,
412
647
  );
413
- if (winner) return Ok(await this.hydrateOrder(winner, ctx));
648
+ if (winner) {
649
+ return this.authorizedReplay(
650
+ winner,
651
+ actor,
652
+ ctx,
653
+ opts?.guestCredential,
654
+ );
655
+ }
414
656
  }
415
657
  throw error;
416
658
  }
@@ -503,25 +745,19 @@ export class OrderService {
503
745
  id: string,
504
746
  actor: Actor | null,
505
747
  ctx?: TxContext,
748
+ guestCredential?: string,
506
749
  ): Promise<Result<HydratedOrder>> {
507
- const orgId = resolveOrgId(actor);
750
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
508
751
  const order = await this.repo.findById(orgId, id, ctx);
509
752
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
510
753
 
511
- try {
512
- if (
513
- actor?.permissions.includes("orders:read") ||
514
- actor?.permissions.includes("*:*")
515
- ) {
516
- // no-op
517
- } else if (actor?.permissions.includes("orders:read:own")) {
518
- assertOwnership(actor, order.customerId ?? null);
519
- } else {
520
- assertPermission(actor, "orders:read");
521
- }
522
- } catch (error) {
523
- return Err(toCommerceError(error));
524
- }
754
+ const access = await this.authorizeOrderRead(
755
+ order,
756
+ actor,
757
+ ctx,
758
+ guestCredential,
759
+ );
760
+ if (!access.ok) return access;
525
761
 
526
762
  const hydrated = await this.hydrateOrder(order, ctx);
527
763
 
@@ -530,7 +766,7 @@ export class OrderService {
530
766
  "orders.afterGet",
531
767
  ) as AfterHook<HydratedOrder>[];
532
768
  if (afterGetHooks.length > 0) {
533
- const hookCtx = context(actor, this.deps.services, this.deps.database, ctx?.tx);
769
+ const hookCtx = context(actor, this.deps.services, this.deps.database, this.deps.config, ctx?.tx);
534
770
  await runAfterHooks(afterGetHooks, null, hydrated, "read", hookCtx);
535
771
  }
536
772
 
@@ -541,11 +777,12 @@ export class OrderService {
541
777
  orderNumber: string,
542
778
  actor: Actor | null,
543
779
  ctx?: TxContext,
780
+ guestCredential?: string,
544
781
  ): Promise<Result<HydratedOrder>> {
545
- const orgId = resolveOrgId(actor);
782
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
546
783
  const order = await this.repo.findByOrderNumber(orgId, orderNumber, ctx);
547
784
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
548
- return this.getById(order.id, actor, ctx);
785
+ return this.getById(order.id, actor, ctx, guestCredential);
549
786
  }
550
787
 
551
788
  /** Returns the order previously created with this idempotency key, or null. */
@@ -553,11 +790,24 @@ export class OrderService {
553
790
  idempotencyKey: string,
554
791
  actor?: Actor | null,
555
792
  ctx?: TxContext,
793
+ guestCredential?: string,
556
794
  ): Promise<Result<HydratedOrder | null>> {
557
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
558
- const order = await this.repo.findByIdempotencyKey(orgId, idempotencyKey, ctx);
795
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
796
+ const resolvedActor = actor ?? ctx?.actor ?? null;
797
+ const idempotencyScope = await makeIdempotencyScope(resolvedActor, guestCredential);
798
+ const order = await this.repo.findByIdempotencyKey(
799
+ orgId,
800
+ idempotencyKey,
801
+ idempotencyScope,
802
+ ctx,
803
+ );
559
804
  if (!order) return Ok(null);
560
- return Ok(await this.hydrateOrder(order, ctx));
805
+ return this.authorizedReplay(
806
+ order,
807
+ actor ?? ctx?.actor ?? null,
808
+ ctx,
809
+ guestCredential,
810
+ );
561
811
  }
562
812
 
563
813
  async list(
@@ -571,7 +821,7 @@ export class OrderService {
571
821
  return Err(toCommerceError(error));
572
822
  }
573
823
 
574
- const orgId = resolveOrgId(actor);
824
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
575
825
  let items: Order[];
576
826
  if (params.status) {
577
827
  items = await this.repo.findByStatus(orgId, params.status, ctx);
@@ -599,7 +849,7 @@ export class OrderService {
599
849
  actor?: Actor | null,
600
850
  ctx?: TxContext,
601
851
  ): Promise<Result<OrderListResult>> {
602
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
852
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
603
853
  let items = await this.repo.findByCustomerId(orgId, customerId, ctx);
604
854
 
605
855
  if (params.status) {
@@ -670,7 +920,7 @@ export class OrderService {
670
920
  return Ok({ items: [], hint: "Enter at least 3 characters to search." });
671
921
  }
672
922
 
673
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
923
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
674
924
  const rows = await this.repo.lookup(orgId, term, opts, ctx);
675
925
  const items = rows.map((r) => ({
676
926
  id: r.id,
@@ -694,7 +944,7 @@ export class OrderService {
694
944
  actor: Actor | null,
695
945
  ctx?: TxContext,
696
946
  ): Promise<Result<HydratedOrder>> {
697
- const orgId = resolveOrgId(actor);
947
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
698
948
  const order = await this.repo.findById(orgId, input.orderId, ctx);
699
949
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
700
950
 
@@ -725,7 +975,7 @@ export class OrderService {
725
975
  "orders.afterStatusChange",
726
976
  ) as AfterStatusChangeHook[];
727
977
 
728
- const hookCtx = context(actor, this.deps.services, this.deps.database, ctx?.tx);
978
+ const hookCtx = context(actor, this.deps.services, this.deps.database, this.deps.config, ctx?.tx);
729
979
  const statusHookInput: StatusChangeHookInput = {
730
980
  orderId: order.id,
731
981
  fromStatus: order.status as OrderState,
@@ -1057,7 +1307,7 @@ export class OrderService {
1057
1307
  } catch (error) {
1058
1308
  return Err(toCommerceError(error));
1059
1309
  }
1060
- const orgId = resolveOrgId(actor);
1310
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
1061
1311
  const found = await this.repo.findWithLineItems(orgId, orderId, ctx);
1062
1312
  if (!found) return Err(new CommerceNotFoundError("Order not found."));
1063
1313
  if (input.lines.length === 0) {
@@ -1206,7 +1456,7 @@ export class OrderService {
1206
1456
  } catch (error) {
1207
1457
  return Err(toCommerceError(error));
1208
1458
  }
1209
- const orgId = resolveOrgId(actor);
1459
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
1210
1460
  const refund = await this.repo.findRefundById(orgId, refundId, ctx);
1211
1461
  if (!refund || refund.orderId !== orderId) {
1212
1462
  return Err(new CommerceNotFoundError("Refund not found."));
@@ -1265,7 +1515,7 @@ export class OrderService {
1265
1515
  } catch (error) {
1266
1516
  return Err(toCommerceError(error));
1267
1517
  }
1268
- const orgId = resolveOrgId(actor);
1518
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
1269
1519
  const order = await this.repo.findById(orgId, orderId, ctx);
1270
1520
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
1271
1521
  return Ok(await this.repo.findRefundsByOrderId(orderId, ctx));
@@ -1281,7 +1531,7 @@ export class OrderService {
1281
1531
  } catch (error) {
1282
1532
  return Err(toCommerceError(error));
1283
1533
  }
1284
- const orgId = resolveOrgId(actor);
1534
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
1285
1535
  const policies = await this.refundPolicies(orgId, ctx);
1286
1536
  const usedToday = await this.repo.sumRefundsByOperatorToday(
1287
1537
  orgId,
@@ -1309,7 +1559,7 @@ export class OrderService {
1309
1559
  } catch (error) {
1310
1560
  return Err(toCommerceError(error));
1311
1561
  }
1312
- const orgId = resolveOrgId(actor);
1562
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
1313
1563
  const order = await this.repo.findById(orgId, orderId, ctx);
1314
1564
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
1315
1565
  return Ok(order);
@@ -1446,7 +1696,7 @@ export class OrderService {
1446
1696
  opts?: { amount?: number },
1447
1697
  ctx?: TxContext,
1448
1698
  ): Promise<Result<HydratedOrder>> {
1449
- const orgId = resolveOrgId(actor);
1699
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
1450
1700
  const order = await this.repo.findById(orgId, orderId, ctx);
1451
1701
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
1452
1702
 
@@ -1515,7 +1765,7 @@ export class OrderService {
1515
1765
  actor?: Actor | null,
1516
1766
  ctx?: TxContext,
1517
1767
  ): Promise<Result<OrderStatusHistory[]>> {
1518
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
1768
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
1519
1769
  const order = await this.repo.findById(orgId, orderId, ctx);
1520
1770
  if (!order) {
1521
1771
  return Err(new CommerceNotFoundError("Order not found."));
@@ -1611,7 +1861,7 @@ export class OrderService {
1611
1861
  } catch (error) {
1612
1862
  return Err(toCommerceError(error));
1613
1863
  }
1614
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
1864
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
1615
1865
  const order = await this.repo.findById(orgId, orderId, ctx);
1616
1866
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
1617
1867
  const guard = this.lineItemEditGuard(order);
@@ -1690,7 +1940,7 @@ export class OrderService {
1690
1940
  } catch (error) {
1691
1941
  return Err(toCommerceError(error));
1692
1942
  }
1693
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
1943
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
1694
1944
  const order = await this.repo.findById(orgId, orderId, ctx);
1695
1945
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
1696
1946
  const guard = this.lineItemEditGuard(order);
@@ -1737,7 +1987,7 @@ export class OrderService {
1737
1987
  } catch (error) {
1738
1988
  return Err(toCommerceError(error));
1739
1989
  }
1740
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
1990
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
1741
1991
  const order = await this.repo.findById(orgId, orderId, ctx);
1742
1992
  if (!order) return Err(new CommerceNotFoundError("Order not found."));
1743
1993
  const guard = this.lineItemEditGuard(order);
@@ -1776,7 +2026,7 @@ export class OrderService {
1776
2026
  actor?: Actor | null,
1777
2027
  ctx?: TxContext,
1778
2028
  ): Promise<Result<Order>> {
1779
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
2029
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
1780
2030
  const order = await this.repo.findById(orgId, orderId, ctx);
1781
2031
  if (!order) {
1782
2032
  return Err(new CommerceNotFoundError("Order not found."));
@@ -1,3 +1,4 @@
1
+ import type { CommerceConfig } from "../../config/types.js";
1
2
  import type { DrizzleDatabase } from "../../kernel/database/drizzle-db.js";
2
3
  import { defineModule } from "../../kernel/module/index.js";
3
4
  import type { CatalogRepository } from "../catalog/repository/index.js";
@@ -24,6 +25,7 @@ export const pricingModule = defineModule<
24
25
  repository: new PricingRepository(deps.db.db as DrizzleDatabase),
25
26
  catalogRepository: deps.services.catalog.repository,
26
27
  hooks: deps.hooks,
28
+ config: deps.config as CommerceConfig,
27
29
  services: deps.services,
28
30
  database: deps.db,
29
31
  }),
@@ -15,6 +15,7 @@ export const prices = pgTable(
15
15
  variantId: uuid("variant_id").references(() => variants.id, { onDelete: "cascade" }),
16
16
  currency: text("currency").notNull(),
17
17
  amount: integer("amount").notNull(),
18
+ compareAtAmount: integer("compare_at_amount"),
18
19
  customerGroupId: text("customer_group_id"),
19
20
  minQuantity: integer("min_quantity"),
20
21
  maxQuantity: integer("max_quantity"),
@@ -7,6 +7,7 @@ export const SetBasePriceBodySchema = z.object({
7
7
  variantId: z.string().optional().openapi({ example: "variant-uuid" }),
8
8
  currency: z.string().length(3).openapi({ example: "USD" }),
9
9
  amount: z.number().openapi({ example: 29.99 }),
10
+ compareAtAmount: z.number().nullable().optional(),
10
11
  customerGroupId: z.string().optional(),
11
12
  minQuantity: z.number().int().optional(),
12
13
  maxQuantity: z.number().int().optional(),