toga-ai 1.0.455 → 1.0.456

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: API
6
6
  client: shared
7
7
  type: architecture
8
8
  status: active
9
- updated: 2026-07-27
9
+ updated: 2026-07-28
10
10
  owners: [jcardinal, bala, mhammontree]
11
11
  files:
12
12
  - api2/Controller/Index.php
@@ -141,6 +141,8 @@ Aliases: `DB_CORE`, `DB_CLIENT`, `DB_CLIENT_LOGS`, `DB_CLIENT_ARCHIVE`, `DB_LOGS
141
141
  `DB_STORE_1`/`DB_VISION_1` (legacy). `_Database::registerClientDatabases(clientId,
142
142
  environment)` joins `Clients`/`Databases`/`DatabaseHosts`/`Environments`, preferring the
143
143
  instance's own region; reads→readers, writes→writers, per-connection transactions.
144
+ `DB_CACHE` (shared Cache cluster) is resolved **by name** (`Databases.name = 'Cache'`) — never by
145
+ a hardcoded id, which differs per Core instance.
144
146
 
145
147
  ## Deployment (EB)
146
148
 
@@ -169,11 +171,39 @@ build. These must be **rotated** (treat the committed tokens as compromised) and
169
171
  Parameter Store / EB env properties. **Flag this if you touch config or deploy.** (Location +
170
172
  remediation only — do not record the token value anywhere.)
171
173
 
172
- **Follow-up (deferred, separate ticket): raw exception disclosure to clients.** The error paths that
173
- surface a caught `\Throwable` (now that Route.php rethrows and the bootstrap guard reports failures)
174
- must not return raw `getMessage()`/`getTrace()` output in the client-facing envelope — that leaks
175
- internal paths, schema names, and stack frames to API consumers. Sanitize the client envelope
176
- (generic message + code; full detail to Sentry/logs only). Not yet done.
174
+ ## Known issues / accepted risks
175
+
176
+ Open items a maintainer should know before changing this tier. None are "bugs to fix right now" —
177
+ they are the known sharp edges. Do not re-discover these from scratch.
178
+
179
+ 1. **Raw exception disclosure to clients (deferred, separate ticket).** The error paths that
180
+ surface a caught `\Throwable` (now that Route.php rethrows and the bootstrap guard reports
181
+ failures) must not return raw `getMessage()`/`getTrace()` output in the client-facing envelope —
182
+ that leaks internal paths, schema names, and stack frames to API consumers. Sanitize the client
183
+ envelope (generic message + code; full detail to Sentry/logs only). Not yet done.
184
+ 2. **Committed plaintext credentials, not yet rotated.** See the Security note above —
185
+ `Config/*.ini` secrets and the per-env `.ebextensions/git.*.json` GitHub PAT. Treat as
186
+ compromised until rotated and moved to SSM / EB env properties.
187
+ 3. **The pre-execute phase still runs before `execute()`'s try/catch.** The 2026-07-23 fix wraps the
188
+ Core/Logs bootstrap specifically; it did not move the phase inside the main guard. Any *new* code
189
+ added to the pre-execute block is again outside `execute()`'s protection and must carry its own
190
+ `try/catch (\Throwable)`.
191
+ 4. **Local Logs DB name mismatch reads as "missing".** The Core Logs schema name comes from a
192
+ `Core.Database` row (`id = CORE_LOGS_DATABASE_ID`); a local Logs DB whose actual schema name
193
+ differs throws `Unknown database`. This is environment config, not a code bug — fix the row or
194
+ the local schema name, don't patch the bootstrap.
195
+ 5. **CORS is fully permissive.** `Access-Control-Allow-*` is wide open on every route. Acceptable
196
+ only because auth is bearer-token (not cookie) based — if any cookie/session-backed auth is ever
197
+ added here, this becomes an exploitable hole and must be tightened first.
198
+ 6. **`_underscore` is cloned at build from a moving branch** (`_<ENVIRONMENT>`), not pinned to a
199
+ commit. Two deploys of the same api2 commit can produce different runtime behavior. Check the
200
+ framework branch state when triaging an "it worked yesterday" regression.
201
+ 7. **`V2.php::execute()` is a ~2,000-line monolith** with `processRoutePairs()` recursion beneath
202
+ it. There is no unit-test harness around it; changes are validated by integration traffic. Make
203
+ surgical edits and preserve the transaction/logging invariant.
204
+ 8. **JWT signing-secret rotation accepts current + previous.** During the overlap window a token
205
+ signed with the retired secret still validates. Revocation is therefore not immediate —
206
+ don't rely on rotation alone to lock out a compromised token.
177
207
 
178
208
  ## When making changes here
179
209
 
@@ -191,5 +221,6 @@ internal paths, schema names, and stack frames to API consumers. Sanitize the cl
191
221
  or `execute()`.
192
222
 
193
223
  ## Change history
224
+ - 2026-07-28 — Added a consolidated **Known issues / accepted risks** section (8 items), absorbing the previously free-floating deferred raw-exception-disclosure follow-up as item 1, so the tier's sharp edges (unrotated committed secrets, pre-execute phase still outside the main guard, local Logs DB name mismatch, permissive CORS, unpinned `_underscore` build clone, untested `V2.php` monolith, JWT rotation overlap window) are in one place instead of scattered. Recorded that `DB_CACHE` is resolved by name (`Databases.name = 'Cache'`), never by a hardcoded id, which differs per Core instance. (jcardinal)
194
225
  - 2026-07-27 — Sharpened the committed-secret note: the plaintext GitHub PAT lives in the per-env **`.ebextensions/git.*.json`** files (used by the `prebuild/git.sh` clone hook to pull `_underscore`), must be rotated and moved to SSM / EB env properties (location + remediation only, no value). (mhammontree)
195
226
  - 2026-07-23 — Documented the now-guarded Core/Logs DB bootstrap in the front controller: the pre-execute block runs before the `execute()` try/catch, the Core Logs schema name is resolved from a `Core.Database` row (`id = CORE_LOGS_DATABASE_ID`) so a name-mismatched local Logs DB reads as missing, and the failure is now wrapped in `try/catch (\Throwable)` returning `INVALID_CONFIGURATION` + Sentry instead of a fatal (guarded no-op rollback, `Database.php:219–226`). Added the deferred raw-getMessage/getTrace client-disclosure follow-up to the Security note. (jcardinal)
@@ -5,7 +5,7 @@ project: _Underscore
5
5
  client: shared
6
6
  type: standard
7
7
  status: active
8
- updated: 2026-06-16
8
+ updated: 2026-07-28
9
9
  owners: [jcardinal]
10
10
  files: []
11
11
  related:
@@ -26,41 +26,52 @@ All framework classes use a leading underscore prefix:
26
26
 
27
27
  - Controllers: `_Controller` base, subclasses `_Controller_<Name>`
28
28
  - Models: `_Model` base, subclasses `_Model_<Name>`
29
- - Workers: `_Worker` base, subclasses `_Worker_<Name>`
29
+ - Workers: `_Worker` dispatcher; action classes are `abstract class _Worker_<Name>` with static entry methods
30
30
  - API handlers: `_Api` base or `_Api_<Name>`
31
31
 
32
32
  Application code in `worker2` and `api2` follows the same leading-underscore convention for framework-extending classes.
33
33
 
34
34
  ## Worker contract
35
35
 
36
- Every worker class must extend `_Worker` and implement the `run()` method.
36
+ Worker action classes **do not extend `_Worker`** and have no `run()` method. A worker is an
37
+ `abstract class` of static entry methods, one method per queue action, mirrored by its file path.
37
38
 
38
39
  ```php
39
- // CORRECT
40
- class _Worker_BatchOrders extends _Worker {
41
- public function run(): void {
42
- // process the job payload from $this->payload
40
+ // CORRECT — worker2/Worker/Platform/Cache.php
41
+ abstract class _Worker_Platform_Cache {
42
+ public static function Clean(int $graceSeconds = 60): void {
43
+ // do the work; parameters arrive as named arguments
43
44
  }
44
45
  }
45
46
  ```
46
47
 
47
- The `run()` method has no parameters and returns void. Job data is accessed via `$this->payload` (or the framework's equivalent property). Do not add parameters to `run()`.
48
+ The class is `abstract` (never instantiated), the entry methods are `public static`, and the
49
+ action's queue name is the `Category/Sub/File/MethodName` path — `Platform/Cache/Clean` above.
50
+ Job data arrives as **method parameters**, not as a payload property: the dispatcher spreads the
51
+ parameter array as named arguments, so parameter names are part of the public contract. Renaming
52
+ a parameter is a breaking change to every queued job already in flight. Give parameters defaults
53
+ where a sensible one exists, so an older enqueued job missing a newly added key still runs.
48
54
 
49
55
  ## Worker dispatch — never call directly
50
56
 
51
- Workers must only be invoked via the queue dispatcher. Never call a worker's `run()` method directly from a controller, another worker, or any non-queue context.
57
+ Workers must only be invoked through the queue. Never call a worker's entry method directly from a
58
+ controller, another worker, or any non-queue context.
52
59
 
53
60
  ```php
54
61
  // CRITICAL VIOLATION — direct call
55
- $worker = new _Worker_BatchOrders($payload);
56
- $worker->run();
62
+ _Worker_Platform_Cache::Clean();
57
63
 
58
- // CORRECT — dispatch through queue
59
- _Queue::dispatch('_Worker_BatchOrders', $payload);
60
- // or the framework's equivalent dispatch method
64
+ // CORRECT — dispatch through the queue
65
+ _Worker::runTask('Platform/Cache/Clean', ['graceSeconds' => 120]);
61
66
  ```
62
67
 
63
- Direct calls bypass retry logic, error handling, visibility timeout, and monitoring. Even in development or testing, use the sync queue adapter — do not call `run()` directly.
68
+ `_Worker::runTask(string $action, array|object $parameters)` is the only supported entry point. The
69
+ action is the `Category/Sub/File/MethodName` path; `parameters` is string-keyed and is spread as
70
+ **named arguments** at dispatch (`$className::$functionName(...$parameters)`), so every key must
71
+ match a parameter name on the target method.
72
+
73
+ Direct calls bypass retry logic, error handling, SQS visibility timeout, WorkerJobs tracking and
74
+ monitoring. Even in development, dispatch through the queue — do not invoke the method directly.
64
75
 
65
76
  ## API response envelope (api2 only)
66
77
 
@@ -143,3 +154,6 @@ public function run(): void {
143
154
  ```
144
155
 
145
156
  Distinguish between retriable errors (transient DB/network issues — re-throw) and non-retriable errors (bad data, missing record — log and return).
157
+
158
+ ## Change history
159
+ - 2026-07-28 — Corrected the **Worker contract** and **Worker dispatch** sections to match the actual codebase: worker actions are `abstract class _Worker_<Name>` with `public static` entry methods dispatched via `_Worker::runTask(string $action, array|object $parameters)` on the `Category/Sub/File/MethodName` path, with parameters spread as **named arguments** (`$className::$functionName(...$parameters)`, worker2 `Controller/Index.php:325,567`; `_underscore/Worker.php:8`). This replaces the previous `extends _Worker` / `run()` / `_Queue::dispatch()` guidance — no worker in worker2 follows it, `_Queue::dispatch()` does not exist in the codebase, and following the old text would produce a worker that never dispatches. (jcardinal)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.455",
3
+ "version": "1.0.456",
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",