@wix/himalaya-cli 0.1527.0 → 0.1529.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/ecom/src/extensions.d.ts +144 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/restaurants/src/extensions.d.ts +93 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +27 -5
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +19 -3
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +27 -5
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-ecom.mjs +58 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-restaurants.mjs +23 -0
  8. package/dist/cli.mjs +5844 -4606
  9. package/fixtures/wix-canned.json +83 -0
  10. package/guides/hhp.md +39 -0
  11. package/guides/himi-json-output.md +67 -1
  12. package/guides/himi-mcp.md +41 -0
  13. package/guides/iap-products.md +88 -23
  14. package/package.json +2 -2
  15. package/templates/beauty-salon/config.ts +12 -1
  16. package/templates/beauty-salon/tier5-src/_shared/himi-restaurants.ts +12 -5
  17. package/templates/beauty-salon/tier5-src/_shared/restaurant-ordering.ts +201 -0
  18. package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +6 -0
  19. package/templates/branded-lite/config.ts +12 -1
  20. package/templates/branded-lite/dev/index.ts +1278 -180
  21. package/templates/branded-lite/tier5-src/_shared/himi-restaurants.ts +12 -5
  22. package/templates/branded-lite/tier5-src/_shared/restaurant-ordering.ts +201 -0
  23. package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +6 -0
  24. package/templates/branded-lite/tier5-src/himi-branded-lite-menu-item/index.ts +144 -77
  25. package/templates/branded-lite/tier5-src/himi-branded-lite-menus/index.ts +16 -5
  26. package/templates/branded-lite/tier5-src/himi-branded-lite-reservations/index.ts +1 -1
  27. package/templates/branded-lite/tier5-src/wix-spaces-food-order-detail/index.ts +76 -14
  28. package/templates/branded-lite/tier5-src/wix-spaces-food-orders/index.ts +807 -55
  29. package/templates/community-club/config.ts +12 -1
  30. package/templates/community-club/tier5-src/_shared/himi-restaurants.ts +12 -5
  31. package/templates/events-meetups/config.ts +12 -1
  32. package/templates/events-meetups/tier5-src/_shared/himi-restaurants.ts +12 -5
  33. package/templates/gym-fitness/config.ts +12 -1
  34. package/templates/gym-fitness/tier5-src/_shared/himi-restaurants.ts +12 -5
  35. package/templates/gym-fitness/tier5-src/_shared/restaurant-ordering.ts +201 -0
  36. package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +6 -0
  37. package/templates/nonprofit-cause/config.ts +12 -1
  38. package/templates/nonprofit-cause/tier5-src/_shared/himi-restaurants.ts +12 -5
  39. package/templates/podcast-creator/config.ts +12 -1
  40. package/templates/podcast-creator/tier5-src/_shared/himi-restaurants.ts +12 -5
  41. package/templates/portfolio-creative/config.ts +12 -1
  42. package/templates/portfolio-creative/tier5-src/_shared/himi-restaurants.ts +12 -5
  43. package/templates/portfolio-creative/tier5-src/_shared/restaurant-ordering.ts +201 -0
  44. package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +6 -0
  45. package/templates/restaurant/README.md +1 -1
  46. package/templates/restaurant/config.ts +12 -1
  47. package/templates/restaurant/dev/index.ts +1373 -275
  48. package/templates/restaurant/himalaya.template.json +2 -1
  49. package/templates/restaurant/tier5-src/_shared/himi-restaurants.ts +12 -5
  50. package/templates/restaurant/tier5-src/_shared/member-orders.ts +8 -0
  51. package/templates/restaurant/tier5-src/_shared/restaurant-ordering.ts +201 -0
  52. package/templates/restaurant/tier5-src/himi-branded-lite-menu-item/index.ts +144 -77
  53. package/templates/restaurant/tier5-src/himi-branded-lite-menus/index.ts +16 -5
  54. package/templates/restaurant/tier5-src/wix-spaces-food-order-detail/index.ts +76 -14
  55. package/templates/restaurant/tier5-src/wix-spaces-food-orders/index.ts +807 -55
  56. package/templates/retail-store/config.ts +12 -1
  57. package/templates/retail-store/tier5-src/_shared/himi-restaurants.ts +12 -5
  58. package/templates/retail-store/tier5-src/_shared/restaurant-ordering.ts +201 -0
  59. package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +6 -0
  60. package/templates/yoga-studio/config.ts +12 -1
  61. package/templates/yoga-studio/tier5-src/_shared/himi-restaurants.ts +12 -5
