toga-ai 1.0.502 → 1.0.503

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.
@@ -7,6 +7,7 @@
7
7
  | [Field-Service Dispatch (central / repair orders)](features/field-service-dispatch.md) | The **central** subsystem is TOGa Desk's field-service dispatch domain: repair-order lifecycle, technician scheduling, onsite vs depot service, parts, and shipm | desk/includes/controllers/actions/central/, desk/includes/classes/class.repair.php, desk/includes/classes/class.repairhistory.php, desk/_/browser/datatable/central.php, desk/template/pages/central.php, desk/template/pages/central/view.php, desk/template/modals/central/addTracking.php, library/app/model/togadesk/repairorder.php, library/app/model/togadesk/repairordertracking.php, library/app/api/carrier/ups.php |
8
8
  | [Managed Service Order Create Flow (New MSO modal → tickets/add)](features/managed-service-order-create.md) | The **Managed Service Order (MSO) create flow** is how a TOGa Desk user manually creates a managed service order: pick an End User (or a Client Location), choos | desk/includes/controllers/actions/tickets/add.php, desk/template/modals/tickets/addNew.php, desk/template/pages/managed.php, desk/template/pages/getinfo.php, desk/template/footer.php, library/app/model/togadesk/repairorder.php |
9
9
  | [Ticket Email Notifications (notifications table)](features/notifications.md) | Which TOGa Desk emails fire for a given client is driven **entirely by data**, not code: the `TOGaDeskSupport.notifications` table holds one row per `(clientid, | desk/includes/classes/class.notification.php, crons/tickets.php, crons/tickets_prod.php |
10
+ | [Per-Client Hostname Restriction (getRestrictedClient)](features/per-client-host-restriction.md) | TOGa Desk supports **per-client branded URLs** (e.g. | desk/includes/functions.php, desk/template/header.php, _/browser/datatable/tickets, desk/includes/classes/class.ticket.php, ebs/setup_phpini.php, ebs/http_to_https.php, desk/template/modals/kb/viewDocument.php, desk/template/modals/files/aws-view.php, desk/template/modals/files/contract-view.php, template/pages/documents/view.php, template/pages/tasks/view.php |
10
11
  | [REST API (RPC-over-POST) & API-Key Auth](features/rest-api.md) | TOGa Desk exposes a programmatic API at `desk/api/`. | desk/api/index.php, desk/api/resources/tickets.php, desk/api/resources/assets.php, desk/api/resources/authenticate.php, desk/includes/classes/class.apikey.php, desk/includes/functions.php |
11
12
  | [SMB Contract Editing & the clientMspId Corruption Trap](features/smb-contract-editing.md) | The SMB contracts page (`/desk/?route=toga/smbcontracts&togaClientId=<id>`) edits `TOGA_*.SMBContracts` rows via a modal. | desk/template/modals/toga/smbcontracts/smbContract.php, desk/includes/controllers/modals/toga/smbcontracts/smbContract.php, desk/includes/controllers/actions/toga/smbcontracts/smbContract.php, desk/includes/controllers/actions/toga/smbcontracts/edit.php |
12
13
  | [Ticket Lifecycle (class.ticket.php)](features/ticket-lifecycle.md) | All TOGa Desk ticket creation and reply handling funnels through `Ticket` in `desk/includes/classes/class.ticket.php`. | desk/includes/classes/class.ticket.php, desk/includes/controllers/actions.php, desk/includes/controllers/actions/tickets/addReply.php, desk/api/resources/tickets.php, desk/api/resources/ticket_replies.php, crons/tickets.php, crons/pipe.php, desk/includes/controllers/actions/tickets/merge.php |
@@ -0,0 +1,107 @@
1
+ ---
2
+ title: Per-Client Hostname Restriction (getRestrictedClient)
3
+ framework: "1.0"
4
+ repo: togadesk
5
+ project: TOGa Desk
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-08-04
10
+ owners: ["mhammontree"]
11
+ files:
12
+ - desk/includes/functions.php
13
+ - desk/template/header.php
14
+ - _/browser/datatable/tickets
15
+ - desk/includes/classes/class.ticket.php
16
+ - ebs/setup_phpini.php
17
+ - ebs/http_to_https.php
18
+ - desk/template/modals/kb/viewDocument.php
19
+ - desk/template/modals/files/aws-view.php
20
+ - desk/template/modals/files/contract-view.php
21
+ - template/pages/documents/view.php
22
+ - template/pages/tasks/view.php
23
+ related:
24
+ - ../architecture.md
25
+ - ../../togaview/architecture.md
26
+ ---
27
+
28
+ ## Summary
29
+
30
+ TOGa Desk supports **per-client branded URLs** (e.g. `rumcsi.togadesk.togatech.com`). The whole
31
+ mechanism is host-based: `getRestrictedClient()` in `desk/includes/functions.php` (~L1513-1592)
32
+ derives a single "restricted client" from the request hostname, and `restrictByClient()` (L1508)
33
+ is the gate used throughout the UI. Adding a new per-client URL is therefore **one switch case
34
+ plus a lot of non-application work** (cert, sessions, hardcoded legacy domains).
35
+
36
+ This contradicts the impression that togadesk has no host-based logic — it does, and this is the
37
+ only place a new subdomain gets registered.
38
+
39
+ ## How it works
40
+
41
+ 1. `getRestrictedClient()` lowercases `$_SERVER['HTTP_HOST']`, strips the port, and matches a long
42
+ **hardcoded switch of per-client subdomains**, returning a `CLIENT_*` constant or `null`.
43
+ 2. Client-ID constants are defined in the same file (~L1488-1506):
44
+ `CLIENT_AGILANT=2`, `CLIENT_OFFICEDEPOT=3`, `CLIENT_RUMCSI=146`, `CLIENT_IMHOUSTON=167`,
45
+ `CLIENT_FORDHAM=179`.
46
+ 3. `restrictByClient()` (L1508) wraps that result and gates:
47
+ - navigation/menus in `desk/template/header.php` (~L1638-1665), and
48
+ - the ticket datatables under `_/browser/datatable/tickets/*`.
49
+ 4. Post-login data filtering keys off the **session `clientid`**, not the host — the host
50
+ restriction is a UI/entry gate, not the record-level tenancy boundary.
51
+
52
+ **TOGa View resolves its host separately.** `togaview/_/app/framework.php` has its own
53
+ `switch($_SERVER['HTTP_HOST'])` that sets `$_SESSION['stylePath']` and selects the RUMCSI SAML
54
+ branch; an unregistered hostname falls through to default branding and **skips SAML**. So a
55
+ togadesk-side DNS record is safe on its own, but any new *togaview* hostname must be added there
56
+ too. _(Carried from the togaview architecture doc — not re-verified in code on 2026-08-04.)_
57
+
58
+ ## Adding a new per-client TOGa Desk URL — checklist
59
+
60
+ The app code is the easy part. What actually bites:
61
+
62
+ - **Register the host** in the `getRestrictedClient()` switch (and add a `CLIENT_*` constant if the
63
+ client is new). Verified 2026-08-04: `rumcsi.togadesk.togatech.com` is **already a case**, so the
64
+ RUMCSI AWS DNS record needs no code change.
65
+ - **TLS cert.** A 4-label host such as `rumcsi.togadesk.togatech.com` is **not** covered by a
66
+ `*.togatech.com` wildcard. You need `*.togadesk.togatech.com` or an exact SAN on the ALB
67
+ listener, plus a host-header rule.
68
+ - **Sessions log everyone out on a domain change.** `ebs/setup_phpini.php` sets
69
+ `session.save_handler=rediscluster` but sets **no `session.cookie_domain`**, and there is no
70
+ `session_set_cookie_params()` anywhere — the cookie is host-scoped. Worse, `people.sessionid` is a
71
+ **single column**, so logging in on a second domain invalidates the session on the first.
72
+ - **Smoke-test Office document previews.** `desk/template/modals/kb/viewDocument.php`,
73
+ `modals/files/aws-view.php`, `modals/files/contract-view.php`, `template/pages/documents/view.php`
74
+ and `template/pages/tasks/view.php` embed `https://{HTTP_HOST}/...` into third-party viewers
75
+ (`docs.google.com/gview`, `view.officeapps.live.com`) which fetch **server-side**. On a host with
76
+ an untrusted cert, Word/Excel/PPT previews fail **silently** while same-origin PDF iframes still
77
+ work — making this the best post-cutover check.
78
+ - **Keep the old domain resolvable.** `class.ticket.php` L485-486 and L886-887 hardcode
79
+ `https://togadesk[-env].agilantsolutions.com/uploads/` when rewriting inline ticket images, so
80
+ outbound ticket emails keep serving images from the old domain. Other hardcoded legacy domains:
81
+ `csat.agilantsolutions.com`, `toga.agilantsolutions.com`,
82
+ `yourcloudhq.togaview.agilantsolutions.com`, and `toga_payment_easyurl` / `fullurl` in every
83
+ `config.*.ini`.
84
+
85
+ ## Gotchas / known issues
86
+
87
+ - **Cross-tenant login hole (pre-existing, NOT fixed — deserves its own ticket).** The
88
+ password-login access condition in `desk/includes/functions.php` (~L627-631) is a chain of ORs,
89
+ and two clauses grant access **regardless of which client's subdomain is in use**:
90
+ `getRestrictedClient() != CLIENT_AGILANT && $restrictedClientId == CLIENT_IMHOUSTON` lets an IM
91
+ Houston user log in on the RUMCSI host, and
92
+ `getRestrictedClient() != CLIENT_FORDHAM && $restrictedClientId == CLIENT_FORDHAM` does the same
93
+ for Fordham. Post-login filtering keys off the session `clientid`, so it is not an immediate
94
+ record leak, but it **defeats the per-client URL restriction and contradicts the comment directly
95
+ above it** (L627-629). Recommended fix: replace with an explicit per-restricted-client allowlist
96
+ using guard clauses. Anyone touching login or adding a client URL must know this.
97
+ - **`siteURL()` emits `http://` behind the ALB.** `desk/includes/functions.php` (~L22-31) only emits
98
+ `https` when `$_SERVER['HTTPS'] == 'on'`; behind the ALB only `X-Forwarded-Proto` is set (see
99
+ `ebs/http_to_https.php`). It currently has **no callers** in togadesk — a latent trap for any new
100
+ absolute-link code.
101
+ - The host switch and the client-ID constants are hardcoded — there is no DB-driven mapping, so
102
+ every new branded URL is a code change.
103
+
104
+ ## Change history
105
+
106
+ - 2026-08-04 — Documented from a read-only review (TRUE-80139) of the RUMCSI branded-URL cutover;
107
+ recorded the add-a-hostname checklist and the cross-tenant login hole. No code changed. (mhammontree)
@@ -8,7 +8,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
8
8
  - **worker** (Worker) — 18 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)
11
- - **togadesk** (TOGa Desk) — 10 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
11
+ - **togadesk** (TOGa Desk) — 11 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
12
12
  - **togaview** (TOGa View) — 6 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
13
13
  - **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
14
14
  - **walmarttechservices** (Walmart Tech Services) — 1 doc(s) → [1.0/apps/walmarttechservices/INDEX.md](1.0/apps/walmarttechservices/INDEX.md)
@@ -56,6 +56,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
56
56
  - **Prudential Financial** (`prudential`) → [clients/prudential/INDEX.md](clients/prudential/INDEX.md)
57
57
  - **Quad Graphics** (`quad`) → [clients/quad/INDEX.md](clients/quad/INDEX.md)
58
58
  - **Rate** (`rate`) → [clients/rate/INDEX.md](clients/rate/INDEX.md)
59
+ - **Richmond University Medical Center** (`rumcsi`) → [clients/rumcsi/INDEX.md](clients/rumcsi/INDEX.md)
59
60
  - **Tow Foundation** (`tow-foundation`) → [clients/tow-foundation/INDEX.md](clients/tow-foundation/INDEX.md)
60
61
  - **TOGA Technology** (`true`) → [clients/true/INDEX.md](clients/true/INDEX.md)
61
62
  - **Walmart Client Profile** (`walmart`) → [clients/walmart/INDEX.md](clients/walmart/INDEX.md)
@@ -0,0 +1,5 @@
1
+ # Client: Richmond University Medical Center `rumcsi`
2
+
3
+ | Doc | Framework | Summary | Files |
4
+ |-----|-----------|---------|-------|
5
+ | [Richmond University Medical Center](profile.md) | 1.0 | Richmond University Medical Center (**RUMCSI**) is a framework **1.0** client served by **TOGa Desk** (staff/analyst side) and **TOGa View** (client portal). | |
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: "Richmond University Medical Center"
3
+ framework: "1.0"
4
+ apps:
5
+ - togadesk
6
+ - togaview
7
+ - library
8
+ project: TOGa Desk
9
+ client: rumcsi
10
+ type: profile
11
+ status: active
12
+ updated: 2026-08-04
13
+ owners: ["mhammontree"]
14
+ files: []
15
+ related:
16
+ - ../../1.0/apps/togadesk/features/per-client-host-restriction.md
17
+ - ../../1.0/apps/togadesk/architecture.md
18
+ - ../../1.0/apps/togaview/architecture.md
19
+ ---
20
+
21
+ ## Summary
22
+
23
+ Richmond University Medical Center (**RUMCSI**) is a framework **1.0** client served by
24
+ **TOGa Desk** (staff/analyst side) and **TOGa View** (client portal). Its TOGa Desk
25
+ `clients.clientId` is **146**, exposed in code as the constant `CLIENT_RUMCSI` in
26
+ `desk/includes/functions.php`.
27
+
28
+ ## Platform footprint
29
+
30
+ - **Branded per-client URL.** RUMCSI is one of the clients gated by TOGa Desk's host-based
31
+ restriction: `rumcsi.togadesk.togatech.com` is already a case in `getRestrictedClient()`, which
32
+ returns `CLIENT_RUMCSI` and drives `restrictByClient()` nav/menu and ticket-datatable scoping.
33
+ See [Per-client hostname restriction](../../1.0/apps/togadesk/features/per-client-host-restriction.md)
34
+ for the full add-a-hostname checklist (cert scope, host-scoped sessions, hardcoded legacy domains).
35
+ - **TOGa View SAML.** `togaview/_/app/framework.php` has a RUMCSI-specific host branch that selects
36
+ branding (`$_SESSION['stylePath']`) and the SAML login path — an unregistered togaview hostname
37
+ falls through to default branding and skips SAML.
38
+ - **Hardcoded client-ID branching.** RUMCSI appears in TOGa Desk's hardcoded client-ID branching
39
+ (`central` dispatch, `tickets/add`) — verify the RUMCSI arm before changing shared logic.
40
+
41
+ ## Change history
42
+
43
+ - 2026-08-04 — Client profile created during the TRUE-80139 read-only review of the RUMCSI branded
44
+ TOGa Desk URL. (mhammontree)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.502",
3
+ "version": "1.0.503",
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",