fix(storage): ASCII-encode S3 object metadata — s3-only upload 500 על שמות-קובץ עבריים (INV-STG2) #237

Merged
chaim merged 1 commits from worktree-s3-meta-ascii into main 2026-06-12 11:31:09 +00:00
Owner

הבעיה

כל העלאת קובץ עם שם עברי נכשלה ב-500 תחת backend s3-only. התגלה דרך קליטת היומונים: היומון האחרון שנקלט הוא 5165 (9.6) — לפני ה-cutover ל-s3-only (2026-06-11); מאז 5166/5167 לא נכנסו.

Traceback (ייצור):

botocore.exceptions.ParamValidationError: Non ascii characters found in S3 metadata
for key "filename", value: "digest_..._יומון 5167 - 11.6.26.pdf". S3 metadata can only contain ASCII.

השורש

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 בלבד.
  • 16 עוברות ב-test_storage_staging.py + test_unified_ingest.py.

Invariants

  • G1 — נרמול-במקור (לא תיקון-בקריאה).
  • INV-STG2 — שם-קובץ עברי כ-metadata, לא ככ-key.
  • G2 — אין מסלול-אחסון מקביל.

🤖 Generated with Claude Code

## הבעיה כל **העלאת קובץ עם שם עברי** נכשלה ב-**500** תחת backend `s3-only`. התגלה דרך קליטת היומונים: היומון האחרון שנקלט הוא 5165 (9.6) — **לפני** ה-cutover ל-s3-only (2026-06-11); מאז 5166/5167 לא נכנסו. **Traceback (ייצור):** ``` botocore.exceptions.ParamValidationError: Non ascii characters found in S3 metadata for key "filename", value: "digest_..._יומון 5167 - 11.6.26.pdf". S3 metadata can only contain ASCII. ``` ## השורש `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 בלבד. - 16 עוברות ב-`test_storage_staging.py` + `test_unified_ingest.py`. ## Invariants - **G1** — נרמול-במקור (לא תיקון-בקריאה). - **INV-STG2** — שם-קובץ עברי כ-metadata, לא ככ-key. - **G2** — אין מסלול-אחסון מקביל. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chaim added 1 commit 2026-06-12 11:30:56 +00:00
fix(storage): ASCII-encode S3 object metadata — s3-only upload 500 on Hebrew filenames (INV-STG2)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 7s
15e4af595a
תיקון: כל העלאת קובץ עם שם עברי נכשלה ב-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>
chaim merged commit 6926d21b15 into main 2026-06-12 11:31:09 +00:00
chaim deleted branch worktree-s3-meta-ascii 2026-06-12 11:31:10 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ezer-mishpati/legal-ai#237