toga-ai 1.0.306 → 1.0.307

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.
@@ -6,7 +6,7 @@ project: Library
6
6
  client: pcmaticb2b
7
7
  type: client-feature
8
8
  status: active
9
- updated: 2026-07-06
9
+ updated: 2026-07-09
10
10
  owners: [snaredla]
11
11
  files:
12
12
  - library/app/api/toga2.php
@@ -75,11 +75,12 @@ Ruled out while debugging "nothing syncs to V1" (0/77 contacts + 0/37 entitlemen
75
75
 
76
76
  Imports Startech (Easeedesk V3) config into TOGA 2.0 — users, groups, devices, categories, ticket types.
77
77
 
78
- - **Groups** must come from `GET /groups_dispatching` (`data.dispatch[]`, keys `group_id`/`group_name`). The company-scoped `dynamic_field_options->data->groups` returns empty here — groups are provider-level, not per-company.
79
- - **Categories** — `App_Api_StarTechTicket::getCategories($companyId, $ticketTypeIds)` forwards a `ticket_type` filter alongside `company`. ⚠ The param name `ticket_type` is **unverified** against the Easeedesk API (not documented for `/tickets/categories`) — confirm in Postman before relying on type filtering; if it's ignored, categories come back unfiltered.
78
+ - **Groups** come from `dynamic_field_options->data->groups` (keys `ID`/`group_name`) — verified 2026-07-09 returning **16 groups** for company 24412. The earlier claim that this returns empty and groups must come from `/groups_dispatching` was **wrong**: the empty result was caused by **incorrect credentials** in `startechticket.php` (`agilant.api`), not the endpoint. Fixed by using the `pcmaticb2b@startechteam.ro` account. `/groups_dispatching` returned 0 and is not used.
79
+ - **Categories** — `App_Api_StarTechTicket::getCategories($companyId, $ticketTypeIds)` forwards a `ticket_type` filter alongside `company`. **Verified 2026-07-09**: `company=24412&ticket_type=50,54` returns 15 categories (the scoped set); the `ticket_type` param works as intended.
80
80
  - Any single upsert failing aborts the run (all `send()` calls throw on API error); the block order is users → groups → devices → categories → ticket types.
81
81
 
82
82
  ## Change history
83
83
 
84
84
  - 2026-06-23: Initial doc — ticket type maps (both directions), NULL sync behavior, TOGADESK_PCS type added
85
85
  - 2026-07-06: Added syncWithToga V1 leg (cross-ref gating, cron-abort ordering, debugging findings) and supporting-records import notes (groups via groups_dispatching, getCategories ticket-type filter)
86
+ - 2026-07-09: Corrected the groups note — groups come from `dynamic_field_options->data->groups` (16 groups); the empty result was a credentials bug (`agilant.api`), not the endpoint. Confirmed `getCategories` `ticket_type` filter works (`50,54` → 15 categories).
@@ -2,5 +2,6 @@
2
2
 
3
3
  | Doc | Framework | Summary | Files |
4
4
  |-----|-----------|---------|-------|
5
+ | [PC Matic B2B — Startech Entitlement Provisioning (customer + SKU)](features/startech-entitlement-provisioning.md) | 2.0 | When a PC Matic B2B entitlement is created in TOGA 2.0 (`POST /entitlements`), the client registers the customer on StarTech's OptimumDesk platform and assigns | _underscore/Trait/Startech/Entitlement.php, _underscore/Model/Pcmaticb2b/Entitlement.php, _underscore/Config.php, api2/Config/production.ini, api2/Config/beta.ini, api2/Config/sandbox-client.ini, test/@srija/Startech Testing/PC Matic B2B/test_e2e_pcmaticb2b.sh |
5
6
  | [PC Matic B2B — Startech Ticket Sync](features/startech-ticket-sync.md) | 1.0 | Bidirectional ticket sync between TOGaDesk 1.0 (client 177), TOGA 2.0 (client 21), and Startech (Easeedesk). | worker/crons/toga2/startech/sync_togadesk_startech_pcmaticb2b.php, worker/crons/toga2/startech/common_import_supporting_records.php, library/app/api/toga2.php, library/app/api/startechticket.php, togadesk/desk/includes/controllers/quickactions.php, togadesk/desk/template/pages/tickets/manage.php, togadesk/desk/includes/functions.php, worker2/Worker/Startech.php, _underscore/Trait/Startech/Ticket.php, dbchanges2/Client_Pcmaticb2b/2026-06-22-pcmaticb2b-enhancements.sql |
6
7
  | [PC Matic B2B Client Profile](profile.md) | 1.0 | PC Matic B2B is a client using TOGaDesk 1.0 for ticket management, with TOGA 2.0 as the data layer and Startech (Easeedesk) as an external ticketing system for | worker/crons/toga2/startech/sync_togadesk_startech_pcmaticb2b.php, togadesk/desk/includes/functions.php |
@@ -0,0 +1,118 @@
1
+ ---
2
+ title: PC Matic B2B — Startech Entitlement Provisioning (customer + SKU)
3
+ framework: "2.0"
4
+ project: TOGa
5
+ client: pcmaticb2b
6
+ type: client-feature
7
+ status: active
8
+ updated: 2026-07-09
9
+ owners: [snaredla]
10
+ files:
11
+ - _underscore/Trait/Startech/Entitlement.php
12
+ - _underscore/Model/Pcmaticb2b/Entitlement.php
13
+ - _underscore/Config.php
14
+ - api2/Config/production.ini
15
+ - api2/Config/beta.ini
16
+ - api2/Config/sandbox-client.ini
17
+ - test/@srija/Startech Testing/PC Matic B2B/test_e2e_pcmaticb2b.sh
18
+ related:
19
+ - clients/pcmaticb2b/features/startech-ticket-sync.md
20
+ - clients/pcmaticb2b/profile.md
21
+ - 1.0/apps/library/features/startech-pcmaticb2b-sync.md
22
+ ---
23
+
24
+ ## Summary
25
+
26
+ When a PC Matic B2B entitlement is created in TOGA 2.0 (`POST /entitlements`), the client
27
+ registers the customer on StarTech's OptimumDesk platform and assigns the entitlement SKU.
28
+ This is the "provisioning" leg — distinct from the ticket sync. It is **one-way, POST-only**:
29
+ it fires on entitlement create, not on update.
30
+
31
+ ## Key files / entry points
32
+
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; }`.
36
+ - `_Trait_Startech_Entitlement::postPost` (`_underscore/Trait/Startech/Entitlement.php`)
37
+ does the two OptimumDesk calls.
38
+
39
+ ## How it works
40
+
41
+ 1. `POST /customer` — body `{ firstName, lastName, emailAddress }` →
42
+ `{"status":"OK","customerId":"<id>"}`. If already present, the response message contains
43
+ `Already Registered` + `customerId=<id>` (regex-extracted).
44
+ 2. `POST /sku` — body is a **JSON array** of assignment objects:
45
+ `[{ "customerID": "<id>", "sku": "140102", "purchaseDate": "YYYY-MM-DD", "quantity": "1" }]`
46
+ → `{"status":"OK","service_id":<id>,"sku":140102}`.
47
+ - `customerID` is **capital-D** (lowercase `customerId` fails customer resolution).
48
+ - `sku` `140102` = `_Model_Pcmaticb2b_Entitlement::STARTECH_ENTITLEMENT_SKU`.
49
+
50
+ ## Endpoint & credentials
51
+
52
+ - Unified endpoint `https://scuses.optimumdesk.com`, **HTTP Basic auth**, account
53
+ `pcmaticb2b@startechteam.ro`.
54
+ - Credentials come from config section **`[startechPcmaticb2b]`**, read via
55
+ `_Config::startechPcmaticb2b('opDeskEndpoint' | 'opDeskUsername' | 'opDeskPassword')`.
56
+ `_Config` has **no explicit method** — `__callStatic` maps the method name directly to the
57
+ ini section name, so the section name and the call must match exactly.
58
+ - The section exists in `production.ini`, `beta.ini`, and `sandbox-client.ini`
59
+ (key order: endpoint, username, password). It was previously named `[asiIntegration]`
60
+ (account `asi.integration`) — renamed because that account's catalog lacked SKU 140102.
61
+
62
+ ## Data model
63
+
64
+ - `_Model_Pcmaticb2b_Entitlement` adds `c_togaServiceRequestId` (INTEGER). The trait does
65
+ **not** write it — it is set later by the `syncWithToga` V1 write-back leg.
66
+ - `prePost` rejects a cancelled subscription (`dateCancelled !== null` → "Subscription not valid").
67
+
68
+ ## Client variations
69
+
70
+ Provisioning is pcmaticb2b-only; the trait is applied solely to `_Model_Pcmaticb2b_Entitlement`.
71
+
72
+ ## Verifying it worked
73
+
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**:
79
+ ```sql
80
+ SELECT direction, method, route, responseCode, responsePayload
81
+ FROM Logs_Pcmaticb2b.Api
82
+ WHERE direction = 'OUT' AND route IN ('/customer', '/sku')
83
+ ORDER BY id DESC LIMIT 4;
84
+ ```
85
+ Look for `OUT POST /sku` → `service_id` + `sku:140102`, `responseCode 200`. The framework
86
+ logs the trait's outbound calls here with `direction='OUT'`.
87
+
88
+ ## End-to-end verification (2026-07-09, post-deploy)
89
+
90
+ Confirmed live against production `api.togahub.com`:
91
+ - `POST /entitlements` → 201; subscription flipped `isActive=1`.
92
+ - Trait fired → OUT log showed `POST /customer` OK (`customerId 1864974`) and
93
+ `POST /sku` OK (`service_id 623917`, `sku 140102`).
94
+
95
+ Runnable harness: `test/@srija/Startech Testing/PC Matic B2B/test_e2e_pcmaticb2b.sh` (bash +
96
+ curl + python). Covers entitlement flow, provisioning direct, ticketing, and import read-side
97
+ with PASS/FAIL assertions. TOGA2 curl auth = `POST /auth/api {client,api,secret}` →
98
+ `data.tokens.access`, then `Authorization: Bearer`.
99
+
100
+ ## Gotchas / known issues
101
+
102
+ - **Silent failure.** On any error the trait `error_log`s and returns — no exception. If creds
103
+ or endpoint are wrong, provisioning fails invisibly. Check `error_log` / the OUT log.
104
+ - **`/sku` must be an array**, and `customerID` must be capital-D.
105
+ - **One-way, POST-only.** No `postPut` — an entitlement created/updated through any non-POST
106
+ path (or the `syncWithToga` PUT write-back) does not (re)register the SKU.
107
+ - **Config drift across envs.** All three env inis must carry `[startechPcmaticb2b]`; a missing
108
+ section means `_Config::startechPcmaticb2b()` returns falsy and the trait bails.
109
+
110
+ ## Related docs
111
+
112
+ - Ticket sync: `clients/pcmaticb2b/features/startech-ticket-sync.md`
113
+ - Library sync engine + import: `1.0/apps/library/features/startech-pcmaticb2b-sync.md`
114
+
115
+ ## Change history
116
+
117
+ - 2026-07-09: Initial doc — entitlement→OptimumDesk customer+SKU provisioning, unified
118
+ endpoint, `[startechPcmaticb2b]` config rename, no-GET-SKU / OUT-log verification, E2E test.
@@ -5,7 +5,7 @@ project: TOGa
5
5
  client: pcmaticb2b
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-07-06
8
+ updated: 2026-07-09
9
9
  owners: [snaredla]
