toga-ai 1.0.1083 → 1.0.1085

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.
@@ -17,7 +17,7 @@ project: _Underscore
17
17
  client: prudential
18
18
  type: profile
19
19
  status: active
20
- updated: 2026-10-18
20
+ updated: 2026-10-19
21
21
  owners: ["jcardinal", "rgirish", "bala", "mhammontree"]
22
22
  files: []
23
23
  related:
@@ -121,6 +121,13 @@ The order-created cron branches on this id; the shipped/delivered crons branch o
121
121
  The 15-minute `prudential_auth_rejection_alert.php` cron now alerts on them — see
122
122
  features/service-request-auth-rejection-alert.md.
123
123
 
124
+ - **Daily "Prudential REQ's Processing Report" recipients are hardcoded.** Sent by 1.0
125
+ `worker/crons/notifications/reports/prudential_exception_report.php` (NOT the sibling
126
+ `reports/prudential/` folder), scheduled in `worker/schedules/cron.worker.notification.json` as
127
+ "Prudential Exception Report (9:00 AM)". Recipients = the `$emailTo` PHP array near the top of the
128
+ file (a hardcoded list of togatech.com addresses, all TO, no CC); no DB table or setting. To add or
129
+ remove someone: edit that array, deploy worker `_production` (CodePipeline `Worker`). (TRUE-82925)
130
+
124
131
  - **SR number race (TRUE-82209: ServiceNow bursts → 1062 `Duplicate entry 'SR…'` → 400 `EV-10`, SR lost).** Fixed by
125
132
  per-client record numbers from `RecordNumbers` (TRUE-82715; SR series continues); the `usleep` stopgap in `_Model_Prudential_ServiceRequest::prePost()`
126
133
  is removed. Load-test with a distinct contact + serial per call and `customer.uuid` set. See
@@ -8,11 +8,12 @@
8
8
  | [Rate Monthly Reconciliation Report](features/monthly-reconciliation-report.md) | 1.0 | Monthly cron that emails an Excel reconciliation of Rate subscription orders + PayPal payments; open when changing the report columns, filters, or recipients. |
9
9
  | [Rate SalesOrder → NetSuite CashSale Export (postPost)](features/netsuite-cashsale-export.md) | 2.0 | How a Rate SalesOrder postPost writes a NetSuite CashSale (ship-to address + line-item internalId resolution); open when touching Rate's NetSuite export. |
10
10
  | [Rate PayPal Subscription Purchase & Webhook Pipeline](features/paypal-subscription-purchase-webhook.md) | 2.0 | How Rate PayPal subscription purchases are created (browser primary, webhook fallback) and how the worker2 webhook handles lifecycle events; open before touchin |
11
- | [Rate SAML SSO](features/saml-sso.md) | 2.0 | How Rate users sign in via Azure AD SAML through the TOGa gateway, plus assertion attributes and the loan-officer upsert; open when debugging Rate login or user |
11
+ | [Rate SAML SSO](features/saml-sso.md) | 2.0 | How Rate users sign in via Azure AD SAML through the TOGa gateway, plus assertion attributes and the loan-officer upsert (and why the LO is usually missing); op |
12
12
  | [Service Card Entitlement Display](features/service-card-entitlements.md) | 2.0 | How Rate's home/services pages render one service card per purchased entitlement (per-entitlement, own pinned address for warranty); open when touching service |
13
13
  | [Rate Service-Purchase Confirmation Emails (Tech / Warranty)](features/service-purchase-emails.md) | 2.0 | How Rate purchase-confirmation emails (tech vs warranty) are triggered from the entitlement postPost and sent off-thread from DB-stored templates; open when edi |
14
14
  | [Rate Tech-Support Subscription Cancellation (portal self-service)](features/subscription-cancellation.md) | 2.0 | Portal self-service cancellation of a Rate tech-support subscription (cancel at PayPal, wind down to period end); open before touching the cancel flow, the two- |
15
15
  | [Rate Whole Home Warranty Per-Address Purchase Guard](features/whole-home-warranty-purchase-guard.md) | 2.0 | The `prePost` guard enforcing one active Whole Home Warranty per validated address (global), via USPS DPV + unit-level dedup; open before touching the WH guard, |
