Files
finansePRO/.paul/plans/20260712-1647-zapamietywanie-logowania/PLAN.md
T
2026-07-12 19:21:35 +02:00

169 lines
7.1 KiB
Markdown

---
plan_id: 20260712-1647-zapamietywanie-logowania
title: Zapamiętywanie logowania przez 30 dni
storage: plan-first
legacy_phase: null
created: 2026-07-12T16:47:19+02:00
status: planned
type: execute
autonomous: true
delegation: auto
files_modified:
- app/Database/Migrations/2026-07-12-160001_CreateRememberTokens.php
- app/Models/RememberTokenModel.php
- app/Controllers/Auth.php
- app/Filters/AuthFilter.php
- app/Views/auth/login.php
- tests/unit/RememberTokenModelTest.php
quality_radar: ok
---
<objective>
## Cel
Umożliwić użytkownikowi zaznaczenie opcji „Zapamiętaj mnie” podczas logowania i utrzymać dostęp przez 30 dni niezależnie na wielu komputerach.
## Powód
Obecna sesja wygasa po 2 godzinach i nie przeżywa zamknięcia przeglądarki. Osobny token dla każdego urządzenia zachowuje równoległe logowania bez współdzielenia jednego identyfikatora sesji.
## Wynik
Checkbox w formularzu, trwałe tokeny przechowywane w bazie wyłącznie jako skróty, automatyczne odtworzenie sesji oraz unieważnienie tokenu bieżącego urządzenia przy wylogowaniu.
</objective>
<context>
## Dokumenty projektu
@.paul/PROJECT.md
@.paul/STATE.md
@.paul/config.md
@.paul/codebase/impact_map.md
@.paul/codebase/quality_risks.md
## Pliki źródłowe
@app/Controllers/Auth.php
@app/Filters/AuthFilter.php
@app/Views/auth/login.php
@app/Config/Routes.php
@app/Config/Cookie.php
@app/Config/Session.php
</context>
<clarifications>
- „Wiele komputerów jednocześnie” oznacza osobny aktywny token na każdym urządzeniu; kolejne logowanie nie usuwa wcześniejszych tokenów.
- Wylogowanie usuwa token tylko z bieżącego urządzenia. Globalne „wyloguj wszędzie” jest poza zakresem.
</clarifications>
<impact_scan>
## Quality Radar
**Status:** ok
**Narzędzia:** codebase-memory-mcp 0.6.1; jscpd i ast-grep wyłączone polityką projektu.
## Dotknięte obszary
- Logowanie: `Auth::login`, `Auth::logout`, `app/Views/auth/login.php`.
- Ochrona tras: `AuthFilter::before` odtwarza zwykłą sesję po poprawnym tokenie.
- Dane: nowa tabela tokenów z wieloma rekordami; konto nadal pochodzi z `.env`.
- Wdrożenie: nowa migracja wymaga ręcznego uruchomienia na hostido.
## Ryzyka duplikacji / wartości hardcoded
- Czas 30 dni ma jedno źródło prawdy w `RememberTokenModel`.
- Token cookie nie może być zapisany jawnie w bazie; tabela przechowuje selektor i hash walidatora.
- Nie wydłużać globalnie `Session::$expiration`, bo nie zapewnia niezależnych urządzeń.
## Jawne odroczenia
- Panel urządzeń i „wyloguj wszędzie” — dodać dopiero na żądanie.
- Harmonogram czyszczenia — przy tej skali wygasłe tokeny wystarczy usuwać podczas użycia mechanizmu.
</impact_scan>
<acceptance_criteria>
## AC-1: Logowanie bez zapamiętania
```gherkin
Given użytkownik nie zaznaczył Zapamiętaj mnie
When poda poprawny email i hasło
Then otrzymuje wyłącznie obecną sesję bez trwałego cookie logowania
```
## AC-2: Logowanie zapamiętane przez 30 dni
```gherkin
Given użytkownik zaznaczył Zapamiętaj mnie
When poda poprawny email i hasło
Then aplikacja zapisuje bezpieczny token i cookie ważne 30 dni
And po utracie zwykłej sesji poprawny token odtwarza sesję i wpuszcza na chronioną trasę
```
## AC-3: Wiele urządzeń
```gherkin
Given użytkownik zaznaczył opcję na dwóch urządzeniach
When oba urządzenia otwierają chronioną trasę bez zwykłej sesji
Then oba niezależne tokeny pozostają poprawne
And wylogowanie na jednym urządzeniu nie unieważnia drugiego
```
## AC-4: Odrzucenie nieważnego tokenu
```gherkin
Given cookie jest zmienione, wygasłe lub nie ma odpowiadającego rekordu
When użytkownik otwiera chronioną trasę
Then cookie i wadliwy rekord są usuwane w możliwym zakresie
And użytkownik trafia na `/login`
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Dodać bezpieczne tokeny per urządzenie</name>
<files>app/Database/Migrations/2026-07-12-160001_CreateRememberTokens.php, app/Models/RememberTokenModel.php</files>
<action>Utworzyć tabelę z unikalnym selektorem, hashem walidatora, `expires_at` i timestampami. W modelu umieścić stałą 30 dni oraz operacje wystawienia tokenu przez `random_bytes`, weryfikacji przez `hash_equals`, usunięcia bieżącego tokenu i wygasłych rekordów. Każde logowanie dopisuje rekord.</action>
<verify>php -l app/Database/Migrations/2026-07-12-160001_CreateRememberTokens.php; php -l app/Models/RememberTokenModel.php</verify>
<done>AC-2, AC-3 i AC-4 mają trwały mechanizm danych bez jawnych sekretów w bazie.</done>
</task>
<task type="auto">
<name>Task 2: Podłączyć checkbox, odtworzenie sesji i wylogowanie</name>
<files>app/Controllers/Auth.php, app/Filters/AuthFilter.php, app/Views/auth/login.php</files>
<action>Dodać checkbox `remember`. Po poprawnym logowaniu tworzyć cookie tylko po zaznaczeniu. W filtrze zachować obecną ścieżkę sesji, a przy jej braku zweryfikować cookie i ustawić `logged_in`/`user_email`. Cookie: HttpOnly, SameSite=Lax, 30 dni, Secure w produkcji. `logout()` usuwa token bieżącego cookie, cookie i sesję.</action>
<verify>php -l app/Controllers/Auth.php; php -l app/Filters/AuthFilter.php; php -l app/Views/auth/login.php</verify>
<done>AC-1..AC-4 są obsłużone w przepływie HTTP.</done>
</task>
<task type="auto">
<name>Task 3: Sprawdzić bezpieczeństwo i równoległe urządzenia</name>
<files>tests/unit/RememberTokenModelTest.php</files>
<action>Dodać jeden mały test obejmujący dwa jednocześnie poprawne tokeny, odrzucenie zmienionego walidatora oraz unieważnienie jednego bez wpływu na drugi. Wykonać UAT w dwóch profilach przeglądarki.</action>
<verify>vendor/bin/phpunit tests/unit/RememberTokenModelTest.php; ręcznie: dwa profile przeglądarki zgodnie z AC-1..AC-4</verify>
<done>AC-1..AC-4 mają automatyczną kontrolę tokenów i potwierdzenie przepływu przeglądarkowego.</done>
</task>
</tasks>
<boundaries>
## Nie zmieniać
- Hasło i email nadal pochodzą z `.env`; nie tworzyć systemu wielu kont.
- Nie zmieniać czasu zwykłej sesji ani chronionych tras.
- Nie dotykać modułów finansów, inwestycji i paragonów.
## Ograniczenia zakresu
- Bez nowej zależności, panelu urządzeń, resetu hasła i „wyloguj wszędzie”.
- Bez surowego tokenu lub hasła w bazie i logach.
</boundaries>
<verification>
- [ ] `php -l` przechodzi dla zmienionych plików PHP.
- [ ] `vendor/bin/phpunit tests/unit/RememberTokenModelTest.php` przechodzi w środowisku z `vendor/`.
- [ ] UAT potwierdza zwykłe logowanie, 30-dniowe cookie, dwa profile, wylogowanie jednego profilu i odrzucenie zmienionego cookie.
- [ ] Cookie ma HttpOnly, SameSite=Lax, właściwy termin i Secure na produkcji.
- [ ] Migracja jest zastosowana ręcznie na zdalnej bazie przed wdrożeniem kodu.
- [ ] Ryzyka Quality Radar są obsłużone lub jawnie odroczone.
</verification>
<success_criteria>
- [ ] Wszystkie AC przechodzą.
- [ ] Weryfikacja jest kompletna.
- [ ] Dwa urządzenia pozostają zalogowane niezależnie przez maksymalnie 30 dni.
- [ ] Baza nie zawiera surowych tokenów.
</success_criteria>
<output>
SUMMARY.md path: `.paul/plans/20260712-1647-zapamietywanie-logowania/SUMMARY.md`
</output>