toga-ai 1.0.1006 → 1.0.1008

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.
@@ -101,15 +101,16 @@ Limits to state to the business:
101
101
  - the effect runs in `"fields-ready"` **or** `"ready"`;
102
102
  - it uses functional `setHomeDataState(prev => …)` spreading `prev.data`, so `bundlesData` survives when the bundles, categories and items blocks all run in one pass;
103
103
  - it depends on `homeDataState.status`, not the whole object (avoids a render loop);
104
- - the view model no longer sets the `*ToDisplay` lists — `HomePage.tsx` rebuilds them in a **`useLayoutEffect`** on `data` via `handleSearchSubmit(inputValue)`, keeping the shopper's search text. A plain `useEffect` caused a one-frame "no results" flash.
104
+ - the view model no longer sets the `*ToDisplay` lists — `HomePage.tsx` rebuilds them in a **`useLayoutEffect`** on `data` via `applySearch(submittedSearchRef.current)`, keeping the shopper's **submitted** search. Not `inputValue` — the search box updates it on every keystroke, so reapplying it would filter by unsubmitted typing (CodeRabbit catch). The ref is set in `handleSearchSubmit` and cleared in `handleClearSearch`. A plain `useEffect` caused a one-frame "no results" flash.
105
105
 
106
106
  ### Item detail Add to Cart must use the refetched price (`TRUE-82427`)
107
107
 
108
- `ItemViewPage.tsx` copies `itemToAddToCart` (price, lease, Item) into `itemForCart` in an effect. It depended on `[selectedItem?.partNumber, currencySymbol]`, so a refetch with a new price for the same part updated the screen but **not** what Add to Cart sent. Fix: depend on `[selectedItem, currencySymbol]`; quantity is kept.
108
+ `ItemViewPage.tsx` copies `itemToAddToCart` (price, lease, Item) into `itemForCart` in an effect. It depended on `[selectedItem?.partNumber, currencySymbol]`, so a refetch with a new price for the same part updated the screen but **not** what Add to Cart sent. Fix: depend on `[selectedItem, currencySymbol, user?._currencyId]`; quantity is kept. `user?._currencyId` is needed because `getItemCurrencyInfo` picks the price by currency id and two currencies can share a symbol (USD and CAD are both `$`).
109
109
 
110
110
  - No loop: `selectedItem` is view-model state, and React Query structural sharing keeps its reference when data is unchanged.
111
111
  - Never add `itemToAddToCart` as a dependency — it is rebuilt every render.
112
112
  - **Open:** after Add to Cart, `handleAddItemToCart` resets `itemForCart` to price `0` / uuid `""` until `selectedItem` or currency changes; a second click in that window can add the item at price 0. Fix direction: rebuild price/lease from `itemToAddToCart` inside the reset.
113
+ - **Open:** `addItem` in `src/stores/useCartStoreZu.ts` keeps the existing cart line's fields when the same item uuid is added again and only increments quantity, so re-adding after a price change keeps the old price on the whole line (CodeRabbit, PR #376). Fix direction: refresh the item fields in the existing-uuid branch. Out of scope for `TRUE-82427` (cart is Zustand, a stated limit).
113
114
 
114
115
  ### Opting a single query out — `staleTime: 0` + `gcTime: 0` is not enough
115
116
 
