makea-cli 0.2.25__tar.gz → 0.2.26__tar.gz

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 (82) hide show
  1. {makea_cli-0.2.25 → makea_cli-0.2.26}/CHANGELOG.md +40 -0
  2. {makea_cli-0.2.25 → makea_cli-0.2.26}/PKG-INFO +22 -1
  3. {makea_cli-0.2.25 → makea_cli-0.2.26}/README.md +21 -0
  4. makea_cli-0.2.26/makea_cli/__init__.py +1 -0
  5. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/api_client.py +125 -0
  6. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/__init__.py +2 -0
  7. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/directory/cmd.py +14 -0
  8. makea_cli-0.2.26/makea_cli/commands/flags/cmd.py +157 -0
  9. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/orders/cmd.py +252 -0
  10. makea_cli-0.2.26/makea_cli/commands/product/cmd.py +449 -0
  11. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/supplier/cmd.py +150 -0
  12. makea_cli-0.2.26/makea_cli/commands/tasks/__init__.py +0 -0
  13. makea_cli-0.2.26/makea_cli/companion.py +278 -0
  14. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/main.py +64 -3
  15. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/output.py +9 -1
  16. {makea_cli-0.2.25 → makea_cli-0.2.26}/pyproject.toml +1 -1
  17. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/golden_manifest.json +1293 -20
  18. makea_cli-0.2.26/tests/test_companion.py +252 -0
  19. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_persona_commands.py +288 -0
  20. {makea_cli-0.2.25 → makea_cli-0.2.26}/uv.lock +1 -1
  21. makea_cli-0.2.25/makea_cli/__init__.py +0 -1
  22. makea_cli-0.2.25/makea_cli/commands/product/cmd.py +0 -203
  23. {makea_cli-0.2.25 → makea_cli-0.2.26}/.claude/skills/create-supplier-profile/SKILL.md +0 -0
  24. {makea_cli-0.2.25 → makea_cli-0.2.26}/.claude/skills/lark-cli-setup/SKILL.md +0 -0
  25. {makea_cli-0.2.25 → makea_cli-0.2.26}/.claude/skills/link-supplier-user/SKILL.md +0 -0
  26. {makea_cli-0.2.25 → makea_cli-0.2.26}/.claude/skills/makea-cli-setup/SKILL.md +0 -0
  27. {makea_cli-0.2.25 → makea_cli-0.2.26}/.claude/skills/payment-revenue-report/SKILL.md +0 -0
  28. {makea_cli-0.2.25 → makea_cli-0.2.26}/.claude/skills/supplier-user-id-migration/SKILL.md +0 -0
  29. {makea_cli-0.2.25 → makea_cli-0.2.26}/.gitignore +0 -0
  30. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea-collection-upload/SKILL.md +0 -0
  31. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea-collection-upload/scripts/create_products.py +0 -0
  32. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/__main__.py +0 -0
  33. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/auth_pkce.py +0 -0
  34. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/broker.py +0 -0
  35. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/_util.py +0 -0
  36. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/about/__init__.py +0 -0
  37. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/about/cmd.py +0 -0
  38. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/analytics/__init__.py +0 -0
  39. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/analytics/cmd.py +0 -0
  40. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/auth/__init__.py +0 -0
  41. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/auth/cmd.py +0 -0
  42. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/brand/__init__.py +0 -0
  43. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/brand/cmd.py +0 -0
  44. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/designer/__init__.py +0 -0
  45. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/designer/cmd.py +0 -0
  46. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/directory/__init__.py +0 -0
  47. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/document/__init__.py +0 -0
  48. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/document/cmd.py +0 -0
  49. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/email/__init__.py +0 -0
  50. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/email/cmd.py +0 -0
  51. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/factory/__init__.py +0 -0
  52. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/factory/cmd.py +0 -0
  53. {makea_cli-0.2.25/makea_cli/commands/library → makea_cli-0.2.26/makea_cli/commands/flags}/__init__.py +0 -0
  54. {makea_cli-0.2.25/makea_cli/commands/metrics → makea_cli-0.2.26/makea_cli/commands/library}/__init__.py +0 -0
  55. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/library/cmd.py +0 -0
  56. {makea_cli-0.2.25/makea_cli/commands/playbook → makea_cli-0.2.26/makea_cli/commands/metrics}/__init__.py +0 -0
  57. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/metrics/cmd.py +0 -0
  58. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/orders/__init__.py +0 -0
  59. {makea_cli-0.2.25/makea_cli/commands/shipping → makea_cli-0.2.26/makea_cli/commands/playbook}/__init__.py +0 -0
  60. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/playbook/cmd.py +0 -0
  61. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/product/__init__.py +0 -0
  62. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/production/__init__.py +0 -0
  63. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/production/cmd.py +0 -0
  64. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/production/pricing_spec.py +0 -0
  65. {makea_cli-0.2.25/makea_cli/commands/tasks → makea_cli-0.2.26/makea_cli/commands/shipping}/__init__.py +0 -0
  66. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/shipping/cmd.py +0 -0
  67. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/supplier/__init__.py +0 -0
  68. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/commands/tasks/cmd.py +0 -0
  69. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/config.py +0 -0
  70. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/errors.py +0 -0
  71. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/identity.py +0 -0
  72. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/posthog_client.py +0 -0
  73. {makea_cli-0.2.25 → makea_cli-0.2.26}/makea_cli/registry.py +0 -0
  74. {makea_cli-0.2.25 → makea_cli-0.2.26}/npm/makea-cli/README.md +0 -0
  75. {makea_cli-0.2.25 → makea_cli-0.2.26}/npm/makea-cli/makea-cli.mjs +0 -0
  76. {makea_cli-0.2.25 → makea_cli-0.2.26}/npm/makea-cli/package.json +0 -0
  77. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_broker.py +0 -0
  78. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_currency_conversion.py +0 -0
  79. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_output_contract.py +0 -0
  80. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_pm_reads.py +0 -0
  81. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_registry.py +0 -0
  82. {makea_cli-0.2.25 → makea_cli-0.2.26}/tests/test_supplier_scorecard.py +0 -0
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.26
4
+
5
+ The admin page is now the CLI's companion. Every `makea-cli admin …` result
6
+ carries `admin_url`, the admin page's link to the record (`--open` opens it in
7
+ the browser). After a successful command the CLI tells the admin tabs you have
8
+ open: they refresh and, with Follow on, open the record. Dry runs and failed
9
+ commands send nothing; `MAKEA_COMPANION=off` turns it off; `MAKEA_APP_URL`
10
+ points the links at another frontend. Works the same from Claude Code, Codex or
11
+ a shell; the page shows which one ran each command.
12
+
13
+ New: what Makea staff do by hand on the admin page, from the terminal. Every
14
+ endpoint is already live; nothing here moves money.
15
+
16
+ - Reads: `admin get production-order`, `admin get supplier`, `admin get user`,
17
+ `admin get product-status` (stage · step · owner per supplier),
18
+ `admin get product-step --supplier` (the steps a factory can be moved to),
19
+ `admin list product-note`, `admin list feature-flag`.
20
+ - `admin update sampling-order / production-order --status`: an order's status.
21
+ The paid statuses (PAID, DEPOSIT_PAID, FINAL_PAYMENT_PAID) are refused; a
22
+ payment records them.
23
+ - `admin set sampling-order-tracking / production-order-tracking`: tracking
24
+ number, URL, method, carrier (production also cartons and gross weight). Only
25
+ the flags given are sent. A new tracking number marks the order shipped and
26
+ tells the brand.
27
+ - `admin update product-step --supplier --stage --step [--note]
28
+ [--notify-brand] [--notify-supplier]`: Change step, for a move that happened
29
+ off the platform. The server refuses money steps.
30
+ - `admin update product`: name, category, launch date, contact, size count,
31
+ grading, custom notes.
32
+ - `admin update product-document --status APPROVED|REJECTED|UPLOADED`.
33
+ - `admin create product-note --content [--internal]`: without `--internal` the
34
+ brand reads it and is emailed.
35
+ - `admin create / delete supplier-link`: assign a factory to a product with no
36
+ price, or remove a link (`--link-id`, or `--supplier` for all of its links).
37
+ Removing a link that already has orders leaves them pointing at nothing.
38
+ - `admin create quote-request-note --text [--requirements-updated]`: write to
39
+ the factory on a quote request.
40
+ - `admin create / update / delete feature-flag`: add a flag, flip it, edit it,
41
+ add or remove one account (`--add-user` / `--remove-user`), remove it.
42
+
3
43
  ## 0.2.25