16
16
  | [Rate](profile.md) | 2.0 | Rate client profile (mortgage/lending; home warranty + home tech support on TOGa View, SAML SSO); open when starting any Rate work. |
17
+ | [Rate — Fill a customer-sent active-subscriptions report from Client_Rate](workflows/active-subscriptions-report-data.md) | 2.0 | How to fill missing columns (address, loan officer, payments) in a report Rate sends us, by hand from prod `Client_Rate`, and how to match their rows; open when |
17
18
  | [Rate — Annual SSL Certificate Renewal (4 Home Warranty / Home Tech Support domains)](workflows/annual-ssl-certificate-renewal.md) | 2.0 | How to generate the four Rate CSRs each year, what to send the GR System team, and what never to send; open when Rate's certs are near expiry. |
18
19
  | [Rate — Backfill a Missed PayPal Sale (Toga + NetSuite reconciliation)](workflows/paypal-sale-backfill-and-reconciliation.md) | 2.0 | How to put a PayPal sale that Toga or NetSuite missed back into both systems, by hand; open when reconciling Rate PayPal vs Toga vs NetSuite or when a webhook w |
@@ -7,13 +7,14 @@ client: rate
7
7
  type: client-feature
8
8
  status: active
9
9
  updated: 2026-09-16
10
- owners: ["rgirish"]
10
+ owners: ["rgirish", "bala"]
11
11
  files:
12
12
  - worker/crons/notifications/reports/rate/send_monthly_rate_purchases_report.php
13
13
  - worker/schedules/cron.worker.notification.json
14
14
  related:
15
15
  - clients/rate/features/saml-sso.md
16
16
  - clients/rate/profile.md
17
+ - clients/rate/workflows/active-subscriptions-report-data.md
17
18
  ---
18
19
  Monthly cron that emails an Excel reconciliation of Rate subscription orders + PayPal payments; open when changing the report columns, filters, or recipients.
19
20
 
@@ -5,17 +5,19 @@ project: SAML SSO Gateway
5
5
  client: rate
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-09-16
9
- owners: ["rgirish"]
8
+ updated: 2026-10-19
9
+ owners: ["rgirish", "bala"]
10
10
  files:
11
11
  - _underscore/Model/Rate/ClientAuthentication.php
12
12
  - saml/Controller/Index.php
13
13
  - toga2-view/src/hooks/useAuthenticationFlow.ts
14
+ - toga2-view/src/routes.tsx
14
15
  related:
15
16
  - 2.0/apps/saml/architecture.md
16
17
  - 2.0/apps/saml/features/rate-user-provisioning.md
18
+ - clients/rate/workflows/active-subscriptions-report-data.md
17
19
  ---
18
- How Rate users sign in via Azure AD SAML through the TOGa gateway, plus assertion attributes and the loan-officer upsert; open when debugging Rate login or user provisioning.
20
+ How Rate users sign in via Azure AD SAML through the TOGa gateway, plus assertion attributes and the loan-officer upsert (and why the LO is usually missing); open when debugging Rate login, user provisioning, or loan officer data.
19
21
 
20
22
  ## Summary
21
23
  Rate uses Azure AD as its IdP (`login.rate.com`). Users sign in at Rate's portal, which redirects to the TOGa SAML gateway at `saml.togahub.com/acs`. On success the gateway redirects the browser back to the Rate frontend with a `?saml=` encrypted payload.
@@ -23,7 +25,7 @@ Rate uses Azure AD as its IdP (`login.rate.com`). Users sign in at Rate's portal
23
25
  ## How it works
24
26
 
25
27
  ### SAML assertion attributes
26
- Rate's Azure AD sends these attributes in the assertion:
28
+ Rate's Azure AD sends these attributes in the assertion (`ClientAuthentication.php` ~L19-23 reads only these):
27
29
  | Attribute key | Description | Required |
28
30
  |---|---|---|
29
31
  | `borrowerID` | Borrower UUID — used as `c_borrowerId` to identify/create users | Yes |
@@ -32,7 +34,7 @@ Rate's Azure AD sends these attributes in the assertion:
32
34
  | `lastName` | Last name | No (null-safe) |
33
35
  | `phoneNumber` | Phone number | No (null-safe) |
34
36
 
35
- `borrowerID` is a UUID string (not numeric).
37
+ `borrowerID` is a UUID string (not numeric). No loan officer attribute is sent.
36
38
 
