toga-ai 1.0.502 → 1.0.504

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)
@@ -0,0 +1,64 @@
1
+ ---
2
+ type: session
3
+ slug: true-80139-togadesk-rumcsi-url-review
4
+ title: TRUE-80139 — impact review of new RUMCSI togadesk hostname
5
+ author: mhammontree
6
+ repos: [togadesk, togaview, library]
7
+ framework: "1.0"
8
+ client: rumcsi
9
+ status: active
10
+ created: 2026-08-04
11
+ updated: 2026-08-04
12
+ ---
13
+
14
+ # Session: true-80139-togadesk-rumcsi-url-review
15
+ **Date:** 2026-08-04
16
+ **Project/Repo:** togadesk (1.0)
17
+ **Task:** TRUE-80139 — a new AWS DNS record was created so `https://rumcsi.togadesk.togatech.com` resolves; review the TOGa Desk 1.0 code to determine whether the new hostname breaks or degrades the RUMCSI (Richmond University Medical Center, clientId 146) experience. Read-only review — no code was changed.
18
+
19
+ ---
20
+
21
+ ## What WORKED
22
+ - **Confirmed the new hostname needs no code change.** `getRestrictedClient()` in `togadesk/desk/includes/functions.php` (~L1513-1592) lowercases `HTTP_HOST`, strips the port (L1516), and matches a hardcoded switch of per-client subdomains. `rumcsi.togadesk.togatech.com` is **already** a case at L1538 returning `CLIENT_RUMCSI` (=146, L1498). Evidence: read the switch directly; the `.togatech.com` variants for all 7 envs are present alongside the legacy `.agilantsolutions.com` ones.
23
+ - **Traced what the restriction actually gates.** `restrictByClient()` (L1508) drives nav/menu visibility in `togadesk/desk/template/header.php` (~L1638-1665: policies, issues) and the ticket datatables in `togadesk/_/browser/datatable/tickets/{all,active,highpriority,awaitingreply}.php` (each at ~L36 and ~L240). Record-level tenancy comes from the session `clientid`, not the host — confirmed via `_/app/ajax.php` and `desk/includes/controllers/modals.php` which branch on `$liu['clientid'] == CLIENT_RUMCSI`.
24
+ - **Confirmed the HTTPS redirect is host-preserving.** `togadesk/ebs/http_to_https.php` writes `RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}` keyed off `X-Forwarded-Proto` — no hardcoded domain, so it follows the new host.
25
+ - **Confirmed no SAML/SSO redirect-URI exposure in togadesk.** Grepped all `config.*.ini` for `saml|acs|entityid|sso` — zero hits. TOGa Desk's AD login is direct LDAP bind (`.ebextensions/008_setup_ldap.config`), which has no per-host callback URL to re-register. (The SAML concern is a *togaview* concern, not togadesk.)
26
+ - **Confirmed no host allowlist at the web-server layer.** `ebs/apache_settings.php` only tunes prefork/MaxRequestWorkers; root `.htaccess` is empty. Nothing rejects an unrecognized `Host` header.
27
+ - **Capture published.** `knowledge/1.0/apps/togadesk/features/per-client-host-restriction.md` and `knowledge/clients/rumcsi/profile.md` created and pushed to `_main` (validate OK, 30 repos; index rebuilt, 312 docs; mirrored to `C:\WWW\.claude\knowledge`).
28
+
29
+ ## What did NOT work — DO NOT RETRY THESE
30
+ - **Do NOT trust the `context-primer` briefing on this topic — it was wrong.** The primer asserted "TogaDesk (`desk/`) is staff-only — it resolves the logged-in user via session, not via subdomain/hostname… there isn't any host-based branching in TogaDesk architecture doc," and concluded a new hostname "doesn't map into TogaDesk's client-selection logic at all." That is false: `getRestrictedClient()` is exactly that logic. The primer was faithfully reporting `knowledge/1.0/apps/togadesk/architecture.md`, which **still** describes the request pipeline as having no host-based logic. Root cause is the stale architecture doc, not the agent. Read `desk/includes/functions.php` L1508-1592 as ground truth.
31
+ - **Searching `config.*.ini` for the session cookie domain found nothing** — not a failed approach so much as a null result worth not repeating: there is no `session.cookie_domain` and no `session_set_cookie_params()` anywhere in the repo. `ebs/setup_phpini.php` sets only `session.save_handler=rediscluster`, `session.save_path` (the `asi-session-cache` cluster endpoint), and `session.gc_maxlifetime=345600`. Cookie scoping is therefore PHP's host-only default, by omission.
32
+
33
+ ## Not tried yet (candidates for next session)
34
+ - **Verify the TLS cert and ALB listener rule** for the 4-label host `rumcsi.togadesk.togatech.com`. A `*.togatech.com` wildcard does **not** cover it — it needs `*.togadesk.togatech.com` or that exact SAN, plus a host-header rule routing to the togadesk environment. Not verifiable from this repo; `ebs/register_instance_to_shared_application_load_balancer.php` contains no host/rule logic (grepped: zero matches for host|rule|rumcsi|togadesk).
35
+ - **Post-cutover smoke test of Office document previews.** `desk/template/modals/kb/viewDocument.php` (~L28) and `desk/template/modals/files/aws-view.php` (~L21), plus `desk/template/modals/files/contract-view.php`, `template/pages/documents/view.php` (~L38), `template/pages/tasks/view.php` (~L48) embed `https://{HTTP_HOST}/...` into `docs.google.com/gview` and `view.officeapps.live.com`, which fetch **server-side**. An untrusted cert breaks Word/Excel/PPT previews silently while same-origin PDF iframes keep working. Test one Office doc on the new host.
36
+ - **Fix the cross-tenant login hole** at `desk/includes/functions.php` ~L627-631 — needs its own ticket (see Decisions).
37
+ - **Apply the 4 held edits to `knowledge/1.0/apps/togadesk/architecture.md`** — drafted by the capture agent, unapplied, still accurate. Needs `jcardinal`'s sign-off (co-owner).
38
+ - **Check whether RUMCSI end users were also given a togaview hostname.** `togaview/_/app/framework.php` has its own `switch ($_SERVER['HTTP_HOST'])` setting `$_SESSION['stylePath']` and the rumcsi SAML branch; an unregistered host falls through to default branding and skips SAML. Not read this session — sourced from the togaview architecture doc, so treat as unverified.
39
+ - **Decide the fate of the legacy `agilantsolutions.com` domain.** `desk/includes/classes/class.ticket.php` L485-486 and L886-887 hardcode `https://togadesk[-env].agilantsolutions.com/uploads/` when rewriting inline ticket images, so outbound ticket emails keep serving images from the old domain regardless of which host the staff member used. Other hardcoded old-domain links: `csat.agilantsolutions.com` (`class.ticket.php` L902, `class.repair.php` L605), `toga.agilantsolutions.com` (`desk/template/pages/tickets/manage.php` L1203, `toga/smbcontracts/manage.php` L106), `yourcloudhq.togaview.agilantsolutions.com` (`toga/smbcontracts/resendemail.php` L36, `resendToAllEmail.php` L38), and `toga_payment_easyurl`/`toga_payment_fullurl` in every `config.*.ini`.
40
+
41
+ ## Current file state
42
+ | File | Status | Notes |
43
+ |------|--------|-------|
44
+ | `togadesk/**` | unchanged | Read-only review. No source file was created, modified, or deleted this session. |
45
+ | `knowledge/1.0/apps/togadesk/features/per-client-host-restriction.md` | created + pushed | Owns all findings: host resolution, add-a-hostname checklist, `siteURL()` trap, cross-tenant login hole, togaview switch (flagged unverified). |
46
+ | `knowledge/clients/rumcsi/profile.md` | created + pushed | New client onboarding — "Richmond University Medical Center", clientId 146 / `CLIENT_RUMCSI`, `apps: [togadesk, togaview, library]`. |
47
+ | `knowledge/1.0/apps/togadesk/architecture.md` | **NOT modified — 4 edits held** | Elevated, co-owned by `jcardinal`. Held edits: bump `updated` to 2026-08-04; add `desk/includes/functions.php`, `desk/template/header.php`, `ebs/setup_phpini.php` to `files:` and the new feature doc to `related:`; add a host-based-restriction bullet under "Entry points & request pipeline"; add two Gotchas bullets (cross-tenant login hole, host-scoped sessions). Doc currently still claims the pipeline has no host-based logic — **incorrect**. |
48
+ | `.claude/toga-ai.version` | updated | Harness auto-updated v1.0.500 → v1.0.502 during `/kickoff` Step 0. |
49
+
50
+ ## Decisions made
51
+ - **Closed TRUE-80139 as no-code-change-required.** Rationale: the hostname is already registered in `getRestrictedClient()`, and Jonathan confirmed the site works with no issues observed. Rejected alternative: adding the host to the switch — unnecessary, it is already there at L1538.
52
+ - **The cross-tenant login hole gets its own ticket, not a fix inside TRUE-80139.** At `desk/includes/functions.php` ~L627-631 the access condition is a chain of ORs; two clauses grant access regardless of which client's subdomain is in use — `(getRestrictedClient() != CLIENT_AGILANT && $restrictedClientId == CLIENT_IMHOUSTON)` lets an IM Houston user (167) log in on the RUMCSI host, and `(getRestrictedClient() != CLIENT_FORDHAM && $restrictedClientId == CLIENT_FORDHAM)` lets a Fordham user (179) do the same. Post-login filtering keys off the session `clientid`, so it is not an immediate record leak, but it defeats the per-client URL restriction and contradicts the comment directly above it at L627-629. Rationale for separating: pre-existing, not a regression from the DNS change, and the fix (an explicit per-restricted-client allowlist with guard clauses) is a behavior change needing its own testing. Rejected alternative: fixing it inline — would have expanded a read-only review into an auth change on a live client host.
53
+ - **Published the two RUMCSI docs but held the `architecture.md` edits.** Rationale: the developer approved "the docs for RUMCSI"; `architecture.md` is co-owned by `jcardinal` and the edits are cross-references, so nothing substantive is lost by holding them — every finding lives in the feature doc. Rejected alternative: pushing all three — would have edited a senior-owned doc on an ambiguous approval.
54
+ - **Treated "users will be logged out" as expected, not a defect.** Sessions are host-scoped by cookie default and `people.sessionid` is a single column updated on login (`functions.php` L635), so a domain switch forces re-login and a second-domain login invalidates the first session. Rationale: correct multi-tenant behavior; scoping the cookie to `.togatech.com` would share sessions across every client subdomain, which is worse.
55
+
56
+ ## Blockers
57
+ - **`architecture.md` correction is blocked on `jcardinal`** (co-owner of an elevated doc). Until applied, the doc actively misleads: it says the TOGa Desk request pipeline has no host-based logic, which is what sent the `context-primer` down the wrong path this session.
58
+ - **Cert/ALB verification is blocked on AWS access** — not answerable from the togadesk repo. Jonathan's confirmation that the site works is strong evidence the cert and listener rule are already correct, but the Office-preview path (third-party server-side fetch) has not been exercised.
59
+
60
+ ## Exact next step
61
+ > Open a new ticket for the cross-tenant login hole at `togadesk/desk/includes/functions.php` L631, quoting the two offending OR clauses (`$restrictedClientId == CLIENT_IMHOUSTON` and `$restrictedClientId == CLIENT_FORDHAM`), and propose replacing the whole condition with an explicit per-restricted-client allowlist using guard clauses. Then ping `jcardinal` to approve the 4 held edits to `knowledge/1.0/apps/togadesk/architecture.md` (drafted in this session's capture — re-run `/capture` in `apply-approved` mode once he signs off).
62
+
63
+ ---
64
+ _Saved by /session-save on 2026-08-04_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.502",
3
+ "version": "1.0.504",
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",