@@ -2093,5 +2093,88 @@
2093
2093
  "POST /ecom/v1/checkouts/chk-0001/create-order": {
2094
2094
  "orderId": "order-0001",
2095
2095
  "paymentGatewayOrderId": "payment-0001"
2096
+ },
2097
+ "GET /ecom/v2/carts/current": {},
2098
+ "GET /restaurants-operations/v1/operations": {
2099
+ "operations": [
2100
+ {
2101
+ "id": "op-0001",
2102
+ "name": "Ordering page",
2103
+ "default": true,
2104
+ "onlineOrderingStatus": "ENABLED",
2105
+ "defaultFulfillmentType": "PICKUP",
2106
+ "fulfillmentIds": [
2107
+ "fm-pickup-0001",
2108
+ "fm-delivery-0001"
2109
+ ]
2110
+ }
2111
+ ]
2112
+ },
2113
+ "GET /fulfillment-methods/v1/fulfillment-methods": {
2114
+ "fulfillmentMethods": [
2115
+ {
2116
+ "id": "fm-pickup-0001",
2117
+ "type": "PICKUP",
2118
+ "name": "Pickup",
2119
+ "enabled": true,
2120
+ "minOrderPrice": "0",
2121
+ "pickupOptions": {
2122
+ "address": {
2123
+ "country": "US",
2124
+ "subdivision": "US-CA",
2125
+ "city": "San Francisco",
2126
+ "formattedAddress": "500 Example St, San Francisco, CA"
2127
+ }
2128
+ }
2129
+ },
2130
+ {
2131
+ "id": "fm-delivery-0001",
2132
+ "type": "DELIVERY",
2133
+ "name": "Delivery Area #1",
2134
+ "enabled": true,
2135
+ "fee": "0",
2136
+ "minOrderPrice": "0",
2137
+ "deliveryOptions": {
2138
+ "deliveryTimeInMinutes": 30
2139
+ }
2140
+ }
2141
+ ],
2142
+ "pagingMetadata": {
2143
+ "count": 2,
2144
+ "hasNext": false
2145
+ }
2146
+ },
2147
+ "GET /restaurants-operations/v1/operations/op-0001/first-available-time-slot-per-fulfillment-type": {
2148
+ "timeslotsPerFulfillmentType": [
2149
+ {
2150
+ "fulfilmentType": "DELIVERY",
2151
+ "timeSlot": {
2152
+ "startTime": "2026-10-29T11:18:00Z",
2153
+ "endTime": "2026-10-29T11:18:00Z",
2154
+ "orderSchedulingType": "ASAP"
2155
+ },
2156
+ "fulfillmentInfo": [
2157
+ {
2158
+ "fee": "0",
2159
+ "minOrderPrice": "0",
2160
+ "maxTime": 60
2161
+ }
2162
+ ]
2163
+ },
2164
+ {
2165
+ "fulfilmentType": "PICKUP",
2166
+ "timeSlot": {
2167
+ "startTime": "2026-10-29T10:48:00Z",
2168
+ "endTime": "2026-10-29T10:48:00Z",
2169
+ "orderSchedulingType": "ASAP"
2170
+ },
2171
+ "fulfillmentInfo": [
2172
+ {
2173
+ "minOrderPrice": "0",
2174
+ "maxTime": 30
2175
+ }
2176
+ ]
2177
+ }
2178
+ ]
2096
2179
  }
2097
2180
  }
package/guides/hhp.md CHANGED
@@ -195,6 +195,45 @@ and auth flows retain their existing transports and network-fixture seams.
195
195
  The studio preview adds compact, medium, and expanded presets. Existing worker state,
196
196
  action, and SDK inspection remain available through the dev drawer.
197
197
 
