toga-ai 1.0.268 → 1.0.270

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.
@@ -4,11 +4,12 @@
4
4
  |-----|---------|-------|
5
5
  | [Library (1.0 Framework) Architecture](architecture.md) | `library` is the shared library repository for **all 1.0 (legacy) applications** — the `App_` framework. | library/_.php, library/app/, library/browser/ |
6
6
  | [App_Sso — Reusable 1.0 SSO Initiation (SP-initiated SAML via saml.togahub.com)](features/app-sso-initiation.md) | `App_Sso` (`library/app/sso.php`) is the **1.0 port of the 2.0 SAML gateway's SP-initiated SSO initiation**, packaged as a reusable, framework-level capability | library/app/sso.php, library/sso/togahub_private_key.key |
7
+ | [Cron Execution Monitoring (App_Framework check-in/out → CronJobExecutions)](features/cron-execution-monitoring.md) | `App_Framework::cronInitialization()` / `App_Framework::cronFinished()` (in `library/app/framework.php`) give every 1.0 (`App_`) cron job a check-in/check-out l | library/app/framework.php |
7
8
  | [Diagnostic Dialog — View Recommended Services Routing](features/diagnostic-dialog-view-recommended-services.md) | `App_Model_Toga_Diagnostic::initializeDiagnosticDialog()` renders the device modal used across all TOGa service request views. | library/app/model/toga/diagnostic.php |
8
9
  | [Elite Freshservice Sync (library)](features/elite-freshservice-sync.md) | `App_Api_Toga2` in `library/app/api/toga2.php` orchestrates bidirectional sync between TOGA 2 and TOGaDesk. | library/app/api/toga2.php |
9
10
  | [Branded HTML Email Templates (App_Email_Template)](features/email-templates.md) | `App_Email_Template` (`app/email/template.php`) is the base class for branded HTML emails in the 1.0 (`App_`) framework. | library/app/email/template.php, library/app/email/agilant.php |
10
11
  | [1.0 MVC Page Pattern & New-App Skeleton](features/mvc-page-pattern-and-app-skeleton.md) | This is the **reusable recipe for standing up a new 1.0 (`App_`) application** and for adding pages to one — the folder-based MVC routing, the page lifecycle, t | library/app/framework.php, library/app/frameworkindex.php, library/app/mvc.php, library/app/database.php, library/app/model.php, library/app/config.php |
11
12
  | [NetSuite SuiteQL/REST API Reference](features/netsuite-suiteql-api-reference.md) | General working reference for the Agilant NetSuite integration: how to authenticate, how SuiteQL behaves, and the confirmed schema of the tables/columns/codes w | library/app/api/netsuite/rest.php, library/ssl/netsuite_ec_key.pem, test/@dave/Junk Drawer/nsq.php |
12
13
  | [NetSuite SuiteQL/REST Shim — Field Semantics](features/netsuite-suiteql-rest-shim.md) | `App_Api_Netsuite_Rest` is the REST/SuiteQL replacement for the deprecated NetSuite SOAP toolkit. | library/app/api/netsuite/rest.php |
