toga-ai 1.0.173 → 1.0.174

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,48 +6,70 @@ project: Test
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-16
10
- owners: [jcardinal]
9
+ updated: 2026-06-23
10
+ owners: [jcardinal, mhammontree]
11
11
  files:
12
12
  - test/team/generate_toga2_onboarding_sql.php
13
13
  related:
14
14
  - ../architecture.md
15
15
  - ./toga2-user-cross-client-access-sql.md
16
+ - ../../../2.0/apps/dbchanges2/workflows/client-onboarding.md
16
17
  ---
17
18
 
18
19
  ## Summary
19
20
 
20
21
  `team/generate_toga2_onboarding_sql.php` generates the SQL needed to **onboard a new client**
21
22
  onto the 2.0 platform. Runs on the **1.0 `App_` framework**
22
- (`App_Framework_Sandbox::initialize()`), but the SQL it produces targets the **2.0** client
23
- databases.
23
+ (`App_Framework_Sandbox::initialize()`), but the SQL it produces targets the **2.0** Core and
24
+ client databases. It is the *insert-generation* half of onboarding; the schema/blank half lives
25
+ in dbchanges2 (see the [2.0 client onboarding workflow](../../../2.0/apps/dbchanges2/workflows/client-onboarding.md)).
24
26
 
25
27
  ## How it works
26
28
 
27
- Configure the `const` block, then run; the script emits the onboarding SQL to stdout for review.
29
+ Configure the `const` block, then run; the script emits the onboarding SQL to stdout (`<pre>`).
28
30
 
29
31
  Key configuration:
30
- - `CLIENT_NAME` — formal client name, proper case (e.g. `'The Coca-Cola Company'`).
31
- - `CLIENT_IDENTIFIER` — PascalCase, no spaces (e.g. `'Cocacola'`).
32
+ - `CLIENT_NAME` — formal client name, proper case (e.g. `'Fordham University'`).
33
+ - `CLIENT_IDENTIFIER` — PascalCase, no spaces (e.g. `'Fordham'`) → drives `Client_<Id>` etc.
32
34
  - `CLIENT_SUBDOMAIN_IDENTIFIER` — lowercase, no spaces; the email domain without TLD.
33
35
  - `CLIENT_EMAIL_DOMAINS` — array of permitted email domains **with** TLD.
34
- - `SHOULD_CREATE_AGILANT_API` — when true, also creates the Agilant API user and api-roles.
36
+ - `SHOULD_CREATE_AGILANT_API` — when true, creates the internal **Agilant** API key + api-roles.
37
+ - `CREATE_CLIENT_API_NAME` — string (e.g. `'Fordham'`) to also create the **client** API key, or `null` to skip.
38
+ - `RELATIVE_PATH_TO_DBCHANGES2`, `SHOULD_CONSOLIDATE` — declared but **not yet implemented** (no
39
+ consolidation logic in this script; the blank/consolidation lives in dbchanges2).
35
40
 
36
- Platform topology baked into the script:
37
- - `DATABASE_PREFIXES = ['Client', 'Logs', 'Archive']` — the three DB families a client gets.
38
- - `ENVIRONMENTS__DATABASE_PREFIXES__CLUSTERS` — per-environment (`dev` / `beta` / `production`)
39
- host endpoints for each DB prefix. Production uses a global Aurora cluster with separate
40
- writer/reader endpoints (`writer.client.database.togahub.com` / `reader1.client.database.togahub.com`);
41
- dev/beta fall back to a single cluster (reader = writer).
41
+ What it emits (UUIDs via `App_Misc::generateUUID()`; it does not touch the DB):
42
+ - **Core inserts** → run on the **core cluster**: `Core.Databases` (Client_/Logs_/Archive_),
43
+ `Core.Clients`, `Core.Domains` (every app × env), `Core.ClientEmailDomains`, `Core.DatabaseHosts`
44
+ (prod null-region + 3 regions).
45
+ - **Client inserts** → run on the **client cluster** (`Client_<Id>`): `Apis` + `Apis_Roles`.
46
+ Note: the `Apis` rows live in the **client** DB, not Core.
47
+
48
+ ## Output split (core vs client clusters)
49
+
50
+ The script emits one combined blob; for deployment, split it: Core-table inserts to the core
51
+ cluster, the `Apis`/`Apis_Roles` inserts to the client cluster (against `Client_<Id>`, which must
52
+ already have the `Base`/`API` roles from the blank seed so the `Apis_Roles` lookup resolves).
42
53
 