10
10
  files:
11
11
  - worker/crons/toga2/startech/sync_togadesk_startech_pcmaticb2b.php
@@ -22,6 +22,7 @@ related:
22
22
  - clients/pcmaticb2b/profile.md
23
23
  - 2.0/apps/worker2/features/startech-webhook-handler.md
24
24
  - 1.0/apps/library/features/startech-pcmaticb2b-sync.md
25
+ - clients/pcmaticb2b/features/startech-entitlement-provisioning.md
25
26
  ---
26
27
 
27
28
  ## Summary
@@ -72,6 +73,8 @@ Column: `TINYINT(1) UNSIGNED NULL DEFAULT NULL`
72
73
 
73
74
  The `ticketType` on Startech-originated tickets is resolved dynamically via `c_startechTicketTypeId` on `TicketTypes` — not hardcoded.
74
75
 
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
+
75
78
  ## Sync Direction 1: Startech to TOGA 2.0 (Webhook)
76
79
 
77
80
  `worker2/Worker/Startech.php` — `_Worker_Startech::Webhook()`
@@ -162,7 +165,34 @@ const TOGADESK_TICKET_TYPE__TOGADESK_PCS = 'TOGaDesk-PCS';
162
165
  - **Staff-email collision.** `App_Api_Toga2::syncToga2ContactIntoTogadesk1People` matches `people` by email OR referenceId and **updates in place**. If the email already exists as a staff/admin account (clientid ≠ 177), it links `referenceId` onto that staff row and never creates a client-177 `type='user'` customer. Use a fresh, non-staff email for customer test tickets.
