toga-ai 1.0.852 → 1.0.854

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.
@@ -16,6 +16,7 @@
16
16
  | [OneUptime external uptime monitoring for 1.0 workers](features/oneuptime-worker-uptime-monitoring.md) | Per-minute external OneUptime "Incoming Request" heartbeat from every 1.0 worker box (Degraded 3 min / Offline 5 min); open for the heartbeat push, monitor prov |
17
17
  | [Prudential: Send Shipments for the Day report (daily cron)](features/send-shipments-for-the-day.md) | Daily 9:00 PM Prudential/Dell cron emailing an Excel of every device shipped today (tracking, serial, XID, FedEx status, vendor); open for the ASN join chain an |
18
18
  | [Staples cXML Order Import (SFTP → NetSuite)](features/staples-cxml-order-import.md) | Hourly cron importing Staples cXML POs from SFTP into NetSuite Sales Orders (writes 855 ack back); open for the per-file flow, saved-search-8412 Location resolu |
19
+ | [Walmart Daily Sales Report (send_toga_walmart_report.php)](features/walmart-daily-sales-report.md) | The two Walmart sales workbooks (summary + details) built from `TOGA_Walmart` (in-store) and `TOGA_WalmartEComm` (.COM); open for the pseudo-store 1472 channel |
19
20
  | [Diagnosing frozen 1.0 worker cron check-ins (Sentry "missed" flood)](workflows/diagnosing-frozen-cron-checkins.md) | Ordered path to diagnose frozen 1.0 worker cron timestamps + a Sentry `worker1` "missed" flood; open when check-ins stall and you suspect a wedged lock. |
20
21
  | [isFulfillable Multi-Client Backfill (all togasupply clients)](workflows/isfulfillable-multi-client-backfill.md) | One-time backfill catching up `Items.isFulfillable` on existing items across all 17 togasupply clients; open when running/re-running it or deciding whether rema |
