61 lines
5.0 KiB
Markdown
61 lines
5.0 KiB
Markdown
# Quality Risks
|
||
|
||
## Post-apply 20260721-2324 — ceny z JSON w groszach
|
||
- **Obsłużone:** eParagon trzyma kwoty w groszach (int); prompt instruuje model, by dzielił przez 100 dla wejścia JSON. `php -l` czysty.
|
||
- **Determinizm:** reguła „/100" jest deterministyczna dla modelu rozumującego; ostateczne potwierdzenie = UAT realnego importu (niedeterminizm LLM znany z Plan 3).
|
||
- **Bez regresji:** reguła warunkowa tylko dla JSON; ścieżka obraz/PDF bez zmian.
|
||
- **Odroczone (YAGNI):** natywny parser eParagon w PHP (0 tokenów, 100% determinizm, ale traci `display`/kategorie z AI) — podnieść, jeśli reguła promptu okaże się zawodna.
|
||
|
||
## Post-apply 20260713-2111
|
||
- **Obsłużone:** jeden istniejący upload, natywne `capture="environment"`, brak nowej zależności i zmian backendu.
|
||
- **Obsłużone po UAT:** mobilny overflow formularza przeglądu — tabela zmienia się w karty poniżej `md`.
|
||
- **Potwierdzone:** nazwy pól, `accept`, `required`, limit 10 MB i skrypt grupowania pozostały spójne.
|
||
- **Zaakceptowane:** zachowanie selektora aparatu zależy od przeglądarki; działa na docelowym telefonie.
|
||
|
||
## Plan 20260713-2111 — skanowanie paragonu kamerą telefonu
|
||
- **Jedno źródło uploadu:** użyć istniejącego pola `receipt` i `Receipts::create`; bez drugiego endpointu, kontrolera lub parsera.
|
||
- **Natywna funkcja platformy:** `capture="environment"`; bez WebRTC, JavaScriptu i nowej zależności.
|
||
- **Zgodność urządzeń:** `capture` jest wskazówką dla przeglądarki; wymagany manualny UAT na docelowym telefonie.
|
||
- **Regresja formatów:** zachować istniejący `accept` dla JPG/JPEG/PNG/PDF/JSON i sprawdzić wybór pliku obok aparatu.
|
||
- **Odroczone:** podgląd na żywo, kadrowanie, kompresja i wiele zdjęć — brak wymagania (YAGNI).
|
||
|
||
## Post-apply 20260712-1647
|
||
- **Obsłużone:** osobne tokeny urządzeń, hash walidatora, `hash_equals`, selektywne wylogowanie.
|
||
- **Obsłużone operacyjnie:** tabela utworzona na zdalnej bazie po wykryciu błędu braku migracji.
|
||
- **Odroczone:** PHPUnit i UAT dwóch profili; brak lokalnego `vendor/` i potwierdzenia użytkownika.
|
||
|
||
## Plan 20260712-1647 — zapamiętywanie logowania
|
||
- **Sekret tokenu:** w bazie wyłącznie hash walidatora; porównanie przez `hash_equals`.
|
||
- **Wiele urządzeń:** nowe logowanie dopisuje token, nie zastępuje aktywnych tokenów.
|
||
- **Wylogowanie:** unieważnia tylko token bieżącego cookie; sesja i cookie są usuwane.
|
||
- **Cookie:** 30 dni, HttpOnly, SameSite=Lax, Secure na produkcji.
|
||
- **Jedno źródło czasu życia:** stała w modelu tokenów.
|
||
- **YAGNI:** bez panelu urządzeń, harmonogramu i globalnego wylogowania.
|
||
|
||
**Aktualizacja:** 2026-07-06 (post-apply Plan 2 — degraded)
|
||
|
||
## Zaakceptowane świadomie
|
||
- **Kopiowanie wzorców zapytań** z `OperationModel` do `InvOperationModel`/`ValuationModel` (filtered/join). Osobna domena (brak type income/expense, dochodzą wyceny) — nie konsolidować w bazowy model, kod krótki.
|
||
- **Format kwoty** `number_format(...,2,',',' ').' zł'` powtórzony w widokach jako lokalna funkcja `$fmt`. Trywialny, świadomie nie wydzielony do helpera (YAGNI).
|
||
|
||
## Rozwiązane
|
||
- Zarobek netto: jedno źródło prawdy `InstrumentModel::withStats` (`net_invested`, `profit`, `percent`); nie liczony w widokach.
|
||
- Typ operacji inwestycyjnej: ENUM `deposit|withdraw` w DB + walidacja `in_list` w modelu + sanity w kontrolerze.
|
||
- Integralność: FK RESTRICT na `inv_operations`/`inv_valuations`.
|
||
|
||
## Odłożone
|
||
- Pełna indeksacja `codebase-memory-mcp` — `$paul-map-codebase`.
|
||
- jscpd/ast-grep — wyłączone polityką w `config.md` (skan on-demand).
|
||
|
||
## Import paragonów (Plan 3)
|
||
- **Zapis operacji przez `OperationModel`** — bez duplikacji walidacji/logiki; `receipt_id` dodany do `allowedFields`. Jedno źródło prawdy zachowane.
|
||
- **Format kwoty `$fmt`** powtórzony w widokach `receipts/` — świadomie spójny z resztą (YAGNI, jak w Plan 1/2).
|
||
- **Podpowiedzi kategorii**: priorytet `receipt_category_map` (nauczone) > propozycja AI; NIC nie księgowane bez `confirm()` użytkownika (wymóg twardy spełniony).
|
||
- **Klucz OpenAI** czytany z `.env` (`OPEN_AI_API`); nie logowany, nie w repo. Model konfigurowalny (`openai.model`).
|
||
- **OCR paragonów niedeterministyczny**: wiersze rabatu/gęsty druk bywają źle odczytane (waha się między próbami). Świadomie kryte edytowalnymi kwotami/nazwami w przeglądzie (pół-automat). o4-mini najdokładniejszy z testowanych (suma pozycji = total co do grosza), gpt-4o/4.1 gorzej.
|
||
- **Mechanizm PDF**: konieczne **Responses API + input_file** — chat-completions `file_data` NIE dostarcza treści PDF (model halucynuje). Rozstrzygnięte i wdrożone.
|
||
- **Do obserwacji**: `normalize()` robi dokładne dopasowanie surowej nazwy — przy rozbieżnych nazwach tej samej rzeczy podpowiedź się nie pojawi; rozbudować gdy za wąska. Koszt tokenów OpenAI per import (o4-mini). Ewent. zapamiętywanie ładnej nazwy w `receipt_category_map`.
|
||
|
||
## Do obserwacji
|
||
- `portfolioTimeline` liczony w PHP O(daty × operacje) — trywialne przy ręcznych wycenach; przy dużej liczbie wpisów rozważyć agregację SQL.
|