43
54
  ## Gotchas
44
55
 
56
+ - **`Apis_Roles` needs a unique uuid per row.** The role-link insert is
57
+ `INSERT … SELECT <uuid>, …, r.id FROM Roles WHERE r.name IN ('Base','API')` — that SELECT returns
58
+ **2 rows**, so a hardcoded literal uuid makes both rows share it → `Duplicate entry … for key
59
+ 'Apis_Roles.uuid'`. Use MySQL **`UUID()`** in the SELECT so each row gets its own. (Fixed
60
+ 2026-06-23; previously bit every client where both roles exist.)
61
+ - **Secrets in output.** The generated `Apis` rows contain real `secret` values. **Never commit**
62
+ the client-insert file (or any artifact containing it) to a repo — run it in prod and distribute
63
+ the secret out-of-band. Core inserts are secret-free and safe to commit.
45
64
  - The cluster/endpoint map is environment infrastructure encoded as constants — if RDS endpoints
46
- change, this script must be updated.
47
- - Identifiers have strict casing rules (formal vs PascalCase vs lowercase-subdomain); getting
48
- them wrong produces inconsistent DB/identity records.
65
+ change, update the script.
66
+ - Identifiers have strict casing rules (formal vs PascalCase vs lowercase-subdomain).
49
67
  - Output is SQL to run manually — review before executing against production.
50
68
 
51
69
  ## Change history
52
70
 
71
+ - 2026-06-23 — Fixed `Apis_Roles` duplicate-uuid bug (use `UUID()` per row); fixed PHP 8 fatal from
72
+ an unquoted `CREATE_CLIENT_API_NAME` constant; implemented the previously-unused client-API block
73
+ (`CREATE_CLIENT_API_NAME`) so it emits both the Agilant and client keys; documented core/client
74
+ cluster split and the secret-handling rule. (mhammontree)
53
75
  - 2026-06-16 — Initial capture.
@@ -4,5 +4,6 @@
4
4
  |-----|---------|-------|
5
5
  | [API (api2 / TOGa API v2) Architecture](architecture.md) | `api2` is the backend powering the public **TOGa 2.0 API**. | api2/Controller/Index.php, api2/Component/Api/V2/V2.php, api2/Component/Api/Cxml/Cxml.php, api2/Component/Api/V2/Response/Response.php, api2/Config/ |
6
6
  | [POST + JSON-body args for scripted APIs](features/scripted-api-post-body-args.md) | The V2 engine can run a Record Script (scripted API) for a **POST** request, and a scripted API can receive its arguments from the **JSON request body** instead | api2/Component/Api/V2/V2.php |
7
+ | [Tickets API (/v2/tickets)](features/tickets-api.md) | The generic ticket endpoint of the 2.0 REST API. | Component/Api/V2/V2.php |
7
8
  | [AWS CodePipeline Deployment via CodeConnections (GitHub → Elastic Beanstalk)](workflows/codepipeline-codeconnections-deploy.md) | 2.0 apps (`api2`, `_underscore`) are deployed through **AWS CodePipeline**. | |
