toga-ai 1.0.514 → 1.0.516

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  | Doc | Summary | Files |
4
4
  |-----|---------|-------|
5
- | [TOGa Desk Architecture](architecture.md) | TOGa Desk is the staff-facing support desk **and field-service platform** (analysts work at `/desk/`). | desk/index.php, desk/includes/loader.php, desk/config.php, desk/includes/controllers/actions.php, desk/includes/controllers/data.php, desk/includes/controllers/modals.php, desk/includes/classes/class.app.php, desk/includes/classes/class.ticket.php, desk/api/index.php, desk/api/resources/tickets.php, crons/tickets.php |
5
+ | [TOGa Desk Architecture](architecture.md) | TOGa Desk is the staff-facing support desk **and field-service platform** (analysts work at `/desk/`). | desk/index.php, desk/includes/loader.php, desk/config.php, desk/includes/controllers/actions.php, desk/includes/controllers/data.php, desk/includes/controllers/modals.php, desk/includes/classes/class.app.php, desk/includes/classes/class.ticket.php, desk/api/index.php, desk/api/resources/tickets.php, crons/tickets.php, desk/includes/functions.php, desk/template/header.php, ebs/setup_phpini.php |
6
6
  | [Email-to-Ticket Intake (crons/tickets.php)](features/email-to-ticket-intake.md) | TOGa Desk ingests support email into tickets through a cron-driven IMAP poller (`crons/tickets.php`) plus a postfix pipe variant (`crons/pipe.php`). | crons/tickets.php, crons/tickets_prod.php, crons/pipe.php, desk/includes/classes/class.ticket.php, vendor/classes/class.imap.php |
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 |
@@ -6,7 +6,7 @@ project: TOGa Desk
6
6
  client: shared
7
7
  type: architecture
8
8
  status: active
9
- updated: 2026-06-15
9
+ updated: 2026-08-04
10
10
  owners: ["mhammontree", "jcardinal"]
11
11
  files:
12
12
  - desk/index.php
@@ -20,7 +20,11 @@ files:
20
20
  - desk/api/index.php
21
21
  - desk/api/resources/tickets.php
22
22
  - crons/tickets.php
23
+ - desk/includes/functions.php
24
+ - desk/template/header.php
25
+ - ebs/setup_phpini.php
23
26
  related:
27
+ - 1.0/apps/togadesk/features/per-client-host-restriction.md
24
28
  - 1.0/apps/togaview/architecture.md
25
29
  - 1.0/apps/togadesk/features/ticket-lifecycle.md
26
30
  - 1.0/apps/togadesk/features/smb-contract-editing.md
@@ -65,6 +69,12 @@ sibling repo `togaview`).
65
69
  | actions | `?action=` | `controllers/actions.php` | CRUD; `isAuthorized()` → domain class → status code → `reroute()` |
66
70
  | data | always | `controllers/data.php` | populate page context; route-specific `controllers/data/<route>.php` |
67
71
  - **Render** (when no modal/qa): `template/header.php` + `template/pages/<route>.php` + `template/footer.php`.
72
+ - **Host-based per-client restriction.** `getRestrictedClient()` in `desk/includes/functions.php`
73
+ (~L1513-1592) maps the request `HTTP_HOST` to a `CLIENT_*` constant via a hardcoded switch
74
+ (e.g. `rumcsi.togadesk.togatech.com` → `CLIENT_RUMCSI`), and `restrictByClient()` (L1508) gates
75
+ navigation/menus in `desk/template/header.php` (~L1638-1665) and the ticket datatables under
76
+ `_/browser/datatable/tickets/*`. This is an entry/UI gate only — **record-level tenancy still
77
+ comes from the session `clientid`, not the host.** See the per-client-host-restriction feature doc.
68
78
  - Unmatched `?action=` values fall back to `controllers/actions/<action>.php` — so actions live
69
79
  either inline in `actions.php` or as files under `controllers/actions/<domain>/`.
70
80
 
@@ -197,6 +207,16 @@ Invariants:
197
207
  - The API has **no pagination** — `get` returns full result sets; Medoo `filters` pass straight
198
208
  to the WHERE clause.
199
209
  - The prod O365 OAuth secret used by `crons/tickets_prod.php` has a **hard expiry (~2026-12-20)**.
210
+ - **Cross-tenant login hole in the per-client host restriction (pre-existing, NOT fixed).** The
211
+ password-login access condition in `desk/includes/functions.php` (~L627-631) is a chain of ORs;
212
+ two clauses grant access regardless of which client's subdomain is in use, letting an IM Houston
213
+ or Fordham user sign in on another client's branded host. Post-login filtering keys off the
214
+ session `clientid` so it is not an immediate record leak, but it defeats the restriction and
215
+ contradicts the comment directly above it. Deserves its own ticket.
216
+ - **Sessions are host-scoped, so a domain change logs everyone out.** `ebs/setup_phpini.php` sets
217
+ `session.save_handler=rediscluster` but no `session.cookie_domain`, and there is no
218
+ `session_set_cookie_params()` anywhere. Combined with `people.sessionid` being a **single
219
+ column**, logging in on a second domain invalidates the session on the first.
200
220
 
201
221
  ## Related docs
202
222
  - [TOGa View architecture](../togaview/architecture.md)
@@ -70,15 +70,22 @@ The app code is the easy part. What actually bites:
70
70
  `redirectTo` NULL unless you specifically want a redirect. Example (RUMCSI cutover, 2026-08-04):
71
71
  `hostName = 'rumcsi.togadesk.togatech.com'`, `redirectTo = NULL` (id 253 — the id is
72
72
  auto-assigned and carries no meaning).
