toga-ai 1.0.995 → 1.0.997
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.
|
@@ -250,14 +250,14 @@ The reverse direction: not "queue a worker from an interceptor" but **"run the p
|
|
|
250
250
|
### Own-row guards in a PRE interceptor
|
|
251
251
|
|
|
252
252
|
A PRE hook that limits a user to their own rows must close four bypasses — each found by review on the `user-global-settings` guard (TRUE-82613):
|
|
253
|
-
1. **Alias keys.** api2 maps `user` / `setting` (FK objects) onto `userId` / `settingId` **after** PRE runs, so a hook that only checks `$payload->userId` is skipped by sending `user: {uuid}`. **Allowlist the payload keys** and
|
|
253
|
+
1. **Alias keys.** api2 maps `user` / `setting` (FK objects) onto `userId` / `settingId` **after** PRE runs, so a hook that only checks `$payload->userId` is skipped by sending `user: {uuid}`. **Allowlist the payload keys, verify every alias that is sent** (`user` must resolve to the caller; `setting` must resolve to an allowed setting, and on PUT/PATCH to the row's own setting), then `unset` all of `userId`, `settingId`, `user`, `setting` so api2 cannot remap them. Reject any other key. Refusing the aliases outright breaks real clients (TOGa Commerce sends `user: {uuid}`, `setting: {slug}`).
|
|
254
254
|
2. **Parent routes.** On `POST /v2/users/<uuid>/user-global-settings` api2 overwrites the FK the hook stamped with the parent's id **after** the hook. Refuse any POST with a parent segment.
|
|
255
255
|
3. **PRE runs BEFORE the field-level write ACL check** — the hook cannot count on the ACL to have rejected a field yet.
|
|
256
256
|
4. **PUT/PATCH carry no owner in the body.** Load the row by `$api->recordUuid`, refuse not-own rows, refuse changes to the owner/type columns, then `unset` them before the save.
|
|
257
257
|
|
|
258
258
|
Refuse API-key callers when the rule is "the signed-in user" (no user on the token). Throw `_Exception_Validation` (400); use **one** message for "not yours" and "not allowed" so the response does not reveal whether a row exists.
|
|
259
259
|
|
|
260
|
-
**Reference implementation:** `_Model_Client_UserGlobalSetting::prePost/prePut/prePatch` (Core.Records **279**), rows in `dbchanges2/Core/2026-10-09a - UserGlobalSettingsInterceptors.sql` (`clientId` + `apiId` NULL → **every tenant, every API**). Keys:
|
|
260
|
+
**Reference implementation:** `_Model_Client_UserGlobalSetting::prePost/prePut/prePatch` (Core.Records **279**), rows in `dbchanges2/Core/2026-10-09a - UserGlobalSettingsInterceptors.sql` (`clientId` + `apiId` NULL → **every tenant, every API**). Keys: `userId`/`user`, `settingId`/`setting`, `value` (aliases verified, then unset). Writable settings (by Core.Settings slug): **language** (value = a code in the **client** `Languages` table, `_Model_Client_Language`), **persona** (value = `Personas.number` of a persona assigned to the caller in `Users_Personas`), **currency** (value = uuid of a currency linked to one of the caller's personas via `Personas_Currencies`). `setting` may be sent as slug, uuid, id, or an object holding one of them. POST stamps `userId` to the caller and refuses a second row for the same user and setting. No ACL grant ships with it yet.
|
|
261
261
|
|
|
262
262
|
**Known own-row holes (open, not fixed — 2026-10-09):**
|
|
263
263
|
- `Client_CompassCanada/2026-01-15 - UserGlobalSettingsAcl.sql` grants UserGlobalSettings writes with no own-row check.
|
|
@@ -86,5 +86,5 @@ Treat this as obfuscation only. Anything genuinely sensitive must not rely on it
|
|
|
86
86
|
- New **encrypted** domains require a code change (`$encryptedDomains` in `index.php`), not just a `forward.ini` edit.
|
|
87
87
|
- `index.php` only runs on a map miss, so a bad/over-broad `forward.ini` host-only line can shadow paths you expected PHP to handle.
|
|
88
88
|
- **EB rejects bundles over 500 MB** ("The artifact is empty or exceeds the maximum size supported by AWS Elastic Beanstalk"), and the CodePipeline EB deploy ignores `.ebignore`. Never commit large static assets here — that broke every deploy from 2026-10-08 until demos moved to S3.
|
|
89
|
-
- **Git history
|
|
89
|
+
- **Git history was rewritten on 2026-10-09** (`git filter-repo`) to drop ~500 MB of old demo blobs; a clone is now ~39 MB. Any clone made before that date must be deleted and re-cloned — pulling into it brings the old history back. GitHub's `refs/pull/1/head` and `refs/pull/2/head` still point at old commits (GitHub blocks pushes to them).
|
|
90
90
|
- **Removing a top-level folder:** first check no Route 53 name pointing at forward EB has a first label matching it (local directory handler). Checked for the 2026-10-09 removal; `togadesk.beta.agilantsolutions.com` is redirected by `forward.ini` first.
|
package/package.json
CHANGED