fix(storage): ASCII-encode S3 object metadata — s3-only upload 500 על שמות-קובץ עבריים (INV-STG2) #237
Reference in New Issue
Block a user
Delete Branch "worktree-s3-meta-ascii"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
הבעיה
כל העלאת קובץ עם שם עברי נכשלה ב-500 תחת backend
s3-only. התגלה דרך קליטת היומונים: היומון האחרון שנקלט הוא 5165 (9.6) — לפני ה-cutover ל-s3-only (2026-06-11); מאז 5166/5167 לא נכנסו.Traceback (ייצור):
השורש
ingest._stage_fileמצרף את שם-הקובץ המקורי כ-S3 object metadata (metadata={"filename": src.name}), ו-S3Backend.put_bytesהעביר אותו verbatim ל-put_object. botocore אוכף ASCII-only על S3 metadata → 500. נחשף ב-cutover ל-s3-only — משפיע על כל העלאה עם שם עברי (יומונים, מסמכי-תיק, פסיקה), לא רק יומונים.התיקון (G1 — נרמול-במקור; INV-STG2)
_ascii_metadataמקודד ערכי-metadata לא-ASCII ב-percent-encoding (lossless; שחזור ב-urllib.parse.unquote); ASCII רגיל עובר ללא שינוי.S3Backend.put_bytesמחיל אותו על כל ערכי ה-Metadata.זהו תיקון בשכבת-האחסון היחידה (choke-point), לא מסלול מקביל (G2).
בדיקות
test_ascii_metadata_encodes_hebrew— ה-helper מקודד עברית ל-ASCII ומשחזר.test_s3_put_bytes_sends_ascii_metadata— משחזר את מסלול-הכשל מולput_objectמזויף ומוודא Metadata ASCII בלבד.test_storage_staging.py+test_unified_ingest.py.Invariants
🤖 Generated with Claude Code
תיקון: כל העלאת קובץ עם שם עברי נכשלה ב-500 תחת backend s3-only. השורש: `ingest._stage_file` מצרף את שם-הקובץ המקורי כ-S3 object metadata (`metadata={"filename": src.name}`), ו-`S3Backend.put_bytes` העביר אותו כמו-שהוא ל-`put_object`. botocore אוכף ASCII-only על S3 metadata → ParamValidationError → 500. שם עברי כמו "יומון 5167 - 11.6.26.pdf" שבר כל upload. נחשף ב-cutover ל-s3-only (2026-06-11): קליטת היומונים (וגם כל מסמך/פסיקה עם שם עברי) הפסיקה לעבוד; היומון האחרון שנקלט (5165, 9.6) היה לפני ה-cutover. התיקון (נרמול-במקור, G1; בשכבת-האחסון היחידה, INV-STG2): - `_ascii_metadata` מקודד ערכי-metadata לא-ASCII ב-percent-encoding (lossless, שחזור עם urllib.parse.unquote); ASCII רגיל עובר ללא שינוי (קריאוּת). - `S3Backend.put_bytes` מחיל אותו על כל ערכי ה-Metadata. בדיקות: test_ascii_metadata_encodes_hebrew (helper) + test_s3_put_bytes_sends_ascii_metadata (משחזר את מסלול-הכשל מול fake put_object). 16 עוברות בקובץ. Invariants: מקיים G1 (נרמול-במקור, לא תיקון-בקריאה), INV-STG2 (שם-קובץ עברי כ-metadata ולא ככ-key), G2 (אין מסלול-אחסון מקביל — תיקון ה-choke-point היחיד). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>