13
- | [Startech PC Matic B2B Sync (library)](features/startech-pcmaticb2b-sync.md) | `library/app/api/toga2.php` handles bidirectional ticket sync for PC Matic B2B between TOGaDesk 1.0 and TOGA 2.0. | library/app/api/toga2.php |
14
+ | [Startech PC Matic B2B Sync (library)](features/startech-pcmaticb2b-sync.md) | `library/app/api/toga2.php` handles bidirectional ticket sync for PC Matic B2B between TOGaDesk 1.0 and TOGA 2.0. | library/app/api/toga2.php, library/app/api/startechticket.php, worker/crons/toga2/startech/common_import_supporting_records.php |
14
15
  | [App_Api_Toga2 — TOGa2 API Client & 1.0↔2.0 Sync Bridge](features/toga2-api-client-and-bridge.md) | `App_Api_Toga2` (`library/app/api/toga2.php`, ~8400 lines) is the **1.0-side client for the TOGa 2 (`_underscore`/api2) public API** *and* the home of the cross | library/app/api/toga2.php, worker/crons/toga2/aig/sync_togasupply_aig.php, worker/crons/toga2/wje/sync_togasupply_wje.php |
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: Cron Execution Monitoring (App_Framework check-in/out → CronJobExecutions)
3
+ framework: "1.0"
4
+ repo: library
5
+ project: Library
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-07-06
10
+ owners: [dfranks]
11
+ files:
12
+ - library/app/framework.php
13
+ related:
14
+ - ../../worker/architecture.md
15
+ ---
16
+
17
+ ## Summary
18
+
19
+ `App_Framework::cronInitialization()` / `App_Framework::cronFinished()` (in
20
+ `library/app/framework.php`) give every 1.0 (`App_`) cron job a check-in/check-out
21
+ lifecycle recorded in the **`CronJobExecutions`** table in **`db_common`**. On start the job
22
+ INSERTs an execution row; on finish it UPDATEs that row with completion state and an
23
+ `executionTimeSeconds` duration. This is the shared-DB monitoring surface for 1.0 crons
24
+ across all 1.0 apps (worker, togadesk, toga, …), independent of the older `Log`/`CRON_START`
25
+ row in `db_log` and of the per-job Sentry check-in monitors.
26
+
27
+ ## How it works
28
+
29
+ - **`cronInitialization()`** — INSERTs one row into `CronJobExecutions` (`db_common`) via the
30
+ execution-id registry variable, records start time, and returns/stores the execution id used
31
+ to close the row later.
32
+ - **`cronFinished()`** — UPDATEs the same `CronJobExecutions` row (matched by execution id)
33
+ with completion status and `executionTimeSeconds`.
34
+ - **Connection:** every `CronJobExecutions` read/write goes against **`db_common`**. The table
35
+ exists **only** in `db_common` — it does **not** exist on the `db_log` connection.
36
+ - **Duration precision:** `executionTimeSeconds` is `round(microtime(true) - $start, 3)` —
37
+ millisecond precision landing in a `decimal(10,3)` column. Do **not** `(int)`-cast it; the
38
+ cast silently discards the sub-second precision even when the schema column is `decimal(10,3)`.
39
+ - **Schema:** the table is provisioned by the dbchanges migration
40
+ `dbchanges/Common/DF/2026-5-7 Cron Checkin.sql` (table `CronJobExecutions`,
41
+ `executionTimeSeconds decimal(10,3)`, no `note` column).
42
+ - **Design decision:** 1.0 records executions by writing **directly to the shared DB**
43
+ (`db_common`), *not* by POSTing from 1.0 to a 2.0 API endpoint. Per Jeff Cardinal, 1.0 code
44
+ must not POST to 2.0 code; the direct shared-DB write is the sanctioned path (TRUE-78182).
45
+
46
+ ## Gotchas
47
+
48
+ - **`db_log` has no `CronJobExecutions` table.** A `cronFinished()` UPDATE that runs against the
49
+ `db_log` connection throws on **every** 1.0 cron job. Both the INSERT and the UPDATE must
50
+ target `db_common`.
51
+ - **A `git merge` can silently resurrect pre-refactor logic.** These functions were cleanly
52
+ consolidated to a single `db_common`-only INSERT/UPDATE pair (commit `0a3a6f75`), but a later
53
+ `git merge origin/_production` (`509614036605…`) reintroduced the old dual-path structure from
54
+ `_production`'s still-unmigrated copy of the file — leaving duplicate INSERT/UPDATE blocks, and
55
+ reverting one path's connection argument back to `db_log`. Automatic merge resolution updated
56
+ the SQL text (renamed the table) but restored the wrong connection name, producing a
57
+ platform-wide breaking bug disguised as a simple PR-feedback rework. **When a merge touches a
58
+ function you already refactored on your branch and the base branch never got that refactor,
59
+ diff against the merge-base — do not just eyeball the current file** — to catch resurrected
60
+ logic. (Fixed 2026-07-06: consolidated back to one `db_common` INSERT/UPDATE pair.)
61
+
62
+ ## Change history
63
+ - 2026-07-06 — Fixed a merge (`origin/_production`) that reintroduced duplicate
64
+ `CronJobExecutions` writes and pointed one `cronFinished()` UPDATE at `db_log` (where the
65
+ table doesn't exist), which would have thrown on every 1.0 cron. Consolidated to one
66
+ `db_common` INSERT/UPDATE pair and switched `executionTimeSeconds` to `round(…, 3)` for the
67
+ `decimal(10,3)` precision the migration provides. (dfranks, TRUE-78182)
68
+ - 2026-05-07 — Introduced `CronJobExecutions` check-in/out in `App_Framework` cron lifecycle;
69
+ direct `db_common` write chosen over a 1.0→2.0 API POST. (dfranks)
70
+ </content>
71
+ </invoke>
@@ -6,10 +6,12 @@ project: Library
6
6
  client: pcmaticb2b
7
7
  type: client-feature
8
8
  status: active
9
- updated: 2026-06-23
9
+ updated: 2026-07-06
10
10
  owners: [snaredla]
11
11
  files:
12
12
  - library/app/api/toga2.php
13
+ - library/app/api/startechticket.php
14
+ - worker/crons/toga2/startech/common_import_supporting_records.php
13
15
  related:
14
16
  - clients/pcmaticb2b/features/startech-ticket-sync.md
15
17
  - clients/pcmaticb2b/profile.md
@@ -63,6 +65,21 @@ Both `PCS Ticket` and `TOGaDesk-PCS` map to `PCS` in TOGA 2.0.
63
65
  - **`SUPPORT REQUEST` with a space** — `TOGA2_TICKET_TYPE_CODE__SUPPORT = 'SUPPORT REQUEST'`. Using `'SUPPORT'` silently breaks type matching.
64
66
  - **`$isPcmaticb2bUuid` flag** is used for PC Matic B2B-specific branching throughout `syncToga2TicketIntoTogadesk1Ticket()`.
65
67
 
68
+ ## syncWithToga → TOGA_PCMaticB2B (V1) — the third leg
69
+
70
+ `sync_togadesk_startech_pcmaticb2b.php` runs `syncWithToga(21, …, true, false)` **before** `syncWithTogadesk`. It pushes 2.0 → V1: Contacts→`Customers` (writes `c_togaCustomerId` back to the 2.0 contact), Entitlements→`ServiceRequests` (writes `c_togaServiceRequestId` back). Only records where the cross-ref **IS NULL** are processed. It uses `throwExceptionOnApiError=true` and runs first, so **any throw here aborts the whole cron — blocking `syncWithTogadesk` too.**
71
+
72
+ Ruled out while debugging "nothing syncs to V1" (0/77 contacts + 0/37 entitlements had their cross-ref set): client-21→`TOGA_PCMaticB2B` mapping (present in `TOGA.Clients`), the `Customers` INSERT columns, and `changeDbLinkToClientDatabase` (`App_Query::execute` re-selects the DB per query from the config `dbname`). Remaining suspects: the PUT-back to 2.0 (throws on non-200) or the cron not executing. The exact throw is only visible in Sentry / `error_log`.
73
+
74
+ ## Supporting-records import (worker/crons/toga2/startech/common_import_supporting_records.php)
75
+
76
+ Imports Startech (Easeedesk V3) config into TOGA 2.0 — users, groups, devices, categories, ticket types.
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.
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
+
66
82
  ## Change history
67
83
 
68
84
  - 2026-06-23: Initial doc — ticket type maps (both directions), NULL sync behavior, TOGADESK_PCS type added
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)
@@ -4,7 +4,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
4
4
 
