toga-ai 1.0.937 → 1.0.938
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.
|
@@ -16,6 +16,7 @@ files:
|
|
|
16
16
|
- template/pages/dashboard.php
|
|
17
17
|
- config.prod.ini
|
|
18
18
|
- dbchanges2/Core/2026-10-02a - TogaDeskSsoDomain.sql
|
|
19
|
+
- dbchanges2/Core/2026-10-02b - TogaDeskSsoDomainReuseRow.sql
|
|
19
20
|
related:
|
|
20
21
|
- ./staff-login-authentication.md
|
|
21
22
|
- ../architecture.md
|
|
@@ -29,7 +30,7 @@ related:
|
|
|
29
30
|
TOGa Desk staff "Sign in with SSO" via saml.togahub.com (TRUE-78064, `Sso` class, Tools pattern); open before touching SSO login, the `?saml=` return, the `[saml]` config, or the TogaDesk Core.Domains row.
|
|
30
31
|
|
|
31
32
|
## Summary
|
|
32
|
-
TRUE-78064 replaces Active Directory for **TOGA staff** with SSO through `saml.togahub.com`, copying the Tools `App_Sso` pattern. Status 2026-10-02:
|
|
33
|
+
TRUE-78064 replaces Active Directory for **TOGA staff** with SSO through `saml.togahub.com`, copying the Tools `App_Sso` pattern. Status 2026-10-02: committed on branch `TRUE-78064` (togadesk `f6f850af`, dbchanges2 `1338980` + `4b677cb`), prod Core.Domains row in place, **not deployed**. The return leg can only be fully tested in prod (prod key).
|
|
33
34
|
|
|
34
35
|
Decisions (Mark + Brandon/call center, 2026-10-02):
|
|
35
36
|
- Staff only. Matched to an existing `TOGaDeskSupport.people` row by email. SSO **never creates** people rows — no row = cannot log in.
|
|
@@ -54,8 +55,10 @@ Decisions (Mark + Brandon/call center, 2026-10-02):
|
|
|
54
55
|
5. **`Sso::isAvailable()`** = every `[saml]` key set (`idp_single_sign_on_service_url`, `idp_entity_identifier`, `assertion_consumer_service_url`, `domain_uuid`, `true_client_uuid`, `return_url`), `[database_true]` + `[database_toga2core]` hostnames set, and `HTTP_HOST` == host of `[saml] return_url`. It does **not** call `getRestrictedClient()` (the root portal also calls it). So client custom-URL hosts never show the button.
|
|
55
56
|
6. **Buttons** on both the root portal login card (`template/pages/dashboard.php` — the page staff land on at `/`) and `/desk/?route=signin` (where failures return).
|
|
56
57
|
|
|
57
|
-
### Core.Domains row (
|
|
58
|
-
`uuid d1e526b9-e2fb-4462-935f-ed449e8f5986` (= `[saml] domain_uuid`), `clientId 1` (True), `appId 18` (togadesk-1,
|
|
58
|
+
### Core.Domains row (prod id 261)
|
|
59
|
+
`uuid d1e526b9-e2fb-4462-935f-ed449e8f5986` (= `[saml] domain_uuid`), `clientId 1` (True), `appId 18` (togadesk-1, confirmed in prod), `environmentId 1`, `domain https://togadesk.togatech.com/desk/`. Domain must have **no query string** — see the [gateway contract](../../../2.0/apps/saml/features/downstream-integration-contract.md).
|
|
60
|
+
- `2026-10-02a` (INSERT) inserted **0 rows** in prod: slot (1, 18, 1) was already taken by id 261, an unused seed row `https://devteam.togadesk.worker.agilantsolutions.com` (old uuid `6ec4d305-104f-5c6f-8589-ed4382d8a77c`). It stays as a harmless no-op.
|
|
61
|
+
- `2026-10-02b` UPDATEs id 261 to the uuid + domain above, guarded on old uuid + old domain + client/app/env. Run and verified on prod Core by Mark 2026-10-02. Config `domain_uuid` did not change.
|
|
59
62
|
|
|
60
63
|
### Kill switch
|
|
61
64
|
Set `[saml] domain_uuid = ""` in `config.prod.ini` and deploy → button hidden, SSO off, password login unaffected.
|
|
@@ -69,4 +72,5 @@ Set `[saml] domain_uuid = ""` in `config.prod.ini` and deploy → button hidden,
|
|
|
69
72
|
- **Local testing ends at the gateway.** Gateway "Invalid SAMLResponse (Code = 2)" locally = local `Core_2.Parameters` key differs from prod. Expected; not a code bug.
|
|
70
73
|
|
|
71
74
|
## Change history
|
|
75
|
+
- 2026-10-02 — Domains INSERT was a no-op in prod (slot held by devteam seed row 261); repointed that row via `2026-10-02b`; committed, not deployed (mhammontree)
|
|
72
76
|
- 2026-10-02 — Created: staff SSO button + `Sso` class, prod-only, staff matched by email, no auto-create (TRUE-78064, not yet deployed) (mhammontree)
|
|
@@ -53,7 +53,7 @@ all encrypted under the Core `API_SECRET_ACCESS_TOKEN`. `urlParameters` from Rel
|
|
|
53
53
|
Exact build (`saml/Controller/Index.php` ~L459): `$domain->domain . '?saml=' . $authPayload . '&urlParameters=' . …`. So:
|
|
54
54
|
- The `Core.Domains.domain` value **must have no query string** — the gateway appends `?saml=` blindly.
|
|
55
55
|
- The payload is base64 but **not urlencoded** — a `+` arrives as a space; the consumer must `strtr(' ', '+')` before decoding.
|
|
56
|
-
- `Core.Domains` has UNIQUE(clientId, appId, environmentId) and a unique `domain`, so an app gets **one return URL per client + app + environment**.
|
|
56
|
+
- `Core.Domains` has UNIQUE(clientId, appId, environmentId) (`Domains_clientId_IDX`, `dbchanges2/Core/HISTORIC/2024/2024-01-01.sql`) and a unique `domain`, so an app gets **one return URL per client + app + environment**.
|
|
57
57
|
|
|
58
58
|
Known 1.0 consumers (all True staff): [Tools](../../../1.0/apps/tools/features/saml-sso-auth.md), [TOGa Desk](../../../1.0/apps/togadesk/features/staff-sso-login.md).
|
|
59
59
|
|
|
@@ -64,12 +64,14 @@ The downstream app then base64-decodes the `saml` param, JSON-parses it, decrypt
|
|
|
64
64
|
2. Implement/extend `_Model_<Client>_ClientAuthentication::getAuthenticatedSsoUser()` in `_underscore` (the gateway repo is not modified — see the per-client extension pattern in the architecture doc).
|
|
65
65
|
3. Initiate SSO via `singleSignOnServiceUrl()`.
|
|
66
66
|
4. Consume the `?saml=` handoff and decrypt the UUIDs with `API_SECRET_ACCESS_TOKEN`.
|
|
67
|
+
5. Register the return domain in `Core.Domains` — **check the (clientId, appId, environmentId) slot first** (see Gotchas).
|
|
67
68
|
|
|
68
69
|
## Gotchas
|
|
69
70
|
|
|
70
71
|
- **Lazy-transaction write-drop.** `_Database::register()` auto-starts a lazy transaction (since Apr 2026). Any `/acs` write path (e.g. user auto-creation) must call `_Database::transactionCommit()` before exit or the writes are silently rolled back.
|
|
71
72
|
- **Gateway holds no session** — every downstream app must build and own its own session from the decrypted handoff.
|
|
72
73
|
- **"Invalid SAMLResponse (Code = 2)"** from the gateway = RelayState could not be decrypted with Core `API_SECRET_ACCESS_TOKEN` / `_PREVIOUS`. Seen when testing from local: local `Core_2.Parameters` key ≠ prod key. A full return-leg test needs the prod `Core.Domains` row + a deploy.
|
|
74
|
+
- **⚠ The Domains slot is often already taken.** Old seed rows `devteam.<app>.worker.agilantsolutions.com` (e.g. ids 259 sync, 260 toga, 261 togadesk) hold the (clientId, appId, environmentId) slot for many apps, and nothing uses them. A guarded `INSERT … WHERE NOT EXISTS` then silently inserts 0 rows. Query the slot first; if a dead seed row holds it, **UPDATE that row** (uuid + domain, guarded on its old uuid + domain) instead of inserting. No FK references `Domains.uuid`, so changing it is safe once no app config uses the old uuid. Example: TOGa Desk `2026-10-02b` ([staff SSO](../../../1.0/apps/togadesk/features/staff-sso-login.md)).
|
|
73
75
|
- **The handoff is not replay-safe** — no issue time or single-use id. See [acs trust gaps](./acs-assertion-trust-gaps.md).
|
|
74
76
|
|
|
75
77
|
## Related
|
|
@@ -79,4 +81,5 @@ The downstream app then base64-decodes the `saml` param, JSON-parses it, decrypt
|
|
|
79
81
|
- [Rate SAML SSO](../../../clients/rate/features/saml-sso.md)
|
|
80
82
|
|
|
81
83
|
## Change history
|
|
84
|
+
- 2026-10-02 — Gotcha: check/reuse the Domains slot (devteam seed rows) before inserting (mhammontree)
|
|
82
85
|
- 2026-10-02 — Documented exact return-URL build (no query string in domain, unencoded base64), one domain per client+app+env, Code 2 meaning, TOGa Desk as consumer (mhammontree)
|
|
@@ -42,7 +42,7 @@ The public **TOGA Technology website** (repo `togatech`, standalone React SPA, a
|
|
|
42
42
|
|
|
43
43
|
The **Tools** app (1.0; repo `tools`) authenticates True users via **SSO** through `saml.togahub.com` and reads the `Client_True` DB **read-only** to gate its internal tooling by staff persona (see `1.0/apps/tools/`). Its gateway return domain is registered in `Core.Domains` (`uuid 2927bc15-e347-4358-a430-fb28f9446d27`, `clientId 1`, `appId 30`, env 1, `https://tools.togatech.com/sso`).
|
|
44
44
|
|
|
45
|
-
**TOGa Desk** (1.0; repo `togadesk`) staff sign in via the same True SSO (TRUE-78064, prod only, not deployed as of 2026-10-02): True user email → one AD People row → existing `TOGaDeskSupport.people` row; no auto-create. Domain row `uuid d1e526b9-e2fb-4462-935f-ed449e8f5986`, `clientId 1`, `appId 18`, env 1, `https://togadesk.togatech.com/desk
|
|
45
|
+
**TOGa Desk** (1.0; repo `togadesk`) staff sign in via the same True SSO (TRUE-78064, prod only, not deployed as of 2026-10-02): True user email → one AD People row → existing `TOGaDeskSupport.people` row; no auto-create. Domain row id 261 (repointed from an unused devteam seed row) `uuid d1e526b9-e2fb-4462-935f-ed449e8f5986`, `clientId 1`, `appId 18`, env 1, `https://togadesk.togatech.com/desk/` — live in prod Core 2026-10-02. See [TOGa Desk staff SSO](../../1.0/apps/togadesk/features/staff-sso-login.md).
|
|
46
46
|
|
|
47
47
|
## ⚠ "Base" maps to Super User in Client_True
|
|
48
48
|
|
package/package.json
CHANGED