toga-ai 1.0.296 → 1.0.297

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.
@@ -21,3 +21,4 @@
21
21
  | [Surface Resolver (_Model_Core_Surface::resolve — replaces Page::meta)](features/surface-resolver.md) | The runtime for the platform-wide **Surface** UI presentation layer: 9 `_underscore` models plus a cached resolver, `_Model_Core_Surface::resolve(&$api, string | _underscore/Model/Core/Surface.php, _underscore/Model/Client/AclRecordScript.php, _underscore/Model/Core/RecordScript.php, dbchanges2/Core/2026-06-30a - SurfaceMetaGroupAndSalesOrderSections.sql, dbchanges2/Client/2026-06-30a - SurfaceMetaGroupAcl.sql, dbchanges2/Client_Quad/2026-07-01a - GrantSurfacesMetaGroupScriptAcl.sql, dbchanges2/Client_CompassCanada/2026-07-01a - GrantSurfacesMetaGroupScriptAcl.sql, dbchanges2/Core/2026-06-29b - SurfaceMetaPublicReadAcl.sql, dbchanges2/Client/2026-06-29c - SurfaceRecordScriptAcl.sql, dbchanges2/Core/2026-06-29c - SurfaceDebugPhpMethodFix.sql, _underscore/Model/Core/SurfaceElement.php, _underscore/Model/Core/Action.php, _underscore/Model/Core/Vocabulary.php, _underscore/Model/Core/VocabularyTerm.php, _underscore/Model/Core/Message.php, _underscore/Model/Client/SurfaceOverride.php, _underscore/Model/Client/MessageTranslation.php, _underscore/Model/Client/ThemeToken.php, _underscore/Model/Core/Page.php |
22
22
  | [Tracking-Number Bridge Migration (ASN / Item Fulfillment / Item Receipt)](features/tracking-number-bridges.md) | Shipment tracking numbers used to live as **scalar FK columns** (`trackingNumberId`, `returnTrackingNumberId`) directly on the lowest-level "unit"/"item" tables | api2/Component/Api/V2/V2.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnit.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillmentItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Prudential/AdvanceShippingNotice.php, _underscore/Model/Compass/AdvanceShippingNotice.php, _underscore/Trait/Netsuite/ItemFulfillment.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Core/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql, dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql |
23
23
  | [Units for Items for Purchase Orders — Data Structure](features/units-for-items-for-purchase-orders.md) | Describes how unit (serialized inventory) data is linked to sales-order and purchase-order line items behind the `units-for-items-for-purchase-orders` TableView | |
24
+ | [Running a 2.0 App Locally (browser, end-to-end via api2)](workflows/running-a-2.0-app-locally.md) | The full dependency chain required to run a 2.0 client app **through the browser**, end-to-end, against a **local `api2`** (e.g. | _underscore/Environment.php, _underscore/Config.php, _underscore/Database.php, _underscore/Route.php, api2/Component/Api/V2/V2.php, api2/index.php, api2/.htaccess |
@@ -6,8 +6,8 @@ project: _Underscore
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-18
10
- owners: ["dfranks", "jcardinal"]
9
+ updated: 2026-07-09
10
+ owners: ["dfranks", "jcardinal", "mhammontree"]
11
11
  files:
12
12
  - _underscore/Database.php
13
13
  - _underscore/ApiRequest.php
@@ -93,6 +93,7 @@ registration is region-aware in `api2/Controller/Index.php`; the alias const is
93
93
 
94
94
  ## Change history
95
95
 
96
+ - 2026-07-09 — Linked the new [Running a 2.0 app locally](../workflows/running-a-2.0-app-locally.md) runbook, which frames these three connections as one requirement of a full local browser run. (mhammontree)
96
97
  - 2026-07-07 — Noted the new shared **Cache** cluster (`Databases` id 145, alias `DB_CACHE`,
97
98
  region-aware) added for the api2 cross-client retrieval engine. (jcardinal)
98
99
  - 2026-06-18 — Documented after the `Logs_Growrk`/`Logs_Aig` local 500s while testing the
@@ -101,4 +102,5 @@ registration is region-aware in `api2/Controller/Index.php`; the alias const is
101
102
  ## Related docs
102
103
 
103
104
  - [_underscore architecture](../architecture.md)
105
+ - [Running a 2.0 app locally (browser end-to-end)](../workflows/running-a-2.0-app-locally.md) — the full local-stack runbook these three connections are one requirement of.
104
106
  - [NetSuite → TOGa Supply per-client sync](../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md) — the work that surfaced this.
@@ -0,0 +1,124 @@
1
+ ---
2
+ title: Running a 2.0 App Locally (browser, end-to-end via api2)
3
+ framework: "2.0"
4
+ repo: _underscore
5
+ project: _Underscore
6
+ client: shared
7
+ type: workflow
8
+ status: active
9
+ updated: 2026-07-09
10
+ owners: ["mhammontree"]
11
+ files:
12
+ - _underscore/Environment.php
13
+ - _underscore/Config.php
14
+ - _underscore/Database.php
15
+ - _underscore/Route.php
16
+ - api2/Component/Api/V2/V2.php
17
+ - api2/index.php
18
+ - api2/.htaccess
19
+ related:
20
+ - ../features/per-client-database-connections.md
21
+ - ../../dbchanges2/workflows/client-onboarding.md
22
+ - ../../dbchanges2/architecture.md
23
+ ---
24
+
25
+ ## Summary
26
+
27
+ The full dependency chain required to run a 2.0 client app **through the browser**,
28
+ end-to-end, against a **local `api2`** (e.g. pointing the `toga2-view` frontend at a laptop
29
+ `api2` instead of beta/prod). This is separate from CLI/script backend testing — it exercises
30
+ the web SAPI, the Apache-supplied environment, Core-driven client-DB registration, and the
31
+ `/v2/auth/login` browser auth gate, none of which the CLI path touches. It cost hours to
32
+ reverse-engineer; the notes below are platform-general (any 2.0 client app), with Rate used
33
+ only as the running example.
34
+
35
+ **Bottom line:** most local failures here are a **provisioning gap in the local stack**
36
+ (missing/stale DB, unregistered origin, unseeded Core), *not* an app bug. The confusing
37
+ `Route.php:525` "failed to determine how to render view" and stale-Core "missing model file"
38
+ fatals below both mean "the local stack isn't fully stood up."
39
+
40
+ > Cost/benefit note from the originating session: because standing the full local backend up
41
+ > is this involved, the team's chosen shortcut for front-end work was to **deploy api2 to beta
42
+ > and point the local frontend at beta** rather than rebuild the entire local backend stack.
43
+
44
+ ## Steps / requirements
45
+
46
+ ### 1. ENVIRONMENT comes from Apache for the web app (not the CLI)
47
+
48
+ - `_Environment::initialize()` reads `getenv('ENVIRONMENT')` (`_underscore/Environment.php:11`)
49
+ and **throws if unset**. `_Config` then loads `Config/<ENVIRONMENT>.ini` (`Config.php:38`).
50
+ - The **web app** gets `ENVIRONMENT` from **Apache** — a `SetEnv ENVIRONMENT <name>` in the
51
+ api2 vhost — *not* from your shell/CLI environment. Dev convention:
52
+ `ENVIRONMENT=dev-<name>-laptop` → loads `Config/dev-<name>-laptop.ini`.
53
+ - To see what the **web** app actually resolves (the frontend URL/console won't show it — api2
54
+ is a separate host), temporarily add to the top of `api2/index.php`:
55
+ `if (isset($_GET['__env'])) die(getenv('ENVIRONMENT'));` and hit `http://api2/?__env=1`.
56
+ Remove it afterward.
57
+
58
+ ### 2. api2 collapses the environment name to a slug
59
+
60
+ - `V2.php:146`: `$this->environment = (substr($name,0,4)=='dev-') ? 'dev' : $name`. So **any**
61
+ `dev-*` INI resolves to the slug **`dev`** for downstream lookups (notably Core DB host
62
+ selection, below).
63
+
64
+ ### 3. Client DB connections are Core-driven, not from the INI
65
+
66
+ - `_Database::registerClientDatabases($environment, $clientId)` (`_underscore/Database.php:56`)
67
+ SELECTs from **Core**, joining `Clients → Databases → DatabaseHosts → Environments(slug=<env>)`
68
+ to resolve the client's **client, log, AND archive** databases (all three INNER-JOINed — a
69
+ missing row for any one drops the whole registration).
70
+ - For local, Core must have an `Environments.slug='dev'` row plus `DatabaseHosts` rows pointing
71
+ all three DBs at `localhost`. A prod Core backup **already carries a `dev`→localhost row by
72
+ design** — do not assume it's missing.
73
+ - There are **two** log connections: `DB_LOGS` (base framework `Logs`) and `DB_CLIENT_LOGS`
74
+ (per-tenant `Logs_<tenant>`). See
75
+ [per-client database connections](../features/per-client-database-connections.md) for the
76
+ three-alias mechanism and the logs-DB write trap.
77
+
78
+ ### 4. Browser login `POST /v2/auth/login` — requirements in the order code checks them
79
+
80
+ Checked in `V2.php` (~lines 485–800):
81
+
82
+ 1. **POST with an `Origin` header.** A browser address-bar **GET** has neither → silent
83
+ fallthrough (no auth, no useful error). Requests must come from the frontend (fetch/XHR),
84
+ not a typed URL.
85
+ 2. **`Core.Domains` row for the port-stripped origin.** `V2.php:98-103` strips the port, so
86
+ `http://rate.togaview:5173` matches a `Core.Domains` row for `http://rate.togaview`. That
87
+ row's `clientId`/`appId` must resolve to the local client/app.
88
+ 3. **Active login user** must exist in `Client_<tenant>.Users`.
89
+ 4. **All four databases must exist WITH SCHEMAS:** `Client_<tenant>`, `Logs_<tenant>`,
90
+ `Archive_<tenant>`, and base `Logs`. An **empty** database is not enough — every request
91
+ writes a transaction log via `$log->save()` at `execute()` finalization (`V2.php:2138`) into
92
+ `Logs_<tenant>.Api` / `Logs.Api`. Structure-only imports of the log/archive DBs are fine.
93
+ 5. **`Core.Apis` must be seeded** — API auth uses `Apis.uuid`/`Apis.secret`. `Apis` is
94
+ deliberately **excluded from blanks/backups**, so a freshly restored Core often has it empty.
95
+
96
+ ## Gotchas / known issues
97
+
98
+ - **The silent `Route.php:525` error** — `"Failed to determine how to render view for route
99
+ '/v2/...'"` (thrown at `_underscore/Route.php:525`) means the API handler returned **no**
100
+ response, so `_Route` fell through to view rendering. It is thrown during bootstrap
101
+ **outside** api2's JSON error handler, so the browser shows raw HTML and often **nothing** is
102
+ written to the PHP error log. The real cause is almost always a **local DB/registration gap**
103
+ (missing DB or schema, unresolved client-DB registration, or the auth gate being skipped per
104
+ step 4.1) — treat it as "the local stack isn't fully provisioned," not a request/app defect.
105
+
106
+ - **A STALE local Core silently 500s every api2 request.** api2's V2 loops **every**
107
+ `Core.Records` model at request time (`$thisModelName::TABLE`, `V2.php:3442-3446`). If local
108
+ Core is missing recent migrations it still references removed models and **fatals on a missing
109
+ model file** — a confusing error that looks unrelated to the DB and breaks *all* requests.
110
+ Concrete example: `dbchanges2/Core/2026-06-10 - TrackingNumberBridges.sql` is **non-idempotent**
111
+ (fixed record ids 317–322, RecordFields 2171–2200 — cannot be re-run) and its Section 9
112
+ **DELETES** Core `Records` row 41 (`ItemFulfillmentPackages`, model
113
+ `\_Model_Client_ItemFulfillmentPackage`), consolidating it into
114
+ `ItemFulfillments_TrackingNumbers` (record 317). A local Core missing this migration still has
115
+ record 41, so V2 fatals on the removed `_Model_Client_ItemFulfillmentPackage` file.
116
+ **Fix:** bring local Core current — apply the missing Core migrations in date order, or refresh
117
+ Core wholesale. Do not re-run a single non-idempotent migration in isolation.
118
+
119
+ ## Change history
120
+
121
+ - 2026-07-09 — Documented the full local browser-run dependency chain (Apache `ENVIRONMENT`,
122
+ `dev-*`→`dev` slug collapse, Core-driven client-DB registration, `/v2/auth/login` browser gate,
123
+ the `Route.php:525` silent-fallthrough gotcha, and the stale-Core "missing model file" fatal),
124
+ discovered while trying to run `toga2-view` against a local `api2`. (mhammontree)
@@ -17,7 +17,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
17
17
 
18
18
  ## 2.0 framework
19
19
 
20
- - **_underscore** (_Underscore) _(framework core)_ — 26 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
20
+ - **_underscore** (_Underscore) _(framework core)_ — 27 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
21
21
  - **worker2** (Worker) — 27 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
22
22
  - **api2** (API) — 10 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
23
23
  - **dbchanges2** (Database Changes) _(framework core)_ — 3 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.296",
3
+ "version": "1.0.297",
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",