@porulle/core 0.11.0 → 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 (289) 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 +30 -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 +6 -5
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +4 -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/route-coverage.d.ts +14 -0
  42. package/dist/interfaces/rest/route-coverage.d.ts.map +1 -0
  43. package/dist/interfaces/rest/route-coverage.js +81 -0
  44. package/dist/interfaces/rest/router.d.ts +7 -2
  45. package/dist/interfaces/rest/router.d.ts.map +1 -1
  46. package/dist/interfaces/rest/router.js +8 -4
  47. package/dist/interfaces/rest/routes/admin/compensation-failures.d.ts.map +1 -1
  48. package/dist/interfaces/rest/routes/admin/compensation-failures.js +7 -5
  49. package/dist/interfaces/rest/routes/admin/custom-field-proposals.js +2 -2
  50. package/dist/interfaces/rest/routes/admin/permissions.d.ts +1 -1
  51. package/dist/interfaces/rest/routes/admin/permissions.d.ts.map +1 -1
  52. package/dist/interfaces/rest/routes/admin/permissions.js +2 -0
  53. package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
  54. package/dist/interfaces/rest/routes/admin/staff.js +126 -66
  55. package/dist/interfaces/rest/routes/admin-jobs.js +3 -3
  56. package/dist/interfaces/rest/routes/audit.js +3 -3
  57. package/dist/interfaces/rest/routes/carts.d.ts.map +1 -1
  58. package/dist/interfaces/rest/routes/carts.js +13 -10
  59. package/dist/interfaces/rest/routes/catalog.d.ts.map +1 -1
  60. package/dist/interfaces/rest/routes/catalog.js +10 -2
  61. package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
  62. package/dist/interfaces/rest/routes/checkout.js +30 -35
  63. package/dist/interfaces/rest/routes/documents.d.ts.map +1 -1
  64. package/dist/interfaces/rest/routes/documents.js +10 -5
  65. package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
  66. package/dist/interfaces/rest/routes/inventory.js +2 -0
  67. package/dist/interfaces/rest/routes/media.d.ts.map +1 -1
  68. package/dist/interfaces/rest/routes/media.js +7 -3
  69. package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
  70. package/dist/interfaces/rest/routes/orders.js +26 -8
  71. package/dist/interfaces/rest/routes/pricing.js +2 -2
  72. package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
  73. package/dist/interfaces/rest/routes/promotions.js +13 -10
  74. package/dist/interfaces/rest/routes/search.d.ts.map +1 -1
  75. package/dist/interfaces/rest/routes/search.js +2 -1
  76. package/dist/interfaces/rest/schemas/carts.d.ts +7 -0
  77. package/dist/interfaces/rest/schemas/carts.d.ts.map +1 -1
  78. package/dist/interfaces/rest/schemas/customer-portal.d.ts +35 -0
  79. package/dist/interfaces/rest/schemas/customer-portal.d.ts.map +1 -1
  80. package/dist/interfaces/rest/schemas/orders.d.ts +204 -0
  81. package/dist/interfaces/rest/schemas/orders.d.ts.map +1 -1
  82. package/dist/interfaces/rest/schemas/responses.d.ts +71 -0
  83. package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
  84. package/dist/interfaces/rest/utils.d.ts +15 -0
  85. package/dist/interfaces/rest/utils.d.ts.map +1 -1
  86. package/dist/interfaces/rest/utils.js +45 -2
  87. package/dist/kernel/compensation/executor.js +2 -2
  88. package/dist/kernel/database/tx-context.d.ts +8 -0
  89. package/dist/kernel/database/tx-context.d.ts.map +1 -1
  90. package/dist/kernel/database/tx-context.js +13 -0
  91. package/dist/kernel/hooks/create-context.d.ts +2 -0
  92. package/dist/kernel/hooks/create-context.d.ts.map +1 -1
  93. package/dist/kernel/hooks/create-context.js +1 -0
  94. package/dist/kernel/hooks/types.d.ts +2 -0
  95. package/dist/kernel/hooks/types.d.ts.map +1 -1
  96. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  97. package/dist/kernel/plugin/manifest.js +9 -5
  98. package/dist/modules/analytics/service.js +2 -2
  99. package/dist/modules/audit/service.js +3 -3
  100. package/dist/modules/cart/repository/index.d.ts +13 -7
  101. package/dist/modules/cart/repository/index.d.ts.map +1 -1
  102. package/dist/modules/cart/repository/index.js +16 -10
  103. package/dist/modules/cart/schema.d.ts +17 -0
  104. package/dist/modules/cart/schema.d.ts.map +1 -1
  105. package/dist/modules/cart/schema.js +4 -0
  106. package/dist/modules/cart/service.d.ts +22 -9
  107. package/dist/modules/cart/service.d.ts.map +1 -1
  108. package/dist/modules/cart/service.js +57 -33
  109. package/dist/modules/catalog/brand-service.js +7 -7
  110. package/dist/modules/catalog/category-service.js +7 -7
  111. package/dist/modules/catalog/entity-service.d.ts +14 -7
  112. package/dist/modules/catalog/entity-service.d.ts.map +1 -1
  113. package/dist/modules/catalog/entity-service.js +109 -31
  114. package/dist/modules/catalog/read-policy.d.ts +9 -0
  115. package/dist/modules/catalog/read-policy.d.ts.map +1 -0
  116. package/dist/modules/catalog/read-policy.js +8 -0
  117. package/dist/modules/catalog/repository/index.d.ts +3 -2
  118. package/dist/modules/catalog/repository/index.d.ts.map +1 -1
  119. package/dist/modules/catalog/repository/index.js +14 -4
  120. package/dist/modules/catalog/service.d.ts +15 -13
  121. package/dist/modules/catalog/service.d.ts.map +1 -1
  122. package/dist/modules/catalog/service.js +25 -18
  123. package/dist/modules/customers/module.d.ts.map +1 -1
  124. package/dist/modules/customers/module.js +1 -0
  125. package/dist/modules/customers/service.d.ts +2 -0
  126. package/dist/modules/customers/service.d.ts.map +1 -1
  127. package/dist/modules/customers/service.js +21 -20
  128. package/dist/modules/documents/module.d.ts.map +1 -1
  129. package/dist/modules/documents/module.js +1 -0
  130. package/dist/modules/documents/service.d.ts +18 -4
  131. package/dist/modules/documents/service.d.ts.map +1 -1
  132. package/dist/modules/documents/service.js +54 -16
  133. package/dist/modules/fulfillment/module.d.ts.map +1 -1
  134. package/dist/modules/fulfillment/module.js +1 -0
  135. package/dist/modules/fulfillment/service.d.ts +2 -0
  136. package/dist/modules/fulfillment/service.d.ts.map +1 -1
  137. package/dist/modules/fulfillment/service.js +15 -6
  138. package/dist/modules/inventory/service.d.ts.map +1 -1
  139. package/dist/modules/inventory/service.js +15 -14
  140. package/dist/modules/media/service.js +6 -6
  141. package/dist/modules/orders/guest-access.d.ts +27 -0
  142. package/dist/modules/orders/guest-access.d.ts.map +1 -0
  143. package/dist/modules/orders/guest-access.js +46 -0
  144. package/dist/modules/orders/module.d.ts.map +1 -1
  145. package/dist/modules/orders/module.js +1 -0
  146. package/dist/modules/orders/quote.d.ts.map +1 -1
  147. package/dist/modules/orders/quote.js +1 -0
  148. package/dist/modules/orders/repository/index.d.ts +1 -1
  149. package/dist/modules/orders/repository/index.d.ts.map +1 -1
  150. package/dist/modules/orders/repository/index.js +2 -2
  151. package/dist/modules/orders/schema.d.ts +17 -0
  152. package/dist/modules/orders/schema.d.ts.map +1 -1
  153. package/dist/modules/orders/schema.js +5 -3
  154. package/dist/modules/orders/service.d.ts +16 -7
  155. package/dist/modules/orders/service.d.ts.map +1 -1
  156. package/dist/modules/orders/service.js +184 -55
  157. package/dist/modules/pricing/module.d.ts.map +1 -1
  158. package/dist/modules/pricing/module.js +1 -0
  159. package/dist/modules/pricing/service.d.ts +2 -0
  160. package/dist/modules/pricing/service.d.ts.map +1 -1
  161. package/dist/modules/pricing/service.js +12 -11
  162. package/dist/modules/promotions/module.d.ts.map +1 -1
  163. package/dist/modules/promotions/module.js +1 -0
  164. package/dist/modules/promotions/service.d.ts +3 -0
  165. package/dist/modules/promotions/service.d.ts.map +1 -1
  166. package/dist/modules/promotions/service.js +19 -11
  167. package/dist/modules/search/adapter.d.ts +6 -0
  168. package/dist/modules/search/adapter.d.ts.map +1 -1
  169. package/dist/modules/search/module.d.ts.map +1 -1
  170. package/dist/modules/search/module.js +1 -0
  171. package/dist/modules/search/service.d.ts +1 -0
  172. package/dist/modules/search/service.d.ts.map +1 -1
  173. package/dist/modules/search/service.js +57 -6
  174. package/dist/modules/settings/module.d.ts.map +1 -1
  175. package/dist/modules/settings/module.js +1 -0
  176. package/dist/modules/settings/service.d.ts +3 -0
  177. package/dist/modules/settings/service.d.ts.map +1 -1
  178. package/dist/modules/settings/service.js +6 -4
  179. package/dist/modules/shipping/service.js +9 -9
  180. package/dist/modules/tax/module.d.ts.map +1 -1
  181. package/dist/modules/tax/module.js +1 -0
  182. package/dist/modules/tax/service.d.ts +3 -0
  183. package/dist/modules/tax/service.d.ts.map +1 -1
  184. package/dist/modules/tax/service.js +11 -9
  185. package/dist/modules/webhooks/hook.js +2 -2
  186. package/dist/modules/webhooks/module.d.ts.map +1 -1
  187. package/dist/modules/webhooks/module.js +1 -0
  188. package/dist/modules/webhooks/service.d.ts +2 -0
  189. package/dist/modules/webhooks/service.d.ts.map +1 -1
  190. package/dist/modules/webhooks/service.js +4 -4
  191. package/dist/runtime/server.d.ts.map +1 -1
  192. package/dist/runtime/server.js +10 -2
  193. package/dist/test-utils/create-pglite-adapter.d.ts.map +1 -1
  194. package/dist/test-utils/create-pglite-adapter.js +35 -13
  195. package/dist/test-utils/create-test-config.d.ts.map +1 -1
  196. package/dist/test-utils/create-test-config.js +4 -0
  197. package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
  198. package/dist/test-utils/rest-api-test-utils.js +2 -0
  199. package/dist/test-utils/test-actors.js +2 -2
  200. package/dist/utils/id.d.ts +2 -0
  201. package/dist/utils/id.d.ts.map +1 -1
  202. package/dist/utils/id.js +11 -0
  203. package/package.json +6 -5
  204. package/src/auth/auth-schema-guard.ts +143 -0
  205. package/src/auth/auth-schema.ts +50 -19
  206. package/src/auth/middleware.ts +17 -5
  207. package/src/auth/org.ts +15 -3
  208. package/src/auth/organization-guard.ts +158 -0
  209. package/src/auth/permissions.ts +31 -8
  210. package/src/auth/role-authority.ts +107 -0
  211. package/src/auth/setup.ts +17 -0
  212. package/src/auth/strict-org-resolution.ts +7 -1
  213. package/src/auth/types.ts +1 -1
  214. package/src/config/defaults.ts +2 -0
  215. package/src/config/types.ts +29 -4
  216. package/src/hooks/checkout.ts +19 -12
  217. package/src/index.ts +16 -6
  218. package/src/interfaces/rest/audit-middleware.ts +2 -0
  219. package/src/interfaces/rest/customer-portal.ts +31 -24
  220. package/src/interfaces/rest/route-coverage.ts +103 -0
  221. package/src/interfaces/rest/router.ts +16 -10
  222. package/src/interfaces/rest/routes/admin/compensation-failures.ts +8 -5
  223. package/src/interfaces/rest/routes/admin/custom-field-proposals.ts +2 -2
  224. package/src/interfaces/rest/routes/admin/permissions.ts +3 -1
  225. package/src/interfaces/rest/routes/admin/staff.ts +161 -72
  226. package/src/interfaces/rest/routes/admin-jobs.ts +3 -3
  227. package/src/interfaces/rest/routes/audit.ts +3 -3
  228. package/src/interfaces/rest/routes/carts.ts +17 -7
  229. package/src/interfaces/rest/routes/catalog.ts +11 -0
  230. package/src/interfaces/rest/routes/checkout.ts +41 -38
  231. package/src/interfaces/rest/routes/documents.ts +15 -1
  232. package/src/interfaces/rest/routes/inventory.ts +2 -0
  233. package/src/interfaces/rest/routes/media.ts +8 -3
  234. package/src/interfaces/rest/routes/orders.ts +27 -8
  235. package/src/interfaces/rest/routes/pricing.ts +2 -2
  236. package/src/interfaces/rest/routes/promotions.ts +12 -9
  237. package/src/interfaces/rest/routes/search.ts +3 -1
  238. package/src/interfaces/rest/utils.ts +61 -2
  239. package/src/kernel/compensation/executor.ts +2 -2
  240. package/src/kernel/database/tx-context.ts +25 -0
  241. package/src/kernel/hooks/create-context.ts +3 -0
  242. package/src/kernel/hooks/types.ts +2 -0
  243. package/src/kernel/plugin/manifest.ts +9 -5
  244. package/src/modules/analytics/service.ts +2 -2
  245. package/src/modules/audit/service.ts +3 -3
  246. package/src/modules/cart/repository/index.ts +22 -8
  247. package/src/modules/cart/schema.ts +4 -0
  248. package/src/modules/cart/service.ts +62 -27
  249. package/src/modules/catalog/brand-service.ts +7 -7
  250. package/src/modules/catalog/category-service.ts +7 -7
  251. package/src/modules/catalog/entity-service.ts +117 -35
  252. package/src/modules/catalog/read-policy.ts +16 -0
  253. package/src/modules/catalog/repository/index.ts +19 -3
  254. package/src/modules/catalog/service.ts +46 -31
  255. package/src/modules/customers/module.ts +2 -0
  256. package/src/modules/customers/service.ts +23 -22
  257. package/src/modules/documents/module.ts +2 -0
  258. package/src/modules/documents/service.ts +74 -11
  259. package/src/modules/fulfillment/module.ts +2 -0
  260. package/src/modules/fulfillment/service.ts +17 -6
  261. package/src/modules/inventory/service.ts +15 -24
  262. package/src/modules/media/service.ts +6 -6
  263. package/src/modules/orders/guest-access.ts +55 -0
  264. package/src/modules/orders/module.ts +1 -0
  265. package/src/modules/orders/quote.ts +1 -0
  266. package/src/modules/orders/repository/index.ts +2 -0
  267. package/src/modules/orders/schema.ts +5 -3
  268. package/src/modules/orders/service.ts +302 -52
  269. package/src/modules/pricing/module.ts +2 -0
  270. package/src/modules/pricing/service.ts +14 -16
  271. package/src/modules/promotions/module.ts +2 -0
  272. package/src/modules/promotions/service.ts +25 -16
  273. package/src/modules/search/adapter.ts +6 -0
  274. package/src/modules/search/module.ts +1 -0
  275. package/src/modules/search/service.ts +55 -6
  276. package/src/modules/settings/module.ts +2 -0
  277. package/src/modules/settings/service.ts +8 -4
  278. package/src/modules/shipping/service.ts +9 -9
  279. package/src/modules/tax/module.ts +1 -0
  280. package/src/modules/tax/service.ts +13 -9
  281. package/src/modules/webhooks/hook.ts +2 -2
  282. package/src/modules/webhooks/module.ts +2 -0
  283. package/src/modules/webhooks/service.ts +6 -4
  284. package/src/runtime/server.ts +16 -2
  285. package/src/test-utils/create-pglite-adapter.ts +34 -12
  286. package/src/test-utils/create-test-config.ts +10 -6
  287. package/src/test-utils/rest-api-test-utils.ts +2 -0
  288. package/src/test-utils/test-actors.ts +2 -2
  289. package/src/utils/id.ts +20 -0
