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-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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-
|
|
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`
|
|
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
|
-
|
|
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
|
|
41
|
-
public function
|
|
42
|
-
//
|
|
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
|
|
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
|
|
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
|
-
|
|
56
|
-
$worker->run();
|
|
62
|
+
_Worker_Platform_Cache::Clean();
|
|
57
63
|
|
|
58
|
-
// CORRECT — dispatch through queue
|
|
59
|
-
|
|
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
|
-
|
|
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