@youzan-cloud/zan-saas-cli 0.0.0-stage → 0.1.0-beta.3

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 (329) hide show
  1. package/DEPENDENCIES.json +50 -0
  2. package/INSTALL.md +79 -0
  3. package/LICENSE +21 -0
  4. package/NOTICE +1 -0
  5. package/README.md +151 -2
  6. package/THIRD_PARTY_NOTICES.txt +162 -0
  7. package/bin/zan-saas-cli.js +28 -0
  8. package/internal/registry/index.js +123 -0
  9. package/internal/registry/manifest.json +424 -0
  10. package/npm-shrinkwrap.json +86 -0
  11. package/package.json +33 -4
  12. package/skills/README.md +30 -0
  13. package/skills/zan-saas/SKILL.md +54 -0
  14. package/skills/zan-saas/references/host-entry.md +25 -0
  15. package/skills/zan-saas-access/SKILL.md +37 -0
  16. package/skills/zan-saas-access/references/role-list.md +11 -0
  17. package/skills/zan-saas-access/references/staff-perms-get.md +11 -0
  18. package/skills/zan-saas-aftersale/SKILL.md +31 -0
  19. package/skills/zan-saas-aftersale/references/case-list.md +13 -0
  20. package/skills/zan-saas-aftersale/references/case-scan.md +31 -0
  21. package/skills/zan-saas-benefit/SKILL.md +46 -0
  22. package/skills/zan-saas-benefit/references/card-get.md +7 -0
  23. package/skills/zan-saas-benefit/references/card-grant-list.md +11 -0
  24. package/skills/zan-saas-benefit/references/card-list.md +7 -0
  25. package/skills/zan-saas-benefit/references/customer-card-get.md +7 -0
  26. package/skills/zan-saas-benefit/references/customer-card-list.md +7 -0
  27. package/skills/zan-saas-coupon/SKILL.md +41 -0
  28. package/skills/zan-saas-coupon/references/activity-get.md +11 -0
  29. package/skills/zan-saas-coupon/references/activity-list.md +15 -0
  30. package/skills/zan-saas-coupon/references/voucher-get.md +13 -0
  31. package/skills/zan-saas-coupon/references/voucher-list.md +25 -0
  32. package/skills/zan-saas-customer/SKILL.md +73 -0
  33. package/skills/zan-saas-customer/references/customer-scan.md +11 -0
  34. package/skills/zan-saas-customer/references/segment-list.md +22 -0
  35. package/skills/zan-saas-fulfillment/SKILL.md +36 -0
  36. package/skills/zan-saas-fulfillment/references/delivery-get.md +11 -0
  37. package/skills/zan-saas-fulfillment/references/shipment-list.md +11 -0
  38. package/skills/zan-saas-fulfillment/references/waybill-get.md +9 -0
  39. package/skills/zan-saas-interaction/SKILL.md +37 -0
  40. package/skills/zan-saas-interaction/references/lottery-get.md +11 -0
  41. package/skills/zan-saas-interaction/references/lottery-list.md +19 -0
  42. package/skills/zan-saas-item/SKILL.md +61 -0
  43. package/skills/zan-saas-item/references/attribute-list.md +11 -0
  44. package/skills/zan-saas-item/references/brand-list.md +7 -0
  45. package/skills/zan-saas-item/references/classification-get.md +7 -0
  46. package/skills/zan-saas-item/references/classification-list.md +7 -0
  47. package/skills/zan-saas-item/references/group-list.md +9 -0
  48. package/skills/zan-saas-item/references/item-content.md +9 -0
  49. package/skills/zan-saas-item/references/item-get.md +9 -0
  50. package/skills/zan-saas-item/references/item-search.md +23 -0
  51. package/skills/zan-saas-item/references/product-identity.md +11 -0
  52. package/skills/zan-saas-member/SKILL.md +41 -0
  53. package/skills/zan-saas-member/references/customer-level-get.md +7 -0
  54. package/skills/zan-saas-member/references/growth-log-list.md +17 -0
  55. package/skills/zan-saas-member/references/membership-get.md +7 -0
  56. package/skills/zan-saas-order/SKILL.md +56 -0
  57. package/skills/zan-saas-order/references/order-get.md +26 -0
  58. package/skills/zan-saas-order/references/order-list.md +25 -0
  59. package/skills/zan-saas-order/references/order-scan.md +35 -0
  60. package/skills/zan-saas-org/SKILL.md +37 -0
  61. package/skills/zan-saas-org/references/staff-get.md +15 -0
  62. package/skills/zan-saas-org/references/staff-role-get.md +11 -0
  63. package/skills/zan-saas-org/references/unit-get.md +11 -0
  64. package/skills/zan-saas-org/references/unit-list.md +15 -0
  65. package/skills/zan-saas-points/SKILL.md +42 -0
  66. package/skills/zan-saas-points/references/account-get.md +7 -0
  67. package/skills/zan-saas-points/references/log-list.md +17 -0
  68. package/skills/zan-saas-points/references/rule-list.md +2 -0
  69. package/skills/zan-saas-privacy/SKILL.md +30 -0
  70. package/skills/zan-saas-privacy/references/field-decrypt.md +19 -0
  71. package/skills/zan-saas-shared/SKILL.md +94 -0
  72. package/skills/zan-saas-shared/references/authentication.md +52 -0
  73. package/skills/zan-saas-shared/references/value-processing.md +27 -0
  74. package/skills/zan-saas-stock/SKILL.md +28 -0
  75. package/skills/zan-saas-stock/references/log-list.md +11 -0
  76. package/skills/zan-saas-valuecard/SKILL.md +37 -0
  77. package/skills/zan-saas-valuecard/references/card-get.md +13 -0
  78. package/skills/zan-saas-valuecard/references/card-list.md +11 -0
  79. package/src/auth/browser.js +28 -0
  80. package/src/auth/callback-server.js +99 -0
  81. package/src/auth/config.js +53 -0
  82. package/src/auth/credential-store.js +109 -0
  83. package/src/auth/oauth-client.js +105 -0
  84. package/src/auth/pkce.js +28 -0
  85. package/src/auth/session.js +178 -0
  86. package/src/auth/tool.js +25 -0
  87. package/src/cli/command-paths.js +126 -0
  88. package/src/cli/context-help.js +102 -0
  89. package/src/cli/diagnostic-command.js +57 -0
  90. package/src/cli/domain-catalog.js +42 -0
  91. package/src/cli/help-text.js +32 -0
  92. package/src/cli/native-loader.js +120 -0
  93. package/src/cli/native-path.js +22 -0
  94. package/src/cli/parser-policy.js +141 -0
  95. package/src/cli/program.js +134 -0
  96. package/src/cli/skill-catalog.js +241 -0
  97. package/src/commands/native/access/commands.index.json +24 -0
  98. package/src/commands/native/access/domain.json +3 -0
  99. package/src/commands/native/access/role/list/command.js +141 -0
  100. package/src/commands/native/access/role/list/schema.json +393 -0
  101. package/src/commands/native/access/staff-perms/get/command.js +119 -0
  102. package/src/commands/native/access/staff-perms/get/schema.json +703 -0
  103. package/src/commands/native/aftersale/case/get/command.js +104 -0
  104. package/src/commands/native/aftersale/case/get/exact-json.js +52 -0
  105. package/src/commands/native/aftersale/case/get/money.js +28 -0
  106. package/src/commands/native/aftersale/case/get/projection.js +120 -0
  107. package/src/commands/native/aftersale/case/get/query.js +72 -0
  108. package/src/commands/native/aftersale/case/get/schema.json +134 -0
  109. package/src/commands/native/aftersale/case/list/command.js +135 -0
  110. package/src/commands/native/aftersale/case/list/schema.json +1095 -0
  111. package/src/commands/native/aftersale/case/scan/command.js +110 -0
  112. package/src/commands/native/aftersale/case/scan/query.js +62 -0
  113. package/src/commands/native/aftersale/case/scan/scan.js +78 -0
  114. package/src/commands/native/aftersale/case/scan/schema.json +964 -0
  115. package/src/commands/native/aftersale/case/scan/search.js +108 -0
  116. package/src/commands/native/aftersale/commands.index.json +42 -0
  117. package/src/commands/native/aftersale/domain.json +3 -0
  118. package/src/commands/native/aftersale/refund/list/command.js +97 -0
  119. package/src/commands/native/aftersale/refund/list/money.js +25 -0
  120. package/src/commands/native/aftersale/refund/list/projection.js +50 -0
  121. package/src/commands/native/aftersale/refund/list/query.js +73 -0
  122. package/src/commands/native/aftersale/refund/list/schema.json +130 -0
  123. package/src/commands/native/aftersale/shared/query.js +58 -0
  124. package/src/commands/native/aftersale/shared/search.js +128 -0
  125. package/src/commands/native/benefit/card-definition/get/command.js +110 -0
  126. package/src/commands/native/benefit/card-definition/get/schema.json +545 -0
  127. package/src/commands/native/benefit/card-definition/list/command.js +105 -0
  128. package/src/commands/native/benefit/card-definition/list/schema.json +690 -0
  129. package/src/commands/native/benefit/card-grant/list/command.js +135 -0
  130. package/src/commands/native/benefit/card-grant/list/schema.json +758 -0
  131. package/src/commands/native/benefit/commands.index.json +51 -0
  132. package/src/commands/native/benefit/customer-card/get/command.js +110 -0
  133. package/src/commands/native/benefit/customer-card/get/schema.json +340 -0
  134. package/src/commands/native/benefit/customer-card/list/command.js +102 -0
  135. package/src/commands/native/benefit/customer-card/list/schema.json +731 -0
  136. package/src/commands/native/benefit/domain.json +3 -0
  137. package/src/commands/native/coupon/activity/get/command.js +183 -0
  138. package/src/commands/native/coupon/activity/get/schema.json +624 -0
  139. package/src/commands/native/coupon/activity/list/command.js +169 -0
  140. package/src/commands/native/coupon/activity/list/schema.json +845 -0
  141. package/src/commands/native/coupon/commands.index.json +42 -0
  142. package/src/commands/native/coupon/domain.json +3 -0
  143. package/src/commands/native/coupon/shared/query.js +15 -0
  144. package/src/commands/native/coupon/voucher/get/command.js +113 -0
  145. package/src/commands/native/coupon/voucher/get/schema.json +147 -0
  146. package/src/commands/native/coupon/voucher/list/command.js +155 -0
  147. package/src/commands/native/coupon/voucher/list/schema.json +772 -0
  148. package/src/commands/native/customer/commands.index.json +96 -0
  149. package/src/commands/native/customer/customer/get/adapter.js +82 -0
  150. package/src/commands/native/customer/customer/get/command.js +106 -0
  151. package/src/commands/native/customer/customer/get/schema.json +958 -0
  152. package/src/commands/native/customer/customer/list/command.js +78 -0
  153. package/src/commands/native/customer/customer/list/input.js +145 -0
  154. package/src/commands/native/customer/customer/list/query.js +103 -0
  155. package/src/commands/native/customer/customer/list/schema.json +969 -0
  156. package/src/commands/native/customer/customer/scan/command.js +80 -0
  157. package/src/commands/native/customer/customer/scan/scan.js +92 -0
  158. package/src/commands/native/customer/customer/scan/schema.json +211 -0
  159. package/src/commands/native/customer/customer-tag/get/command.js +166 -0
  160. package/src/commands/native/customer/customer-tag/get/schema.json +317 -0
  161. package/src/commands/native/customer/customer-tag/list/command.js +143 -0
  162. package/src/commands/native/customer/customer-tag/list/schema.json +259 -0
  163. package/src/commands/native/customer/domain.json +3 -0
  164. package/src/commands/native/customer/segment/list/command.js +96 -0
  165. package/src/commands/native/customer/segment/list/query.js +98 -0
  166. package/src/commands/native/customer/segment/list/schema.json +135 -0
  167. package/src/commands/native/customer/segment-customer/list/command.js +171 -0
  168. package/src/commands/native/customer/segment-customer/list/schema.json +123 -0
  169. package/src/commands/native/customer/shared/search-input.js +179 -0
  170. package/src/commands/native/customer/shared/search-page.js +54 -0
  171. package/src/commands/native/customer/tag/get/command.js +73 -0
  172. package/src/commands/native/customer/tag/get/schema.json +339 -0
  173. package/src/commands/native/customer/tagcategory/get/command.js +80 -0
  174. package/src/commands/native/customer/tagcategory/get/query.js +98 -0
  175. package/src/commands/native/customer/tagcategory/get/schema.json +339 -0
  176. package/src/commands/native/customer/tagcategory/list/command.js +127 -0
  177. package/src/commands/native/customer/tagcategory/list/schema.json +394 -0
  178. package/src/commands/native/fulfillment/commands.index.json +33 -0
  179. package/src/commands/native/fulfillment/delivery/get/command.js +107 -0
  180. package/src/commands/native/fulfillment/delivery/get/projection.js +142 -0
  181. package/src/commands/native/fulfillment/delivery/get/schema.json +173 -0
  182. package/src/commands/native/fulfillment/domain.json +3 -0
  183. package/src/commands/native/fulfillment/shipment/list/command.js +83 -0
  184. package/src/commands/native/fulfillment/shipment/list/projection.js +130 -0
  185. package/src/commands/native/fulfillment/shipment/list/schema.json +752 -0
  186. package/src/commands/native/fulfillment/waybill/get/command.js +193 -0
  187. package/src/commands/native/fulfillment/waybill/get/response.js +68 -0
  188. package/src/commands/native/fulfillment/waybill/get/schema.json +190 -0
  189. package/src/commands/native/interaction/commands.index.json +24 -0
  190. package/src/commands/native/interaction/domain.json +3 -0
  191. package/src/commands/native/interaction/lottery/get/command.js +61 -0
  192. package/src/commands/native/interaction/lottery/get/query.js +152 -0
  193. package/src/commands/native/interaction/lottery/get/schema.json +1004 -0
  194. package/src/commands/native/interaction/lottery/list/command.js +176 -0
  195. package/src/commands/native/interaction/lottery/list/schema.json +898 -0
  196. package/src/commands/native/item/attribute/list/command.js +122 -0
  197. package/src/commands/native/item/attribute/list/schema.json +727 -0
  198. package/src/commands/native/item/brand/list/command.js +114 -0
  199. package/src/commands/native/item/brand/list/schema.json +725 -0
  200. package/src/commands/native/item/classification/get/command.js +87 -0
  201. package/src/commands/native/item/classification/get/schema.json +596 -0
  202. package/src/commands/native/item/classification/list/command.js +105 -0
  203. package/src/commands/native/item/classification/list/schema.json +676 -0
  204. package/src/commands/native/item/commands.index.json +87 -0
  205. package/src/commands/native/item/domain.json +1 -0
  206. package/src/commands/native/item/group/list/command.js +122 -0
  207. package/src/commands/native/item/group/list/schema.json +809 -0
  208. package/src/commands/native/item/item/get/command.js +122 -0
  209. package/src/commands/native/item/item/get/schema.json +3799 -0
  210. package/src/commands/native/item/item/list/command.js +7 -0
  211. package/src/commands/native/item/item/list/schema.json +1118 -0
  212. package/src/commands/native/item/item/scan/command.js +7 -0
  213. package/src/commands/native/item/item/scan/schema.json +1046 -0
  214. package/src/commands/native/item/item-content/get/command.js +54 -0
  215. package/src/commands/native/item/item-content/get/schema.json +677 -0
  216. package/src/commands/native/item/shared/api.js +31 -0
  217. package/src/commands/native/item/shared/content.js +20 -0
  218. package/src/commands/native/item/shared/diagnostics.js +61 -0
  219. package/src/commands/native/item/shared/h5.js +63 -0
  220. package/src/commands/native/item/shared/identity.js +62 -0
  221. package/src/commands/native/item/shared/normalize.js +49 -0
  222. package/src/commands/native/item/shared/scope.js +22 -0
  223. package/src/commands/native/item/shared/search-command.js +61 -0
  224. package/src/commands/native/item/shared/search-options.js +150 -0
  225. package/src/commands/native/item/shared/search.js +158 -0
  226. package/src/commands/native/member/commands.index.json +60 -0
  227. package/src/commands/native/member/customer-level/get/command.js +122 -0
  228. package/src/commands/native/member/customer-level/get/schema.json +300 -0
  229. package/src/commands/native/member/domain.json +3 -0
  230. package/src/commands/native/member/growth/get/command.js +64 -0
  231. package/src/commands/native/member/growth/get/schema.json +283 -0
  232. package/src/commands/native/member/growth-log/list/command.js +203 -0
  233. package/src/commands/native/member/growth-log/list/schema.json +695 -0
  234. package/src/commands/native/member/level/get/command.js +70 -0
  235. package/src/commands/native/member/level/get/query.js +125 -0
  236. package/src/commands/native/member/level/get/schema.json +339 -0
  237. package/src/commands/native/member/level/list/command.js +50 -0
  238. package/src/commands/native/member/level/list/query.js +109 -0
  239. package/src/commands/native/member/level/list/schema.json +104 -0
  240. package/src/commands/native/member/membership/get/command.js +78 -0
  241. package/src/commands/native/member/membership/get/schema.json +283 -0
  242. package/src/commands/native/order/commands.index.json +33 -0
  243. package/src/commands/native/order/domain.json +3 -0
  244. package/src/commands/native/order/order/get/command.js +155 -0
  245. package/src/commands/native/order/order/get/schema.json +1167 -0
  246. package/src/commands/native/order/order/list/command.js +230 -0
  247. package/src/commands/native/order/order/list/schema.json +1363 -0
  248. package/src/commands/native/order/order/scan/command.js +148 -0
  249. package/src/commands/native/order/order/scan/scan.js +89 -0
  250. package/src/commands/native/order/order/scan/schema.json +1445 -0
  251. package/src/commands/native/order/shared/projection.js +183 -0
  252. package/src/commands/native/order/shared/query.js +84 -0
  253. package/src/commands/native/order/shared/search.js +112 -0
  254. package/src/commands/native/org/commands.index.json +42 -0
  255. package/src/commands/native/org/domain.json +3 -0
  256. package/src/commands/native/org/shared/single-staff.js +115 -0
  257. package/src/commands/native/org/staff/get/command.js +148 -0
  258. package/src/commands/native/org/staff/get/schema.json +114 -0
  259. package/src/commands/native/org/staff-role/get/command.js +45 -0
  260. package/src/commands/native/org/staff-role/get/schema.json +93 -0
  261. package/src/commands/native/org/unit/get/command.js +131 -0
  262. package/src/commands/native/org/unit/get/schema.json +478 -0
  263. package/src/commands/native/org/unit/list/command.js +187 -0
  264. package/src/commands/native/org/unit/list/schema.json +828 -0
  265. package/src/commands/native/points/account/get/command.js +65 -0
  266. package/src/commands/native/points/account/get/schema.json +303 -0
  267. package/src/commands/native/points/commands.index.json +33 -0
  268. package/src/commands/native/points/domain.json +3 -0
  269. package/src/commands/native/points/log/list/command.js +141 -0
  270. package/src/commands/native/points/log/list/schema.json +761 -0
  271. package/src/commands/native/points/rule/list/command.js +82 -0
  272. package/src/commands/native/points/rule/list/schema.json +294 -0
  273. package/src/commands/native/privacy/commands.index.json +15 -0
  274. package/src/commands/native/privacy/domain.json +3 -0
  275. package/src/commands/native/privacy/field/decrypt/command.js +185 -0
  276. package/src/commands/native/privacy/field/decrypt/schema.json +656 -0
  277. package/src/commands/native/privacy/shared/order-source.js +33 -0
  278. package/src/commands/native/stock/commands.index.json +15 -0
  279. package/src/commands/native/stock/domain.json +3 -0
  280. package/src/commands/native/stock/log/list/command.js +207 -0
  281. package/src/commands/native/stock/log/list/schema.json +922 -0
  282. package/src/commands/native/valuecard/card/get/command.js +107 -0
  283. package/src/commands/native/valuecard/card/get/schema.json +683 -0
  284. package/src/commands/native/valuecard/card/list/command.js +136 -0
  285. package/src/commands/native/valuecard/card/list/pagination.js +23 -0
  286. package/src/commands/native/valuecard/card/list/schema.json +780 -0
  287. package/src/commands/native/valuecard/commands.index.json +24 -0
  288. package/src/commands/native/valuecard/domain.json +3 -0
  289. package/src/commands/native/valuecard/shared/projection.js +57 -0
  290. package/src/commands/system/api.js +47 -0
  291. package/src/commands/system/auth.js +118 -0
  292. package/src/commands/system/contracts.js +373 -0
  293. package/src/commands/system/doctor.js +24 -0
  294. package/src/commands/system/install.js +41 -0
  295. package/src/commands/system/printer.js +16 -0
  296. package/src/commands/system/schema.js +162 -0
  297. package/src/commands/system/shop-guidance.js +9 -0
  298. package/src/commands/system/shop.js +237 -0
  299. package/src/commands/system/skills.js +49 -0
  300. package/src/execution/beijing-date-time.js +29 -0
  301. package/src/execution/beijing-time.js +21 -0
  302. package/src/execution/bounded-input.js +42 -0
  303. package/src/execution/command-io.js +137 -0
  304. package/src/execution/command-policy.js +41 -0
  305. package/src/execution/command-schema.js +131 -0
  306. package/src/execution/datetime.js +83 -0
  307. package/src/execution/error-details.js +399 -0
  308. package/src/execution/error-model.js +82 -0
  309. package/src/execution/exact-json.js +80 -0
  310. package/src/execution/list-total.js +10 -0
  311. package/src/execution/money.js +59 -0
  312. package/src/execution/parser-error.js +66 -0
  313. package/src/execution/privacy.js +197 -0
  314. package/src/execution/public-schema.js +52 -0
  315. package/src/execution/query-api.js +101 -0
  316. package/src/execution/range.js +84 -0
  317. package/src/execution/request-state.js +55 -0
  318. package/src/execution/schema-completeness.js +116 -0
  319. package/src/execution/shop-query.js +54 -0
  320. package/src/execution/target-shop-default.js +23 -0
  321. package/src/execution/target-shop.js +49 -0
  322. package/src/identity/context-store.js +54 -0
  323. package/src/identity/context.js +38 -0
  324. package/src/installation/install.js +158 -0
  325. package/src/installation/npm-error.js +93 -0
  326. package/src/installation/skill.js +113 -0
  327. package/src/transport/account-api.js +152 -0
  328. package/src/transport/api.js +199 -0
  329. package/src/transport/shop-app.js +63 -0
