toga-ai 1.0.941 → 1.0.942
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/2.0/apps/_underscore/features/apirequest-json-content-type.md +12 -2
- package/knowledge/2.0/apps/_underscore/features/cli-script-bootstrap.md +11 -1
- package/knowledge/2.0/apps/dbchanges2/architecture.md +2 -1
- package/knowledge/2.0/apps/worker2/INDEX.md +1 -0
- package/knowledge/2.0/apps/worker2/features/8x8-post-call-survey-import.md +86 -0
- package/knowledge/2.0/apps/worker2/features/creating-worker-actions.md +6 -1
- package/knowledge/INDEX.md +1 -1
- package/knowledge/clients/pcmaticb2b/features/startech-ticket-sync.md +7 -2
- package/knowledge/clients/true/profile.md +4 -1
- package/package.json +1 -1
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["jcardinal", "ajean", "rgirish", "kyalamarthi"]
|
|
9
|
+
updated: 2026-10-05
|
|
10
|
+
owners: ["jcardinal", "ajean", "rgirish", "kyalamarthi", "mhammontree"]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/ApiRequest.php
|
|
13
13
|
- _underscore/Model/Client/Logs/Api.php
|
|
@@ -17,6 +17,7 @@ related:
|
|
|
17
17
|
- ../../worker2/features/creating-worker-actions.md
|
|
18
18
|
- ../../worker2/features/talos-transcript-ingestion.md
|
|
19
19
|
- togaiq-gateway-client.md
|
|
20
|
+
- ../../worker2/features/8x8-post-call-survey-import.md
|
|
20
21
|
---
|
|
21
22
|
|
|
22
23
|
`_ApiRequest`, the 2.0 outbound HTTP client — JSON encode/decode, retry, and api-logging traps; open before calling it or reading `Logs.Api`.
|
|
@@ -94,6 +95,14 @@ case-insensitive scan of already-set headers, so a caller-supplied `Content-Type
|
|
|
94
95
|
**hardcodes** its token in committed source — flagged for a rotate-and-move-to-config ticket; 11
|
|
95
96
|
worker2 files use it). When adding a new component, decide deliberately: log and accept the header
|
|
96
97
|
exposure, strip/redact the auth header before the call is logged, or `setLogging(false)`.
|
|
98
|
+
Basic auth via `CURLOPT_USERPWD` is **not** logged (it is not a header); bearer headers and
|
|
99
|
+
request/response bodies **are**. Vendor calls carrying secrets or caller PII → `setLogging(false)`
|
|
100
|
+
(e.g. [8x8 survey import](../../worker2/features/8x8-post-call-survey-import.md)).
|
|
101
|
+
- **⚠ OPEN, not fixed: SSL peer verification is OFF by default.** `ApiRequest.php:238` sets
|
|
102
|
+
`CURLOPT_SSL_VERIFYPEER` to `0` whenever `sslVerifyPeer` is null — despite the "AUTO based on
|
|
103
|
+
https" comment, `!null` is true, so an unset value never verifies, https included. New components
|
|
104
|
+
must call `setSslVerifyPeer(true)`. Changing the default touches every caller — needs a `cto`
|
|
105
|
+
opinion. 1.0 twin: [library architecture](../../../1.0/apps/library/architecture.md).
|
|
97
106
|
- **Multipart/file upload ALREADY WORKS — do not add an `ENCODE__MULTIPART` case (2026-09-04).**
|
|
98
107
|
The request-encoding switch (`ApiRequest.php:205-228`) has **no `default:` case**, so
|
|
99
108
|
`payloadEncoding: null` passes the payload through **untouched** and sets no `Content-Type`; `:236`
|
|
@@ -153,6 +162,7 @@ case-insensitive scan of already-set headers, so a caller-supplied `Content-Type
|
|
|
153
162
|
`dtStamp` (indexed) or it times out — `WHERE source = '…'` alone will not return.
|
|
154
163
|
|
|
155
164
|
## Change history
|
|
165
|
+
- 2026-10-05 — Added SSL-verify-off default (OPEN) and basic-auth-not-logged note, from TRUE-82185 (mhammontree)
|
|
156
166
|
- 2026-09-25 — renamed product reference from "TogaIQ" to "Talos" (rebrand; TOGa IQ is now the separate `toga25-iq` app) (jcardinal)
|
|
157
167
|
|
|
158
168
|
## Related
|
|
@@ -6,7 +6,7 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-10-05
|
|
10
10
|
owners: ["bala", "mhammontree"]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Database.php
|
|
@@ -66,6 +66,15 @@ For DB-**free** unit tests of interceptor logic, use the PHPUnit scaffold instea
|
|
|
66
66
|
anything touches `App_Framework`. `__APPROOT__/app/framework.php` shadows the library file for
|
|
67
67
|
*both* class names, so resolving `App_Framework` first loads the app file and the library
|
|
68
68
|
definition never arrives.
|
|
69
|
+
- **Locally, `registerClientDatabases()` can fail outright.** It reads `Clients` through the local
|
|
70
|
+
`Core` alias, which on a laptop may point at the 1.0 `Core` DB (no `Clients` table). Register the
|
|
71
|
+
client schema directly instead: `_Database::register(...)` with `database` = the real schema
|
|
72
|
+
(e.g. `Client_True`) and `alias` = `DB_CLIENT`. Windows MySQL reports schema names lower-case
|
|
73
|
+
(`client_true`) — compare case-insensitively.
|
|
74
|
+
- **⚠ The 2.0 debug error page prints `print_r($GLOBALS)`, including `$_SERVER` / env.** A script
|
|
75
|
+
that reads a secret from env vars must scrub them (`putenv`, `unset($_SERVER[...], $_ENV[...])`)
|
|
76
|
+
and keep the value out of global scope (inside a function) **before** the framework loads, or the
|
|
77
|
+
first error dumps the secret to the screen.
|
|
69
78
|
- Do not drive a local harness through `_Worker::runTask` — the dev config's
|
|
70
79
|
`[cloud] aws_worker_queue_url` points at the **production** SQS queue. Call the target method
|
|
71
80
|
in-process. (Also noted on [email-template-sending.md](./email-template-sending.md).)
|
|
@@ -79,4 +88,5 @@ For DB-**free** unit tests of interceptor logic, use the PHPUnit scaffold instea
|
|
|
79
88
|
— the work these traps surfaced in.
|
|
80
89
|
|
|
81
90
|
## Change history
|
|
91
|
+
- 2026-10-05 — Added local `registerClientDatabases` failure + debug-page `$GLOBALS` secret leak gotchas (TRUE-82185) (mhammontree)
|
|
82
92
|
- 2026-09-25 — Added lazy-CWD autoloader gotcha (found building the worker2 Codeception harness) (mhammontree)
|
|
@@ -6,7 +6,7 @@ project: Database Changes
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: architecture
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-05
|
|
10
10
|
owners: [jcardinal, mhammontree, bala, ajean]
|
|
11
11
|
files:
|
|
12
12
|
- Core/
|
|
@@ -189,6 +189,7 @@ When the executor processes a client, it applies that client's own folder **plus
|
|
|
189
189
|
|---|---|---|
|
|
190
190
|
| `netsuite` | `_modules/netsuite/` | Compass, Canon, Ncci, Sbasite, Spglobal, … (most clients) |
|
|
191
191
|
| `startech` | `_modules/startech/` | Pcmatic |
|
|
192
|
+
| `8x8` | `_modules/8x8/` | True (8x8 post-call survey tables, TRUE-82185) |
|
|
192
193
|
|
|
193
194
|
Module folders use the **same `YYYY-MM-DD` naming + ordering rules** as client folders.
|
|
194
195
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
| Doc | Summary |
|
|
4
4
|
|-----|---------|
|
|
5
5
|
| [Worker (worker2) Architecture](architecture.md) | How worker2 (Elastic Beanstalk Worker Tier background-job app) works overall — job pipeline, MySQL/SQS roles, Lambdas, routing, transactions; open for any worke |
|
|
6
|
+
| [8x8 Post-Call Survey (CSAT) Import (8x8/Surveys → _modules/8x8 tables)](features/8x8-post-call-survey-import.md) | worker2 imports 8x8 Contact Center post-call surveys (CSAT) from the 8x8 Analytics API into `Client_True` tables, hourly, with an import-run watermark; open bef |
|
|
6
7
|
| [Deploy-Time Auto-Registration to the Shared ALB Target Group (non-production)](features/alb-target-group-auto-registration.md) | Deploy-time postdeploy hook that self-registers a non-prod EB instance into the shared-ALB target group; open when a non-prod worker2/saml/api2 env is unreachab |
|
|
7
8
|
| [All-Client Email Queue Monitor (Monitor/Operations/EmailQueue)](features/all-client-email-queue-monitor.md) | Cross-client health check for the 2.0 outbound email queue (`Logs_<Client>.Email`); open when working on email-queue alerting or an all-client DB fan-out. |
|
|
8
9
|
| [API 2.0 Stability Monitor (Monitor/Operations/ApiStability)](features/api-stability-monitor.md) | End-to-end authenticated round-trip probe of the production 2.0 API; open when working on API liveness monitoring or a server-side call to the public-auth endpo |
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "8x8 Post-Call Survey (CSAT) Import (8x8/Surveys → _modules/8x8 tables)"
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: worker2
|
|
5
|
+
project: Worker
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: draft
|
|
9
|
+
updated: 2026-10-05
|
|
10
|
+
owners: ["mhammontree"]
|
|
11
|
+
files:
|
|
12
|
+
- worker2/Worker/8x8/Surveys.php
|
|
13
|
+
- _underscore/Component/Api/8x8/8x8.php
|
|
14
|
+
- dbchanges2/Core/2026-10-02a - 8x8 partner and survey import cron.sql
|
|
15
|
+
- dbchanges2/_modules/8x8/2026-10-02a - PostCallSurveys.sql
|
|
16
|
+
related:
|
|
17
|
+
- ../../_underscore/features/apirequest-json-content-type.md
|
|
18
|
+
- ../../_underscore/features/cloud-secrets-manager.md
|
|
19
|
+
- ../../_underscore/features/cli-script-bootstrap.md
|
|
20
|
+
- ./creating-worker-actions.md
|
|
21
|
+
- ../../../clients/true/profile.md
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
worker2 imports 8x8 Contact Center post-call surveys (CSAT) from the 8x8 Analytics API into `Client_True` tables, hourly, with an import-run watermark; open before touching the 8x8 component, the survey tables, or 8x8 credentials.
|
|
25
|
+
|
|
26
|
+
## Summary
|
|
27
|
+
|
|
28
|
+
**Status (2026-10-05): built on branch `TRUE-82185` in `_underscore`, `worker2`, `dbchanges2` — NOT committed, NOT deployed.** Ticket TRUE-82185; design from the 2026-09-29 "8x8 Integration" meeting.
|
|
29
|
+
|
|
30
|
+
Replaces the manual 8x8 CSV export + Excel pivots. Phase 1 = store only. Later phases link surveys to Desk tickets, Chat, call records. Power BI / Talos read the tables directly (no `Core.Records` registration yet).
|
|
31
|
+
|
|
32
|
+
One 8x8 tenant (`agilantsolutionsi01`, TOGA's call center) serves many end clients (Office Depot, Craftex, Walmart, PC Matic). **All surveys land in `Client_True`**; the end client is identified by `surveyName` / `queueName`. Routing to per-end-client DBs is deferred.
|
|
33
|
+
|
|
34
|
+
## How it works
|
|
35
|
+
|
|
36
|
+
**Credentials.** AWS Secrets Manager `partners/8x8/<clientIdentifier>` (us-east-1), JSON `{clientId, secret, region}`. Not in `Core.PartnerApiIdentities.partnerApiPassword` — that column is a STRING RecordField on record 305, readable through the records API.
|
|
37
|
+
|
|
38
|
+
**Component `_Component_Api_8x8`** (`_underscore/Component/Api/8x8/8x8.php`):
|
|
39
|
+
1. Token: `POST https://api.8x8.com/oauth/v2/token`, client_credentials, Basic `clientId:secret`, lives ~1799s.
|
|
40
|
+
2. Create report: `POST /analytics/cc/v8/historical-metrics/detailed-reports`, type `detailed-reports-survey`; returns `DONE` immediately.
|
|
41
|
+
3. Page data: `GET /detailed-reports/{id}/data?size=1000`; next-page cursor is the `Last-Document-Id` **response header**.
|
|
42
|
+
4. Region path prefix: us `''`, `eu`, `au`, `ca`.
|
|
43
|
+
5. `Logs.Api` logging OFF on every call (bearer token + caller PII); `setSslVerifyPeer(true)`. A 204 / empty body = empty page. Exception messages carry response shape only, never values.
|
|
44
|
+
|
|
45
|
+
**Worker `_Worker_8x8_Surveys`** (`worker2/Worker/8x8/Surveys.php`):
|
|
46
|
+
1. `8x8/Surveys/Dispatch` (cron `15 * * * *`, 300s) queues one `8x8/Surveys/Import` per client with an 8x8 row in `Core.PartnerApiIdentities`.
|
|
47
|
+
2. `Import(int $clientId, ?string $windowStart, ?string $backfillStart)` — one client per job, 1-day windows, 180s budget, then re-queues itself via `runTask` with `windowStart`.
|
|
48
|
+
3. Start = last SUCCESS `dtWindowEnd` − 48h overlap; with no SUCCESS row, `backfillStart` is required (else throws).
|
|
49
|
+
4. Upsert on `(source, externalResponseKey)` via raw escaped `INSERT … ON DUPLICATE KEY UPDATE` — `_Model` has no upsert and `save()` cascades to parents. Agents/answers are delete+reinsert **only** when the survey row changed (affected rows 0 = unchanged → skip).
|
|
50
|
+
5. Fail loud: a bad record throws, the window is marked FAILED, the watermark does not advance.
|
|
51
|
+
6. RUNNING guard also treats a SUCCESS completed within 300s as running (closes the chain hand-off gap).
|
|
52
|
+
7. Read host disabled for the job (`_Database::setIsReadHostEnabled(false)`) — see Gotchas.
|
|
53
|
+
|
|
54
|
+
**Schema.**
|
|
55
|
+
- `Core`: `PartnerApiIdentities.clientApiId` now NULL-able; `Partners` row `8x8`; identity row clientIdentifier `True` → partnerIdentifier `agilantsolutionsi01`; `CronJobs` `8x8/Surveys/Dispatch` inserted **INACTIVE**.
|
|
56
|
+
- Module `8x8` (`_modules/8x8/`, listed in `Client_True/_modules.txt`): `PostCallSurveys`, `PostCallSurveyAgents`, `PostCallSurveyAnswers`, `PostCallSurveyImports` (the import-run table is the watermark, not `MAX(dtSurveyStarted)`).
|
|
57
|
+
- Survey times stored **UTC** (8x8 returns local time + offset). Vendor values (`surveyType`, `questionType`, `answerType`) are VARCHAR, not ENUM; our `status` is ENUM.
|
|
58
|
+
|
|
59
|
+
**8x8 data shape (probed 2026-10-02).**
|
|
60
|
+
- One row = one survey. `surveyId` is the survey **template** (1201 OD Customer Survey, 2164 Craftex CSAT, 1221 Walmart Customers, 1161 PC Matic Survey); there is no response id. Unique key = `surveyId` + highest `interactionId` (ids start with a hex timestamp; 1–2 per row on transfer).
|
|
61
|
+
- Answers nested in `items[key=results].value[]`; values like `StayOnCall`, `Scale`, `VoiceComment`, `Valid`, `Recorded`. `surveyIsDeleted` is the string `"false"`. Durations in ms. `voiceRecordingUuid` is per answer (`callerVoiceInput-<uuid>`).
|
|
62
|
+
- Volume ~110 surveys/day.
|
|
63
|
+
|
|
64
|
+
**Deploy order** (human steps):
|
|
65
|
+
1. Run the Core SQL (cron stays inactive).
|
|
66
|
+
2. Run the module SQL on `Client_True`.
|
|
67
|
+
3. Verify the `PartnerApiIdentities` row for `True`.
|
|
68
|
+
4. devops grants the worker2 EB role `secretsmanager:GetSecretValue` on `partners/8x8/*`.
|
|
69
|
+
5. Deploy `_underscore` (Rohan's weekly window), then worker2.
|
|
70
|
+
6. Run `8x8/Surveys/Import` by hand with `backfillStart`.
|
|
71
|
+
7. Verify SUCCESS rows in `PostCallSurveyImports`, including one empty window.
|
|
72
|
+
8. Set `CronJobs.isActive = 1`.
|
|
73
|
+
|
|
74
|
+
**Local verification.** `test/@Mark/TRUE-82185/upsert_local_test.php` feeds a saved real page through private `upsertSurvey` (ReflectionMethod) into local `Client_True`: 25 inserted; re-run 25 unchanged, 0 answers rewritten. Full end-to-end through the worker not yet run (needs AWS secret access).
|
|
75
|
+
|
|
76
|
+
## Gotchas
|
|
77
|
+
|
|
78
|
+
- **Omit the report `timezone` param.** The tenant rejects `"UTC"` ("Timezone UTC is not valid or configured for this tenant"); convert to UTC in PHP.
|
|
79
|
+
- **The 1.0 VCC API has no survey data.** `vcc-na20.8x8.com/api` (basic auth tenant+token; `library/app/api/8x8.php`, `worker/crons/togadesk/send_uma_8x8_daily_report.php`) gives queue stats only. Surveys need the Analytics API (CC API v7+).
|
|
80
|
+
- **8x8 developer reference pages render in JavaScript** — WebFetch gets no schemas. Confirm fields with a real call.
|
|
81
|
+
- **Read-after-write in the job:** SELECTs go to the read host (a separate connection) and cannot see the job's uncommitted insert. Disable the read host for the job — same fix as `_Email` (TRUE-80448). See [api-payload-interceptors](../../api2/features/api-payload-interceptors.md).
|
|
82
|
+
- **DB errors: store/rethrow only `errno` + error text.** The raw `_Query` message repeats the whole INSERT, with caller PII, into `WorkerJobs.output` / `Logs.Issue`.
|
|
83
|
+
- **8x8 report storage:** each run creates reports on 8x8's side (~72/day). Not cleaned up unless 8x8 complains (decided 2026-10-02).
|
|
84
|
+
|
|
85
|
+
## Change history
|
|
86
|
+
- 2026-10-05 — Created: Phase 1 survey import built on `TRUE-82185` (uncommitted, not deployed); single-tenant → `Client_True` decision, Secrets Manager creds, import-run watermark (mhammontree)
|
|
@@ -6,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-10-05
|
|
10
10
|
owners: [jcardinal, dfranks, mhammontree, tcox, bala, ajean, rgirish]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/
|
|
@@ -513,10 +513,15 @@ Rules: rename **both sides in one PR and one deploy**; grep every repo for the o
|
|
|
513
513
|
failure indefinitely. The dry run must exercise the **same helpers** as the real path — a separate
|
|
514
514
|
test harness that reimplements them proves nothing. See
|
|
515
515
|
[netsuite-opportunity-sync](./netsuite-opportunity-sync.md#gotchas--known-issues) for what it caught.
|
|
516
|
+
- **Read-after-write inside an action needs the read host OFF.** `_Query` sends SELECTs to the read
|
|
517
|
+
host — a separate connection that cannot see the job's own uncommitted insert (not replication
|
|
518
|
+
lag). Call `_Database::setIsReadHostEnabled(false)` for the job, as `_Email` (TRUE-80448) and
|
|
519
|
+
[8x8 survey import](./8x8-post-call-survey-import.md) do.
|
|
516
520
|
- See [architecture.md](../architecture.md) for the always-HTTP-200 rule and the
|
|
517
521
|
commit-before-SQS transaction pattern that the worker relies on.
|
|
518
522
|
|
|
519
523
|
## Change history
|
|
524
|
+
- 2026-10-05 — Added read-host read-after-write gotcha for worker actions (TRUE-82185) (mhammontree)
|
|
520
525
|
- 2026-09-17 — Added the **half-written `WorkerJobs` row** tell: a row with `dtStarted` but no
|
|
521
526
|
`dtCompleted`/`isSuccess`/`output` means the **action class is not on the box**, not a hung job.
|
|
522
527
|
`Controller/Index.php` (~L322) calls `method_exists($className, 'initialize')` one line **above**
|
package/knowledge/INDEX.md
CHANGED
|
@@ -20,7 +20,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
20
20
|
## 2.0 framework
|
|
21
21
|
|
|
22
22
|
- **_underscore** (_Underscore) _(framework core)_ — 94 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
|
|
23
|
-
- **worker2** (Worker) —
|
|
23
|
+
- **worker2** (Worker) — 82 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
|
|
24
24
|
- **api2** (API) — 26 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
|
|
25
25
|
- **dbchanges2** (Database Changes) _(framework core)_ — 22 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
|
|
26
26
|
- **toga2-supply** (TOGa Supply) — 9 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
|
|
@@ -5,8 +5,8 @@ project: TOGa
|
|
|
5
5
|
client: pcmaticb2b
|
|
6
6
|
type: client-feature
|
|
7
7
|
status: active
|
|
8
|
-
updated: 2026-
|
|
9
|
-
owners: [snaredla, jcardinal]
|
|
8
|
+
updated: 2026-10-05
|
|
9
|
+
owners: [snaredla, jcardinal, mhammontree]
|
|
10
10
|
files:
|
|
11
11
|
- worker/crons/toga2/startech/sync_togadesk_startech_pcmaticb2b.php
|
|
12
12
|
- worker/crons/toga2/startech/common_import_supporting_records.php
|
|
@@ -177,6 +177,8 @@ const TOGADESK_TICKET_TYPE__TOGADESK_PCS = 'TOGaDesk-PCS';
|
|
|
177
177
|
- **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.
|
|
178
178
|
- **ticketType uses `c_startechTicketTypeId` dynamically** — stored on `TicketTypes`, not hardcoded in the worker.
|
|
179
179
|
|
|
180
|
+
- **⚠ OPEN (found 2026-10-05, not fixed): Startech credentials are exposed in two places.** (1) `_underscore/Component/Api/Startech/Startech.php` hardcodes `STARTECH_API_USERNAME` / `STARTECH_API_PASSWORD` class constants in committed source — rotate, then move to Secrets Manager. (2) `Core.PartnerApiIdentities.partnerApiPassword` holds the Startech password in plaintext and is a STRING RecordField on record 305, so the records API can read it. New partners use Secrets Manager instead (see [8x8 survey import](../../../2.0/apps/worker2/features/8x8-post-call-survey-import.md)).
|
|
181
|
+
|
|
180
182
|
### Sync prerequisites & gotchas (2026-07-06)
|
|
181
183
|
- **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".
|
|
182
184
|
- **These prePost rejections are now HTTP 400, not 500 (fixed 2026-08-25).** `_Model_Pcmaticb2b_Ticket::prePost()` (the 2.0 pre-interceptor for `POST /v2/tickets`) previously threw a **plain `Exception`** for its four client-actionable rejections — *"Ticket requires a contact…"*, *"Contact not found for uuid=…"*, *"Contact not found for email=…"*, *"No active entitlement found for contact"* — each producing **HTTP 500 (EO-1)** plus a `Logs.Issue` and a Sentry event (the "requires a contact" one was prod `Logs.Issue` ref `FG`, 215 occurrences). All four now throw **`_Exception_Validation`**, which `Controller/Index.php` maps to **HTTP 400** — the client sees it in the response envelope with no Issue/Sentry/5xx-health impact. A client-input / business rejection belongs at 400, not 500. (See the 2.0 backend-php standard, *Choosing an exception class is a ROUTING decision*.)
|
|
@@ -195,3 +197,6 @@ const TOGADESK_TICKET_TYPE__TOGADESK_PCS = 'TOGaDesk-PCS';
|
|
|
195
197
|
- [Startech webhook handler (worker2)](../../../2.0/apps/worker2/features/startech-webhook-handler.md)
|
|
196
198
|
- [Library Startech pcmaticb2b sync](../../../1.0/apps/library/features/startech-pcmaticb2b-sync.md)
|
|
197
199
|
- [Startech entitlement provisioning](startech-entitlement-provisioning.md)
|
|
200
|
+
|
|
201
|
+
## Change history
|
|
202
|
+
- 2026-10-05 — Recorded open Startech credential exposure (hardcoded constants + plaintext `partnerApiPassword` RecordField) (mhammontree)
|
|
@@ -16,7 +16,7 @@ project: _Underscore
|
|
|
16
16
|
client: true
|
|
17
17
|
type: profile
|
|
18
18
|
status: active
|
|
19
|
-
updated: 2026-10-
|
|
19
|
+
updated: 2026-10-05
|
|
20
20
|
owners: [jcardinal, kyalamarthi, tcox, rgirish, mhammontree]
|
|
21
21
|
files: []
|
|
22
22
|
related:
|
|
@@ -24,6 +24,7 @@ related:
|
|
|
24
24
|
- ../../2.0/apps/saml/features/gateway-environments-and-redirect-safety.md
|
|
25
25
|
- ../../2.0/apps/_underscore/features/core-domains-app-host-registry.md
|
|
26
26
|
- ../../1.0/apps/togadesk/features/staff-sso-login.md
|
|
27
|
+
- ../../2.0/apps/worker2/features/8x8-post-call-survey-import.md
|
|
27
28
|
---
|
|
28
29
|
|
|
29
30
|
"True" — TOGa's internal/staff tenant (`Client_True`, identifier `True`, default email SSO mapper); open for its internal apps (Tools, sprint dashboard, togatech site) and its Talos-pricing internal-tenant role.
|
|
@@ -44,6 +45,8 @@ The **Tools** app (1.0; repo `tools`) authenticates True users via **SSO** throu
|
|
|
44
45
|
|
|
45
46
|
**TOGa Desk** (1.0; repo `togadesk`) staff sign in via the same True SSO (TRUE-78064, prod only, not deployed as of 2026-10-02): True user email → one AD People row → existing `TOGaDeskSupport.people` row; no auto-create. Domain row id 261 (repointed from an unused devteam seed row) `uuid d1e526b9-e2fb-4462-935f-ed449e8f5986`, `clientId 1`, `appId 18`, env 1, `https://togadesk.togatech.com/desk/` — live in prod Core 2026-10-02. See [TOGa Desk staff SSO](../../1.0/apps/togadesk/features/staff-sso-login.md).
|
|
46
47
|
|
|
48
|
+
**8x8 post-call surveys (CSAT)** for every end client served by TOGA's one 8x8 call-center tenant (Office Depot, Craftex, Walmart, PC Matic) are stored in `Client_True` (module `8x8` in `Client_True/_modules.txt`); the end client is read from `surveyName` / `queueName`. Built on TRUE-82185, not deployed as of 2026-10-05. See [8x8 survey import](../../2.0/apps/worker2/features/8x8-post-call-survey-import.md).
|
|
49
|
+
|
|
47
50
|
## ⚠ "Base" maps to Super User in Client_True
|
|
48
51
|
|
|
49
52
|
In `Client_True` the role **named `Base`** maps to **`coreRoleId` 3 = Super User**. Every other
|
package/package.json
CHANGED