fix(models): migrate Archive_Content_Base to Vision ID pattern

- Replace integer `id` (alias archive_content_id) with Vision string fields:
  `id: Optional[str]` and `archive_content_id: Optional[str]` — both always
  hold the random string ID, never the DB integer.
- Add `root_validator(pre=True)` (map_v3_ids) that maps id_random /
  archive_content_id_random → id and archive_content_id, with collision
  prevention to reject any integer that arrives in these fields.
- Remove old `archive_content_id_lookup` integer validator (superseded by
  sanitize_payload + root_validator).
- Keep `id_random` (alias archive_content_id_random) in responses for
  backward compatibility; add id, archive_content_id, id_random to
  fields_to_exclude_from_db so they never appear in INSERT/UPDATE payloads.

Generic CRUD layer safety net (post_obj + post_child_obj):
- After building resp_data on create, swap any integer {obj_type}_id with
  the corresponding {obj_type}_id_random value — catches models not yet
  migrated to Vision IDs.
- Fix return_obj=False fallback to return obj_id as the random string.

Docs: add Section 3D to GUIDE__AE_API_V3_for_Frontend.md documenting the
Vision ID convention — {obj_type}_id is always the random string; the
_id_random suffix is a legacy artifact that frontend code should phase out.

Fixes: POST /v3/crud/archive/{id}/archive_content/ returning integer ID,
breaking the subsequent PATCH flow (422 min_length validation failure).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-25 17:40:27 -04:00
parent 9d5f2c8cea
commit cffde249d3
4 changed files with 59 additions and 16 deletions

View File

@@ -68,6 +68,30 @@ 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.
### D. ID Fields in Responses (Vision ID Convention)
> [!IMPORTANT]
> **V3 responses always use random string IDs — never database integers.**
After a successful `POST` create or any `GET`, the response contains:
| Field | Type | Use |
| :--- | :--- | :--- |
| `{obj_type}_id` | `string` | **Primary public ID.** Use this for subsequent `PATCH` calls and UI routing. |
| `{obj_type}_id_random` | `string` | Legacy alias. Same value as `{obj_type}_id`. Present for backward compat only. |
**Example — create then immediately PATCH:**
```ts
const created = await postArchiveContent(archiveId, payload);
const newId = created.data.archive_content_id; // random string e.g. "xK9mP3qRtL2"
// Use it directly in the PATCH URL — no lookup needed
await patchArchiveContent(newId, { name: 'Updated Name' });
// PATCH /v3/crud/archive/{archive_id}/archive_content/{newId}
```
> **Note on `_id_random` suffix:** The `{obj_type}_id_random` field is a legacy artifact from the pre-Vision model. Once you confirm `{obj_type}_id` is a random string (length 1122), you do not need `_id_random` as a fallback. New code should only read `{obj_type}_id`.
---
## 4. V3 Uniform Lookup System