@@ -135,7 +136,7 @@ const shouldDehydrateQuery = (query) => {
135
136
  >
136
137
  > When they meet, merge into **one** filter holding both key lists.
137
138
 
138
- **Bundle queries uncached — `TRUE-81382` branch only.** There, `bundleData`, `bundleImagesData`, `fetchBundlesByPersona` spread `BUNDLE_NO_CACHE_QUERY_OPTIONS` (`{ staleTime: 0, gcTime: 0 }`) and are excluded by `shouldPersistQuery`; `useBundleBuilderZu` no longer persists the raw parent-bundle payload (cause: an inactive item was orderable from a stale persisted bundle). The constant does **not** exist on `_production` or `TRUE-82427`. **Merge decision open:** `TRUE-82427` removed `refetchOnWindowFocus: false` from these queries; `TRUE-81382` keeps it — keeping it opts bundles out of focus refetch. In `App.tsx` keep **both** `buster` and `dehydrateOptions`.
139
+ **Bundle queries uncached — `TRUE-81382` branch only.** There, `bundleData`, `bundleImagesData`, `fetchBundlesByPersona` spread `BUNDLE_NO_CACHE_QUERY_OPTIONS` (`{ staleTime: 0, gcTime: 0 }`) and are excluded by `shouldPersistQuery`; `useBundleBuilderZu` no longer persists the raw parent-bundle payload (cause: an inactive item was orderable from a stale persisted bundle). The constant does **not** exist on `_production` or `TRUE-82427`. **Merging with `TRUE-82427`** (verified 2026-10-13 against `origin/TRUE-81382` `7fcecbf3`): 81382 does **not** set `refetchOnWindowFocus: false` on the bundle queries. Both branches edit the same lines in `useBundleQueryData.ts` and the Home bundles query, so git shows a conflict there. Resolve to: keep the `...BUNDLE_NO_CACHE_QUERY_OPTIONS` spread; no `refetchOnWindowFocus: false`; no `staleTime: 30_000`; no `gcTime: 1h` on the bundle queries (81382's `gcTime: 0` wins). `_sandbox-client` still carries the old `false` values (app-wide and per-query) until 82427 reaches it. In `App.tsx` keep **both** `buster` and `dehydrateOptions`.
139
140
 
140
141
  ### Decision — `gcTime` is the speed knob, `staleTime` is the correctness knob
141
142
 
@@ -182,7 +183,7 @@ Pinned 2026-09-03 on `TRUE-81610`.
182
183
  - **`AuthLayout` never remounts**, so `refetchOnMount` fires once per session for queries it owns.
183
184
 
184
185
  ## Change history
185
- - 2026-10-13 — `TRUE-82427` (`93f12265`, pending merge): per-query `staleTime` / `refetchOnWindowFocus: false` overrides removed, focus refetch on app-wide, guard's explicit opt-in removed, Home refetch fix, item-detail Add to Cart uses refetched price; four other refetch-ignoring pages logged as open. Countries + 5-min login queries left out of scope. 30s heavy-query shape superseded. (tcox)
186
+ - 2026-10-13 — `TRUE-82427` (`93f12265`, pending merge): per-query `staleTime` / `refetchOnWindowFocus: false` overrides removed, focus refetch on app-wide, guard's explicit opt-in removed, Home refetch fix, item-detail Add to Cart uses refetched price (and rebuilds on currency id change), Home refetch reapplies the submitted search (CodeRabbit fixes `61e4ffd9`, `e5eca52f`), 81382 merge resolution corrected; four other refetch-ignoring pages logged as open. Countries + 5-min login queries left out of scope. 30s heavy-query shape superseded. (tcox)
186
187
  - 2026-10-08 — Bundle queries uncached + excluded from persistence (TRUE-81382); branch map of the two persistence filters; buster live on `_production`. (tcox)
187
188
  - 2026-10-01 — Global default already `staleTime: 0`; per-query 24h overrides inventoried; ticket scope agreed. (apeterson)
188
189
  - 2026-09-22 — Causes 1 (default) and 2 fixed; login resets client state. TRUE-81991 (`e546db3d`). (apeterson)
@@ -0,0 +1,61 @@
1
+ ---
2
+ type: session
3
+ slug: TRUE-82718
4
+ title: Desk KB document red box — s3fs mount uses deleted IAM key
5
+ author: mhammontree
6
+ repos: [togadesk, toga]
7
+ framework: "1.0"
8
+ client: true
9
+ status: active
10
+ created: 2026-10-13
11
+ updated: 2026-10-13
12
+ ---
13
+
14
+ # Session: TRUE-82718
15
+ **Date:** 2026-10-13
16
+ **Project/Repo:** togadesk (1.0)
17
+ **Task:** Investigate the TOGa Desk red box when opening Knowledge Base documents (`template/pages/documents/viewdocument.php` line 9: `file_get_contents(/var/app/asifiles/knowledgebase-prod/general/1741): failed to open stream: No such file or directory`). Investigation only; the fix is handed to Srija.
18
+
19
+ ---
20
+
21
+ ## What WORKED
22
+ - **Proved the file is not missing.** Mark found `asifiles/knowledgebase-prod/general/1741` in S3. So the data is fine; the server cannot read it.
23
+ - **Found how Desk reads KB files.** `/var/app/asifiles` is an s3fs mount of bucket `asifiles` on each EB server (`.ebextensions/006_mount-s3fs.config` → `ebs/create-s3fs-credentials-file.php` writes `/etc/passwd-s3fs`, then `ebs/mount-s3fs-folders.php` builds the mount command into the EB deploy hook `appdeploy/enact/04_s3fs.sh`).
24
+ - **Root cause (confirmed by Mark in IAM).** `ebs/create-s3fs-credentials-file.php` hardcodes IAM key `AKIAJAGE…` (full id in the file). In IAM (Mark's view) only users `jhammontree` and `ses-smtp-user.20240731-170420` exist. Neither owns that key, so it was removed in the TRUE-82705 key cleanup (2026-10-12). The s3fs mount cannot log in, so every file under `/var/app/asifiles` (KB docs, ticket uploads, depot repair files) reads as "No such file".
25
+ - **Second dead key.** `ebs/check_s3fs.php` (cron every 3 min, ends a server whose mount dropped) and `ebs/register_instance_to_shared_application_load_balancer.php` hardcode the deleted key `AKIAIPDI…` (the TRUE-82705 key). So the auto-repair also fails.
26
+ - **Reviewed Srija's toga fix, commit `79336c1f01b5d632d146bc23f6debc93009b3cec`** (on toga `_production`, `_demo`, `TRUE-82714`): adds `-o iam_role=auto` to `ebs/mount-s3fs-folders.php`, and changes `ebs/create-s3fs-credentials-file.php` to drop the key and delete any old `/etc/passwd-s3fs`. toga's pre-change copies of both files are identical to togadesk's today (`diff --strip-trailing-cr` = same). So it applies to togadesk as-is.
27
+ - **Reviewed Srija's composer commit `63c5ed07f76fc1962d035bf83d7751fb773c4fd6`** (toga, TRUE-82714): adds `aws/aws-sdk-php ^3.328` (locks 3.337.3). **togadesk does NOT need it.** togadesk's `composer.json` has had `aws/aws-sdk-php ^3.337` since `f7611893` (TRUE-57575, 2025-02-14), and `composer.lock` pins 3.337.3. Deploy runs `composer install` (`.ebextensions/015_install_composer.config`), and `_/app/framework.php:17-18` loads `vendor/autoload.php`.
28
+
29
+ ## What did NOT work — DO NOT RETRY THESE
30
+ - Nothing failed. Do not look for a missing S3 object or a stale DB row: the file exists in S3, and the cause is the mount login.
31
+
32
+ ## Not tried yet (candidates for next session)
33
+ - Check that the TOGa Desk EB environment uses the same EC2 instance profile as toga, and that the role has access to `asifiles` (`s3:ListBucket` on the bucket; `GetObject`/`PutObject`/`DeleteObject`/`PutObjectAcl` on objects — ACL because the mount uses `default_acl=public-read`). If Desk's servers are in a different account than 502614707982, a bucket policy is also needed.
34
+ - Confirm toga uploads work after Srija's deploy. That proves `iam_role=auto` works with s3fs 1.84 on this old Amazon Linux 1 platform.
35
+ - On a Desk prod server after deploy: `ls /var/app/asifiles/knowledgebase-prod/general/1741`.
36
+ - togaview has the same dead keys in all four `ebs/` files and needs the same fix (separate ticket).
37
+
38
+ ## Current file state
39
+ | File | Status | Notes |
40
+ |------|--------|-------|
41
+ | (none) | unchanged | No code changed this session. togadesk is on branch `TRUE-82718` (created by Mark), clean. |
42
+
43
+ ## Decisions made
44
+ - **Srija does the togadesk fix** (Mark, 2026-10-13). She has it ready. This session made no code change.
45
+ - **Scope of the togadesk fix**, as agreed in review:
46
+ 1. Srija's s3fs change from toga `79336c1` (`mount-s3fs-folders.php` + `create-s3fs-credentials-file.php`).
47
+ 2. `ebs/check_s3fs.php`: replace the deleted key with the `WorkloadsRuntime` assume-role pattern (see `tools/ebs/check_s3fs.php`). toga has no copy of this file, so Srija's commit does not cover it.
48
+ 3. `ebs/register_instance_to_shared_application_load_balancer.php`: copy toga's fix `21b142d` (TRUE-82705).
49
+ 4. `template/pages/documents/viewdocument.php`: cast `$_GET['id']` to int before the file path and the SQL. Today `?id=../../../current/config.prod.ini` can read any server file, and the SQL is not escaped. Also show "document not available" instead of the red box.
50
+ - **Composer change not needed for togadesk** (AWS SDK already present, same version).
51
+ - **Rejected:** deleting `create-s3fs-credentials-file.php` (Srija's version keeps it and removes `/etc/passwd-s3fs`, so `006_mount-s3fs.config` keeps working). Rejected: making a new long-lived IAM key (TRUE-82705 removed all keys on purpose).
52
+ - **Order:** the role must have `asifiles` access before the togadesk deploy, or the mount still fails.
53
+
54
+ ## Blockers
55
+ - none for this session. The fix is with Srija.
56
+
57
+ ## Exact next step
58
+ > Ask Srija for her togadesk commit SHA, then review it against the 4-item scope in "Decisions made". Check especially items 2 (`check_s3fs.php`) and 4 (`viewdocument.php` int cast), which are not in her toga commit.
59
+
60
+ ---
61
+ _Saved by /session-save on 2026-10-13_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.1006",
3
+ "version": "1.0.1008",
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",