37
39
  ### Frontend SAML landing (`useAuthenticationFlow.ts`)
38
40
  1. If `?saml=` is in the URL: strip it immediately via `window.history.replaceState` (prevents stale payload replay on refresh), then call `/v2/auth/encrypted-user-uuid`.
@@ -40,15 +42,30 @@ Rate's Azure AD sends these attributes in the assertion:
40
42
  3. On error: navigate to `/login`.
41
43
 
42
44
  ### Loan officer upsert
43
- After successful auth, if `urlParameters` contains `loid` + `loname`:
45
+ Source: the loan officer reaches us **only** as `loid` (short numeric, e.g. `38623`) + `loname` query params on the landing link Rate sends the borrower. `routes.tsx` (~L52-57) saves every non-`saml` query param to localStorage `urlParameters`. The raw assertion / RelayState / landing URL is never stored.
46
+
47
+ After successful auth, if `urlParameters` contains `loid` + `loname` (`useAuthenticationFlow.ts` ~L72-115):
44
48
  1. Fetch the user's Contact to get their Customer UUID.
45
- 2. Search `Contacts` by `c_loid` — PUT to update name if found; POST to create with `contactType = 'Loan Officer'` (UUID `d1f67efc-a984-aebc-42f5-5313f44f52ed`) linked to the customer.
49
+ 2. Search `Contacts` by `c_loid` (global, not per customer) — PUT to update name if found; POST to create with `contactTypeId = 1` 'Loan Officer' (UUID `d1f67efc-a984-aebc-42f5-5313f44f52ed`) linked to the customer.
50
+
51
+ No `loid` in the link → no `/v2/contacts?...c_loid` call, no loan officer row. Prod 2026-10-19: only 9 loan officer Contacts in `Client_Rate` (first 2026-06-14) vs 734 customers.
52
+
53
+ Options for more coverage (not built):
54
+ - Ask Rate to add a loan officer attribute to the assertion next to `borrowerID`; read it in `ClientAuthentication.php`.
55
+ - Backfill: send Rate the `Customers.c_borrowerId` list; Rate maps borrower → loan officer.
46
56
 
47
57
  ## Gotchas
48
58
  - **`?saml=` replay** — the frontend strips the param immediately after processing. Before this fix, refreshing replayed the stale payload → EZ-1 "Invalid User".
49
59
  - **New users silently not created (Apr 2 – Jun 11 2026)** — `_Database::register()` auto-starts a lazy transaction; the saml gateway never called `transactionCommit()`, so all new user INSERTs were rolled back silently. Fixed by adding `_Database::transactionCommit()` before the redirect in `saml/Controller/Index.php`.
50
60
  - **Both saml and _underscore must be deployed together** — saml pulls `_underscore` at EB build time. A fix in `_underscore` requires a saml redeploy to take effect.
61
+ - **Loan officer never linked to a second borrower (bug, not fixed).** The `c_loid` lookup is global; if the LO exists it only PUTs `firstName`/`lastName`. `Contacts.customerId` stays the first borrower, so later borrowers of the same LO show none. One Contact row = one customer, so the model cannot hold one LO for many borrowers as-is; a fix needs a link table or a per-customer LO row.
62
+ - **`borrowerId` is not the loan officer id.** `Customers.c_borrowerId` / `Users.c_borrowerId` is Rate's IdP UUID, one per customer (prod 2026-10-19: 734 customers, 734 distinct). LO ids are short numerics in `Contacts.c_loid`. The SSO default role `roleId = 1` is *named* 'Loan Officer' (`ClientAuthentication.php` ~L74) — it is only the access role.
63
+ - **Missing LOs cannot be recovered from our side** — nothing that carried them is persisted. Only Rate can supply them.
51
64
 
52
65
  ## Related
53
66
  - [SAML architecture](2.0/apps/saml/architecture.md)
54
67
  - [Rate user provisioning](2.0/apps/saml/features/rate-user-provisioning.md)
68
+ - [Rate active-subscriptions report data](clients/rate/workflows/active-subscriptions-report-data.md)
69
+
70
+ ## Change history
71
+ - 2026-10-19 — Documented loan officer source (landing-link `loid` only), the global-lookup link gap, and borrowerId vs `c_loid` (TRUE-82942) (bala)
@@ -14,7 +14,7 @@ project: SAML SSO Gateway
14
14
  client: rate
