@endora-commerce/contracts 0.100.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 (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -0
  3. package/dist/actor.d.ts +79 -0
  4. package/dist/actor.d.ts.map +1 -0
  5. package/dist/actor.js +41 -0
  6. package/dist/actor.js.map +1 -0
  7. package/dist/addresses.d.ts +134 -0
  8. package/dist/addresses.d.ts.map +1 -0
  9. package/dist/addresses.js +16 -0
  10. package/dist/addresses.js.map +1 -0
  11. package/dist/admin-actions.d.ts +367 -0
  12. package/dist/admin-actions.d.ts.map +1 -0
  13. package/dist/admin-actions.js +287 -0
  14. package/dist/admin-actions.js.map +1 -0
  15. package/dist/admin-contributions.d.ts +518 -0
  16. package/dist/admin-contributions.d.ts.map +1 -0
  17. package/dist/admin-contributions.js +495 -0
  18. package/dist/admin-contributions.js.map +1 -0
  19. package/dist/admin-i18n.d.ts +135 -0
  20. package/dist/admin-i18n.d.ts.map +1 -0
  21. package/dist/admin-i18n.js +72 -0
  22. package/dist/admin-i18n.js.map +1 -0
  23. package/dist/admin-notifications.d.ts +55 -0
  24. package/dist/admin-notifications.d.ts.map +1 -0
  25. package/dist/admin-notifications.js +16 -0
  26. package/dist/admin-notifications.js.map +1 -0
  27. package/dist/admin-roles.d.ts +125 -0
  28. package/dist/admin-roles.d.ts.map +1 -0
  29. package/dist/admin-roles.js +2 -0
  30. package/dist/admin-roles.js.map +1 -0
  31. package/dist/admin-users.d.ts +178 -0
  32. package/dist/admin-users.d.ts.map +1 -0
  33. package/dist/admin-users.js +14 -0
  34. package/dist/admin-users.js.map +1 -0
  35. package/dist/admin.d.ts +243 -0
  36. package/dist/admin.d.ts.map +1 -0
  37. package/dist/admin.js +246 -0
  38. package/dist/admin.js.map +1 -0
  39. package/dist/analytics.d.ts +123 -0
  40. package/dist/analytics.d.ts.map +1 -0
  41. package/dist/analytics.js +68 -0
  42. package/dist/analytics.js.map +1 -0
  43. package/dist/api-keys.d.ts +97 -0
  44. package/dist/api-keys.d.ts.map +1 -0
  45. package/dist/api-keys.js +64 -0
  46. package/dist/api-keys.js.map +1 -0
  47. package/dist/assets-library.d.ts +684 -0
  48. package/dist/assets-library.d.ts.map +1 -0
  49. package/dist/assets-library.js +181 -0
  50. package/dist/assets-library.js.map +1 -0
  51. package/dist/audit-logs.d.ts +141 -0
  52. package/dist/audit-logs.d.ts.map +1 -0
  53. package/dist/audit-logs.js +31 -0
  54. package/dist/audit-logs.js.map +1 -0
  55. package/dist/auth.d.ts +174 -0
  56. package/dist/auth.d.ts.map +1 -0
  57. package/dist/auth.js +27 -0
  58. package/dist/auth.js.map +1 -0
  59. package/dist/blog.d.ts +669 -0
  60. package/dist/blog.d.ts.map +1 -0
  61. package/dist/blog.js +360 -0
  62. package/dist/blog.js.map +1 -0
  63. package/dist/capabilities.d.ts +40 -0
  64. package/dist/capabilities.d.ts.map +1 -0
  65. package/dist/capabilities.js +38 -0
  66. package/dist/capabilities.js.map +1 -0
  67. package/dist/carts.d.ts +1367 -0
  68. package/dist/carts.d.ts.map +1 -0
  69. package/dist/carts.js +405 -0
  70. package/dist/carts.js.map +1 -0
  71. package/dist/catalog.d.ts +2855 -0
  72. package/dist/catalog.d.ts.map +1 -0
  73. package/dist/catalog.js +1543 -0
  74. package/dist/catalog.js.map +1 -0
  75. package/dist/cms.d.ts +872 -0
  76. package/dist/cms.d.ts.map +1 -0
  77. package/dist/cms.js +468 -0
  78. package/dist/cms.js.map +1 -0
  79. package/dist/common.d.ts +82 -0
  80. package/dist/common.d.ts.map +1 -0
  81. package/dist/common.js +72 -0
  82. package/dist/common.js.map +1 -0
  83. package/dist/comparisons.d.ts +487 -0
  84. package/dist/comparisons.d.ts.map +1 -0
  85. package/dist/comparisons.js +221 -0
  86. package/dist/comparisons.js.map +1 -0
  87. package/dist/credentials.d.ts +292 -0
  88. package/dist/credentials.d.ts.map +1 -0
  89. package/dist/credentials.js +142 -0
  90. package/dist/credentials.js.map +1 -0
  91. package/dist/credit-limits.d.ts +111 -0
  92. package/dist/credit-limits.d.ts.map +1 -0
  93. package/dist/credit-limits.js +35 -0
  94. package/dist/credit-limits.js.map +1 -0
  95. package/dist/currencies.d.ts +127 -0
  96. package/dist/currencies.d.ts.map +1 -0
  97. package/dist/currencies.js +20 -0
  98. package/dist/currencies.js.map +1 -0
  99. package/dist/custom-fields.d.ts +345 -0
  100. package/dist/custom-fields.d.ts.map +1 -0
  101. package/dist/custom-fields.js +185 -0
  102. package/dist/custom-fields.js.map +1 -0
  103. package/dist/customer-accounts.d.ts +690 -0
  104. package/dist/customer-accounts.d.ts.map +1 -0
  105. package/dist/customer-accounts.js +41 -0
  106. package/dist/customer-accounts.js.map +1 -0
  107. package/dist/customers.d.ts +305 -0
  108. package/dist/customers.d.ts.map +1 -0
  109. package/dist/customers.js +158 -0
  110. package/dist/customers.js.map +1 -0
  111. package/dist/dictionary.d.ts +580 -0
  112. package/dist/dictionary.d.ts.map +1 -0
  113. package/dist/dictionary.js +297 -0
  114. package/dist/dictionary.js.map +1 -0
  115. package/dist/email-address.d.ts +62 -0
  116. package/dist/email-address.d.ts.map +1 -0
  117. package/dist/email-address.js +64 -0
  118. package/dist/email-address.js.map +1 -0
  119. package/dist/email.d.ts +175 -0
  120. package/dist/email.d.ts.map +1 -0
  121. package/dist/email.js +45 -0
  122. package/dist/email.js.map +1 -0
  123. package/dist/envelopes.d.ts +15 -0
  124. package/dist/envelopes.d.ts.map +1 -0
  125. package/dist/envelopes.js +16 -0
  126. package/dist/envelopes.js.map +1 -0
  127. package/dist/environment-inputs.d.ts +306 -0
  128. package/dist/environment-inputs.d.ts.map +1 -0
  129. package/dist/environment-inputs.js +277 -0
  130. package/dist/environment-inputs.js.map +1 -0
  131. package/dist/erp-connector.d.ts +52 -0
  132. package/dist/erp-connector.d.ts.map +1 -0
  133. package/dist/erp-connector.js +34 -0
  134. package/dist/erp-connector.js.map +1 -0
  135. package/dist/errors.d.ts +455 -0
  136. package/dist/errors.d.ts.map +1 -0
  137. package/dist/errors.js +532 -0
  138. package/dist/errors.js.map +1 -0
  139. package/dist/google-analytics.d.ts +181 -0
  140. package/dist/google-analytics.d.ts.map +1 -0
  141. package/dist/google-analytics.js +176 -0
  142. package/dist/google-analytics.js.map +1 -0
  143. package/dist/google-tag-manager.d.ts +111 -0
  144. package/dist/google-tag-manager.d.ts.map +1 -0
  145. package/dist/google-tag-manager.js +129 -0
  146. package/dist/google-tag-manager.js.map +1 -0
  147. package/dist/i18n.d.ts +69 -0
  148. package/dist/i18n.d.ts.map +1 -0
  149. package/dist/i18n.js +59 -0
  150. package/dist/i18n.js.map +1 -0
  151. package/dist/import-export.d.ts +63 -0
  152. package/dist/import-export.d.ts.map +1 -0
  153. package/dist/import-export.js +37 -0
  154. package/dist/import-export.js.map +1 -0
  155. package/dist/index.d.ts +82 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +126 -0
  158. package/dist/index.js.map +1 -0
  159. package/dist/inventory.d.ts +673 -0
  160. package/dist/inventory.d.ts.map +1 -0
  161. package/dist/inventory.js +412 -0
  162. package/dist/inventory.js.map +1 -0
  163. package/dist/invoice-ledger.d.ts +366 -0
  164. package/dist/invoice-ledger.d.ts.map +1 -0
  165. package/dist/invoice-ledger.js +114 -0
  166. package/dist/invoice-ledger.js.map +1 -0
  167. package/dist/invoices.d.ts +845 -0
  168. package/dist/invoices.d.ts.map +1 -0
  169. package/dist/invoices.js +314 -0
  170. package/dist/invoices.js.map +1 -0
  171. package/dist/kernel.d.ts +49 -0
  172. package/dist/kernel.d.ts.map +1 -0
  173. package/dist/kernel.js +19 -0
  174. package/dist/kernel.js.map +1 -0
  175. package/dist/languages.d.ts +122 -0
  176. package/dist/languages.d.ts.map +1 -0
  177. package/dist/languages.js +24 -0
  178. package/dist/languages.js.map +1 -0
  179. package/dist/linkedin-ads.d.ts +167 -0
  180. package/dist/linkedin-ads.d.ts.map +1 -0
  181. package/dist/linkedin-ads.js +156 -0
  182. package/dist/linkedin-ads.js.map +1 -0
  183. package/dist/megamenu.d.ts +556 -0
  184. package/dist/megamenu.d.ts.map +1 -0
  185. package/dist/megamenu.js +186 -0
  186. package/dist/megamenu.js.map +1 -0
  187. package/dist/meta-ads.d.ts +126 -0
  188. package/dist/meta-ads.d.ts.map +1 -0
  189. package/dist/meta-ads.js +112 -0
  190. package/dist/meta-ads.js.map +1 -0
  191. package/dist/mfa.d.ts +274 -0
  192. package/dist/mfa.d.ts.map +1 -0
  193. package/dist/mfa.js +187 -0
  194. package/dist/mfa.js.map +1 -0
  195. package/dist/modules.d.ts +1706 -0
  196. package/dist/modules.d.ts.map +1 -0
  197. package/dist/modules.js +1390 -0
  198. package/dist/modules.js.map +1 -0
  199. package/dist/newsletter.d.ts +611 -0
  200. package/dist/newsletter.d.ts.map +1 -0
  201. package/dist/newsletter.js +345 -0
  202. package/dist/newsletter.js.map +1 -0
  203. package/dist/orders.d.ts +1175 -0
  204. package/dist/orders.d.ts.map +1 -0
  205. package/dist/orders.js +630 -0
  206. package/dist/orders.js.map +1 -0
  207. package/dist/organizations.d.ts +938 -0
  208. package/dist/organizations.d.ts.map +1 -0
  209. package/dist/organizations.js +418 -0
  210. package/dist/organizations.js.map +1 -0
  211. package/dist/pagination.d.ts +21 -0
  212. package/dist/pagination.d.ts.map +1 -0
  213. package/dist/pagination.js +22 -0
  214. package/dist/pagination.js.map +1 -0
  215. package/dist/payment-methods.d.ts +472 -0
  216. package/dist/payment-methods.d.ts.map +1 -0
  217. package/dist/payment-methods.js +175 -0
  218. package/dist/payment-methods.js.map +1 -0
  219. package/dist/payment-return-url.d.ts +53 -0
  220. package/dist/payment-return-url.d.ts.map +1 -0
  221. package/dist/payment-return-url.js +35 -0
  222. package/dist/payment-return-url.js.map +1 -0
  223. package/dist/payments.d.ts +386 -0
  224. package/dist/payments.d.ts.map +1 -0
  225. package/dist/payments.js +84 -0
  226. package/dist/payments.js.map +1 -0
  227. package/dist/pim-connector.d.ts +60 -0
  228. package/dist/pim-connector.d.ts.map +1 -0
  229. package/dist/pim-connector.js +43 -0
  230. package/dist/pim-connector.js.map +1 -0
  231. package/dist/pim-field-path.d.ts +6 -0
  232. package/dist/pim-field-path.d.ts.map +1 -0
  233. package/dist/pim-field-path.js +101 -0
  234. package/dist/pim-field-path.js.map +1 -0
  235. package/dist/platform-language.d.ts +20 -0
  236. package/dist/platform-language.d.ts.map +1 -0
  237. package/dist/platform-language.js +22 -0
  238. package/dist/platform-language.js.map +1 -0
  239. package/dist/price-lists.d.ts +685 -0
  240. package/dist/price-lists.d.ts.map +1 -0
  241. package/dist/price-lists.js +330 -0
  242. package/dist/price-lists.js.map +1 -0
  243. package/dist/product-feeds.d.ts +2837 -0
  244. package/dist/product-feeds.d.ts.map +1 -0
  245. package/dist/product-feeds.js +1504 -0
  246. package/dist/product-feeds.js.map +1 -0
  247. package/dist/product-scope-overrides.d.ts +134 -0
  248. package/dist/product-scope-overrides.d.ts.map +1 -0
  249. package/dist/product-scope-overrides.js +82 -0
  250. package/dist/product-scope-overrides.js.map +1 -0
  251. package/dist/product-value-resolver.d.ts +88 -0
  252. package/dist/product-value-resolver.d.ts.map +1 -0
  253. package/dist/product-value-resolver.js +128 -0
  254. package/dist/product-value-resolver.js.map +1 -0
  255. package/dist/promotions.d.ts +678 -0
  256. package/dist/promotions.d.ts.map +1 -0
  257. package/dist/promotions.js +479 -0
  258. package/dist/promotions.js.map +1 -0
  259. package/dist/prompt-actions.d.ts +582 -0
  260. package/dist/prompt-actions.d.ts.map +1 -0
  261. package/dist/prompt-actions.js +221 -0
  262. package/dist/prompt-actions.js.map +1 -0
  263. package/dist/pwa.d.ts +293 -0
  264. package/dist/pwa.d.ts.map +1 -0
  265. package/dist/pwa.js +204 -0
  266. package/dist/pwa.js.map +1 -0
  267. package/dist/quick-order.d.ts +340 -0
  268. package/dist/quick-order.d.ts.map +1 -0
  269. package/dist/quick-order.js +177 -0
  270. package/dist/quick-order.js.map +1 -0
  271. package/dist/quote-requests.d.ts +538 -0
  272. package/dist/quote-requests.d.ts.map +1 -0
  273. package/dist/quote-requests.js +308 -0
  274. package/dist/quote-requests.js.map +1 -0
  275. package/dist/returns.d.ts +774 -0
  276. package/dist/returns.d.ts.map +1 -0
  277. package/dist/returns.js +389 -0
  278. package/dist/returns.js.map +1 -0
  279. package/dist/sales-channels.d.ts +392 -0
  280. package/dist/sales-channels.d.ts.map +1 -0
  281. package/dist/sales-channels.js +285 -0
  282. package/dist/sales-channels.js.map +1 -0
  283. package/dist/scope-notice.d.ts +60 -0
  284. package/dist/scope-notice.d.ts.map +1 -0
  285. package/dist/scope-notice.js +56 -0
  286. package/dist/scope-notice.js.map +1 -0
  287. package/dist/search.d.ts +321 -0
  288. package/dist/search.d.ts.map +1 -0
  289. package/dist/search.js +160 -0
  290. package/dist/search.js.map +1 -0
  291. package/dist/seo.d.ts +113 -0
  292. package/dist/seo.d.ts.map +1 -0
  293. package/dist/seo.js +63 -0
  294. package/dist/seo.js.map +1 -0
  295. package/dist/settings.d.ts +453 -0
  296. package/dist/settings.d.ts.map +1 -0
  297. package/dist/settings.js +337 -0
  298. package/dist/settings.js.map +1 -0
  299. package/dist/shipments.d.ts +140 -0
  300. package/dist/shipments.d.ts.map +1 -0
  301. package/dist/shipments.js +14 -0
  302. package/dist/shipments.js.map +1 -0
  303. package/dist/shipping-methods.d.ts +350 -0
  304. package/dist/shipping-methods.d.ts.map +1 -0
  305. package/dist/shipping-methods.js +99 -0
  306. package/dist/shipping-methods.js.map +1 -0
  307. package/dist/shopping-lists.d.ts +122 -0
  308. package/dist/shopping-lists.d.ts.map +1 -0
  309. package/dist/shopping-lists.js +92 -0
  310. package/dist/shopping-lists.js.map +1 -0
  311. package/dist/taxes.d.ts +106 -0
  312. package/dist/taxes.d.ts.map +1 -0
  313. package/dist/taxes.js +80 -0
  314. package/dist/taxes.js.map +1 -0
  315. package/dist/text-normalization.d.ts +199 -0
  316. package/dist/text-normalization.d.ts.map +1 -0
  317. package/dist/text-normalization.js +205 -0
  318. package/dist/text-normalization.js.map +1 -0
  319. package/dist/transactional-emails.d.ts +459 -0
  320. package/dist/transactional-emails.d.ts.map +1 -0
  321. package/dist/transactional-emails.js +212 -0
  322. package/dist/transactional-emails.js.map +1 -0
  323. package/dist/webhooks.d.ts +69 -0
  324. package/dist/webhooks.d.ts.map +1 -0
  325. package/dist/webhooks.js +53 -0
  326. package/dist/webhooks.js.map +1 -0
  327. package/package.json +46 -0
@@ -0,0 +1,221 @@
1
+ import { z } from 'zod';
2
+ import { uuidSchema, moneySchema, multilingualStringSchema } from './common.js';
3
+ import { attributeValueTypeSchema } from './catalog.js';
4
+ // @endora-commerce/contracts — Compare module contracts (feature 007).
5
+ //
6
+ // Per Constitution V, this file is the source of truth for every Zod schema
7
+ // crossing the comparisons HTTP boundary; TS types are inferred via z.infer.
8
+ //
9
+ // US1 schemas (this file): owner-facing CRUD payloads and the
10
+ // `ComparisonOwnerView` response. US2 (recipient view), US4 (PDF export),
11
+ // and US5 (admin overview) extend this file in their respective phases.
12
+ // ---------------------------------------------------------------------------
13
+ // Constants used by storefront + admin clients.
14
+ // ---------------------------------------------------------------------------
15
+ export const COMPARE_DISPLAY_MODES = ['all', 'common', 'differences'];
16
+ export const COMPARE_MAX_PRODUCTS_LOWER_BOUND = 1;
17
+ export const COMPARE_MAX_PRODUCTS_UPPER_BOUND = 16;
18
+ // ---------------------------------------------------------------------------
19
+ // Display mode and per-attribute row class.
20
+ // ---------------------------------------------------------------------------
21
+ export const comparisonDisplayModeSchema = z.enum(COMPARE_DISPLAY_MODES);
22
+ /**
23
+ * Server-computed classification per attribute row, per research.md R-6:
24
+ * - `'common'` — every product carries the same value (set-equal for
25
+ * multi-value, ===-equal for scalars).
26
+ * - `'different'` — at least one product disagrees, OR at least one
27
+ * product has no value at all.
28
+ */
29
+ export const comparisonRowClassSchema = z.enum(['common', 'different']);
30
+ // ---------------------------------------------------------------------------
31
+ // Per-product card (always-on row of the comparison page / PDF).
32
+ // ---------------------------------------------------------------------------
33
+ export const comparisonProductSummarySchema = z.object({
34
+ id: uuidSchema,
35
+ sku: z.string(),
36
+ name: multilingualStringSchema,
37
+ slug: z.string(),
38
+ type: z.enum(['simple', 'configurable', 'grouped', 'bundle', 'virtual']),
39
+ /**
40
+ * Resolved base image (asset URL); null when the product has no
41
+ * `gallery_item_labels.label='base_image'` row or its asset cannot be
42
+ * resolved. The PDF renderer renders a placeholder when null.
43
+ */
44
+ primaryAssetUrl: z.string().url().nullable(),
45
+ /**
46
+ * Price in the viewer's sales-channel currency. Null when the product
47
+ * has no resolvable price for the channel (e.g. shared-link recipient
48
+ * on a channel where the product is not listed).
49
+ */
50
+ price: moneySchema.nullable(),
51
+ /**
52
+ * False when the product is not currently sellable in the viewer's
53
+ * channel — archived, channel-restricted, or otherwise refused. The
54
+ * column still renders, but the *Add to cart* control is disabled.
55
+ */
56
+ available: z.boolean(),
57
+ addedAt: z.string().datetime(),
58
+ });
59
+ // ---------------------------------------------------------------------------
60
+ // Body row of the comparison table (one per `comparable` attribute).
61
+ // ---------------------------------------------------------------------------
62
+ export const comparisonAttributeRowSchema = z.object({
63
+ key: z.string(),
64
+ label: multilingualStringSchema,
65
+ valueType: attributeValueTypeSchema,
66
+ /**
67
+ * One entry per product in the same column-order as `products`. Strings
68
+ * are pre-formatted by the server for display; multi-value attributes
69
+ * are joined with `', '`. `null` represents "no value" — the storefront
70
+ * renders it as `—` (per spec edge case "Missing values"). Per R-6,
71
+ * any `null` causes the row to be classified as `'different'`.
72
+ */
73
+ values: z.array(z.string().nullable()),
74
+ rowClass: comparisonRowClassSchema,
75
+ });
76
+ /**
77
+ * Whose prices the columns carry.
78
+ *
79
+ * The viewer's identity decides the figures, always: `organization` means they
80
+ * were resolved against the reader's own price lists, `channel` that they are
81
+ * the sales channel's public ones. A share token decides *which products* are
82
+ * in a comparison and never *which prices* are shown, so sender and recipient
83
+ * legitimately see different numbers on one link — and a reader who cannot tell
84
+ * which they are looking at cannot act on either.
85
+ */
86
+ export const comparisonPricedForSchema = z.enum(['organization', 'channel']);
87
+ // ---------------------------------------------------------------------------
88
+ // Full owner-facing read response.
89
+ // ---------------------------------------------------------------------------
90
+ export const comparisonOwnerViewSchema = z.object({
91
+ id: uuidSchema,
92
+ shareToken: z.string().min(8).max(32),
93
+ displayMode: comparisonDisplayModeSchema,
94
+ /** Resolved `compare.max_products` for the owner's sales channel. */
95
+ maxProducts: z.number().int().positive(),
96
+ products: z.array(comparisonProductSummarySchema),
97
+ comparableAttributes: z.array(comparisonAttributeRowSchema),
98
+ /** Whose prices the `products[].price` figures are. */
99
+ pricedFor: comparisonPricedForSchema,
100
+ /**
101
+ * How many products the comparison holds that this viewer may not see.
102
+ * Zero for almost every read; non-zero for a recipient the owner's
103
+ * restricted products are not disclosed to, and for an owner whose own
104
+ * product was restricted after they added it. The count is what lets a
105
+ * shorter table say so instead of being silently shorter.
106
+ */
107
+ hiddenProductCount: z.number().int().nonnegative(),
108
+ createdAt: z.string().datetime(),
109
+ updatedAt: z.string().datetime(),
110
+ });
111
+ export const comparisonOwnerResponseSchema = z.object({
112
+ data: comparisonOwnerViewSchema,
113
+ });
114
+ // ---------------------------------------------------------------------------
115
+ // Mutation inputs.
116
+ // ---------------------------------------------------------------------------
117
+ export const comparisonAddProductInputSchema = z.object({
118
+ productId: uuidSchema,
119
+ });
120
+ export const comparisonSetDisplayModeInputSchema = z.object({
121
+ displayMode: comparisonDisplayModeSchema,
122
+ });
123
+ // ---------------------------------------------------------------------------
124
+ // US2 — recipient (share-token) view.
125
+ // ---------------------------------------------------------------------------
126
+ /**
127
+ * Recipient-side projection. Same column shape as the owner view minus
128
+ * `maxProducts` (the recipient cannot mutate the comparison, so the cap
129
+ * is irrelevant) plus `meta.viewerIsOwner` so the storefront knows
130
+ * whether to render owner-only affordances (Add to cart, Remove,
131
+ * Delete, Copy share link).
132
+ */
133
+ export const comparisonSharedViewSchema = z.object({
134
+ id: uuidSchema,
135
+ shareToken: z.string().min(8).max(32),
136
+ displayMode: comparisonDisplayModeSchema,
137
+ products: z.array(comparisonProductSummarySchema),
138
+ comparableAttributes: z.array(comparisonAttributeRowSchema),
139
+ /**
140
+ * Whose prices these are — the recipient's own, or the channel's. The
141
+ * sender's are never among the answers: the token carries the products, not
142
+ * a pricing identity.
143
+ */
144
+ pricedFor: comparisonPricedForSchema,
145
+ /**
146
+ * How many of the sender's products this recipient may not see. The token
147
+ * grants access to the comparison, never to what is in it, so a recipient's
148
+ * table is the sender's minus whatever the sender's organisation alone is
149
+ * entitled to — and it says how much is missing rather than being quietly
150
+ * shorter.
151
+ */
152
+ hiddenProductCount: z.number().int().nonnegative(),
153
+ createdAt: z.string().datetime(),
154
+ updatedAt: z.string().datetime(),
155
+ });
156
+ export const comparisonSharedResponseSchema = z.object({
157
+ data: comparisonSharedViewSchema,
158
+ meta: z.object({
159
+ viewerIsOwner: z.boolean(),
160
+ }),
161
+ });
162
+ // ---------------------------------------------------------------------------
163
+ // US5 — admin overview (read-only).
164
+ // ---------------------------------------------------------------------------
165
+ export const comparisonAdminOwnerSchema = z.object({
166
+ kind: z.enum(['customer', 'anonymous']),
167
+ customerAccountId: uuidSchema.nullable(),
168
+ /** Human-readable identifier for the list (email or display name). */
169
+ email: z.string().nullable(),
170
+ /** The opaque cookie token; null for authenticated owners. */
171
+ anonymousToken: z.string().nullable(),
172
+ });
173
+ export const comparisonAdminSalesChannelSchema = z.object({
174
+ id: uuidSchema,
175
+ code: z.string(),
176
+ });
177
+ export const comparisonAdminListItemSchema = z.object({
178
+ id: uuidSchema,
179
+ shareToken: z.string(),
180
+ owner: comparisonAdminOwnerSchema,
181
+ salesChannel: comparisonAdminSalesChannelSchema,
182
+ displayMode: comparisonDisplayModeSchema,
183
+ productCount: z.number().int().nonnegative(),
184
+ createdAt: z.string().datetime(),
185
+ updatedAt: z.string().datetime(),
186
+ });
187
+ export const comparisonAdminListQuerySchema = z.object({
188
+ salesChannelId: uuidSchema.optional(),
189
+ customerAccountId: uuidSchema.optional(),
190
+ ownerType: z.enum(['customer', 'anonymous']).optional(),
191
+ createdAfter: z.string().datetime().optional(),
192
+ createdBefore: z.string().datetime().optional(),
193
+ cursor: z.string().optional(),
194
+ limit: z.number().int().min(1).max(100).optional(),
195
+ });
196
+ export const comparisonAdminListResponseSchema = z.object({
197
+ data: z.array(comparisonAdminListItemSchema),
198
+ meta: z.object({
199
+ limit: z.number().int().positive(),
200
+ nextCursor: z.string().nullable(),
201
+ }),
202
+ });
203
+ /**
204
+ * Admin detail — same shape the storefront owner sees, plus the admin
205
+ * metadata block (owner identity, sales channel, raw shareToken). The
206
+ * detail endpoint renders prices in the comparison's RECORDED channel
207
+ * (the creator's), not the admin's preferred channel — so a support
208
+ * investigation matches what the customer reported.
209
+ */
210
+ export const comparisonAdminDetailSchema = z.object({
211
+ id: uuidSchema,
212
+ shareToken: z.string(),
213
+ owner: comparisonAdminOwnerSchema,
214
+ salesChannel: comparisonAdminSalesChannelSchema,
215
+ displayMode: comparisonDisplayModeSchema,
216
+ products: z.array(comparisonProductSummarySchema),
217
+ comparableAttributes: z.array(comparisonAttributeRowSchema),
218
+ createdAt: z.string().datetime(),
219
+ updatedAt: z.string().datetime(),
220
+ });
221
+ //# sourceMappingURL=comparisons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparisons.js","sourceRoot":"","sources":["../src/comparisons.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,292 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Credentials module (feature 058) — boundary schemas.
4
+ *
5
+ * The credentials core is type-agnostic (Principle XIV): a "configuration type"
6
+ * is a code-registered descriptor declaring its provider variants and per-field
7
+ * definitions (some `secret`). The core stores/validates the declared fields but
8
+ * never interprets provider meaning. These schemas are the single source of
9
+ * truth for the admin API and the in-process configuration-type registry.
10
+ *
11
+ * Secret field values are NEVER returned in plaintext by any read: the DTO
12
+ * replaces them with an `isSet` boolean. Only the server-side `resolve` path
13
+ * (not modelled as an HTTP response) exposes decrypted values for consumer use.
14
+ */
15
+ /** Frozen field-kind set. */
16
+ export declare const CREDENTIAL_FIELD_KINDS: readonly ["string", "number", "boolean", "select"];
17
+ export declare const FieldKindSchema: z.ZodEnum<{
18
+ string: "string";
19
+ number: "number";
20
+ boolean: "boolean";
21
+ select: "select";
22
+ }>;
23
+ export type FieldKind = z.infer<typeof FieldKindSchema>;
24
+ export declare const FieldOptionSchema: z.ZodObject<{
25
+ value: z.ZodString;
26
+ label: z.ZodString;
27
+ }, z.core.$strip>;
28
+ export type FieldOption = z.infer<typeof FieldOptionSchema>;
29
+ export declare const FieldDefinitionSchema: z.ZodObject<{
30
+ key: z.ZodString;
31
+ label: z.ZodString;
32
+ kind: z.ZodEnum<{
33
+ string: "string";
34
+ number: "number";
35
+ boolean: "boolean";
36
+ select: "select";
37
+ }>;
38
+ required: z.ZodBoolean;
39
+ secret: z.ZodBoolean;
40
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
41
+ value: z.ZodString;
42
+ label: z.ZodString;
43
+ }, z.core.$strip>>>;
44
+ placeholder: z.ZodOptional<z.ZodString>;
45
+ }, z.core.$strip>;
46
+ export type FieldDefinition = z.infer<typeof FieldDefinitionSchema>;
47
+ export declare const ProviderVariantSchema: z.ZodObject<{
48
+ code: z.ZodString;
49
+ label: z.ZodString;
50
+ fields: z.ZodArray<z.ZodObject<{
51
+ key: z.ZodString;
52
+ label: z.ZodString;
53
+ kind: z.ZodEnum<{
54
+ string: "string";
55
+ number: "number";
56
+ boolean: "boolean";
57
+ select: "select";
58
+ }>;
59
+ required: z.ZodBoolean;
60
+ secret: z.ZodBoolean;
61
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
62
+ value: z.ZodString;
63
+ label: z.ZodString;
64
+ }, z.core.$strip>>>;
65
+ placeholder: z.ZodOptional<z.ZodString>;
66
+ }, z.core.$strip>>;
67
+ }, z.core.$strip>;
68
+ export type ProviderVariant = z.infer<typeof ProviderVariantSchema>;
69
+ export declare const ConfigurationTypeDescriptorSchema: z.ZodObject<{
70
+ code: z.ZodString;
71
+ label: z.ZodString;
72
+ ownerModule: z.ZodString;
73
+ providers: z.ZodArray<z.ZodObject<{
74
+ code: z.ZodString;
75
+ label: z.ZodString;
76
+ fields: z.ZodArray<z.ZodObject<{
77
+ key: z.ZodString;
78
+ label: z.ZodString;
79
+ kind: z.ZodEnum<{
80
+ string: "string";
81
+ number: "number";
82
+ boolean: "boolean";
83
+ select: "select";
84
+ }>;
85
+ required: z.ZodBoolean;
86
+ secret: z.ZodBoolean;
87
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
88
+ value: z.ZodString;
89
+ label: z.ZodString;
90
+ }, z.core.$strip>>>;
91
+ placeholder: z.ZodOptional<z.ZodString>;
92
+ }, z.core.$strip>>;
93
+ }, z.core.$strip>>;
94
+ }, z.core.$strip>;
95
+ export type ConfigurationTypeDescriptor = z.infer<typeof ConfigurationTypeDescriptorSchema>;
96
+ /** `GET /api/v1/admin/credentials/types` response. */
97
+ export declare const ConfigurationTypesResponseSchema: z.ZodObject<{
98
+ types: z.ZodArray<z.ZodObject<{
99
+ code: z.ZodString;
100
+ label: z.ZodString;
101
+ ownerModule: z.ZodString;
102
+ providers: z.ZodArray<z.ZodObject<{
103
+ code: z.ZodString;
104
+ label: z.ZodString;
105
+ fields: z.ZodArray<z.ZodObject<{
106
+ key: z.ZodString;
107
+ label: z.ZodString;
108
+ kind: z.ZodEnum<{
109
+ string: "string";
110
+ number: "number";
111
+ boolean: "boolean";
112
+ select: "select";
113
+ }>;
114
+ required: z.ZodBoolean;
115
+ secret: z.ZodBoolean;
116
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
117
+ value: z.ZodString;
118
+ label: z.ZodString;
119
+ }, z.core.$strip>>>;
120
+ placeholder: z.ZodOptional<z.ZodString>;
121
+ }, z.core.$strip>>;
122
+ }, z.core.$strip>>;
123
+ }, z.core.$strip>>;
124
+ }, z.core.$strip>;
125
+ export type ConfigurationTypesResponse = z.infer<typeof ConfigurationTypesResponseSchema>;
126
+ /** `POST /api/v1/admin/credentials` body. */
127
+ export declare const CreateConfigurationSchema: z.ZodObject<{
128
+ code: z.ZodString;
129
+ name: z.ZodString;
130
+ typeCode: z.ZodString;
131
+ providerCode: z.ZodString;
132
+ values: z.ZodRecord<z.ZodString, z.ZodUnknown>;
133
+ }, z.core.$strip>;
134
+ export type CreateConfiguration = z.infer<typeof CreateConfigurationSchema>;
135
+ /**
136
+ * `PUT /api/v1/admin/credentials/:code` body.
137
+ *
138
+ * `typeCode`/`providerCode` are intentionally absent — they are immutable after
139
+ * create (a change is rejected with `CREDENTIAL_TYPE_IMMUTABLE`). A secret field
140
+ * omitted or submitted blank/`[redacted]` preserves the stored envelope
141
+ * (write-only semantics, FR-015). `expectedVersion` drives the optimistic lock.
142
+ */
143
+ export declare const UpdateConfigurationSchema: z.ZodObject<{
144
+ name: z.ZodOptional<z.ZodString>;
145
+ values: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
146
+ expectedVersion: z.ZodOptional<z.ZodNumber>;
147
+ }, z.core.$strip>;
148
+ export type UpdateConfiguration = z.infer<typeof UpdateConfigurationSchema>;
149
+ /**
150
+ * One field in a masked configuration DTO. Secret fields carry only `isSet`
151
+ * (never a value); non-secret fields carry their plain `value`.
152
+ */
153
+ export declare const ConfigurationFieldDtoSchema: z.ZodObject<{
154
+ key: z.ZodString;
155
+ secret: z.ZodBoolean;
156
+ isSet: z.ZodOptional<z.ZodBoolean>;
157
+ value: z.ZodOptional<z.ZodUnknown>;
158
+ }, z.core.$strip>;
159
+ export type ConfigurationFieldDto = z.infer<typeof ConfigurationFieldDtoSchema>;
160
+ export declare const ConfigurationDtoSchema: z.ZodObject<{
161
+ id: z.ZodString;
162
+ code: z.ZodString;
163
+ name: z.ZodString;
164
+ typeCode: z.ZodString;
165
+ typeLabel: z.ZodNullable<z.ZodString>;
166
+ providerCode: z.ZodString;
167
+ providerLabel: z.ZodNullable<z.ZodString>;
168
+ inert: z.ZodBoolean;
169
+ fields: z.ZodArray<z.ZodObject<{
170
+ key: z.ZodString;
171
+ secret: z.ZodBoolean;
172
+ isSet: z.ZodOptional<z.ZodBoolean>;
173
+ value: z.ZodOptional<z.ZodUnknown>;
174
+ }, z.core.$strip>>;
175
+ version: z.ZodNumber;
176
+ updatedAt: z.ZodString;
177
+ }, z.core.$strip>;
178
+ export type ConfigurationDto = z.infer<typeof ConfigurationDtoSchema>;
179
+ /** `GET /api/v1/admin/credentials` response. */
180
+ export declare const ConfigurationListResponseSchema: z.ZodObject<{
181
+ configurations: z.ZodArray<z.ZodObject<{
182
+ id: z.ZodString;
183
+ code: z.ZodString;
184
+ name: z.ZodString;
185
+ typeCode: z.ZodString;
186
+ typeLabel: z.ZodNullable<z.ZodString>;
187
+ providerCode: z.ZodString;
188
+ providerLabel: z.ZodNullable<z.ZodString>;
189
+ inert: z.ZodBoolean;
190
+ fields: z.ZodArray<z.ZodObject<{
191
+ key: z.ZodString;
192
+ secret: z.ZodBoolean;
193
+ isSet: z.ZodOptional<z.ZodBoolean>;
194
+ value: z.ZodOptional<z.ZodUnknown>;
195
+ }, z.core.$strip>>;
196
+ version: z.ZodNumber;
197
+ updatedAt: z.ZodString;
198
+ }, z.core.$strip>>;
199
+ }, z.core.$strip>;
200
+ export type ConfigurationListResponse = z.infer<typeof ConfigurationListResponseSchema>;
201
+ /** Optional `?type=` filter on the list endpoint. */
202
+ export declare const ConfigurationListQuerySchema: z.ZodObject<{
203
+ type: z.ZodOptional<z.ZodString>;
204
+ }, z.core.$strip>;
205
+ export type ConfigurationListQuery = z.infer<typeof ConfigurationListQuerySchema>;
206
+ /** Delete-blocked payload — the settings referencing a configuration (FR-012). */
207
+ export declare const ConfigurationReferenceSchema: z.ZodObject<{
208
+ settingCode: z.ZodString;
209
+ salesChannelCode: z.ZodOptional<z.ZodString>;
210
+ }, z.core.$strip>;
211
+ export type ConfigurationReference = z.infer<typeof ConfigurationReferenceSchema>;
212
+ /** Frozen resolution-status set. */
213
+ export declare const CREDENTIAL_RESOLVE_STATUSES: readonly ["ok", "not_configured", "unavailable"];
214
+ export declare const CREDENTIAL_UNAVAILABLE_REASONS: readonly ["missing", "inert_type"];
215
+ /**
216
+ * Discriminated result of `CredentialsService.resolve(code)`. `ok` carries
217
+ * decrypted secret values for in-memory consumer use only; the other variants
218
+ * fail closed (never a foreign configuration, never a plaintext leak).
219
+ */
220
+ export declare const ResolveResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
221
+ status: z.ZodLiteral<"ok">;
222
+ typeCode: z.ZodString;
223
+ providerCode: z.ZodString;
224
+ values: z.ZodRecord<z.ZodString, z.ZodUnknown>;
225
+ }, z.core.$strip>, z.ZodObject<{
226
+ status: z.ZodLiteral<"not_configured">;
227
+ }, z.core.$strip>, z.ZodObject<{
228
+ status: z.ZodLiteral<"unavailable">;
229
+ reason: z.ZodEnum<{
230
+ missing: "missing";
231
+ inert_type: "inert_type";
232
+ }>;
233
+ }, z.core.$strip>], "status">;
234
+ export type ResolveResult = z.infer<typeof ResolveResultSchema>;
235
+ /**
236
+ * Container name: `credentialsService`. Owner: `credentials`.
237
+ *
238
+ * `resolve` is the one method that matters at run time: it decrypts a stored
239
+ * configuration's secrets for the integration about to use them. When
240
+ * `credentials` is off it fails closed, and it must — an integration that
241
+ * caught the refusal and proceeded would run against whatever it had cached,
242
+ * which for a credential means "the one the operator just revoked".
243
+ */
244
+ export interface CredentialsPort {
245
+ list(typeFilter?: string): Promise<ConfigurationDto[]>;
246
+ getByCode(code: string): Promise<ConfigurationDto | null>;
247
+ create(data: CreateConfiguration): Promise<ConfigurationDto>;
248
+ update(code: string, data: UpdateConfiguration): Promise<ConfigurationDto>;
249
+ delete(code: string): Promise<void>;
250
+ resolve(configurationCode: string): Promise<ResolveResult>;
251
+ }
252
+ /**
253
+ * Container name: `configurationTypeRegistry`. Owner: `credentials`.
254
+ *
255
+ * A **contribution seam**: a module that needs a credential type describes it
256
+ * here from its boot hook, and the admin screen renders the form from the
257
+ * descriptor. Every edge into it classifies as `contributes`.
258
+ *
259
+ * `isAvailable` / `get` / `resolve` / `list` filter on the contributor's
260
+ * effective state; `entry`, `ownerOf` and `listAll` deliberately do not, so an
261
+ * admin screen can keep showing a stored configuration *and* the reason its
262
+ * type is unavailable — a credential row outlives the module that described
263
+ * its shape, and hiding the row would look like data loss.
264
+ *
265
+ * **Owner off:** nothing throws here. This is a **contribution seam**, a plain
266
+ * `di.register` rather than a `providePort`, so a push still lands and
267
+ * `credentials` filters by contributor when it enumerates. Converting it to
268
+ * `providePort` would move every edge into it from `contributes` to
269
+ * `fails-closed` in the deactivation-consequence ledger, and change the
270
+ * sentence the operator's confirmation dialog renders.
271
+ */
272
+ export interface ConfigurationTypeRegistryPort {
273
+ register(descriptor: ConfigurationTypeDescriptor): void;
274
+ unregister(code: string): void;
275
+ /** Registered at all, presence-blind. */
276
+ isRegistered(code: string): boolean;
277
+ /** Registered **and** its contributing module effectively present. */
278
+ isAvailable(code: string): boolean;
279
+ /** The descriptor, presence-blind. */
280
+ entry(code: string): ConfigurationTypeDescriptor | undefined;
281
+ /** The descriptor, or `undefined` when unregistered or its owner is absent. */
282
+ get(code: string): ConfigurationTypeDescriptor | undefined;
283
+ /** Like {@link get}, but throws `ConfigurationTypeUnknown` instead. */
284
+ resolve(code: string): ConfigurationTypeDescriptor;
285
+ /** Descriptors whose contributor is present, in registration order. */
286
+ list(): ConfigurationTypeDescriptor[];
287
+ /** Every registered descriptor, presence-blind. */
288
+ listAll(): ConfigurationTypeDescriptor[];
289
+ /** Which module contributed the code, or `null` when nobody did. */
290
+ ownerOf(code: string): string | null;
291
+ }
292
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Credentials module (feature 058) — boundary schemas.
4
+ *
5
+ * The credentials core is type-agnostic (Principle XIV): a "configuration type"
6
+ * is a code-registered descriptor declaring its provider variants and per-field
7
+ * definitions (some `secret`). The core stores/validates the declared fields but
8
+ * never interprets provider meaning. These schemas are the single source of
9
+ * truth for the admin API and the in-process configuration-type registry.
10
+ *
11
+ * Secret field values are NEVER returned in plaintext by any read: the DTO
12
+ * replaces them with an `isSet` boolean. Only the server-side `resolve` path
13
+ * (not modelled as an HTTP response) exposes decrypted values for consumer use.
14
+ */
15
+ // ---------------------------------------------------------------------------
16
+ // Configuration-type descriptors (registry surface)
17
+ // ---------------------------------------------------------------------------
18
+ /** Frozen field-kind set. */
19
+ export const CREDENTIAL_FIELD_KINDS = ['string', 'number', 'boolean', 'select'];
20
+ export const FieldKindSchema = z.enum(CREDENTIAL_FIELD_KINDS);
21
+ export const FieldOptionSchema = z.object({
22
+ value: z.string(),
23
+ label: z.string(),
24
+ });
25
+ export const FieldDefinitionSchema = z.object({
26
+ key: z.string().min(1),
27
+ label: z.string(),
28
+ kind: FieldKindSchema,
29
+ required: z.boolean(),
30
+ secret: z.boolean(),
31
+ options: z.array(FieldOptionSchema).optional(),
32
+ placeholder: z.string().optional(),
33
+ });
34
+ export const ProviderVariantSchema = z.object({
35
+ code: z.string().min(1),
36
+ label: z.string(),
37
+ fields: z.array(FieldDefinitionSchema),
38
+ });
39
+ export const ConfigurationTypeDescriptorSchema = z.object({
40
+ code: z.string().min(1),
41
+ label: z.string(),
42
+ ownerModule: z.string().min(1),
43
+ providers: z.array(ProviderVariantSchema),
44
+ });
45
+ /** `GET /api/v1/admin/credentials/types` response. */
46
+ export const ConfigurationTypesResponseSchema = z.object({
47
+ types: z.array(ConfigurationTypeDescriptorSchema),
48
+ });
49
+ // ---------------------------------------------------------------------------
50
+ // Write requests
51
+ // ---------------------------------------------------------------------------
52
+ /** `POST /api/v1/admin/credentials` body. */
53
+ export const CreateConfigurationSchema = z.object({
54
+ code: z.string().min(1).max(128),
55
+ name: z.string().min(1).max(255),
56
+ typeCode: z.string().min(1).max(64),
57
+ providerCode: z.string().min(1).max(64),
58
+ /** Field-value bag keyed by `FieldDefinition.key`; validated per descriptor. */
59
+ values: z.record(z.string(), z.unknown()),
60
+ });
61
+ /**
62
+ * `PUT /api/v1/admin/credentials/:code` body.
63
+ *
64
+ * `typeCode`/`providerCode` are intentionally absent — they are immutable after
65
+ * create (a change is rejected with `CREDENTIAL_TYPE_IMMUTABLE`). A secret field
66
+ * omitted or submitted blank/`[redacted]` preserves the stored envelope
67
+ * (write-only semantics, FR-015). `expectedVersion` drives the optimistic lock.
68
+ */
69
+ export const UpdateConfigurationSchema = z.object({
70
+ name: z.string().min(1).max(255).optional(),
71
+ values: z.record(z.string(), z.unknown()).optional(),
72
+ expectedVersion: z.number().int().nonnegative().optional(),
73
+ });
74
+ // ---------------------------------------------------------------------------
75
+ // Read DTO (secrets masked)
76
+ // ---------------------------------------------------------------------------
77
+ /**
78
+ * One field in a masked configuration DTO. Secret fields carry only `isSet`
79
+ * (never a value); non-secret fields carry their plain `value`.
80
+ */
81
+ export const ConfigurationFieldDtoSchema = z.object({
82
+ key: z.string(),
83
+ secret: z.boolean(),
84
+ /** Present for secret fields — whether a secret is stored. */
85
+ isSet: z.boolean().optional(),
86
+ /** Present for non-secret fields — the plain stored value. */
87
+ value: z.unknown().optional(),
88
+ });
89
+ export const ConfigurationDtoSchema = z.object({
90
+ id: z.string(),
91
+ code: z.string(),
92
+ name: z.string(),
93
+ typeCode: z.string(),
94
+ /** Null when the type is no longer registered (inert). */
95
+ typeLabel: z.string().nullable(),
96
+ providerCode: z.string(),
97
+ /** Null when the type/provider is no longer registered (inert). */
98
+ providerLabel: z.string().nullable(),
99
+ /** True when `typeCode` is no longer registered; the row renders read-only. */
100
+ inert: z.boolean(),
101
+ fields: z.array(ConfigurationFieldDtoSchema),
102
+ version: z.number().int(),
103
+ updatedAt: z.string(),
104
+ });
105
+ /** `GET /api/v1/admin/credentials` response. */
106
+ export const ConfigurationListResponseSchema = z.object({
107
+ configurations: z.array(ConfigurationDtoSchema),
108
+ });
109
+ /** Optional `?type=` filter on the list endpoint. */
110
+ export const ConfigurationListQuerySchema = z.object({
111
+ type: z.string().min(1).max(64).optional(),
112
+ });
113
+ /** Delete-blocked payload — the settings referencing a configuration (FR-012). */
114
+ export const ConfigurationReferenceSchema = z.object({
115
+ settingCode: z.string(),
116
+ salesChannelCode: z.string().optional(),
117
+ });
118
+ // ---------------------------------------------------------------------------
119
+ // Server-side resolution (never an HTTP response body)
120
+ // ---------------------------------------------------------------------------
121
+ /** Frozen resolution-status set. */
122
+ export const CREDENTIAL_RESOLVE_STATUSES = ['ok', 'not_configured', 'unavailable'];
123
+ export const CREDENTIAL_UNAVAILABLE_REASONS = ['missing', 'inert_type'];
124
+ /**
125
+ * Discriminated result of `CredentialsService.resolve(code)`. `ok` carries
126
+ * decrypted secret values for in-memory consumer use only; the other variants
127
+ * fail closed (never a foreign configuration, never a plaintext leak).
128
+ */
129
+ export const ResolveResultSchema = z.discriminatedUnion('status', [
130
+ z.object({
131
+ status: z.literal('ok'),
132
+ typeCode: z.string(),
133
+ providerCode: z.string(),
134
+ values: z.record(z.string(), z.unknown()),
135
+ }),
136
+ z.object({ status: z.literal('not_configured') }),
137
+ z.object({
138
+ status: z.literal('unavailable'),
139
+ reason: z.enum(CREDENTIAL_UNAVAILABLE_REASONS),
140
+ }),
141
+ ]);
142
+ //# sourceMappingURL=credentials.js.map