4
44
 
5
45
  New: `designer create proposal`, a tech-pack change as a card on the field it
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: makea-cli
3
- Version: 0.2.25
3
+ Version: 0.2.26
4
4
  Summary: Makea admin CLI (browser login + Makea admin HTTP API)
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: click<9,>=8.1
@@ -90,21 +90,27 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
90
90
  | 命令 | 读/写 | 后端 | 说明 | 旧名 |
91
91
  |---|---|---|---|---|
92
92
  | `makea-cli admin backfill supplier-id` | write(never) | `POST /admin/supplier/backfill_supplier_id_with_quote_requests` | Migrate supplier_id from a wrong UUID to the Cognito user sub (user_id): profile + Cognito supplierReferenceId, optio… | `backfill-supplier-id` |
93
+ | `makea-cli admin create feature-flag` | write(ask) | `POST /admin/feature-flags` | add a flag (off unless --enabled). An existing key is refused. | — |
93
94
  | `makea-cli admin create library-element` | write(auto) | `POST /admin/designer/{user_id}/library_components` | save a reusable component under a designer. Provide --section and --values (see admin get library-schema). | `library-create` |
95
+ | `makea-cli admin create product-note` | write(ask) | `POST /admin/products/{product_id}/notes` | write a note on a product. Without --internal it goes to the brand. | — |
94
96
  | `makea-cli admin create quote-request` | write(ask) | `POST /admin/supplier/create_quote_request` | create/send a quote request to a supplier for a product (admin). | `create-quote-request` |
97
+ | `makea-cli admin create quote-request-note` | write(ask) | `POST /admin/quote_requests/{quote_request_id}/reply_status_note` | write to the factory on a quote request (e.g. answer its clarification). --requirements-updated words the email as a change to the product's requirements. | — |
95
98
  | `makea-cli admin create rule` | write(ask) | `POST /admin/playbook/{target}/rules` | add a rule to a person's (`--user`, user_id or email), a factory's (`--supplier`) or the platform-wide (`--global`, max 30 live) AI playbook; admin-authored, active unless --status. Refuses a repeat or a conflict unless --force. --reason required; --why / --proof are what the brand reads under it, --title its card name. | — |
96
99
  | `makea-cli admin create shipping-fee` | write(ask) | `POST /admin/shipping_orders/{shipping_order_id}/fees/add` | add a fee (fixed amount or percentage) on top of the freight. | — |
97
100
  | `makea-cli admin create shipping-option` | write(ask) | `POST /admin/shipping_orders/{shipping_order_id}/shipping-options` | add one freight quote (provider, speed, price, currency). | — |
98
101
  | `makea-cli admin create shipping-order` | write(ask) | `POST /admin/shipping_orders/create` | make a shipment for a brand's production and/or sampling orders. The shipment belongs to the orders' owner; you are r… | — |