8
9
  | [New Environment Configuration & Provisioning (api2)](workflows/environment-configuration-and-provisioning.md) | What it takes for a 2.0 API environment (e.g. | api2/Config/<environment>.ini, api2/Controller/Index.php, dbchanges2/Core/2026-06-16a - DatabaseHosts for new QA QC stage demo environments.sql, _underscore/Route.php |
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: Tickets API (/v2/tickets)
3
+ framework: "2.0"
4
+ repo: api2
5
+ project: API
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-23
10
+ owners: ["mhammontree"]
11
+ files:
12
+ - Component/Api/V2/V2.php
13
+ related:
14
+ - ../architecture.md
15
+ - ../../dbchanges2/workflows/client-onboarding.md
16
+ ---
17
+
18
+ ## Summary
19
+
20
+ The generic ticket endpoint of the 2.0 REST API. Tickets are a metadata-driven **Record**
21
+ (`tickets` → `_Model_Client_Ticket`, `aclDatabase = CLIENT`), so they're created/updated/read like
22
+ any record: `POST/PUT/GET /v2/tickets` (and `/v2/tickets/{uuid}`). PC Matic instead uses
23
+ `/v2/entitlement-tickets` (entitlement-wrapped); plain clients (e.g. Fordham) use `/v2/tickets`
24
+ with ticket fields at the top level.
25
+
26
+ ## Auth & request conventions
27
+
28
+ - **Base URL** `https://api.togahub.com/v2` (sandbox `https://api.client.sandbox.togahub.com/v2`).
29
+ - **Auth**: `POST /v2/auth/api {client, api, secret}` → `data.tokens.access` (Bearer, ~1h) +
30
+ `data.tokens.refresh` (~30d). `client` = `Core.Clients.uuid`, `api`/`secret` = the client's
31
+ `Client_<Id>.Apis` row. Refresh via `POST /v2/auth/refresh` with the refresh token as Bearer.
32
+ - Every request needs a **unique `transactionId`** query param (reuse → `EV-5`).
33
+ - Response envelope: `{transactionId, isSuccess, status, error, messages[], meta{}, data{}}`. A
34
+ created/read ticket comes back under **`data.tickets`** (not bare `data`).
35
+
36
+ ## How it works (write model)
37
+
38
+ - **Related objects are nested and resolved by a natural identifier**, not numeric IDs — and **each
39
+ field has its own identifier set**:
40
+ - `urgency` → `name` / `weight` / `uuid` (**NOT `code`**)
41
+ - `ticketStage` → `code`
42
+ - `ticketType`, `ticketTopic` → `name`
43
+ Sending an identifier a field doesn't recognize returns **`EV-12`** (the error lists the valid
44
+ identifier fields). These are **MATCH** (must-exist) references — the value must already exist in
45
+ the client's reference data.
46
+ - **Inline-created** objects (safe to send without pre-existing data): `address` (CREATE),
47
+ `contact`/`contactPhoneNumber`/`location`/`reportedByContact` (MATCH_UPSERT).
48
+ - **Child arrays** created inline: `ticketNotes[]`, `ticketFiles[]`, `ticketUnits[]`, `ticketItems[]`,
49
+ `ticketUsers[]`, `ticketServiceQuestionAnswers[]`.
50
+ - Add a note to an existing ticket via the nested route `POST /v2/tickets/{uuid}/ticket-notes`.
51
+ - `number` is auto-generated (`TK`-prefixed, starts `TK100000`).
52
+
53
+ A minimal create needs only `shortDescription`/`longDescription` (+ optional `impact`, `ticketNotes`);
54
+ the FK references are all nullable.
55
+
56
+ ## GET / filtering
57
+
58
+ `GET /v2/tickets` supports `fields`, `where`, `join`/`ojoin`, `sort`, `group`, pagination
59
+ (`page`/`recordsPerPage`), `depth`. To fetch tickets for a contact on the generic flow, join the
60
+ ticket's own contact: `join=Contacts@Contacts:Contacts.id=Tickets.contactId&where=(Contacts.uuid:eq:<uuid>)`.
61
+ (PC Matic instead joins through Entitlements — only valid for its entitlement flow.)
62
+
63
+ ## Gotchas
64
+
65
+ - **`urgency` matches by `name`, not `code`** — the most common `EV-12` cause.
66
+ - **Reference data must exist** — a newly onboarded client has no Urgencies/TicketTypes/TicketStages/
67
+ TicketTopics until seeded, so those fields can't be referenced yet (see the onboarding workflow).
68
+ - **Response is under `data.tickets`** — not bare `data`.
69
+
70
+ ## Change history
71
+
72
+ - 2026-06-23 — Initial capture from the Fordham ticket integration + customer docs (TRUE-79699). (mhammontree)
@@ -3,3 +3,4 @@
3
3
  | Doc | Summary | Files |