198
+ ## Design fidelity (`himi fidelity`)
199
+
200
+ `himi fidelity` answers one question per screen: does what shipped look like what was designed? It is repo-only for now and advisory. No CI gate reads it. Its readers are the authoring agent, before it calls an app done, and the PR reviewer.
201
+
202
+ Declare the mockup each screen was designed from in `hhp.json`:
203
+
204
+ ```json
205
+ { "version": "hhp/2", "screens": { "schedule": { "html": "screens/schedule.html", "mockup": "mockup/schedule.html" } } }
206
+ ```
207
+
208
+ A screen may also carry `params` (the navigation input a device opens it with, used by native capture, #4935) and `fidelity: { "warn": 80, "fail": 60 }`. Thresholds can also be set app-wide at the top level.
209
+
210
+ ```bash
211
+ himi fidelity --content <dir> [--screen a,b] [--variant light,dark,rtl,tablet] [--no-native] [--json] [--post-pr <n>]
212
+ ```
213
+
214
+ For each screen and variant (`light`, `dark`, `rtl`, `tablet`), the command does four things:
215
+
216
+ 1. **Captures the mockup.** It draws the page in Chromium at the variant's width. Dark mode is drawn by emulating `prefers-color-scheme`. RTL is drawn by setting `dir=rtl` on the page.
217
+ 2. **Captures the web render** from the app's recorded data, as `himi render` does by default. Native frames come through a capture seam. Until #4935 lands, the seam reports iOS and Android as skipped.
218
+ 3. **Scores mockup↔web** with ImageMagick SSIM, globally and per tile. The worst tile says where the screens differ most.
219
+ 4. **Asks a fresh model** two questions, using the repo's fidelity judge prompt. The model never ran in the session that wrote the app.
220
+ - **Design:** does WEB look like the MOCKUP? This judges the port.
221
+ - **Parity:** do IOS and ANDROID look like WEB? This judges the native renderers.
222
+
223
+ Each row gets a status:
224
+
225
+ | Status | When |
226
+ |---|---|
227
+ | **fail** | The judge answers `mismatch` to either question, or the mockup↔web score is below a `fail` threshold you set. |
228
+ | **warn** | `partial`, `cannot_tell`, a skipped surface, a mockup with no styling for the variant (`no_reference`), a missing mockup (`fidelity_mockup_missing`), or a score below `warn`. |
229
+ | **pass** | Anything else. |
230
+
231
+ The command exits 1 if any row fails. Output goes to `.himi/fidelity/<run>/`: `report.json` and one strip PNG per row. `--post-pr <n>` keeps one plain PR comment per app up to date. The comment opens with `<!-- himi-fidelity: app=<app> run=<id> -->`, and only your own comment is ever edited. It is never a review thread.
232
+
233
+ The pixel score has no default threshold, on purpose. On the repo's four HTML-first fixture apps, a blank page scores 87–95 against a mockup, while faithful ports score 69–93. Native chrome also shifts every row, so a native bug and its fix score within a point of each other. The judge is the gate, and the score points at where to look. Set thresholds only for a screen whose port is meant to be pixel-close.
234
+
235
+ Without the `claude` CLI, every verdict is `cannot_tell`, and no row passes. Outside the himalaya repo, the command refuses with `code: "fidelity_outside_repo"`.
236
+
198
237
  ## Qualification
199
238
 
200
239
  Automated tests cover v1
@@ -6,7 +6,7 @@ repurposed when human wording changes. New codes may be added; consumers must
6
6
  handle an unknown code as a failure, without parsing prose.
7
7
 
8
8
  **Rollout:** this contract is enforced for **`himi push`**, including `--only`,
9
- first, for **`himi store iap connect`**, for **`himi site member-app`**, and for the **`himi base44`** entity and function verbs. Other subcommands still have legacy failures without codes and are a
9
+ first, for **`himi store iap connect`**, for **`himi site member-app`**, for **`himi fidelity`**, and for the **`himi base44`** entity and function verbs. Other subcommands still have legacy failures without codes and are a
10
10
  follow-up migration. This is an additive change: existing `error`, `errors`,
11
11
  `message`, `hint`, status, body, and gate-specific fields stay as they were.
12
12
  Some legacy envelopes have no singular `error` or `hint`; consumers must not
@@ -394,8 +394,74 @@ On success (`ok: true`, stdout, exit 0) `capabilities[]` lists the ids the gener
394
394
  `--force` to overwrite it). A skipped file is not a failure. `orphaned[]`, when present, lists
395
395
  generated files for entities no longer declared. They are never deleted.
396
396
 
397
+ ## `himi fidelity` codes
398
+
399
+ `himi fidelity` failures print `ok: false` and `code`:
400
+
401
+ - `fidelity_rows_failed`: the run completed and at least one screen × variant row failed (a judge
402
+ `mismatch`, or a score below a threshold `hhp.json` sets). The report follows in the same
403
+ envelope. Exit 1.
404
+ - `fidelity_outside_repo`: the content directory is not inside a himalaya repo checkout, which
405
+ carries the fidelity judge; the command is repo-only for now. Exit 2.
406
+ - `fidelity_not_hhp`: the content directory has no `hhp.json`. Exit 2.
407
+ - `fidelity_unknown_screen`: `--screen` names a screen `hhp.json` does not declare. Exit 2.
408
+ - `fidelity_bad_flag`: a flag value is invalid (a missing content directory, an unknown
409
+ `--variant`, or a `--post-pr` that is not a PR number). Exit 2.
410
+ - `fidelity_post_failed`: `--post-pr` could not create or edit the PR comment. Exit 1.
411
+ - `fidelity_error`: any other failure before a report existed, such as an unreadable `hhp.json`.
412
+ Exit 1.
413
+
414
+ A row's own failure is not a command failure. A missing mockup gives that row
415
+ `error.code: "fidelity_mockup_missing"`, and a capture, score or strip that throws gives it
416
+ `error.code: "fidelity_row_failed"`. Both rows warn, and the other rows still run.
417
+
397
418
  ## Follow-ups
398
419
 
399
420
  - Migrate failure envelopes in subcommands other than `push`, keeping this contract.
400
421
  - Review/reword human messages separately; no message rewrite is part of this change.
401
422
  - Review exit-code conventions separately; no exit code changes are part of this change.
