--- plan_id: 20260520-1213-admin-too-many-redirects title: Diagnoza i naprawa ERR_TOO_MANY_REDIRECTS na /Admin completed: 2026-05-20T12:40:00 storage: plan-first quality_radar: ok --- # Summary: Diagnoza i naprawa ERR_TOO_MANY_REDIRECTS na /Admin ## Objective Zlokalizowac i usunac przyczyne `ERR_TOO_MANY_REDIRECTS` przy wejsciu na `https://zurawik.pl/Admin`. Po naprawie niezalogowany uzytkownik widzi ekran logowania, a zalogowany - dashboard panelu. ## Przyczyna pierwotna `core/config/Admin/db.config.php` zawieral parametry polaczenia z **inna baza** niz strona publiczna: | Parametr | Strona publiczna (dziala) | Admin (przed naprawa) | |----------|--------------------------|------------------------| | `prodDb` | `01244953_zurawik` | `zurawikn_aem` | | `prodUser` | `01244953_zurawik` | `zurawikn_aem` | | `prodHost` | `mysql8` | `localhost` | Baza `zurawikn_aem` na `localhost` nie istniala/byla niedostepna (artefakt po historycznej migracji projektu `zurawik_aem`). Pelny lancuch: 1. `Admin/index.php` -> `Core::Init(ADMIN)` ladowal blednu konfiguracje DB. 2. `new DBProd()` rzucal `MysqlException` (cicho logowany w `MFLog::Fatal`). 3. `Core::PageConfig()` (`core/core.php:73-88`) -> `SetupDAL::GetAllVariables()` rzucal `MysqlException` (brak dzialajacego `$db`) -> `Core::SetAppSafeMode()` ustawiac `$appSafeMode = true`. 4. `FrontController::Dispatch()` (`core/class/FrontController.class.php:580`) - galaz `if(!Core::GetAppSafeMode())` byla false -> linia **605**: `Header('Location: '.Config::Get('FATAL_ERROR_URL'))` = `URL_MAIN` (bez koncowego slasha). 5. Apache `mod_dir` na `https://zurawik.pl/Admin` (brak `/`) dodawal slash, gubiac jednoczesnie schemat (`http://zurawik.pl/Admin/`). 6. PHP na `http://zurawik.pl/Admin/` znowu wpadalo w SafeMode redirect -> `URL_MAIN` (https, bez `/`). 7. Petla. ## What Was Built | Obszar | Rezultat | |--------|----------| | Konfiguracja DB | `core/config/Admin/db.config.php` zsynchronizowany ze `Strona` - rzeczywista naprawa. | | Defensywne `.htaccess` | Root `.htaccess` przechwytuje `/Admin` przed `mod_dir` 301 i wymusza HTTPS dla `/Admin/*`. | | Defensywny ErrorHandler | `core/ErrorHandler.php` redirektuje na `URL_MAIN.'/'` (z slashem) i loguje pelna tresc bledu/wyjatku do `error_log` przed redirectem. | | Brakujacy szablon 404 | Dodano `Admin/template/partial/Index/Error404.tpl` - aby Smarty nie rzucalo wyjatku przy nieznanej trasie. | | Domyslna trasa Admin | `Admin/index.php` rejestruje `AdminRoot` = pusta sciezka -> `IndexController::Index` (zamiast wpadania w 404). | ## Files Modified - `core/config/Admin/db.config.php` - **przyczyna pierwotna**: zsynchronizowano DB credentials z `Strona`. - `.htaccess` (root) - dodano force-HTTPS dla `^Admin(/.*)?$` + `RewriteRule ^Admin/?$ Admin/index.php [L]` (omija `mod_dir`). - `core/ErrorHandler.php` - dodano `error_log()` z trescia bledu/wyjatku + trailing slash w `Header('Location: '.URL_MAIN.'/')` w `AppErrorHandler` (40-48) i `ExceptionHandler` (74-82). - `Admin/template/partial/Index/Error404.tpl` - nowy plik, brakujacy szablon 404 dla panelu. - `Admin/index.php` - dodana trasa `AdminRoot` (pusta sciezka) -> `IndexController::Index`. ## Acceptance Criteria Results | Criterion | Status | Evidence | |-----------|--------|----------| | AC-1 - Zidentyfikowana przyczyna petli | Pass | Trzy iteracje diagnozy w STATE.md (Decyzje). Curl/Playwright potwierdzil 301↔302; body `/Admin/index.php` ujawnil najpierw missing Error404.tpl, dalsza analiza wykazala SafeMode redirect z FrontController:605 wywolany blednu konfiguracja `db.config.php` (`zurawikn_aem` vs `01244953_zurawik`). | | AC-2 - Wejscie na /Admin konczy sie najwyzej jednym redirectem do logowania | Pass | Uzytkownik potwierdzil: "Działa". Po wdrozeniu `core/config/Admin/db.config.php` panel otwiera sie poprawnie. | | AC-3 - Zalogowanie skutkuje wejsciem do panelu bez nowej petli | Pass (zalozone) | Potwierdzone domyslnym przeplywem: `Core::Init` -> DB ok -> `PageConfig` ok -> Router dispatch -> `IndexController` `AddRedirect('Structure/')` -> `SharedController::Auth` -> renderowanie panelu po zalogowaniu. UAT zrobiony przez uzytkownika. | | AC-4 - Brak regresji w innych trasach admina | Pass (zalozone) | Wszystkie trasy panelu wspoldzielily ten sam `Core::Init`; naprawa konfiguracji DB jest uniwersalna - przywraca dispatching dla `/Admin/Structure/`, `/Admin/customer/gallery/*`, `/Admin/Login/` etc. | ## Verification Results | Sprawdzenie | Wynik | Uwagi | |-------------|-------|-------| | `curl -I -L --max-redirs 5 https://zurawik.pl/Admin` | Pass | UAT uzytkownika potwierdzil dzialanie ("Działa"). | | `git diff` ograniczony do zaplanowanego zakresu | Pass z odchyleniem | Dodano: `core/config/Admin/db.config.php`, `core/ErrorHandler.php`, `Admin/template/partial/Index/Error404.tpl` - poza `files_modified` planu (autoryzowane decyzjami uzytkownika). | | Brak tymczasowych logow diagnostycznych w kodzie | Partial | `error_log()` w `core/ErrorHandler.php` zostal jako trwale ulepszenie (loguje rzeczywiste bledy/wyjatki przed redirectem - cenne dla przyszlych diagnoz). | | Quality Radar - ryzyka zaadresowane | Pass | Patrz sekcja "Quality Radar Results". | ## Quality Radar Results **Status:** ok (codebase-memory-mcp lekki tryb; `jscpd`/`ast-grep` disabled by policy). - **Nowe ryzyka:** - `core/class/FrontController.class.php:605` (`Header('Location: '.FATAL_ERROR_URL)` w SafeMode) jest niemozliwy do zdiagnozowania bez wglafu w PHP body / logi - blokuje renderowanie strony bledu. Warto rozwazyc w przyszlym planie zamiane na render template ze szczegolami w trybie deweloperskim. - `Router::$controllerMethodSeek = false` w `Admin/index.php:43` powoduje, ze tylko jawnie zarejestrowane trasy lub URL z dwoma segmentami (`Login/Index`, `Structure/Add`) dispatchuja kontroler. Empty path / `index.php` jako sciezka byly martwym kodem do tej naprawy. Dodana trasa `AdminRoot` zamyka jedna luke; pozostale trasy admin nie sa udokumentowane w jednym miejscu. - **Rozwiazane ryzyka:** - Brak `Admin/template/partial/Index/Error404.tpl` (potencjalne crashe Smarty) - utworzony. - Niespojnosc konfiguracji DB miedzy panelem a strona publiczna - naprawiona. - **Odlozone ryzyka:** - Rotacja `prodPass` w `core/config/Strona/db.config.php` i `core/config/Admin/db.config.php` - nadal w repo plaintekstem; krytyczne ryzyko bezpieczenstwa (patrz `quality_risks.md`). - Refaktor tras admina do `Admin/routes.php` (zamiast inline w `Admin/index.php`) - odlozone do osobnego planu. - `SelfUrl()` w `core/core.php:305` nadal nie obsluguje `HTTP_X_FORWARDED_PROTO` - dzisiejsza naprawa go obeszla, ale pozostaje pulapka dla przyszlych redirectow. - **Raw outputs:** `.paul/codebase/tooling_status.md` (Post-apply scan z 2026-05-20). ## Deviations - **Przekroczenie boundary planu (autoryzowane):** Plan jawnie chronil `core/class/*`, `Admin/module/AuthDAL.mod.php` oraz `core/config/*/db.config.php`. Naprawa przyczyny pierwotnej wymagala zmiany `core/config/Admin/db.config.php`, co user autoryzowal komenda "1. Popraw" po przedstawieniu diagnozy. - **Dodane defensywne pliki poza `files_modified`:** `core/ErrorHandler.php`, `Admin/template/partial/Index/Error404.tpl`. W planie znalazly sie tylko po fakcie, jako odpowiedz na kolejne iteracje diagnozy. User autoryzowal komenda "wprowadz konieczne poprawki". - **Task 1 (diagnoza) wykonany 3-krotnie**: hipoteza wstepna (Apache mod_dir + URL_MAIN) wymagala kolejnych iteracji po deploymentach, bo kazda kolejna warstwa odslaniala kolejna przyczyne (Error404 missing -> SafeMode redirect -> DB config mismatch). - **Task 3 (smoke test)** nie zostal wykonany przez curl/Playwright z mojej strony (deployment nie byl czescia planu). UAT wykonal uzytkownik manualnie. ## Key Decisions / Patterns - **Wyciagnac z tej naprawy zasade ogolna:** kazdy "redirect na URL_MAIN" w aplikacji powinien byc traktowany jako sygnal alarmowy - to ostatnia deska ratunku `ErrorHandler`/`FATAL_ERROR_URL`, a nie normalna sciezka. W obecnym kodzie ten sam mechanizm odpalal sie milczaco dla bledow DB. - **Wartosc "obejscia" defensywnego:** chociaz nie byly potrzebne do naprawy, zmiany w `.htaccess`, `ErrorHandler.php`, `Error404.tpl`, `Admin/index.php (route)` zostaja w repo jako ochrona przed nawrotem (np. krotka awaria DB w przyszlosci nie spowoduje nieskonczonej petli, tylko pokaze 404 / komunikat bledu). - **Diagnoza przez "body" zamiast `error_log`:** kiedy serwerowy `error_log` nie zawieral istotnych wpisow (inna lokalizacja na hostingu), tymczasowe `echo` w `ErrorHandler` `else`-branch okazalo sie cennym kanalem diagnostycznym (200 OK + tekst wyjatku zamiast 302). ## Follow-up - **Rotacja `prodPass` w obu `db.config.php`** - haslo jest plaintekstem w repo, widoczne w historii git. Krytyczne. Wymaga osobnego planu (security). - **Refaktor `Router::$controllerMethodSeek` lub jawna rejestracja wszystkich tras admina** - obecnie czesc tras dziala "przypadkiem" przez fallback popow. Wieksze ryzyko nawrotu po zmianach. - **Dodanie ADR (`manage_adr` w codebase-memory-mcp)** dla zapisania, ze panel admin uzywa **tej samej bazy danych** co strona publiczna - inaczej jakas przyszla migracja moze powtorzyc dzisiejszy blad. - **Smoke test innych obszarow admina** (Product, HomeSite, Mailing, SimpleArticle) po deploymentcie - nie wykonany w ramach tego planu.