5
5
  ## 1.0 framework
6
6
 
7
- - **library** (Library) _(framework core)_ — 10 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
7
+ - **library** (Library) _(framework core)_ — 11 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
8
8
  - **worker** (Worker) — 12 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
9
9
  - **togadesk** (TOGa Desk) — 8 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
10
10
  - **togaview** (TOGa View) — 6 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
@@ -2,5 +2,5 @@
2
2
 
3
3
  | Doc | Framework | Summary | Files |
4
4
  |-----|-----------|---------|-------|
5
- | [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, library/app/api/toga2.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 |
5
+ | [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
6
  | [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 |
@@ -5,11 +5,13 @@ project: TOGa
5
5
  client: pcmaticb2b
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-06-23
8
+ updated: 2026-07-06
9
9
  owners: [snaredla]
10
10
  files:
11
11
  - worker/crons/toga2/startech/sync_togadesk_startech_pcmaticb2b.php
12
+ - worker/crons/toga2/startech/common_import_supporting_records.php
12
13
  - library/app/api/toga2.php
14
+ - library/app/api/startechticket.php
13
15
  - togadesk/desk/includes/controllers/quickactions.php
14
16
  - togadesk/desk/template/pages/tickets/manage.php
15
17
  - togadesk/desk/includes/functions.php
@@ -154,6 +156,13 @@ const TOGADESK_TICKET_TYPE__TOGADESK_PCS = 'TOGaDesk-PCS';
154
156
  - **Webhook must set c_escalateToStartech=0** — without this, the `postPost` gate evaluates `!null = true` and would skip Startech for webhook-originated tickets on any subsequent PUT.
155
157
  - **ticketType uses c_startechTicketTypeId dynamically** — stored on `TicketTypes`, not hardcoded in the worker.
156
158
 
159
+ ## Sync Prerequisites & Gotchas (2026-07-06)
160
+
161
+ - **The entitlement gate blocks the 2.0 create.** A TOGaDesk ticket only syncs up to TOGA 2.0 (and can then reach Startech) if its email maps to an existing 2.0 contact **with an active entitlement**. `_Model_Pcmaticb2b_Ticket::prePost` rejects the create otherwise, so the desk ticket never gets a `referenceId` — and the escalate handler shows "Ticket is not linked to TOGa 2.0".
162
+ - **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
+ - **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
+
157
165
  ## Change history
158
166
 
159
167
  - 2026-06-23: Initial doc — full bidirectional sync, c_escalateToStartech semantics, ticket type maps, escalate button, DB migration, constants, gotchas
168
+ - 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)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.268",
3
+ "version": "1.0.270",
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",