toga-ai 1.0.615 → 1.0.616

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.
@@ -5,6 +5,7 @@
5
5
  | [TOGa Commerce (toga2-commerce / commerce2-react) Architecture](architecture.md) | `toga2-commerce` (npm package name **`commerce2-react`**, product name **TOGa Commerce**) is the customer-facing **B2B commerce storefront** of the 2.0 platform | src/main.tsx, src/App.tsx, src/routes.tsx, src/contexts/AuthContext.tsx, src/contexts/helpers/getLoginSettings.ts, src/api/axiosInstance.ts, src/stores/, src/themeConfig/ThemeContext.tsx, src/fieldsConfig/index.ts, src/hooks/useAssignClientFields.ts, vite.config.ts, package.json |
6
6
  | [Cart Bundle Submission & the bundleUuid Identity Contract](features/cart-bundle-submission-and-identity.md) | How cart **bundles** (kits) are turned into `SalesOrderItems` when a cart is submitted or an existing order is edited, and the **identity-field contract** every | src/api/syncSalesOrderItemsFromLocalStorageCartToApi.ts, src/utils/formatSalesOrderBundlesFromApi.ts, src/stores/useCartStoreZu.ts, src/pages/OrderDetails/helpers/formatSalesOrderDataFromLocalStorage.ts, src/pages/OrderDetails/view/components/OrderItems.tsx |
7
7
  | [Cart Notification Emails — duplicate prevention](features/cart-notification-emails.md) | On the cart "Notifications" section a user can add CC email addresses to an order. | src/pages/Cart/CartPage.tsx, src/pages/Cart/view/cartForm/CartForm.tsx, src/stores/useEmailOptionsStore.ts, src/stores/useCartSalesQuoteZu.ts, src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts |
8
+ | [Cart Order-Total & Shipping Computation](features/cart-order-total-computation.md) | The Cart summary section (subtotal / shipping / tax / total) is **data-driven** from `cartData`. | toga2-commerce/src/pages/Cart/viewModel/useCartViewModel.ts, toga2-commerce/src/pages/Cart/CartPage.tsx, toga2-commerce/src/pages/Cart/view/cartForm/CartForm.tsx, toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/api/CartApi.ts |
8
9
  | [Cart Page — config-driven form architecture (current state + planned refactor)](features/cart-page-config-architecture.md) | The Cart page (`src/pages/Cart/`) is the most config-heavy page in `toga2-commerce`. | src/pages/Cart/CartPage.tsx, src/pages/Cart/view/cartForm/CartForm.tsx, src/pages/Cart/view/cartForm/CartFormSection.tsx, src/pages/Cart/view/cartForm/CartFormRenderer.tsx, src/pages/Cart/view/EditCart.tsx, src/pages/Cart/view/EditOrder.tsx, src/pages/Cart/viewModel/useEditOrderOrEditCartViewModel.ts, src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts, src/hooks/useAssignClientFields.ts |
9
10
  | [Catalog cache freshness — the 24h persisted query cache, and how to opt a query out of it](features/catalog-cache-freshness.md) | TOGa Commerce runs a **single `QueryClient` with a 24-hour default `staleTime`**, and persists it to **`localStorage["commerce"]`** through `PersistQueryClientP | toga2-commerce/src/App.tsx, toga2-commerce/src/contexts/AuthContext.tsx, toga2-commerce/src/pages/ItemsView/viewModel/useItemDetailsViewModel.ts |
10
11
  | [Category Tile Order (AssortmentItems.sortOrder) — merchandising a storefront category](features/category-tile-sort-order.md) | **"Move item X to the front of category Y" is a DATA change, not a code change.** The order of item tiles on a storefront category page is driven by exactly one | src/pages/Filter/api/FilterApi.ts, src/pages/Filter/viewModel/useFilterViewModel.ts, api2/Component/Api/V2/V2.php, toga2-supply/src/pages/Items/api/itemsApi.ts |
@@ -14,6 +15,7 @@
14
15
  | [Inactive-item purchase gating (standalone lines only — kits are exempt by design)](features/inactive-item-purchase-gating.md) | An item with **`Items.isActive = 0`** must not be viewable, addable to a cart, or orderable **as a standalone line** on the storefront — but the **same flag is | toga2-commerce/src/utils/checkIsItemPurchasable.ts, toga2-commerce/src/api/fetchItemsActiveStatus.ts, toga2-commerce/src/hooks/useCartReconciliation.ts, toga2-commerce/src/stores/useCartStoreZu.ts, toga2-commerce/src/pages/ItemsView/api/ItemsApi.ts, toga2-commerce/src/pages/ItemsView/viewModel/useItemDetailsViewModel.ts, toga2-commerce/src/pages/ItemsView/ItemViewPage.tsx, toga2-commerce/src/components/AuthLayout/AuthLayout.tsx, toga2-commerce/src/pages/Cart/CartPage.tsx, toga2-commerce/src/pages/Cart/view/cartTable/CartTableBundleItem.tsx, toga2-commerce/src/api/syncSalesOrderFromApiToLocalStorage.ts, _underscore/Model/Compass/SalesOrder.php, dbchanges2/Client_Compass/2026-08-14a - AddSalesOrderInactiveStandaloneItemPreInterceptors.sql, dbchanges2/Client_CompassCanada/2026-08-14a - AddSalesOrderInactiveStandaloneItemPreInterceptors.sql |
15
16
  | [Multi-Tenant Resolution & Theming](features/multi-tenant-theming.md) | `toga2-commerce` serves multiple clients from one codebase. | src/themeConfig/themes.json, src/themeConfig/ThemeContext.tsx, src/themeConfig/types.ts, src/components/ThemeSwitcher/ThemeSwitcher.tsx, src/components/AuthLayout/AuthLayout.tsx, src/api/axiosInstance.ts, src/contexts/AuthContext.tsx, tailwind.config.js |
16
17
  | [Order-submit sync sequencing (useSubmitOrder) — why these calls must not run in parallel](features/order-submit-sync-sequencing.md) | Submitting an order from the cart fires **two independent sync routines** — one for the sales-order header (`syncSalesOrderData`) and one for the line items (`s | toga2-commerce/src/pages/OrderDetails/hooks/useSubmitOrder.ts, toga2-commerce/src/api/syncSalesOrdersDataFromLocalStorageCartToApi.ts, toga2-commerce/src/api/syncSalesOrderItemsFromLocalStorageCartToApi.ts |
