toga-ai 1.0.885 → 1.0.886
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: Tools
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
9
|
+
updated: 2026-09-24
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- tools/_/app/developers/multiclientsql.php
|
|
@@ -18,6 +18,7 @@ related:
|
|
|
18
18
|
- ./developer-tools.md
|
|
19
19
|
- ./persona-gated-navigation.md
|
|
20
20
|
- ../../test/features/2-0-deployment-client-sql.md
|
|
21
|
+
- ../../../../2.0/apps/_underscore/features/per-client-database-connections.md
|
|
21
22
|
---
|
|
22
23
|
|
|
23
24
|
Tools `/developers/multi-client-sql` — fans one SQL change-set across a live list of 2.0 client/log/archive/module DBs into a copy/download script (never executes); open to use/extend it or for the `Databases` reserved-word gotcha.
|
|
@@ -31,10 +32,11 @@ Replaces `test/team/2.0 deployment/generate_client_sql.php`. Development Team pe
|
|
|
31
32
|
1. Paste SQL, pick a list, untick/filter DBs. Generate builds the script **in the browser**: header + per-DB banner + `` USE `db`; `` + SQL. Copy / Download `.sql`. Warns if the SQL has its own `USE`.
|
|
32
33
|
2. `post.php` action `lists` only returns JSON lists.
|
|
33
34
|
3. Lists are dynamic — no tools commit when clients change:
|
|
34
|
-
- **All Clients / Client Logs / Client Archives** — live read of `Core.Clients` joined to `Core.Databases` on `clientDatabaseId` / `logDatabaseId` / `archiveDatabaseId`, via config `[database_toga2core]`.
|
|
35
|
-
- **Module lists** — one per folder under `dbchanges2/_modules` (branch `_main`). A client is in the list when `Client_<Name>/_modules.txt` names the module (case-insensitive); DB name = client folder name. GitHub GraphQL, 2 calls (folder list, then all `_modules.txt` as aliased blobs). APCu cache 5 min + 7-day "last good" fallback shown with a warning. Warns when a module client is not in `Core.Clients
|
|
36
|
-
4.
|
|
37
|
-
5. Every
|
|
35
|
+
- **All Clients / Client Logs / Client Archives** — live read of `Core.Clients` joined to `Core.Databases` on `clientDatabaseId` / `logDatabaseId` / `archiveDatabaseId`, via config `[database_toga2core]`. Keeps a DB only if `EXISTS` a `Core.DatabaseHosts` row (INNER JOIN `Environments` on `slug`) for the `ENVIRONMENT` env var (tools is production-only: `production`). Missing `ENVIRONMENT` → user-safe error, never an unfiltered list. Why: `Core.Clients` has never-built clients (see [per-client DB gotcha](../../../../2.0/apps/_underscore/features/per-client-database-connections.md)). `isActive` flag rejected: inactive ≠ no DB, flags drift, and it is a Core schema change.
|
|
36
|
+
- **Module lists** — one per folder under `dbchanges2/_modules` (branch `_main`). A client is in the list when `Client_<Name>/_modules.txt` names the module (case-insensitive); DB name = client folder name. GitHub GraphQL, 2 calls (folder list, then all `_modules.txt` as aliased blobs). APCu cache 5 min + 7-day "last good" fallback shown with a warning. Warns when a module client is not in `Core.Clients`; drops clients whose client DB is not built. One retry on a dropped connection; log names the failed step (`folder list` / `_modules.txt read`).
|
|
37
|
+
4. Env vars `GITHUB_TOKEN` and `ENVIRONMENT` read by shared `envValue()` (`getenv` + `$_SERVER` + `$_ENV`, because php-fpm `clear_env`). GitHub token: **only** `GITHUB_TOKEN`. No config fallback (developer decision). Own curl, not `App_Design_Github`. Needs read on `agilantsolutions/dbchanges2`; set as an EB environment property in prod.
|
|
38
|
+
5. Every list returns a `skipped` array, shown on the page ("Skipped N (database not built — no DatabaseHosts row): …").
|
|
39
|
+
6. Every DB/folder name is checked against `^[A-Za-z0-9_]{1,64}$` before it goes into GraphQL or a `USE` line. Page writes via `textContent`/`.value` only.
|
|
38
40
|
|
|
39
41
|
## Gotchas
|
|
40
42
|
|
|
@@ -51,3 +53,4 @@ Replaces `test/team/2.0 deployment/generate_client_sql.php`. Development Team pe
|
|
|
51
53
|
## Change history
|
|
52
54
|
|
|
53
55
|
- 2026-09-22 — Created; shipped and verified in production. (jcardinal)
|
|
56
|
+
- 2026-09-24 — Lists filtered by `Core.DatabaseHosts` for `ENVIRONMENT`; `skipped` list shown; verified prod 35 of 46. (jcardinal)
|
|
@@ -6,7 +6,7 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
9
|
+
updated: 2026-09-24
|
|
10
10
|
owners: ["dfranks", "jcardinal", "mhammontree", "apeterson", "kyalamarthi", "bala"]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Database.php
|
|
@@ -59,6 +59,7 @@ When `_underscore` serves a request for a client it opens **three distinct per-c
|
|
|
59
59
|
|
|
60
60
|
## Gotchas
|
|
61
61
|
|
|
62
|
+
- **`Core.Clients` has rows for clients whose DBs were never built** (prod 2026-09-24: 46 rows, 35 built). "DB exists" = a `Core.DatabaseHosts` row (`databaseId` + `environmentId` [+ `regionId`]) for the current `Environments.slug` — the same rows `registerClientDatabases()` resolves. Any fan-out over all clients must filter `EXISTS` on `DatabaseHosts` for the env, not `Core.Clients` alone; `isActive`-style flags are wrong (inactive clients still have DBs). Host-row count varies (e.g. `Archive_Nychh` has 1, others 4) — still built. Example: [Tools Multi-Client SQL](../../../../1.0/apps/tools/features/multi-client-sql.md).
|
|
62
63
|
- **⚠ NEVER read `LAST_INSERT_ID()` (or any other per-connection session value) through `_Query`.** `_Query` defaults `_isReadHostEnabled = true` (`Query.php:8`) and routes SELECTs to `CONNECTION_READ` (`Query.php:273-276`). `LAST_INSERT_ID()` is scoped to the connection that did the INSERT, so a read-host SELECT returns **0** — silently wrong, and now an FK violation wherever the id is used as a foreign key. Use `mysqli_insert_id` on the write/transaction connection and reject `<= 0`. It is not biting today only because most client registrations leave `writeHost`/`readHost` null, and `Database.php:488` then points READ and WRITE at the **same** `mysqli` handle (so raw `mysqli_query` and `new _Query(...)` share one connection and one transaction). Configuring a real read host for any client would break every such call at once. Worked example: [Compass PEOPLE-file user lifecycle](../../../clients/compass-usa/features/people-file-user-lifecycle.md).
|
|
63
64
|
- **Raw `mysqli_query` bypasses `_Query`'s automatic query-cache reset.** After a hand-rolled write, call `_Database::resetQueryCache($dbName)` yourself or later model reads serve stale rows.
|
|
64
65
|
|
|
@@ -92,3 +93,4 @@ Methodology lesson — why the wrong conclusion was reached: the model-class com
|
|
|
92
93
|
|
|
93
94
|
## Change history
|
|
94
95
|
- 2026-09-23 — Added the read-host routing trap: `_Query` sends SELECTs to `CONNECTION_READ`, so `LAST_INSERT_ID()` read through `_Query` can return 0; noted that null `writeHost`/`readHost` currently collapses both to one handle, and that raw `mysqli_query` needs a manual `resetQueryCache()`. (mhammontree)
|
|
96
|
+
- 2026-09-24 — Added gotcha: filter client fan-outs by `DatabaseHosts` for the environment; `Core.Clients` includes never-built clients. (jcardinal)
|
package/package.json
CHANGED