61 Commits
Author SHA1 Message Date
mstfyldz 95478c09e8 fix: PK signature offset searching for UDF files in backend 2026-08-14 13:23:48 +03:00
mstfyldz 6dd34fe703 feat: enhance UDF file extraction pipeline to unzip container and handle content.xml or embedded PDF files 2026-08-14 13:13:37 +03:00
mstfyldz 644d5f4052 fix: strictly penalize pure mahkumiyet onamasi decisions on beraat search and extract beraat passages 2026-08-14 12:15:46 +03:00
mstfyldz 8ae98a9500 feat: smart intent-based precedent re-ranking for beraat/bozma/tazminat outcomes 2026-08-14 12:12:19 +03:00
mstfyldz 58ae3655b6 fix: insert assistant digital-intern responses into chat_messages table 2026-08-14 12:06:19 +03:00
mstfyldz ee83ea648d feat: complete targetPersona opponent attorney cross examination simulator prompts 2026-08-14 11:56:28 +03:00
mstfyldz d2ea58942c fix: add stream routes and guarantee finalJson answer property 2026-08-14 11:53:04 +03:00
mstfyldz c4947422dc feat: add digital-intern live-qa endpoints for pinpoint hearing assistance 2026-08-14 11:48:49 +03:00
mstfyldz d3f91d4da6 fix: support both clientName and client_name in analyzeStrategy and analyzeMediation 2026-08-14 11:42:59 +03:00
mstfyldz d7a99a9db0 fix: add role-based strategic goals and winSteps to runStrategyAnalysis 2026-08-14 11:39:37 +03:00
mstfyldz 11c26d6029 fix: re-orient STATEMENT_ANALYSIS_SYSTEM_PROMPT to focus on stage and cross-witness contradictions 2026-08-14 11:34:49 +03:00
mstfyldz 9f1ffedb88 fix: enforce K.H. Kamu Hukuku exclusion rule in STATEMENT_ANALYSIS_SYSTEM_PROMPT and filter output 2026-08-14 11:31:51 +03:00
mstfyldz 7da869224f fix: add alias routes for case analysis endpoints 2026-08-14 01:16:05 +03:00
mstfyldz fab80e05a0 feat: upgrade AI prompts to v2 specification with grounding and injection shield 2026-08-14 00:52:41 +03:00
mstfyldz f1457b02ca fix(chat): allow AI to finish and save responses even if client disconnects 2026-08-12 13:02:40 +03:00
mstfyldz d10ea1b0fd fix(chat): add SSE padding to bypass proxy buffering 2026-08-12 12:48:04 +03:00
mstfyldz 7b6b27909c chore: remove test files 2026-08-12 11:22:27 +03:00
mstfyldz e25bab8146 fix: Supabase storage upload hatasını çözmek için dosya adlarındaki Türkçe karakterler ve boşluklar temizlendi 2026-08-12 11:22:05 +03:00
mstfyldz 571e1f63d1 feat: Arabuluculuk & Müzakere Asistanı analiz endpoint'leri eklendi 2026-08-12 10:58:44 +03:00
mstfyldz 6916a7d9ba perf: prevent duplicate CDN uploads by checking Supabase first 2026-08-12 10:41:08 +03:00
mstfyldz b86aa54378 feat: migrate local file cache to BunnyCDN storage API 2026-08-12 10:35:44 +03:00
mstfyldz 437f973d6f feat: Add precedent caching mechanism via txt and supabase 2026-08-12 02:17:57 +03:00
mstfyldz f7daa3d4c7 feat(chat): add digital intern (live search) mode 2026-08-11 23:49:33 +03:00
mstfyldz 05341e1171 feat(calendar): extract dates into case_events 2026-08-11 23:19:53 +03:00
mstfyldz f87b595ccd feat(simulator): add opponent/judge simulator feature endpoints 2026-08-11 22:54:42 +03:00
mstfyldz 69edf3aa61 feat(drafting): add fast-path generateAngarya endpoint for routine petitions 2026-08-11 21:45:17 +03:00
mstfyldz 6299a269a1 feat: dava stratejisi olusturucu - analyzeStrategy endpoint 2026-08-11 17:02:18 +03:00
mstfyldz 5c8c676d45 feat: add deficiency analysis route 2026-08-11 16:30:22 +03:00
mstfyldz 05fcc00de9 revision 2026-08-11 16:27:02 +03:00
mstfyldz 6bd6da3776 fix: prevent duplicate document rows on OCR retry
registerLocalDocument always did a plain insert, so retrying a
document whose first OCR attempt failed created a new duplicate
row each time instead of updating the existing one. Now looks up
an existing (case_id, filename) match and updates it in place.
2026-08-11 11:09:05 +03:00
mstfyldz 8065df4ff0 fix: raise Express JSON body limit to 25mb for OCR image payloads
Default 100kb limit rejected base64-encoded scanned page images
with 413 Payload Too Large, breaking /documents/ocr-image for any
realistic scan.
2026-08-11 10:50:58 +03:00
mstfyldz a6c1eabaad fix: default OCR prompt to markdown output
Kullanıcı OCR sonuçlarının markdown formatında gelmesini istedi — test
edildi (gerçek çok sayfalı taranmış evrakta doğrulandı), tablo/başlık
yapısını doğru yakalıyor.
2026-08-11 10:28:19 +03:00
mstfyldz 97ec7cd7f8 feat: DeepSeek-OCR endpoint + GPU request queue for AI calls
Mizan ve DeepSeek-OCR aynı self-hosted GPU'yu paylaşıyor; backend'de hiçbir
eşzamanlılık sınırı yoktu, yoğun anlarda istekler Ollama kuyruğunda 90sn'yi
aşıp sessizce "başarısız" görünüyordu. aiQueue.ts, GPU'ya giden istek sayısını
sınırlayıp fazlasını backend'de bekletiyor.

