toga-ai 1.0.424 → 1.0.425
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.
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
| [Rate SAML SSO](features/saml-sso.md) | 2.0 | Rate uses Azure AD as its IdP (`login.rate.com`). | _underscore/Model/Rate/ClientAuthentication.php, saml/Controller/Index.php, toga2-view/src/hooks/useAuthenticationFlow.ts |
|
|
9
9
|
| [Service Card Entitlement Display](features/service-card-entitlements.md) | 2.0 | Rate's home and services pages display one service card per purchased entitlement. | src/components/ServiceCard/ServiceCard.tsx, src/components/ServiceCard/index.ts, src/hooks/useBundleServices.ts, src/hooks/useActiveServices.ts, src/pages/Home/api/homeApi.ts, src/pages/Home/view/HomePage.tsx, src/pages/Home/viewModels/useHomePageViewModel.ts, src/pages/Services/view/ServicesPage.tsx, src/pages/Services/viewModels/useServicePageViewModel.ts, src/api/serviceAddressApi.ts, src/api/apiErrors.ts |
|
|
10
10
|
| [Rate Service-Purchase Confirmation Emails (Tech / Warranty)](features/service-purchase-emails.md) | 2.0 | When a Rate customer purchases a service, a confirmation email is sent. | _underscore/Model/Rate/Entitlement.php, worker2/Worker/Notification/EmailTemplate.php, dbchanges2/Client_Rate/2026-06-30a - Rate purchase email templates.sql |
|
|
11
|
-
| [Rate Whole Home Warranty Per-Address Purchase Guard](features/whole-home-warranty-purchase-guard.md) | 2.0 | > **⚠ DEPLOYING beta→production, NOT YET PROD-VERIFIED (as of 2026-07-23).** TRUE-79533 is > beta-verified (PM Paulina tested the WH purchase flow on beta) and | _underscore/Model/Rate/Entitlement.php, _underscore/Model/Client/Entitlement.php, _underscore/Model/Client/Address.php, dbchanges2/Client/2026-07-22a - EntitlementServiceAddressId.sql, dbchanges2/Core/2026-07-22a - EntitlementServiceAddressIdField.sql, dbchanges2/
|
|
11
|
+
| [Rate Whole Home Warranty Per-Address Purchase Guard](features/whole-home-warranty-purchase-guard.md) | 2.0 | > **⚠ DEPLOYING beta→production, NOT YET PROD-VERIFIED (as of 2026-07-23).** TRUE-79533 is > beta-verified (PM Paulina tested the WH purchase flow on beta) and | _underscore/Model/Rate/Entitlement.php, _underscore/Model/Client/Entitlement.php, _underscore/Model/Client/Address.php, dbchanges2/Client/2026-07-22a - EntitlementServiceAddressId.sql, dbchanges2/Core/2026-07-22a - EntitlementServiceAddressIdField.sql, dbchanges2/Client_Rate/2026-07-23a - EntitlementServiceAddressIdFieldPermission.sql, test/@Mark/Rate/verify_wholehome_per_address_guard.php |
|
|
12
12
|
| [Rate](profile.md) | 2.0 | Rate is a mortgage/lending client. | |
|
|
@@ -14,7 +14,7 @@ files:
|
|
|
14
14
|
- _underscore/Model/Client/Address.php
|
|
15
15
|
- dbchanges2/Client/2026-07-22a - EntitlementServiceAddressId.sql
|
|
16
16
|
- dbchanges2/Core/2026-07-22a - EntitlementServiceAddressIdField.sql
|
|
17
|
-
- dbchanges2/
|
|
17
|
+
- dbchanges2/Client_Rate/2026-07-23a - EntitlementServiceAddressIdFieldPermission.sql
|
|
18
18
|
- test/@Mark/Rate/verify_wholehome_per_address_guard.php
|
|
19
19
|
related:
|
|
20
20
|
- clients/rate/profile.md
|
|
@@ -32,11 +32,12 @@ related:
|
|
|
32
32
|
> **shared-interceptor merge hazard** gotcha and the **dangling-pin** / **unguarded prod
|
|
33
33
|
> interceptor** gotchas before merging to `_production`.
|
|
34
34
|
>
|
|
35
|
-
> **🚨 LAUNCH BLOCKER (
|
|
36
|
-
> READ ACL grant.** The custom→standard
|
|
37
|
-
>
|
|
38
|
-
>
|
|
39
|
-
>
|
|
35
|
+
> **🚨 LAUNCH BLOCKER — RESOLVED (migration built 2026-07-23, mhammontree; found 2026-07-23,
|
|
36
|
+
> tcox) — the standard `serviceAddressId` field had NO READ ACL grant.** The custom→standard
|
|
37
|
+
> redesign shipped the column + `Core.RecordFields` row but **not** the `AclFieldPermissions`
|
|
38
|
+
> read grant, so `GET /v2/entitlements?fields=serviceAddressId` returned **403 `EZ-2`**. The fix
|
|
39
|
+
> now ships as **`dbchanges2/Client_Rate/2026-07-23a - EntitlementServiceAddressIdFieldPermission.sql`**
|
|
40
|
+
> (committed `b74f42a` on TRUE-79533) — see
|
|
40
41
|
> **[Launch blocker: standard field needs a READ ACL grant](#launch-blocker-true-79533--the-standard-field-needs-a-read-acl-grant)**.
|
|
41
42
|
|
|
42
43
|
## Summary
|
|
@@ -144,7 +145,7 @@ during backend review (Jeff). This is the single biggest change since the beta b
|
|
|
144
145
|
|
|
145
146
|
**The custom→standard redesign shipped the column and the `Core.RecordFields` row but NOT the
|
|
146
147
|
`AclFieldPermissions` READ grant.** Probe-verified on **beta 2026-07-23**:
|
|
147
|
-
`GET /v2/entitlements?fields=serviceAddressId` returns **403 `EZ-2`**
|
|
148
|
+
`GET /v2/entitlements?fields=serviceAddressId` returns **403 `EZ-2`** (no read ACL row)
|
|
148
149
|
(Entitlements has `Core.Records.aclDatabase = 'CLIENT'`, so the grant lives in each client DB).
|
|
149
150
|
Without the grant, **production launches with the exact `EZ-2` failure beta hit** — the field is
|
|
150
151
|
registered but unreadable, so the service cards cannot fetch the pin.
|
|
@@ -157,16 +158,20 @@ field is authorized through **`AclFieldPermissions`**, keyed by the **`Core.Reco
|
|
|
157
158
|
because the `CustomRecordFields` row for `c_serviceAddressId` was deleted in the standard-field
|
|
158
159
|
redesign. The read grant now has to be an **`AclFieldPermissions`** row instead.
|
|
159
160
|
|
|
160
|
-
**
|
|
161
|
-
`dbchanges2/
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
-
|
|
169
|
-
|
|
161
|
+
**The migration that ships (built + committed `b74f42a` on TRUE-79533):**
|
|
162
|
+
`dbchanges2/Client_Rate/2026-07-23a - EntitlementServiceAddressIdFieldPermission.sql`:
|
|
163
|
+
- Resolves field ids via cross-schema `Core.RecordFields` / `Core.Records` subselects (route
|
|
164
|
+
`'entitlements'`, field `'serviceAddressId'`) — never hardcodes ids.
|
|
165
|
+
- **Grants READ only (`isWritable = 0`)** — `serviceAddressId` is written **server-side** by
|
|
166
|
+
`_Model_Rate_Entitlement::postPost` via raw SQL, never by the API caller.
|
|
167
|
+
- **Mirrors the reader ROLE(s) of the sibling standard FK `saleItemId` — which is `role 1` in
|
|
168
|
+
`Client_Rate`** (the same role the earlier `c_serviceAddressId` custom grant used). Although
|
|
169
|
+
the cross-role probe showed roles 1/2/4 all lacked a grant, **role 1 is the only actual reader**
|
|
170
|
+
of this field (Rate's toga2-view service cards), so the grant is role-1 only.
|
|
171
|
+
- Guards each INSERT with `NOT EXISTS` — safe no-op until the field is registered
|
|
172
|
+
(`AclFieldPermissions` is `UNIQUE (recordFieldId, roleId)`).
|
|
173
|
+
- **Scoped to `Client_Rate`, not a `Client/` fan-out** — Rate is the only client whose UI reads
|
|
174
|
+
the field today. A `Client/` fan-out grant is the follow-up if another client's UI needs it.
|
|
170
175
|
|
|
171
176
|
## Beta data migration — old-column pins are orphaned by the redesign (beta only, NO prod impact)
|
|
172
177
|
|
|
@@ -289,6 +294,17 @@ live carrier waterfall is opt-in via `RUN_LIVE=1` (defaults off). Verified **18/
|
|
|
289
294
|
the deleted `2026-07-07a` interceptor registration was redundant — and why keeping it would have
|
|
290
295
|
been a latent hazard: a fresh environment running both would **double-register**, firing
|
|
291
296
|
`prePost` twice. **Recommend adding a `NOT EXISTS` guard to the `2026-07-15` file.**
|
|
297
|
+
- **`AclFieldPermissions` has NO `isReadable` column — a ROW grants READ; `isWritable`
|
|
298
|
+
*additionally* grants WRITE** (reusable platform fact, verified against the api2 enforcement
|
|
299
|
+
code, not just schema). In `api2/Component/Api/V2/V2.php`, `getAclFieldPermissions()` (~line
|
|
300
|
+
5731) sets the field key regardless of `isWritable`, and the read-authorization checks test key
|
|
301
|
+
**presence** (`isset`/`array_key_exists`). Consequences: to make a field API-**readable** you
|
|
302
|
+
insert an `AclFieldPermissions` row (`isWritable = 0` for read-only); to make it **writable** set
|
|
303
|
+
`isWritable = 1`. And promoting a custom (`c_`) field to a **standard** field means its read grant
|
|
304
|
+
must be **re-created** as a standard `AclFieldPermissions` row (keyed by the `Core.RecordFields`
|
|
305
|
+
id) — the old `AclCustomFieldPermissions` grant (keyed by `CustomRecordFields` id) does **not**
|
|
306
|
+
carry over. This is exactly why the `c_serviceAddressId` grant did not cover the standard field
|
|
307
|
+
and the launch-blocker migration above was needed.
|
|
292
308
|
- **`Core.RecordFields` has no `foreignRecordId` column** — FK resolution for `serviceAddressId`
|
|
293
309
|
is entirely **model-side** (the `_Model_Client_Entitlement` FK declaration). The RecordField row
|
|
294
310
|
only carries type/identifier/childPolicy/precision, mirroring sibling FKs `saleItemId`/`vendorId`.
|
|
@@ -297,6 +313,17 @@ live carrier waterfall is opt-in via `RUN_LIVE=1` (defaults off). Verified **18/
|
|
|
297
313
|
|
|
298
314
|
## Change history
|
|
299
315
|
|
|
316
|
+
- 2026-07-23 — **READ-ACL grant BUILT — launch blocker resolved** (TRUE-79533, committed `b74f42a`).
|
|
317
|
+
Added `dbchanges2/Client_Rate/2026-07-23a - EntitlementServiceAddressIdFieldPermission.sql`: a
|
|
318
|
+
READ-only (`isWritable = 0`) `AclFieldPermissions` grant for the standard `serviceAddressId`,
|
|
319
|
+
resolving field ids cross-schema (route `entitlements`), `NOT EXISTS`-guarded. Final scope
|
|
320
|
+
corrected vs. the earlier proposal: **`Client_Rate` (not a `Client/` fan-out), role 1 only** —
|
|
321
|
+
mirroring the sibling standard FK `saleItemId`'s reader role (role 1 is the sole actual reader,
|
|
322
|
+
the toga2-view service cards). Recorded the reusable platform fact that **`AclFieldPermissions`
|
|
323
|
+
has no `isReadable` column — row presence grants READ, `isWritable` additionally grants WRITE**
|
|
324
|
+
(verified in `api2/Component/Api/V2/V2.php` `getAclFieldPermissions()` ~line 5731), which is why
|
|
325
|
+
a custom→standard promotion must re-create the read grant as an `AclFieldPermissions` row.
|
|
326
|
+
(mhammontree)
|
|
300
327
|
- 2026-07-23 — **LAUNCH BLOCKER found: the standard `serviceAddressId` field has NO read ACL grant**
|
|
301
328
|
(tcox). Probe-verified on beta: `GET /v2/entitlements?fields=serviceAddressId` → 403 `EZ-2` for
|
|
302
329
|
roles 1/2/4 (`aclDatabase=CLIENT`). Standard fields are authorized via **`AclFieldPermissions`**
|
package/package.json
CHANGED