toga-ai 1.0.998 → 1.0.1000
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.
- package/knowledge/2.0/apps/_underscore/INDEX.md +1 -1
- package/knowledge/2.0/apps/_underscore/workflows/recreated-shared-branch-stale-local-remerge.md +16 -3
- package/knowledge/2.0/apps/toga2-commerce/features/catalog-cache-freshness.md +14 -5
- package/knowledge/2.0/apps/toga2-commerce/features/inactive-item-purchase-gating.md +26 -4
- package/knowledge/2.0/apps/toga2-commerce/workflows/local-development-hosts.md +4 -2
- package/knowledge/2.0/apps/toga25-blox/INDEX.md +2 -0
- package/knowledge/2.0/apps/toga25-blox/features/old-blox-port.md +69 -0
- package/knowledge/2.0/apps/toga25-blox/workflows/moving-an-old-app-onto-toga25-blox.md +44 -0
- package/knowledge/INDEX.md +1 -1
- package/knowledge/standalone/apps/togatech/features/navv2-global-nav.md +2 -1
- package/package.json +1 -1
|
@@ -64,6 +64,6 @@
|
|
|
64
64
|
| [Users.email is a login identity — the forgot-password chain and tenant routing that depend on it](features/user-email-as-identity-and-password-reset.md) | Why `Users.email` in 2.0 is a login identity + tenant-routing key (forgot-password takeover primitive, domain routing); open before building any UI/job that edi |
|
|
65
65
|
| [USPS DPV Deliverability Verdict (is this address actually insurable/shippable?)](features/usps-dpv-deliverability.md) | How USPS DPV (Delivery Point Validation) codes decide whether an address is deliverable, and the platform Y/D/S/N mapping; open when validating an address or wh |
|
|
66
66
|
| [Refreshing a Local Dev Database from Beta (dev-sandbox)](workflows/local-db-refresh-from-beta.md) | Reset a local 2.0 dev DB from the beta/dev-sandbox host; open when a local schema is stale/broken, or after pulling `_underscore` past a migration the local sch |
|
|
67
|
-
| [Deleting a shared branch does not remove bad commits — a stale local clone merges them back](workflows/recreated-shared-branch-stale-local-remerge.md) | Why a bug "fixed" by deleting/recreating a shared branch returns
|
|
67
|
+
| [Deleting a shared branch does not remove bad commits — a stale local clone merges them back](workflows/recreated-shared-branch-stale-local-remerge.md) | Why a bug "fixed" by deleting/recreating/force-pushing a shared branch returns, and why a merged fix can vanish from one; open when asking "we already fixed thi |
|
|
68
68
|
| [Rotating Public TLS Certificates (ACM, CloudFront, ALB, Elastic Beanstalk, API Gateway)](workflows/rotating-public-tls-certificates.md) | How to replace the public TLS certificates that terminate HTTPS for TOGa front-end domains (togahub, togacommerce, togadesk, togaretail, togasupply, togaview, t |
|
|
69
69
|
| [Running a 2.0 App Locally (browser, end-to-end via api2)](workflows/running-a-2.0-app-locally.md) | Full dependency chain to run a 2.0 client app through the browser against a local api2; open when standing up the local web stack or debugging a local-only 500. |
|
package/knowledge/2.0/apps/_underscore/workflows/recreated-shared-branch-stale-local-remerge.md
CHANGED
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: workflow
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: [apeterson]
|
|
9
|
+
updated: 2026-10-08
|
|
10
|
+
owners: [apeterson, tcox]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Core/Surface.php
|
|
13
13
|
- _underscore/Model/Client/RecordFieldSetting.php
|
|
@@ -20,7 +20,7 @@ related:
|
|
|
20
20
|
- ../../dbchanges2/workflows/framework-branch-ahead-of-schema.md
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
Why a bug "fixed" by deleting/recreating a shared branch returns; open when asking "we already fixed this — why is it back?"
|
|
23
|
+
Why a bug "fixed" by deleting/recreating/force-pushing a shared branch returns, and why a merged fix can vanish from one; open when asking "we already fixed this — why is it back?" or "my fix doesn't work on sandbox".
|
|
24
24
|
|
|
25
25
|
## Summary
|
|
26
26
|
|
|
@@ -48,6 +48,19 @@ The recreated branch looks fixed, and genuinely is, for as long as it takes one
|
|
|
48
48
|
|
|
49
49
|
**Why branch deletion could never have worked here:** `a5e79448` — the commit introducing the whole affected code path — is **also** reachable from `origin/toga25-desk` and `origin/_qa-alpha`, and `toga25-desk` is merged into `_sandbox-client` routinely (e.g. `8bca0286`, 2026-08-27). Even with every stale local clone deleted, the code path returns on the next `toga25-desk` merge. **Deleting a ref cannot remove a commit another branch reaches** — the structural reason to fix forward, not to keep doing branch surgery.
|
|
50
50
|
|
|
51
|
+
**Same mechanism, other direction — a merged fix disappears (`toga2-commerce` / `_sandbox-client`, 2026-10-07).** `_sandbox-client` was force-pushed ~16:21 to `fdbdcfde` (PR #374, TRUE-82423), dropping earlier merges incl. TRUE-81382 (`3054a1e8`, `0f2076a1`, `c50bd952`). Symptom: "my fix doesn't work on sandbox" — the fix was simply not on the branch any more.
|
|
52
|
+
|
|
53
|
+
## Steps — "my fix doesn't work on the shared branch"
|
|
54
|
+
|
|
55
|
+
1. Is the fix still on the remote branch?
|
|
56
|
+
```
|
|
57
|
+
git fetch origin
|
|
58
|
+
git merge-base --is-ancestor <fix-commit> origin/<branch> && echo ON || echo GONE
|
|
59
|
+
```
|
|
60
|
+
2. Was the branch rewritten? `git reflog show origin/<branch>` — a `forced-update` line marks the rewrite.
|
|
61
|
+
3. **Do NOT push your local copy** — it still holds the old remote history and re-pollutes the branch (rule 2 below).
|
|
62
|
+
4. Delete the local branch, recreate it tracking `origin/<branch>`, re-merge only your ticket branch, then push.
|
|
63
|
+
|
|
51
64
|
## Steps — triaging "we already fixed this, why is it back?"
|
|
52
65
|
|
|
53
66
|
1. **Read the merge parents of the reconcile merge.** Names the vector precisely, one command:
|
|
@@ -6,7 +6,7 @@ project: TOGa Commerce
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-08
|
|
10
10
|
owners: ["bala", "apeterson", "tcox"]
|
|
11
11
|
files:
|
|
12
12
|
- toga2-commerce/src/lib/queryClient.ts
|
|
@@ -24,6 +24,7 @@ files:
|
|
|
24
24
|
- toga2-commerce/src/pages/Cart/viewModel/useEditAddressFromCartForm.ts
|
|
25
25
|
- toga2-commerce/src/queries/queries.ts
|
|
26
26
|
- toga2-commerce/src/hooks/useDeploymentGuard.tsx
|
|
27
|
+
- toga2-commerce/src/stores/useBundleBuilderZu.ts
|
|
27
28
|
related:
|
|
28
29
|
- ./inactive-item-purchase-gating.md
|
|
29
30
|
- ./force-logout-on-deployment.md
|
|
@@ -78,7 +79,14 @@ const shouldDehydrateQuery = (query) => {
|
|
|
78
79
|
// … persistOptions: { dehydrateOptions: { shouldDehydrateQuery } }
|
|
79
80
|
```
|
|
80
81
|
|
|
81
|
-
> **⚠
|
|
82
|
+
> **⚠ Branch state (verified 2026-10-08) — two different persistence filters exist; neither is on `_production`.**
|
|
83
|
+
> - `_production`: `buster` + `throttleTime: 0`, **no `dehydrateOptions`** — nothing is excluded from persistence.
|
|
84
|
+
> - `_beta` / `#sprint84`: the `NON_PERSISTED_QUERY_KEYS` filter above, in `App.tsx`.
|
|
85
|
+
> - `TRUE-81382` / `_sandbox-client`: `shouldPersistQuery` in `src/queries/queries.ts`, excluding `BUNDLE_QUERY_KEYS` (`fetchBundlesByPersona`, `bundleData`, `bundleImagesData`, `fetchItemDetailsViaBundle`).
|
|
86
|
+
>
|
|
87
|
+
> When these meet, merge into **one** filter holding both key lists. Confirm the branch before relying on this section.
|
|
88
|
+
|
|
89
|
+
**Bundle queries are uncached (TRUE-81382).** `bundleData`, `bundleImagesData`, `fetchBundlesByPersona` spread `BUNDLE_NO_CACHE_QUERY_OPTIONS` (`{ staleTime: 0, gcTime: 0 }`, `src/queries/queries.ts`) and are excluded by `shouldPersistQuery`. `useBundleBuilderZu` no longer persists the raw parent-bundle API payload. Cause: an inactive item was orderable from a stale persisted bundle. Merging with `e546db3d` (TRUE-81991): in `App.tsx` keep **both** `buster` and `dehydrateOptions`; in the bundle queries keep `BUNDLE_NO_CACHE_QUERY_OPTIONS` + `refetchOnWindowFocus: false` and drop the 30s/1h values.
|
|
82
90
|
|
|
83
91
|
**Why the exclusion is required:** `gcTime: 0` only evicts a query once it becomes **inactive**. An **active** query — exactly the state the item page is in while the user is looking at it — is still dehydrated and written to `localStorage`, and is rehydrated on the next load. So `gcTime: 0` alone leaves the stale answer on disk.
|
|
84
92
|
|
|
@@ -126,7 +134,7 @@ Inventory verified read-only on 2026-10-01. Every value below is a **per-query o
|
|
|
126
134
|
|---|---|
|
|
127
135
|
| **24h** | `pages/ItemsView/viewModel/useItemDetailsViewModel.ts:76` (item detail) · `pages/Filter/viewModel/useFilterViewModel.ts:106,134` (filter/search results) · `pages/Cart/viewModel/useCartViewModel.ts:310` (shipping methods) · `pages/Cart/viewModel/useEditAddressFromCartForm.ts:75` |
|
|
128
136
|
| **5 min** | `queries/queries.ts:39,46,68,78` (login / prefetch) |
|
|
129
|
-
| **30s** (+ `gcTime: 1h`) | `pages/Home/viewModel/useHomeViewModel.ts:150,175,201` · `pages/BundleView/hooks/useBundleQueryData.ts:26,42` |
|
|
137
|
+
| **30s** (+ `gcTime: 1h`) | `pages/Home/viewModel/useHomeViewModel.ts:150,175,201` · `pages/BundleView/hooks/useBundleQueryData.ts:26,42` — the **bundle** queries among these become `0`/`0` with TRUE-81382 (above) |
|
|
130
138
|
|
|
131
139
|
**Consequence — the answer to "why doesn't a price change show up":** a price or availability edit can take **up to 24 hours** to reach a shopper on the item page, and **a browser refresh does not fix it**, because the cache is persisted to `localStorage["commerce"]` and survives reload and browser restart.
|
|
132
140
|
|
|
@@ -180,15 +188,16 @@ Keep the **app default at `0`**, like supply.
|
|
|
180
188
|
- **⚠ A cart line's price never refetches.** The cart is Zustand + `localStorage`, outside React Query; no `staleTime` change touches it.
|
|
181
189
|
- **⚠ Never verify a catalogue or FIELDS change on a warm browser.** Clear `localStorage.removeItem('commerce')` or log out first. A "it didn't deploy" report is usually a rehydrated cache.
|
|
182
190
|
- **⚠ `gcTime: 0` does not stop persistence.** Active queries are still dehydrated. Exclude the key via `dehydrateOptions.shouldDehydrateQuery` as well.
|
|
183
|
-
- **⚠ Nothing is excluded from persistence on `_production`** — the `
|
|
191
|
+
- **⚠ Nothing is excluded from persistence on `_production`** (2026-10-08) — the two filters live on `_beta` and on `TRUE-81382`/`_sandbox-client`. Check the branch.
|
|
184
192
|
- **⚠ The core-parameters watcher is not a targeted invalidation** — any Core parameter change force-logs-out every user on the environment. Use per-query opt-out or `queryClient.invalidateQueries` for anything narrower.
|
|
185
193
|
- **⚠ A `queryClient.clear()` that is not awaited behind cache restoration is undone.** Always clear via `clearPersistedQueryCache()`; never call `queryClient.clear()` directly. Cancelling in-flight queries is part of the clear, not an extra.
|
|
186
194
|
- **⚠ A persister `throttleTime` above 0 can write back after a clear.** Keep it at `0`.
|
|
187
195
|
- **⚠ Gate auth on `user`, never `accessToken`** — `fetchPublicToken` writes a public token into `accessToken`. See [SSO redirect & session gating](./sso-redirect-and-session-gating.md).
|
|
188
|
-
-
|
|
196
|
+
- **`persistOptions.buster = __BUILD_ID__` is live on `_production`** (`e546db3d`): a new build drops the persisted cache on restore instead of hydrating it. It runs inside the app, so it cannot fix a browser-cached JS bundle — see [supply's persisted query cache](../../toga25-supply/features/persisted-query-cache.md#the-buster-gap).
|
|
189
197
|
- **`AuthLayout` never remounts**, so `refetchOnMount` fires once per session for queries it owns — a route-change refresh has to be wired explicitly. That interacts with everything above: a query can be both stale *and* never refetched during a session.
|
|
190
198
|
|
|
191
199
|
## Change history
|
|
200
|
+
- 2026-10-08 — Bundle queries uncached + excluded from persistence (TRUE-81382); branch map of the two persistence filters; buster marked live on `_production`. (tcox)
|
|
192
201
|
- 2026-10-01 — Corrected: the global default is already `staleTime: 0` (`QueryClient` moved to `src/lib/queryClient.ts`, `refetchOnWindowFocus: false`, persister `buster` added). Per-query 24h overrides inventoried at `file:line`; ticket scope and the post-change freshness promise (and its cart / alt-tab / first-paint limits) recorded. No code changed. (apeterson)
|
|
193
202
|
- 2026-09-22 — Causes 1 and 2 fixed: app default `staleTime: 0` + `refetchOnWindowFocus: false`, heavy hooks on 30s/1h, and all clears routed through `clearPersistedQueryCache()` with `throttleTime: 0`. Login now resets client state. TRUE-81991 (`e546db3d`). (apeterson)
|
|
194
203
|
- 2026-09-21 — Cause 3 (public-token auth gate) fixed on `TRUE-82172` and moved to its own doc; causes 1, 2, 4 still open. (tcox)
|
|
@@ -6,8 +6,8 @@ project: TOGa Commerce
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["bala"]
|
|
9
|
+
updated: 2026-10-08
|
|
10
|
+
owners: ["bala", "tcox"]
|
|
11
11
|
files:
|
|
12
12
|
- toga2-commerce/src/utils/checkIsItemPurchasable.ts
|
|
13
13
|
- toga2-commerce/src/api/fetchItemsActiveStatus.ts
|
|
@@ -18,6 +18,9 @@ files:
|
|
|
18
18
|
- toga2-commerce/src/pages/Cart/CartPage.tsx
|
|
19
19
|
- toga2-commerce/src/pages/Cart/view/cartTable/CartTableBundleItem.tsx
|
|
20
20
|
- toga2-commerce/src/api/syncSalesOrderFromApiToLocalStorage.ts
|
|
21
|
+
- toga2-commerce/src/pages/OrderDetails/hooks/useSubmitOrder.ts
|
|
22
|
+
- toga2-commerce/src/pages/OrderDetails/helpers/findUnavailableCartItems.ts
|
|
23
|
+
- toga2-commerce/src/pages/OrderDetails/api/OrderDetailsApi.ts
|
|
21
24
|
- _underscore/Model/Compass/SalesOrder.php
|
|
22
25
|
- dbchanges2/Client_Compass/2026-08-14a - AddSalesOrderInactiveStandaloneItemPreInterceptors.sql
|
|
23
26
|
- dbchanges2/Client_CompassCanada/2026-08-14a - AddSalesOrderInactiveStandaloneItemPreInterceptors.sql
|
|
@@ -33,7 +36,7 @@ related:
|
|
|
33
36
|
- ../../../clients/compass-usa/workflows/changing-a-kit-line-item.md
|
|
34
37
|
---
|
|
35
38
|
|
|
36
|
-
`Items.isActive = 0` blocks standalone purchase but means something different on kit components, so the gate keys on purchase CONTEXT not the flag; open when touching item purchasability, cart reconciliation, or the order-write interceptor.
|
|
39
|
+
`Items.isActive = 0` blocks standalone purchase but means something different on kit components, so the gate keys on purchase CONTEXT not the flag; open when touching item purchasability, cart reconciliation, the submit-time availability re-check, or the order-write interceptor.
|
|
37
40
|
|
|
38
41
|
## Summary
|
|
39
42
|
|
|
@@ -53,9 +56,11 @@ An item with **`Items.isActive = 0`** must not be viewable, addable to a cart, o
|
|
|
53
56
|
|
|
54
57
|
**Therefore the gate is on the purchase CONTEXT, never on the flag alone.** The discriminator is whether the line belongs to a kit: `isset($payload->bundleItem)` server-side, the bundle wrapper client-side. Kit lines are never evaluated.
|
|
55
58
|
|
|
59
|
+
> **⚠ Branch state (verified 2026-10-08): two separate implementations exist.** Layers 1-4 (`checkIsItemPurchasable`, `useCartReconciliation`) are on **`_beta` only** — not `_production`, not `_sandbox-client`. Layer 6 (TRUE-81382 submit re-check) was built on `_production`'s base and is on `TRUE-81382` / `_sandbox-client`. They **disagree on kit lines** (first gotcha). Reconcile them before both reach `_production`.
|
|
60
|
+
|
|
56
61
|
## How it works
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
Six layers, front to back. Each one is independently sufficient for its own entry point; together they close the paths a single check would leave open.
|
|
59
64
|
|
|
60
65
|
| # | Layer | Where |
|
|
61
66
|
|---|---|---|
|
|
@@ -64,6 +69,7 @@ Five layers, front to back. Each one is independently sufficient for its own ent
|
|
|
64
69
|
| 3 | Guard inside the cart store's `addItem` | `src/stores/useCartStoreZu.ts` |
|
|
65
70
|
| 4 | Cart reconciliation against the live catalog | `useCartReconciliation.ts`, `CartPage.tsx` |
|
|
66
71
|
| 5 | Server-side PRE interceptor on the order write | `_Model_Compass_SalesOrder::prePost` / `::prePut` |
|
|
72
|
+
| 6 | Submit-time re-fetch of every cart line (TRUE-81382) | `useSubmitOrder.ts`, `helpers/findUnavailableCartItems.ts` |
|
|
67
73
|
|
|
68
74
|
### 1–2. The helper fails CLOSED, and that is the whole point
|
|
69
75
|
|
|
@@ -93,6 +99,18 @@ Registered by `dbchanges2/Client_{Compass,CompassCanada}/2026-08-14a - AddSalesO
|
|
|
93
99
|
- **Server:** the check returns early unless `$api->app->slug === 'commerce'`. Supply, NetSuite, EDI and admin corrections must still be able to write lines referencing deactivated items. It uses the **slug**, not `Apps.id`, because **only `Core.Records` and `Core.RecordFields` carry team-maintained ids** — `Apps.id` differs per environment, so an id literal would silently scope to the wrong app somewhere.
|
|
94
100
|
- **Front end:** the new list-form item fetch and the unavailable panel are gated on the **`getItemsByPersona.isEnabled` FIELDS flag**, not on a client name. QUAD is the only tenant with it enabled, and QUAD keeps the old single-uuid persona-filtered path **byte-for-byte unchanged**. A future tenant opts in by *not* enabling that flag, with no code change.
|
|
95
101
|
|
|
102
|
+
### 6. Submit-time re-check (TRUE-81382)
|
|
103
|
+
|
|
104
|
+
Second guard for an item switched off while **already in the cart** (item/bundle pages already show "Item Not Available" on the add button). Runs only on a **new** cart submit (`viewTypeParam === "cart"`); edit-order is skipped (next section — an old deactivated line would block every edit, even an address change).
|
|
105
|
+
|
|
106
|
+
- **Standalone lines:** one `/items` list fetch by uuid **with no `isActive` filter on purpose** — inactive rows must come back to be judged.
|
|
107
|
+
- **Bundles:** `GET /bundles/<uuid>` per bundle with `bundleItems.isActive`, `bundleItems.item.isActive`, nested `childBundle` fields. Unavailable = bundle, bundle item, its item, or child bundle is off **or missing** (404/410 bundle = gone).
|
|
108
|
+
- **Block:** error toaster `These items are no longer available. Remove them from your cart to continue:` + one `Title (partNumber)` per line.
|
|
109
|
+
- **Fails closed:** check still throws after retry → toaster `We could not confirm your items are still available. Please try again.` + Sentry capture; no submit.
|
|
110
|
+
- **A missing flag is NOT inactive** (`isFlagOff` accepts only `false`/`0`/`"0"`/`"false"`). Opposite of layer 2's rule — layer 2 asks "is it purchasable?", layer 6 asks "was it switched off?".
|
|
111
|
+
|
|
112
|
+
Test (verified sandbox-client 2026-10-08): add a bundle with an active item → set `Items.isActive = 0` → submit **without refreshing** → toaster. Used `Client_Compass.Items.id 795` (`13400---ODP`) in bundle "HP Light Duty Color L/J Printer".
|
|
113
|
+
|
|
96
114
|
### Editing a placed order KEEPS an already-inactive line
|
|
97
115
|
|
|
98
116
|
Only a **newly added** inactive item is refused. An order that already contains a line whose item has since been deactivated must still be editable.
|
|
@@ -106,6 +124,7 @@ Implementation:
|
|
|
106
124
|
|
|
107
125
|
## Gotchas
|
|
108
126
|
|
|
127
|
+
- **⚠ OPEN CONFLICT — layer 6 judges kit components; this doc says that must never happen.** `findUnavailableCartItems` blocks a kit line when `bundleItems.item.isActive` is off. Most Compass kit heroes are inactive **on purpose** (Summary table: 87 of 91 primaries on dev-sandbox), so on that data layer 6 would block nearly every kit order. Before TRUE-81382 reaches `_production`: check real kit data, and likely judge kit lines only on `bundleItems.isActive` + bundle / child-bundle flags, not the component item's own flag.
|
|
109
128
|
- **⚠ `Items.isActive = 0` means two different things and nothing distinguishes them.** Never gate on the flag alone. Only a **standalone** line is judged; the kit-membership check (`bundleItem` present / absent) is what makes the flag safe to read.
|
|
110
129
|
- **⚠ A failed lookup must never empty a cart.** `fetchItemsActiveStatus` originally returned `[]` when `data.items` was missing or not an array. Reconciliation reads an empty list as *"every item I asked about is gone"* and clears the cart — so a malformed `200` walked straight past the `try`/`catch` that was supposed to guarantee a lookup failure was harmless. It now **throws**, so the caller's `catch` leaves the cart untouched; a genuine zero-row answer still returns a real empty array. Any "reconcile against the server" routine needs this distinction between *empty* and *unknown*.
|
|
111
130
|
- **⚠ Judge only the uuids you actually queried.** The reconcile `set` filtered the *current* `state.items` against results computed from a snapshot taken **before** the `await`, so a line added while the lookup was in flight was removed without ever being checked. Fixed by scoping the removal to the queried uuid set.
|
|
@@ -115,6 +134,9 @@ Implementation:
|
|
|
115
134
|
- **⚠ Do not resolve a hero (or any kit line) by `partNumber` alone.** `Client_Compass.Items` can hold the same part number twice with opposite flags — `MD7F4LL/A-S` is id **2760** (`title` set, `isActive = 0`, the row the kits actually reference) and id **2784** (`title` NULL, `isActive = 1`, unused). A part-number lookup can land on the twin that no kit uses, and the two disagree about `isActive`. Match on `BundleItems.itemId`.
|
|
116
135
|
- **The server check is one query per order, not per line** — uuids are deduped into a single `IN (…)` lookup, and the empty list returns early because `IN ()` is a MySQL syntax error.
|
|
117
136
|
|
|
137
|
+
## Change history
|
|
138
|
+
- 2026-10-08 — Added layer 6 (TRUE-81382 submit re-check), branch state, and the open kit-component conflict. (tcox)
|
|
139
|
+
|
|
118
140
|
## Related
|
|
119
141
|
|
|
120
142
|
- [catalog-cache-freshness](./catalog-cache-freshness.md)
|
|
@@ -6,8 +6,8 @@ project: TOGa Commerce
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: workflow
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: [apeterson]
|
|
9
|
+
updated: 2026-10-08
|
|
10
|
+
owners: [apeterson, tcox]
|
|
11
11
|
files:
|
|
12
12
|
- toga2-commerce/vite.config.ts
|
|
13
13
|
- toga2-commerce/package.json
|
|
@@ -32,6 +32,8 @@ The tenant is resolved from `window.location.hostname`, and api2 checks the requ
|
|
|
32
32
|
|
|
33
33
|
- **⚠ `npm run sandbox-client` dies with `getaddrinfo ENOTFOUND`** until `client.sandbox.togacommerce` has its own hosts entry.
|
|
34
34
|
- **⚠ A missing hosts entry looks like an auth bug.** The symptom is an instant redirect to `/login`, not a network error.
|
|
35
|
+
- **⚠ `npm run dev` talks to beta, not sandbox-client.** `.env.development` sets `VITE_API = https://api.beta.togahub.com/v2`. A DB error seen locally (e.g. 1054 `Unknown column 'isOpen'` on `SalesOrderItems`, 2026-10-08) is beta's schema — check the request host before reading another environment's DB or `Logs_<Tenant>.Api`.
|
|
35
36
|
|
|
36
37
|
## Change history
|
|
38
|
+
- 2026-10-08 — Added: local dev API target is beta. (tcox)
|
|
37
39
|
- 2026-09-25 — Documented after tracing "cannot sign in locally" to the Origin/`Core.Domains` check. (apeterson)
|
|
@@ -3,3 +3,5 @@
|
|
|
3
3
|
| Doc | Summary |
|
|
4
4
|
|-----|---------|
|
|
5
5
|
| [TOGa Blox 2.5 — Architecture](architecture.md) | Shared React+TS SOURCE library for the new platform apps (new platform apps first; replaces toga-blox for all apps over time); read the ADR for full detail, not |
|
|
6
|
+
| [Old blox (toga-blox) straight port inside toga25-blox](features/old-blox-port.md) | Old `@agilant/toga-blox` code copied unchanged into toga25-blox (blox-v1 layer); open before touching any old component, its checks/config, or merging Storybook |
|
|
7
|
+
| [Moving an old app from @agilant/toga-blox onto toga25-blox](workflows/moving-an-old-app-onto-toga25-blox.md) | Planned steps to switch an old app off the `@agilant/toga-blox` npm package onto toga25-blox source with zero import edits; open before moving any old app. |
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Old blox (toga-blox) straight port inside toga25-blox
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: toga25-blox
|
|
5
|
+
project: TOGa Blox 2.5
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-08
|
|
10
|
+
owners: [tcox]
|
|
11
|
+
files:
|
|
12
|
+
- toga25-blox/src/index.ts
|
|
13
|
+
- toga25-blox/src/components
|
|
14
|
+
- toga25-blox/assets
|
|
15
|
+
- toga25-blox/tsconfig.blox-v1.json
|
|
16
|
+
- toga25-blox/vitest.blox-v1.config.ts
|
|
17
|
+
- toga25-blox/types/fontawesome-pro.d.ts
|
|
18
|
+
- toga25-blox/package.json
|
|
19
|
+
related:
|
|
20
|
+
- ../architecture.md
|
|
21
|
+
- ../workflows/moving-an-old-app-onto-toga25-blox.md
|
|
22
|
+
- ../../toga-blox/architecture.md
|
|
23
|
+
---
|
|
24
|
+
Old `@agilant/toga-blox` code copied unchanged into toga25-blox (blox-v1 layer); open before touching any old component, its checks/config, or merging Storybook onto it.
|
|
25
|
+
|
|
26
|
+
## Summary
|
|
27
|
+
|
|
28
|
+
Old blox moves to toga25-blox as a **straight port, not a rewrite** (tcox, 2026-10-07). Only the delivery changes (git source, no npm); the code and its public names do not. Apps must keep compiling with zero import edits.
|
|
29
|
+
|
|
30
|
+
**Rules:**
|
|
31
|
+
- Copy old code unchanged. Never rename exports, props, signatures, or return types — old apps across the org import them. New names are additive only.
|
|
32
|
+
- No `legacy/` folder. Old code keeps its old layout.
|
|
33
|
+
- Do not fix old bugs during the port; fix them later as separate, additive changes.
|
|
34
|
+
|
|
35
|
+
A first attempt that rewrote Tooltip/Tabs/Avatar/InlineAlert in new-blox style with renamed props was thrown away for breaking these rules.
|
|
36
|
+
|
|
37
|
+
## How it works
|
|
38
|
+
|
|
39
|
+
### Layout
|
|
40
|
+
- Source = `toga-blox-npm` **`origin/_production`** (the local `_sandbox-client` checkout differed from origin in 18 files — do not copy from a local branch).
|
|
41
|
+
- Copied to the **top of `toga25-blox/src`** in the old layout: `src/index.ts` (old root barrel), `components`, `utils`, `api`, `hooks`, `templates`, `reactQuery`, `hoc`, `userHoc`, `global.css`, `main.css`, `setupTests.ts`, `global.d.ts`. New entries (`lib`, `core`, … `data-table`) sit beside them, untouched.
|
|
42
|
+
- Old `assets/` lives at the **repo root**, so old `../../../../assets/...` imports still resolve.
|
|
43
|
+
- `*.stories.*` not copied.
|
|
44
|
+
- Name clashes (old vs new `Badge`, `Toaster`, `MultiSelect`, `useTableData`) are avoided by entry: old ones only behind the old root barrel, new ones behind `@toga/blox/<entry>`.
|
|
45
|
+
- `src/components/old/` is old blox's own folder of older versions (Badge, BaseButton, BaseInput, Header, Toaster, ToggleButton). Not exported, no app imports it, but Card templates, CounterButton, GetSupport, InfoBanner, MobileMenu import it internally — keep it.
|
|
46
|
+
|
|
47
|
+
### Checks and config (old code is not held to new-blox rules)
|
|
48
|
+
- **TypeScript:** `tsconfig.json` excludes the old folders. `tsconfig.blox-v1.json` = old repo compiler settings (strict off, tests excluded) + `types/`. `npm run typecheck` runs both.
|
|
49
|
+
- **ESLint:** `eslint.config.js` ignores the old folders.
|
|
50
|
+
- **Tests:** `vitest.config.ts` excludes them. `vitest.blox-v1.config.ts` (globals + jest-dom, FA Pro aliased to `@fortawesome/free-solid-svg-icons`) runs via `npm run test:blox-v1` — **not** part of `npm test`. 13 old test files already fail in the old repo (stale: `dist/main.css` imports, wrong paths, old props); keeping them out keeps blox-gate CI green.
|
|
51
|
+
- **Dependencies:** old packages are **devDependencies only, never peers** — blox peers feed `defineTogaApp` dedupe in desk/iq/template Vite builds. Apps install them themselves (see the workflow). `uuid@^9` added explicitly — old blox imported it without declaring it.
|
|
52
|
+
- **FontAwesome Pro is not installed in blox.** blox-gate CI runs `npm ci` with no tokens by design. `types/fontawesome-pro.d.ts` stubs types for `src/utils/getFontAwesomeIcon.tsx`; apps install Pro.
|
|
53
|
+
- No `.npmrc`, no publish/`dist` config; every lockfile package resolves from public `registry.npmjs.org` — no tie to the old npm subscription.
|
|
54
|
+
- `npm run inventory` lists the old folders as entries; undocumented old exports are a warning only.
|
|
55
|
+
|
|
56
|
+
## Gotchas
|
|
57
|
+
|
|
58
|
+
- **Old `Header` (`src/components/old/Header`) renders two hamburger buttons** when `mobileLeft` and `mobileRight` are both true (git history shows it was `mobileRight ? right : left`). Ported as-is, not fixed.
|
|
59
|
+
- **The port is a snapshot of `origin/_production` taken 2026-10-07.** A fix merged into `toga-blox-npm` after that must also be applied here, or the copies drift.
|
|
60
|
+
- **Merging Storybook (branch TRUE-82044) onto the port (TRUE-81994):** expect conflicts in `package.json`, `tsconfig.json`, `scripts/inventory/inventory.mjs` (inventory.json output); regenerate `package-lock.json`. Stories for old components must import from `src/index.ts` and need Tailwind plus the FA Pro→free alias. Do not commit `storybook-static/` — build it in CI.
|
|
61
|
+
|
|
62
|
+
## Related
|
|
63
|
+
|
|
64
|
+
- [toga25-blox architecture](../architecture.md)
|
|
65
|
+
- [Moving an old app onto toga25-blox](../workflows/moving-an-old-app-onto-toga25-blox.md)
|
|
66
|
+
- [toga-blox architecture](../../toga-blox/architecture.md) — the source library.
|
|
67
|
+
|
|
68
|
+
## Change history
|
|
69
|
+
- 2026-10-08 — Port landed on branch TRUE-81994: old src copied as-is, separate blox-v1 typecheck/test configs, old packages as devDependencies (tcox)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Moving an old app from @agilant/toga-blox onto toga25-blox
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: toga25-blox
|
|
5
|
+
project: TOGa Blox 2.5
|
|
6
|
+
client: shared
|
|
7
|
+
type: workflow
|
|
8
|
+
status: draft
|
|
9
|
+
updated: 2026-10-08
|
|
10
|
+
owners: [tcox]
|
|
11
|
+
files:
|
|
12
|
+
- toga25-blox/src/index.ts
|
|
13
|
+
related:
|
|
14
|
+
- ../features/old-blox-port.md
|
|
15
|
+
- ../architecture.md
|
|
16
|
+
- ../../toga-blox/workflows/local-link-into-a-consumer-app.md
|
|
17
|
+
---
|
|
18
|
+
Planned steps to switch an old app off the `@agilant/toga-blox` npm package onto toga25-blox source with zero import edits; open before moving any old app. Not yet done for any app.
|
|
19
|
+
|
|
20
|
+
## Summary
|
|
21
|
+
|
|
22
|
+
Old-blox apps: toga25-supply, toga2-hub, toga2-view, toga2-commerce, toga2-supply, BDR, talos, togatech. Each switches by **aliasing** the old package name to the ported source ([old-blox-port](../features/old-blox-port.md)) — app code and imports do not change. Status: planned; no app moved yet — confirm each step on the first app and update this doc.
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
|
|
26
|
+
1. Alias `@agilant/toga-blox` → `../toga25-blox/src/index.ts` in the app's Vite config and tsconfig `paths`.
|
|
27
|
+
2. Alias `@agilant/toga-blox/dist/*` → `../toga25-blox/src/*` (covers ~40 deep `dist/components/...` imports).
|
|
28
|
+
3. Add to the app's own `package.json` the packages old blox used to ship as its dependencies: framer-motion, react-select, react-multi-select-component, @tanstack/react-table, @tanstack/react-virtual, react-table, dayjs, class-variance-authority, classnames, tailwind-merge, uuid, @sentry/react, react-router-dom, FontAwesome (incl. Pro — blox does not install Pro).
|
|
29
|
+
4. Dedupe `react` / `react-dom` and shared peers in the Vite config.
|
|
30
|
+
5. Amplify build: clone `toga25-blox` instead of `npm install @agilant/toga-blox@$MODE`.
|
|
31
|
+
6. Remove `@agilant/toga-blox` from `package.json`.
|
|
32
|
+
7. toga2-supply only: point the Tailwind `content` glob at `../toga25-blox/src`.
|
|
33
|
+
|
|
34
|
+
## Gotchas
|
|
35
|
+
|
|
36
|
+
- **BDR and talos are Next.js / React 19** — the Vite alias steps do not apply as written. Work out the Next alias setup separately.
|
|
37
|
+
|
|
38
|
+
## Related
|
|
39
|
+
|
|
40
|
+
- [Old blox port](../features/old-blox-port.md)
|
|
41
|
+
- [Local-linking blox into a consumer](../../toga-blox/workflows/local-link-into-a-consumer-app.md) — dedupe and React 19 lessons.
|
|
42
|
+
|
|
43
|
+
## Change history
|
|
44
|
+
- 2026-10-08 — Plan written; no app moved yet (tcox)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -32,7 +32,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
32
32
|
- **toga25-supply** (TOGa 2.5 Supply) — 23 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
|
|
33
33
|
- **toga25-iq** (TOGa IQ) — 1 doc(s) → [2.0/apps/toga25-iq/INDEX.md](2.0/apps/toga25-iq/INDEX.md)
|
|
34
34
|
- **toga25-desk** (TOGa Desk 2.5) — 1 doc(s) → [2.0/apps/toga25-desk/INDEX.md](2.0/apps/toga25-desk/INDEX.md)
|
|
35
|
-
- **toga25-blox** (TOGa Blox 2.5) —
|
|
35
|
+
- **toga25-blox** (TOGa Blox 2.5) — 3 doc(s) → [2.0/apps/toga25-blox/INDEX.md](2.0/apps/toga25-blox/INDEX.md)
|
|
36
36
|
- **toga-blox** (TOGa Blox) — 15 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
|
|
37
37
|
|
|
38
38
|
## standalone framework
|
|
@@ -6,7 +6,7 @@ project: TOGA Technology Website
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-12
|
|
10
10
|
owners: ["tcox"]
|
|
11
11
|
files:
|
|
12
12
|
- togatech/src/components/NavV2/view/NavV2.tsx
|
|
@@ -63,6 +63,7 @@ Global header in `src/components/NavV2/` (MVVM: `view/`, `viewModel/`, menu data
|
|
|
63
63
|
- **Design anchors usually do not exist on our pages.** Use a design link anchor (`#apps`, `#solutions`, `#culture`, `#mission`, `#team`, `#why-us`, …) only if that id exists on the target page; otherwise keep the `navRoutes.ts` route / `/company/*` stub. None of the phase-one anchors exist today.
|
|
64
64
|
- Between ~88px scroll and one screen, neither bar nor FAB shows. Matches the design; open question with tcox — do not "fix" without asking.
|
|
65
65
|
- `/ai-solutions` stub is no longer linked from the nav.
|
|
66
|
+
- Nav type spec (sizes, weights, spacing, line-height, colour) is `navigation-type-spec.md`, attached to ClickUp TRUE-82043. Check nav type changes against it.
|
|
66
67
|
|
|
67
68
|
## Change history
|
|
68
69
|
- 2026-10-05 — Phase-one redesign: 4 → 2 menus, `flatLinks[]`, Platforms/Company panels rebuilt, scroll reveal + `data-nav-pinned`, compact viewport, FAB visibility rules (tcox)
|
package/package.json
CHANGED