From 50649baeedfcb8c9e24be781cf56b6ca07cd0018 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sun, 10 May 2026 18:30:49 +0000 Subject: [PATCH] fix: prevent JSONB double-encoding on methodology save MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass req.value directly to asyncpg instead of json.dumps(req.value). When a Python string was passed with ::jsonb, asyncpg encoded it as a JSONB string (not an array), causing the frontend spread operator to split it into individual characters — one textarea per character. Also fix typo in DISCUSSION_RULES default: "אסה" → "מאסה". Co-Authored-By: Claude Sonnet 4.6 --- mcp-server/src/legal_mcp/services/lessons.py | 2 +- web/app.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mcp-server/src/legal_mcp/services/lessons.py b/mcp-server/src/legal_mcp/services/lessons.py index c9e7fe9..e1fc91b 100644 --- a/mcp-server/src/legal_mcp/services/lessons.py +++ b/mcp-server/src/legal_mcp/services/lessons.py @@ -123,7 +123,7 @@ SUMMARY_STRATEGIES = { DISCUSSION_RULES: dict[str, list[str]] = { "universal": [ - "פרק הדיון = אסה רציפה. אין כותרות משנה (H2/H3). מעברים רק עם ביטויי מעבר טקסטואליים.", + "פרק הדיון = מאסה רציפה. אין כותרות משנה (H2/H3). מעברים רק עם ביטויי מעבר טקסטואליים.", "חריג יחיד לכותרות משנה: נושאים נפרדים לחלוטין (למשל: הקלה בגובה + התייחסות לטענות נוספות).", "טווח אורך סעיפים: 20 עד 600+ מילים. סעיף עם ציטוט מקיף = בלוק אחד שלם, לא שבירה לסעיפים קצרים.", ], diff --git a/web/app.py b/web/app.py index 1f07e36..60a521e 100644 --- a/web/app.py +++ b/web/app.py @@ -3095,11 +3095,14 @@ async def api_update_methodology(category: str, key: str, req: MethodologyUpdate raise HTTPException(422, "content_checklists value must be a non-empty string") pool = await db.get_pool() + # Pass req.value directly — asyncpg serializes Python list/dict to JSONB. + # json.dumps() caused double-encoding: string passed to ::jsonb became a JSONB string, + # not a JSONB array, making the frontend spread it as individual chars. await pool.execute( "INSERT INTO appeal_type_rules (id, appeal_type, rule_category, rule_key, rule_value) " "VALUES (gen_random_uuid(), '_global', $1, $2, $3::jsonb) " "ON CONFLICT (appeal_type, rule_category, rule_key) DO UPDATE SET rule_value = $3::jsonb", - category, key, json.dumps(req.value, ensure_ascii=False), + category, key, req.value, ) return {"key": key, "value": req.value, "is_override": True}