toga-ai 1.0.313 → 1.0.314

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.
@@ -5,7 +5,7 @@ project: TOGa
5
5
  client: pcmaticb2b
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-07-09
8
+ updated: 2026-07-10
9
9
  owners: [snaredla]
10
10
  files:
11
11
  - _underscore/Trait/Startech/Entitlement.php
@@ -31,10 +31,11 @@ it fires on entitlement create, not on update.
31
31
  ## Key files / entry points
32
32
 
33
33
  - `_Model_Pcmaticb2b_Entitlement::postPost` (`_underscore/Model/Pcmaticb2b/Entitlement.php`)
34
- activates the subscription (`isActive = true`) then calls the trait via
35
- `use _Trait_Startech_Entitlement { postPost as traitEntitlementPostPost; }`.
34
+ activates the subscription (`isActive = true`), calls the trait, then links the returned
35
+ customerId onto the contact (see "Contact linkage" below).
36
36
  - `_Trait_Startech_Entitlement::postPost` (`_underscore/Trait/Startech/Entitlement.php`)
37
- does the two OptimumDesk calls.
37
+ does the two OptimumDesk calls and **returns the resolved `customerId`**. It is
38
+ **client-agnostic** — no client-specific model references (that was moved to the model).
38
39
 
39
40
  ## How it works
40
41
 
@@ -47,6 +48,22 @@ it fires on entitlement create, not on update.
47
48
  - `customerID` is **capital-D** (lowercase `customerId` fails customer resolution).
48
49
  - `sku` `140102` = `_Model_Pcmaticb2b_Entitlement::STARTECH_ENTITLEMENT_SKU`.
49
50
 
51
+ ## Contact linkage (customerId → c_startechUserId)
52
+
53
+ After the trait resolves the `customerId`, `_Model_Pcmaticb2b_Entitlement::postPost` writes it
54
+ onto the entitlement's contact as **`c_startechUserId`** (loads the contact by
55
+ `payload->contact->uuid`, saves via direct model — wrapped in its own try/catch so a linkage
56
+ failure never blocks provisioning).
57
+
58
+ Why: OptimumDesk uses this **same id** as the ticket `creator`/`affected_user` and as the
59
+ `owner_id` for the subscriptions endpoint. Pre-linking it means inbound Startech webhooks match
60
+ the existing contact (webhook matches on `affected_user` = `c_startechUserId`) instead of
61
+ creating a duplicate. Confirmed: **provisioning `customerId` = ticketing owner id = `c_startechUserId`**
62
+ (same id-space).
63
+
64
+ Design note: the trait returns the id and stays client-agnostic; the pcmatic-specific write
65
+ lives in the client model. Do **not** put client model refs back in the trait.
66
+
50
67
  ## Endpoint & credentials
51
68
 
52
69
  - Unified endpoint `https://scuses.optimumdesk.com`, **HTTP Basic auth**, account
@@ -71,11 +88,18 @@ Provisioning is pcmaticb2b-only; the trait is applied solely to `_Model_Pcmaticb
71
88
 
72
89
  ## Verifying it worked
73
90
 
74
- There is **no GET-SKU / list-services endpoint** on the provisioning API — probing
75
- `/sku?customerID=`, `/customer/{id}/services`, `/skus/{id}` all return the OptimumDesk
76
- "machine-to-machine" 404 page. Only `GET /customer/{id}` works, and it does **not** list SKUs.
77
-
78
- The authoritative check is the **outbound API log**:
91
+ **Read-back endpoint (added by StarTech 2026-07-10):**
92
+ ```
93
+ GET /api/v3/easeedesk/owner/{owner_id}/activated_subscriptions (JWT auth)
94
+ ```
95
+ Returns the active subscriptions for an owner — `sku`, `sku_name`, `devices_left`,
96
+ `workorder_id`, `workorder_sku_id`, `ticket_id`. **`owner_id` = the provisioning `customerId`
97
+ = the contact's `c_startechUserId`**, so no extra lookup is needed to call it. Verified live
98
+ returning SKU `140102` "24/7 Unlimited Tech Support B2B" for our provisioned customers.
99
+ (The provisioning API itself still has no GET-SKU route — only `GET /customer/{id}`, which does
100
+ not list SKUs; the ticketing/JWT API above is where subscriptions are read back.)
101
+
102
+ The other authoritative check is the **outbound API log**:
79
103
  ```sql
80
104
  SELECT direction, method, route, responseCode, responsePayload
81
105
  FROM Logs_Pcmaticb2b.Api