4
4
  |-----|---------|-------|
5
5
  | [Database Changes (dbchanges2) Repository Architecture](architecture.md) | `dbchanges2` is the **schema-migration / SQL change-set repository** for the entire 2.0 platform. | Core/, Client/, Client_<Tenant>/, Logs/, Logs_Client/, _modules/ |
6
+ | [2.0 New-Client Onboarding (manual process)](workflows/client-onboarding.md) | How to manually stand up a new 2.0 client (tenant). | Client/, Client_<Tenant>/, Core/, Logs_Client/ |
@@ -6,7 +6,7 @@ project: Database Changes
6
6
  client: shared
7
7
  type: architecture
8
8
  status: active
9
- updated: 2026-06-19
9
+ updated: 2026-06-23
10
10
  owners: [jcardinal, mhammontree]
11
11
  files:
12
12
  - Core/
@@ -36,7 +36,9 @@ is the intended execution order.
36
36
  **Critical rules:** every new `.sql` file **must** be named `YYYY-MM-DD<letter> - <Description>.sql`
37
37
  with a **mandatory lower-case letter** right after the date (`a` for the first file of that day
38
38
  in a folder, then `b`, `c`, …). One folder per database; place client changes under the matching
39
- `Client_<Name>` folder. Never edit an already-run migration — add a new dated file instead.
39
+ `Client_<Name>` folder. Never edit an already-run migration — add a new dated file instead. The
40
+ `Client/` **blank must carry the baseline DATA seed** (roles, full ACL, reference/lookup tables,
41
+ UI config) — **not just schema**; a schema-only blank produces non-functional clients.
40
42
 
41
43
  ## File naming convention (the execution contract)
42
44
 
@@ -124,6 +126,31 @@ already-applied change files moved aside to keep the live list short. Present un
124
126
  typically bucketed as `FILES BEFORE <date>` (or by year under `Core/`). **Never** rely on a
125
127
  file inside `HISTORIC` running; **never** add new changes there.
126
128
 
129
+ ## The Client blank: baseline data + consolidation
130
+
131
+ `Client/<DATE>-BLANK_CLIENT_DATABASE.sql` (the **latest-dated** one is the current blank) is the
132
+ starting point for every new tenant. It is **not schema-only** — it must also carry the **baseline
133
+ data seed**: the standard roles (`Base`, `Developer`, `API`, `Public`), the full ACL
134
+ (`AclRecordPermissions`/`AclFieldPermissions`/`AclRecordExpressions`/`AclLogicGroups`/…), the
135
+ reference/lookup tables (countries, states, statuses, types, …), and UI config (`TableViews` + fields,
136
+ `SectionRecordFields`). A client built from a **schema-only** blank has no roles/ACL and **cannot
137
+ authorize** — this regressed once (the blank was reduced to `EmailTemplates`-only), which is why a new
138
+ client appeared to onboard but failed at the API.
139
+
140
+ **Consolidation lifecycle** (folding loose `Client/` changes back into a fresh blank):
141
+ 1. The loose `Client/` files must **already be applied to every existing client DB** before they're
142
+ archived (otherwise the new blank diverges from live clients). This is done manually as the files
143
+ are created.
144
+ 2. Rebuild the blank from the **current clean schema + the baseline data** and `mysqldump` **WITH
145
+ data** (never `--no-data` — that is exactly how the seed was lost). Keep secret-bearing tables
146
+ (`Apis`) **out** of the blank.
147
+ 3. `git mv` the old blank + the consolidated loose files into `Client/HISTORIC/FILES BEFORE <DATE>/`,
148
+ leaving `Client/` with only the new dated blank.
149
+
150
+ **Applying loose files** requires `SET FOREIGN_KEY_CHECKS=0` — several `ALTER … MODIFY/DROP` a column
151
+ that participates in a foreign key and otherwise fail with error 1832. (The blank dump sets this in
152
+ its own header.)
153
+
127
154
  ## Adding a new change (the rules)