423
+
424
+
425
+ ## IAP setup and mapping controls
426
+
427
+ `himi store iap check --json` (also local MCP `himi_iap_status`) returns one read-only
428
+ report. Its top-level `code` is `ok` or `setup_incomplete`; exit status is 0 or 1. The report
429
+ contains `checks` and per-product `items[].checks`. Each check has an `id`, `state`
430
+ (`ok`, `missing`, `blocked`), stable `code`, and human-readable `fix`.
431
+
432
+ The setup checker uses the stable code vocabulary below. Consumers branch on
433
+ codes, never the fix text. Codes include:
434
+
435
+ - Registration/key: `purchases_app_missing`, `purchases_app_mismatch`, `iap_key_missing`.
436
+ - Provider/access: `provider_check_unavailable`, `provider_not_connected`, `apple_access_blocked`,
437
+ `apple_app_mismatch`, `setup_read_failed`.
438
+ - Mappings: `mapping_missing`, `mapping_inactive`, `mapping_type_mismatch`, `mapping_conflict`,
439
+ `mapping_visibility_unverified`, `mapping_not_visible`.
440
+ - Apple readiness: `apple_product_missing`, `apple_product_not_ready`, `review_screenshot_missing`,
441
+ `apple_readiness_blocked`.
442
+ - Vertical: `sale_disabled`, `item_unsupported`, `vertical_check_unavailable`.
443
+ - Binding: `config_binding_missing`, `config_binding_conflict`, `build_binding_unverified`,
444
+ `build_binding_conflict`.
445
+ - Notifications: `notification_check_unavailable`, `notification_url_mismatch`.
446
+
447
+ `ok: false` with `setup_incomplete` can contain successful findings too; a failed read does not
448
+ suppress the remaining checks. Unavailable provider/notification reads are blocked evidence,
449
+ not evidence of an absent configuration.
450
+
451
+ `himi store iap mappings` lists without writes. Changes require both `--product` (Catalog mapping
452
+ id) and `--active true|false`, plus confirmation. Missing confirmation is
453
+ `confirmation_required`; malformed inputs are `invalid_usage`. Catalog errors preserve the
454
+ existing managed failure codes. `--profile` remains the explicit legacy Apple mode for the
455
+ provisioning commands; `--managed` is optional when no profile is supplied. `--no-submit` on
456
+ managed apply still uploads the review screenshot but skips submit-for-review.
457
+
458
+ A managed-only manifest used with explicit legacy `--profile` mode returns
459
+ `credentials_unavailable` before reading any profile or key, with guidance to add
460
+ `target.profile` and `target.teamId` or continue through Catalog. Apple products whose setup
461
+ is complete remain configured while their review submission progresses; an ok setup finding
462
+ is not App Store approval.
463
+
464
+ Apple provisioning commands (`draft`, `plan`, `apply`, `status`, `screenshots`) reject explicit
465
+ legacy `--profile` combined with Catalog registration/route selectors as `invalid_usage`,
466
+ before reading inputs or credentials. `connect` retains its intentional legacy profile plus
467
+ Catalog mapping route and registration check.
@@ -4,6 +4,47 @@
4
4
  Claude Code, Cursor, Codex, VS Code — calls them as tools instead of remembering commands. Every
5
5
  tool runs the same `himi` command you would type, on the app folder already on your disk.
6
6
 
