Files
legal-ai/docs/spec/X6-ui-api-contract.md
Chaim 37c56ff22a docs(spec): cycle-2 — 8 application-surface domains (X6–X10) + ui-audit + GAP-24..62/FU-9..15
Extends the system spec beyond the core pipeline to the 8 surfaces outside it:
- X6 UI↔API contract + design rules (INV-UI1..6)
- X7 Paperclip client & connection params (INV-INT4..8)
- X8 field-population & extraction provenance (INV-FP1..5)
- X9 MCP tool contract — 71 tools (INV-TOOL1..6)
- X10 deploy/env/secrets (INV-ENV1..5)
- ui-audit.md — page-by-page UI audit (13 pages)
- 02-data-model: derived-entity invariants (INV-DM4..6)
- X4-agents: tool-grant map + INV-AG3
- gap-audit: GAP-24..62 → FU-9..15; cycle-1 (FU-1..8b) marked done
- constitution §7 + README index (X1..X10)

Planning/spec artifacts only — no application code. All engineering invariants
backed by ≥3 sources; every finding carries verified file:line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 16:21:27 +00:00

11 KiB
Raw Permalink Blame History

X6 — חוזה UI↔API וכללי-עיצוב הממשק (UI↔API Contract & Design Rules)

קובץ-תחום זה כפוף ל-חוקת המערכת והוא ה-deep-dive על הממשק (web-ui) וחוזה ה-API בינו לבקאנד — שלא היה מכוסה בספ עד כה. הוא מגדיר: (א) חוזה-הקשר פרונט↔בק (OpenAPI כ-SSoT, מודלי-תשובה, envelope, SSE, טיפול-שגיאות); (ב) כללי-עיצוב הממשק — מקור-אמת יחיד ל-enums/תוויות, helpers משותפים, וחוזה-טופס לכל סוג-מסמך. הממצאים בפועל מתועדים ב-ui-audit.md.

שני סוגי invariant כאן. UI1UI5 הם הנדסיים (חוזה-API/קליינט כללי — ≥3 מקורות + סטטוס). UI6 (חוזה-טופס) הוא פרויקטלי-תפעולי, נגזר מ-X8, ומשרת G9.