21
22
  | [Deduplicating NetSuite duplicate Items across client DBs (recursive MERGE)](workflows/netsuite-duplicate-items-dedup.md) | Per-client cleanup collapsing duplicate `Items` rows (same `partNumber`) to one canonical via recursive MERGE; open before running it — and read the catalog-bli |
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: Walmart Daily Sales Report (send_toga_walmart_report.php)
3
+ framework: "1.0"
4
+ repo: worker
5
+ project: Worker
6
+ client: walmart
7
+ type: feature
8
+ status: active
9
+ updated: 2026-09-21
10
+ owners: ["mhammontree"]
11
+ files:
12
+ - worker/crons/notifications/reports/send_toga_walmart_report.php
13
+ - worker/crons/notifications/reports/send_incomm_report.php
14
+ related:
15
+ - ../../../clients/walmart/profile.md
16
+ - ../workflows/tracing-a-worker-cron-run-in-production.md
17
+ - ../../library/features/email-test-mode-and-write-free-sends.md
18
+ ---
19
+
20
+ The two Walmart sales workbooks (summary + details) built from `TOGA_Walmart` (in-store) and `TOGA_WalmartEComm` (.COM); open for the pseudo-store 1472 channel trap, the registration-not-sale counting rule, and the unmapped-category hole.
21
+
22
+ ## Summary
23
+
24
+ `send_toga_walmart_report.php` emails two Excel workbooks:
25
+
26
+ - `WalmartTOGaSales_<date>.xlsx` — "Stores *" summary tabs (Weekly / Prior Week / YTD), categories in columns.
27
+ - `WalmartTOGaSalesDetails_<date>.xlsx` — item-level tabs, one row per paid sale.
28
+
29
+ Data comes from two databases, unioned: **`TOGA_Walmart`** (in-store) and
30
+ **`TOGA_WalmartEComm`** (online, rendered as a pseudo-store `.COM`). The report reads
31
+ `togaClientId = 6` with database `TOGA_Walmart` — **not** the `TOGA.Clients.id = 7` on the
32
+ [Walmart profile](../../../clients/walmart/profile.md). Both identifiers are live; do not
33
+ "correct" one to the other.
34
+
35
+ ## How it works
36
+
37
+ 1. `$storeNumberSql` (defined once at the top) is the shared channel-label expression, reused
38
+ by the item-level query and both store-level queries so every tab labels a sale the same way.
39
+ Named constants: `$multiChannelStoreId = 1472`, `$areaNumberNoStoreArea = '998'`,
40
+ `$areaNumberEComm = '999'`.
41
+ 2. Store-level tabs: `UNION ALL` of the `TOGA_Walmart` in-store leg and the
42
+ `TOGA_WalmartEComm` `.COM` leg, in both the "get stores" and "get data" queries. The store
43
+ list is scoped to stores that **actually sold in the reporting period**, so the ~29 dormant
44
+ stores stay off the tab.
45
+ 3. Item-level tabs: `LEFT OUTER JOIN Stores ON Stores.id = ServiceRequests.storeId`, grouped by
46
+ `$storeNumberSql` (not `Stores.id`).
47
+ 4. Rows are bucketed into columns by `$cntCategoryMapping` / `$amountCategoryMapping`.
48
+
49
+ ## Gotchas
50
+
51
+ - **`TOGA_Walmart.Stores.id = 1472` is a pseudo-store catch-all, and its own `storeNumber` is
52
+ wrong.** Every non-store sale hangs off id 1472. The real channel lives on
53
+ **`ServiceRequests.storeNumber`**, not `Stores.storeNumber`. Verified in prod: id 1472 carries
54
+ `WB` (219 rows, 2023-06-29 → 2026-09-20), `WM+` (118 rows, ended 2023-09-27), and one NULL
55
+ (2025-02-13) — while `Stores.storeNumber` for id 1472 says `WM+`. Reading the Stores row
56
+ mislabels every current sale. Store 1472 also has no `Addresses` row, so City/State render blank.
57
+ - **Never `INNER JOIN Stores` off `ServiceRequests.storeId`** — `storeId` is nullable and the
58
+ inner join silently deletes paid sales (4 lost since 2026-07-01, incl. the 2026-09-13 sale the
59
+ business flagged missing from `WalmartTOGaSalesDetails_20260915.xlsx`).
60
+ - **The report counts registrations, not sales.** `ServiceRequests` rows are created when a
61
+ customer registers the card, never when Walmart rings it up. The InComm SFTP feed is **never
62
+ imported**: `send_incomm_report.php` only downloads the day's files and emails them as
63
+ attachments — no DB write anywhere. So the report's in-store count is structurally lower than
64
+ the InComm file. Investigated under TRUE-81324; **no importer is being built** because Mike
65
+ confirmed Walmart no longer does in-store sales. Do not re-investigate this gap.
66
+ (InComm product: `TOGA_Walmart.Services` id 43558, SKU 302010001, UPC 643570190193,
67
+ `reportingCategory` 'Support'; FY26-to-date 44 units / $3,996.)
68
+ - **Open defect — unmapped categories vanish from the Stores tabs.** The category mappings cover
69
+ only Phone Repair, Tablet Repair, Set-up, Repair, Support, In-Home, Associate Performed.
70
+ Anything else lands in no column and is excluded from the Total. Verified: `TOGA_WalmartEComm`
71
+ has 181 items / $14,118 YTD with `reportingCategory = '0'` that are invisible on the report;
72
+ `TOGA_Walmart` has 6 such services. Fix for a future ticket: add an "Other" catch-all column.
73
+
74
+ ## Change history
75
+
76
+ - 2026-09-21 — Restored the in-store `TOGA_Walmart` leg on the Stores tabs (deleted by 4d8e48803 / TRUE-60157 in 2025-03), switched the item query to `LEFT OUTER JOIN Stores`, and extracted the shared `$storeNumberSql` label expression (TRUE-81324). (mhammontree)
@@ -18,6 +18,7 @@
18
18
  | [Multi-Tenant Resolution & Theming](features/multi-tenant-theming.md) | How the hostname resolves the tenant and fans out to API base URL, theme (CSS variables), and fields; open when adding a tenant or debugging wrong-theme/wrong-A |