99
102
  | `makea-cli admin create supplier` | write(ask) | `POST /admin/supplier/add_supplier` | create supplier from JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the field taxonomy (… | `add-supplier` |
103
+ | `makea-cli admin create supplier-link` | write(ask) | `POST /admin/product/link_supplier` | assign a factory to a product, with no price. A bare assignment is not a quote: no quote email goes out and nothing is priced. To quote, use admin submit quote on the quote request. | — |
100
104
  | `makea-cli admin create user` | write(never) | `POST /admin/users/create` | register a user and confirm the Cognito account in one step (no verification email). Allowed --user-type values: "Fas… | `create-user` |
101
105
  | `makea-cli admin delete about` | write(ask) | `DELETE /admin/about/{target}/{key}` | remove one About you line (`--user` / `--supplier`); it is not guessed again. --reason required. | — |
106
+ | `makea-cli admin delete feature-flag` | write(ask) | `DELETE /admin/feature-flags/{key}` | remove a flag. Every check of it then reads false, so delete it only once the code that reads it is gone. | — |
102
107
  | `makea-cli admin delete library-element` | write(never) | `DELETE /admin/designer/{user_id}/library_components/{component_id}` | remove a component from the designer's org library. | `library-delete` |
103
108
  | `makea-cli admin delete rule` | write(ask) | `DELETE /admin/playbook/{target}/rules/{rule_id}` | remove a rule (`--user` / `--supplier` / `--global`): archived, with who and why kept on it (`update rule --status active` restores it). --reason required. | — |
104
109
  | `makea-cli admin delete shipping-fee` | write(ask) | `DELETE /admin/shipping_orders/{shipping_order_id}/fees/{fee_id}/remove` | remove one fee. | — |
105
110
  | `makea-cli admin delete shipping-option` | write(ask) | `DELETE /admin/shipping_orders/{shipping_order_id}/shipping-options/{shipping_option_id}/remove` | withdraw one freight quote. | — |
106
111
  | `makea-cli admin delete shipping-order` | write(never) | `DELETE /admin/shipping_orders/{shipping_order_id}/delete` | remove a shipment and free its orders. Graded `never`: the backend does not check status, so it removes a paid or in-transit shipment too. | — |
107
112
  | `makea-cli admin delete shipping-order-item` | write(ask) | `POST /admin/production_orders/{id}/unlink_from_shipping_order/{shipping_order_id}` | take one production or sampling order off a shipment. A shipment left empty is deleted. | — |
113
+ | `makea-cli admin delete supplier-link` | write(ask) | `POST /admin/product/unlink_supplier` | remove a supplier link from a product. --link-id removes one link; --supplier removes every link that supplier has on the product. | — |
108
114
  | `makea-cli admin download document` | read | `GET /admin/document/download` | save a document file (document id + designer user_id). | `download-document` |
109
115
  | `makea-cli admin download product-document` | read | `GET /admin/document/download` | Resolve product via admin list product-order payload, then GET /admin/document/download. | `download-product-document` |
110
116
  | `makea-cli admin generate about` | write(auto) | `POST /admin/about/{target}/refresh` | recount an account's About you now; `--read` also reads its conversations (one model call). | — |
@@ -117,19 +123,26 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
117
123
  | `makea-cli admin get growth-snapshot` | read | `GET /admin/growth/snapshots/{id}` | one reconciled Growth Analysis snapshot (default `latest`); `--block` prints one block (headline, gates, review_items, …). | — |
118
124
  | `makea-cli admin get library-schema` | read | `GET /admin/library_components/schema` | the tech-pack library taxonomy: sections and their library-role field keys (run this before create/update). | `library-schema` |
119
125
  | `makea-cli admin get playbook-preview` | read | `GET /admin/playbook/preview` | the playbook block one AI surface would get for a person or factory, and every rule left out with its reason; --product previews a conversation about one product, --rule answers for one rule. | — |
126
+ | `makea-cli admin get product-status` | read | `GET /admin/products/{product_id}/status` | where the product is: stage · step · owner for each supplier on it (the shared status model), plus the step catalog. | — |
127
+ | `makea-cli admin get product-step` | read | `GET /admin/products/{product_id}/suppliers/{supplier_id}/change_step` | the step one factory is at on a product and the steps admin update product-step can move it to (options; money steps are listed but never selectable). | — |
128
+ | `makea-cli admin get production-order` | read | `GET /admin/production_orders/{production_order_id}/details` | one production (or restock) order in full: items, status, progress steps, tracking, notes, documents and linked suppliers. For only its pricing use admin get production-pricing. | — |
120
129
  | `makea-cli admin get production-pricing` | read | `GET /admin/production_orders/{id}/details` | show a production order's price tiers, MOQ, sizes/colours, pricing groups and cart coverage. | `production-pricing-show` |
121
130
  | `makea-cli admin get quote-request` | read | `GET /admin/quote_requests/{quote_request_id}` | one quote request in full. | — |
122
131
  | `makea-cli admin get rule` | read | `GET /admin/playbook/{target}/rules/{rule_id}` | one rule in full (`--user` / `--supplier` / `--global`), with its evidence: where it came from, who changed it and why. | — |
123
132
  | `makea-cli admin get rule-history` | read | `GET /admin/playbook/rules/{rule_id}/history` | every revision of one rule: its words, who changed it and why, and the rule that replaced it. | — |
124
133
  | `makea-cli admin get shipping-order` | read | `GET /admin/shipping_orders/{shipping_order_id}/details` | one shipment with its production and sampling orders, freight quotes, fees, tracking and address. | — |
134
+ | `makea-cli admin get supplier` | read | `GET /admin/supplier/get_supplier_by_id` | one supplier's full profile (contact, capabilities, documents) plus its financial documents. | — |
125
135
  | `makea-cli admin get supplier-profile-schema` | read | `GET /admin/supplier/profile/schema` | supplier profile v2 schema (section/field taxonomy: sections, fields, options, required rules). | `get-supplier-profile-schema` |
126
136
  | `makea-cli admin get task` | read | `GET /admin/tasks/{task_id}` | one Makea task in full: body, admin link, what settles it, and for a held lesson the finding Beeboo kept. | — |
127
137
  | `makea-cli admin get tech-spec-extraction` | read | `GET /admin/products/{id}/extract-tech-specifications` | AI-generate specs (not saved). | `extract-ai-tech-spec` |
128
138
  | `makea-cli admin get top-clicks` | read | `POST /admin/analytics/query` | which buttons/elements get clicked most. | `analytics-top-clicks` |
129
139
  | `makea-cli admin get top-features` | read | `POST /admin/analytics/query` | a quick map of which features get used most. | `analytics-top-features` |
140
+ | `makea-cli admin get user` | read | `GET /admin/user-profiles/{user_id}` | one account's profile (Cognito sub as id). | — |
141
+ | `makea-cli admin list feature-flag` | read | `GET /admin/feature-flags` | every flag: global switch, default value, and the accounts it is on for (id, email, name). | — |
130
142
  | `makea-cli admin list library-element` | read | `GET /admin/designer/{user_id}/library_components` | list a designer's tech-pack library (org-fanned). Optional --section scopes to one type. | `library-list` |
131
143
  | `makea-cli admin list growth-snapshot` | read | `GET /admin/growth/snapshots` | published Growth Analysis snapshots, newest first (the change log). | — |
132
144
  | `makea-cli admin list misc-payment` | read | `GET /admin/products/{id}/misc-payments` | misc payments for one product (admin). | `list-misc-payments-by-product` |
145
+ | `makea-cli admin list product-note` | read | `GET /admin/products/{product_id}/notes` | the notes Makea wrote to the brand on a product. | — |
133
146
  | `makea-cli admin list product-order` | read | `GET /admin/designer/get_all_product_orders` | designer product (SKU) list. For 大货 use admin list production-order or admin list production-order --product. | `list-product-orders` |
134
147
  | `makea-cli admin list production-order` | read | `GET /admin/production_orders?type=PRODUCTION` | 大货 (production) orders only. For restock use admin list restock-order; for shipping use admin list shipping-order. | `list-all-production-orders` |
135
148
  | `makea-cli admin list quote-request` | read | `GET /admin/quote_requests` | quote requests, optionally for one product (--product) or one supplier (--supplier, GET /admin/quote_requests/supplie… | — |
@@ -143,15 +156,23 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
143
156
  | `makea-cli admin list user` | read | `GET /admin/users` | list registered users (admin, optional pagination). | `list-users` |
144
157
  | `makea-cli admin send email` | write(ask) | `POST /admin/email/send` | queue an HTML email (To required, Cc optional). From must be @makea.co; HTML from --html-file or stdin ('-'). Require… | `send-email` |
145
158
  | `makea-cli admin set pricing-groups` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set a production order's pricing groups from a JSON file, copy them from the order's quote, or clear them (--clear) t… | `production-groups-set` |
159
+ | `makea-cli admin set production-order-tracking` | write(ask) | `POST /admin/production_orders/{production_order_id}/tracking` | the bulk parcel: tracking number, URL, shipping method, carrier, plus cartons and gross weight off the packing list. Only what you pass is changed; an empty string clears a field. | — |
146
160
  | `makea-cli admin set production-tiers` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set the order-wide price tiers / MOQ / incoterm / currency on a production order (the schedule used when it has no pr… | `production-tiers-set` |
147
161
  | `makea-cli admin set production-variants` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set a production order's available sizes and colours (the grid the buyer's cart and every pricing group's cart keys a… | `production-variants-set` |
162
+ | `makea-cli admin set sampling-order-tracking` | write(ask) | `PUT /admin/sampling_orders/{sampling_order_id}/tracking` | the sample's parcel: tracking number, URL, shipping method, carrier. Only what you pass is changed; an empty string clears a field. | — |
148
163
  | `makea-cli admin submit quote` | write(ask) | `POST /admin/quote_requests/{quote_request_id}/submit_quote` | admin submits a new quote (link) to a quote request. Pricing groups cannot be sent here (the submit endpoint ignores … | `submit-supplier-quote` |
149
164
  | `makea-cli admin update about` | write(ask) | `PATCH /admin/about/{target}/{key}` | add or reword one About you line (stands as the account's own words); `--restore` brings a removed one back. --reason required. | — |
150
165
  | `makea-cli admin update about-pause` | write(ask) | `POST /admin/about/{target}/pause` | stop (or `--resume`) Beeboo using an account's About you. --reason required. | — |
166
+ | `makea-cli admin update feature-flag` | write(ask) | `PATCH /admin/feature-flags/{key}` | flip the global switch, edit the description or default value, or add / remove one account on the allow-list (by user id; find it with admin list user). | — |
151
167
  | `makea-cli admin update library-element` | write(auto) | `PATCH /admin/designer/{user_id}/library_components/{component_id}` | update a component's name and/or values (empty value clears a field). | `library-update` |
168
+ | `makea-cli admin update product` | write(ask) | `PUT /admin/products/{product_id}/basic-info` | change a product's name, category, launch date, contact, size count, grading or custom notes. Only what you pass is changed. Shipping address, sampling sizes and colourways are not covered here. | — |
169
+ | `makea-cli admin update product-document` | write(ask) | `POST /admin/designer/update_document_status` | review one of a product's documents: APPROVED, REJECTED, UPLOADED. | — |
170
+ | `makea-cli admin update product-step` | write(ask) | `POST /admin/products/{product_id}/suppliers/{supplier_id}/change_step` | move a factory to a step when it happened off the platform. Before production any step can be picked, backwards too; PRODUCE, QC and SHIP only go forward, and a step behind an unpaid payment is refused. Run admin get product-step first for the options. | — |
171
+ | `makea-cli admin update production-order` | write(ask) | `PUT /admin/production_orders/{production_order_id}/status` | move a production order to another status (DRAFT, IN_REVIEW, READY_FOR_PRODUCTION, PRODUCTION_IN_PROGRESS, PRODUCTION_COMPLETED, SHIPPED, DELIVERED, COMPLETED, CANCELLED). The paid statuses (PAID, DEPOSIT_PAID, FINAL_PAYMENT_PAID) are recorded by the payment and are refused here. | — |
152
172
  | `makea-cli admin update quote` | write(ask) | `POST /admin/product/edit_supplier_link_override_info` | admin updates an existing quote (supplier link) in place. Only the options you pass are sent, and the backend leaves … | `update-supplier-quote` |
153
173
  | `makea-cli admin update quote-request` | write(ask) | `PATCH /admin/quote_requests/{quote_request_id}/update` | set a quote request's stage, status and/or due date. Only what you pass is changed. This is the door that unblocks a … | `update-quote-request` |
154
174
  | `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/{target}/rules/{rule_id}` | change a rule's text, status, applies_to, when, mode or end date (--valid-until), the --why / --proof the brand reads, or its card --title, on `--user` / `--supplier` / `--global`. --reason required; the rule keeps what it was before. | — |
175
+ | `makea-cli admin update sampling-order` | write(ask) | `PUT /admin/sampling_orders/{sampling_order_id}/status` | move a sampling order to another status (DRAFT, IN_PROGRESS, SAMPLING_COMPLETED, APPROVAL, SHIPPED, DELIVERED, CANCELLED). PAID is recorded by the payment and is refused here. Prefer admin update product-step, which moves the same statuses through the step model. | — |
155
176
  | `makea-cli admin update shipping-order` | write(ask) | `PUT /admin/shipping_orders/{shipping_order_id}/status` | Change a shipment: --status (PUT .../status), tracking flags (POST .../tracking), --address (PUT .../shipping-address… | — |
156
177
  | `makea-cli admin update supplier` | write(ask) | `PUT /admin/supplier/update_supplier` | update an existing supplier from a JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the fi… | `update-supplier` |
157
178
  | `makea-cli admin update task` | write(ask) | `POST /admin/tasks/{task_id}/{done\|dismiss}` | close a Makea task with a note: `--done` once handled (a held lesson's `--reason` goes to Beeboo's next reading), or `--dismiss`. | — |
@@ -78,21 +78,27 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
78
78
  | 命令 | 读/写 | 后端 | 说明 | 旧名 |
79
79
  |---|---|---|---|---|
80
80
  | `makea-cli admin backfill supplier-id` | write(never) | `POST /admin/supplier/backfill_supplier_id_with_quote_requests` | Migrate supplier_id from a wrong UUID to the Cognito user sub (user_id): profile + Cognito supplierReferenceId, optio… | `backfill-supplier-id` |
81
+ | `makea-cli admin create feature-flag` | write(ask) | `POST /admin/feature-flags` | add a flag (off unless --enabled). An existing key is refused. | — |
81
82
  | `makea-cli admin create library-element` | write(auto) | `POST /admin/designer/{user_id}/library_components` | save a reusable component under a designer. Provide --section and --values (see admin get library-schema). | `library-create` |
83
+ | `makea-cli admin create product-note` | write(ask) | `POST /admin/products/{product_id}/notes` | write a note on a product. Without --internal it goes to the brand. | — |
82
84
  | `makea-cli admin create quote-request` | write(ask) | `POST /admin/supplier/create_quote_request` | create/send a quote request to a supplier for a product (admin). | `create-quote-request` |
85
+ | `makea-cli admin create quote-request-note` | write(ask) | `POST /admin/quote_requests/{quote_request_id}/reply_status_note` | write to the factory on a quote request (e.g. answer its clarification). --requirements-updated words the email as a change to the product's requirements. | — |
83
86
  | `makea-cli admin create rule` | write(ask) | `POST /admin/playbook/{target}/rules` | add a rule to a person's (`--user`, user_id or email), a factory's (`--supplier`) or the platform-wide (`--global`, max 30 live) AI playbook; admin-authored, active unless --status. Refuses a repeat or a conflict unless --force. --reason required; --why / --proof are what the brand reads under it, --title its card name. | — |
84
87
  | `makea-cli admin create shipping-fee` | write(ask) | `POST /admin/shipping_orders/{shipping_order_id}/fees/add` | add a fee (fixed amount or percentage) on top of the freight. | — |
85
88
  | `makea-cli admin create shipping-option` | write(ask) | `POST /admin/shipping_orders/{shipping_order_id}/shipping-options` | add one freight quote (provider, speed, price, currency). | — |
86
89
  | `makea-cli admin create shipping-order` | write(ask) | `POST /admin/shipping_orders/create` | make a shipment for a brand's production and/or sampling orders. The shipment belongs to the orders' owner; you are r… | — |
87
90
  | `makea-cli admin create supplier` | write(ask) | `POST /admin/supplier/add_supplier` | create supplier from JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the field taxonomy (… | `add-supplier` |
91
+ | `makea-cli admin create supplier-link` | write(ask) | `POST /admin/product/link_supplier` | assign a factory to a product, with no price. A bare assignment is not a quote: no quote email goes out and nothing is priced. To quote, use admin submit quote on the quote request. | — |
88
92
  | `makea-cli admin create user` | write(never) | `POST /admin/users/create` | register a user and confirm the Cognito account in one step (no verification email). Allowed --user-type values: "Fas… | `create-user` |
89
93
  | `makea-cli admin delete about` | write(ask) | `DELETE /admin/about/{target}/{key}` | remove one About you line (`--user` / `--supplier`); it is not guessed again. --reason required. | — |
94
+ | `makea-cli admin delete feature-flag` | write(ask) | `DELETE /admin/feature-flags/{key}` | remove a flag. Every check of it then reads false, so delete it only once the code that reads it is gone. | — |
90
95
  | `makea-cli admin delete library-element` | write(never) | `DELETE /admin/designer/{user_id}/library_components/{component_id}` | remove a component from the designer's org library. | `library-delete` |
91
96
  | `makea-cli admin delete rule` | write(ask) | `DELETE /admin/playbook/{target}/rules/{rule_id}` | remove a rule (`--user` / `--supplier` / `--global`): archived, with who and why kept on it (`update rule --status active` restores it). --reason required. | — |
92
97
  | `makea-cli admin delete shipping-fee` | write(ask) | `DELETE /admin/shipping_orders/{shipping_order_id}/fees/{fee_id}/remove` | remove one fee. | — |
93
98
  | `makea-cli admin delete shipping-option` | write(ask) | `DELETE /admin/shipping_orders/{shipping_order_id}/shipping-options/{shipping_option_id}/remove` | withdraw one freight quote. | — |
94
99
  | `makea-cli admin delete shipping-order` | write(never) | `DELETE /admin/shipping_orders/{shipping_order_id}/delete` | remove a shipment and free its orders. Graded `never`: the backend does not check status, so it removes a paid or in-transit shipment too. | — |
95
100
  | `makea-cli admin delete shipping-order-item` | write(ask) | `POST /admin/production_orders/{id}/unlink_from_shipping_order/{shipping_order_id}` | take one production or sampling order off a shipment. A shipment left empty is deleted. | — |
101
+ | `makea-cli admin delete supplier-link` | write(ask) | `POST /admin/product/unlink_supplier` | remove a supplier link from a product. --link-id removes one link; --supplier removes every link that supplier has on the product. | — |
96
102
  | `makea-cli admin download document` | read | `GET /admin/document/download` | save a document file (document id + designer user_id). | `download-document` |
97
103
  | `makea-cli admin download product-document` | read | `GET /admin/document/download` | Resolve product via admin list product-order payload, then GET /admin/document/download. | `download-product-document` |
98
104
  | `makea-cli admin generate about` | write(auto) | `POST /admin/about/{target}/refresh` | recount an account's About you now; `--read` also reads its conversations (one model call). | — |
@@ -105,19 +111,26 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
105
111
  | `makea-cli admin get growth-snapshot` | read | `GET /admin/growth/snapshots/{id}` | one reconciled Growth Analysis snapshot (default `latest`); `--block` prints one block (headline, gates, review_items, …). | — |
106
112
  | `makea-cli admin get library-schema` | read | `GET /admin/library_components/schema` | the tech-pack library taxonomy: sections and their library-role field keys (run this before create/update). | `library-schema` |
107
113
  | `makea-cli admin get playbook-preview` | read | `GET /admin/playbook/preview` | the playbook block one AI surface would get for a person or factory, and every rule left out with its reason; --product previews a conversation about one product, --rule answers for one rule. | — |
114
+ | `makea-cli admin get product-status` | read | `GET /admin/products/{product_id}/status` | where the product is: stage · step · owner for each supplier on it (the shared status model), plus the step catalog. | — |
115
+ | `makea-cli admin get product-step` | read | `GET /admin/products/{product_id}/suppliers/{supplier_id}/change_step` | the step one factory is at on a product and the steps admin update product-step can move it to (options; money steps are listed but never selectable). | — |
116
+ | `makea-cli admin get production-order` | read | `GET /admin/production_orders/{production_order_id}/details` | one production (or restock) order in full: items, status, progress steps, tracking, notes, documents and linked suppliers. For only its pricing use admin get production-pricing. | — |
108
117
  | `makea-cli admin get production-pricing` | read | `GET /admin/production_orders/{id}/details` | show a production order's price tiers, MOQ, sizes/colours, pricing groups and cart coverage. | `production-pricing-show` |
109
118
  | `makea-cli admin get quote-request` | read | `GET /admin/quote_requests/{quote_request_id}` | one quote request in full. | — |
110
119
  | `makea-cli admin get rule` | read | `GET /admin/playbook/{target}/rules/{rule_id}` | one rule in full (`--user` / `--supplier` / `--global`), with its evidence: where it came from, who changed it and why. | — |
111
120
  | `makea-cli admin get rule-history` | read | `GET /admin/playbook/rules/{rule_id}/history` | every revision of one rule: its words, who changed it and why, and the rule that replaced it. | — |
112
121
  | `makea-cli admin get shipping-order` | read | `GET /admin/shipping_orders/{shipping_order_id}/details` | one shipment with its production and sampling orders, freight quotes, fees, tracking and address. | — |
122
+ | `makea-cli admin get supplier` | read | `GET /admin/supplier/get_supplier_by_id` | one supplier's full profile (contact, capabilities, documents) plus its financial documents. | — |
113
123
  | `makea-cli admin get supplier-profile-schema` | read | `GET /admin/supplier/profile/schema` | supplier profile v2 schema (section/field taxonomy: sections, fields, options, required rules). | `get-supplier-profile-schema` |
114
124
  | `makea-cli admin get task` | read | `GET /admin/tasks/{task_id}` | one Makea task in full: body, admin link, what settles it, and for a held lesson the finding Beeboo kept. | — |
115
125
  | `makea-cli admin get tech-spec-extraction` | read | `GET /admin/products/{id}/extract-tech-specifications` | AI-generate specs (not saved). | `extract-ai-tech-spec` |
116
126
  | `makea-cli admin get top-clicks` | read | `POST /admin/analytics/query` | which buttons/elements get clicked most. | `analytics-top-clicks` |
117
127
  | `makea-cli admin get top-features` | read | `POST /admin/analytics/query` | a quick map of which features get used most. | `analytics-top-features` |
128
+ | `makea-cli admin get user` | read | `GET /admin/user-profiles/{user_id}` | one account's profile (Cognito sub as id). | — |
129
+ | `makea-cli admin list feature-flag` | read | `GET /admin/feature-flags` | every flag: global switch, default value, and the accounts it is on for (id, email, name). | — |
118
130
  | `makea-cli admin list library-element` | read | `GET /admin/designer/{user_id}/library_components` | list a designer's tech-pack library (org-fanned). Optional --section scopes to one type. | `library-list` |
119
131
  | `makea-cli admin list growth-snapshot` | read | `GET /admin/growth/snapshots` | published Growth Analysis snapshots, newest first (the change log). | — |
120
132
  | `makea-cli admin list misc-payment` | read | `GET /admin/products/{id}/misc-payments` | misc payments for one product (admin). | `list-misc-payments-by-product` |
133
+ | `makea-cli admin list product-note` | read | `GET /admin/products/{product_id}/notes` | the notes Makea wrote to the brand on a product. | — |
121
134
  | `makea-cli admin list product-order` | read | `GET /admin/designer/get_all_product_orders` | designer product (SKU) list. For 大货 use admin list production-order or admin list production-order --product. | `list-product-orders` |
122
135
  | `makea-cli admin list production-order` | read | `GET /admin/production_orders?type=PRODUCTION` | 大货 (production) orders only. For restock use admin list restock-order; for shipping use admin list shipping-order. | `list-all-production-orders` |
123
136
  | `makea-cli admin list quote-request` | read | `GET /admin/quote_requests` | quote requests, optionally for one product (--product) or one supplier (--supplier, GET /admin/quote_requests/supplie… | — |
@@ -131,15 +144,23 @@ exit code:`0` 成功 · `2` 用法错 · `3` 未登录或身份与 persona 不
131
144
  | `makea-cli admin list user` | read | `GET /admin/users` | list registered users (admin, optional pagination). | `list-users` |
132
145
  | `makea-cli admin send email` | write(ask) | `POST /admin/email/send` | queue an HTML email (To required, Cc optional). From must be @makea.co; HTML from --html-file or stdin ('-'). Require… | `send-email` |
133
146
  | `makea-cli admin set pricing-groups` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set a production order's pricing groups from a JSON file, copy them from the order's quote, or clear them (--clear) t… | `production-groups-set` |
147
+ | `makea-cli admin set production-order-tracking` | write(ask) | `POST /admin/production_orders/{production_order_id}/tracking` | the bulk parcel: tracking number, URL, shipping method, carrier, plus cartons and gross weight off the packing list. Only what you pass is changed; an empty string clears a field. | — |
134
148
  | `makea-cli admin set production-tiers` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set the order-wide price tiers / MOQ / incoterm / currency on a production order (the schedule used when it has no pr… | `production-tiers-set` |
135
149
  | `makea-cli admin set production-variants` | write(ask) | `POST /admin/production_orders/{id}/details/update` | Set a production order's available sizes and colours (the grid the buyer's cart and every pricing group's cart keys a… | `production-variants-set` |
150
+ | `makea-cli admin set sampling-order-tracking` | write(ask) | `PUT /admin/sampling_orders/{sampling_order_id}/tracking` | the sample's parcel: tracking number, URL, shipping method, carrier. Only what you pass is changed; an empty string clears a field. | — |
136
151
  | `makea-cli admin submit quote` | write(ask) | `POST /admin/quote_requests/{quote_request_id}/submit_quote` | admin submits a new quote (link) to a quote request. Pricing groups cannot be sent here (the submit endpoint ignores … | `submit-supplier-quote` |
137
152
  | `makea-cli admin update about` | write(ask) | `PATCH /admin/about/{target}/{key}` | add or reword one About you line (stands as the account's own words); `--restore` brings a removed one back. --reason required. | — |
138
153
  | `makea-cli admin update about-pause` | write(ask) | `POST /admin/about/{target}/pause` | stop (or `--resume`) Beeboo using an account's About you. --reason required. | — |
154
+ | `makea-cli admin update feature-flag` | write(ask) | `PATCH /admin/feature-flags/{key}` | flip the global switch, edit the description or default value, or add / remove one account on the allow-list (by user id; find it with admin list user). | — |
139
155
  | `makea-cli admin update library-element` | write(auto) | `PATCH /admin/designer/{user_id}/library_components/{component_id}` | update a component's name and/or values (empty value clears a field). | `library-update` |
156
+ | `makea-cli admin update product` | write(ask) | `PUT /admin/products/{product_id}/basic-info` | change a product's name, category, launch date, contact, size count, grading or custom notes. Only what you pass is changed. Shipping address, sampling sizes and colourways are not covered here. | — |
157
+ | `makea-cli admin update product-document` | write(ask) | `POST /admin/designer/update_document_status` | review one of a product's documents: APPROVED, REJECTED, UPLOADED. | — |
158
+ | `makea-cli admin update product-step` | write(ask) | `POST /admin/products/{product_id}/suppliers/{supplier_id}/change_step` | move a factory to a step when it happened off the platform. Before production any step can be picked, backwards too; PRODUCE, QC and SHIP only go forward, and a step behind an unpaid payment is refused. Run admin get product-step first for the options. | — |
159
+ | `makea-cli admin update production-order` | write(ask) | `PUT /admin/production_orders/{production_order_id}/status` | move a production order to another status (DRAFT, IN_REVIEW, READY_FOR_PRODUCTION, PRODUCTION_IN_PROGRESS, PRODUCTION_COMPLETED, SHIPPED, DELIVERED, COMPLETED, CANCELLED). The paid statuses (PAID, DEPOSIT_PAID, FINAL_PAYMENT_PAID) are recorded by the payment and are refused here. | — |
140
160
  | `makea-cli admin update quote` | write(ask) | `POST /admin/product/edit_supplier_link_override_info` | admin updates an existing quote (supplier link) in place. Only the options you pass are sent, and the backend leaves … | `update-supplier-quote` |
141
161
  | `makea-cli admin update quote-request` | write(ask) | `PATCH /admin/quote_requests/{quote_request_id}/update` | set a quote request's stage, status and/or due date. Only what you pass is changed. This is the door that unblocks a … | `update-quote-request` |
142
162
  | `makea-cli admin update rule` | write(ask) | `PATCH /admin/playbook/{target}/rules/{rule_id}` | change a rule's text, status, applies_to, when, mode or end date (--valid-until), the --why / --proof the brand reads, or its card --title, on `--user` / `--supplier` / `--global`. --reason required; the rule keeps what it was before. | — |
163
+ | `makea-cli admin update sampling-order` | write(ask) | `PUT /admin/sampling_orders/{sampling_order_id}/status` | move a sampling order to another status (DRAFT, IN_PROGRESS, SAMPLING_COMPLETED, APPROVAL, SHIPPED, DELIVERED, CANCELLED). PAID is recorded by the payment and is refused here. Prefer admin update product-step, which moves the same statuses through the step model. | — |
143
164
  | `makea-cli admin update shipping-order` | write(ask) | `PUT /admin/shipping_orders/{shipping_order_id}/status` | Change a shipment: --status (PUT .../status), tracking flags (POST .../tracking), --address (PUT .../shipping-address… | — |
144
165
  | `makea-cli admin update supplier` | write(ask) | `PUT /admin/supplier/update_supplier` | update an existing supplier from a JSON file (admin). Run `makea-cli get-supplier-profile-schema` FIRST to get the fi… | `update-supplier` |
145
166
  | `makea-cli admin update task` | write(ask) | `POST /admin/tasks/{task_id}/{done\|dismiss}` | close a Makea task with a note: `--done` once handled (a held lesson's `--reason` goes to Beeboo's next reading), or `--dismiss`. | — |
@@ -0,0 +1 @@
1
+ __version__ = "0.2.26"
@@ -1282,6 +1282,131 @@ def admin_playbook_preview(
1282
1282
  return get_json("/admin/playbook/preview", params=params)
1283
1283
 
1284
1284
 
1285
+ # --- admin: what the admin page does by hand (orders, products, people, flags) -----
1286
+ # None of these move money: order statuses that record a payment are refused by
1287
+ # the commands, and change_step refuses money steps server-side.
1288
+
1289
+
1290
+ def admin_get_supplier(supplier_id: str) -> Any:
1291
+ """GET /admin/supplier/get_supplier_by_id?supplier_id= — profile plus financial documents."""
1292
+ return get_json("/admin/supplier/get_supplier_by_id", params={"supplier_id": supplier_id})
1293
+
1294
+
1295
+ def admin_get_user_profile(user_id: str) -> Any:
1296
+ """GET /admin/user-profiles/{user_id}"""
1297
+ return get_json(f"/admin/user-profiles/{quote(user_id, safe='')}")
1298
+
1299
+
1300
+ def admin_update_sampling_order_status(sampling_order_id: str, status: str) -> Any:
1301
+ """PUT /admin/sampling_orders/{id}/status"""
1302
+ return put_json(f"/admin/sampling_orders/{sampling_order_id}/status", {"status": status})
1303
+
1304
+
1305
+ def admin_update_production_order_status(production_order_id: str, status: str) -> Any:
1306
+ """PUT /admin/production_orders/{id}/status"""
1307
+ return put_json(f"/admin/production_orders/{production_order_id}/status", {"status": status})
1308
+
1309
+
1310
+ def admin_set_sampling_order_tracking(sampling_order_id: str, body: dict[str, Any]) -> Any:
1311
+ """PUT /admin/sampling_orders/{id}/tracking — tracking_number / tracking_url /
1312
+ shipping_method / carrier_id, flat in the body."""
1313
+ return put_json(f"/admin/sampling_orders/{sampling_order_id}/tracking", body)
1314
+
1315
+
1316
+ def admin_set_production_order_tracking(production_order_id: str, body: dict[str, Any]) -> Any:
1317
+ """POST /admin/production_orders/{id}/tracking — as sampling, plus cartons and
1318
+ gross_weight_kg (absent = unchanged, empty string = cleared)."""
1319
+ return post_json(f"/admin/production_orders/{production_order_id}/tracking", body)
1320
+
1321
+
1322
+ def admin_get_product_status(product_id: str) -> Any:
1323
+ """GET /admin/products/{id}/status — the product's stage · step · owner per supplier,
1324
+ with the step catalog."""
1325
+ return get_json(f"/admin/products/{product_id}/status")
1326
+
1327
+
1328
+ def admin_get_change_step(product_id: str, supplier_id: str) -> Any:
1329
+ """GET /admin/products/{id}/suppliers/{sid}/change_step — where the factory is
1330
+ and which steps can be picked."""
1331
+ return get_json(f"/admin/products/{product_id}/suppliers/{supplier_id}/change_step")
1332
+
1333
+
1334
+ def admin_change_step(product_id: str, supplier_id: str, body: dict[str, Any]) -> Any:
1335
+ """POST /admin/products/{id}/suppliers/{sid}/change_step —
1336
+ {stage, step, note?, notify_brand?, notify_supplier?}."""
1337
+ return post_json(f"/admin/products/{product_id}/suppliers/{supplier_id}/change_step", body)
1338
+
1339
+
1340
+ def admin_list_product_notes(product_id: str) -> Any:
1341
+ """GET /admin/products/{id}/notes — the product's customer notes."""
1342
+ return get_json(f"/admin/products/{product_id}/notes")
1343
+
1344
+
1345
+ def admin_add_product_note(product_id: str, content: str, *, internal: bool) -> Any:
1346
+ """POST /admin/products/{id}/notes — {content, is_internal}. The backend reads
1347
+ ``is_internal``; a customer note (the default) is emailed to the brand."""
1348
+ return post_json(
1349
+ f"/admin/products/{product_id}/notes",
1350
+ {"content": content, "is_internal": internal},
1351
+ )
1352
+
1353
+
1354
+ def admin_update_product_basic_info(product_id: str, body: dict[str, Any]) -> Any:
1355
+ """PUT /admin/products/{id}/basic-info — only the fields given are changed."""
1356
+ return put_json(f"/admin/products/{product_id}/basic-info", body)
1357
+
1358
+
1359
+ def admin_update_product_document_status(product_id: str, document_id: str, status: str) -> Any:
1360
+ """POST /admin/designer/update_document_status — {product_id, document_id, status}."""
1361
+ return post_json(
1362
+ "/admin/designer/update_document_status",
1363
+ {"product_id": product_id, "document_id": document_id, "status": status},
1364
+ )
1365
+
1366
+
1367
+ def admin_link_supplier(body: dict[str, Any]) -> Any:
1368
+ """POST /admin/product/link_supplier — a bare assignment (no price, so not a quote)."""
1369
+ return post_json("/admin/product/link_supplier", body)
1370
+
1371
+
1372
+ def admin_unlink_supplier(
1373
+ product_id: str, *, link_id: str | None = None, supplier_id: str | None = None
1374
+ ) -> Any:
1375
+ """POST /admin/product/unlink_supplier?product_id=&link_id=|supplier_id= (query, no body)."""
1376
+ params: dict[str, Any] = {"product_id": product_id}
1377
+ if link_id:
1378
+ params["link_id"] = link_id
1379
+ if supplier_id:
1380
+ params["supplier_id"] = supplier_id
1381
+ return _request("POST", "/admin/product/unlink_supplier", params=params)
1382
+
1383
+
1384
+ def admin_reply_quote_request(quote_request_id: str, body: dict[str, Any]) -> Any:
1385
+ """POST /admin/quote_requests/{id}/reply_status_note — {status_note, notification_kind}."""
1386
+ return post_json(f"/admin/quote_requests/{quote_request_id}/reply_status_note", body)
1387
+
1388
+
1389
+ def admin_list_feature_flags() -> Any:
1390
+ """GET /admin/feature-flags — every flag with its allow-list resolved."""
1391
+ return get_json("/admin/feature-flags")
1392
+
1393
+
1394
+ def admin_create_feature_flag(body: dict[str, Any]) -> Any:
1395
+ """POST /admin/feature-flags — {key, description?, enabled?, value?}."""
1396
+ return post_json("/admin/feature-flags", body)
1397
+
1398
+
1399
+ def admin_update_feature_flag(key: str, body: dict[str, Any]) -> Any:
1400
+ """PATCH /admin/feature-flags/{key} — enabled / description / value /
1401
+ add_user_id / remove_user_id, one account at a time."""
1402
+ return patch_json(f"/admin/feature-flags/{quote(key, safe='')}", body)
1403
+
1404
+
1405
+ def admin_delete_feature_flag(key: str) -> Any:
1406
+ """DELETE /admin/feature-flags/{key} — every check of the flag then reads false."""
1407
+ return delete_json(f"/admin/feature-flags/{quote(key, safe='')}")
1408
+
1409
+
1285
1410
  # --- supplier persona: a factory acting on its own RFQs, quotes and orders --------
1286
1411
 
1287
1412
 
@@ -11,6 +11,7 @@ from makea_cli.commands.directory.cmd import register as register_directory
11
11
  from makea_cli.commands.document.cmd import register as register_document
12
12
  from makea_cli.commands.email.cmd import register as register_email
13
13
  from makea_cli.commands.factory.cmd import register as register_factory
14
+ from makea_cli.commands.flags.cmd import register as register_flags
14
15
  from makea_cli.commands.library.cmd import register as register_library
15
16
  from makea_cli.commands.metrics.cmd import register as register_metrics
16
17
  from makea_cli.commands.orders.cmd import register as register_orders
@@ -41,3 +42,4 @@ def register_all(app: typer.Typer) -> None:
41
42
  register_playbook(app)
42
43
  register_about(app)
43
44
  register_tasks(app)
45
+ register_flags(app)
@@ -54,6 +54,20 @@ def register(app: typer.Typer) -> None:
54
54
  """
55
55
  print_json_or_exit(console, lambda: api_client.get_all_users(limit=limit, offset=offset))
56
56
 
57
+ @command(
58
+ app,
59
+ "admin",
60
+ "get",
61
+ "user",
62
+ api="GET /admin/user-profiles/{user_id}",
63
+ help="GET /admin/user-profiles/{user_id} — one account's profile (Cognito sub as id).",
64
+ )
65
+ def get_user(
66
+ user_id: str = typer.Argument(..., help="Cognito sub (user_id) of the account."),
67
+ ) -> None:
68
+ """Show one user's profile."""
69
+ print_json_or_exit(console, lambda: api_client.admin_get_user_profile(user_id))
70
+
57
71
  @command(
58
72
  app,
59
73
  "admin",
@@ -0,0 +1,157 @@
1
+ """Admin feature flags: the switches on the admin page's Flags tab.
2
+
3
+ A flag is on globally, or, while the global switch is off, on for the accounts
4
+ on its allow-list. The allow-list holds user ids (Cognito sub), never emails.
5
+ Every change reaches prod users at once, so every write asks first.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ from typing import Any
12
+
13
+ import typer
14
+ from rich.console import Console
15
+
16
+ from makea_cli import api_client
17
+ from makea_cli.commands._util import print_json_or_exit
18
+ from makea_cli.registry import command
19
+
20
+ console = Console()
21
+
22
+ # Mirrors garmentby_service.common.feature_flags (FLAG_KEY_PATTERN, MAX_FLAG_KEY_CHARS).
23
+ _FLAG_KEY = re.compile(r"^[A-Z][A-Z0-9_]*$")
24
+ _FLAG_KEY_MAX = 64
25
+
26
+
27
+ def _flag_key(raw: str) -> str:
28
+ key = raw.strip().upper()
29
+ if not _FLAG_KEY.match(key) or len(key) > _FLAG_KEY_MAX:
30
+ raise typer.BadParameter(
31
+ f"flag key must be ALL_CAPS with underscores, at most {_FLAG_KEY_MAX} characters"
32
+ )
33
+ return key
34
+
35
+
36
+ def register(app: typer.Typer) -> None:
37
+ @command(
38
+ app,
39
+ "admin",
40
+ "list",
41
+ "feature-flag",
42
+ api="GET /admin/feature-flags",
43
+ help=(
44
+ "GET /admin/feature-flags — every flag: global switch, default value, and the "
45
+ "accounts it is on for (id, email, name)."
46
+ ),
47
+ )
48
+ def list_feature_flags() -> None:
49
+ """List feature flags."""
50
+ print_json_or_exit(console, api_client.admin_list_feature_flags)
51
+
52
+ @command(
53
+ app,
54
+ "admin",
55
+ "create",
56
+ "feature-flag",
57
+ api="POST /admin/feature-flags",
58
+ side_effects=["with --enabled the flag is on for every account at once"],
59
+ approval="ask",
60
+ reversible=True,
61
+ idempotent=False,
62
+ help=(
63
+ "POST /admin/feature-flags — add a flag (off unless --enabled). An existing key "
64
+ "is refused."
65
+ ),
66
+ )
67
+ def create_feature_flag(
68
+ key: str = typer.Argument(..., help="Flag key, ALL_CAPS_WITH_UNDERSCORES."),
69
+ description: str | None = typer.Option(None, "--description", help="What it gates."),
70
+ enabled: bool = typer.Option(False, "--enabled", help="Turn it on globally now."),
71
+ value: str | None = typer.Option(
72
+ None,
73
+ "--value",
74
+ help="Default value, for flags that name a choice (e.g. DEEPSEEK).",
75
+ ),
76
+ ) -> None:
77
+ """Create a feature flag."""
78
+ body: dict[str, Any] = {"key": _flag_key(key), "enabled": enabled}
79
+ if description is not None:
80
+ body["description"] = description.strip()
81
+ if value is not None:
82
+ body["value"] = value.strip()
83
+ print_json_or_exit(console, lambda: api_client.admin_create_feature_flag(body))
84
+
85
+ @command(
86
+ app,
87
+ "admin",
88
+ "update",
89
+ "feature-flag",
90
+ api="PATCH /admin/feature-flags/{key}",
91
+ side_effects=["the change reaches the affected accounts at once"],
92
+ approval="ask",
93
+ reversible=True,
94
+ idempotent=True,
95
+ help=(
96
+ "PATCH /admin/feature-flags/{key} — flip the global switch, edit the description "
97
+ "or default value, or add / remove one account on the allow-list (by user id; "
98
+ "find it with admin list user)."
99
+ ),
100
+ )
101
+ def update_feature_flag(
102
+ key: str = typer.Argument(..., help="Flag key."),
103
+ enabled: bool | None = typer.Option(
104
+ None, "--enabled/--disabled", help="The global switch."
105
+ ),
106
+ description: str | None = typer.Option(None, "--description"),
107
+ value: str | None = typer.Option(
108
+ None, "--value", help="Default value; an empty string clears it."
109
+ ),
110
+ add_user: str | None = typer.Option(
111
+ None, "--add-user", help="User id (Cognito sub) to put on the allow-list."
112
+ ),
113
+ remove_user: str | None = typer.Option(
114
+ None, "--remove-user", help="User id to take off the allow-list."
115
+ ),
116
+ ) -> None:
117
+ """Change a feature flag."""
118
+ body: dict[str, Any] = {}
119
+ if enabled is not None:
120
+ body["enabled"] = enabled
121
+ if description is not None:
122
+ body["description"] = description.strip()
123
+ if value is not None:
124
+ body["value"] = value.strip()
125
+ if add_user and add_user.strip():
126
+ body["add_user_id"] = add_user.strip()
127
+ if remove_user and remove_user.strip():
128
+ body["remove_user_id"] = remove_user.strip()
129
+ if not body:
130
+ raise typer.BadParameter(
131
+ "pass at least one of --enabled/--disabled, --description, --value, "
132
+ "--add-user, --remove-user"
133
+ )
134
+ flag = _flag_key(key)
135
+ print_json_or_exit(console, lambda: api_client.admin_update_feature_flag(flag, body))
136
+
137
+ @command(
138
+ app,
139
+ "admin",
140
+ "delete",
141
+ "feature-flag",
142
+ api="DELETE /admin/feature-flags/{key}",
143
+ side_effects=["every check of the flag reads false from then on"],
144
+ approval="ask",
145
+ reversible=False,
146
+ idempotent=True,
147
+ help=(
148
+ "DELETE /admin/feature-flags/{key} — remove a flag. Every check of it then reads "
149
+ "false, so delete it only once the code that reads it is gone."
150
+ ),
151
+ )
152
+ def delete_feature_flag(
153
+ key: str = typer.Argument(..., help="Flag key."),
154
+ ) -> None:
155
+ """Delete a feature flag."""
156
+ flag = _flag_key(key)
157
+ print_json_or_exit(console, lambda: api_client.admin_delete_feature_flag(flag))