18
+ | [Config-Driven Shipping Cost Waiver (Standard Ground free for computer kits)](features/shipping-cost-waiver-gating.md) | On the toga2-commerce **Cart** page, a shipping option's **cost** can be waived by config using the same `PrimaryItemShippingRule` vocabulary that drives expedi | toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/CartPage.tsx |
17
19
  | [AWS Amplify Build & Deploy (non-prod environments)](workflows/amplify-build-and-deploy.md) | How `toga2-commerce` (React + Vite, "commerce2-react") builds and deploys on **AWS Amplify**. | toga2-commerce/amplify.yml, toga2-commerce/.gitattributes, toga2-commerce/package.json, toga2-commerce/.github/workflows/sync-stage-environments.yml |
18
20
  | [Cart e2e — Cypress conventions & harness (toga2-commerce)](workflows/cypress-testing.md) | The Cypress **e2e** convention set for `toga2-commerce`, and the first **active** e2e coverage for the **Cart** page (`cartV2.cy.ts`, slice 1 — 12 tests, verifi | toga2-commerce/cypress/e2e/cartPage/cartV2.cy.ts, toga2-commerce/cypress/fixtures/cart/fetchSingleUserAdmin.json, toga2-commerce/cypress/fixtures/cart/fetchLocations.json, toga2-commerce/cypress/fixtures/cart/fetchUserShippingMethods.json, toga2-commerce/cypress/support/commands.ts, toga2-commerce/cypress/support/e2e.ts, toga2-commerce/src/pages/Cart/CartPage.tsx, toga2-commerce/src/pages/Cart/view/cartForm/CartForm.tsx, toga2-commerce/src/pages/Cart/view/cartForm/CartFormSection.tsx, toga2-commerce/src/pages/Cart/view/cartTable/CartContentsTable.tsx, toga2-commerce/src/pages/Cart/view/cartTable/CartTableItem.tsx, toga2-commerce/src/components/Inputs/AdvancedInput.tsx, toga2-commerce/src/components/BaseButton/BaseButton.tsx |
19
21
  | [Diagnosing ERR_HTTP2_PROTOCOL_ERROR (one client fails, everyone else is fine)](workflows/http2-protocol-error-diagnosis.md) | When a Chromium browser (Chrome / Edge) shows **`ERR_HTTP2_PROTOCOL_ERROR`** loading a `*.togacommerce.com` tenant for **one client/network but works for the TO | |
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: Cart Order-Total & Shipping Computation
3
+ framework: "2.0"
4
+ repo: toga2-commerce
5
+ project: TOGa Commerce
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-08-19
10
+ owners: [apeterson]
11
+ files:
12
+ - toga2-commerce/src/pages/Cart/viewModel/useCartViewModel.ts
13
+ - toga2-commerce/src/pages/Cart/CartPage.tsx
14
+ - toga2-commerce/src/pages/Cart/view/cartForm/CartForm.tsx
15
+ - toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts
16
+ - toga2-commerce/src/pages/Cart/api/CartApi.ts
17
+ related:
18
+ - 2.0/apps/toga2-commerce/features/shipping-cost-waiver-gating.md
19
+ - 2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
20
+ - 2.0/apps/toga2-commerce/features/cart-page-config-architecture.md
21
+ ---
22
+
23
+ ## Summary
24
+ The Cart summary section (subtotal / shipping / tax / total) is **data-driven** from
25
+ `cartData`. `cartData.total` is computed in `useCartViewModel` as `subtotal + tax + shipping`,
26
+ where `shipping` is read from `salesOrder.shipping` in the zustand cart/sales-quote store —
27
+ **not** directly from the selected dropdown option. A `CartPage` effect is the bridge: it
28
+ watches the selected shipping method, looks up the matching fetched option, reads its `c_cost`,
29
+ applies waiver cost-gates, and calls `setShipping()` to write `salesOrder.shipping`.
30
+
31
+ ## How it works
32
+ 1. `CartForm.tsx` renders the summary purely from `cartData` (subtotal/shipping/tax/total).
33
+ 2. `useCartViewModel.ts` computes `cartData.total = subtotal + tax + shipping`, with `shipping`
34
+ derived from `salesOrder.shipping` (zustand store).
35
+ 3. `CartPage.tsx` has an effect watching the selected `shippingMethod`: it finds the matching
36
+ fetched option, reads `c_cost`, applies waiver cost-gates (see
37
+ [shipping-cost-waiver-gating](shipping-cost-waiver-gating.md)), then `setShipping()` writes
38
+ `salesOrder.shipping`. So the dropdown never feeds the total directly — it flows through the
39
+ store.
40
+
41
+ ## Gotchas
42
+ - **`c_cost` is ACL-gated per tenant, and a missing grant silently zeroes shipping.** Only the
43
+ **Compass USA** CARTPAGE configs request fields `["uuid","name","c_cost"]` in
44
+ `fetchShippingMethod`. **Compass Canada** and **Quad** request only `["uuid","name"]`, so
45
+ their fetched options carry no `c_cost`; `Number(undefined) → NaN → "0"`, and shipping falls
46
+ back to `"0"` with no error. This is a **latent gap** for those tenants — if they are meant to
47
+ charge shipping, their CARTPAGE `fetchShippingMethod` field list must include `c_cost`.
48
+ - **Shipping lives in the store, not the dropdown.** Reading the selected option's cost alone
49
+ will not tell you the order total — always trace through `setShipping()` →
50
+ `salesOrder.shipping` → `useCartViewModel`.
51
+
52
+ ## Change history
53
+ - 2026-08-19 — Documented the previously-undocumented cart total/shipping computation path
54
+ while fixing the Compass USA Standard Ground waiver. Recorded the `c_cost` ACL-gating latent
55
+ gap for Compass Canada and Quad (their fetched options have no `c_cost`, so shipping silently
56
+ resolves to "0"). (apeterson)
57
+ </content>
@@ -6,8 +6,8 @@ project: TOGa Commerce
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-07-27
10
- owners: [tcox]
9
+ updated: 2026-08-19
10
+ owners: [tcox, apeterson]
11
11
  files:
12
12
  - toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts
13
13
  - toga2-commerce/src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts
@@ -103,6 +103,10 @@ behavior is expressed in config, not in code branches.
103
103
  on that doc's slice-2 work-list.
104
104
 
105
105
  ## Change history
106
+ - 2026-08-19 — No change to expedited visibility. Noted that the shared shipping-rule type
107
+ gained an optional `requireNoOtherItemsInKit` flag (+ `bundleHasOtherItems()` helper) used by
108
+ the separate Standard Ground cost waiver — see
109
+ [shipping-cost-waiver-gating](shipping-cost-waiver-gating.md). (apeterson)
106
110
  - 2026-07-27 — No behavior change. Noted that a cart Cypress e2e harness now exists and a
107
111
  gating + guardrail-modal spec is feasible (the `cart/fetchUserShippingMethods.json` fixture
108
112
  already ships the gated names with no `c_cost`); it is on the slice-2 work-list. Linked
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: Config-Driven Shipping Cost Waiver (Standard Ground free for computer kits)
3
+ framework: "2.0"
4
+ repo: toga2-commerce
5
+ project: TOGa Commerce
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-08-19
10
+ owners: [apeterson]
11
+ files:
12
+ - toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts
13
+ - toga2-commerce/src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts
14
+ - toga2-commerce/src/pages/Cart/CartPage.tsx
15
+ related:
16
+ - 2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
17
+ - 2.0/apps/toga2-commerce/features/cart-order-total-computation.md
18
+ - ../../../../clients/compass-usa/profile.md
19
+ ---
20
+
21
+ ## Summary
22
+ On the toga2-commerce **Cart** page, a shipping option's **cost** can be waived by config
23
+ using the same `PrimaryItemShippingRule` vocabulary that drives expedited-option visibility.
24
+ The **Compass USA** carts attach a cost gate `STANDARD_GROUND_FREE_FOR_COMPUTER_KITS` to the
25
+ *Shipping Method* field so that **Standard Ground** ships free for a bare computer kit. The
26
+ waiver is config-driven (no `if (clientSlug === ...)` branching) and is referenced only by the
27
+ four Compass USA role configs (USER/ADMIN/MANAGER/SUPERUSER).
28
+
29
+ ## Key files / entry points
30
+ - `src/pages/Cart/helpers/shippingOptionGates.ts` — `PrimaryItemShippingRule` type,
31
+ `evaluateShippingOptionRule`, and the `bundleHasOtherItems()` helper.
32
+ - `src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts` — the
33
+ `STANDARD_GROUND_FREE_FOR_COMPUTER_KITS` gate constant (primary item
34
+ `itemCategory.name === "COMPUTERS"`, with `requireNoOtherItemsInKit: true`).
35
+ - `src/pages/Cart/CartPage.tsx` — the effect that reads the selected option's `c_cost` and
36
+ applies waiver cost-gates before calling `setShipping()` (see
37
+ [cart-order-total-computation](cart-order-total-computation.md)).
38
+
39
+ ## How it works
40
+ 1. A cost gate matches a bundle when its **primary item** (`bundleItemGroup.slug === "primary"`)
41
+ satisfies the `{ item, path, operator, value }` rule — here
42
+ `item.itemCategory.name === "COMPUTERS"`.
43
+ 2. The **optional `requireNoOtherItemsInKit` flag** on `PrimaryItemShippingRule` narrows the
44
+ match: when set, the bundle qualifies only if the primary item matches **and** the kit has
45
+ no other items. `bundleHasOtherItems()` returns true when `bundleProgressContents` contains
46
+ any entry whose `bundleItemGroup.slug !== "primary"` (fees are already excluded from
47
+ `bundleProgressContents` upstream).
48
+ 3. `evaluateShippingOptionRule` qualifies a bundle only when the primary item matches AND, if
49
+ `requireNoOtherItemsInKit` is set, the kit is bare. Existing cart-wide "any qualifying
50
+ bundle" semantics for multi-bundle carts are preserved.
51
+ 4. When the selected method qualifies, the effect in `CartPage` waives its `c_cost` to 0 before
52
+ writing `salesOrder.shipping`.
53
+
54
+ Resulting Compass USA behavior: bare computer kit (primary computer only) → Standard Ground
55
+ free; computer kit **with** other items → charged $10; all non-computer kits → charged;
56
+ expedited methods unchanged (still priced).
57
+
58
+ ## Gotchas
59
+ - **The waiver only means what the flag says.** Before this fix the gate had no
60
+ `requireNoOtherItemsInKit`, so Standard Ground (the default selection) was waived for **any**
61
+ cart whose primary bundle item was in `COMPUTERS` — computer kits loaded at $0 shipping and
62
+ stayed there regardless of what else was in the kit. Always set `requireNoOtherItemsInKit`
63
+ when a waiver is meant only for a bare kit.
64
+ - **`bundleProgressContents` is the source of truth for "other items"** — it already excludes
65
+ fees, so a fee line does not make a kit count as "having other items." If that upstream
66
+ exclusion ever changes, the waiver's narrowing changes with it.
67
+ - **Waiver correctness depends on `COMPUTERS` categorization**, same as the expedited gate —
68
+ a computer kit mis-categorized in the catalog will neither waive nor gate.
69
+
70
+ ## Change history
71
+ - 2026-08-19 — Fixed an over-broad Standard Ground waiver for Compass USA computer-kit carts:
72
+ added the optional `requireNoOtherItemsInKit` flag on `PrimaryItemShippingRule` and the
73
+ `bundleHasOtherItems()` helper, and set the flag on
74
+ `STANDARD_GROUND_FREE_FOR_COMPUTER_KITS`. Bare computer kits now ship free; kits with other
75
+ items are charged. Config-driven, Compass USA only, no client branching. No test harness in
76
+ the repo (no vitest/jest); verified by review. (apeterson)
77
+ </content>
78
+ </invoke>
@@ -29,7 +29,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
29
29
  - **talos** (TOGa IQ) — 7 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
30
30
  - **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
31
31
  - **ai-bdr** (AI-BDR) — 9 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
32
- - **toga2-commerce** (TOGa Commerce) — 17 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
32
+ - **toga2-commerce** (TOGa Commerce) — 19 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
33
33
  - **toga25-supply** (TOGa 2.5 Supply) — 11 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
34
34
  - **toga-blox** (TOGa Blox) — 9 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
35
35
  - **bdr** (BDR) — 0 doc(s) → [2.0/apps/bdr/INDEX.md](2.0/apps/bdr/INDEX.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.615",
3
+ "version": "1.0.616",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",