19
19
  | [Order-submit sync sequencing (useSubmitOrder) — why these calls must not run in parallel](features/order-submit-sync-sequencing.md) | The item sync must finish before the header sync on order submit, or concurrent line deletes race a depth-3 response into an uncaught api2 500; open when touchi |
20
20
  | [Config-Driven Shipping Cost Waiver (Standard Ground free for computer kits)](features/shipping-cost-waiver-gating.md) | Config-driven cost waiver making Standard Ground free for a bare computer kit (Compass USA); open when touching shipping cost gates or the Compass free-freight |
21
+ | [SSO redirect & public-vs-user session gating (useAuthenticationFlow)](features/sso-redirect-and-session-gating.md) | How commerce decides on "/" whether a visitor is signed in, goes to SSO, or goes to /login; open for "blank page at /" or "SSO never fires" reports on any tenan |
21
22
  | [Storefront persona gating — the Home page's kit / category / item counts, and the persona switcher](features/storefront-persona-gating-and-home-counts.md) | What a storefront user sees on the Home page is decided **in the front end**, from `user._personaIds`, not by the API's ACL. |
22
23
  | [View-as another user — parked admin tokens & return-to-self](features/view-as-session-tokens.md) | How an admin impersonates another user and gets back: the delegated token pair, the parked admin pair in localStorage, and the return path. |
23
24
  | [AWS Amplify Build & Deploy (non-prod environments)](workflows/amplify-build-and-deploy.md) | How toga2-commerce builds/deploys on AWS Amplify (one dynamic amplify.yml, branch-per-env, per-env blox channel); open to deploy, stand up an env, resolve a blo |
@@ -80,7 +80,7 @@ E2E tests use **Cypress** (`cypress/`, `cypress.config.ts`).
80
80
  ## Routing (`src/routes.tsx`, createBrowserRouter)
81
81
 
82
82
  Public:
83
- - `/` → `AuthRedirect` (→ `/home` if authenticated, else renders nothing while the auth flow runs)
83
+ - `/` → `AuthRedirect` (→ `/home` if authenticated, else an `AuthLoading` spinner while the auth flow redirects to SSO or `/login` — never `null`, which is what made `/` blank)
84
84
  - `/login` → `LoginRoute` (→ `/home` if already authenticated, else `<Login/>`)
85
85
  - `/reset-password` → `ResetPasswordPage`
86
86
 
@@ -196,3 +196,4 @@ The backend (`api2`) returns the standard 2.0 envelope (`success`/`data`/`errors
196
196
  - **Tenant resolution depends on the hostname.** On `localhost` with no `*.togacommerce` host the first DNS label won't match a tenant, so config falls back (`getClientLoginFields` → COMPASS, theme → DEFAULT). Use the per-tenant dev scripts.
197
197
  - **Theme vs. fields language keys differ** — theme/field *folder* names are uppercase (`COMPASSCANADA`, `ENGLISH`/`FRENCH`) but the runtime `FIELDS` registry keys language as `en` / **`fr-CA`** (not `fr`). Any language branch must use `startsWith("fr")` — a `=== "fr"` comparison silently never matches. See the client-fields doc.
198
198
  - **Tailwind: not every `<n>px` name is a token.** `max-h-300px` does not exist (300px is only on the height/width scales) — write `max-h-[300px]`. `w-345px`, `h-300px`, `border-1` and `shadow-subMenu` do exist. A non-existent class silently renders unstyled.
199
+ - **⚠ A token in `localStorage` is not a session.** Any logged-out request mints a **public** `accessToken` via `fetchPublicToken` (`src/api/axiosInstance.ts`). Gating auth on `accessToken` made `/` render blank until the user cleared site data, on every tenant. Gate on a stored `user` JSON with a `uuid`. See [SSO redirect & session gating](features/sso-redirect-and-session-gating.md).
@@ -6,8 +6,8 @@ project: TOGa Commerce
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-09-16
10
- owners: ["bala", "apeterson"]
9
+ updated: 2026-09-21
10
+ owners: ["bala", "apeterson", "tcox"]
11
11
  files:
12
12
  - toga2-commerce/src/App.tsx
13
13
  - toga2-commerce/src/contexts/AuthContext.tsx
@@ -89,11 +89,7 @@ Verified 2026-09-03 on branch `TRUE-81610`. Read-only; none of these are fixed.
89
89
 
90
90
  This is the "it's not successfully clearing their caches" report. Supply already solved it with an `awaitRestoration()` promise built from `useIsRestoring()` (`toga25-supply/src/contexts/AuthContext.tsx:56-77`) and gates every clear behind it.
91
91
 
92
- **3. Two auth gates read two different localStorage keys → stuck on a broken login page.**
93
- - The axios request interceptor gates on **`user`** (`src/api/axiosInstance.ts:112-118`). With no `user` it calls `fetchPublicToken()`, which POSTs `/auth/public` and **writes the public token back as `accessToken`** (`src/api/axiosInstance.ts:53-64`).
94
- - But `src/hooks/useAuthenticationFlow.ts:213-217` gates on **`accessToken`** and returns early if it exists.
95
-
96
- So after a forced logout: the first API call writes a *public* `accessToken`, the auth flow sees a token, skips **both** the SSO redirect and `/login`, and the user is logged out while the app believes they are not. Supply gates on `user` — with an explicit comment at `toga25-supply/src/contexts/AuthContext.tsx:47-51`. This is the app-side twin of the blox `fetchPublicToken` gotcha already recorded in `2.0/standards/frontend.md` §22.
92
+ **3. Two auth gates read two different localStorage keys → blank page / stuck login.** ✅ **Fixed on `TRUE-82172` (2026-09-21) — not yet merged.** Moved to its own doc: [SSO redirect & session gating](./sso-redirect-and-session-gating.md). It is an auth-gating defect, not a cache defect — clearing site data only masked it.
97
93
 
98
94
  **4. The forced logout is too aggressive, and login never clears the cache.** `src/contexts/AuthContext.tsx:192-252`:
99
95
  - On **any** core-parameter change it calls `logout()` + `window.location.href = "/"` with **no notice** to the user. On an SSO client `/` re-triggers the IdP.
@@ -131,13 +127,18 @@ Keep the **app default at `0`**, like supply.
131
127
  - **⚠ Nothing is excluded from persistence on `_production`** — the `shouldDehydrateQuery` allowlist lives only on `_beta`/`#sprint84`. Check the branch.
132
128
  - **⚠ 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.
133
129
  - **⚠ A `queryClient.clear()` that is not awaited behind cache restoration is undone.** All three of commerce's clear sites have this bug.
134
- - **⚠ Gate auth on `user`, never `accessToken`** — `fetchPublicToken` writes a public token into `accessToken`.
130
+ - **⚠ Gate auth on `user`, never `accessToken`** — `fetchPublicToken` writes a public token into `accessToken`. See [SSO redirect & session gating](./sso-redirect-and-session-gating.md).
135
131
  - **A `persistOptions.buster` keyed on the build version** would fix stale data at deploy time. Commerce has a committed `amplify.yml`, so injecting `AWS_COMMIT_ID` as a build id is straightforward here (`package.json` `version` is `0.0.0` and `vite.config.ts` has no `define` block, so the id must be created first). Mechanics and the scope limit — a buster runs inside the app and can never fix a browser-cached JS bundle — are written up in [supply's persisted query cache](../../toga25-supply/features/persisted-query-cache.md#the-buster-gap). Still **not implemented**.
136
132
  - **`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.
137
133
 
134
+ ## Change history
135
+ - 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)
136
+ - 2026-09-03 — Four stacked causes pinned to `file:line`; `gcTime`-vs-`staleTime` decision recorded. (bala, apeterson)
137
+
138
138
  ## Related
139
139
 
140
140
  - [inactive-item-purchase-gating](./inactive-item-purchase-gating.md)
141
+ - [sso-redirect-and-session-gating](./sso-redirect-and-session-gating.md)
141
142
  - [architecture](../architecture.md)
142
143
  - [supply persisted-query-cache](../../toga25-supply/features/persisted-query-cache.md)
143
144
  - [supply force-logout-on-deployment](../../toga25-supply/features/force-logout-on-deployment.md)
@@ -0,0 +1,74 @@
1
+ ---
2
+ title: SSO redirect & public-vs-user session gating (useAuthenticationFlow)
3
+ framework: "2.0"
4
+ repo: toga2-commerce
5
+ project: TOGa Commerce
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-09-21
10
+ owners: [tcox]
11
+ files:
12
+ - toga2-commerce/src/hooks/useAuthenticationFlow.ts
13
+ - toga2-commerce/src/routes.tsx
14
+ - toga2-commerce/src/contexts/AuthContext.tsx
15
+ - toga2-commerce/src/api/axiosInstance.ts
16
+ related:
17
+ - ./catalog-cache-freshness.md
18
+ - ./view-as-session-tokens.md
19
+ - ../architecture.md
20
+ - ../../toga25-supply/features/sso-redirect-and-session-gating.md
21
+ - ../../../standards/frontend.md
22
+ ---
23
+
24
+ How commerce decides on "/" whether a visitor is signed in, goes to SSO, or goes to /login; open for "blank page at /" or "SSO never fires" reports on any tenant.
25
+
26
+ ## Summary
27
+
28
+ Three pieces decide it, and they must all read the same signal:
29
+
30
+ | Piece | File | Question it answers |
31
+ |---|---|---|
32
+ | axios request interceptor | `src/api/axiosInstance.ts:105-125` | Bearer a real token or a **public** one? |
33
+ | `useAuthenticationFlow` | `src/hooks/useAuthenticationFlow.ts:185-215` | Already signed in → do nothing; else SSO or `/login` |
34
+ | `AuthRedirect` (route `/`) | `src/routes.tsx` | Render `/home`, or a spinner while the flow runs |
35
+
36
+ **The only valid "is this visitor signed in?" test is a stored `user` JSON with a `uuid`** — never `localStorage.accessToken`. Shared code, so every tenant (compass, compasscanada, quad) behaves the same.
37
+
38
+ ## How it works
39
+
40
+ 1. **Logged-out requests mint a public token into `accessToken`.** `fetchPublicToken` (`axiosInstance.ts:52-64`) POSTs `/auth/public` and writes **both** `accessToken` and `refreshToken` to `localStorage`. The interceptor calls it whenever `localStorage.user` is absent — the SSO domain lookup on `/`, the login page's `/domains` and `/languages` calls, a failed SSO return. So a token in storage proves nothing.
41
+ 2. **The flow gates on the user, parsed safely** (`useAuthenticationFlow.ts:193-204`):
42
+ ```ts
43
+ const hasUserInStorage = (() => {
44
+ try {
45
+ const storedUser = localStorage.getItem("user");
46
+ return Boolean(storedUser && JSON.parse(storedUser)?.uuid);
47
+ } catch (error) { console.error("Could not read stored user:", error); return false; }
48
+ })();
49
+ if (isAuthenticated || hasUserInStorage) return;
50
+ ```
51
+ Missing, invalid, or unparsable storage counts as logged out. Same test as `AuthProvider`'s initial `isAuthenticated` (`AuthContext.tsx:73-85`) and as toga25-supply.
52
+ 3. **Otherwise it saves the post-auth redirect and runs `checkSsoAuth`** — a `singleSignOnServiceUrl` for the domain → `window.location` to the IdP; none → `/login`.
53
+ 4. **`AuthRedirect` at `/` renders `<AuthLoading/>`, never `null`,** in the not-authenticated case. A `<Navigate to="/login"/>` there was **rejected**: it fires before the SSO lookup resolves and cancels the IdP redirect for a first-time visitor.
54
+
55
+ ### Reproducing it without Cypress
56
+
57
+ - **Prod:** log in, then DevTools `localStorage.removeItem('user')`, load `/`.
58
+ - **Local:** `npm run compasscanada`; a temp page under `public/` sets `localStorage.accessToken='stale'`, removes `user`, `location.replace('/')`; dump with
59
+ `chrome.exe --headless=new --disable-extensions --user-data-dir=<temp> --virtual-time-budget=25000 --dump-dom <url>` and assert `input[name="userEmail"]` exists.
60
+ - Old code renders no login form (blank page); fixed code renders `/login`.
61
+
62
+ **Local and prod end differently for compasscanada — that is data, not a bug.** Beta has `Core.Domains` id 588 with **no** `ClientAuthentications` row, so the domains list is empty and the flow lands on `/login`; prod has `Core.Domains` id 600 → `ClientAuthentications` id 8 (type SSO, created 2026-04-06) and ends in an IdP redirect. Beta `/auth/public` also needs an allowed `Origin` header or it 401s `EN-6 "domain not permitted"` (`http://compasscanada.togacommerce:5173` is allowed).
63
+
64
+ ## Gotchas
65
+
66
+ - **⚠ A token in `localStorage` is not a session.** Gating on `accessToken` made any visitor who had touched the API look authenticated → the flow skipped **both** the SSO redirect and `/login`, `AuthRedirect` returned `null`, and `/` was **permanently blank** until the user cleared site data. Per browser profile, so Chrome and Edge fail independently. It reads as an HTTP-caching bug and is not one — prod headers are correct (HTML `no-cache/no-store`, hashed immutable JS/CSS, missing chunk 404s, no service worker). Introduced 2026-02-12 by the `hasTokenInStorage` "Fix logout" change; fixed on `TRUE-82172`.
67
+ - **⚠ Don't `Navigate` to `/login` from `AuthRedirect`.** It races the SSO lookup and kills the IdP redirect for first-time visitors. Show the spinner.
68
+ - **⚠ Open: the cross-tab `storage` handler still gates on the token.** `AuthContext.tsx:254-262` does `setIsAuthenticated(Boolean(localStorage.getItem("accessToken")))`, so a logged-out tab minting a public token can flip another logged-out tab to "authenticated" → 401s. Derive it from `user` too. **Not fixed.**
69
+ - **⚠ Open: a malformed `user` crashes the whole tree.** `AuthProvider`'s initial state does `JSON.parse(localStorage.user)` in a `try`/**`finally` with no `catch`** (`AuthContext.tsx:73-85`). **Not fixed.**
70
+ - **A 403 on `GET /notifications` during the manual repro is expected** — after `user` is removed the interceptor swaps the still-mounted app onto a public token.
71
+ - **Cypress can't cover this on a broken binary cache.** A regression spec exists untracked at `cypress/e2e/AuthFlow/staleTokenRedirect.cy.ts` (stubs `**/auth/public` + `**/domains?*`, asserts `/login`). Local Cypress 15.19.0 fails with `bad option: --smoke-test` → `npx cypress install --force`. Machine-local, not a repo problem.
72
+
73
+ ## Change history
74
+ - 2026-09-21 — Blank page at `/` fixed: gate on stored `user.uuid`, `AuthRedirect` renders the spinner instead of `null`. Branch `TRUE-82172` (`1eebdd96`, `3dc53d9a`), **not merged or deployed**. (tcox)
@@ -5,7 +5,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
5
5
  ## 1.0 framework
6
6
 
7
7
  - **library** (Library) _(framework core)_ — 26 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
8
- - **worker** (Worker) — 36 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
8
+ - **worker** (Worker) — 37 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
9
9
  - **dbchanges** (Database Changes) _(framework core)_ — 1 doc(s) → [1.0/apps/dbchanges/INDEX.md](1.0/apps/dbchanges/INDEX.md)
10
10
  - **worker1.5** (Worker 1.5) — 0 doc(s) → [1.0/apps/worker1.5/INDEX.md](1.0/apps/worker1.5/INDEX.md)
11
11
  - **togadesk** (TOGa Desk) — 13 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
@@ -31,7 +31,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
31
31
  - **talos-backend** (TOGa IQ Backend) — 1 doc(s) → [2.0/apps/talos-backend/INDEX.md](2.0/apps/talos-backend/INDEX.md)
32
32
  - **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
33
33
  - **ai-bdr** (AI-BDR) — 13 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
34
- - **toga2-commerce** (TOGa Commerce) — 24 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
34
+ - **toga2-commerce** (TOGa Commerce) — 25 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
35
35
  - **toga25-supply** (TOGa 2.5 Supply) — 21 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
36
36
  - **toga-blox** (TOGa Blox) — 14 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
37
37
  - **bdr** (BDR) — 0 doc(s) → [2.0/apps/bdr/INDEX.md](2.0/apps/bdr/INDEX.md)
@@ -17,7 +17,7 @@ project: _Underscore
17
17
  client: compass-canada
18
18
  type: profile
19
19
  status: active
20
- updated: 2026-09-17
20
+ updated: 2026-09-21
21
21
  owners: [jcardinal, bala, tcox, apeterson, ajean]
22
22
  files: []
23
23
  related:
@@ -35,6 +35,7 @@ related:
35
35
  - features/order-fulfillment-status-per-line.md
36
36
  - features/item-fulfillment-tableviews.md
37
37
  - ../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
38
+ - ../../2.0/apps/toga2-commerce/features/sso-redirect-and-session-gating.md
38
39
  - ../../2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md
39
40
  - ../../2.0/apps/_underscore/features/surface-resolver.md
40
41
  ---
@@ -117,6 +118,15 @@ to but distinct from Compass USA. Like Compass USA it spans the **2.0** commerce
117
118
  instead of **12 / 8 / 33**. Removing the hack gives them *more* access; whether Canada should get
118
119
  it is an **open decision**. See
119
120
  [Storefront persona gating](../../2.0/apps/toga2-commerce/features/storefront-persona-gating-and-home-counts.md).
121
+ - **⚠ "Blank page at `https://compasscanada.togacommerce.com/`" (reported by Compass Canada IT,
122
+ Sept 2026) is a shared auth-gating bug, not a Canada or caching problem.** A stale **public**
123
+ `accessToken` made the app think the visitor was signed in, so `/` rendered nothing until the
124
+ user cleared site data. Canada was hit hardest because the "Tech Hub is now available in Canada"
125
+ memo points everyone at `/`, and anyone who visited before the Canada SSO row existed
126
+ (`ClientAuthentications` id 8, created 2026-04-06) or landed on `/login` once already carried that
127
+ token. Same code path on Compass USA and Quad. Fixed on `TRUE-82172` (TRUE-82172 branch off
128
+ `_production`) — **not merged or deployed**. See
129
+ [SSO redirect & session gating](../../2.0/apps/toga2-commerce/features/sso-redirect-and-session-gating.md).
120
130
  - **No persona switcher here** (that is Quad-only), but Canada **is** the tenant with
121
131
  `languageSwitcher.isEnabled = true` (`fieldsConfig/clientFields/COMPASSCANADA.json`).
122
132
 
@@ -9,7 +9,7 @@ apps:
9
9
  client: walmart
10
10
  type: client-feature
11
11
  status: active
12
- updated: 2026-09-16
12
+ updated: 2026-09-21
13
13
  owners: ["mhammontree"]
14
14
  files:
15
15
  - library/app/client/walmart.php
@@ -19,6 +19,7 @@ related:
19
19
  - clients/walmart/features/domain-migration.md
20
20
  - clients/walmart/features/registration-route.md
21
21
  - clients/walmart/features/customer-email-lifecycle.md
22
+ - 1.0/apps/worker/features/walmart-daily-sales-report.md
22
23
  ---
23
24
 
24
25
  Walmart B2C tech-services tenant (client id 7); open for its identifiers, key files, and the `requireRegistrationUrl` DB rule.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.852",
3
+ "version": "1.0.854",
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",