73
- - **Enforcement location is UNVERIFIED / needs tracing.** The DB row and the behavior are
74
- developer-confirmed, but the code performing the check was **not** found on 2026-08-04. Greps
75
- across `togadesk`, `library`, `togaview` and `_underscore` for `CopyrightHosts`, `Vision_Log`,
76
- `copyright`, `unauthoriz` and `hostName` surfaced no host-authorization check. The only related
77
- hook is `App_Framework_Index::copyrightFooter()` (`library/app/frameworkindex.php` L152-157),
78
- which emits the copyright footer div and registers a final JS call `initializeCopyright();` —
79
- and `initializeCopyright` is **defined nowhere in the library repo** (that is its only call
80
- site), suggesting the check is served remotely or lives in another app/asset. Start there if you
81
- need to trace it; do not assume anything further.
73
+ - **Enforcement location is STILL UNLOCATED (behavior is confirmed; the code is not).** As of
74
+ 2026-08-04 the check is **not present** in `togadesk`, `library`, `togaview`, `_underscore`, or
75
+ the shared front-end assets repo (`C:\WWW\resources`, not yet in `registry.json`) by grep for
76
+ `CopyrightHosts`, `Vision_Log`, `copyright`, `unauthoriz` and `hostName`.
77
+ - **The `copyrightFooter()` / `initializeCopyright()` lead is POSITIVELY EXCLUDED — do not
78
+ re-chase it.** `initializeCopyright()` *is* defined, in the shared assets repo at
79
+ `resources/library.js` L1075-1078, and it is **purely cosmetic**: it wires `window.onscroll`
80
+ plus a 300ms `setInterval` to `checkCopyrightPosition()` (L1068-1074), which only toggles
81
+ `position: relative` on `#copyrightFooter` when the document is taller than the window. No
82
+ network call, no hostname read, no license logic. The same repo has **no** first-party JS
83
+ reading `location.host` or `document.domain` (only vendored libraries match) and no
84
+ CopyrightHosts / unauthorized-use logic at all.
85
+ - **Remaining candidates to try next:** (a) a server-side check in another app that owns the
86
+ `Vision_Log` schema — i.e. the Vision/TOGa side, not the desk repos; (b) a minified or
87
+ obfuscated asset; (c) something entirely outside these repos. Until one is confirmed, treat the
88
+ behavior as authoritative and the mechanism as unknown.
82
89
  - **This check appears to be cross-app**, i.e. 1.0 apps generally (via `library`), not
83
90
  togadesk-specific — it is documented here because that is where it was discovered. If it is later
84
91
  confirmed framework-wide it may belong in a library/framework-level doc; flag that move rather
@@ -133,3 +140,8 @@ The app code is the easy part. What actually bites:
133
140
  `Vision_Log.CopyrightHosts` or the app shows an unauthorized-use screen. Row inserted for
134
141
  `rumcsi.togadesk.togatech.com`. Enforcement code not located — marked UNVERIFIED with the
135
142
  `copyrightFooter()` / `initializeCopyright()` lead. (mhammontree)
143
+ - 2026-08-04 — Corrected the CopyrightHosts enforcement-location caveat: `initializeCopyright()` is
144
+ defined in `resources/library.js` (L1075-1078) and is purely cosmetic footer positioning, so that
145
+ lead is ruled out; the shared assets repo contains no host-authorization logic. Enforcement
146
+ remains unlocated; next candidates recorded. Behavior and the STEP 1 checklist entry unchanged.
147
+ (mhammontree)
@@ -26,11 +26,15 @@ updated: 2026-08-04
26
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
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
28
 
29
+ - **`Vision_Log.CopyrightHosts` row added (developer-supplied — the step this review MISSED).** TOGa 1.0 apps run a license/anti-piracy host-authorization check ("call home") against `Vision_Log.CopyrightHosts` keyed on `hostName`; with no matching row the app renders an **unauthorized-use error screen** instead of the application, regardless of DNS, cert, ALB, or `getRestrictedClient()`. The developer inserted the row: id 253, `hostName` = `rumcsi.togadesk.togatech.com`, `redirectTo` = NULL. This is now **step 1** of the add-a-hostname checklist in the feature doc.
30
+
29
31
  ## What did NOT work — DO NOT RETRY THESE
30
32
  - **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.
33
+ - **Do NOT expect to find the CopyrightHosts enforcement code by grepping the repos — it is not there.** Searched togadesk, library, togaview and `_underscore` for `CopyrightHosts`, `Vision_Log`, `copyright`, `unauthoriz` and `hostName`: no host-authorization check exists in source. The only lead is `App_Framework_Index::copyrightFooter()` at `library/app/frameworkindex.php` L152-157, which emits the footer div and registers a final JS call `initializeCopyright();` — and `initializeCopyright` is **defined nowhere in the library repo** (that call site is the only occurrence). The check is therefore served remotely or lives in another app/asset. Treat the enforcement location as unverified; start tracing from `initializeCopyright`.
31
34
  - **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
35
 
33
36
  ## Not tried yet (candidates for next session)
37
+ - **Trace where the `Vision_Log.CopyrightHosts` check is actually enforced**, starting from `initializeCopyright()` (registered at `library/app/frameworkindex.php` L157, defined nowhere in `library`). Once located, this likely belongs in a `1.0` library/framework-level doc or a `1.0/standards` rule ("every new 1.0 hostname must be registered in `Vision_Log.CopyrightHosts`") rather than the togadesk feature doc — the capture agent flagged that placement change as deferred pending this trace. Also confirm what `redirectTo` does when non-NULL.
34
38
  - **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
39
  - **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
40
  - **Fix the cross-tenant login hole** at `desk/includes/functions.php` ~L627-631 — needs its own ticket (see Decisions).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.514",
3
+ "version": "1.0.516",
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",