toga-ai 1.0.67 → 1.0.69
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.
- package/knowledge/1.0/apps/togadesk/INDEX.md +8 -0
- package/knowledge/1.0/apps/togadesk/architecture.md +87 -0
- package/knowledge/1.0/apps/togadesk/features/smb-contract-editing.md +90 -0
- package/knowledge/1.0/apps/togadesk/features/ticket-lifecycle.md +102 -0
- package/knowledge/1.0/apps/togadesk/workflows/standalone-test-scripts.md +49 -0
- package/knowledge/1.0/apps/togaview/INDEX.md +8 -0
- package/knowledge/1.0/apps/togaview/architecture.md +67 -0
- package/knowledge/1.0/apps/togaview/features/login-flows.md +65 -0
- package/knowledge/1.0/apps/togaview/features/msp-dashboard.md +84 -0
- package/knowledge/1.0/apps/togaview/features/ticket-detail-page.md +76 -0
- package/knowledge/INDEX.md +2 -0
- package/knowledge/registry.json +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# togadesk (TogaDesk) — 1.0 knowledge
|
|
2
|
+
|
|
3
|
+
| Doc | Summary | Files |
|
|
4
|
+
|-----|---------|-------|
|
|
5
|
+
| [TogaDesk Architecture](architecture.md) | TogaDesk is the staff-facing support desk (analysts work at `/desk/`). | desk/includes/classes/class.ticket.php, desk/includes/controllers/actions.php, desk/api/resources/tickets.php, crons/tickets.php |
|
|
6
|
+
| [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 |
|
|
7
|
+
| [Ticket Lifecycle (class.ticket.php)](features/ticket-lifecycle.md) | All TogaDesk 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/api/resources/tickets.php, crons/tickets.php, desk/includes/controllers/actions/tickets/merge.php |
|
|
8
|
+
| [Standalone PHP Test Script Bootstrap (TogaDesk)](workflows/standalone-test-scripts.md) | How to write a standalone CLI PHP script that bootstraps the TogaDesk framework for read-only testing of desk classes (e.g. | |
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TogaDesk Architecture
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togadesk
|
|
5
|
+
project: TogaDesk
|
|
6
|
+
client: shared
|
|
7
|
+
type: architecture
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- desk/includes/classes/class.ticket.php
|
|
13
|
+
- desk/includes/controllers/actions.php
|
|
14
|
+
- desk/api/resources/tickets.php
|
|
15
|
+
- crons/tickets.php
|
|
16
|
+
related:
|
|
17
|
+
- 1.0/apps/togaview/architecture.md
|
|
18
|
+
- 1.0/apps/togadesk/features/ticket-lifecycle.md
|
|
19
|
+
- 1.0/apps/togadesk/features/smb-contract-editing.md
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Summary
|
|
23
|
+
TogaDesk is the staff-facing support desk (analysts work at `/desk/`). It is a framework 1.0
|
|
24
|
+
(`App_`) app bootstrapped from the `library` core (`_.php`). The on-disk repo root contains
|
|
25
|
+
legacy top-level code; **the live application root is `desk/`** — e.g. the live
|
|
26
|
+
`class.ticket.php` is `desk/includes/classes/class.ticket.php`, while the root
|
|
27
|
+
`includes/classes/class.ticket.php` is an ancient variant that must never be extended.
|
|
28
|
+
|
|
29
|
+
## System topology
|
|
30
|
+
| System | Serves | DB connections |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| TogaDesk (`desk/`) | Staff/analysts | `db_togadesk` (TOGaDeskSupport), `db_toga` (TOGA), `db_client_aig`, per-client by name |
|
|
33
|
+
| TogaView (sibling repo) | Clients at `<client>.togaview.com` | same cluster, same link names |
|
|
34
|
+
|
|
35
|
+
- **TogaDesk and TogaView share the `TOGaDeskSupport` database** — tickets, clients,
|
|
36
|
+
contacts, departments, ClientMsp all live there. A change to ticket data semantics affects
|
|
37
|
+
both apps.
|
|
38
|
+
- All legacy databases (TOGaDeskSupport, TOGA, TOGA_*, RetailServices) are on the same MySQL
|
|
39
|
+
cluster, so cross-schema joins (e.g. `TOGaDeskSupport.ClientMsp` from a `db_toga`
|
|
40
|
+
connection) work and are used everywhere.
|
|
41
|
+
- `db_X` link names resolve generically to `[database_X]` sections in the per-environment
|
|
42
|
+
`config.<env>.ini`. Environment comes from the `ENVIRONMENT` env var — it defaults to
|
|
43
|
+
`worker` if unset, so a CLI script without it fails looking for `config.worker.ini`.
|
|
44
|
+
|
|
45
|
+
## The MSP data model (the core of everything)
|
|
46
|
+
```
|
|
47
|
+
TOGaDeskSupport.clients (togadesk client)
|
|
48
|
+
▲ clientId
|
|
49
|
+
TOGaDeskSupport.ClientMsp (id, clientId, type ENUM 'msp'|'reseller',
|
|
50
|
+
▲ ticketDepartmentId, companyName)
|
|
51
|
+
│ clientMspId
|
|
52
|
+
TOGaDeskSupport.ClientMspContacts(togadeskContactId → TOGaDeskSupport.contacts.id)
|
|
53
|
+
= the people who get MSP logins in togaview
|
|
54
|
+
|
|
55
|
+
TOGA.Clients (toga client registry; togadeskClientId, databaseName)
|
|
56
|
+
TOGA_<databaseName>.SMBContracts (clientMspId → ClientMsp.id, mainContactId,
|
|
57
|
+
serviceSeats, dateContractEnd)
|
|
58
|
+
TOGA_*.SMBContractItems (seats; serviceRequestId NULL = open seat)
|
|
59
|
+
TOGA_*.ServiceRequests (contactId → Contacts.id)
|
|
60
|
+
TOGA_*.Contacts (customerId → Customers.id)
|
|
61
|
+
TOGA_*.Customers (the managed business)
|
|
62
|
+
```
|
|
63
|
+
Invariants:
|
|
64
|
+
- An MSP's "customers" are **TOGA-side `Customers` rows**, NOT togadesk clients. All of an
|
|
65
|
+
MSP's tickets carry the MSP's own `tickets.clientid`.
|
|
66
|
+
- A togadesk client can own **multiple ClientMsp rows** (clients 18 and 26 do). Never assume
|
|
67
|
+
exactly one.
|
|
68
|
+
- **Multiple TOGA clients can share one TOGA_* database** (e.g. TOGA clients 9 and 20 both
|
|
69
|
+
use `TOGA_True`). Any page listing `SMBContracts` for a `togaClientId` lists every tenant's
|
|
70
|
+
contracts in that database — the root of the clientMspId corruption bug.
|
|
71
|
+
- `tickets_departments.clientId` maps support departments to a togadesk client; a client can
|
|
72
|
+
have several, but `ClientMsp.ticketDepartmentId` holds only ONE — never build
|
|
73
|
+
department-scoping logic on it.
|
|
74
|
+
|
|
75
|
+
## Key flows
|
|
76
|
+
- All ticket creation/replies funnel through `Ticket` (`desk/includes/classes/`):
|
|
77
|
+
staff UI (`actions.php`), API (`desk/api/resources/tickets.php`), email intake
|
|
78
|
+
(`crons/tickets.php` IMAP poll → `emailToTicket()`), merge. See ticket-lifecycle feature doc.
|
|
79
|
+
- SMB contract administration edits TOGA_* `SMBContracts` from `/desk/?route=toga/smbcontracts`.
|
|
80
|
+
See smb-contract-editing feature doc.
|
|
81
|
+
|
|
82
|
+
## Key decisions
|
|
83
|
+
- `Ticket::deriveCustomerId()` (June 2026) resolves `tickets.customerid` at creation so
|
|
84
|
+
staff/API/email tickets are visible in the TogaView MSP portal; it returns null rather than
|
|
85
|
+
guess when ambiguous, and swallows (logs) exceptions so email intake is never blocked.
|
|
86
|
+
- DB access for tooling: legacy cluster via the TOGa Database Integration MCP, environment
|
|
87
|
+
`legacy`; schemas `TOGaDeskSupport`, `TOGA`, `TOGA_True`, etc.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: SMB Contract Editing & the clientMspId Corruption Trap
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togadesk
|
|
5
|
+
project: TogaDesk
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- desk/template/modals/toga/smbcontracts/smbContract.php
|
|
13
|
+
- desk/includes/controllers/modals/toga/smbcontracts/smbContract.php
|
|
14
|
+
- desk/includes/controllers/actions/toga/smbcontracts/smbContract.php
|
|
15
|
+
- desk/includes/controllers/actions/toga/smbcontracts/edit.php
|
|
16
|
+
related:
|
|
17
|
+
- 1.0/apps/togadesk/features/ticket-lifecycle.md
|
|
18
|
+
- 1.0/apps/togaview/features/msp-dashboard.md
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Summary
|
|
22
|
+
The SMB contracts page (`/desk/?route=toga/smbcontracts&togaClientId=<id>`) edits
|
|
23
|
+
`TOGA_*.SMBContracts` rows via a modal. Because multiple TOGA clients can share one TOGA_*
|
|
24
|
+
database, this page historically corrupted `clientMspId` on save — the root cause of MSP
|
|
25
|
+
portal users seeing "You have no assigned clients" in TogaView. Fixed June 2026.
|
|
26
|
+
|
|
27
|
+
## Key files / entry points
|
|
28
|
+
- Modal template: `desk/template/modals/toga/smbcontracts/smbContract.php`
|
|
29
|
+
- Modal controller: `desk/includes/controllers/modals/toga/smbcontracts/smbContract.php`
|
|
30
|
+
- Submit action: `desk/includes/controllers/actions/toga/smbcontracts/smbContract.php`
|
|
31
|
+
- `edit.php` in the same actions folder is a separate, partly-legacy path that does NOT touch
|
|
32
|
+
`clientMspId`.
|
|
33
|
+
- The same controller serves the CSP variant (`csp=true` → `type='reseller'`).
|
|
34
|
+
|
|
35
|
+
## How it works
|
|
36
|
+
The bug pattern (now guarded against):
|
|
37
|
+
1. Multiple TOGA clients share one TOGA_* database (e.g. TOGA clients 9 "True" and 20
|
|
38
|
+
"craftex" both use `TOGA_True`), so the contracts page under client A lists client B's
|
|
39
|
+
contracts too.
|
|
40
|
+
2. The modal's MSP dropdown was scoped to client A's `ClientMsp` rows; the contract's real MSP
|
|
41
|
+
wasn't an option; no option got `selected`; **the browser silently auto-selects the first
|
|
42
|
+
option**; saving wrote the wrong `clientMspId`.
|
|
43
|
+
3. TogaView msp_dashboard's `SMBContracts WHERE clientMspId = <session clientMspId>` then
|
|
44
|
+
matched nothing for the real MSP's users.
|
|
45
|
+
|
|
46
|
+
Fixes in place (June 2026):
|
|
47
|
+
- The modal appends the contract's current MSP to the option list when missing.
|
|
48
|
+
- The action only assigns a posted `clientMspId` that is `> 0` AND exists in `ClientMsp`
|
|
49
|
+
(`App_Model_TogaDesk_ClientMsp::exists()`); otherwise it keeps the stored value.
|
|
50
|
+
- `SMBContracts.clientMspId` is nullable — NEW + "None" saves NULL (fine).
|
|
51
|
+
|
|
52
|
+
## Data model
|
|
53
|
+
```
|
|
54
|
+
TOGaDeskSupport.clients (togadesk client)
|
|
55
|
+
▲ clientId
|
|
56
|
+
TOGaDeskSupport.ClientMsp (id, clientId, type ENUM 'msp'|'reseller',
|
|
57
|
+
▲ ticketDepartmentId, companyName)
|
|
58
|
+
│ clientMspId
|
|
59
|
+
TOGA.Clients (toga client registry; togadeskClientId, databaseName)
|
|
60
|
+
TOGA_<databaseName>.SMBContracts (clientMspId → ClientMsp.id, mainContactId,
|
|
61
|
+
serviceSeats, dateContractEnd)
|
|
62
|
+
```
|
|
63
|
+
- A togadesk client can own **multiple ClientMsp rows** (clients 18 and 26 do — mixes of msp
|
|
64
|
+
and reseller). Code must not assume exactly one.
|
|
65
|
+
- **Multiple TOGA clients can share one TOGA_* database** — any page listing `SMBContracts`
|
|
66
|
+
for a `togaClientId` actually lists every tenant's contracts in that database.
|
|
67
|
+
|
|
68
|
+
Integrity audit query (run per shared TOGA_* db, eyeball contractNumber vs companyName
|
|
69
|
+
mismatches):
|
|
70
|
+
```sql
|
|
71
|
+
SELECT sc.id, sc.contractNumber, sc.clientMspId, cm.companyName, cm.clientId
|
|
72
|
+
FROM SMBContracts sc
|
|
73
|
+
LEFT JOIN TOGaDeskSupport.ClientMsp cm ON cm.id = sc.clientMspId
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Client variations
|
|
77
|
+
None in code — uniform. Craftex reference values: togadesk clientid 169, ClientMsp 42, TOGA
|
|
78
|
+
client 20 (`TOGA_True`), SMBContract 230 (Customer 932297).
|
|
79
|
+
|
|
80
|
+
## Gotchas / known issues
|
|
81
|
+
- `dateContractEnd` in the past is display-only — it does not hide tickets in the MSP portal.
|
|
82
|
+
- `ClientMsp.ticketDepartmentId` holds only ONE department even when the client has several —
|
|
83
|
+
never build department logic on it (see TogaView msp-dashboard doc).
|
|
84
|
+
|
|
85
|
+
## Change history
|
|
86
|
+
- 2026-06-12 — documented; modal + action guards shipped to togadesk dev branch (mhammontree)
|
|
87
|
+
|
|
88
|
+
## Related docs
|
|
89
|
+
- [Ticket lifecycle](ticket-lifecycle.md)
|
|
90
|
+
- [TogaView MSP dashboard](../../togaview/features/msp-dashboard.md)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Ticket Lifecycle (class.ticket.php)
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togadesk
|
|
5
|
+
project: TogaDesk
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- desk/includes/classes/class.ticket.php
|
|
13
|
+
- desk/includes/controllers/actions.php
|
|
14
|
+
- desk/api/resources/tickets.php
|
|
15
|
+
- crons/tickets.php
|
|
16
|
+
- desk/includes/controllers/actions/tickets/merge.php
|
|
17
|
+
related:
|
|
18
|
+
- 1.0/apps/togadesk/features/smb-contract-editing.md
|
|
19
|
+
- 1.0/apps/togaview/features/msp-dashboard.md
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Summary
|
|
23
|
+
All TogaDesk ticket creation and reply handling funnels through `Ticket` in
|
|
24
|
+
`desk/includes/classes/class.ticket.php`. This doc covers the creation paths, the
|
|
25
|
+
`deriveCustomerId()` resolution added June 2026, and the `addReply()` status-transition
|
|
26
|
+
switch — including its known gaps.
|
|
27
|
+
|
|
28
|
+
⚠ There are TWO `class.ticket.php` files. The live one is
|
|
29
|
+
`desk/includes/classes/class.ticket.php`. The root `includes/classes/class.ticket.php` is an
|
|
30
|
+
ancient variant (random 6-digit ticket numbers, schema that no longer matches) — never extend it.
|
|
31
|
+
|
|
32
|
+
## Key files / entry points
|
|
33
|
+
Creation paths — all funnel through `Ticket::add($data)`:
|
|
34
|
+
- Staff UI: `desk/includes/controllers/actions.php` → `Ticket::add($_POST)`
|
|
35
|
+
- API: `desk/api/resources/tickets.php`
|
|
36
|
+
- Email intake: `crons/tickets.php` (IMAP poll per `tickets_departments.email`, called via
|
|
37
|
+
`tickets_<ENV>.php` wrappers; loads desk classes via `appClassAutoload`) →
|
|
38
|
+
`Ticket::emailToTicket()` → parses "Ticket #NNNNNNN" from subject → matched ticket ⇒
|
|
39
|
+
`addReply()`, else ⇒ `add()`.
|
|
40
|
+
- Ticket merge (`actions/tickets/merge.php`) inserts a master ticket directly — it copies
|
|
41
|
+
fields from the child, including `customerid` (since June 2026).
|
|
42
|
+
|
|
43
|
+
## How it works
|
|
44
|
+
|
|
45
|
+
### `Ticket::deriveCustomerId(int, string): ?int` (added June 2026)
|
|
46
|
+
Called from `add()` when no `customerId` was supplied — fixes MSP-portal-invisible tickets
|
|
47
|
+
(togaview MSP pages filter on `tickets.customerid`, which only togaview-side creation set;
|
|
48
|
+
staff/API/email tickets left it NULL).
|
|
49
|
+
|
|
50
|
+
Logic: collect ALL ClientMsp ids for the clientid (non-MSP ⇒ null) →
|
|
51
|
+
`TOGA.Clients.databaseName` → try email match against contracted end users
|
|
52
|
+
(`SMBContracts→SMBContractItems→ServiceRequests→Contacts`) → fallback to the MSP's **sole
|
|
53
|
+
distinct** customer via `SMBContracts.mainContactId`; multiple customers + no email match ⇒
|
|
54
|
+
null (never guess). Exceptions are logged and swallowed — the email cron must never be blocked.
|
|
55
|
+
|
|
56
|
+
Read-only test harness pattern: see the standalone-test-scripts workflow doc.
|
|
57
|
+
|
|
58
|
+
### `Ticket::addReply($data)` status transitions
|
|
59
|
+
When the caller supplies no status, a `switch ($ticket['status'])` decides. Pattern: staff
|
|
60
|
+
reply preserves "waiting" states; client reply moves to `Open`; Closed/Review → `Reopened`.
|
|
61
|
+
|
|
62
|
+
**The status write is gated on `isset($data['status'])`** — a status missing from the switch
|
|
63
|
+
means the reply lands but the ticket status silently never changes (no history entry, no queue
|
|
64
|
+
re-entry). That was the On Hold SLA bug; `case 'On Hold'` (admin ⇒ stays On Hold, client ⇒
|
|
65
|
+
Open) was added June 2026.
|
|
66
|
+
|
|
67
|
+
- Special case: an admin replying to their OWN ticket is treated as a user reply.
|
|
68
|
+
- Auto-assign on first staff reply requires the role perm `allowAutoAssign` via
|
|
69
|
+
profiles/profile_departments.
|
|
70
|
+
- Side integrations on reply: Syncro status push (`referenceId='SYNCRO'`), Talos AI summaries
|
|
71
|
+
(TogaIQ), merged-ticket fan-out (replies propagate to child tickets).
|
|
72
|
+
|
|
73
|
+
## Data model
|
|
74
|
+
- `TOGaDeskSupport.tickets` — `clientid`, `customerid` (TOGA `Customers.id`, drives MSP portal
|
|
75
|
+
visibility), `departmentid`, `email`, `status`. **No closed-date column.**
|
|
76
|
+
- `tickets_replies` (`newStatus`), `tickets_history`.
|
|
77
|
+
|
|
78
|
+
## Client variations
|
|
79
|
+
None — uniform. Pre-fix tickets for a given MSP client may need a one-time `customerid`
|
|
80
|
+
backfill (e.g. craftex:
|
|
81
|
+
`UPDATE TOGaDeskSupport.tickets SET customerid = 932297 WHERE clientid = 169 AND customerid IS NULL;`).
|
|
82
|
+
|
|
83
|
+
## Gotchas / known issues
|
|
84
|
+
- `'Resolved'` is STILL missing from the `addReply()` switch — a client reply to a Resolved
|
|
85
|
+
ticket changes nothing. Known gap, awaiting product decision.
|
|
86
|
+
- **There is NO 72-hour reopen window in code**, despite SME belief. `Closed` → `Reopened` is
|
|
87
|
+
unconditional, email intake has no age check, and the `tickets` table has no closed-date
|
|
88
|
+
column (close time would have to come from `tickets_replies.newStatus='Closed'` or
|
|
89
|
+
`tickets_history`). Implementing it is a product decision: what happens to a lapsed reply
|
|
90
|
+
(attach-but-closed / new ticket / bounce)?
|
|
91
|
+
- Legacy `togadesk/includes/class.ticket.php` has active email-reopen logic; the live
|
|
92
|
+
`desk/includes` version has it commented out — email replies never set status to "Reopened"
|
|
93
|
+
via `emailToTicket()`.
|
|
94
|
+
|
|
95
|
+
## Change history
|
|
96
|
+
- 2026-06-12 — documented from craftex MSP portal debugging session (mhammontree)
|
|
97
|
+
- 2026-06 — added `deriveCustomerId()`; added `On Hold` case to addReply() switch; merge
|
|
98
|
+
copies `customerid` (mhammontree)
|
|
99
|
+
|
|
100
|
+
## Related docs
|
|
101
|
+
- [SMB contract editing](smb-contract-editing.md)
|
|
102
|
+
- [TogaView MSP dashboard](../../togaview/features/msp-dashboard.md)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Standalone PHP Test Script Bootstrap (TogaDesk)
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togadesk
|
|
5
|
+
project: TogaDesk
|
|
6
|
+
client: shared
|
|
7
|
+
type: workflow
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files: []
|
|
12
|
+
related:
|
|
13
|
+
- 1.0/apps/togadesk/features/ticket-lifecycle.md
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Summary
|
|
17
|
+
How to write a standalone CLI PHP script that bootstraps the TogaDesk framework for
|
|
18
|
+
read-only testing of desk classes (e.g. `Ticket::deriveCustomerId()`), without running the
|
|
19
|
+
web stack. Example harness: `C:\WWW\test\@Mark\TOGaDeskSupport\test_derive_customer_id.php`
|
|
20
|
+
(local path — adapt per machine).
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
1. `chdir()` to the desk app root (`<togadesk>/desk`).
|
|
24
|
+
2. Fake `$_SERVER['SCRIPT_FILENAME']` so the framework resolves paths.
|
|
25
|
+
3. `require` the 1.0 framework bootstrap `<library>/_.php`, then desk `functions.php` +
|
|
26
|
+
`config.php`.
|
|
27
|
+
4. Register `vendorClassAutoload` / `appClassAutoload`, plus composer autoload.
|
|
28
|
+
5. Set the `ENVIRONMENT` env var BEFORE bootstrap (or default it in the script). If unset it
|
|
29
|
+
defaults to `worker` and the script dies looking for `config.worker.ini`.
|
|
30
|
+
6. Wrap `App_Framework_TOGaDesk::initialize()` in `ob_start()` … `ob_end_clean()` — the
|
|
31
|
+
framework echoes a Sentry warning during init, which marks headers as sent and makes the
|
|
32
|
+
session `ini_set()` throw.
|
|
33
|
+
7. Restore error/exception handlers after init to see real errors instead of the HTML error
|
|
34
|
+
page.
|
|
35
|
+
8. Skip medoo unless needed (PHP 8.2 deprecation noise); `App_Database` is enough.
|
|
36
|
+
|
|
37
|
+
## Systems involved
|
|
38
|
+
- `library` (1.0 framework core), togadesk desk classes, legacy MySQL cluster.
|
|
39
|
+
- DB link names (`db_togadesk`, `db_toga`, …) resolve to `[database_X]` sections in
|
|
40
|
+
`config.<ENVIRONMENT>.ini`.
|
|
41
|
+
|
|
42
|
+
## Edge cases & escalation
|
|
43
|
+
- "Sentry is not installed" output followed by an `ini_set` session error = you missed the
|
|
44
|
+
output-buffer wrap (step 6).
|
|
45
|
+
- Scripts should stay read-only against shared/mirrored data unless explicitly doing a data
|
|
46
|
+
fix.
|
|
47
|
+
|
|
48
|
+
## Change history
|
|
49
|
+
- 2026-06-12 — captured from deriveCustomerId test harness work (mhammontree)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# togaview (TogaView) — 1.0 knowledge
|
|
2
|
+
|
|
3
|
+
| Doc | Summary | Files |
|
|
4
|
+
|-----|---------|-------|
|
|
5
|
+
| [TogaView Architecture](architecture.md) | TogaView is the client-facing support portal, served per client at `<client>.togaview.com`. | index.php, _/app/framework.php, mvc/login/post.php |
|
|
6
|
+
| [TogaView Login Flows & Session Variables](features/login-flows.md) | `mvc/login/post.php` tries login flows in order; the first match wins. | mvc/login/post.php, _/app/framework.php |
|
|
7
|
+
| [MSP Dashboard & Ticket Visibility Rules](features/msp-dashboard.md) | Why tickets "disappear" in the TogaView client portal: different pages scope tickets **differently**, and the MSP pages depend on `tickets.customerid` and `SMBC | common/togaview/msp_dashboard.php, mvc/msp_client_dashboard, mvc/enterprise_dashboard, mvc/support/support.php |
|
|
8
|
+
| [Ticket Detail Page Security (common/togaview/ticket.php)](features/ticket-detail-page.md) | `common/togaview/ticket.php` is the ticket detail page for nearly ALL hosts — only towfoundation/newcenturyholdingsllc have their own variants; every other clie | common/togaview/ticket.php |
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TogaView Architecture
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togaview
|
|
5
|
+
project: TogaView
|
|
6
|
+
client: shared
|
|
7
|
+
type: architecture
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- index.php
|
|
13
|
+
- _/app/framework.php
|
|
14
|
+
- mvc/login/post.php
|
|
15
|
+
related:
|
|
16
|
+
- 1.0/apps/togadesk/architecture.md
|
|
17
|
+
- 1.0/apps/togaview/features/login-flows.md
|
|
18
|
+
- 1.0/apps/togaview/features/msp-dashboard.md
|
|
19
|
+
- 1.0/apps/togaview/features/ticket-detail-page.md
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Summary
|
|
23
|
+
TogaView is the client-facing support portal, served per client at `<client>.togaview.com`.
|
|
24
|
+
Framework 1.0 (`App_`) app bootstrapped from the `library` core (`_.php`). It shares the
|
|
25
|
+
`TOGaDeskSupport` database with TogaDesk (tickets, clients, contacts, departments, ClientMsp)
|
|
26
|
+
— see the TogaDesk architecture doc for the cluster topology and the full MSP data model;
|
|
27
|
+
those invariants apply here unchanged.
|
|
28
|
+
|
|
29
|
+
## Page routing (stylePath model)
|
|
30
|
+
`index.php → App_Framework_TogaView::renderIndex()` (in `_/app/framework.php`):
|
|
31
|
+
|
|
32
|
+
1. A giant `switch ($_SERVER['HTTP_HOST'])` sets `$_SESSION['stylePath']` (and sometimes
|
|
33
|
+
`$_SESSION['host']`). Client subdomains are **hardcoded** — a new client subdomain must be
|
|
34
|
+
added to this switch (e.g. `craftex.togaview.com` → stylePath `togatechnology`, no `host`).
|
|
35
|
+
2. Page files: `mvc/<page>/get.php` typically resolves the template as:
|
|
36
|
+
- host in `HOSTS_USING_TOGA_TECH_STYLE` (= `['towfoundation','newcenturyholdingsllc']`)
|
|
37
|
+
→ `common/<host>/<page>.php`;
|
|
38
|
+
- else `common/<stylePath>/<page>.php` if it exists;
|
|
39
|
+
- else **fallback `common/togaview/<page>.php`** — the generic implementation.
|
|
40
|
+
3. `common/togatechnology/` has only header/footer/sidebar — so most clients run the
|
|
41
|
+
**generic** `common/togaview/*.php` pages. Only towfoundation, newcenturyholdingsllc (and
|
|
42
|
+
partially rumcsi via inline branches) have real page variants.
|
|
43
|
+
|
|
44
|
+
**Implication:** a change to `common/togaview/<page>.php` affects nearly every client at
|
|
45
|
+
once; a per-client behavior change belongs in a host/stylePath variant or an inline branch.
|
|
46
|
+
|
|
47
|
+
## Session / identity model
|
|
48
|
+
Login (`mvc/login/post.php`) tries flows in order — Retail, MSP contact, SMB admin, end user,
|
|
49
|
+
plus inline client branches (staplesprotection) and SAML clients handled in `framework.php`
|
|
50
|
+
(rumcsi, newcenturyholdingsllc). **Each flow sets a different session shape**; notably
|
|
51
|
+
staplesprotection sets `$_SESSION['email']` (not `emailAddress`) and no `togadeskClientId`.
|
|
52
|
+
Full matrix: login-flows feature doc. Any page reading session identity must tolerate the
|
|
53
|
+
divergent shapes (read `emailAddress` with `email` fallback).
|
|
54
|
+
|
|
55
|
+
## Ticket visibility
|
|
56
|
+
Each page scopes tickets differently (msp_dashboard, msp_client_dashboard,
|
|
57
|
+
enterprise_dashboard, support.php) — see the msp-dashboard feature doc. The MSP portal
|
|
58
|
+
depends on `tickets.customerid` being populated (TOGA `Customers.id`), which TogaDesk's
|
|
59
|
+
`Ticket::deriveCustomerId()` now sets at creation.
|
|
60
|
+
|
|
61
|
+
## Key decisions
|
|
62
|
+
- The ticket detail page `common/togaview/ticket.php` enforces an ownership check (clientid
|
|
63
|
+
match OR requester-email match) on both ticket view and attachment download; the email arm
|
|
64
|
+
is intentionally NOT restricted to unassigned tickets (staplesprotection and support.php
|
|
65
|
+
semantics require it). See ticket-detail-page feature doc.
|
|
66
|
+
- New client onboarding touches at minimum: the HTTP_HOST switch in `framework.php`, a login
|
|
67
|
+
flow (or SAML branch), and possibly the `smbContractSkus` whitelist in `login/post.php`.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TogaView Login Flows & Session Variables
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togaview
|
|
5
|
+
project: TogaView
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- mvc/login/post.php
|
|
13
|
+
- _/app/framework.php
|
|
14
|
+
related:
|
|
15
|
+
- 1.0/apps/togaview/features/msp-dashboard.md
|
|
16
|
+
- 1.0/apps/togaview/features/ticket-detail-page.md
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Summary
|
|
20
|
+
`mvc/login/post.php` tries login flows in order; the first match wins. Each flow sets a
|
|
21
|
+
DIFFERENT session shape — any code reading session vars must know which flows set what.
|
|
22
|
+
Several production bugs (ownership checks rejecting valid users) came from assuming a
|
|
23
|
+
uniform session.
|
|
24
|
+
|
|
25
|
+
## How it works
|
|
26
|
+
|
|
27
|
+
| Flow | userType | Key session vars |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| Retail (walmart/walmartplus) | `RETAIL` | `togadeskClientId=11` (hardcoded), `emailAddress`, `supportSkuExists=true` |
|
|
30
|
+
| MSP contact (ClientMspContacts join) | `MSP` | `clientMspId`, `togadeskClientId` (=ClientMsp.clientId), `clientDepartmentId` (=ClientMsp.ticketDepartmentId), `emailAddress`, `customerId` → redirects `/msp_dashboard` |
|
|
31
|
+
| SMB admin (SMBContracts.mainContactId) | `CUSTOMER` | same family as MSP, `togadeskClientId` from ClientMsp.clientId |
|
|
32
|
+
| End user (SMBContractItems→ServiceRequests→Contacts) | `ENDUSER` | `emailAddress`, `clientMspId`, `togadeskClientId`, `clientDepartmentId`, `supportSkuExists` → `/enterprise_dashboard` |
|
|
33
|
+
| staplesprotection (inline, AIG-backed) | `ENDUSER` | ⚠ sets `$_SESSION['email']` **not** `emailAddress`, and **no `togadeskClientId`** |
|
|
34
|
+
| rumcsi / newcenturyholdingsllc (SAML in framework.php) | `ENDUSER`/`ADMIN` | `togadeskClientId` = their togadesk clientid; newcentury auto-creates `people` rows from SAML |
|
|
35
|
+
|
|
36
|
+
- `$_SESSION['supportSkuExists']` gates the entire ticket block on enterprise_dashboard. Set
|
|
37
|
+
by checking the contract's service SKU against a **hardcoded whitelist** in login/post.php
|
|
38
|
+
(`smbContractSkus` = [190001, 190002, 190003, 210001, 210002, 210003, 24477039, 160202,
|
|
39
|
+
160203]). New support SKUs must be added there.
|
|
40
|
+
- MSP logins join through `TOGaDeskSupport.ClientMspContacts` →
|
|
41
|
+
`TOGaDeskSupport.contacts` — a malformed contact email breaks the match (e.g. contact 76
|
|
42
|
+
"Wendy Williams" had `Wendy@craftex` missing `.com`).
|
|
43
|
+
|
|
44
|
+
## Data model
|
|
45
|
+
`TOGaDeskSupport.ClientMsp` / `ClientMspContacts` / `contacts`; TOGA-side
|
|
46
|
+
`SMBContracts` / `SMBContractItems` / `ServiceRequests` / `Contacts` for SMB admin and
|
|
47
|
+
end-user flows.
|
|
48
|
+
|
|
49
|
+
## Client variations
|
|
50
|
+
- walmart/walmartplus: hardcoded `togadeskClientId=11`.
|
|
51
|
+
- staplesprotection: inline branch, end-user style, divergent session keys (see table).
|
|
52
|
+
- rumcsi / newcenturyholdingsllc: SAML handled in `_/app/framework.php`, not login/post.php.
|
|
53
|
+
|
|
54
|
+
## Gotchas / known issues
|
|
55
|
+
- Code consuming the session must read `emailAddress` with an `email` fallback (and tolerate
|
|
56
|
+
missing `togadeskClientId`) or it rejects all staplesprotection users — this broke the
|
|
57
|
+
ticket.php ownership check until the fallback was added (June 2026).
|
|
58
|
+
- The flows are order-dependent: a contact matching an earlier flow never reaches later ones.
|
|
59
|
+
|
|
60
|
+
## Change history
|
|
61
|
+
- 2026-06-12 — documented from craftex MSP portal debugging session (mhammontree)
|
|
62
|
+
|
|
63
|
+
## Related docs
|
|
64
|
+
- [MSP dashboard & ticket visibility](msp-dashboard.md)
|
|
65
|
+
- [Ticket detail page](ticket-detail-page.md)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: MSP Dashboard & Ticket Visibility Rules
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togaview
|
|
5
|
+
project: TogaView
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- common/togaview/msp_dashboard.php
|
|
13
|
+
- mvc/msp_client_dashboard
|
|
14
|
+
- mvc/enterprise_dashboard
|
|
15
|
+
- mvc/support/support.php
|
|
16
|
+
related:
|
|
17
|
+
- 1.0/apps/togaview/features/login-flows.md
|
|
18
|
+
- 1.0/apps/togadesk/features/ticket-lifecycle.md
|
|
19
|
+
- 1.0/apps/togadesk/features/smb-contract-editing.md
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Summary
|
|
23
|
+
Why tickets "disappear" in the TogaView client portal: different pages scope tickets
|
|
24
|
+
**differently**, and the MSP pages depend on `tickets.customerid` and `SMBContracts`
|
|
25
|
+
integrity. Covers the per-page filters and the June 2026 multi-department stats fix.
|
|
26
|
+
|
|
27
|
+
## How it works
|
|
28
|
+
|
|
29
|
+
### Ticket filters per page
|
|
30
|
+
| Page | Ticket filter |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `common/togaview/msp_dashboard.php` (MSP/CUSTOMER) | per-customer counts: `clientid` + `customerid` + `departmentid IN (client's departments)`; customer list driven by `SMBContracts WHERE clientMspId = session clientMspId` — **zero contracts ⇒ "You have no assigned clients" and no ticket query at all** |
|
|
33
|
+
| `mvc/msp_client_dashboard` (ticket list) | `tickets.customerid IN (<customers>) AND tickets.clientid = <session togadeskClientId>` — **no department filter** |
|
|
34
|
+
| `mvc/enterprise_dashboard` (ENDUSER) | `tickets.email = session emailAddress AND tickets.departmentid = session clientDepartmentId AND status <> 'Closed'`, gated by `supportSkuExists` |
|
|
35
|
+
| `mvc/support/support.php` | `tickets.email = <email>` only — no client filter |
|
|
36
|
+
|
|
37
|
+
**The #1 trap: `tickets.customerid`.** The MSP portal can only show tickets whose
|
|
38
|
+
`customerid` matches a TOGA `Customers.id` under the MSP's SMBContracts. Only togaview-side
|
|
39
|
+
ticket creation set it; tickets created in togadesk (staff UI, API, email intake)
|
|
40
|
+
historically left it NULL ⇒ invisible to the MSP portal. Fixed June 2026 by
|
|
41
|
+
`Ticket::deriveCustomerId()` (see togadesk ticket-lifecycle doc). Pre-fix tickets need a
|
|
42
|
+
one-time backfill per client.
|
|
43
|
+
|
|
44
|
+
`$disableTickets` on msp_client_dashboard is seat-arithmetic only
|
|
45
|
+
(`serviceSeats < activeUsers`) — it hides Create-Ticket buttons, never the list.
|
|
46
|
+
|
|
47
|
+
### Multi-department stats (fixed June 2026)
|
|
48
|
+
`common/togaview/msp_dashboard.php` used to filter every stat on the single
|
|
49
|
+
`ClientMsp.ticketDepartmentId`. It now derives **all** of the client's departments once
|
|
50
|
+
(`tickets_departments WHERE clientId = <togadeskClientId>`) into `$departmentIdList` and uses
|
|
51
|
+
`departmentid IN (...)` everywhere (status counts, priority counts, per-day chart, KB
|
|
52
|
+
category resolution).
|
|
53
|
+
- The department fetch is **MSP-level on purpose** — don't move it inside the customer loop.
|
|
54
|
+
- Empty department list → `'0'` sentinel (valid SQL, matches nothing) + `error_log`.
|
|
55
|
+
- A ticket with `departmentid = 0` is excluded from stats by design.
|
|
56
|
+
|
|
57
|
+
## Data model
|
|
58
|
+
- `TOGaDeskSupport.tickets` (`clientid`, `customerid`, `departmentid`, `email`, `status`)
|
|
59
|
+
- `TOGaDeskSupport.tickets_departments.clientId` maps support departments to a togadesk
|
|
60
|
+
client — a client can have several (craftex: 317, 318, 319), but
|
|
61
|
+
`ClientMsp.ticketDepartmentId` holds only ONE. Never build department logic on it.
|
|
62
|
+
- An MSP's "customers" are **TOGA-side `Customers` rows**, NOT togadesk clients. All of an
|
|
63
|
+
MSP's tickets carry the MSP's own `tickets.clientid`.
|
|
64
|
+
|
|
65
|
+
## Client variations
|
|
66
|
+
- The single-department pattern still exists in the `newcenturyholdingsllc` and
|
|
67
|
+
`towfoundation` dashboard variants (not yet fixed there) and in enterprise_dashboard's
|
|
68
|
+
`clientDepartmentId` filter for end users.
|
|
69
|
+
- Only towfoundation / newcenturyholdingsllc have their own dashboard variants; everyone else
|
|
70
|
+
runs the generic `common/togaview/` pages.
|
|
71
|
+
|
|
72
|
+
## Gotchas / known issues
|
|
73
|
+
- "You have no assigned clients" usually means the MSP's `SMBContracts.clientMspId` was
|
|
74
|
+
corrupted by the togadesk contract modal (see smb-contract-editing doc) — check data before
|
|
75
|
+
debugging code.
|
|
76
|
+
- An expired `SMBContracts.dateContractEnd` is display-only; it does not hide tickets.
|
|
77
|
+
|
|
78
|
+
## Change history
|
|
79
|
+
- 2026-06-12 — documented; multi-department stats fix shipped to dev (mhammontree)
|
|
80
|
+
|
|
81
|
+
## Related docs
|
|
82
|
+
- [Login flows](login-flows.md)
|
|
83
|
+
- [TogaDesk ticket lifecycle](../../togadesk/features/ticket-lifecycle.md)
|
|
84
|
+
- [SMB contract editing](../../togadesk/features/smb-contract-editing.md)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Ticket Detail Page Security (common/togaview/ticket.php)
|
|
3
|
+
framework: "1.0"
|
|
4
|
+
repo: togaview
|
|
5
|
+
project: TogaView
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-06-12
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- common/togaview/ticket.php
|
|
13
|
+
related:
|
|
14
|
+
- 1.0/apps/togaview/features/login-flows.md
|
|
15
|
+
- 1.0/apps/togaview/features/msp-dashboard.md
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Summary
|
|
19
|
+
`common/togaview/ticket.php` is the ticket detail page for nearly ALL hosts — only
|
|
20
|
+
towfoundation/newcenturyholdingsllc have their own variants; every other client's style falls
|
|
21
|
+
back to it. Hardened June 2026 against IDOR (ticket view + file attachment download) and a
|
|
22
|
+
"Deactivated Seat" false positive that blocked MSP admins.
|
|
23
|
+
|
|
24
|
+
## How it works
|
|
25
|
+
|
|
26
|
+
### Ownership check (IDOR fix)
|
|
27
|
+
Applies to BOTH the ticket view AND the `fileId` attachment download (which runs first and
|
|
28
|
+
`exit`s). Access allowed iff:
|
|
29
|
+
- `tickets.clientid == (int) $_SESSION['togadeskClientId']`, OR
|
|
30
|
+
- ticket email == session email (case-insensitive; reads `emailAddress` with `email` fallback
|
|
31
|
+
for staplesprotection sessions).
|
|
32
|
+
|
|
33
|
+
Attachment ownership resolves `files → tickets_replies → tickets`. Unauthorized or missing ⇒
|
|
34
|
+
"Ticket Not Found" + exit.
|
|
35
|
+
|
|
36
|
+
**Do NOT "tighten" the email arm to clientid<=0-only tickets** (a CodeRabbit suggestion,
|
|
37
|
+
reviewed and declined): staplesprotection sessions have no `togadeskClientId`, and
|
|
38
|
+
support.php lists tickets by email with no client filter — the requester is always entitled
|
|
39
|
+
to their own ticket.
|
|
40
|
+
|
|
41
|
+
### Deactivated-seat gate
|
|
42
|
+
Only `USERTYPE_ENDUSER` gets the "Deactivated Seat" block. It fires when the ticket's
|
|
43
|
+
requester email isn't a provisioned SMB seat user (the SMBContractItems JOIN returns empty) —
|
|
44
|
+
which is NORMAL for email-intake tickets, so it must never apply to MSP/CUSTOMER viewers.
|
|
45
|
+
|
|
46
|
+
### Input handling
|
|
47
|
+
`$_GET['ticketId']` is int-cast once at the top — it is interpolated into several queries in
|
|
48
|
+
this file (was a live SQL injection before June 2026).
|
|
49
|
+
|
|
50
|
+
## Data model
|
|
51
|
+
`TOGaDeskSupport.tickets`, `tickets_replies`, `files`; TOGA-side `SMBContractItems` →
|
|
52
|
+
`ServiceRequests` → `Contacts` for the seat check.
|
|
53
|
+
|
|
54
|
+
## Client variations
|
|
55
|
+
- All style variants fall back to this file — no style has its own ticket.php except
|
|
56
|
+
towfoundation/newcenturyholdingsllc.
|
|
57
|
+
- staplesprotection: session uses `email`/`clientId` keys (not
|
|
58
|
+
`emailAddress`/`togadeskClientId`) — the ownership check's email fallback exists for them.
|
|
59
|
+
|
|
60
|
+
## Gotchas / known issues
|
|
61
|
+
- Pre-existing warts (untouched): unescaped `$emailAddress` in the walmart branch query;
|
|
62
|
+
unguarded `explode(' ', name)` in rumcsi/towfoundation branches.
|
|
63
|
+
- Pending as of 2026-06-12: MSP/CUSTOMER bypass for the ownership check (MSP session's
|
|
64
|
+
`togadeskClientId` is the MSP's own client id — matches their customers' tickets since those
|
|
65
|
+
carry the MSP's clientid, but verify when an MSP views a ticket whose clientid differs);
|
|
66
|
+
togaview changes were uncommitted at session end.
|
|
67
|
+
|
|
68
|
+
## Change history
|
|
69
|
+
- 2026-06-12 — file-attachment IDOR fix (ownership check now covers fileId branch);
|
|
70
|
+
email-key fallback for staplesprotection (mhammontree)
|
|
71
|
+
- 2026-06 — ownership check added (ticket view), deactivated-seat gate restricted to
|
|
72
|
+
ENDUSER, ticketId int-cast (mhammontree)
|
|
73
|
+
|
|
74
|
+
## Related docs
|
|
75
|
+
- [Login flows](login-flows.md)
|
|
76
|
+
- [MSP dashboard & ticket visibility](msp-dashboard.md)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -6,6 +6,8 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
6
6
|
|
|
7
7
|
- **library** (Library) _(framework core)_ — 4 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
|
|
8
8
|
- **worker** (Worker) — 4 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
|
|
9
|
+
- **togadesk** (TogaDesk) — 4 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
|
|
10
|
+
- **togaview** (TogaView) — 4 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
|
|
9
11
|
|
|
10
12
|
## 2.0 framework
|
|
11
13
|
|
package/knowledge/registry.json
CHANGED
|
@@ -7,5 +7,7 @@
|
|
|
7
7
|
{ "repo": "worker", "project": "Worker", "framework": "1.0", "role": "app", "dependsOn": [] },
|
|
8
8
|
{ "repo": "toga2-supply", "project": "TOGa Supply", "framework": "2.0", "role": "app", "dependsOn": ["api2"] },
|
|
9
9
|
{ "repo": "saml", "project": "SAML SSO Gateway", "framework": "2.0", "role": "app", "dependsOn": [] },
|
|
10
|
-
{ "repo": "toga2-view", "project": "TOGa View Frontend", "framework": "2.0", "role": "app", "dependsOn": ["api2"] }
|
|
10
|
+
{ "repo": "toga2-view", "project": "TOGa View Frontend", "framework": "2.0", "role": "app", "dependsOn": ["api2"] },
|
|
11
|
+
{ "repo": "togadesk", "project": "TogaDesk", "framework": "1.0", "role": "app", "dependsOn": [] },
|
|
12
|
+
{ "repo": "togaview", "project": "TogaView", "framework": "1.0", "role": "app", "dependsOn": [] }
|
|
11
13
|
]
|
package/package.json
CHANGED