@@ -112,7 +136,19 @@ with PASS/FAIL assertions. TOGA2 curl auth = `POST /auth/api {client,api,secret}
112
136
  - Ticket sync: `clients/pcmaticb2b/features/startech-ticket-sync.md`
113
137
  - Library sync engine + import: `1.0/apps/library/features/startech-pcmaticb2b-sync.md`
114
138
 
139
+ ## PC Matic integration note
140
+
141
+ PC Matic does **not** integrate with StarTech directly and needs no StarTech creds/API. Every
142
+ sale → PC Matic creates an **entitlement in TOGA 2.0** → this trait provisions the customer +
143
+ SKU to StarTech → an **active subscription** appears on StarTech. Customers/agents verify
144
+ subscriptions via the PC Matic Agent, the OptimumDesk portal (Customers → customer → subscriptions),
145
+ or the `activated_subscriptions` endpoint above.
146
+
115
147
  ## Change history
116
148
 
117
149
  - 2026-07-09: Initial doc — entitlement→OptimumDesk customer+SKU provisioning, unified
118
150
  endpoint, `[startechPcmaticb2b]` config rename, no-GET-SKU / OUT-log verification, E2E test.
151
+ - 2026-07-10: Refactor — trait returns customerId (client-agnostic); model writes
152
+ `c_startechUserId` on the contact. Added `activated_subscriptions` read-back endpoint
153
+ (owner_id = customerId = c_startechUserId). Noted PC Matic does not integrate with StarTech.
154
+ E2E confirmed in prod (17/17).
@@ -5,7 +5,7 @@ project: TOGa
5
5
  client: pcmaticb2b
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-07-09
8
+ updated: 2026-07-10
9
9
  owners: [snaredla]
10
10
  files:
11
11
  - worker/crons/toga2/startech/sync_togadesk_startech_pcmaticb2b.php
@@ -75,6 +75,37 @@ The `ticketType` on Startech-originated tickets is resolved dynamically via `c_s
75
75
 
76
76
  **Verified 2026-07-09 (company 24412):** `getTicketTypes(24412)` returns exactly two active types — **50 = Support Request**, **54 = Phone Call Support**. The import cron uses `STARTECH_TICKET_TYPE_IDS='50,54'` and maps them to TOGaDesk departments `50→336` (Support Request), `54→337` (Phone Call/PCS). The older `SUPPORT REQUEST=6 / API=201` values above are stale for this company — treat 50/54 as authoritative.
77
77
 
78
+ ## Ticket Statuses & Workflows (verified 2026-07-10, company 24412)
79
+
80
+ Statuses are **per workflow**, and the workflow is keyed by its **workflow_id — NOT the ticket-type id**:
81
+
82
+ - Support Request (type 50) → **workflow_id 56**
83
+ - Phone Call Support (type 54) → **workflow_id 59**
84
+
85
+ ```
86
+ GET /api/v3/easeedesk/tickets/workflows
87
+ GET /api/v3/easeedesk/tickets/statuses?workflow_id=56 # Support Request
88
+ GET /api/v3/easeedesk/tickets/statuses?workflow_id=59 # Phone Call Support
89
+ ```
90
+ ⚠ Do **not** pass the type id (50/54) as `workflow_id` — that queries a different workflow and returns unrelated statuses (this caused an earlier mis-read that reported "subscription statuses" on 54).
91
+
92
+ ### Our `TicketStages.c_startechStageId` vs the workflows
93
+ | TOGA stage | c_startechStageId | in 56 (SR) | in 59 (PCS) |
94
+ |---|---|---|---|
95
+ | New Ticket | 1 | ✓ | ✓ |
96
+ | In Progress | 2 | ✓ | ✓ |
97
+ | Resolved | 5 | ✓ | ✓ |
98
+ | Reopened | 6 | ✓ | ✓ |
99
+ | Closed | 7 | ✓ | ✓ |
100
+ | Awaiting User | 210 | ✗ disabled by StarTech | ✗ |
101
+ | Open | 72 | ✗ not in workflow | ✗ |
102
+ | On Hold | 209 | ✗ disabled by StarTech | ✗ |
103
+
104
+ StarTech (Razvan) enabled Resolved(5)/Reopened(6)/Closed(7) in both workflows and **disabled Awaiting User(210) & On Hold(209)**; `Open(72)` is not present in either. So **those three stage mappings are currently invalid** and would be rejected on sync.
105
+
106
+ ### Pending enhancement — per-ticket-type statuses
107
+ Each workflow also exposes many operational statuses we don't handle (Connected, Transferred, User Offline, Cancelled, Remote Control, Customer Confirmation, Lost, Dispatched, Automate Check, Live, Rework), and the two ticket types have **different** status sets. We have **never** supported statuses that differ by ticket type — Razvan is asking us to map his workflow-specific statuses like the PC Matic / Tech Services setup, which we have **not** integrated with TOGaDesk. This is a **separate enhancement on both the sync and TOGaDesk** sides; raised with Jake/JT for a decision — **not yet implemented**.
108
+
78
109
  ## Sync Direction 1: Startech to TOGA 2.0 (Webhook)
79
110
 
80
111
  `worker2/Worker/Startech.php` — `_Worker_Startech::Webhook()`
@@ -196,3 +227,4 @@ not yet resolved:
196
227
  - 2026-06-23: Initial doc — full bidirectional sync, c_escalateToStartech semantics, ticket type maps, escalate button, DB migration, constants, gotchas
197
228
  - 2026-07-06: Added sync prerequisites/gotchas (entitlement gate, staff-email collision) and clarified the escalate button's actual behavior (desk changes always; 2.0 PUT only when linked)
198
229
  - 2026-07-09: Corrected Startech ticket-type IDs (50 Support Request, 54 Phone Call Support for company 24412); added Sync Risks (escalate flag never reset, webhook 1→0 silencing, interceptor DB-gating) and Verification (OUT-log + E2E test); cross-linked entitlement provisioning.
230
+ - 2026-07-10: Added Ticket Statuses & Workflows section — workflow IDs 56 (Support Request) / 59 (Phone Call Support), statuses queried by workflow_id (not type id); TicketStages.c_startechStageId check (Awaiting User 210 / On Hold 209 disabled, Open 72 absent → invalid); flagged per-ticket-type statuses as a pending enhancement (sync + TOGaDesk).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.313",
3
+ "version": "1.0.314",
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",