7
+ ## Apple in-app purchases
8
+
9
+ The local server exposes typed tools using the same IAP command implementations through
10
+ Catalog, with the site's owner authentication and server-held Apple keys. No tool accepts a
11
+ local Apple profile, key path, or private key. Supply the assigned `catalogRoute`; the Apple
12
+ provisioning tools also require the registered `purchasesApp` id.
13
+
14
+ | Tool | Operation | Confirmation |
15
+ | --- | --- | --- |
16
+ | `himi_iap_status` | Combined setup check: coded `ok`, `missing`, or `blocked` findings and fixes. Optional `dir`, built `plist`, and `visitorClient` provide binding and app-visibility evidence. | Read-only |
17
+ | `himi_iap_draft` | Read Wix items and Apple pricing; write a draft manifest. | No server writes |
18
+ | `himi_iap_plan` | Read Apple state; write a sealed plan for review. | No server writes |
19
+ | `himi_iap_apply` | Create/update products, have Catalog generate review screenshots, and by default submit for review. `noSubmit: true` skips submission. | `confirm: true` after user approval |
20
+ | `himi_iap_connect` | Preview registration, provider connection, mappings and optional config binding. Apply the reviewed setup with `confirm: true`. | Dry run by default |
21
+ | `himi_iap_mappings` | List mappings; supply `product` and `active` to turn one on/off. | Updates require `confirm: true` |
22
+
23
+ Draft/plan write local artifacts, so their MCP `readOnlyHint` is false. Mapping tools also
24
+ use false because they can update a mapping. Every tool that can replace files or external
25
+ state advertises `destructiveHint: true`, including mixed tools whose default is a list or dry
26
+ run. The host must obtain its own user consent; a model-supplied `confirm` is not proof of it.
27
+
28
+ Catalog generates review screenshots on the server; MCP has no local screenshot capture tool.
29
+ Managed plan/apply never read or upload local images.
30
+
31
+ IAP paths, including references inside a manifest/plan, always stay inside the
32
+ trusted workspace root. `HIMI_WORKSPACE` takes precedence; otherwise the host's workspace root
33
+ (or the server's working directory) is the boundary. Absolute paths, parent traversal and
34
+ symlinks that leave that boundary are refused before invoking the command. The hosted connector does
35
+ not gain these local tools.
36
+
37
+ Status never treats an unverified provider or Apple notification destination as ready. The
38
+ current provider contract lacks a read-only readiness method, and notification-destination
39
+ verification is not yet wired into the checker, so it reports `provider_check_unavailable` and
40
+ `notification_check_unavailable`. Managed connect can reuse a purchase key stored on the server;
41
+ if it is missing, it reports the onboarding blocker instead of opening a local key. See
42
+ [IAP products](iap-products.md#one-setup-check-and-mapping-controls).
43
+
44
+ Owner Wix authentication is separate from the publishing token minted by
45
+ `himi_login`. IAP uses the owner's Wix CLI session (`wix login`); that prerequisite is not
46
+ satisfied by signing in for draft publishing alone.
47
+
7
48
  ## Set it up
8
49
 
9
50
  **Nothing to do for a new app.** `himi init` (and `himi agent-init` in an existing app) writes the
@@ -6,8 +6,8 @@ initial price and explicit territories. It then exports a Wix→Apple mapping fo
6
6
  backend import.
7
7
 
8
8
  It is an administration workflow, not a build: it never builds, signs or bumps a version,
9
- and it runs anywhere `himi` is installed. Choose an explicit local credential profile, or
10
- managed Catalog provisioning with the site's existing Branded Apple connection. It does not run during an app build or
9
+ and it runs anywhere `himi` is installed. Catalog provisioning with the site's existing
10
+ Branded Apple connection is the default. `--profile` explicitly selects legacy local-key mode. It does not run during an app build or
11
11
  a customer checkout.
12
12
 
13
13
  It registers one-time **non-consumables**, and **consumable price tiers** for large
@@ -17,10 +17,10 @@ catalogs. Subscriptions are refused before anything reaches Apple.
17
17
 
18
18
  - **The Apple app record already exists.** This command never creates apps or accounts,
19
19
  and never accepts agreements.
20
- - **You have an App Store Connect API key for the account that owns the app.** Managing
20
+ - **For explicit legacy mode, an App Store Connect API key for the account that owns the app.** Managing
21
21
  in-app purchases needs the **Admin** or **App Manager** role (or Account Holder). A
22
22
  user's role in the web UI does not grant it to a key.
23
- - **You have a credential profile for that key** at
23
+ - **For explicit legacy mode, a credential profile for that key** at
24
24
  `~/.himalaya/store-credentials/<name>.json`. It holds identifiers plus a path to the
25
25
  `.p8`, never the key itself:
26
26
 
@@ -35,16 +35,27 @@ These key and profile prerequisites apply to direct Apple mode. There is **no am
35
35
 
36
36
  ## Managed provisioning through Catalog
37
37
 
38
- `plan`, `apply`, and `status` accept `--managed --purchases-app <registration-id>`.
38
+ Provisioning commands use managed mode when `--profile` is absent; `--managed`
39
+ remains an optional explicit spelling. `draft`, `plan`, `apply`, and `status`
40
+ read Apple through Catalog with `--purchases-app <registration-id>`. Wix catalog reads,
41
+ registration, provider connection, and mapping writes keep their existing owner-scoped services.
39
42
  They use the manifest's Wix site and the site's existing Branded Apple connection. No local
40
43
  credential profile or `.p8` is opened. `--profile` and `--managed` cannot be combined, and a
41
- Catalog refusal never falls back to direct Apple mode. Existing manifests retain their
42
- `target.profile` and `target.teamId` fields for compatibility; those fields do not select
43
- managed credentials or identify a managed plan.
44
+ Catalog refusal never falls back to direct Apple mode. For `draft`, `plan`, `apply`, `status`
45
+ and `screenshots`, `--profile` also cannot be combined with explicit `--purchases-app` or
46
+ `--catalog-route` selectors: choose one mode. Legacy `connect` intentionally accepts a Catalog
47
+ route for its Wix mappings and an optional registration id to verify. Existing manifests retain their
48
+ `target.profile` and `target.teamId` fields for compatibility; new managed drafts omit them.
49
+ Those fields do not select managed credentials or identify a managed plan. Legacy mode still
50
+ requires both fields to match its explicit profile. A managed-only target returns
51
+ `credentials_unavailable` with instructions to use Catalog or add the matching legacy identity
52
+ before any profile or key is read.
44
53
 
45
54
  Supply the assigned Catalog gateway prefix, including its
46
55
  version segment, through `--catalog-route <assigned-prefix>` or `HIMI_IAP_CATALOG_ROUTE`.
47
- There is no default. During rollout some gateway nodes can return an empty 404. The CLI
56
+ Managed Catalog and purchases setup calls require the owner’s Wix user session. Standalone
57
+ Wix catalog reads and explicit legacy profile mode retain account API-key authentication.
58
+ There is no default route. During rollout some gateway nodes can return an empty 404. The CLI
48
59
  does not retry it automatically; the owner reruns. Reads are safe to rerun, and writes
49
60
  read state before creating resources.
50
61
 
@@ -61,12 +72,18 @@ send the requested amount, currency, territory and `EXACT`/`AT_LEAST` rule, neve
61
72
  price-point id. Catalog reports `APPLIED` or `ALREADY_APPLIED`. Existing product locks,
62
73
  read-before-write checks, plan review, confirmation and local apply locking still apply.
63
74
 
64
- Managed apply finishes each configured item by uploading its App Review screenshot and calling
65
- Catalog's Product `submit-for-review`. Without `reviewScreenshot`, Catalog generates an image
66
- from the first localization's display name; no `imageUrl` is sent. If the manifest names a PNG
67
- or JPEG, the CLI uploads the checked bytes to the site's Wix Media and sends its
68
- `https://static.wixstatic.com/media/…` URL. An already complete screenshot is **reused**,
69
- even when a different image is requested; the CLI never replaces it.
75
+ For the setup check, an Apple product whose metadata is complete remains configured while its
76
+ submission is waiting for review, in review, or waiting on an app version. This reports completed
77
+ setup, not Apple approval; Catalog readiness blockers still prevent an ok finding.
78
+
79
+ Managed apply finishes each configured item by asking Catalog to generate its App Review screenshot and, by
80
+ default, calling Catalog's Product `submit-for-review`. Pass `--no-submit` to provision and generate
81
+ the screenshot on the server without submitting for review. Catalog generates the image from the first
82
+ localization's display name. Managed plan and apply ignore local `reviewScreenshot` paths:
83
+ no image is read, rendered, or uploaded from the agent's machine. An already complete
84
+ screenshot is reused without replacement. Local capture is available only through the
85
+ explicit legacy `screenshots --profile` workflow. Older managed plans that sealed a local
86
+ image are refused before requests; generate and review a new plan for server generation.
70
87
 
71
88
  Before any managed apply writes for an item, Catalog must have one active mapping for its
72
89
  expected Wix item, SKU and type. Conflicts use the existing connect codes (`sku_in_use`,
@@ -88,6 +105,52 @@ mapping reports `catalog_mapping_missing`; create/reconcile mappings with `conne
88
105
  managed submission. Other per-item failures include `catalog_screenshot_upload_failed` and
89
106
  `catalog_submit_blocked` (see [JSON codes](himi-json-output.md)).
90
107
 
108
+ ## One setup check and mapping controls
109
+
110
+ `check` combines the registration, stored purchase key, Catalog mappings, Apple product and
111
+ screenshot readiness, vertical sales rules, app visibility, and source/build binding in one
112
+ read-only report. Unlike `connect --dry-run`, it never reports the payment provider as planned
113
+ and counts that as readiness. Every finding carries `state: "ok" | "missing" | "blocked"`, a
114
+ stable `code`, and a `fix`; overall `code` is `ok` or `setup_incomplete` (exit 0 or 1).
115
+
116
+ ```sh
117
+ himi store iap check --manifest ./iap-products.json --catalog-route <assigned-prefix> \
118
+ --content . --plist /path/to/Built.app/Info.plist --visitor-client <headless-client-id> --json
119
+ himi store iap mappings --site <msid> --purchases-app <registration-id> --catalog-route <assigned-prefix> --json
120
+ himi store iap mappings --site <msid> --purchases-app <registration-id> --catalog-route <assigned-prefix> \
121
+ --product <catalog-mapping-id> --active false --yes --json
122
+ ```
123
+
124
+ `check` discovers the registration for the manifest's bundle on its site. An optional
125
+ `--purchases-app` must agree. `--content` inspects the authored config without executing it;
126
+ `--plist` checks the built Apple binding using macOS `plutil`; `--visitor-client` checks Serve
127
+ mapping visibility with a fresh anonymous visitor, not the owner's token. Missing evidence
128
+ stays blocked. A visitor check does not prove a particular signed-in member's checkout.
129
+
130
+ The current wix-iap contract exposes provider connection but no read-only provider-readiness
131
+ method, so `provider_check_unavailable` asks for verification in payment settings. Apple exposes notification URL attributes on its App resource, but this checker does not yet
132
+ compare them with a verified purchases-service destination. `notification_check_unavailable`
133
+ therefore asks for App Store Connect verification. These blockers prevent an unproven all-ready verdict. The checker is
134
+ shared with local MCP; it does not add a Serve GET route for these unavailable reads.
135
+
136
+ Mapping lists make no writes. On/off updates require confirmation and send only `active`
137
+ with Catalog's current revision, preserving the SKU, item identity, and metadata.
138
+
139
+ Managed `connect` never opens an Apple key on the Mac. It reuses an In-App Purchase key
140
+ already stored by purchases. If there is none, it reports `apple_key_missing`; an App Store
141
+ Connect API key is a different credential and cannot replace it. The purchases contract
142
+ supports encrypted key writes but not reading a key back, and Branded does not currently
143
+ provide a dedicated In-App Purchase key bridge. Provisioning that missing server key remains
144
+ a backend prerequisite. Explicit legacy `--profile` plus `--iap-key` remains available for
145
+ owner-driven onboarding. Supplying local key flags in managed mode is refused.
146
+
147
+ For a managed draft, pass the Catalog registration and route:
148
+
149
+ ```sh
150
+ himi store iap draft --site <msid> --purchases-app <registration-id> --catalog-route <assigned-prefix> \
151
+ --apple-app <apple-id> --bundle <bundle-id> --base-territory USA --out ./iap-products.json
152
+ ```
153
+
91
154
  ## Drafting the manifest from your Wix catalog
92
155
 
93
156
  You don't have to write the manifest by hand. `draft` reads the site's whole catalog —
@@ -95,7 +158,7 @@ every page of Wix Stores (Catalog V3 or V1), Online Programs and Pricing Plans
95
158
  a manifest of everything that can be sold:
96
159
 
97
160
  ```bash
98
- himi store iap draft --site <msid> --profile fit-club-owner --apple-app 6450000001 \
161
+ himi store iap draft --site <msid> --purchases-app <registration-id> --catalog-route <assigned-prefix> --apple-app 6450000001 \
99
162
  --bundle com.example.fitclub --base-territory USA --territories USA,CAN --out ./iap-products.json
100
163
  ```
101
164
 
@@ -210,7 +273,9 @@ Rules, all checked locally before any request:
210
273
  used twice, including a Wix entity mapped both directly and through a tier.
211
274
  - **Unknown keys are refused, at every level.** So is any string that looks like a key or a token.
212
275
 
213
- ## The workflow
276
+ ## Legacy workflow with a local profile
277
+
278
+ These examples explicitly select local-key mode. The managed examples above need no local Apple key.
214
279
 
215
280
  ```bash
216
281
  himi store iap draft --site <msid> --profile fit-club-owner --apple-app 6450000001 --bundle com.example.fitclub --base-territory USA --out ./iap-products.json
@@ -294,9 +359,9 @@ hosts only ever get the file's bytes, never the API key's token.
294
359
  the result. A refused image (`FAILED`) fails the step with Apple's reason. An image still
295
360
  processing (`UPLOAD_COMPLETE`) counts as uploaded.
296
361
 
297
- ### Making the review screenshots: `screenshots`
362
+ ### Legacy local review screenshots: `screenshots --profile`
298
363
 
299
- `himi store iap screenshots --manifest <file> --content <app dir> [--profile <name>]` makes each
364
+ `himi store iap screenshots --manifest <file> --content <app dir> --profile <name>` makes each
300
365
  product's review screenshot from the app's own purchase screen, so nobody has to take them on a phone:
301
366
 
302
367
  **One-time setup.** The screenshots are taken in a headless Chromium on your machine, so no phone,
@@ -327,12 +392,11 @@ before rendering anything and says so (`browser_unavailable`). A `--dry-run` doe
327
392
  (the largest-iPhone App Store size). It then sets each item's `reviewScreenshot` to that file,
328
393
  leaving the rest of the manifest as it was.
329
394
 
330
- **Apple's price** comes from App Store Connect when you pass `--profile`, a read-only call. Otherwise it is
331
- the manifest's `exact` amount. An `atLeast` item that Apple has no price for yet is skipped: run `apply`
395
+ **Apple's price** is read directly from App Store Connect with the explicit legacy `--profile`. If Apple has no observed price, the manifest's `exact` amount can be used. An `atLeast` item that Apple has no price for yet is skipped: run `apply`
332
396
  first. A price tier has no single purchase screen and is skipped too.
333
397
 
334
398
  **Other options:**
335
- - With `--profile`, a product that is live or in review keeps its screenshot: changing it there is a
399
+ - A product that is live or in review keeps its screenshot: changing it there is a
336
400
  conflict anyway.
337
401
  - An item that already names a screenshot is kept unless you pass `--force`.
338
402
  - `--only <productId,…>` limits the run; an id the manifest doesn't have is reported.
@@ -418,7 +482,8 @@ In order:
418
482
  app platform-wide: if another app holds it (another site's, or another account's), that is a
419
483
  `bundle_registered_elsewhere` conflict. Only that registration's owner can remove it; `connect`
420
484
  never does.
421
- 2. **The In-App Purchase key.** It stores `--iap-key` / `--iap-key-id` once, server-side. This is
485
+ 2. **The In-App Purchase key.** Managed mode reuses the server key, or reports `apple_key_missing`.
486
+ Legacy `--profile` mode stores `--iap-key` / `--iap-key-id` once, server-side. This is
422
487
  an App Store Connect **In-App Purchase** key (Users and Access → Integrations → In-App
423
488
  Purchase), not the App Store Connect API key `--profile` names; the service rejects that kind.
424
489
  The issuer comes from the profile. Skipped when a key is already stored.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1527.0",
3
+ "version": "0.1529.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -71,5 +71,5 @@
71
71
  "artifactId": "himalaya-cli"
72
72
  }
73
73
  },
74
- "falconPackageHash": "7d4595824e3745b02e52e9cc9c3d3b444992162a8b5792733b07a811"
74
+ "falconPackageHash": "28b98bdc9fc68f9be64914a2b88e5593f330b1f1f8e51dc6b49bba20"
75
75
  }