128
155
 
129
156
  1. Pick the right folder for the target DB: `Core/`, `Logs/`, the shared `Client/` (every
@@ -0,0 +1,97 @@
1
+ ---
2
+ title: 2.0 New-Client Onboarding (manual process)
3
+ framework: "2.0"
4
+ repo: dbchanges2
5
+ project: Database Changes
6
+ client: shared
7
+ type: workflow
8
+ status: active
9
+ updated: 2026-06-23
10
+ owners: ["mhammontree"]
11
+ files:
12
+ - Client/
13
+ - Client_<Tenant>/
14
+ - Core/
15
+ - Logs_Client/
16
+ related:
17
+ - ../architecture.md
18
+ - ../../../1.0/apps/test/features/toga2-client-onboarding-sql.md
19
+ - ../../api2/features/tickets-api.md
20
+ ---
21
+
22
+ ## Summary
23
+
24
+ How to manually stand up a new 2.0 client (tenant). A tenant spans three databases on three
25
+ clusters — `Client_<Name>` (client cluster), `Logs_<Name>` (logs cluster), `Archive_<Name>`
26
+ (archive cluster) — plus registration rows in **Core** and two API keys. The schema + baseline
27
+ data come from the dbchanges2 **blank**; the Core/client registration + API keys are generated by
28
+ the [onboarding SQL generator](../../../1.0/apps/test/features/toga2-client-onboarding-sql.md).
29
+ Goal: every `Client_<Name>` DB is architecturally identical.
30
+
31
+ ## Steps
32
+
33
+ Order matters — each step assumes the prior one ran.
34
+
35
+ 1. **Decide identifiers** — formal name, identifier (PascalCase → `Client_<Id>`), subdomain
36
+ (lowercase), email domain(s) with TLD, and any modules.
37
+ 2. **Create the three databases** — `CREATE DATABASE Client_<Id>` (client cluster),
38
+ `Logs_<Id>` (logs cluster), `Archive_<Id>` (archive cluster). `Archive_<Id>` can be empty.
39
+ 3. **Build `Client_<Id>` schema + baseline** — apply the current blank
40
+ (`Client/<DATE>-BLANK_CLIENT_DATABASE.sql` — latest-dated), which creates all tables **and** the
41
+ baseline seed (roles, full ACL, reference/lookup tables, UI config). Run with
42
+ `SET FOREIGN_KEY_CHECKS=0` (the loose schema files assume it; see Gotchas).
43
+ 4. **Build `Logs_<Id>`** — apply `Logs_Client/<DATE>_BLANK_CLIENT_LOGS_DATABASE.SQL`. The API logs
44
+ here and checks the auth-rate limit against it, so it **must** exist for the API to work.
45
+ 5. **Generate the inserts** — run `test/team/generate_toga2_onboarding_sql.php` (set the client
46
+ consts). It emits Core inserts + the two API-key inserts.
47
+ 6. **Run Core inserts on the core cluster** — `Core.Databases`, `Core.Clients`, `Core.Domains`
48
+ (every app × env), `Core.ClientEmailDomains`, `Core.DatabaseHosts`. This is what makes the API
49
+ route to the tenant.
50
+ 7. **Run the API-key inserts on the client cluster** (against `Client_<Id>`) — two `Apis` rows
51
+ (internal "Agilant" + the client key) and their `Apis_Roles` links to `Base`+`API`. Distribute
52
+ the secrets out-of-band (internal → our systems; client → the client). **Never commit secrets.**
53
+ 8. **Register for shared changes** — append `Client_<Id>` to `test/team/2.0 deployment/Clients_Db.txt`
54
+ so future shared `Client/` changes fan out to it.
55
+ 9. **Configure client reference/ACL data** — seed the client's ticket reference data
56
+ (Urgencies, TicketTypes, TicketStages, TicketTopics) and any record/field ACL beyond baseline.
57
+ 10. **Verify** — authenticate via the API with `{client = Core.Clients.uuid, api = Apis.uuid,
58
+ secret = Apis.secret}`, then a smoke request (e.g. create a ticket).
59
+
60
+ ## Systems involved
61
+
62
+ - **dbchanges2** — the blank (schema + baseline seed), loose `Client/` changes, `Logs_Client/`
63
+ blank, and the generated `Core/` + `Client_<Name>/` onboarding SQL.
64
+ - **test** (1.0) — `generate_toga2_onboarding_sql.php` produces the Core + API-key inserts.
65
+ - **Core DB** — `Clients`, `Databases`, `DatabaseHosts`, `Domains`, `ClientEmailDomains`
66
+ (route/identity metadata; supplies the `client` uuid used at auth).
67
+ - **api2 / _underscore** — the API the client calls; verify here.
68
+ - **Bastion** — production deploy path (upload SQL, source per cluster).
69
+
70
+ ## Edge cases & escalation
71
+
72
+ - **Logs/Archive scope** — building the `Logs_`/`Archive_` *schemas* is sometimes treated as a
73
+ later phase, but `Logs_<Id>` is required for the API to authenticate/log. Their **Core
74
+ registration** rows (Databases/DatabaseHosts) are always generated regardless.
75
+ - **Reference data** — a fresh client has roles/ACL/lookups from the blank, but **not** ticket
76
+ reference data (Urgencies/TicketTypes/TicketStages/TicketTopics). Until seeded, ticket creates
77
+ that reference them return `EV-12`.
78
+ - **Drift before consolidation** — loose `Client/` files must already be applied to all existing
79
+ clients before they're consolidated/archived (otherwise the new blank diverges from live
80
+ clients). See the dbchanges2 architecture doc.
81
+
82
+ ## Gotchas
83
+
84
+ - **`FOREIGN_KEY_CHECKS=0`** is required when applying the loose schema files — several
85
+ `ALTER … MODIFY/DROP` a column that's in an FK and fail with error 1832 otherwise.
86
+ - **`Apis` rows are in the CLIENT database**, not Core. Core only holds `Clients`/`ClientEmailDomains`
87
+ /`ClientApiIdentities`. Auth needs three values: `client` = `Core.Clients.uuid`, `api` =
88
+ `Client_<Id>.Apis.uuid`, `secret` = `Client_<Id>.Apis.secret`.
89
+ - **`Apis_Roles` needs `Base`+`API` to pre-exist** in `Client_<Id>` — they come from the blank
90
+ seed. If the blank lacks roles, the role links insert zero rows and the key can't authorize.
91
+ - **Never commit secrets** — the generated `Apis` secrets go in a non-committed artifact; the Core
92
+ inserts are secret-free and committable.
93
+ - **Domain URLs** — dev uses `http://<sub>.togaX` (no TLD); beta/prod use `https://…<env>.togaX.com`.
94
+
95
+ ## Change history
96
+
97
+ - 2026-06-23 — Initial capture from the Fordham onboarding (TRUE-79702). (mhammontree)
@@ -17,8 +17,8 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
17
17
 
