fix(v3-vision): allow resolved integers to pass model validation during creation

Hardened root_validators in Event and Post Comment models to use Union[int, str] for Vision ID fields. This ensures that integer IDs resolved by sanitize_payload reach the database during POST/PATCH operations while maintaining clean string outputs for clients.
This commit is contained in:
Scott Idem
2026-02-05 20:30:44 -05:00
parent 03a1569eba
commit 78f04bca50
2 changed files with 73 additions and 49 deletions

View File

@@ -17,13 +17,14 @@ class Post_Comment_Base(BaseModel):
log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
# --- Standardized Vision IDs (Strings) ---
id: Optional[str] = Field(None, **base_fields['post_comment_id_random'])
post_comment_id: Optional[str] = Field(None, **base_fields['post_comment_id_random'])
post_id: Optional[str] = Field(None, **base_fields['post_id_random'])
account_id: Optional[str] = Field(None, **base_fields['account_id_random'])
person_id: Optional[str] = Field(None, **base_fields['person_id_random'])
user_id: Optional[str] = Field(None, **base_fields['user_id_random'])
# --- Standardized Vision IDs (Strings for API, Integers for DB) ---
# We use Union[int, str] to allow both public string IDs and resolved DB integers to pass validation.
id: Optional[Union[int, str]] = Field(None, **base_fields['post_comment_id_random'])
post_comment_id: Optional[Union[int, str]] = Field(None, **base_fields['post_comment_id_random'])
post_id: Optional[Union[int, str]] = Field(None, **base_fields['post_id_random'])
account_id: Optional[Union[int, str]] = Field(None, **base_fields['account_id_random'])
person_id: Optional[Union[int, str]] = Field(None, **base_fields['person_id_random'])
user_id: Optional[Union[int, str]] = Field(None, **base_fields['user_id_random'])
# --- Standardized Legacy / Internal IDs (Excluded) ---
id_random: Optional[str] = Field(None, alias='post_comment_id_random', exclude=True)
@@ -63,7 +64,8 @@ class Post_Comment_Base(BaseModel):
def map_v3_ids(cls, values):
"""
Vision Transformer:
Map DB keys to clean API keys and strip internal integers.
Map DB keys to clean API keys and strip internal integers during READ operations.
During CREATE (POST) operations, we ensure resolved integers are preserved.
"""
# 1. Map Random Strings to Clean Names
rid = values.get('id_random') or values.get('post_comment_id_random')
@@ -76,19 +78,19 @@ class Post_Comment_Base(BaseModel):
if per_rid := values.get('person_id_random'): values['person_id'] = per_rid
if u_rid := values.get('user_id_random'): values['user_id'] = u_rid
# 2. Prevent "Collision Population" or leakage of integers in string fields
# Note: During a POST (create), IDs are resolved to integers.
# We only delete them if a string version was successfully mapped above.
# 2. Prevent "Collision Population" or leakage of integers during API responses
# WE MUST NOT DELETE these if they are already integers during a POST operation
# as they have been resolved by sanitize_payload.
# We only delete the integer if a string version was successfully mapped above.
for k in ['id', 'post_comment_id', 'post_id', 'account_id', 'person_id', 'user_id']:
if k in values and not isinstance(values[k], str):
# Only delete if we have a random ID counterpart indicating we are in "Read" mode
# or if the integer is not strictly required for the current operation.
val = values.get(k)
if val is not None and not isinstance(val, str):
# If we have a random ID counterpart in the source dict, we are in "Read Mode".
# In Read Mode, we prioritize the string ID for the client.
# In "Create Mode", the random ID field won't be in 'values' after sanitize_payload
# but the integer will be in 'k'.
if values.get(f'{k}_random') or (k=='id' and values.get('id_random')):
del values[k]
else:
# It's a raw integer from the DB/view result (e.g. from v_post_comment)
# We MUST delete it from the string field to avoid ValidationError
del values[k]
return values