toga-ai 1.0.1016 → 1.0.1017
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/features/email-send-pipeline.md +11 -2
- package/knowledge/2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md +32 -7
- package/knowledge/2.0/apps/_underscore/features/user-email-as-identity-and-password-reset.md +35 -4
- package/knowledge/2.0/apps/toga25-supply/INDEX.md +1 -0
- package/knowledge/2.0/apps/toga25-supply/features/forgot-password-and-create-password.md +83 -0
- package/knowledge/INDEX.md +1 -1
- package/knowledge/clients/elite/profile.md +5 -4
- package/package.json +1 -1
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["bala", "tcox", "dfranks", "apeterson", "jcardinal"]
|
|
9
|
+
updated: 2026-10-14
|
|
10
|
+
owners: ["bala", "tcox", "dfranks", "apeterson", "jcardinal", "rgirish"]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Email.php
|
|
13
13
|
- _underscore/String.php
|
|
@@ -102,6 +102,14 @@ derive one from the other).
|
|
|
102
102
|
inbox.** Whatever the caller rendered (placeholders resolved, built tables, escaping applied) is
|
|
103
103
|
in the `body` column the moment `send()` returns. This is the cheapest way to verify a new email:
|
|
104
104
|
query the row, not your mail client.
|
|
105
|
+
- **⚠ client-sandbox does not deliver email (seen 2026-10-13).** Two separate faults:
|
|
106
|
+
1. Some sandbox `Logs_<Client>` DBs lack the `Email` / `EmailAttachment` tables, so `_Email::send()`
|
|
107
|
+
fails with 500 `Table 'Logs_Elite.Email' doesn't exist`. Fix: create them from the
|
|
108
|
+
`dbchanges2/Logs_Client` blank DB plus the `2026-09-23a` EmailReview columns.
|
|
109
|
+
2. Even with the tables, the `Infrastructure/Email/Send/Run` cron is configured but `PENDING` rows
|
|
110
|
+
never go out on client-sandbox (`Logs_Compass` had 95 stuck). In non-prod, mail is rewritten
|
|
111
|
+
to `devteam@togatech.com` ("DEVELOPMENT MODE") anyway — so read the link/body from the
|
|
112
|
+
`Logs_<Client>.Email` row instead of waiting for mail.
|
|
105
113
|
- **⚠ `debug_mode` / `send_debug_emails_to` redirects at QUEUE time ONLY — never at send time.**
|
|
106
114
|
The redirect happens inside `_Email::send()` as it writes the `PENDING` row, so the row is
|
|
107
115
|
**already addressed** by the time the Send worker reads it. The worker does no redirect of its
|
|
@@ -202,6 +210,7 @@ derive one from the other).
|
|
|
202
210
|
for a hotfix.
|
|
203
211
|
|
|
204
212
|
## Change history
|
|
213
|
+
- 2026-10-14 — Gotcha: client-sandbox missing `Logs_<Client>.Email` tables and a Send cron that never drains `PENDING` rows (rgirish)
|
|
205
214
|
- 2026-09-23 — Review hold: `HELD`/`CANCELLED` statuses, `emailTemplateId`/`reviewOfEmailId`/
|
|
206
215
|
`dtReviewed`/`reviewedBy` columns, `setIsHeld`/`setEmailTemplateId`/`setReviewOfEmailId`;
|
|
207
216
|
`send()` now returns the log id; stale "enqueues" docblock fixed. (jcardinal)
|
package/knowledge/2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md
CHANGED
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: [bala]
|
|
9
|
+
updated: 2026-10-14
|
|
10
|
+
owners: [bala, rgirish]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Client/SalesOrder.php
|
|
13
13
|
- _underscore/Model/Quad/SalesOrder.php
|
|
@@ -114,16 +114,30 @@ fulfillment statuses — filter widened to `['_picked','_packed','_shipped']`:
|
|
|
114
114
|
|---|---|---|
|
|
115
115
|
| Base, Quad (non-SA) | Pending → Picked → Packed → Partially Fulfilled → Fulfilled | all IF stages |
|
|
116
116
|
| Compass USA + Canada | Pending → Partially Fulfilled → Fulfilled | **shipped IF stage only**; fulfilled-vs-partial rule differs per region (`_fulfillmentStatus()`) |
|
|
117
|
-
| Elite | pendingFulfillment →
|
|
117
|
+
| Elite | pendingFulfillment → picked → packed → partiallyFulfilled → shipped / fulfilled → delivered (+ canceled) | all IF stages + shipment state; **no approval stage** |
|
|
118
118
|
|
|
119
119
|
Quad `SA%` orders delegate to the base machine; an explicit `salesOrderStageId` overrides the
|
|
120
120
|
calculated status everywhere.
|
|
121
121
|
|
|
122
122
|
**Elite is a third policy, not a variant of Compass.** `_Model_Elite_SalesOrder::_status`
|
|
123
|
-
(`FIELD_SQL` override, with
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
`
|
|
123
|
+
(`FIELD_SQL` override, with private helper builders, plus `_Model_Elite_SalesOrderStatus`) walks
|
|
124
|
+
an **eight-status ladder**: Pending Fulfillment → Picked → Packed → Partially Fulfilled →
|
|
125
|
+
Shipped / Fulfilled → Delivered, plus Canceled (covers NetSuite *Cancelled* and *Closed*).
|
|
126
|
+
`shipped`/`delivered` were added first; **`picked`/`packed` were added 2026-10-08**:
|
|
127
|
+
- When shipped qty = 0 and a **picked** NetSuite IF exists → `picked`; else if a **packed** IF
|
|
128
|
+
exists → `packed`. Picked wins when both exist (same as the base `_Model_Client_SalesOrder`).
|
|
129
|
+
The counts come from the private helper `buildCountOfFulfillmentsWithStatus()`.
|
|
130
|
+
- No import change was needed: the 1.0 sync (`sync_togasupply_elite.php` →
|
|
131
|
+
`syncItemFulfillmentFromNetsuite`) already imported `_picked`/`_packed` IFs into
|
|
132
|
+
`ItemFulfillmentStages`. `_status` only counted shipped, so orders jumped Pending Fulfillment →
|
|
133
|
+
Delivered.
|
|
134
|
+
- Data: `dbchanges2/Client_Elite/2026-10-08a - SalesOrderStatusPickedPacked.sql` (picked `F5A623`,
|
|
135
|
+
packed `4DBCC4`) and `dbchanges2/Core/2026-10-08a - SalesOrderStatusVocabularyFulfillmentTerms.sql`
|
|
136
|
+
(Core `Messages` + `sales-order-status` `VocabularyTerms` for picked/packed/shipped/delivered).
|
|
137
|
+
- **Decision:** NetSuite order-header billing statuses (*Pending Billing*, *Billed*) are **not**
|
|
138
|
+
shown as their own Elite status.
|
|
139
|
+
- Prod-verified 2026-10-14: SR-14847 / SO 292745 shows Picked.
|
|
140
|
+
**Elite has no approval model at all**, so the Compass status
|
|
127
141
|
logic — which is written around the MR/MA approval flow — does not apply and must not be copied
|
|
128
142
|
across. The override also fixed a **`billed` → `pendingFulfillment` mislabel affecting 13 orders**.
|
|
129
143
|
|
|
@@ -197,6 +211,17 @@ Fan-out (`Client/`, every client) + a Compass-Canada-specific set. Execution is
|
|
|
197
211
|
`_Model_Client_ItemFulfillmentStatus`); only the shipped check uses a constant. Adding a base IF
|
|
198
212
|
picked/packed constant would let the literal be removed.
|
|
199
213
|
|
|
214
|
+
- **A new order-status slug needs TWO data rows, or the toga25-supply UI shows a blank badge.**
|
|
215
|
+
The table pill reads `Client_<Tenant>.SalesOrderStatuses` (name + `colorHex`); the record-modal
|
|
216
|
+
header badge reads the **Core** `sales-order-status` vocabulary terms (`VocabularyTerms` +
|
|
217
|
+
`Messages`). Elite's header badge was blank for `shipped`/`delivered` until the Core terms were
|
|
218
|
+
added (2026-10-08). No frontend code change is needed for a new slug.
|
|
219
|
+
|
|
220
|
+
## Change history
|
|
221
|
+
- 2026-10-14 — Elite `_status` now shows Picked / Packed from NetSuite IF stages; Core vocabulary
|
|
222
|
+
terms added for picked/packed/shipped/delivered; billing statuses kept out by decision (rgirish)
|
|
223
|
+
- 2026-09-16 — Compass per-region `_fulfillmentStatus()` seam; Elite six-status ladder documented (bala)
|
|
224
|
+
|
|
200
225
|
## Related
|
|
201
226
|
- [Recursive Item Fulfillments](recursive-item-fulfillments.md) — the engine that mirrors IFs (and
|
|
202
227
|
now their stages) up the chain.
|
package/knowledge/2.0/apps/_underscore/features/user-email-as-identity-and-password-reset.md
CHANGED
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: [ajean]
|
|
9
|
+
updated: 2026-10-14
|
|
10
|
+
owners: [ajean, rgirish]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Client/User.php
|
|
13
13
|
- api2/Component/Api/V2/V2.php
|
|
@@ -16,6 +16,8 @@ related:
|
|
|
16
16
|
- ./record-change-audit-log.md
|
|
17
17
|
- ../../../1.0/apps/tools/features/compass-user-persona-admin.md
|
|
18
18
|
- ../../../clients/compass-usa/features/people-file-user-lifecycle.md
|
|
19
|
+
- ../../toga25-supply/features/forgot-password-and-create-password.md
|
|
20
|
+
- ./email-send-pipeline.md
|
|
19
21
|
---
|
|
20
22
|
|
|
21
23
|
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 edits an email address.
|
|
@@ -35,13 +37,13 @@ Verified on code 2026-09-04 while adding email editing to the [Tools Compass adm
|
|
|
35
37
|
|
|
36
38
|
Key entry points:
|
|
37
39
|
|
|
38
|
-
- **`_underscore/Model/Client/User.php
|
|
40
|
+
- **`_underscore/Model/Client/User.php` `sendForgotPasswordEmail()`** — the forgot-password lookup and token mint; `updatePassword()` checks the token and sets the password.
|
|
39
41
|
- **`api2/Component/Api/V2/V2.php:762-765`** — binds the authenticated session to the row carrying the address.
|
|
40
42
|
- **`api2/Component/Api/V2/V2.php:611-621`** — resolves `clientId` from the email **domain** via `Core.ClientEmailDomains` when the request host does not identify the client.
|
|
41
43
|
|
|
42
44
|
### The forgot-password chain (the takeover primitive)
|
|
43
45
|
|
|
44
|
-
`_underscore/Model/Client/User.php
|
|
46
|
+
`_underscore/Model/Client/User.php` `sendForgotPasswordEmail()`:
|
|
45
47
|
|
|
46
48
|
1. Selects `Users` **by email** with **no `isActive` filter** and **no duplicate handling**.
|
|
47
49
|
2. `fetchRow()` takes the **FIRST** row returned — order is not defined.
|
|
@@ -53,6 +55,20 @@ So whoever controls an address that appears on a `Users` row can request, receiv
|
|
|
53
55
|
- A **dead (inactive) row** can be password-reset but **cannot be logged into**.
|
|
54
56
|
- The chain works end-to-end on an **ACTIVE** user.
|
|
55
57
|
|
|
58
|
+
### The two scripted APIs and the reset token
|
|
59
|
+
|
|
60
|
+
- **`GET /users/sendForgotPasswordEmail?userEmail=`** and **`GET /users/updatePassword?password=&token=`**
|
|
61
|
+
— `Core.RecordScripts` 8 and 9, **GET only**. The `Public` role needs `AclRecordScripts` rows for
|
|
62
|
+
both, or a logged-out user cannot call them.
|
|
63
|
+
- The emailed link is `<request Origin>/create-password?token=…`. The host comes from the JWT `aud`
|
|
64
|
+
(the request Origin), so it **must be a `Core.Domains` row** for that client.
|
|
65
|
+
- Email body comes from the `EmailTemplates` row `623c8869-4c59-409d-a6ff-c5d8818c9161` (per client
|
|
66
|
+
DB; Talos uses its own template).
|
|
67
|
+
- **Token lifetime is 30 minutes** (`const PASSWORD_RESET_TOKEN_SECONDS = 1800`, was 24h until
|
|
68
|
+
2026-10-13). `updatePassword()` returns `false` when the signature is bad **or** `exp` has passed.
|
|
69
|
+
The token is **still reusable inside the 30 minutes** — single-use would need a new `Users` column.
|
|
70
|
+
- Applies to every client and every app that uses this flow (toga2-supply, toga25-supply, Talos).
|
|
71
|
+
|
|
56
72
|
### Tenant routing from the email domain
|
|
57
73
|
|
|
58
74
|
`V2.php:611-621` derives `clientId` from the address's domain through `Core.ClientEmailDomains` whenever the request host does not identify the client. An editable email is therefore also a **tenant-routing control**, not just a credential hint. The related cross-client login branch (a home user authenticating against another tenant) is documented in [/auth/login resolves the client from the email domain](../../api2/features/login-cross-client-user-resolution.md).
|
|
@@ -63,9 +79,24 @@ So whoever controls an address that appears on a `Users` row can request, receiv
|
|
|
63
79
|
- **⚠ Do not assume the database enforces one email per user.** The 2.0 blank-client template declares `UNIQUE KEY email (email)`, but **live tenants have diverged** — both Compass tenants have no unique key and no index on `email` (prod-verified 2026-09-04). Any code that writes an email must check for a cross-row collision itself. Evidence and the full index list: [PEOPLE-file User Lifecycle](../../../clients/compass-usa/features/people-file-user-lifecycle.md).
|
|
64
80
|
- **⚠ Treat an email write as a security change, not a data change.** Minimum rails for any UI or job that sets `Users.email`: confirm the value twice, validate the domain against `Core.ClientEmailDomains`, refuse when another row in the tenant already holds the address, and write an audit row **before** the update. That is the shape the [Tools Compass admin](../../../1.0/apps/tools/features/compass-user-persona-admin.md) shipped.
|
|
65
81
|
- **An email is also a worker matching key.** worker2's `ensureCrossRegionUsersActive()` matches Compass users on **email**, so changing an address can silently remove a user from a hardcoded protected set — a second reason email edits need an explicit block list.
|
|
82
|
+
- **⚠ `_Http::validateJsonWebToken()` checks the signature only, never `exp`.** Any code that trusts
|
|
83
|
+
a JWT must check `exp` itself. Before 2026-10-13, `updatePassword()` did not, so a reset link
|
|
84
|
+
never expired.
|
|
85
|
+
- **Follow-up owed:** the "Forgot Password" `EmailTemplates` text still says "Link Valid for 1 Hour";
|
|
86
|
+
it should say 30 minutes (per client DB).
|
|
87
|
+
- **⚠ Known security debt (accepted, not fixed):** `sendForgotPasswordEmail` BCCs
|
|
88
|
+
`devteam@togatech.com` with the **live** reset link, and because `updatePassword` is GET-only the
|
|
89
|
+
new password travels in the query string and lands in `Logs_<Client>.Api`.
|
|
90
|
+
- **Testing tip:** in non-prod, mail is redirected to the dev team, so pull the reset link from the
|
|
91
|
+
`Logs_<Client>.Email` row body instead of an inbox (see [Email Send Pipeline](./email-send-pipeline.md)).
|
|
66
92
|
- **Never paste real addresses into tickets or the KB.** Reference the mechanism and the column, not the person.
|
|
67
93
|
|
|
94
|
+
## Change history
|
|
95
|
+
- 2026-10-14 — Reset token now 30 min and `updatePassword()` rejects expired tokens; documented the two scripted APIs, Public ACL, `Core.Domains` link host, and the BCC / query-string exposure (rgirish)
|
|
96
|
+
- 2026-09-16 — Created: email as login identity and tenant-routing key (ajean)
|
|
97
|
+
|
|
68
98
|
## Related
|
|
99
|
+
- [toga25-supply Forgot / Create Password pages](../../toga25-supply/features/forgot-password-and-create-password.md)
|
|
69
100
|
|
|
70
101
|
- [/auth/login resolves the client from the email domain](../../api2/features/login-cross-client-user-resolution.md)
|
|
71
102
|
- [Record change audit log](./record-change-audit-log.md)
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| [Client-Configurable Fields (useClientFields / fieldsConfig)](features/client-configurable-fields.md) | Config that varies by client (or client × role) — field overrides, filter buttons, group-by, column pickers, layout toggles — resolved through `src/fieldsConfig |
|
|
10
10
|
| [Column State (URL-driven show/hide, order & pinning)](features/column-visibility.md) | URL-driven "Columns" button + modal (`cols` param) for show/hide + order + pinning of table columns, client-configurable then Surface-driven; open for column-vi |
|
|
11
11
|
| [Force Logout on Deployment (useDeploymentGuard)](features/force-logout-on-deployment.md) | Force-signs-out every user when a deploy bumps a Core parameter, so session + caches reset to the new build; open when debugging surprise logouts or `useDeploym |
|
|
12
|
+
| [Forgot password & Create password pages (toga25-supply)](features/forgot-password-and-create-password.md) | The toga25-supply forgot-password and create-password pages: routes, page states, router-state notices, and the two backend scripted APIs they call. |
|
|
12
13
|
| [Loading & save-error states (table skeletons, shimmers, Refresh busy pill, save-error toaster)](features/loading-and-error-states.md) | Owning doc for how supply shows loading (table skeleton, sub-section shimmer, Refresh busy pill, sales-order modal skeletons) and failed saves (error toaster, n |
|
|
13
14
|
| [Meta-Driven Page & Table Setup](features/meta-driven-table-data.md) | A page is meta-driven end to end — page meta + table meta + table data, each keyed by slug via toga-blox hooks; pagination-vs-infinite is decided solely by meta |
|
|
14
15
|
| [Persisted React Query cache (localStorage `supply-chain-query-cache`)](features/persisted-query-cache.md) | `localStorage["supply-chain-query-cache"]` is the whole React Query cache dehydrated to disk (survives reloads AND sessions); the owning doc for staleTime rules |
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Forgot password & Create password pages (toga25-supply)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: toga25-supply
|
|
5
|
+
project: TOGa 2.5 Supply
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-10-14
|
|
10
|
+
owners: [rgirish]
|
|
11
|
+
files:
|
|
12
|
+
- toga25-supply/src/routes.tsx
|
|
13
|
+
- toga25-supply/src/pages/Login/LoginPage.tsx
|
|
14
|
+
- toga25-supply/src/pages/Login/view/AuthNotice.tsx
|
|
15
|
+
- toga25-supply/src/pages/ForgotPassword/ForgotPasswordPage.tsx
|
|
16
|
+
- toga25-supply/src/pages/ForgotPassword/viewModel/useForgotPasswordViewModel.ts
|
|
17
|
+
- toga25-supply/src/pages/CreatePassword/CreatePasswordPage.tsx
|
|
18
|
+
- toga25-supply/src/pages/CreatePassword/viewModel/useCreatePasswordViewModel.ts
|
|
19
|
+
- toga25-supply/src/pages/CreatePassword/helpers/passwordRules.ts
|
|
20
|
+
related:
|
|
21
|
+
- ./sso-redirect-and-session-gating.md
|
|
22
|
+
- ../workflows/porting-a-page-from-toga2-supply.md
|
|
23
|
+
- ../../_underscore/features/user-email-as-identity-and-password-reset.md
|
|
24
|
+
- ../../_underscore/features/email-send-pipeline.md
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
The toga25-supply forgot-password and create-password pages: routes, page states, router-state notices, and the two backend scripted APIs they call.
|
|
28
|
+
|
|
29
|
+
## Summary
|
|
30
|
+
|
|
31
|
+
toga25-supply has its own **Forgot password** and **Create password** pages (2026-10). The flow is a
|
|
32
|
+
copy of toga2-supply's, redesigned to a provided design (light mode). The backend is **unchanged** —
|
|
33
|
+
the same two `_underscore` scripted APIs every app uses.
|
|
34
|
+
|
|
35
|
+
## How it works
|
|
36
|
+
|
|
37
|
+
### Routes
|
|
38
|
+
|
|
39
|
+
`/forgot-password` and `/create-password` are **public** routes in `src/routes.tsx`, next to `/login`.
|
|
40
|
+
|
|
41
|
+
### Login page
|
|
42
|
+
|
|
43
|
+
- Centered **"Forgot password?"** link.
|
|
44
|
+
- Wrong credentials → red `AuthNotice` with a reset link. Shown **only** when
|
|
45
|
+
`useLoginPageViewModel` throws `"Invalid Credentials"` (not for other errors).
|
|
46
|
+
- Router state `passwordUpdated` → green "Password updated." notice.
|
|
47
|
+
- `AuthNotice.tsx` is the shared notice component for all three pages.
|
|
48
|
+
|
|
49
|
+
### Forgot password page
|
|
50
|
+
|
|
51
|
+
1. User enters the email → calls `GET /users/sendForgotPasswordEmail?userEmail=`.
|
|
52
|
+
2. Switches to a **"Check your email"** view with **Change** (edit the address), **Back to Sign In**,
|
|
53
|
+
and a **30-second resend countdown**.
|
|
54
|
+
3. Router state `linkExpired` → amber "link expired" notice.
|
|
55
|
+
|
|
56
|
+
The API always returns `true` (it does not reveal whether the address exists).
|
|
57
|
+
|
|
58
|
+
### Create password page
|
|
59
|
+
|
|
60
|
+
1. Reads `token` from the URL **once**, then strips it from the URL.
|
|
61
|
+
2. Missing token, or the API returns `false` → navigate to `/forgot-password` with `linkExpired`.
|
|
62
|
+
3. Calls `GET /users/updatePassword?password=&token=`.
|
|
63
|
+
4. Success → navigate to `/` with `passwordUpdated`.
|
|
64
|
+
5. Rules (in `helpers/passwordRules.ts`, with `passwordRules.test.ts`): 12+ characters, an uppercase
|
|
65
|
+
letter, a number, a special character.
|
|
66
|
+
|
|
67
|
+
Backend details (token lifetime 30 min, Public ACL, `Core.Domains` link host) live in
|
|
68
|
+
[Users.email & password reset](../../_underscore/features/user-email-as-identity-and-password-reset.md).
|
|
69
|
+
|
|
70
|
+
## Gotchas
|
|
71
|
+
|
|
72
|
+
- **Send the password with axios `params`, never by building the URL.** `updatePassword` is a
|
|
73
|
+
GET-only scripted API, so the password goes in the query string; `params` encodes `&`, `#`, `+`.
|
|
74
|
+
A hand-built URL breaks on those characters.
|
|
75
|
+
- **Use `font-medium`, not `font-semibold`.** The app font loads only weights 300/400/500/700, so
|
|
76
|
+
Tailwind `font-semibold` (600) falls back to the heavy 700.
|
|
77
|
+
- **The reset link host is the request Origin.** A new app host must be a `Core.Domains` row for the
|
|
78
|
+
client, or the emailed link points to the wrong place / the call fails.
|
|
79
|
+
- **Testing on non-prod:** mail is redirected to the dev team and client-sandbox does not send at
|
|
80
|
+
all — read the token from the `Logs_<Client>.Email` row body.
|
|
81
|
+
|
|
82
|
+
## Change history
|
|
83
|
+
- 2026-10-14 — Created: forgot-password + create-password pages ported from toga2-supply and redesigned (rgirish)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -31,7 +31,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
31
31
|
- **toga2-view** (TOGa View Frontend) — 12 doc(s) → [2.0/apps/toga2-view/INDEX.md](2.0/apps/toga2-view/INDEX.md)
|
|
32
32
|
- **toga2-hub** (TOGa Hub) — 2 doc(s) → [2.0/apps/toga2-hub/INDEX.md](2.0/apps/toga2-hub/INDEX.md)
|
|
33
33
|
- **toga2-commerce** (TOGa Commerce) — 30 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
|
|
34
|
-
- **toga25-supply** (TOGa 2.5 Supply) —
|
|
34
|
+
- **toga25-supply** (TOGa 2.5 Supply) — 24 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
|
|
35
35
|
- **toga25-iq** (TOGa IQ) — 1 doc(s) → [2.0/apps/toga25-iq/INDEX.md](2.0/apps/toga25-iq/INDEX.md)
|
|
36
36
|
- **toga25-desk** (TOGa Desk 2.5) — 1 doc(s) → [2.0/apps/toga25-desk/INDEX.md](2.0/apps/toga25-desk/INDEX.md)
|
|
37
37
|
- **toga25-blox** (TOGa Blox 2.5) — 3 doc(s) → [2.0/apps/toga25-blox/INDEX.md](2.0/apps/toga25-blox/INDEX.md)
|
|
@@ -18,7 +18,7 @@ project: Worker
|
|
|
18
18
|
client: elite
|
|
19
19
|
type: profile
|
|
20
20
|
status: active
|
|
21
|
-
updated: 2026-
|
|
21
|
+
updated: 2026-10-14
|
|
22
22
|
owners: [snaredla, apeterson, tcox, bala, rgirish, jcardinal]
|
|
23
23
|
files:
|
|
24
24
|
- worker2/Worker/Elite.php
|
|
@@ -85,9 +85,10 @@ method still carries GroWrk-specific rules. TO↔PO links: [TO↔PO link reconci
|
|
|
85
85
|
so it is **prod-only drift owed a `dbchanges2` catch-up**. Full write-up in
|
|
86
86
|
[netsuite-togasupply-sync](features/netsuite-togasupply-sync.md).
|
|
87
87
|
|
|
88
|
-
**Elite order status is its own
|
|
89
|
-
pendingFulfillment /
|
|
90
|
-
|
|
88
|
+
**Elite order status is its own ladder.** `_Model_Elite_SalesOrder::_status` emits
|
|
89
|
+
pendingFulfillment / picked / packed / partiallyFulfilled / shipped / fulfilled / delivered / canceled
|
|
90
|
+
(picked/packed added 2026-10-08 from NetSuite IF stages; billing statuses are deliberately not shown).
|
|
91
|
+
**Elite has no approval model**, so the Compass status logic does not transfer - see
|
|
91
92
|
[IF stage lifecycle & order status](../../2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md).
|
|
92
93
|
|
|
93
94
|
## Supply Inventory grouping — "Units by Items" is two levels, not three (2026-09-21)
|
package/package.json
CHANGED