From c378040ad4e553bb105cce43f5371b999a023581 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 30 Apr 2026 17:14:42 -0400 Subject: [PATCH] Updated docs --- .../GUIDE__AE_API_V3_for_Frontend.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/documentation/GUIDE__AE_API_V3_for_Frontend.md b/documentation/GUIDE__AE_API_V3_for_Frontend.md index d63c09e..773dcae 100644 --- a/documentation/GUIDE__AE_API_V3_for_Frontend.md +++ b/documentation/GUIDE__AE_API_V3_for_Frontend.md @@ -21,6 +21,9 @@ Required for any non-public data (Journals, Badges, Users, etc.). * **Header:** `x-no-account-id: bypass` 3. **Token Access**: Provide a **JWT** in the query string. * **Query Param:** `?jwt=` +4. **Important Distinction:** A query parameter named `key` is **not** an account-context bypass signal. + * `key` may be used by specific endpoints/business logic, but it must **not** cause the frontend to remove `x-account-id`. + * Only explicit `x-no-account-id: bypass` should strip account context. > [!CAUTION] > **UNSUPPORTED HEADERS:** The header `x-aether-api-token` is **NOT recognized** by the V3 API. If you send it, the backend will treat you as a guest and block access to private data. @@ -99,6 +102,22 @@ Modify data in the system. * **Header:** `x-ae-ignore-extra-fields: true` * **Behavior:** When set to `true`, the backend will automatically strip any fields from the payload that are not defined in the object's model before attempting to save to the database. +#### `*_json` field serialization — do NOT pre-stringify in route/component code + +The frontend API wrappers (`src/lib/ae_api/api_post__crud_obj.ts` for V3, `src/lib/api/api.ts` for legacy CRUD) automatically serialize any field whose name ends in `_json` (e.g. `cfg_json`, `data_json`) before sending. They pretty-print with 2-space indent via an internal `serialize_json_field_pretty()` helper. + +**Pass `*_json` fields as plain JS objects from routes and components.** The serialization layer handles the rest. + +```ts +// ✅ Correct — pass as plain object; V3 wrapper serializes it +await update_ae_obj__site({ site_id, data_kv: { cfg_json: { jitsi_token_endpoint: url } } }); + +// ❌ Wrong — double-encodes the JSON string (the wrapper would stringify an already-stringified value) +await update_ae_obj__site({ site_id, data_kv: { cfg_json: JSON.stringify({ jitsi_token_endpoint: url }) } }); +``` + +The V3 wrapper (`api_post__crud_obj.ts`) only serializes when `typeof value === 'object'`, so it will not double-encode a plain string. The legacy wrapper (`api.ts`) stringifies unconditionally, so pre-stringifying there **will** produce double-encoded JSON. In both cases, the right answer is to pass the raw object and let the layer handle it. + ### D. ID Fields in Responses (Vision ID Convention) > [!IMPORTANT] @@ -587,3 +606,5 @@ If you receive a 403 on a valid ID: 2. Ensure you are sending `x-account-id` and NOT `x-aether-api-token`. 3. Verify the record actually belongs to the account ID you are sending. 4. Check if the object is marked `public_read: True` in the registry. (Posts and Archive Content allow guest access; Journals and Badges do not). +5. Confirm the frontend is not treating `params.key` as an implicit bypass and stripping `x-account-id`. +6. If list/search endpoints work but `GET /v3/crud/{obj_type}/{id}` still returns 403, this is likely endpoint-level policy (e.g., requires stronger auth like JWT) rather than a transport/header bug.