toga-ai 1.0.1000 → 1.0.1002
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/sessions/2026-10-12-odp-as2-aws-key-outage-bala.md +67 -0
- package/knowledge/standalone/apps/claude/workflows/knowledge-publish-pipeline.md +4 -2
- package/knowledge/standalone/apps/togatech/INDEX.md +1 -1
- package/knowledge/standalone/apps/togatech/features/navv2-global-nav.md +22 -2
- package/knowledge/standalone/apps/togatech/features/talos-product-page.md +12 -3
- package/knowledge/standalone/apps/togatech/workflows/local-dev-and-headless-verification.md +5 -2
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: session
|
|
3
|
+
slug: odp-as2-aws-key-outage
|
|
4
|
+
title: Office Depot POs not importing (AS2 Lambda stopped, then AWS key deleted)
|
|
5
|
+
author: bala
|
|
6
|
+
repos: [worker, library]
|
|
7
|
+
framework: "1.0"
|
|
8
|
+
client: compass-usa
|
|
9
|
+
status: active
|
|
10
|
+
created: 2026-10-12
|
|
11
|
+
updated: 2026-10-12
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session: odp-as2-aws-key-outage
|
|
15
|
+
**Date:** 2026-10-12
|
|
16
|
+
**Project/Repo:** worker + library (1.0)
|
|
17
|
+
**Task:** Find why Compass Office Depot vendor POs stopped coming into Supply after Sat 2026-10-10 07:23, recover the stuck POs, and replace the deleted AWS key that the 1.0 Office Depot crons depend on.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What WORKED
|
|
22
|
+
- Found the real inbound path. Office Depot sends over AS2 to AWS Transfer server `s-54dad64b145d417a9` (toga-legacy 502614707982, us-west-2), agreement `a-904effd552db4348b` "OfficeDepotProd". Files land in `s3://agilant-as2/processed/<uuid>.<msgid>.net`. An S3 event rule (prefix `processed/`, Put+Post) calls Lambda `rename_edi_files`, which moves `*.net` to `s3://agilant-as2/OfficeDepot/`. Cron `worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php` imports from there.
|
|
23
|
+
- Proved the Lambda stopped. Its CloudWatch log ends at Sat 2026-10-10 07:29 CDT. The Invocations metric was 285-753 per weekday, then 0. Errors and Throttles were 0.
|
|
24
|
+
- Moved the stuck files by hand (`aws s3 mv` from `processed/` to `OfficeDepot/`, only `.net` files after 2026-10-10 12:30 UTC). Moved 67 files with 0 failures at about 13:20 CDT. 3a imported all 52 stuck POs into prod `Client_Compass.PurchaseOrders` (0 over-quantity rejects), and later 58 including new arrivals. Cron 5 pushed 57 of 58 to NetSuite by 14:42. The last one, SA138891 (ODP PO 42185598-1214), was eligible but not yet picked at that time.
|
|
25
|
+
- At 15:37 CDT, moved 39 more files to `OfficeDepot/` with `scripts/odp_move_stuck_as2_files.sh --once`. They are waiting there and CANNOT import until AWS access is restored (see Blockers).
|
|
26
|
+
- Wrote the stop-gap cron `worker/crons/toga2/compass/workflow/move_office_depot_as2_files_to_import_folder.php` plus a `*/5` entry in `worker/schedules/cron.worker.sync.json`. php-reviewer found nothing blocking, and the null-list throw was added after review. Per capture, it is committed in worker `_production` as `b3f57866`.
|
|
27
|
+
- Found why the cron fails on the box: at 15:00:28-15:00:31 CDT Jeff deleted IAM user `jcardinal` and its access key. That is the key hardcoded in `library/app/cloud.php` (static props, the `$preCommands` export, and the SDK `credentials` arrays). Error on the box: `InvalidAccessKeyId ... The AWS Access Key Id you provided does not exist in our records.`
|
|
28
|
+
- Confirmed 1.0 email still sends after 15:00. Legacy `Logs.Emails` shows 249 successful sends from 15:00 to 15:38, so SES SMTP was not affected.
|
|
29
|
+
|
|
30
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
31
|
+
- Re-applying the same S3 event config (`aws s3api put-bucket-notification-configuration` on `agilant-as2`) failed with `InvalidArgument: Unable to validate the following destination configurations`. That proves S3 cannot call the Lambda. Nothing was changed.
|
|
32
|
+
- `aws lambda add-permission` on `rename_edi_files` failed with `AccessDeniedException`. Role `GoAgilant-Developers` has no Lambda rights. `get-function-configuration`, `get-function` and `list-functions` are also denied.
|
|
33
|
+
- Running `php 3a_import_office_depot_purchase_orders.php` by hand on the worker box exits silently. This is expected: the scheduled run (PID 1364) was already running and `cronInitialization` exits when another copy runs.
|
|
34
|
+
- Asking Jeff for a replacement key: refused. The key leaked via GitHub configs and an attacker used it on 2026-10-10. AWS suspended services (Lambda among them). The company is on SSO and will not issue long-lived keys again.
|
|
35
|
+
- The Transfer Family workflow `w-f8951fd4252a5b890` "OfficeDepot" (COPY to `OfficeDepot/`) is NOT the live path. It has no executions in a year of server logs.
|
|
36
|
+
|
|
37
|
+
## Not tried yet (candidates for next session)
|
|
38
|
+
- Ask Jeff to create a dedicated instance role for EB env `agilant-worker` (instance `i-0208ceac48ce0f343`, currently on the shared `aws-elasticbeanstalk-ec2-role`). Keep the 3 EB managed policies. Add S3 on `agilant-as2` (+ `asifiles`), `transfer:StartFileTransfer` on connectors `c-0fc19b6317af42f69` (ODP) and `c-392be4fc627a47a19` (Canon), logs `DescribeLogStreams/CreateLogStream/PutLogEvents` on `AS2-*`, `sqs:SendMessage` on the 2.0 worker queue (account 654654170868), and `ec2:AssociateAddress/CreateTags` for the worker EIP. NO `ssm:PutParameter`.
|
|
39
|
+
- Change `library/app/cloud.php` to the default AWS credential chain: remove the static key props, make `$preCommands` only `unset` lines, and drop the `credentials` arrays from the 5 SDK clients. Remove keys from the worker/tools config ini files and `worker/ebs/cron.worker.php`. Run php-reviewer + cso.
|
|
40
|
+
- Fix shell injection in `App_Cloud::copyFileToS3` (`library/app/cloud.php` ~377). It is reached from `togaview/mvc/ticket/post.php` ~137-160 with the upload filename unescaped. Use `escapeshellarg()` or the SDK.
|
|
41
|
+
- Check whether 2.0 is also broken. The same deleted key is in `api2/Config/production.ini:87`, `worker2/Config/production.ini:85,145` and `saml/Config/production.ini:37`. Check the SQS `NumberOfMessagesSent` metric for `WorkerProductionQueue` (toga-production, us-east-1) since 2026-10-12 20:00 UTC. Not checked because toga-production SSO had expired.
|
|
42
|
+
- Find ODP PO `42187275-6869` (Compass PO 50315219-1, ODP SO 485188717) in the files waiting in `OfficeDepot/` or `processed/`. The developer asked, then said "wait", so it was not searched.
|
|
43
|
+
- Publish the `/capture` docs. They are written in `toga-tech/knowledge` but held because the team repo has someone else's unpushed changes.
|
|
44
|
+
|
|
45
|
+
## Current file state
|
|
46
|
+
| File | Status | Notes |
|
|
47
|
+
|------|--------|-------|
|
|
48
|
+
| worker/crons/toga2/compass/workflow/move_office_depot_as2_files_to_import_folder.php | created | Stop-gap move cron. Committed b3f57866 on _production per capture. Fails until AWS access is restored. Disable when the Lambda is back. |
|
|
49
|
+
| worker/schedules/cron.worker.sync.json | modified | Added `*/5` entry for the move cron, after 3a |
|
|
50
|
+
| C:/WWW/scripts/odp_move_stuck_as2_files.sh | created (outside repos) | Local helper using the developer SSO profile. Loop every 5 min, or `--once`. |
|
|
51
|
+
| toga-tech/knowledge (5 docs) | written, NOT published | New `1.0/apps/library/features/app-cloud-aws-credentials.md`. Updated the compass-usa ODP pipeline and recovery workflows, `error-capture-1-0.md` and the togaview `ticket-detail-page.md`. Architecture section skipped by the developer. |
|
|
52
|
+
|
|
53
|
+
## Decisions made
|
|
54
|
+
- **Replace keys with per-environment instance roles + the default credential chain** in `App_Cloud` (and 2.0 `_underscore/Cloud.php`). Rationale: nothing to leak, credentials expire, least privilege. The CTO agreed. cso agreed with the design but blocks rollout until the other committed secrets (DB passwords, NetSuite key, payment keys, SSO signing keys) are rotated. Rejected: a new long-lived key (DevOps refuses, and it is the same risk), widening the shared `aws-elasticbeanstalk-ec2-role` (about 60 envs would get EDI access), and per-cron credentials (duplicates the shared class).
|
|
55
|
+
- **Put the stop-gap cron in `crons/toga2/compass/workflow/` with no step number.** It sits beside `send_as2_outbox.php` (the outbound AS2 plumbing). It is temporary, not a business step.
|
|
56
|
+
- **Disable the infra-automation crons** (RDS scaler, terminate, failover) until reviewed. They needed admin powers.
|
|
57
|
+
|
|
58
|
+
## Blockers
|
|
59
|
+
- No AWS access for any 1.0 App_Cloud call since 2026-10-12 15:00 CDT. 3a cannot import, `send_as2_outbox.php` cannot send ACKs/ASNs, and the move cron cannot run. Waiting on Jeff to create the instance role.
|
|
60
|
+
- Lambda `rename_edi_files` is suspended by AWS after the breach. Jeff is waiting for AWS to restore it.
|
|
61
|
+
- 39+ Office Depot files are waiting in `s3://agilant-as2/OfficeDepot/`, and new ones keep landing in `processed/`.
|
|
62
|
+
|
|
63
|
+
## Exact next step
|
|
64
|
+
> Ask Jeff whether the `agilant-worker` instance role is created. Then edit `library/app/cloud.php` to use the default credential chain (remove the key statics, the `$preCommands` export and the SDK `credentials` arrays), run php-reviewer + cso, and deploy library + worker. After that, confirm 3a imports the files waiting in `s3://agilant-as2/OfficeDepot/` (new `ODP_EDI` rows in legacy `Logs.FileLog`).
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
_Saved by /session-save on 2026-10-12_
|
|
@@ -6,8 +6,8 @@ project: Claude Harness
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: workflow
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["jcardinal"]
|
|
9
|
+
updated: 2026-10-12
|
|
10
|
+
owners: ["jcardinal", "tcox"]
|
|
11
11
|
files:
|
|
12
12
|
- claude/knowledge.js
|
|
13
13
|
related:
|
|
@@ -47,6 +47,8 @@ Publish sequence, run inside the team repo clone (`~/toga-tech`):
|
|
|
47
47
|
- **`.claude/settings.json` is tracked in this repo and is edited by the harness itself**, so local drift there is expected and recurring. It was the dirty file that made the failure 100% reproducible on at least one machine. `--autostash` makes publish tolerate it, but the drift still wants a periodic `git diff .claude/settings.json` decision — commit it or revert it. It is also the file most likely to make `npx toga-ai`'s `git pull --ff-only` refuse (see the harness distribution doc).
|
|
48
48
|
- **A `catch` that discards `stderr` disguises a deterministic bug as a flaky one.** This bug went undiagnosed for months purely because `catch (e)` threw git's stderr away while git was naming the exact cause on every single run. Any retry wrapper around a shell command in this repo must surface `e.stderr || e.stdout` on final failure.
|
|
49
49
|
|
|
50
|
+
- **`--mirror` copies the whole KB into `<repo>/.claude/knowledge`** (~784 files in togatech), untracked in app repos. Never commit it to an app repo. Hide it locally with `.git/info/exclude` (add `.claude/knowledge/`) — do not edit the app's `.gitignore` for it.
|
|
51
|
+
|
|
50
52
|
## Related
|
|
51
53
|
|
|
52
54
|
- [Harness Distribution](harness-distribution.md)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|-----|---------|
|
|
5
5
|
| [TOGA Technology Website Architecture](architecture.md) | Public TOGA Technology marketing site — standalone React/TS SPA (no PHP framework); open for stack, bootstrap, routing, page layout, integrations, build/deploy. |
|
|
6
6
|
| [Careers Section — Live Paylocity Job Openings (About page + /v2/campaigns/jobs proxy)](features/careers-paylocity-job-openings.md) | togatech About page "Join Our Team" section — live Paylocity jobs via unauthenticated `GET /v2/campaigns/jobs` record-script proxy; open for the fetch→proxy→map |
|
|
7
|
-
| [NavV2 Global Nav — menus, scroll reveal, Talos FAB](features/navv2-global-nav.md) | togatech NavV2 header (designer "phase one"): data-driven menus, `data-nav-reveal` scroll hide/show, opt-in `data-nav-
|
|
7
|
+
| [NavV2 Global Nav — menus, panel shell, scroll reveal, Talos FAB](features/navv2-global-nav.md) | togatech NavV2 header (designer "phase one"): data-driven menus, one shared panel shell + WebGL canvas, `data-nav-reveal` scroll hide/show, opt-in `data-nav-pin |
|
|
8
8
|
| [SEO / AEO / GEO — Prerendering, Single-Source Meta & Structured Data](features/seo-aeo-geo-prerender.md) | togatech SEO/AEO/GEO — build-time Puppeteer prerender + single-source per-page meta + JSON-LD; open for the robots-gating de-index bug and Amplify build require |
|
|
9
9
|
| [Talos Product Page (/talos) — ported designer prototype](features/talos-product-page.md) | togatech `/talos` Talos AI product page, ported from a designer HTML/JSX/CSS prototype; open for the design-port CSS approach, re-porting a new design drop, laz |
|
|
10
10
|
| [Creating Pull Requests on togatech](workflows/creating-pull-requests.md) | Open a PR on `agilantsolutions/togatech` — `gh` CLI lacks `read:org`, so use a raw GitHub REST call with the keychain token; base is `_production`. |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: NavV2 Global Nav — menus, scroll reveal, Talos FAB
|
|
2
|
+
title: NavV2 Global Nav — menus, panel shell, scroll reveal, Talos FAB
|
|
3
3
|
framework: "standalone"
|
|
4
4
|
repo: togatech
|
|
5
5
|
project: TOGA Technology Website
|
|
@@ -12,8 +12,11 @@ files:
|
|
|
12
12
|
- togatech/src/components/NavV2/view/NavV2.tsx
|
|
13
13
|
- togatech/src/components/NavV2/view/TalosFab.tsx
|
|
14
14
|
- togatech/src/components/NavV2/view/NavDestLink.tsx
|
|
15
|
+
- togatech/src/components/NavV2/view/SilkCanvas.tsx
|
|
15
16
|
- togatech/src/components/NavV2/view/panels/WhatPanel.tsx
|
|
16
17
|
- togatech/src/components/NavV2/view/panels/CompanyPanel.tsx
|
|
18
|
+
- togatech/src/components/NavV2/view/panels/IndustriesPanel.tsx
|
|
19
|
+
- togatech/src/components/NavV2/view/panels/ResourcesPanel.tsx
|
|
17
20
|
- togatech/src/components/NavV2/view/panels/PanelFooter.tsx
|
|
18
21
|
- togatech/src/components/NavV2/navV2.module.css
|
|
19
22
|
- togatech/src/components/NavV2/types.ts
|
|
@@ -26,12 +29,15 @@ files:
|
|
|
26
29
|
- togatech/src/components/NavV2/viewModel/FIELDS/NAVFIELDS.json
|
|
27
30
|
- togatech/src/components/MobileNav/MobileNav.tsx
|
|
28
31
|
- togatech/src/styles/index.css
|
|
32
|
+
- togatech/public/assets/nav/logo-talos-ai.svg
|
|
33
|
+
- togatech/public/assets/nav/logo-toga-platform.svg
|
|
34
|
+
- togatech/tailwind.config.js
|
|
29
35
|
related:
|
|
30
36
|
- ../architecture.md
|
|
31
37
|
- talos-product-page.md
|
|
32
38
|
---
|
|
33
39
|
|
|
34
|
-
togatech NavV2 header (designer "phase one"): data-driven menus, `data-nav-reveal` scroll hide/show, opt-in `data-nav-pinned` for sticky scenes, Talos FAB rules, design-anchor rule. Open before touching the nav or adding a full-screen sticky section.
|
|
40
|
+
togatech NavV2 header (designer "phase one"): data-driven menus, one shared panel shell + WebGL canvas, `data-nav-reveal` scroll hide/show, opt-in `data-nav-pinned` for sticky scenes, Talos FAB rules, design-anchor rule. Open before touching the nav or adding a full-screen sticky section.
|
|
35
41
|
|
|
36
42
|
## Summary
|
|
37
43
|
|
|
@@ -44,6 +50,16 @@ Global header in `src/components/NavV2/` (MVVM: `view/`, `viewModel/`, menu data
|
|
|
44
50
|
- Flat links are `flatLinks[]` (was single `flatLink`): The TOGA Blog → `/blog` stub, Contact.
|
|
45
51
|
- What we do has 2 tabs (Business Units, Platforms). Tab hover switches the tab but never moves keyboard focus (`useRovingTabs`).
|
|
46
52
|
- Company panel and What-we-do share `panels/PanelFooter.tsx`.
|
|
53
|
+
- Platforms tab titles ("Talos AI", "TOGa Platform") show a brand logo on the left: data is `logo: {src, size}` in `NAVFIELDS.json` (`PlatformLogo` in `types.ts`), files in `public/assets/nav/` (Talos 38px, TOGa Platform 32px), 9px gap, class `.platformTitle`.
|
|
54
|
+
|
|
55
|
+
**Panel shell (one for all menus):** `NavV2.tsx` renders the only `.panel` (`hidden={!anyOpen}`) with the only `<SilkCanvas active={anyOpen}/>` + `.panelScrimOverlay`. Panel components (What / Industries / Company / Resources) return just their `.panelPad` div with `id` (the `aria-controls` target) and `data-screen-label`.
|
|
56
|
+
- **Never put a `.panel` shell or a `SilkCanvas` inside a panel component.** Each canvas is a WebGL context; one canvas per panel made a new context on every menu open (Chrome keeps only ~16 live).
|
|
57
|
+
- `.panel[hidden]{display:none}` is required — `.panel{display:flex}` beats the `hidden` attribute.
|
|
58
|
+
- `navPanelIn` slide-in plays on open (display none → flex restarts it); switching menu to menu does not replay it.
|
|
59
|
+
|
|
60
|
+
**Type:** matches the designer type spec (see Gotchas). `navV2.module.css` resets the site-wide word-spacing inside the nav: `.root :where(p,h2,h3,h4,h5,h6,a,li,button){word-spacing:normal}` (same idea as `/talos` — see [talos-product-page.md](talos-product-page.md) Gotchas).
|
|
61
|
+
|
|
62
|
+
**Mobile:** `MobileNav` closes on resize only when width > 1280 (`MOBILE_NAV_MAX_WIDTH_PX`), matching `tailwind.config.js` `md: {max:'1280px'}` (AppLayout: NavV2 `md:hidden`, hamburger `hidden md:block`).
|
|
47
63
|
|
|
48
64
|
**Scroll reveal (`useNavReveal.ts`):** sets `data-nav-reveal = top | hidden | shown` on the **nav root**, not `<html>`.
|
|
49
65
|
- `top` within 80px of page top. Hides after 8px scroll down; shows after 8px scroll up.
|
|
@@ -63,7 +79,11 @@ Global header in `src/components/NavV2/` (MVVM: `view/`, `viewModel/`, menu data
|
|
|
63
79
|
- **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
80
|
- Between ~88px scroll and one screen, neither bar nor FAB shows. Matches the design; open question with tcox — do not "fix" without asking.
|
|
65
81
|
- `/ai-solutions` stub is no longer linked from the nav.
|
|
82
|
+
- **Tailwind screens here are max-width (desktop-first):** `md:` means "≤ 1280px", not "≥ 768px".
|
|
83
|
+
- **Tailwind line-height traps:** `text-xs/sm/base/lg` set their own line-height; `leading-normal` is `1.5`, not CSS `line-height: normal`. When the design says "normal", use `leading-[normal]`.
|
|
84
|
+
- **Set logo size by inline style, not the `height` attribute** — Tailwind preflight `img{height:auto}` overrides it (the TOGa Platform SVG is 98x100, not square).
|
|
66
85
|
- 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.
|
|
67
86
|
|
|
68
87
|
## Change history
|
|
88
|
+
- 2026-10-12 — Type spec match, Platforms logos, one shared panel shell + SilkCanvas (WebGL context leak fix), MobileNav closes only above 1280px (TRUE-82042, tcox)
|
|
69
89
|
- 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)
|
|
@@ -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/pages/Talos/TalosPage.tsx
|
|
@@ -14,6 +14,9 @@ files:
|
|
|
14
14
|
- togatech/src/pages/Talos/viewModel/useTalosSparks.ts
|
|
15
15
|
- togatech/src/pages/Talos/viewModel/useGlassPanes.ts
|
|
16
16
|
- togatech/src/pages/Talos/viewModel/useTalosPanelSky.ts
|
|
17
|
+
- togatech/src/pages/Talos/viewModel/useTalosSubnav.ts
|
|
18
|
+
- togatech/src/pages/Talos/viewModel/FIELDS
|
|
19
|
+
- togatech/src/pages/Talos/view/sections/TalosChoosing/TalosChoosing.tsx
|
|
17
20
|
- togatech/src/pages/Talos/view/shared/Reveal.tsx
|
|
18
21
|
- togatech/src/pages/Talos/view/sections/TalosHero
|
|
19
22
|
- togatech/src/pages/Talos/view/sections/TalosVoice
|
|
@@ -42,7 +45,8 @@ togatech `/talos` Talos AI product page, ported from a designer HTML/JSX/CSS pro
|
|
|
42
45
|
- After regenerating, re-apply the port edits: add any design token the CSS uses but our copy lacks (the first port missed `--ease-enter`, so `.reveal` / `.tlh-enter` / `.tpl-rev` had no valid transition); drop `.needs-dev*`, `.tvq*`, and design `.talos-fab{display:none !important}` (it is for the design's orb launcher and would hide our NavV2 FAB until the orb is ported).
|
|
43
46
|
- **Not a CSS module:** the design JS finds elements by raw class names/ids and sets keyframe names inline; CSS-module hashing breaks all of that. (CTO-reviewed choice.)
|
|
44
47
|
- Design timing workarounds are kept on purpose: IntersectionObserver + rect-poll backstops and `setTimeout` retry chains (rAF / ResizeObserver can go silent on cold load). Animation loops pause off-screen and on hidden tab.
|
|
45
|
-
- `<html>`-level styles (`overflow-x: clip` so `position: sticky` works — never `hidden`; `scroll-behavior: smooth`) are set in `useLayoutEffect` and **removed** on unmount, not "restored" (a prerendered snapshot already carries them, so the "previous" value is wrong).
|
|
48
|
+
- `<html>`-level styles (`overflow-x: clip` so `position: sticky` works — never `hidden`; `scroll-behavior: smooth`) are set in `useLayoutEffect` (`useRootStyles` in `TalosPage.tsx`) and **removed** on unmount, not "restored" (a prerendered snapshot already carries them, so the "previous" value is wrong).
|
|
49
|
+
- **Reduced motion:** under `prefers-reduced-motion`, `useRootStyles` skips `scroll-behavior: smooth` and `useTalosSubnav` scrolls with `behavior: "instant"` — `"auto"` inherits the `<html>` smooth setting.
|
|
46
50
|
|
|
47
51
|
**Code-split + prerender:** `routes.tsx` wraps the page in `React.lazy` + `<Suspense fallback={null}>` inside the route `Component`. Rules in [seo-aeo-geo-prerender.md](seo-aeo-geo-prerender.md). Page-specific: `useGlassPanes` `useFitGap` (56px under the lede) skips on the `TOGAPrerender` UA so the snapshot does not bake the crawler-viewport margin.
|
|
48
52
|
|
|
@@ -55,7 +59,11 @@ togatech `/talos` Talos AI product page, ported from a designer HTML/JSX/CSS pro
|
|
|
55
59
|
|
|
56
60
|
**Routing:** `/talos` is in `LIVE_ROUTES` (`NavV2/navRoutes.ts`) and `src/routes.config.json`. Sub-pages `/talos/one|flow|engage` are still `STUB_ROUTES`.
|
|
57
61
|
|
|
58
|
-
**Copy:** the design's default `COPY.katie` set (Katie signs off copy).
|
|
62
|
+
**Copy:** the design's default `COPY.katie` set (Katie signs off copy). Not production-ready yet (new ticket pending, as of 2026-10-12):
|
|
63
|
+
- `TALOSFAQFIELDS.json` — 6 answers are "[Answer not written. Needs Jeff.]"; "Certification three/four" are placeholders.
|
|
64
|
+
- `TALOSVOICEFIELDS.json` — quote still flagged as placeholder.
|
|
65
|
+
- `TalosChoosing` card CTAs ("Book a demo", "See TOGa Platform") are plain spans with no link.
|
|
66
|
+
- Demo stage has no video.
|
|
59
67
|
|
|
60
68
|
## Port status (design drop 2, 2026-10)
|
|
61
69
|
|
|
@@ -76,5 +84,6 @@ Design's `HeroWeave` / `HeroDots` / old Hero are dead code — do not port.
|
|
|
76
84
|
- Tailwind preflight is global and can differ from the design's browser defaults — check margins/list/button resets when a section looks off.
|
|
77
85
|
|
|
78
86
|
## Change history
|
|
87
|
+
- 2026-10-12 — Reduced-motion: no smooth scroll on `<html>`, instant subnav jumps; listed open placeholder copy/CTAs (TRUE-82042, tcox)
|
|
79
88
|
- 2026-10-05 — Design drop 2, batches 1–2: talos.css regen (+`--ease-enter`, `.talos-mark`), Hero "Ask Talos", Voice → `.tproof-*`, FAQ bridge rules, useFitGap prerender skip (tcox)
|
|
80
89
|
- 2026-09-25 — Built /talos from the designer prototype; added Outlet context `openTalosChat`, `ROUTES_WITH_OWN_FOOTER`, TalosFab now opens chat (tcox)
|
|
@@ -6,12 +6,14 @@ project: TOGA Technology Website
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: workflow
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-12
|
|
10
10
|
owners: ["tcox"]
|
|
11
11
|
files:
|
|
12
12
|
- togatech/package.json
|
|
13
13
|
- togatech/cypress.config.ts
|
|
14
14
|
- togatech/src/App.tsx
|
|
15
|
+
- togatech/tsconfig.json
|
|
16
|
+
- togatech/tsconfig.app.json
|
|
15
17
|
related:
|
|
16
18
|
- ../architecture.md
|
|
17
19
|
- ../features/careers-paylocity-job-openings.md
|
|
@@ -28,7 +30,7 @@ The gotcha-avoidance path for getting `togatech` up on a dev machine and actuall
|
|
|
28
30
|
1. **`npm install` before anything else, every time you pull.** A stale `node_modules` shows up as a Vite resolve error, not as a missing dependency: `"react-helmet-async" is imported by … but could not be resolved`. Both `react-helmet-async` and `react-google-recaptcha-v3` are declared in `package.json` (added by the SEO work) but absent from an older install, and the site simply will not load.
|
|
29
31
|
2. **Start the dev server** — `npm run dev`, or `npm run togatech` for the `--host togatech` variant (Vite `allowedHosts: ["togatech"]`).
|
|
30
32
|
3. **Clear localStorage before judging any data fetch.** `App.tsx` wraps the app in `PersistQueryClientProvider` with the persister key **`"commerce"`** and a **24h `staleTime`**, so a previously cached query (e.g. `jobPosts`) renders from localStorage with **no network request at all**. Clear the persisted cache **and** `accessToken` / `refreshToken` — a stale public token from `POST /v2/auth/public` will otherwise be reused too.
|
|
31
|
-
4. **Do not expect `npm run lint` to work.** The script is `eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0`, but **`eslint` is not in `package.json` dependencies or devDependencies at all** — there is no local binary, so a clean install cannot lint. There is also **no ESLint config** — ad hoc `npx eslint` fails with "couldn't find an eslint.config.* file". Type-check with `npx tsc --noEmit -p tsconfig.app.json
|
|
33
|
+
4. **Do not expect `npm run lint` to work.** The script is `eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0`, but **`eslint` is not in `package.json` dependencies or devDependencies at all** — there is no local binary, so a clean install cannot lint. There is also **no ESLint config** — ad hoc `npx eslint` fails with "couldn't find an eslint.config.* file". Type-check with `npx tsc --noEmit -p tsconfig.app.json` — **not** `-p .`: root `tsconfig.json` has `"files": []` (references only), so `tsc -p .` and the `tsc` step in `npm run build` check nothing. It has pre-existing errors (13 on 2026-10-12, in Modal.tsx, PinScroll.tsx, TalosChat.tsx, IQ.tsx, OurHistory.tsx, routes.tsx, getFontAwesomeIcon.tsx), so filter the output by the paths you touched.
|
|
32
34
|
5. **If Cypress won't run, verify headlessly with the repo's Puppeteer.** `cypress` 15.11 fails its own binary verification on this Windows machine — `bad option: --smoke-test` — and `npx cypress install` does **not** fix it. Workaround: `puppeteer` is already a dependency, so drive **system Chrome** directly by passing `executablePath` to `puppeteer.launch()`, navigate to the dev-server URL, and assert on the rendered DOM (the section testids, e.g. `job-posting-section` / `job-opening-cards`). Same technique the production build already uses in `scripts/prerender.mjs`.
|
|
33
35
|
|
|
34
36
|
## Gotchas
|
|
@@ -46,5 +48,6 @@ The gotcha-avoidance path for getting `togatech` up on a dev machine and actuall
|
|
|
46
48
|
- [Careers Section — Live Paylocity Job Openings](../features/careers-paylocity-job-openings.md)
|
|
47
49
|
|
|
48
50
|
## Change history
|
|
51
|
+
- 2026-10-12 — Root tsconfig checks nothing (build's `tsc` does not type-check); 13 known errors (tcox)
|
|
49
52
|
- 2026-10-05 — Prod build sends GA hits from localhost; robotsPlugin closeBundle fails without dist/ (tcox)
|
|
50
53
|
- 2026-09-25 — No eslint config either; `tsc -p tsconfig.app.json` path-filter tip; robotsPlugin ignores --outDir (tcox)
|
package/package.json
CHANGED