15
15
  type: profile
16
16
  status: active
17
- updated: 2026-10-14
17
+ updated: 2026-10-19
18
18
  owners: ["rgirish", "bala", "mhammontree", "tcox"]
19
19
  files: []
20
20
  related:
@@ -29,6 +29,7 @@ related:
29
29
  - clients/rate/features/home-warranty-terms-content.md
30
30
  - clients/rate/workflows/annual-ssl-certificate-renewal.md
31
31
  - clients/rate/workflows/paypal-sale-backfill-and-reconciliation.md
32
+ - clients/rate/workflows/active-subscriptions-report-data.md
32
33
  ---
33
34
  Rate client profile (mortgage/lending; home warranty + home tech support on TOGa View, SAML SSO); open when starting any Rate work.
34
35
 
@@ -0,0 +1,45 @@
1
+ ---
2
+ title: "Rate — Fill a customer-sent active-subscriptions report from Client_Rate"
3
+ framework: "2.0"
4
+ project: SAML SSO Gateway
5
+ client: rate
6
+ type: workflow
7
+ status: active
8
+ updated: 2026-10-19
9
+ owners: ["bala"]
10
+ files:
11
+ - worker/crons/notifications/reports/rate/send_monthly_rate_purchases_report.php
12
+ related:
13
+ - ../profile.md
14
+ - ../features/monthly-reconciliation-report.md
15
+ - ../features/saml-sso.md
16
+ - ../features/service-card-entitlements.md
17
+ - ../workflows/paypal-sale-backfill-and-reconciliation.md
18
+ ---
19
+ How to fill missing columns (address, loan officer, payments) in a report Rate sends us, by hand from prod `Client_Rate`, and how to match their rows; open when Rate asks for subscription data or names in their own template.
20
+
21
+ ## Summary
22
+ Rate sends a PayPal-based template (customer name, email, product, start date, ...) and asks us to fill gaps. Pull from `Client_Rate` (read-only), match each row carefully, and flag disagreements instead of overwriting. Loan officer is usually not available — see [SAML SSO](../features/saml-sso.md) *Loan officer upsert*.
23
+
24
+ ## How it works
25
+
26
+ ### Join path
27
+ - `Subscriptions` → `Entitlements` (`Entitlements.subscriptionId`) → `Contacts` (`Entitlements.contactId`) → `Customers` (`Contacts.customerId`).
28
+ - Address: `Entitlements.serviceAddressId` → `Addresses` + `States.code` (column is `code`, not `abbreviation`). `Contacts.primaryContactAddressId` points at the same address.
29
+ - Payments: `Entitlements_SalesOrders` → `SalesOrders` → `SalesOrders_Payments` → `Payments`.
30
+ - Loan officer: `Contacts` with `contactTypeId = 1` and `c_loid`, owned by the customer (`customerId`). Rarely present.
31
+
32
+ ### Matching a report row to our data
33
+ 1. Match on name + address + start date, not email alone.
34
+ 2. The report email (PayPal email) can differ from `Users.email` / `ContactEmailAddresses` (seen: one letter off; a different gmail).
35
+ 3. `Customers.name` can be a different household member than the name in the report.
36
+ 4. Fill only proven matches. List unmatched rows for the requester.
37
+
38
+ ## Gotchas
39
+ - **Premium Tech Support ($9.97) entitlements have no address** — the tech support checkout never collects one. Only Whole Home Warranty ($89.97) has one. A blank address there is correct, not missing data.
40
+ - **`Subscriptions.isActive` can disagree with Rate's PayPal-based template.** Flag it; do not change either side.
41
+ - **`Logs_Rate.Api` is ~3.9M rows.** Broad `LIKE` scans on `requestPayload` / `route` over months time out (300s). Always filter a narrow `dtStamp` window plus `userId`.
42
+ - The [monthly reconciliation report](../features/monthly-reconciliation-report.md) cron uses the same joins; reuse its SQL as a starting point.
43
+
44
+ ## Change history
45
+ - 2026-10-19 — Created from the TRUE-82942 Rate active-subscriptions data request (bala)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.1083",
3
+ "version": "1.0.1085",
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",