18
18
  - **_underscore** (_Underscore) _(framework core)_ — 11 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
19
19
  - **worker2** (Worker) — 11 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
20
- - **api2** (API) — 4 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
21
- - **dbchanges2** (Database Changes) _(framework core)_ — 1 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
20
+ - **api2** (API) — 5 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
21
+ - **dbchanges2** (Database Changes) _(framework core)_ — 2 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
22
22
  - **toga2-supply** (TOGa Supply) — 3 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
23
23
  - **saml** (SAML SSO Gateway) — 2 doc(s) → [2.0/apps/saml/INDEX.md](2.0/apps/saml/INDEX.md)
24
24
  - **toga2-view** (TOGa View Frontend) — 1 doc(s) → [2.0/apps/toga2-view/INDEX.md](2.0/apps/toga2-view/INDEX.md)
@@ -41,6 +41,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
41
41
  - **Compass Canada** (`compass-canada`) → [clients/compass-canada/INDEX.md](clients/compass-canada/INDEX.md)
42
42
  - **Compass USA** (`compass-usa`) → [clients/compass-usa/INDEX.md](clients/compass-usa/INDEX.md)
43
43
  - **Elite** (`elite`) → [clients/elite/INDEX.md](clients/elite/INDEX.md)
44
+ - **Fordham University** (`fordham`) → [clients/fordham/INDEX.md](clients/fordham/INDEX.md)
44
45
  - **GroWrk** (`growrk`) → [clients/growrk/INDEX.md](clients/growrk/INDEX.md)