@@ -0,0 +1,259 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "input": {
4
+ "type": "object",
5
+ "required": [
6
+ "kdtId",
7
+ "yzOpenId"
8
+ ],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "kdtId": {
12
+ "$ref": "#/definitions/shopId"
13
+ },
14
+ "yzOpenId": {
15
+ "$ref": "#/definitions/customerId"
16
+ }
17
+ },
18
+ "description": "CLI 解析参数并完成必要上下文补全后的业务输入;不是直接传入 CLI 的 JSON。原始选项、必填条件和默认值见 options。"
19
+ },
20
+ "output": {
21
+ "type": "object",
22
+ "required": [
23
+ "data"
24
+ ],
25
+ "additionalProperties": false,
26
+ "properties": {
27
+ "data": {
28
+ "type": "object",
29
+ "required": [
30
+ "yzOpenId",
31
+ "tags"
32
+ ],
33
+ "additionalProperties": false,
34
+ "properties": {
35
+ "yzOpenId": {
36
+ "$ref": "#/definitions/customerId"
37
+ },
38
+ "tags": {
39
+ "type": "array",
40
+ "description": "本次响应的客户标签关系集合;明确空数组有效,不保证独立快照或服务端可见范围之外的完整性。",
41
+ "items": {
42
+ "type": "object",
43
+ "required": [
44
+ "tagId",
45
+ "tagName",
46
+ "tagCategoryId"
47
+ ],
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "tagId": {
51
+ "type": "integer",
52
+ "minimum": 1,
53
+ "maximum": 9007199254740991,
54
+ "description": "标签定义 ID,不接受有损整数。"
55
+ },
56
+ "tagName": {
57
+ "type": "string",
58
+ "description": "标签名称。"
59
+ },
60
+ "tagCategoryId": {
61
+ "type": "integer",
62
+ "minimum": 0,
63
+ "maximum": 9007199254740991,
64
+ "description": "标签组 ID,0 表示未分组。"
65
+ },
66
+ "tagCategoryName": {
67
+ "type": "string",
68
+ "description": "标签组名称,未取得或为 null 时省略,空字符串保留。"
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ },
77
+ "preview": {
78
+ "type": "object",
79
+ "required": [
80
+ "method",
81
+ "path",
82
+ "body"
83
+ ],
84
+ "additionalProperties": false,
85
+ "properties": {
86
+ "method": {
87
+ "const": "POST"
88
+ },
89
+ "path": {
90
+ "const": "youzan.scrm.tagrelation.query/1.0.0"
91
+ },
92
+ "body": {
93
+ "type": "object",
94
+ "required": [
95
+ "account",
96
+ "display_type",
97
+ "filter_invalid_tag",
98
+ "filter_category_tag"
99
+ ],
100
+ "additionalProperties": false,
101
+ "properties": {
102
+ "account": {
103
+ "type": "object",
104
+ "required": [
105
+ "account_id",
106
+ "account_type"
107
+ ],
108
+ "additionalProperties": false,
109
+ "properties": {
110
+ "account_id": {
111
+ "$ref": "#/definitions/customerId"
112
+ },
113
+ "account_type": {
114
+ "const": 5
115
+ }
116
+ }
117
+ },
118
+ "display_type": {
119
+ "const": 2
120
+ },
121
+ "filter_invalid_tag": {
122
+ "const": false
123
+ },
124
+ "filter_category_tag": {
125
+ "const": false
126
+ }
127
+ }
128
+ }
129
+ }
130
+ },
131
+ "error": {
132
+ "type": "object",
133
+ "required": [
134
+ "success",
135
+ "code",
136
+ "message"
137
+ ],
138
+ "additionalProperties": false,
139
+ "properties": {
140
+ "success": {
141
+ "const": false
142
+ },
143
+ "code": {
144
+ "const": -10001
145
+ },
146
+ "message": {
147
+ "type": "string",
148
+ "minLength": 1
149
+ },
150
+ "details": {
151
+ "type": "object",
152
+ "required": [
153
+ "category",
154
+ "stage",
155
+ "command",
156
+ "targetScope",
157
+ "requestState",
158
+ "nextStep"
159
+ ],
160
+ "additionalProperties": false,
161
+ "properties": {
162
+ "category": {
163
+ "enum": [
164
+ "input",
165
+ "configuration",
166
+ "authentication",
167
+ "permission",
168
+ "http",
169
+ "business_rejected",
170
+ "transport",
171
+ "protocol"
172
+ ]
173
+ },
174
+ "stage": {
175
+ "enum": [
176
+ "arguments",
177
+ "kdtId",
178
+ "yzOpenId",
179
+ "format",
180
+ "context",
181
+ "configuration",
182
+ "request",
183
+ "response"
184
+ ]
185
+ },
186
+ "command": {
187
+ "const": "customer.customer-tag.list"
188
+ },
189
+ "targetScope": {
190
+ "type": "object",
191
+ "additionalProperties": false,
192
+ "description": "失败诊断不回显客户标识或自由文本。"
193
+ },
194
+ "requestState": {
195
+ "enum": [
196
+ "not_sent",
197
+ "sent",
198
+ "unknown"
199
+ ]
200
+ },
201
+ "nextStep": {
202
+ "type": "string",
203
+ "minLength": 1
204
+ },
205
+ "api": {
206
+ "const": "youzan.scrm.tagrelation.query/1.0.0"
207
+ },
208
+ "httpStatus": {
209
+ "type": "integer",
210
+ "minimum": 100,
211
+ "maximum": 599
212
+ },
213
+ "businessCode": {
214
+ "type": "integer",
215
+ "minimum": -9007199254740991,
216
+ "maximum": 9007199254740991
217
+ },
218
+ "gatewayCode": {
219
+ "anyOf": [{ "type": "integer" }, { "type": "string", "pattern": "^-?\\d{1,12}$" }]
220
+ },
221
+ "trace_id": {
222
+ "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,128}$"
223
+ }
224
+ }
225
+ }
226
+ }
227
+ },
228
+ "definitions": {
229
+ "shopId": {
230
+ "type": "integer",
231
+ "minimum": 1,
232
+ "maximum": 9007199254740991,
233
+ "description": "显式目标店铺 ID;本地上下文准入不能替代服务端授权。"
234
+ },
235
+ "customerId": {
236
+ "type": "string",
237
+ "minLength": 1,
238
+ "description": "首尾空白处理后的 yzOpenId;响应必须完全匹配该值。"
239
+ }
240
+ },
241
+ "api": {
242
+ "method": "POST",
243
+ "path": "youzan.scrm.tagrelation.query/1.0.0"
244
+ },
245
+ "success": {
246
+ "description": "客户 ID 精确匹配且标签集合明确取得,每项满足模型后成功。"
247
+ },
248
+ "notes": [
249
+ "--kdt-id 省略时使用本次有效上下文 shopId;显式提供的非法值不回退。两者都缺失时拒绝;目标范围、同店核验和服务端权限仍按本命令校验。",
250
+ "保留既有 list 契约,返回 data.yzOpenId 和 data.tags;新调用获取一个客户的标签集合推荐 customer-tag get,不互为别名或失败降级入口。",
251
+ "不分页、不截断标签集合,不承诺快照;缺核心字段或不安全整数失败。",
252
+ "分类名称未取得或为 null 时省略,空字符串保留;标签组 ID 为 0 表示未分组。",
253
+ "真实调用前须独立确认凭证与目标店铺绑定;本地上下文、客户匹配和本地模拟不证明远端授权或编码已验收。",
254
+ "本地 --dry-run 不读取凭证、不联网;预览只证明构造计划,不证明对象存在或权限有效。真实执行仍需有效上下文及目标范围授权,at 声明不替代服务端授权。"
255
+ ],
256
+ "errors": {
257
+ "description": "失败 stdout 为空,stderr 为一份脱敏错误 JSON,退出码非零;不返回部分成功,不自动重试、切换身份或目标。按 error 模型及安全下一步处理。"
258
+ }
259
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "description": "客户:档案、行为、标签与分群"
3
+ }
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const { withTargetShopDefault } = require('../../../../../execution/target-shop-default');
4
+
5
+ const { Command, Option } = require('commander');
6
+ const { resolveTargetShop } = require('../../../../../execution/target-shop');
7
+ const { validateCommandValue } = require('../../../../../execution/command-schema');
8
+ const { reject, readPage, serialize, bindingPath } = require('./query');
9
+ const schema = require('./schema.json');
10
+
11
+ function buildInput(options, context) {
12
+ let target;
13
+ try { target = resolveTargetShop(options, context, 'customer.segment.list'); }
14
+ catch (error) {
15
+ const { category, stage, targetScope } = error.cliDetails;
16
+ const scope = targetScope.kdtId ? { kdtId: String(targetScope.kdtId) } : {};
17
+ throw reject(category, ['scope', 'validation'].includes(stage) ? 'input' : stage, scope);
18
+ }
19
+ const input = { kdtId: String(target.kdtId) };
20
+ for (const [name, fallback, maximum] of [['pageNo', '1', 10000], ['pageSize', '20', 100]]) {
21
+ const value = options[name] === undefined ? fallback : options[name];
22
+ if (typeof value !== 'string' || !/^[1-9]\d*$/.test(value) || Number(value) > maximum) {
23
+ throw reject('validation', 'input');
24
+ }
25
+ input[name] = Number(value);
26
+ }
27
+ if (Object.hasOwn(options, 'keyword')) {
28
+ if (typeof options.keyword !== 'string') throw reject('validation', 'input');
29
+ input.keyword = options.keyword.trim();
30
+ if (!input.keyword || Array.from(input.keyword).length > 200) throw reject('validation', 'input');
31
+ }
32
+ if (options.format !== undefined && !['json', 'pretty'].includes(options.format)) throw reject('validation', 'input');
33
+ try { validateCommandValue(schema, 'input', input); }
34
+ catch { throw reject('validation', 'input'); }
35
+ return input;
36
+ }
37
+
38
+ function requestBody(input, redact = false) {
39
+ const request = { page_no: input.pageNo, page_size: input.pageSize };
40
+ if (Object.hasOwn(input, 'keyword')) request.keyword = redact ? '***' : input.keyword;
41
+ return { request: JSON.stringify(request) };
42
+ }
43
+
44
+ function preview(input) {
45
+ const plan = { requests: [
46
+ { method: 'POST', path: bindingPath, body: {} },
47
+ { method: 'POST', path: schema.api.path, body: requestBody(input, true) }
48
+ ] };
49
+ validateCommandValue(schema, 'preview', plan);
50
+ return plan;
51
+ }
52
+
53
+ function createCommand({ context } = {}) {
54
+ const seen = new Set();
55
+ const command = new Command('list')
56
+ .description('读取一页已保存分群目录,以稳定 segmentId 发现分群,不查询成员或规则')
57
+ .allowExcessArguments(false)
58
+ .exitOverride(error => {
59
+ if (['commander.helpDisplayed', 'commander.version'].includes(error.code)) throw error;
60
+ throw reject('validation', 'input');
61
+ })
62
+ .option('--kdt-id <id>', '目标店铺正安全整数 ID 文本;默认本次有效 context.shopId,非法显式值不回退')
63
+ .option('--keyword <text>', '分群名称关键词,去首尾空白后 1..200 字符,不保证精确匹配')
64
+ .option('--page-no <n>', '本次页码 1..10000,默认 1,不自动翻页', '1')
65
+ .option('--page-size <n>', '本页容量 1..100,默认 20,不是总数', '20')
66
+ .addOption(new Option('--format <format>', 'json 或 pretty,仅改变排版').choices(['json', 'pretty']).default('json'))
67
+ .option('--dry-run', '纯本地零认证零请求预览,keyword 遮盖为 ***')
68
+ .addHelpText('after', `
69
+ 同店核验后只读一页,最多两次业务请求;每次10秒,不重试、切店、换身份或读取详情。
70
+ 执行需要四字段上下文。非总部目标须等于shopId,总部仍需同店核验及服务端授权。
71
+ 仅缺少上下文时可显式合法目标预览;无效或冲突上下文即使预览也拒绝。
72
+ 分群定义与规则形成动态成员,目录customerCount只是本次报告人数,不是成员快照。
73
+ segmentId是正Long十进制字符串,名称不唯一;不返回未核实的日期、描述或version。
74
+ 未取得总数时省略total,hasMore为null,空页和短页不证明取完;第10000页仍有更多时hasMore为null。
75
+ 固定data.segments与四字段pagination;响应累计10MiB,含换行输出5MiB,超限整体失败。
76
+ 不提供扫描、排序、include、成员、规则、timeout或retry。分群详情及成员查询当前没有入口。
77
+ 错误stdout为空,stderr为脱敏JSON。预览和绑定不证明店铺员工权限。
78
+ 完整契约:zan-saas schema customer.segment.list
79
+ 示例:zan-saas customer segment list --keyword '首购' --page-size 20
80
+ 预览:zan-saas customer segment list --kdt-id 63077 --keyword '首购' --dry-run
81
+ `)
82
+ .action(async options => {
83
+ const input = buildInput(options, context);
84
+ const result = options.dryRun ? preview(input) : await readPage(input, requestBody(input));
85
+ console.log(serialize(result, options.format, { kdtId: input.kdtId }, options.dryRun ? 'not_sent' : 'sent'));
86
+ });
87
+ for (const option of command.options) {
88
+ command.on(`option:${option.name()}`, () => {
89
+ if (seen.has(option.name())) throw reject('validation', 'input');
90
+ seen.add(option.name());
91
+ });
92
+ }
93
+ return command;
94
+ }
95
+
96
+ module.exports = { kind: 'atomic', risk: 'read', at: 'all', createCommand: withTargetShopDefault(createCommand), buildInput, requestBody, preview };
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+
3
+ const { readTotal } = require('../../../../../execution/list-total');
4
+
5
+ const { createBoundShopQuery, bindingPath } = require('../../../../../execution/shop-query');
6
+ const { QueryError, object } = require('../../../../../execution/query-api');
7
+ const { parseExactJson } = require('../../../../../execution/exact-json');
8
+ const { validateCommandValue } = require('../../../../../execution/command-schema');
9
+ const schema = require('./schema.json');
10
+
11
+ const RESPONSE_LIMIT = 10 * 1024 * 1024;
12
+ const OUTPUT_LIMIT = 5 * 1024 * 1024;
13
+ const LONG_MAX = 9223372036854775807n;
14
+
15
+ function reject(category, stage, scope = {}, state = 'not_sent', facts = {}) {
16
+ return new QueryError(category, stage, scope, facts, state, 'customer.segment.list',
17
+ '核对原店铺、分页、字段来源与服务端授权;失败不返回部分目录,不自动换店、换身份或重放请求。');
18
+ }
19
+
20
+ function adaptError(error, scope) {
21
+ if (!error.cliDetails) return reject('configuration', 'configuration', scope);
22
+ const { category, stage, requestState, ...details } = error.cliDetails;
23
+ const facts = {};
24
+ for (const name of ['api', 'httpStatus', 'businessCode', 'gatewayCode', 'trace_id', 'request_id']) {
25
+ if (details[name] !== undefined) facts[name] = details[name];
26
+ }
27
+ return reject(category, stage, scope, requestState, facts);
28
+ }
29
+
30
+ async function readPage(input, body, responseLimit = RESPONSE_LIMIT) {
31
+ const scope = { kdtId: input.kdtId };
32
+ let responseBytes = 0;
33
+ let response;
34
+ try {
35
+ const query = await createBoundShopQuery({ kdtId: Number(input.kdtId) }, 'customer.segment.list', 'shop-binding', {
36
+ onResponse: result => { responseBytes += result.responseBytes; },
37
+ transportOptions: { maxResponseBytes: () => responseLimit - responseBytes, shopApp: false }
38
+ });
39
+ response = await query.read(schema.api.path, body, 'list');
40
+ } catch (error) { throw adaptError(error, scope); }
41
+ try {
42
+ const result = parseExactJson(response.rawBody, token => {
43
+ if (!/^-?(?:0|[1-9]\d*)$/.test(token)) return NaN;
44
+ const integer = BigInt(token);
45
+ return integer >= BigInt(Number.MIN_SAFE_INTEGER) && integer <= BigInt(Number.MAX_SAFE_INTEGER) ?
46
+ Number(integer) : integer;
47
+ });
48
+ return adapt(result.data, input, response.facts);
49
+ } catch { throw reject('protocol', 'output', scope, 'sent', response.facts); }
50
+ }
51
+
52
+ function segment(source) {
53
+ if (!object(source)) throw new Error('segment');
54
+ const value = source.crowd_id;
55
+ if (!(typeof value === 'bigint' || typeof value === 'string' || Number.isSafeInteger(value))) throw new Error('id');
56
+ const segmentId = String(value);
57
+ if (!/^[1-9]\d{0,18}$/.test(segmentId) || BigInt(segmentId) > LONG_MAX) throw new Error('id');
58
+ const result = { segmentId, name: source.crowd_name };
59
+ for (const [name, field] of Object.entries({ customerCount: 'customer_num', type: 'crowd_type', editorMode: 'editor_mode' })) {
60
+ if (Object.hasOwn(source, field)) result[name] = source[field];
61
+ }
62
+ return result;
63
+ }
64
+
65
+ function adapt(data, input, facts = {}) {
66
+ try {
67
+ if (!object(data) || !Array.isArray(data.items) || data.items.length > input.pageSize || !object(data.paginator)) {
68
+ throw new Error('page');
69
+ }
70
+ const page = data.paginator;
71
+ if (page.page !== input.pageNo || page.page_size !== input.pageSize) throw new Error('pagination');
72
+ const total = readTotal(page, 'total_count');
73
+ if (total !== null && total > 2147483647) {
74
+ throw new Error('total');
75
+ }
76
+ const count = data.items.length;
77
+ const offset = (input.pageNo - 1) * input.pageSize;
78
+ if (total !== null && (count > 0 ? total < offset + count : total > offset)) throw new Error('contradiction');
79
+ const segments = data.items.map(segment);
80
+ if (new Set(segments.map(row => row.segmentId)).size !== segments.length) throw new Error('duplicate');
81
+ const hasMore = total === null ? null : total <= input.pageNo * input.pageSize ? false : input.pageNo < 10000 ? true : null;
82
+ const output = { data: { segments, pagination: { pageNo: page.page, pageSize: page.page_size,
83
+ ...(total === null ? {} : { total }), hasMore } } };
84
+ validateCommandValue(schema, 'output', output);
85
+ for (const row of segments) {
86
+ if (Object.hasOwn(row, 'customerCount') && !Number.isSafeInteger(row.customerCount)) throw new Error('count');
87
+ }
88
+ return output;
89
+ } catch { throw reject('protocol', 'output', { kdtId: input.kdtId }, 'sent', facts); }
90
+ }
91
+
92
+ function serialize(output, format, scope, state = 'sent', limit = OUTPUT_LIMIT) {
93
+ const text = JSON.stringify(output, null, format === 'pretty' ? 2 : 0);
94
+ if (Buffer.byteLength(`${text}\n`, 'utf8') > limit) throw reject('limit', 'output', scope, state);
95
+ return text;
96
+ }
97
+
98
+ module.exports = { readPage, adapt, serialize, reject, bindingPath, RESPONSE_LIMIT, OUTPUT_LIMIT };
@@ -0,0 +1,135 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "input": {
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": ["kdtId", "pageNo", "pageSize"],
7
+ "description": "规范化业务输入,不是接收 JSON 的参数。目标默认有效上下文店铺,格式与预览控制不进入此模型。",
8
+ "properties": {
9
+ "kdtId": { "$ref": "#/definitions/shopId" },
10
+ "keyword": {
11
+ "type": "string", "minLength": 1, "maxLength": 200,
12
+ "pattern": "^\\S(?:[\\s\\S]*\\S)?$",
13
+ "description": "可选的分群名称关键词,去首尾空白后非空,最多200字符;按原生检索,不承诺分词或精确匹配。"
14
+ },
15
+ "pageNo": { "type": "integer", "minimum": 1, "maximum": 10000, "description": "本次页码,默认1,上限10000是CLI预算。" },
16
+ "pageSize": { "type": "integer", "minimum": 1, "maximum": 100, "description": "本页容量,默认20,上限100是CLI预算,不是总数。" }
17
+ }
18
+ },
19
+ "output": {
20
+ "type": "object", "additionalProperties": false, "required": ["data"],
21
+ "description": "同店核验后一页分群目录的有限视图,全部校验通过才输出。",
22
+ "properties": {
23
+ "data": {
24
+ "type": "object", "additionalProperties": false, "required": ["segments", "pagination"],
25
+ "description": "本次范围内的目录和分页,不含成员、逐群规则或完整快照。",
26
+ "properties": {
27
+ "segments": {
28
+ "type": "array", "maxItems": 100, "description": "本页分群,数量不超过pageSize,保留源顺序和同名记录;空数组仅表示本次没有返回条目。",
29
+ "items": {
30
+ "type": "object", "additionalProperties": false, "required": ["segmentId", "name"],
31
+ "description": "以稳定ID引用的已保存分群;可选字段缺省省略,返回null或错型整体失败。",
32
+ "properties": {
33
+ "segmentId": { "type": "string", "pattern": "^[1-9]\\d{0,18}$", "description": "分群正Long十进制字符串,1..9223372036854775807,无损保留,同页不允许重复;不是客户ID。" },
34
+ "name": { "type": "string", "description": "分群名称,合法空串保留,可以重名,名称不证明规则正确。" },
35
+ "customerCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991, "description": "可选的本次报告客户数,0保留,不是实时成员快照或历史名单。" },
36
+ "type": { "type": "string", "minLength": 1, "description": "可选分群类型代码。string \"0\"=自定义人群,string \"4\"=系统推荐;未来非空string原样保留,不自动转换number或按类型隐藏记录。" },
37
+ "editorMode": { "type": "string", "minLength": 1, "description": "可选规则编辑器表现模式。string \"simple_version\"=简单编辑器模式,string \"advance_version\"=高级编辑器模式;未来非空string原样保留,不推定规则版本或引擎。" }
38
+ }
39
+ }
40
+ },
41
+ "pagination": {
42
+ "type": "object", "additionalProperties": false, "required": ["pageNo", "pageSize", "hasMore"],
43
+ "description": "本次响应分页,不补造缺失的源页码或容量;不承诺跨页排序或快照。",
44
+ "properties": {
45
+ "pageNo": { "type": "integer", "minimum": 1, "maximum": 10000, "description": "响应页码,必须与本次输入一致。" },
46
+ "pageSize": { "type": "integer", "minimum": 1, "maximum": 100, "description": "响应页容量,必须与本次输入一致。" },
47
+ "total": { "type": "integer", "minimum": 0, "maximum": 2147483647, "description": "匹配本次查询条件的总记录数,不是当前页返回条数;上游未提供可确认总数时省略。" },
48
+ "hasMore": { "type": ["boolean", "null"], "description": "true 表示还有后续页,false 表示已确认没有后续页;无法确定时为 null,不以空页或短页推算。" }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ },
55
+ "preview": {
56
+ "type": "object", "additionalProperties": false, "required": ["requests"],
57
+ "description": "纯本地两请求计划,不读取凭证或认证,不证明权限、对象或总数。关键词遮盖为***。",
58
+ "properties": {
59
+ "requests": {
60
+ "type": "array", "minItems": 2, "maxItems": 2, "additionalItems": false,
61
+ "description": "固定先绑定店铺、再读一页目录,主请求的request为JSON文本。",
62
+ "items": [
63
+ {
64
+ "type": "object", "additionalProperties": false, "required": ["method", "path", "body"],
65
+ "properties": {
66
+ "method": { "const": "POST", "description": "计划请求方法。" },
67
+ "path": { "const": "youzan.shop.basic.get/3.0.0", "description": "计划店铺核验路径。" },
68
+ "body": { "type": "object", "additionalProperties": false, "maxProperties": 0, "description": "空店铺核验请求。" }
69
+ }
70
+ },
71
+ {
72
+ "type": "object", "additionalProperties": false, "required": ["method", "path", "body"],
73
+ "properties": {
74
+ "method": { "const": "POST", "description": "计划请求方法。" },
75
+ "path": { "const": "youzan.crm.crowd.list/1.0.0", "description": "计划目录查询路径。" },
76
+ "body": {
77
+ "type": "object", "additionalProperties": false, "required": ["request"],
78
+ "description": "一页查询计划,无额外店铺字段。",
79
+ "properties": {
80
+ "request": { "type": "string", "description": "JSON对象文本,只含page_no、page_size和可选keyword;预览keyword固定***。" }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ ]
86
+ }
87
+ }
88
+ },
89
+ "error": {
90
+ "type": "object", "additionalProperties": false, "required": ["success", "code", "message", "details"],
91
+ "properties": {
92
+ "success": { "const": false },
93
+ "code": { "const": -10001 },
94
+ "message": { "type": "string", "minLength": 1, "description": "受控错误,不回显关键词、凭证、自由消息或响应原文。" },
95
+ "details": {
96
+ "type": "object", "additionalProperties": false,
97
+ "required": ["category", "stage", "command", "targetScope", "requestState", "nextStep"],
98
+ "properties": {
99
+ "category": {
100
+ "enum": ["validation", "configuration", "authentication", "permission", "scope_unresolved", "http", "business_rejected", "transport", "protocol", "limit"],
101
+ "description": "validation输入错误;configuration配置不可用;authentication认证失败;permission权限拒绝;scope_unresolved店铺未确认;http请求拒绝;business_rejected业务拒绝;transport传输失败;protocol协议不符;limit超预算。"
102
+ },
103
+ "stage": { "enum": ["input", "context", "configuration", "shop-binding", "list", "output"], "description": "input本地输入;context上下文;configuration公共环境;shop-binding同店核验;list目录请求;output视图验证。" },
104
+ "command": { "const": "customer.segment.list" },
105
+ "targetScope": { "type": "object", "additionalProperties": false, "description": "已确认的本次目标店铺,尚未确定时为空,不含关键词。", "properties": { "kdtId": { "$ref": "#/definitions/shopId" } } },
106
+ "requestState": { "enum": ["not_sent", "sent", "unknown"], "description": "not_sent相关失败请求未发送;sent已收到响应但不代表业务成功;unknown发送后结果不明,不重放。" },
107
+ "nextStep": { "type": "string", "minLength": 1, "description": "保留原目标排查,不自动重试、切店或换身份。" },
108
+ "api": { "enum": ["youzan.shop.basic.get/3.0.0", "youzan.crm.crowd.list/1.0.0"] },
109
+ "httpStatus": { "type": "integer", "minimum": 100, "maximum": 599 },
110
+ "businessCode": { "$ref": "#/definitions/diagnosticCode" },
111
+ "gatewayCode": { "$ref": "#/definitions/diagnosticCode" },
112
+ "trace_id": { "$ref": "#/definitions/trace" },
113
+ "request_id": { "$ref": "#/definitions/trace" }
114
+ }
115
+ }
116
+ }
117
+ },
118
+ "definitions": {
119
+ "shopId": { "type": "string", "pattern": "^[1-9]\\d*$", "maxLength": 16, "description": "目标店铺正安全整数ID文本,1..9007199254740991;默认有效context.shopId,显式非法值不回退。" },
120
+ "diagnosticCode": { "anyOf": [{ "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, { "type": "string", "pattern": "^-?\\d{1,12}$" }], "description": "受限业务或网关代码,不包含自由消息。" },
121
+ "trace": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,128}$", "description": "受限请求追踪标识。" }
122
+ },
123
+ "api": { "method": "POST", "path": "youzan.crm.crowd.list/1.0.0" },
124
+ "success": { "description": "同店核验、一页目录、稳定ID及所选字段、分页和预算全部满足后,一次输出data,不返回部分成功。" },
125
+ "errors": { "description": "失败stdout为空,stderr为一份脱敏JSON,退出码非零。不重试、重定向、换店、换身份或降级到其他查询。" },
126
+ "notes": [
127
+ "分群是已保存的客户分群定义,规则形成动态成员;目录人数只是本次报告数,不代表成员快照或计算截止时间。名称不唯一,不能由名称推断规则正确。",
128
+ "目录读取不保证覆盖全店所有系统、推荐或其他产品分群;不隐藏返回的已知或未来类型。不提供规则、成员、扫描、排序或include。",
129
+ "真实执行需要userId、hq、shopId、orgType四字段上下文。非总部目标须匹配shopId,总部仍需同店核验和服务端授权。绑定和at声明不证明员工权限。",
130
+ "只有缺少上下文时可用显式合法目标本地预览;无效或冲突上下文即使预览也拒绝。关键词遮盖,预览不读取凭证或发认证请求。",
131
+ "最多两次业务请求,每次10秒,累计业务响应10MiB,最终UTF-8输出含换行5MiB。超限整体失败,不裁剪字段或目录。",
132
+ "仅读取本页。保留keyword和pageSize,显式递增合法pageNo可继续读取;总数未知时hasMore为null,第10000页不能继续。不保证跨页稳定排序、快照或无遗漏。",
133
+ "未核实的日期、描述、version不进入结果。当前没有分群详情、成员或写入命令,不能把目录当成员名单。"
134
+ ]
135
+ }