Yeni POST /documents/ocr-image, tek bir görseli DeepSeek-OCR ile metne
çeviriyor (Electron tarafındaki çok sayfalı TIFF/taranmış PDF işleme
adımının kullanacağı uç, ayrı bir PR'da bağlanacak).
2026-08-11 10:12:33 +03:00
mstfyldz 7915571130 fix: remove hardcoded old Supabase domain and leaked service_role key from scratch.js
Supabase migrated from the sslip.io address to https://supa.ayris.tech;
scratch.js now reads SUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY from env instead
of hardcoding the stale host and a plaintext secret.
2026-08-10 13:49:10 +03:00
mstfyldzandClaude Sonnet 5 ce6fa9deae feat: Google Drive restore endpoints (Faz 3)
GET /api/google-drive/backup-files: kullanıcının senkronize
edilmiş dosyalarının listesi (PRD §28 "N dosya bulundu"). GET
/download: bir dosyayı Drive'dan proxy'leyip ham baytları döner —
istenen drive_file_id'nin gerçekten bu kullanıcıya ait olduğu
önce doğrulanıyor (PRD §39, başka kullanıcının backup'ı sızmasın).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 04:24:56 +03:00
mstfyldzandClaude Sonnet 5 313d5b72ef feat: Google Drive backup upload endpoint (Faz 2 — backend half)
POST /api/google-drive/upload: Electron'un backupQueue'sunun
gönderdiği tek dosyayı alıp Google'ın resumable upload session'ıyla
Drive'a yazıyor (mevcutsa aynı drive_file_id'yi PATCH ederek yeni
sürüm olarak, PRD Test 4). Dava başlığı = Drive'daki alt klasör adı
(lokal yapı korunuyor). GET /backup-status: Ayarlar > Yedekleme
paneli için toplam dosya/boyut/son senkron özeti.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 04:14:27 +03:00
mstfyldzandClaude Sonnet 5 328aef91bd feat: Google Drive backup OAuth (Faz 1 — backend)
PRD "AyrisLegal Google Drive Backup & Recovery" kapsamında sadece
backend altyapısı: OAuth connect/callback/status/disconnect/refresh
uç noktaları, AES-256-GCM token şifreleme (tokenCrypto.ts), tek
kullanımlık CSRF state (oauthState.ts), drive.file scope ile
AyrisLegal/Davalar klasör oluşturma (googleDriveClient.ts). Electron
tarafı (dosya tarama/kuyruk/UI) ayrı bir aşamada.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 03:51:02 +03:00
mstfyldzandClaude Sonnet 5 9618ff4513 feat: file attachments in chat + document-select for case chat
- Yeni POST /api/documents/extract-text: dosyayı hiçbir yere
  kaydetmeden sadece metnini çıkarıp döner (chat ataç özelliği için)
- chatMessage ve sendThreadMessage artık body'de attachments
  ({filename,text}[]) kabul ediyor; AI bağlamına ekleniyor, kayıtlı
  mesaja da "[Ek dosya(lar): ...]" notu düşülüyor
- chatMessage ayrıca document_ids kabul ediyor — dosya sohbetinde
  kullanıcının bu mesajda özellikle işaret ettiği mevcut belge(ler)
  AI'ye vurgulanıyor

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 01:03:13 +03:00
mstfyldzandClaude Sonnet 5 029402a620 fix: raise num_predict for interactive chat to stop mid-sentence cutoffs
800 token sınırı çok düşüktü — çok bölümlü hukuki cevaplar (kira feshi,
tazminat hesabı gibi) bu sınıra çarpıp cümlenin ortasında kesiliyordu.
Varsayılan ve chatMessage/sendThreadMessage'ın kullandığı num_predict
2048'e çıkarıldı. Ayrıca Ollama done_reason:"length" döndürdüğünde
(yanıt sınıra çarpıp kesildiğinde) sunucu loglarına uyarı yazılıyor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 00:35:00 +03:00
mstfyldzandClaude Sonnet 5 ea5211e05d revert: always send full document text in case chat context
Özet-önce yaklaşımı, kullanıcı uzun bir mesaj/belge verdiğinde sohbet
ekranında soruna yol açtığı için geri alındı — chatMessage yine her
zaman belgelerin tam extracted_text'ini sistem promptuna gömüyor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 00:26:22 +03:00
mstfyldzandClaude Sonnet 5 bcc78ce304 perf: switch all AI calls to native Ollama endpoint, add streaming + keep_alive
Tüm AI çağrıları artık ortak lib/aiClient.ts üzerinden gidiyor:
- /v1/chat/completions yerine native /api/chat (think:false burada
  güvenilir çalışıyor)
- keep_alive:30m ile model her istekte bellekten atılıp soğuk
  başlamıyor
- num_predict ile öngörülemez uzunlukta üretime üst sınır
- İnteraktif sohbet uç noktaları (chatMessage, sendThreadMessage)
  artık SSE ile token token akıtıyor
- Dosya sohbetinde varsayılan olarak belgenin tam metni değil analiz
  özeti gönderiliyor; tam metin sadece kullanıcı açıkça isterse
  eklenir

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 00:21:49 +03:00
mstfyldzandClaude Sonnet 5 0318f2ac77 feat: persist general chat as chat_threads, decoupled from cases
Sohbet/Asistan sayfasındaki genel sohbetler artık kalıcı: yeni
chat_threads/thread_messages tabloları (cases ile ilişkisiz) ile
sendThreadMessage endpoint'i eklendi. Eski caseId==='general'
(kalıcı olmayan) dalı kaldırıldı, AI çağrısı ortak callAiChat
yardımcısına taşındı.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 00:07:44 +03:00
mstfyldzandClaude Sonnet 5 982f908bf9 feat: persist generated petition drafts
generateDraft now inserts into a new drafts table (case_id, content,
petition_type, template_id) so drafts survive navigating away, and
show up in both the "Dilekçelerim" list and the originating case's own
"Dilekçeler" section. Read/update/delete go straight through Supabase
from the frontend (same pattern as events/clients).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 22:15:59 +03:00
mstfyldzandClaude Sonnet 5 2c28cdbf9e fix: forbid markdown formatting in AI-generated petition drafts
The draft prompt didn't say anything about output format, so the model
would sometimes emit **bold**/## headers like it does elsewhere -
wrong for a document meant to go straight into a court filing. Now
explicitly instructed to use plain text with conventional Turkish
petition section labels (AÇIKLAMALAR:, SONUÇ VE İSTEM: etc.) instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 22:05:37 +03:00
mstfyldzandClaude Sonnet 5 79b2bad396 fix: never auto-rename real case files from chat's first-message title
chatMessage() was auto-generating and overwriting cases.title from the
first chat message for ANY case_id, including real UYAP-imported dava
dosyaları (kind='case') — not just the chat-only "Yeni Sohbet" threads
(kind='chat') this was built for. Asking a real case a single question
in Sohbet silently destroyed its court-derived title. Now gated on
kind === 'chat'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 20:25:35 +03:00
mstfyldzandClaude Sonnet 5 fa01432ffe feat: use firm's own templates as style guide for AI-drafted petitions
Belge Şablonları uploads now also get extracted_text (same OCR/office
pipeline as documents), and a new POST /api/drafting/generate builds
a real AI draft from the case's actual data (title, UYAP parties,
latest Dosya Özeti) — if the lawyer picks one of their own templates,
its extracted text is passed as a style/format reference only (the
prompt explicitly forbids copying the template's old case facts).
Dilekçe Hazırlama no longer fakes a draft with setTimeout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 20:20:47 +03:00
mstfyldzandClaude Sonnet 5 50f6cbb1b2 feat: narrative "Dosya Özeti" report instead of field-by-field JSON
summarizeCase now produces a full Markdown narrative report (Olayın
Özeti, Yargılama Süreci ve Kararlar, Taraf İddia/Savunmaları, Önemli
Bulgular ve Belgeler, Sonuç) instead of short structured fields - the
iddianame pre-analysis (when found) still runs first and is fed in as
context. The raw AI text is stored as {ozet: string} rather than
JSON-parsed, since asking the model to escape a multi-paragraph report
inside JSON was fragile.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 20:09:31 +03:00
mstfyldzandClaude Sonnet 5 c939dcf564 feat: iddianame-first case summary + remove hardcoded AI endpoint
- summarizeCase: if an iddianame is among the case's documents, run a
  narrow first-pass analysis on it alone (isnatEdilenSuc, iddiaOzeti,
  onemliTarihler), then feed that as context into the general
  case-wide evaluation instead of treating every document equally.
- ANALYSIS_SYSTEM_PROMPT no longer asks the AI to guess "taraflar" -
  that now comes from real UYAP data (cases.parties) instead.
- Removed the hardcoded RunPod proxy URL fallback from every call
  site (document/chat/precedent controllers + lib/openai.ts) - it was
  a real infra endpoint checked into source. New lib/aiConfig.ts
  throws if RUNPOD_API_BASE_URL isn't set rather than silently
  falling back to it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 20:00:06 +03:00
mstfyldzandClaude Sonnet 5 af5a03db92 feat: add template upload/download/delete endpoints
Belge Şablonları now stores real files: POST /api/templates/upload
(multer -> Supabase Storage under templates/<user>/, then a templates
row), GET /api/templates/:id/download-url (short-lived signed URL),
and DELETE /api/templates/:id. Mounted at /api/templates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 19:50:46 +03:00
mstfyldzandClaude Sonnet 5 99d4d770d5 feat: add POST /api/cases/parties to store UYAP taraf bilgileri
The UYAP extension now captures the davaci/davali/sanik + vekil data
from the "Taraf Bilgileri" tab and sends it once per case. This
endpoint finds/creates the matching case by title (same lookup used
by registerLocalDocument, now shared via lib/caseLookup.ts) and stores
it in a new cases.parties column - a much more reliable source for
the case detail screen's "Taraflar" info than the AI's own guess from
OCR'd document text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 19:29:53 +03:00
mstfyldzandClaude Sonnet 5 9f5c5c1e45 feat: add case-level AI summary endpoint
POST /api/cases/:caseId/summarize combines extracted text from all of
a case's documents and runs the existing AI analysis prompt, storing
the result as a case-level analysis (document_id: null). Powers the
"Özet Hazırla" button on the case detail screen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 16:14:41 +03:00
mstfyldzandClaude Sonnet 5 5ddf6ce0cf feat: distinguish chat-only cases from real case files via kind column
New chat threads created from the Sohbet screen were creating rows in
the same cases table that Dava Dosyaları lists, so every new chat
showed up there too. createCase now accepts an optional kind
('case'|'chat', default 'case') so chat-only threads can be excluded.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 12:09:32 +03:00
mstfyldz 67b0398b8c feat: add POST /api/documents/register-local for extension import
Accepts pre-extracted text (no raw file) from the AyrisLegal Electron
app's local OCR pipeline, matches/creates a case by title, and runs
the existing AI analysis flow. Also fixes a bug in uploadDocument:
officeparser@7.x's parseOffice() now returns a result object with
.toText() instead of a plain string, which was breaking PDF/DOCX
manual uploads.
2026-08-09 11:26:36 +03:00
mstfyldz d213d68e0f feat: add POST /api/precedent-analysis for research "Analiz modu"
Takes the user's described situation plus the top search results and
asks the AI model for a short legal assessment. Auth-protected since
it's a paid AI call.
2026-08-09 10:47:59 +03:00
mstfyldz 0e40aaef96 feat: add case creation endpoint and auto-title from first message
POST /api/cases lets the frontend actually create a new dava dosyası
(no working "Yeni Dosya" flow existed before). chatMessage now
generates a short title from a case's first message (like Claude/
ChatGPT auto-titling) and renames the case, returned as `newTitle`.
2026-08-09 10:34:55 +03:00
mstfyldz 7b354d4f96 feat: add DELETE /api/cases/:caseId to fully delete a case
Chat panel's trash icon should remove the whole case (not just clear
its chat history) — documents/analyses/chat_messages cascade-delete
via the existing ON DELETE CASCADE foreign keys.
2026-08-09 10:26:36 +03:00
mstfyldz 0831ebb25b feat: add DELETE /api/chat/:caseId to clear a case's chat history
Frontend's chat history trash icon was calling this endpoint but it
didn't exist yet, causing a JSON-parse error on the default 404 page.

Also renames the LegalOS health-check message to AyrisLegal.
2026-08-09 10:09:15 +03:00
mstfyldz b030bdaa60 fix: allow case-less ("general") chat without ownership check
requireAuth treated every chat caseId as a real cases row and rejected
"general" (the no-file chat sentinel) with 403. general chat now skips
the ownership check and is answered without touching chat_messages,
since that table's case_id is a NOT NULL FK to cases.
2026-08-09 01:52:53 +03:00
mstfyldz afbfb413ce fix: set trust proxy for rate limiter 2026-08-08 17:48:45 +03:00
mstfyldz 633f66b09b Fix TypeScript error for officeparser 2026-08-08 17:22:39 +03:00
mstfyldz df70520ede Initial commit 2026-08-08 17:19:28 +03:00