45
46
  - **New York City Department of Education** (`nycdoe`) → [clients/nycdoe/INDEX.md](clients/nycdoe/INDEX.md)
46
47
  - **NYC Health & Hospitals** (`nychh`) → [clients/nychh/INDEX.md](clients/nychh/INDEX.md)
@@ -0,0 +1,5 @@
1
+ # Client: Fordham University `fordham`
2
+
3
+ | Doc | Framework | Summary | Files |
4
+ |-----|-----------|---------|-------|
5
+ | [Fordham University](profile.md) | 2.0 | Fordham University (`fordham.edu`), `clientIdentifier` **Fordham**, onboarded onto the 2.0 platform in June 2026 (TRUE-79702). | |
@@ -0,0 +1,49 @@
1
+ ---
2
+ title: "Fordham University"
3
+ framework: "2.0"
4
+ apps:
5
+ - _underscore
6
+ - api2
7
+ - dbchanges2
8
+ project: API
9
+ client: fordham
10
+ type: profile
11
+ status: active
12
+ updated: 2026-06-23
13
+ owners: ["mhammontree"]
14
+ files: []
15
+ related:
16
+ - ../../2.0/apps/api2/features/tickets-api.md
17
+ - ../../2.0/apps/dbchanges2/workflows/client-onboarding.md
18
+ ---
19
+
20
+ ## Summary
21
+
22
+ Fordham University (`fordham.edu`), `clientIdentifier` **Fordham**, onboarded onto the 2.0 platform
23
+ in June 2026 (TRUE-79702). Their integration uses the **TOGa 2.0 ticket API** (`/v2/tickets`) — they
24
+ create/update/read support tickets in our system via REST. Tickets are the **generic** flow (not
25
+ entitlement-based like PC Matic): the request body is ticket fields at the top level.
26
+
27
+ ## Onboarding
28
+
29
+ Provisioned via the standard [2.0 client onboarding process](../../2.0/apps/dbchanges2/workflows/client-onboarding.md):
30
+ `Client_Fordham` / `Logs_Fordham` / `Archive_Fordham`, Core registration, and two API keys
31
+ (internal "Agilant" + the "Fordham" client key). The committed dbchanges2 artifacts are
32
+ `Client/<DATE>-BLANK_CLIENT_DATABASE.sql` (seeded blank) and `Core/<DATE>-onboard_Fordham.sql`
33
+ (Core inserts); the API-key inserts (with secrets) are kept out of the repo.
34
+
35
+ ## Integration / API
36
+
37
+ - Uses **generic `/v2/tickets`** (POST/PUT/GET) — see [tickets-api](../../2.0/apps/api2/features/tickets-api.md).
38
+ - Customer-facing docs delivered (TRUE-79699): a Markdown guide + a Postman collection in PC-Matic
39
+ style (globals for `{{url}}`/`{{accessToken}}`, hardcoded creds in the auth body).
40
+
41
+ ## Known gaps
42
+
43
+ - **Ticket reference data not yet seeded** — `Urgencies`, `TicketTypes`, `TicketStages`,
44
+ `TicketTopics` are empty for Fordham, so ticket creates can only set descriptions/notes until those
45
+ are configured; referencing them returns `EV-12`.
46
+
47
+ ## Change history
48
+
49
+ - 2026-06-23 — Initial onboarding + ticket API integration. (mhammontree)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.173",
3
+ "version": "1.0.174",
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",