This commit is contained in:
2026-07-12 19:21:35 +02:00
parent f2d944b117
commit 41cb412cb0
49 changed files with 3170 additions and 52 deletions
+18
View File
@@ -0,0 +1,18 @@
# Architecture
## Stos
- CodeIgniter 4.7.3, PHP 8.2, MySQL, Bootstrap 5.
- Jedno konto aplikacji pobierane z `.env` (`user_email`, `user_password`).
## Uwierzytelnianie
- `Auth::login` tworzy zwykłą sesję; opcjonalnie wystawia trwały token.
- `AuthFilter::before` chroni trasy i może odtworzyć sesję z cookie `remember_token`.
- `Auth::logout` usuwa sesję oraz token tylko bieżącego urządzenia.
- `RememberTokenModel` jest jednym źródłem logiki tokenów i czasu życia 30 dni.
## Granice
- Brak tabeli użytkowników i systemu wielu kont.
- Moduły finansów, inwestycji i paragonów korzystają wyłącznie z wyniku filtra `auth`.
+14
View File
@@ -0,0 +1,14 @@
# Database Schema
## `remember_tokens`
| Kolumna | Typ | Uwagi |
|---------|-----|-------|
| `id` | INT UNSIGNED | Primary key, auto increment |
| `selector` | VARCHAR(32) | Unique, jawna część identyfikacyjna tokenu |
| `validator_hash` | CHAR(64) | SHA-256 walidatora; surowy walidator nie jest zapisywany |
| `expires_at` | DATETIME | Indeksowany termin ważności |
| `created_at` | DATETIME NULL | Timestamp CodeIgniter |
| `updated_at` | DATETIME NULL | Timestamp CodeIgniter |
Tabela przechowuje wiele aktywnych rekordów, dzięki czemu urządzenia pozostają zalogowane niezależnie.
+23
View File
@@ -1,5 +1,19 @@
# Impact Map
## Post-apply 20260712-1647
- Mechanizm wdrożony w kontrolerze logowania, filtrze, widoku, modelu i migracji.
- Zdalna tabela `remember_tokens` istnieje.
- Trasy i globalna konfiguracja sesji pozostały bez zmian.
- Do ręcznego potwierdzenia pozostaje UAT dwóch profili przeglądarki.
## Plan 20260712-1647 — zapamiętywanie logowania (plan scan)
- Logowanie: `app/Controllers/Auth.php`, `app/Views/auth/login.php`.
- Odtworzenie sesji: `app/Filters/AuthFilter.php`; trasy pozostają bez zmian.
- Dane: nowa tabela tokenów i model; wiele rekordów umożliwia wiele urządzeń.
- Konfiguracja: użyć istniejących ustawień HttpOnly/SameSite; nie wydłużać `Session::$expiration`.
- Test/UAT: dwa profile, wylogowanie jednego urządzenia, nieważny i wygasły token.
- Wdrożenie: migrację zastosować ręcznie na hostido przed kodem.
**Aktualizacja:** 2026-07-06 (post-apply Plan 2 — degraded)
## Kontekst
@@ -16,6 +30,15 @@ CodeIgniter 4.7.3 + MySQL (`.env`). Radar degraded — brak indeksu codebase-mem
- Wyceny: `ValuationModel`, `Valuations.php`, widoki `valuations/`, tabela `inv_valuations` (FK RESTRICT → inv_instruments).
- Pulpit inwestycji: `Investments::index``investments/index.php`, trasa `/investments`.
### Import paragonów (Plan 3)
- Paragony: `ReceiptModel` (`withCounts`), `ReceiptItemModel` (`forReceipt`, `name` surowa + `display_name` ładna), `Receipts.php`, widoki `receipts/`, tabele `receipts` + `receipt_items` (FK CASCADE → receipts, SET NULL → categories).
- Uczone dopasowania: `ReceiptCategoryMapModel` (`normalize`, `suggest`, `remember`), tabela `receipt_category_map` (item_name UNIQUE → category_id). Klucz = surowa nazwa z paragonu. Tylko podpowiedź, brak auto-zapisu.
- Parser AI: `app/Libraries/ReceiptParser.php` — OpenAI **Responses API** (`/v1/responses`) przez `\Config\Services::curlrequest()`; jpg/png (`input_image`), pdf (`input_file` — OpenAI renderuje strony), json (`input_text`). Model z `env('openai.model')` domyślnie **o4-mini** (rozumujący; mini/gpt-4o za słabe na gęsty druk). Zwraca `name`+`display`. Klucz `OPEN_AI_API`.
- Upload bez `fileinfo` (hostido je wyłącza): walidacja rozszerzeń ręczna, własna nazwa pliku, MIME z rozszerzenia. Cały przepływ w try/catch → błąd zapisany w `receipts.error_msg`, nie 500.
- Zapis: `confirm()` grupuje pozycje po kategorii → 1 operacja `expense`/kategoria (suma edytowalnych kwot) przez `OperationModel`, z `operations.receipt_id` (FK SET NULL). Uczenie na surowej nazwie, opis z ładnych. Transakcja DB.
- Kategorie: `CategoryModel::tree()` daje `path_label` („Nadrzędna → Podrzędna") — używane w przeglądzie paragonu; `indent_label` nadal w operacjach.
- Pliki skanów: `writable/uploads/receipts/`, serwowane przez `Receipts::file` pod filtrem `auth`.
### Pulpit globalny
- `Dashboard::index``app/Views/dashboard/index.php`, trasy `/` i `/dashboard`. Majątek = saldo bieżące (`OperationModel::totals`) + wartość inwestycji (`InstrumentModel::withStats`).
+22
View File
@@ -1,5 +1,18 @@
# Quality Risks
## 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
@@ -15,5 +28,14 @@
- 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.
@@ -0,0 +1,15 @@
Tryb: plan
Data: 2026-07-12T16:47:19+02:00
Projekt: C-visual-studio-code-finansePRO
Status indeksu: indexed, moderate, 789 nodes, 1015 edges
Zapytania: logowanie, sesja, filtr auth, logout, remember.
Najważniejsze pliki:
- `app/Controllers/Auth.php`
- `app/Filters/AuthFilter.php`
- `app/Views/auth/login.php`
- `app/Config/Session.php`
- `app/Config/Cookie.php`
Wniosek: osobne trwałe tokeny per urządzenie odtwarzające istniejącą sesję; bez wydłużania globalnej sesji.
@@ -0,0 +1,12 @@
Tryb: post-apply
Data: 2026-07-12T17:31:28+02:00
Projekt: C-visual-studio-code-finansePRO
- Indeks moderate odświeżony: 789 nodes, 1015 edges.
- `search_graph` nie zwrócił nowych symboli `RememberTokenModel`.
- `search_code` zakończył się błędem tworzenia pliku tymczasowego.
- Fallback: bezpośredni lint 6 zmienionych plików — wszystkie poprawne.
- Zdalna tabela `remember_tokens`: 6 kolumn, 3 indeksy.
- PHPUnit: niedostępny, brak `vendor/bin/phpunit`.
Status: degraded — kod i schemat sprawdzone, brak automatycznego testu runtime.
+9 -14
View File
@@ -1,16 +1,11 @@
# Tooling Status
**Timestamp:** 2026-07-06T13:10
**Scan mode:** post-apply (plan 20260706-1248-fundament-wydatki-przychody)
## Narzędzia
- `codebase-memory-mcp`: enabled, indeks nieodświeżony (ponytail: pełna indeksacja odłożona do `$paul-map-codebase`; kod świeżo dodany, weryfikacja przeszła runtime'owo).
- `jscpd`: disabled by policy
- `ast-grep`: disabled by policy
## Weryfikacja runtime (zamiast skanu statycznego)
- `php spark migrate` / `db:seed` — OK (zdalna baza hostido).
- `php spark serve` + curl: login/logout, CRUD kategorii i operacji, filtry, sumy, 3 wykresy dashboardu, blokada usunięcia używanej kategorii, wymuszenie typu operacji przez kategorię — wszystko potwierdzone.
## Następna akcja
`$paul-map-codebase` (pełny indeks codebase-memory-mcp) po ustabilizowaniu modułu, lub przed Planem 2 (inwestycje).
- Timestamp: 2026-07-12T17:31:28+02:00
- Scan mode: post-apply
- codebase-memory-mcp: degraded; indeks odświeżony, ale nowe symbole nie zostały zwrócone, a `search_code` zgłosił błąd pliku tymczasowego
- fallback: `php -l` dla 6 plików — pass
- PHPUnit: unavailable (`vendor/bin/phpunit` missing)
- jscpd: disabled by policy
- ast-grep: disabled by policy
- Raw output: `.paul/codebase/radar/codebase-memory-post-apply.txt`
- Next action: opcjonalny UAT dwóch profili przeglądarki.