1. ארכיטקטורה קיימת

  • web-ui — Next.js 16 + TS + Tailwind v4 + shadcn + TanStack Query. 13 דפים (ראה ui-audit.md).
  • Proxynext.config.ts: /api/*NEXT_PUBLIC_API_ORIGIN (ברירת-מחדל http://127.0.0.1:8000); /openapi.json → schema של ה-FastAPI.
  • לקוחclient.ts: apiRequest<T> + ApiError + makeQueryClient. 18 מודולי-API.
  • טיפוסיםtypes.ts (auto-gen openapi-typescript, 124 operations). npm run api:types.
  • SSEsse.ts: openSSE (progress של העלאות/עיבוד).
  • בקאנדweb/app.py: 143 endpoints, מונוליטי, ~60% ללא Pydantic response model.

2. Invariants של התחום

INV-UI1: ה-OpenAPI schema הוא ה-SSoT לחוזה — טיפוסי-לקוח נגזרים, לא ידניים-סוטים

כלל: חוזה ה-API מוגדר פעם אחת ב-OpenAPI (שמופק מהבקאנד); טיפוסי-ה-frontend נגזרים ממנו (openapi-typescript), ואינם מתוחזקים ידנית במקביל. אין "טיפוס-מראה" מקומי שמשכפל endpoint וסוטה ממנו. מופע של G2 (מקור-אמת יחיד). מקורות: OpenAPI Specification 3.1 (single contract / source of truth; JSON-Schema 2020-12) (https://spec.openapis.org/oas/latest.html) · Pact — consumer-driven contract testing (https://docs.pact.io/) · Speakeasy — Pact vs OpenAPI (provider-driven SSoT) (https://www.speakeasy.com/blog/pact-vs-openapi) | סטטוס: verified אכיפה: npm run api:types ב-CI; איסור טיפוסי-מראה ידניים. כיום אין — ה-frontend מתחזק טיפוסים ידניים. הפרה ידועה: cases.ts:1-9 מתעד מפורשות שה-/api/cases מחזיר unknown ולכן מוחזק טיפוס CaseDetail ידני; PracticeArea מוגדר ב-3 מקומות עם ערכים שונים (ui-audit.md, gap-audit GAP-30/31).

INV-UI2: לכל endpoint נצרך — response model מפורש (חוזה-שלמות API)

כלל: כל endpoint שה-UI צורך נושא response model מפורש (Pydantic), כך ש-OpenAPI מפיק טיפוס אמיתי (לא unknown/object). זהו פאֶט של G4 (שלמות-חוזה לפני צריכה). מקורות: OpenAPI 3.1 (schema objects) · Zalando RESTful API Guidelines (explicit schemas) (https://opensource.zalando.com/restful-api-guidelines/) · FastAPI Response Model docs (https://fastapi.tiangolo.com/tutorial/response-model/) | סטטוס: verified אכיפה: linter/CI שמסמן endpoint נצרך ללא response_model. כיום אין — ~60% מהendpoints ללא מודל. הפרה ידועה: רוב ה-endpoints ב-app.py מחזירים dict חופשי → unknown ב-types.ts (gap-audit GAP-30).

INV-UI3: envelope-תשובה ושגיאה עקבי על-פני ה-API

כלל: כל ה-endpoints חולקים מבנה-תשובה ומבנה-שגיאה אחיד (לא string-לפעמים-JSON-לפעמים). שגיאות לפי תבנית סטנדרטית (Problem Details). מופע של G2. מקורות: RFC 9457 — Problem Details for HTTP APIs (https://www.rfc-editor.org/rfc/rfc9457) · Zalando RESTful API Guidelines (consistent responses) · Microsoft REST API Guidelines (error structure) (https://github.com/microsoft/api-guidelines) | סטטוס: verified אכיפה: envelope משותף ב-app.py + handler-שגיאות גלובלי. כיום אין — מעורב string/JSON/{error}/{detail}. הפרה ידועה: search.py מחזיר "לא נמצאו תוצאות." או JSON; חלק מהכלים {error:...}, חלק raise (gap-audit GAP-32, X9 INV-TOOL1).

INV-UI4: אין בליעת-שגיאה ב-UI

כלל: כל מצב-שגיאה (fetch/mutation) מוצג או מטופל מפורשות — error boundary ו/או טיפול ב-error של useQuery/useMutation. אין כשל שקט שמשאיר את המשתמש בלי משוב. תואם כלל "אין בליעה שקטה" (חוקה §6). מקורות: React docs — Error Boundaries (https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) · TanStack Query — Error handling (https://tanstack.com/query/latest/docs/framework/react/guides/query-functions#handling-and-throwing-errors) · Nielsen Norman Group — Error-Message Guidelines (https://www.nngroup.com/articles/error-message-guidelines/) | סטטוס: verified אכיפה: error boundary ברמת-האפליקציה + רכיב-שגיאה משותף; code-review. כיום חלקי — חלק מהדפים אינם מטפלים ב-error; כרטיסי-שגיאה משוכפלים ולא-עקביים. הפרה ידועה: ui-audit.md — כרטיס-שגיאה משוכפל ×3, fallback של SSE שמסתיר כישלון כ-"completed" (gap-audit GAP-32/33).

INV-UI5: חוזה-SSE/progress עם terminal states מוגדרים

כלל: ערוץ ה-progress (SSE) נושא terminal states מפורשים (completed/failed/timeout). אין הנחת-השלמה שקטה על timeout; אי-התאמות-TTL (frontend↔backend) נמנעות. נקשר ל-freshness (G6). מקורות: WHATWG HTML — Server-Sent Events / EventSource (https://html.spec.whatwg.org/multipage/server-sent-events.html) · MDN — Using server-sent events (https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) · TanStack Query — Important Defaults (staleTime/refetch) (https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults) | סטטוס: verified אכיפה: סכמת-אירוע SSE עם terminal state מפורש; יישור TTL. כיום: fallback של 10ש' מניח completed. הפרה ידועה: documents.ts:226-232 — timeout→{status:"completed"}; TTL 5ש' front מול 300ש' redis (gap-audit GAP-33).

INV-UI6: חוזה-טופס מוצהר לכל סוג-מסמך + שיקוף מקור-המילוי

כלל: לכל סוג-מסמך (מסמך-תיק / פסיקה חיצונית / החלטה פנימית) יש חוזה-טופס מוצהר — אילו שדות, חובה/רשות/אוטו/pending/editable — נגזר מ-X8; וה-UI משקף את מקור-המילוי (מסמן מה חולץ אוטומטית/ע"י-Opus מול מה שהיו"ר הזין), כדי שהיו"ר ידע מה לאמת. מופע של G9 (שקיפות-מקור). invariant פרויקטלי-תפעולי. מקור-סמכות: X8-field-provenance.md (טבלת-ה-provenance); feedback היו"ר. אכיפה: רכיב-טופס נגזר-X8 + אינדיקציית "מולא-ע"י-Opus"/"ממתין"/searchable. כיום אין — שדות-Opus מוצגים כשדות-עריכה רגילים ללא סימון. הפרה ידועה: precedents/[id]/page.tsxsummary/headnote/key_quote ללא חיווי-מקור; אין חיווי searchable (gap-audit GAP-36).


3. כללי-עיצוב (Design Rules) — נגזרים מה-invariants

  • SSoT ל-enums/תוויות/tones: כל enum (CaseStatus, PracticeArea, AppealSubtype, DocType, outcome) + תוויותיו + צבעיו מוגדרים פעם אחת ונצרכים מיבוא — לא משוכפלים בין דפים/רכיבים (מופע UI1/G2).
  • helpers משותפים: פירמוט-תאריך, builder ל-FormData (העלאות), רכיב-שגיאה, query-config (intervals) — משותפים, לא מועתקים.
  • חוזי-טופס: ראה INV-UI6 (X8).

הממצאים הקונקרטיים (כפילויות, הגדרות-שגויות, redundancy) ב-ui-audit.md; התיקון — FU-10.


4. הפניות-אחיות