toga-ai 1.0.569 → 1.0.570
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.
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
| Doc | Summary | Files |
|
|
4
4
|
|-----|---------|-------|
|
|
5
5
|
| [Library (1.0 Framework) Architecture](architecture.md) | `library` is the shared library repository for **all 1.0 (legacy) applications** — the `App_` framework. | library/_.php, library/app/, library/browser/ |
|
|
6
|
+
| [Address Validation Gateway (App_Api_OfficeDepot::validateAddress + USPS fallback)](features/address-validation-gateway.md) | `App_Api_OfficeDepot::validateAddress()` is the shared 1.0 (`App_`) address-validation gateway. | library/app/api/officedepot.php, library/app/api/usps.php |
|
|
6
7
|
| [Where a new App_ class goes — the app/ folder IS a behavioral contract](features/app-class-placement-base-contracts.md) | In `library/app/`, choosing a folder is **not** a filing decision — the autoloader maps `App_<Folder>_<File>` to `app/<folder>/<file>.php`, and each folder's ba | library/app/model.php, library/app/client.php, library/app/api.php, library/app/api/servicerequest.php, library/app/api/volt.php, library/app/api/carrier/fedex.php |
|
|
7
8
|
| [App_Sso — Reusable 1.0 SSO Initiation (SP-initiated SAML via saml.togahub.com)](features/app-sso-initiation.md) | `App_Sso` (`library/app/sso.php`) is the **1.0 port of the 2.0 SAML gateway's SP-initiated SSO initiation**, packaged as a reusable, framework-level capability | library/app/sso.php, library/sso/togahub_private_key.key |
|
|
8
9
|
| [Cron Execution Monitoring (App_Framework check-in/out → CronJobExecutions)](features/cron-execution-monitoring.md) | `App_Framework::cronInitialization()` / `App_Framework::cronFinished()` (in `library/app/framework.php`) give every 1.0 (`App_`) cron job a check-in/check-out l | library/app/framework.php |
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Address Validation Gateway (App_Api_OfficeDepot::validateAddress + USPS fallback)
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: library
|
|
5
|
+
project: Library
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-08-13
|
|
10
|
+
owners: [jcardinal]
|
|
11
|
+
files:
|
|
12
|
+
- library/app/api/officedepot.php
|
|
13
|
+
- library/app/api/usps.php
|
|
14
|
+
related:
|
|
15
|
+
- ../../toga/features/odp-customer-search-loyalty-persistence.md
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Summary
|
|
19
|
+
`App_Api_OfficeDepot::validateAddress()` is the shared 1.0 (`App_`) address-validation gateway.
|
|
20
|
+
It is the entry point every TOGa 1.0 flow calls (via classic AJAX
|
|
21
|
+
`ajaxAction('App_Api_OfficeDepot','validateAddress')`) to standardize/verify a typed address
|
|
22
|
+
before it is saved. It wraps ODP's address-validation service and falls back to
|
|
23
|
+
`App_Api_USPS::validateAddress()` (USPS REST API v3, OAuth `client_credentials`, in
|
|
24
|
+
`library/app/api/usps.php`). It returns a standardized address (corrected city/casing/zip) that
|
|
25
|
+
callers are expected to write back before saving.
|
|
26
|
+
|
|
27
|
+
## Key files / entry points
|
|
28
|
+
- `library/app/api/officedepot.php` — `App_Api_OfficeDepot::validateAddress()`, the gateway.
|
|
29
|
+
- `library/app/api/usps.php` — `App_Api_USPS::validateAddress()`, the fallback carrier.
|
|
30
|
+
|
|
31
|
+
## How it works
|
|
32
|
+
1. **Endpoint selection.** The gateway calls the ODP **sandbox** endpoint when
|
|
33
|
+
`App_Registry::inTestMode()` is true (`inTestMode` = `config['internal']['test_mode'] > 0`),
|
|
34
|
+
and the **live** ODP endpoint otherwise. Production is effectively hard-pinned to live
|
|
35
|
+
(comment "2024-01-22 JC - Always using production...").
|
|
36
|
+
2. **On a real ODP answer** (HTTP 200, whether it accepts or rejects the address) the gateway
|
|
37
|
+
returns ODP's standardized result.
|
|
38
|
+
3. **On any non-200 ODP response** (sandbox down/expired, etc.) it falls back to
|
|
39
|
+
`App_Api_USPS::validateAddress()` and returns the USPS result — a genuine standardization
|
|
40
|
+
**or** a genuine bad-address rejection both count as a real answer and are returned.
|
|
41
|
+
4. **Only when BOTH ODP and USPS are unavailable** does it return `array('success' => true)`
|
|
42
|
+
with no standardized fields (fail-open, so associates are never hard-blocked by an outage).
|
|
43
|
+
|
|
44
|
+
## Gotchas / known issues
|
|
45
|
+
- **Beta-bypass class of bug (fixed 2026-08-13).** Previously the ODP-failure `else` branch
|
|
46
|
+
returned `array('success' => true)` with **no** standardized address fields and the USPS
|
|
47
|
+
fallback was commented out. Beta/test uses the ODP **sandbox**; when the sandbox was
|
|
48
|
+
down/expired, callers saw `success:true` and saved the **raw typed address** (wrong city,
|
|
49
|
+
wrong casing) with no validation. Production was unaffected because it hits the working live
|
|
50
|
+
ODP endpoint. The fix restores the USPS fallback so a validation only truly fails open when
|
|
51
|
+
**both** carriers are down.
|
|
52
|
+
- **"Both unavailable" must check BOTH USPS service-down strings.** USPS signals unavailability
|
|
53
|
+
two ways: `'Address validation service is temporarily unavailable'` **and**
|
|
54
|
+
`'USPS OAuth authentication failed'`. The fail-open condition must match either. Checking only
|
|
55
|
+
the first string wrongly blocks associates when ODP is down *and* USPS OAuth also fails
|
|
56
|
+
(a php-reviewer pass caught this).
|
|
57
|
+
- **Front-end write-back anti-pattern (widespread, mostly UNFIXED).** Many 1.0 front-end
|
|
58
|
+
callbacks use the gateway response only as a pass/fail **gate**, then rebuild the save payload
|
|
59
|
+
from the raw DOM inputs — discarding the standardized `address1`/`city`/`state`/`zipCode` the
|
|
60
|
+
gateway returned. So even a successful validation never persists the corrected address. Known
|
|
61
|
+
flows with this anti-pattern still present:
|
|
62
|
+
`toga/app/togarefresh2026/servicerequests/finalizequote.php`,
|
|
63
|
+
`toga/app/togarefresh2026/appointment/select.php`,
|
|
64
|
+
`toga/app/servicerequests/builder.php`, `toga/app/loaners/checkout.php`,
|
|
65
|
+
`toga/app/jobjackets/view.php`, and the `togarefresh2023` variants. The 2026-08-13 gateway fix
|
|
66
|
+
protects all of them from the beta bypass, but the write-back was only corrected in the
|
|
67
|
+
`togarefresh2026` customersearch flow (see related doc). When touching any of these, write the
|
|
68
|
+
standardized address back into the inputs before building the save payload.
|
|
69
|
+
|
|
70
|
+
## Related docs
|
|
71
|
+
- `../../toga/features/odp-customer-search-loyalty-persistence.md` — the customersearch save
|
|
72
|
+
flow, where the write-back fix was applied.
|
|
73
|
+
|
|
74
|
+
## Change history
|
|
75
|
+
- 2026-08-13 — Fix: restored the USPS fallback in `App_Api_OfficeDepot::validateAddress` so the
|
|
76
|
+
beta/sandbox path no longer fakes `success:true` and saves unvalidated addresses; fail-open now
|
|
77
|
+
requires BOTH ODP and USPS down, checking both USPS service-down strings. (jcardinal)
|
|
@@ -6,13 +6,14 @@ project: TOGa
|
|
|
6
6
|
client: office-depot
|
|
7
7
|
type: client-feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-08-
|
|
9
|
+
updated: 2026-08-13
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- toga/app/togarefresh2026/customersearch/view.php
|
|
13
13
|
- library/app/model/customer.php
|
|
14
14
|
related:
|
|
15
15
|
- ./bundleconfirmation-cart-preservation.md
|
|
16
|
+
- ../../library/features/address-validation-gateway.md
|
|
16
17
|
---
|
|
17
18
|
|
|
18
19
|
## Summary
|
|
@@ -47,6 +48,18 @@ field.
|
|
|
47
48
|
## Data model
|
|
48
49
|
- `Customers.merchantId` (TOGA_ODP legacy DB) — stores the ODP loyalty/rewards `memberId`.
|
|
49
50
|
|
|
51
|
+
## Standardized-address write-back (Next button flow)
|
|
52
|
+
The "Existing PC Services" flow — `content=togarefresh2026_customersearch`, Next button
|
|
53
|
+
(`#nextSubmit`) → `validateAddress()` → JS callback `validateAddressResponse(resp)` — used the
|
|
54
|
+
gateway response only as a pass/fail gate, then rebuilt the save `formData` from the raw DOM
|
|
55
|
+
inputs and called `App_Model_Customer::saveNewCustomer` — discarding `resp['address1']`/`city`/
|
|
56
|
+
`state`/`zipCode`, so the validated casing/city/zip never persisted. Fixed 2026-08-13: before
|
|
57
|
+
building `formData`, the callback now writes the standardized address from `resp` back into the
|
|
58
|
+
`streetAddress`/`line2`/`city`/`state`/`zip` inputs (guarded on `resp['address1']` present), so
|
|
59
|
+
the corrected address is what gets saved. The gateway itself lives in `library` — see
|
|
60
|
+
`../../library/features/address-validation-gateway.md`, which lists the many other 1.0 flows
|
|
61
|
+
that still have this write-back anti-pattern.
|
|
62
|
+
|
|
50
63
|
## Gotchas / known issues
|
|
51
64
|
- **`saveNewCustomer` has two callers.** `togarefresh2026` now sends `merchantId`;
|
|
52
65
|
`togarefresh2023` does **not**. The `!empty()` guard is what keeps the 2023 flow safe — it
|
|
@@ -64,6 +77,9 @@ field.
|
|
|
64
77
|
- `./bundleconfirmation-cart-preservation.md`
|
|
65
78
|
|
|
66
79
|
## Change history
|
|
80
|
+
- 2026-08-13 — Fix: `validateAddressResponse` now writes the standardized address from the
|
|
81
|
+
validation gateway back into the form inputs before saving, so validated city/casing/zip
|
|
82
|
+
persist (previously the response was used only as a pass/fail gate). (jcardinal)
|
|
67
83
|
- 2026-08-10 — Fix: ODP loyalty number now persists to Customers.merchantId across the
|
|
68
84
|
togarefresh2026 customer-search save flow (front end + saveNewCustomer), guarded by !empty().
|
|
69
85
|
Flagged a pre-existing SQL-injection risk in the same method for follow-up. (jcardinal)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -4,7 +4,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
4
4
|
|
|
5
5
|
## 1.0 framework
|
|
6
6
|
|
|
7
|
-
- **library** (Library) _(framework core)_ —
|
|
7
|
+
- **library** (Library) _(framework core)_ — 18 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
|
|
8
8
|
- **worker** (Worker) — 23 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
|
|
9
9
|
- **dbchanges** (Database Changes) _(framework core)_ — 1 doc(s) → [1.0/apps/dbchanges/INDEX.md](1.0/apps/dbchanges/INDEX.md)
|
|
10
10
|
- **worker1.5** (Worker 1.5) — 0 doc(s) → [1.0/apps/worker1.5/INDEX.md](1.0/apps/worker1.5/INDEX.md)
|
package/package.json
CHANGED