@@ -3,11 +3,11 @@ import { runAfterHooks } from "../../kernel/hooks/executor.js";
3
3
  import { createHookContext } from "../../kernel/hooks/create-context.js";
4
4
  import { Err, Ok } from "../../kernel/result.js";
5
5
  import { createLogger } from "../../utils/logger.js";
6
- import { resolveOrgId } from "../../auth/org.js";
6
+ import { resolveOrgId, resolveOrgIdForCommerce } from "../../auth/org.js";
7
7
  // PromotionType is derived from the zod enum (single source of truth) in
8
8
  // ./schemas.js; re-export it here for backwards-compatible imports.
9
9
  import { promotionTypeEnum } from "./schemas.js";
10
- function hookContext(actor, services, database, tx) {
10
+ function hookContext(actor, services, database, config, tx) {
11
11
  return createHookContext({
12
12
  actor,
13
13
  tx,
@@ -15,6 +15,7 @@ function hookContext(actor, services, database, tx) {
15
15
  services,
16
16
  context: { moduleName: "promotions" },
17
17
  database: { db: database.db },
18
+ commerceConfig: config,
18
19
  });
19
20
  }
20
21
  function matchesWindow(promotion, timestamp) {
@@ -70,6 +71,12 @@ export class PromotionService {
70
71
  this.catalogRepo = deps.catalogRepository;
71
72
  this.ordersRepo = deps.ordersRepository;
72
73
  }
74
+ resolveEvaluationOrgId(ctx, explicitOrgId) {
75
+ if (explicitOrgId) {
76
+ return resolveOrgId(ctx?.actor ?? null, explicitOrgId);
77
+ }
78
+ return resolveOrgIdForCommerce(ctx?.actor ?? null, this.deps.config);
79
+ }
73
80
  async create(input, actor, ctx) {
74
81
  if (!input.name) {
75
82
  return Err(new CommerceValidationError("Promotion name is required."));
@@ -82,7 +89,7 @@ export class PromotionService {
82
89
  if (!validTypes.includes(input.type)) {
83
90
  return Err(new CommerceValidationError(`Invalid promotion type "${input.type}". Must be one of: ${validTypes.join(", ")}`));
84
91
  }
85
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
92
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
86
93
  if (input.code) {
87
94
  const normalized = input.code.trim().toUpperCase();
88
95
  const existing = await this.repo.findByCode(orgId, normalized, ctx);
@@ -109,7 +116,7 @@ export class PromotionService {
109
116
  validUntil: input.validUntil ?? null,
110
117
  }, ctx);
111
118
  const afterHooks = this.deps.hooks.resolve("promotions.afterCreate");
112
- const hctx = hookContext(actor ?? ctx?.actor ?? null, this.deps.services, this.deps.database, ctx?.tx ?? null);
119
+ const hctx = hookContext(actor ?? ctx?.actor ?? null, this.deps.services, this.deps.database, this.deps.config, ctx?.tx ?? null);
113
120
  await runAfterHooks(afterHooks, null, promotion, "create", hctx);
114
121
  return Ok(promotion);
115
122
  }
@@ -123,7 +130,8 @@ export class PromotionService {
123
130
  return Err(new CommerceNotFoundError("Promotion not found."));
124
131
  }
125
132
  const afterHooks = this.deps.hooks.resolve("promotions.afterUpdate");
126
- const hctx = hookContext(null, this.deps.services, this.deps.database, ctx?.tx ?? null);
133
+ // Actor-less by design; resolves to the deployment's declared organization.
134
+ const hctx = hookContext(null, this.deps.services, this.deps.database, this.deps.config, ctx?.tx ?? null);
127
135
  await runAfterHooks(afterHooks, promotion, updated, "update", hctx);
128
136
  return Ok(updated);
129
137
  }
@@ -192,12 +200,12 @@ export class PromotionService {
192
200
  return Err(new CommerceNotFoundError("Promotion not found."));
193
201
  }
194
202
  const afterHooks = this.deps.hooks.resolve("promotions.afterUpdate");
195
- const hctx = hookContext(actor ?? ctx?.actor ?? null, this.deps.services, this.deps.database, ctx?.tx ?? null);
203
+ const hctx = hookContext(actor ?? ctx?.actor ?? null, this.deps.services, this.deps.database, this.deps.config, ctx?.tx ?? null);
196
204
  await runAfterHooks(afterHooks, existing, updated, "update", hctx);
197
205
  return Ok(updated);
198
206
  }
199
207
  async list(filter, actor, ctx) {
200
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
208
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
201
209
  const all = await this.repo.findAll(orgId, ctx);
202
210
  const now = new Date();
203
211
  if (!filter?.status)
@@ -218,7 +226,7 @@ export class PromotionService {
218
226
  return Ok(sortByPriority(filtered));
219
227
  }
220
228
  async listActive(actor, timestamp = new Date(), ctx) {
221
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
229
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
222
230
  const active = await this.repo.findActive(orgId, ctx);
223
231
  // Further filter by timestamp in case repo returns slightly stale results
224
232
  const filtered = active.filter((p) => matchesWindow(p, timestamp));
@@ -226,7 +234,7 @@ export class PromotionService {
226
234
  }
227
235
  async validate(code, context, ctx) {
228
236
  const normalized = code.trim().toUpperCase();
229
- const evalOrgId = resolveOrgId(ctx?.actor ?? null, context.orgId);
237
+ const evalOrgId = this.resolveEvaluationOrgId(ctx, context.orgId);
230
238
  const promotion = await this.repo.findByCode(evalOrgId, normalized, ctx);
231
239
  if (!promotion) {
232
240
  return Err(new CommerceNotFoundError(`Promotion code ${normalized} not found.`));
@@ -251,7 +259,7 @@ export class PromotionService {
251
259
  }
252
260
  async applyPromotions(context, ctx) {
253
261
  const timestamp = context.timestamp ?? new Date();
254
- const applyOrgId = resolveOrgId(ctx?.actor ?? null, context.orgId);
262
+ const applyOrgId = this.resolveEvaluationOrgId(ctx, context.orgId);
255
263
  const result = {
256
264
  totalDiscount: 0,
257
265
  freeShipping: false,
@@ -341,7 +349,7 @@ export class PromotionService {
341
349
  if (!context.customerId) {
342
350
  return "First-order promotion requires authenticated customer.";
343
351
  }
344
- const orders = await this.ordersRepo.findByCustomerId(resolveOrgId(ctx?.actor ?? null, context.orgId), context.customerId, ctx);
352
+ const orders = await this.ordersRepo.findByCustomerId(this.resolveEvaluationOrgId(ctx, context.orgId), context.customerId, ctx);
345
353
  if (orders.length > 0) {
346
354
  return "Promotion is valid for first order only.";
347
355
  }
@@ -1,11 +1,13 @@
1
1
  import type { Result } from "../../kernel/result.js";
2
2
  export interface SearchDocument {
3
3
  id: string;
4
+ organizationId?: string;
4
5
  type: string;
5
6
  slug: string;
6
7
  title: string;
7
8
  description?: string;
8
9
  status?: string;
10
+ isVisible?: boolean;
9
11
  categories: string[];
10
12
  brands: string[];
11
13
  text: string;
@@ -13,6 +15,8 @@ export interface SearchDocument {
13
15
  payload?: Record<string, unknown>;
14
16
  }
15
17
  export interface SearchFilters {
18
+ /** Server-supplied tenant constraint; REST callers cannot choose this value. */
19
+ organizationId?: string;
16
20
  type?: string;
17
21
  category?: string;
18
22
  brand?: string;
@@ -30,6 +34,8 @@ export interface SearchSuggestParams {
30
34
  prefix: string;
31
35
  type?: string;
32
36
  limit?: number;
37
+ /** Server-supplied tenant constraint; REST callers cannot choose this value. */
38
+ organizationId?: string;
33
39
  }
34
40
  export interface SearchHit {
35
41
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/modules/search/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CACjE"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/modules/search/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CACjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/search/module.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,YAAY,2GAkBxB,CAAC"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/search/module.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,YAAY,2GAmBxB,CAAC"}
@@ -9,6 +9,7 @@ export const searchModule = defineModule({
9
9
  return new SearchService({
10
10
  catalogRepository: deps.services.catalog.repository,
11
11
  resolveEntityFieldDefinitions: deps.services.catalog.resolveEntityFieldDefinitions.bind(deps.services.catalog),
12
+ config,
12
13
  ...(config.entities ? { entities: config.entities } : {}),
13
14
  ...(config.search?.adapter ? { adapter: config.search.adapter } : {}),
14
15
  ...(config.search?.defaultFacets
@@ -6,6 +6,7 @@ import type { SearchAdapter, SearchQueryParams, SearchQueryResult, SearchSuggest
6
6
  import type { EntityFieldDefinitionResolver } from "../catalog/service.js";
7
7
  interface SearchServiceDeps {
8
8
  catalogRepository: CatalogRepository;
9
+ config: CommerceConfig;
9
10
  entities?: CommerceConfig["entities"];
10
11
  resolveEntityFieldDefinitions?: EntityFieldDefinitionResolver;
11
12
  adapter?: SearchAdapter;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/search/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EACV,aAAa,EAGb,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAE3E,UAAU,iBAAiB;IACzB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,6BAA6B,CAAC,EAAE,6BAA6B,CAAC;IAC9D,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAoDD,qBAAa,aAAa;IACZ,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,iBAAiB;YAE7B,gBAAgB;YAwBhB,YAAY;YAwBZ,aAAa;YAqEb,YAAY;IAY1B,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,aAAa;IAoEf,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAcpE,KAAK,CACT,MAAM,EAAE,iBAAiB,EACzB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAsE/B,OAAO,CACX,MAAM,EAAE,mBAAmB,EAC3B,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;CAoC7B"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/search/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EACV,aAAa,EAGb,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAG3E,UAAU,iBAAiB;IACzB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,6BAA6B,CAAC,EAAE,6BAA6B,CAAC;IAC9D,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAoDD,qBAAa,aAAa;IACZ,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,iBAAiB;YAE7B,gBAAgB;YAwBhB,YAAY;YAwBZ,aAAa;YAuEb,YAAY;IAoB1B,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,aAAa;IAoEf,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAcpE,KAAK,CACT,MAAM,EAAE,iBAAiB,EACzB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IA8F/B,OAAO,CACX,MAAM,EAAE,mBAAmB,EAC3B,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;CA+C7B"}
@@ -1,5 +1,7 @@
1
- import { Ok } from "../../kernel/result.js";
2
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { Err, Ok } from "../../kernel/result.js";
2
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
3
+ import { OrgResolutionError } from "../../kernel/errors.js";
4
+ import { canReadUnpublishedCatalog } from "../catalog/read-policy.js";
3
5
  function unique(values) {
4
6
  return [...new Set(values)];
5
7
  }
@@ -111,11 +113,13 @@ export class SearchService {
111
113
  ];
112
114
  return {
113
115
  id: entity.id,
116
+ organizationId: entity.organizationId,
114
117
  type: entity.type,
115
118
  slug: entity.slug,
116
119
  title,
117
120
  ...(description ? { description } : {}),
118
121
  status: entity.status,
122
+ isVisible: entity.isVisible,
119
123
  categories,
120
124
  brands,
121
125
  text: textParts.join(" ").trim(),
@@ -126,13 +130,23 @@ export class SearchService {
126
130
  };
127
131
  }
128
132
  async allDocuments(ctx) {
129
- const orgId = resolveOrgId(ctx?.actor ?? null);
130
- const entities = await this.deps.catalogRepository.findEntities(orgId, undefined, ctx);
133
+ const actor = ctx?.actor;
134
+ if (!actor) {
135
+ // Deliberate exception: this needs an authenticated actor, not merely a
136
+ // resolvable organization, because visibility scoping is decided from the
137
+ // actor's permissions. A declared deployment default would satisfy the
138
+ // organization but not that.
139
+ throw new OrgResolutionError("Organization could not be resolved for a search read.");
140
+ }
141
+ const orgId = resolveOrgIdForCommerce(actor, this.deps.config);
142
+ const entities = await this.deps.catalogRepository.findEntities(orgId, canReadUnpublishedCatalog(actor) ? undefined : { status: "active", isVisible: true }, ctx);
131
143
  return Promise.all(entities.map((entity) => this.buildDocument(entity, ctx)));
132
144
  }
133
145
  matchesFilters(document, filters) {
134
146
  if (!filters)
135
147
  return true;
148
+ if (filters.organizationId && document.organizationId !== filters.organizationId)
149
+ return false;
136
150
  if (filters.type && document.type !== filters.type)
137
151
  return false;
138
152
  if (filters.status && document.status !== filters.status)
@@ -220,11 +234,35 @@ export class SearchService {
220
234
  // Cap query length to prevent abuse / excessive processing
221
235
  const safeQuery = (params.query ?? "").slice(0, 500);
222
236
  if (this.deps.adapter) {
223
- return this.deps.adapter.search({
237
+ const actor = ctx?.actor ?? null;
238
+ // Deliberate exception: this needs an authenticated actor, not merely a
239
+ // resolvable organization, because visibility scoping is decided from the
240
+ // actor's permissions. A declared deployment default would satisfy the
241
+ // organization but not that.
242
+ if (!actor)
243
+ return Err(new OrgResolutionError("Organization could not be resolved for a search read."));
244
+ const organizationId = resolveOrgIdForCommerce(actor, this.deps.config);
245
+ const result = await this.deps.adapter.search({
224
246
  ...params,
225
247
  query: safeQuery,
226
248
  page,
227
249
  limit,
250
+ filters: {
251
+ ...params.filters,
252
+ organizationId,
253
+ ...(!canReadUnpublishedCatalog(actor) ? { status: "active" } : {}),
254
+ },
255
+ });
256
+ if (!result.ok)
257
+ return result;
258
+ const hits = result.value.hits.filter((hit) => hit.document.organizationId === organizationId &&
259
+ (canReadUnpublishedCatalog(actor) ||
260
+ (hit.document.status === "active" && hit.document.isVisible !== false)));
261
+ return Ok({
262
+ ...result.value,
263
+ hits,
264
+ total: hits.length,
265
+ facets: this.computeFacets(hits.map((hit) => hit.document), params.facets),
228
266
  });
229
267
  }
230
268
  // In-memory fallback: require a non-empty query to avoid loading all entities
@@ -284,11 +322,24 @@ export class SearchService {
284
322
  if (prefix.length === 0)
285
323
  return Ok([]);
286
324
  if (this.deps.adapter) {
287
- return this.deps.adapter.suggest({
325
+ const actor = ctx?.actor ?? null;
326
+ // Deliberate exception: this needs an authenticated actor, not merely a
327
+ // resolvable organization, because visibility scoping is decided from the
328
+ // actor's permissions. A declared deployment default would satisfy the
329
+ // organization but not that.
330
+ if (!actor)
331
+ return Err(new OrgResolutionError("Organization could not be resolved for a search read."));
332
+ const organizationId = resolveOrgIdForCommerce(actor, this.deps.config);
333
+ const result = await this.deps.adapter.suggest({
288
334
  ...params,
289
335
  prefix,
290
336
  limit,
337
+ organizationId,
291
338
  });
339
+ if (!result.ok)
340
+ return result;
341
+ const visibleTitles = new Set((await this.allDocuments(ctx)).map((document) => document.title));
342
+ return Ok(result.value.filter((title) => visibleTitles.has(title)));
292
343
  }
293
344
  // In-memory fallback: require prefix >= 2 chars to avoid loading all entities
294
345
  // (allDocuments triggers N+1 DB queries per entity — unsafe at scale)
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/settings/module.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,eAAO,MAAM,cAAc;mBACR,OAAO,aAAa;0CAUrC,CAAC"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/settings/module.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,eAAO,MAAM,cAAc;mBACR,OAAO,aAAa;0CAWrC,CAAC"}
@@ -7,5 +7,6 @@ export const settingsModule = defineModule({
7
7
  schema: () => ({ storeSettings }),
8
8
  service: (deps) => new SettingsService({
9
9
  repository: new SettingsRepository(deps.db.db),
10
+ config: deps.config,
10
11
  }),
11
12
  });
@@ -1,9 +1,11 @@
1
1
  import type { Actor } from "../../auth/types.js";
2
+ import type { CommerceConfig } from "../../config/types.js";
2
3
  import type { TxContext } from "../../kernel/database/tx-context.js";
3
4
  import { type Result } from "../../kernel/result.js";
4
5
  import type { SettingsRepository } from "./repository/index.js";
5
6
  interface SettingsServiceDeps {
6
7
  repository: SettingsRepository;
8
+ config: CommerceConfig;
7
9
  }
8
10
  /**
9
11
  * Org-scoped runtime settings (issue #49).
@@ -14,6 +16,7 @@ interface SettingsServiceDeps {
14
16
  */
15
17
  export declare class SettingsService {
16
18
  private repository;
19
+ private config;
17
20
  constructor(deps: SettingsServiceDeps);
18
21
  /** Runtime read for plugins/hooks. Unset groups read as `{}`. */
19
22
  read(orgId: string, group: string, ctx?: TxContext): Promise<Record<string, unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/settings/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAErE,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE,UAAU,mBAAmB;IAC3B,UAAU,EAAE,kBAAkB,CAAC;CAChC;AAED;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAqB;gBAE3B,IAAI,EAAE,mBAAmB;IAIrC,iEAAiE;IAC3D,IAAI,CACR,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAK7B,QAAQ,CACZ,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAKrC,MAAM,CACV,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAQ3D,wEAAwE;IAClE,WAAW,CACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAkB5C"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/settings/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAErE,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAIhE,UAAU,mBAAmB;IAC3B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,MAAM,CAAiB;gBAEnB,IAAI,EAAE,mBAAmB;IAKrC,iEAAiE;IAC3D,IAAI,CACR,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAK7B,QAAQ,CACZ,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAKrC,MAAM,CACV,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAQ3D,wEAAwE;IAClE,WAAW,CACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,EACpB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAkB5C"}
@@ -1,4 +1,4 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  import { CommerceValidationError } from "../../kernel/errors.js";
3
3
  import { Err, Ok } from "../../kernel/result.js";
4
4
  const GROUP_NAME_RE = /^[a-z][a-z0-9_-]*$/;
@@ -11,8 +11,10 @@ const GROUP_NAME_RE = /^[a-z][a-z0-9_-]*$/;
11
11
  */
12
12
  export class SettingsService {
13
13
  repository;
14
+ config;
14
15
  constructor(deps) {
15
16
  this.repository = deps.repository;
17
+ this.config = deps.config;
16
18
  }
17
19
  /** Runtime read for plugins/hooks. Unset groups read as `{}`. */
18
20
  async read(orgId, group, ctx) {
@@ -20,11 +22,11 @@ export class SettingsService {
20
22
  return row?.value ?? {};
21
23
  }
22
24
  async getGroup(group, actor, ctx) {
23
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
25
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
24
26
  return Ok(await this.read(orgId, group, ctx));
25
27
  }
26
28
  async getAll(actor, ctx) {
27
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
29
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
28
30
  const rows = await this.repository.findAll(orgId, ctx);
29
31
  const all = {};
30
32
  for (const row of rows)
@@ -36,7 +38,7 @@ export class SettingsService {
36
38
  if (!GROUP_NAME_RE.test(group)) {
37
39
  return Err(new CommerceValidationError("Settings group must match [a-z][a-z0-9_-]* (e.g. general, branding, policies)."));
38
40
  }
39
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
41
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
40
42
  const current = await this.read(orgId, group, ctx);
41
43
  const next = { ...current };
42
44
  for (const [key, value] of Object.entries(patch)) {
@@ -1,4 +1,4 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  import { CommerceNotFoundError, CommerceValidationError } from "../../kernel/errors.js";
3
3
  import { Err, Ok } from "../../kernel/result.js";
4
4
  import { calculateShippingCost, computeShippableWeightGrams, } from "./calculator.js";
@@ -83,7 +83,7 @@ export class ShippingService {
83
83
  if (input.countries.length === 0) {
84
84
  return Err(new CommerceValidationError("A shipping zone requires at least one country (\"*\" matches any)."));
85
85
  }
86
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
86
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
87
87
  const zone = await this.deps.repository.createZone({
88
88
  organizationId: orgId,
89
89
  name: input.name,
@@ -95,11 +95,11 @@ export class ShippingService {
95
95
  return Ok(zone);
96
96
  }
97
97
  async listZones(actor, ctx) {
98
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
98
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
99
99
  return Ok(await this.deps.repository.findZones(orgId, ctx));
100
100
  }
101
101
  async updateZone(id, patch, actor, ctx) {
102
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
102
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
103
103
  const existing = await this.deps.repository.findZoneById(orgId, id, ctx);
104
104
  if (!existing)
105
105
  return Err(new CommerceNotFoundError("Shipping zone not found."));
@@ -117,7 +117,7 @@ export class ShippingService {
117
117
  return Ok(updated);
118
118
  }
119
119
  async deleteZone(id, actor, ctx) {
120
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
120
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
121
121
  const existing = await this.deps.repository.findZoneById(orgId, id, ctx);
122
122
  if (!existing)
123
123
  return Err(new CommerceNotFoundError("Shipping zone not found."));
@@ -125,7 +125,7 @@ export class ShippingService {
125
125
  return Ok({ deleted: true });
126
126
  }
127
127
  async createRate(input, actor, ctx) {
128
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
128
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
129
129
  const zone = await this.deps.repository.findZoneById(orgId, input.zoneId, ctx);
130
130
  if (!zone)
131
131
  return Err(new CommerceNotFoundError("Shipping zone not found."));
@@ -145,11 +145,11 @@ export class ShippingService {
145
145
  return Ok(rate);
146
146
  }
147
147
  async listRates(filter, actor, ctx) {
148
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
148
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
149
149
  return Ok(await this.deps.repository.findRates(orgId, filter?.zoneId !== undefined ? { zoneId: filter.zoneId } : undefined, ctx));
150
150
  }
151
151
  async updateRate(id, patch, actor, ctx) {
152
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
152
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
153
153
  const existing = await this.deps.repository.findRateById(orgId, id, ctx);
154
154
  if (!existing)
155
155
  return Err(new CommerceNotFoundError("Shipping rate not found."));
@@ -169,7 +169,7 @@ export class ShippingService {
169
169
  return Ok(updated);
170
170
  }
171
171
  async deleteRate(id, actor, ctx) {
172
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
172
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
173
173
  const existing = await this.deps.repository.findRateById(orgId, id, ctx);
174
174
  if (!existing)
175
175
  return Err(new CommerceNotFoundError("Shipping rate not found."));
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/tax/module.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,eAAO,MAAM,SAAS;cACR,OAAO,QAAQ;gBAAc,OAAO,UAAU;qCAW1D,CAAC"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/tax/module.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,eAAO,MAAM,SAAS;cACR,OAAO,QAAQ;gBAAc,OAAO,UAAU;qCAY1D,CAAC"}
@@ -8,5 +8,6 @@ export const taxModule = defineModule({
8
8
  service: (deps) => new TaxService({
9
9
  adapter: deps.config.tax?.adapter,
10
10
  repository: new TaxRatesRepository(deps.db.db),
11
+ config: deps.config,
11
12
  }),
12
13
  });
@@ -1,4 +1,5 @@
1
1
  import type { Actor } from "../../auth/types.js";
2
+ import type { CommerceConfig } from "../../config/types.js";
2
3
  import type { TxContext } from "../../kernel/database/tx-context.js";
3
4
  import { type Result } from "../../kernel/result.js";
4
5
  import type { TaxAdapter, TaxCalculationParams, TaxCalculationResult, TaxReportParams, TaxVoidParams } from "./adapter.js";
@@ -6,10 +7,12 @@ import type { TaxClass, TaxRate, TaxRatesRepository } from "./repository/index.j
6
7
  interface TaxServiceDeps {
7
8
  adapter: TaxAdapter | undefined;
8
9
  repository?: TaxRatesRepository;
10
+ config: CommerceConfig;
9
11
  }
10
12
  export declare class TaxService {
11
13
  private adapter;
12
14
  private repository;
15
+ private config;
13
16
  constructor(deps: TaxServiceDeps);
14
17
  /**
15
18
  * Calculates tax. Resolution order:
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/tax/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/tax/service.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,14 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  import { CommerceNotFoundError, CommerceValidationError } from "../../kernel/errors.js";
3
3
  import { Err, Ok } from "../../kernel/result.js";
4
4
  export class TaxService {
5
5
  adapter;
6
6
  repository;
7
+ config;
7
8
  constructor(deps) {
8
9
  this.adapter = deps.adapter;
9
10
  this.repository = deps.repository;
11
+ this.config = deps.config;
10
12
  }
11
13
  /**
12
14
  * Calculates tax. Resolution order:
@@ -117,7 +119,7 @@ export class TaxService {
117
119
  if (input.rateBps < 0) {
118
120
  return Err(new CommerceValidationError("rateBps must be non-negative."));
119
121
  }
120
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
122
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
121
123
  if (input.isDefault)
122
124
  await repo.value.clearDefaultClass(orgId, ctx);
123
125
  const created = await repo.value.createClass({
@@ -133,14 +135,14 @@ export class TaxService {
133
135
  const repo = this.requireRepository();
134
136
  if (!repo.ok)
135
137
  return repo;
136
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
138
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
137
139
  return Ok(await repo.value.findAllClasses(orgId, ctx));
138
140
  }
139
141
  async updateTaxClass(id, patch, actor, ctx) {
140
142
  const repo = this.requireRepository();
141
143
  if (!repo.ok)
142
144
  return repo;
143
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
145
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
144
146
  const existing = await repo.value.findClassById(orgId, id, ctx);
145
147
  if (!existing)
146
148
  return Err(new CommerceNotFoundError("Tax class not found."));
@@ -158,7 +160,7 @@ export class TaxService {
158
160
  const repo = this.requireRepository();
159
161
  if (!repo.ok)
160
162
  return repo;
161
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
163
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
162
164
  const existing = await repo.value.findClassById(orgId, id, ctx);
163
165
  if (!existing)
164
166
  return Err(new CommerceNotFoundError("Tax class not found."));
@@ -207,7 +209,7 @@ export class TaxService {
207
209
  if (input.rateBps < 0) {
208
210
  return Err(new CommerceValidationError("rateBps must be non-negative."));
209
211
  }
210
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
212
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
211
213
  const rate = await repo.value.create({
212
214
  organizationId: orgId,
213
215
  name: input.name,
@@ -224,14 +226,14 @@ export class TaxService {
224
226
  const repo = this.requireRepository();
225
227
  if (!repo.ok)
226
228
  return repo;
227
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
229
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
228
230
  return Ok(await repo.value.findAll(orgId, ctx));
229
231
  }
230
232
  async updateTaxRate(id, patch, actor, ctx) {
231
233
  const repo = this.requireRepository();
232
234
  if (!repo.ok)
233
235
  return repo;
234
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
236
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
235
237
  const existing = await repo.value.findById(orgId, id, ctx);
236
238
  if (!existing)
237
239
  return Err(new CommerceNotFoundError("Tax rate not found."));
@@ -252,7 +254,7 @@ export class TaxService {
252
254
  const repo = this.requireRepository();
253
255
  if (!repo.ok)
254
256
  return repo;
255
- const orgId = resolveOrgId(actor ?? ctx?.actor ?? null);
257
+ const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.config);
256
258
  const existing = await repo.value.findById(orgId, id, ctx);
257
259
  if (!existing)
258
260
  return Err(new CommerceNotFoundError("Tax rate not found."));
@@ -1,4 +1,4 @@
1
- import { resolveOrgId } from "../../auth/org.js";
1
+ import { resolveOrgIdForCommerce } from "../../auth/org.js";
2
2
  /**
3
3
  * Webhook delivery hook — enqueues delivery jobs instead of blocking.
4
4
  *
@@ -15,7 +15,7 @@ export const deliverWebhooks = async ({ result, operation, context }) => {
15
15
  // VAPT r2 (codex) finding: fan-out queried ALL endpoints across the
16
16
  // database, so Tenant B's webhooks fired on Tenant A's events —
17
17
  // payload-level cross-tenant data leak. Now scoped to the actor's org.
18
- const orgId = resolveOrgId(context.actor);
18
+ const orgId = resolveOrgIdForCommerce(context.actor, context.commerceConfig);
19
19
  const endpoints = await webhooksService.getEndpointsForEvent(eventName, orgId);
20
20
  if (!endpoints.ok)
21
21
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/webhooks/module.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAO9C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAWzB,CAAC"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/modules/webhooks/module.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAO9C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAYzB,CAAC"}
@@ -11,5 +11,6 @@ export const webhooksModule = defineModule({
11
11
  }),
12
12
  service: (deps) => new WebhookService({
13
13
  repository: new WebhooksRepository(deps.db.db),
14
+ config: deps.config,
14
15
  }),
15
16
  });
@@ -1,9 +1,11 @@
1
1
  import type { Actor } from "../../auth/types.js";
2
+ import type { CommerceConfig } from "../../config/types.js";
2
3
  import { type Result } from "../../kernel/result.js";
3
4
  import type { TxContext } from "../../kernel/database/tx-context.js";
4
5
  import type { WebhooksRepository, WebhookEndpoint } from "./repository/index.js";
5
6
  interface WebhookServiceDeps {
6
7
  repository: WebhooksRepository;
8
+ config: CommerceConfig;
7
9
  }
8
10
  export declare class WebhookService {
9
11
  private deps;