From e7b6045580129aface488e73503a449a72c9dc98 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 30 Apr 2026 17:13:11 -0400 Subject: [PATCH] Updates to the documentation. Co-authored-by: Copilot --- documentation/BOOTSTRAP__AI_Agent_Quickstart.md | 8 ++++++++ documentation/GUIDE__AE_API_V3_for_Frontend.md | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/documentation/BOOTSTRAP__AI_Agent_Quickstart.md b/documentation/BOOTSTRAP__AI_Agent_Quickstart.md index 2ce7c955..3fcce07e 100644 --- a/documentation/BOOTSTRAP__AI_Agent_Quickstart.md +++ b/documentation/BOOTSTRAP__AI_Agent_Quickstart.md @@ -296,6 +296,14 @@ These are real incidents — know them before you start. valid account-scoped requests to lose account context and 403. `key` can be a valid endpoint/business param, but it is not equivalent to `x-no-account-id: bypass`. +11. **Pre-stringifying `*_json` fields before passing to API wrappers** — the API wrappers + (`api_post__crud_obj.ts` for V3, `api.ts` for legacy CRUD) automatically serialize any + field ending in `_json` (e.g. `cfg_json`, `data_json`). Pass these as plain JS objects. + Pre-stringifying with `JSON.stringify()` before calling the wrapper will double-encode + the value in the legacy path (stringify sees a string and escapes it), and is at best + redundant on the V3 path. Both paths now pretty-print with 2-space indent. + See `GUIDE__AE_API_V3_for_Frontend.md` → section 3C for the full explanation. + --- ## 8. Source Layout (Quick Reference) diff --git a/documentation/GUIDE__AE_API_V3_for_Frontend.md b/documentation/GUIDE__AE_API_V3_for_Frontend.md index 19d01e7b..773dcae7 100644 --- a/documentation/GUIDE__AE_API_V3_for_Frontend.md +++ b/documentation/GUIDE__AE_API_V3_for_Frontend.md @@ -102,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]