@@ -424,7 +424,7 @@ export default defineApp({
424
424
  // Your on-device database. It must declare every entity a worker reads or writes,
425
425
  // or those calls fail closed — keep it in step with `local_database` above.
426
426
  dataSchema: {
427
- "version": 1,
427
+ "version": 2,
428
428
  "entities": [
429
429
  {
430
430
  "name": "products",
@@ -549,6 +549,17 @@ export default defineApp({
549
549
  }
550
550
  ]
551
551
  },
552
+ {
553
+ "name": "food_orders",
554
+ "encrypted": true,
555
+ "fields": [
556
+ {
557
+ "name": "id",
558
+ "type": "string",
559
+ "required": true
560
+ }
561
+ ]
562
+ },
552
563
  {
553
564
  "name": "member_bookings",
554
565
  "encrypted": true,
@@ -133,15 +133,18 @@ export function itemLabels(value: unknown, limit = 3): string[] {
133
133
  }
134
134
 
135
135
  /** Price-variant rows ({ name, priceLine }) from the item's loose
136
- * `priceVariants.variants` payload — [] when the item has a single price. */
137
- export function itemPriceVariants(item: WixItem): Array<{ id: string; name: string; priceLine: string }> {
136
+ * `priceVariants.variants` payload — [] when the item has a single price.
137
+ * `variantId` is Wix's own id for the variant (live rows carry `variantId`; older
138
+ * fixtures `id`), "" when the payload has none — a synthetic `variant-<n>` row id is
139
+ * only for the UI and must never be sent to Wix. `price` is the decimal price. */
140
+ export function itemPriceVariants(item: WixItem): Array<{ id: string; variantId: string; name: string; priceLine: string; price: string }> {
138
141
  const raw = item as unknown as { priceVariants?: { variants?: unknown[] } };
139
142
  const variants = raw.priceVariants?.variants;
140
143
  if (!Array.isArray(variants)) return [];
141
- const rows: Array<{ id: string; name: string; priceLine: string }> = [];
144
+ const rows: Array<{ id: string; variantId: string; name: string; priceLine: string; price: string }> = [];
142
145
  for (const [index, entry] of variants.entries()) {
143
146
  if (!entry || typeof entry !== "object") continue;
144
- const node = entry as { id?: unknown; name?: unknown; priceInfo?: { price?: unknown; currency?: unknown } };
147
+ const node = entry as { id?: unknown; variantId?: unknown; name?: unknown; priceInfo?: { price?: unknown; currency?: unknown; formattedPrice?: unknown } };
145
148
  const name = typeof node.name === "string" ? cleanTitle(node.name) : "";
146
149
  const price = node.priceInfo?.price;
147
150
  if (price == null || price === "" || Number.isNaN(Number(price))) continue;
@@ -152,7 +155,11 @@ export function itemPriceVariants(item: WixItem): Array<{ id: string; name: stri
152
155
  priceLine = formatCurrency(Number(price), currency, "en");
153
156
  } catch { /* keep the bare amount */ }
154
157
  }
155
- rows.push({ id: typeof node.id === "string" && node.id ? node.id : `variant-${index}`, name: name || "Option", priceLine });
158
+ const formatted = typeof node.priceInfo?.formattedPrice === "string" ? node.priceInfo.formattedPrice.trim() : "";
159
+ if (formatted) priceLine = normalizeFormattedPrice(formatted);
160
+ const variantId = typeof node.variantId === "string" && node.variantId ? node.variantId
161
+ : typeof node.id === "string" && node.id ? node.id : "";
162
+ rows.push({ id: variantId || `variant-${index}`, variantId, name: name || "Option", priceLine, price: `${price}` });
156
163
  }
157
164
  return rows;
158
165
  }