163
166
  - **The escalate button applies desk changes unconditionally.** The handler sets dept→337, `escalateToStartech=1`, Ticket Type→"Phone Call Support", and adds history **regardless of 2.0 linkage**. The `c_escalateToStartech=1` PUT (which triggers Startech) fires **only when `referenceId` is already set**; unlinked tickets are left for the sync cron to link — the button does not create the 2.0 ticket on-demand.
164
167
 
168
+ ## Sync Risks (2026-07-09, from full-path trace)
169
+
170
+ These are latent issues in the current loop-guard design — flagged for a follow-up fix,
171
+ not yet resolved:
172
+
173
+ 1. **`c_escalateToStartech` is never reset after escalation.** Once an analyst escalates,
174
+ the 2.0 record keeps `=1` permanently. Every subsequent togadesk→2.0 sync PUT (every 2 min
175
+ on any ticket/note change) delivers `$outData` with `escalate=1` + `c_startechTicketId` set,
176
+ so `postPut` passes the `!== 1` guard and re-pushes a `change_ticket_status`/category update
177
+ to StarTech each cycle. Not an infinite loop, but repeated echo updates.
178
+ 2. **Webhook flips `1→0`, silencing later analyst-side updates.** Once StarTech's webhook writes
179
+ `c_escalateToStartech=0` on an escalated ticket, later Togadesk edits (synced up without
180
+ setting escalate) leave the stored value at 0, so `postPut`'s `!==1` guard blocks them —
181
+ legitimate analyst changes to an escalated ticket may stop propagating to StarTech.
182
+ 3. **Interceptor firing is DB-gated.** `postPost`/`postPut` only run if an active
183
+ `ApiPayloadInterceptor` row exists for `_Model_Pcmaticb2b_Ticket` POST/PUT
184
+ (`api2/Component/Api/V2/V2.php`). Correct trait code is insufficient — verify the rows in
185
+ the live client DB or escalation silently never fires.
186
+
187
+ ## Verification
188
+
189
+ - **Entitlement provisioning** (customer + SKU) — see
190
+ `clients/pcmaticb2b/features/startech-entitlement-provisioning.md`. Confirm via
191
+ `Logs_Pcmaticb2b.Api` `direction='OUT'` rows for `/customer` + `/sku`.
192
+ - **Runnable E2E harness:** `test/@srija/Startech Testing/PC Matic B2B/test_e2e_pcmaticb2b.sh`.
193
+
165
194
  ## Change history
166
195
 
167
196
  - 2026-06-23: Initial doc — full bidirectional sync, c_escalateToStartech semantics, ticket type maps, escalate button, DB migration, constants, gotchas
168
197
  - 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
+ - 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.306",
3
+ "version": "1.0.307",
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",