--- phase: 04h-hotfix-https-updates plan: 01 type: execute wave: 1 depends_on: [] files_modified: - autoload/Shared/Helpers/Helpers.php - autoload/admin/factory/class.Update.php - C:/visual studio code/projekty/cmstest.pagedev.pl/autoload/class.S.php - C:/visual studio code/projekty/cmstest.pagedev.pl/autoload/admin/factory/class.Update.php - updates/cmsPro.zip - updates/1.50/ver_1.519.zip - updates/**/ver_*.zip (audit + warunkowy patch) - updates/**/ver_*_manifest.json (regeneracja checksum_zip jeśli paczka patchowana) autonomous: false delegation: off --- ## Goal Naprawić mechanizm wykrywania nowych wersji aktualizacji (HTTP 301 → HTTPS bug) w trzech warstwach: 1. Bieżący kod cmsPRO (źródło) 2. Instancja testowa cmstest.pagedev.pl (działający bug) 3. Wszystkie dystrybuowane paczki (cmsPro.zip baseline + ver_*.zip), aby nowe instalacje cmsPRO nigdy nie utknęły z tym samym problemem ## Purpose Serwer cmspro.project-dc.pl został przeniesiony z HTTP na HTTPS i odpowiada `301 Moved Permanently`. PHP-owy `file_get_contents()` bez kontekstu nie podąża za redirectem, więc zwraca HTML 301 zamiast listy wersji. Skutkiem `(float)max($html_lines)` daje 0 i `S::get_new_version()` nigdy nie pokazuje nowszej wersji niż zainstalowana. Aktualnie WSZYSTKIE instancje cmsPRO zainstalowane przed migracją serwera są zablokowane. ## Output - Patch HTTP→HTTPS w kodzie źródłowym i w instancji testowej - Audit-report listujący każdą paczkę aktualizacji zawierającą `http://www.cmspro.project-dc.pl` - Patchowane paczki ZIP + zaktualizowane manifesty (SHA256) - ver_1.519.zip rozszerzony o poprawione class.S.php i class.Update.php — "kotwica fixa" dla instancji przechodzących przez tę wersję - Lista plików do uploadu na cmspro.project-dc.pl (dla użytkownika) ## Project Context @.paul/PROJECT.md @.paul/STATE.md @.paul/ROADMAP.md ## Source Files @autoload/Shared/Helpers/Helpers.php @autoload/admin/factory/class.Update.php @build-update.ps1 ## AC-1: Kod źródłowy cmsPRO używa HTTPS ```gherkin Given pliki autoload/Shared/Helpers/Helpers.php oraz autoload/admin/factory/class.Update.php When zostają zaktualizowane Then nie zawierają już ciągu "http://www.cmspro.project-dc.pl" And zawierają "https://www.cmspro.project-dc.pl" ``` ## AC-2: Instancja testowa jest odblokowana ```gherkin Given instancja w C:\visual studio code\projekty\cmstest.pagedev.pl\ na wersji 1.519 When pliki autoload/class.S.php i autoload/admin/factory/class.Update.php zostają poprawione (http→https) And sesja "new-version" zostaje wyczyszczona (przez wylogowanie/restart sesji) Then panel admina pokazuje nową wersję > 1.519 And klik "Aktualizuj" pobiera kolejną paczkę bez błędu ``` ## AC-3: Wszystkie paczki dystrybucyjne wolne od bug-a ```gherkin Given katalog updates/ z plikami cmsPro.zip oraz updates/**/ver_*.zip When skrypt audit przeskanuje każdą paczkę Then żadna paczka nie zawiera pliku z ciągiem "http://www.cmspro.project-dc.pl" And paczki które zawierały bug zostały sparowane z patched-wersjami And manifesty (jeśli istnieją) mają zaktualizowane checksum_zip (SHA256) zgodne z nowym ZIP ``` ## AC-4: ver_1.519.zip jest "kotwicą fixa" ```gherkin Given oryginalny ver_1.519.zip zawiera tylko class.Articles.php When zostaje rozszerzony o poprawione autoload/class.S.php i autoload/admin/factory/class.Update.php Then każda nowa instancja cmsPRO przechodząca update do 1.519 dostaje plik z https:// And tym samym może wykryć i pobrać kolejne aktualizacje ``` ## AC-5: Audit report dostarczony ```gherkin Given wykonany skrypt audit When skanowanie się kończy Then powstaje plik .paul/phases/04h-hotfix-https-updates/audit-report.md Z listą: każda paczka, jakie zawiera podejrzane pliki, czy zawiera http://, akcja podjęta (patched|skipped|N/A) ``` Task 1: Patch kodu źródłowego cmsPRO (HTTP → HTTPS) autoload/Shared/Helpers/Helpers.php, autoload/admin/factory/class.Update.php Zamień wszystkie wystąpienia `http://www.cmspro.project-dc.pl` → `https://www.cmspro.project-dc.pl` w obu plikach (Edit replace_all). Plików łącznie ~6 wystąpień: - Helpers.php:456 (versions.php) - factory/class.Update.php: versions.php, .zip, _manifest.json, _sql.txt, _files.txt NIE dodawaj kontekstu stream (follow_location=1) — wystarczy zmiana protokołu, bo serwer obsługuje HTTPS bezpośrednio i bez redirectu. NIE zmieniaj logiki parsowania, kontroli wersji, manifestów — tylko URL. NIE ruszaj index.php:92 (`\S::get( 'hash' ) == $settings['update_key']`) — to inna sprawa. grep -c "http://www.cmspro.project-dc.pl" autoload/Shared/Helpers/Helpers.php autoload/admin/factory/class.Update.php → wynik 0:0 (zero wystąpień) grep -c "https://www.cmspro.project-dc.pl" → wynik >=1:>=4 AC-1 satisfied Task 2: Hotfix instancji testowej cmstest.pagedev.pl C:/visual studio code/projekty/cmstest.pagedev.pl/autoload/class.S.php, C:/visual studio code/projekty/cmstest.pagedev.pl/autoload/admin/factory/class.Update.php W instancji testowej zamień `http://www.cmspro.project-dc.pl` → `https://www.cmspro.project-dc.pl` w obu plikach (Edit replace_all). Pliki w instancji testowej mają STARSZĄ strukturę (przed refaktoringiem) — class.S.php zawiera get_new_version(), class.Update.php (factory) zawiera 4 wystąpienia URL (versions.php, .zip, _sql.txt, _files.txt — bez manifest, bez SHA256). Po patchu trzeba poinstruować użytkownika, żeby: - wylogował się z panelu (wyczyści sesję `new-version`), - lub w przeglądarce otworzył dowolny link admina po wylogowaniu i ponownym zalogowaniu. NIE modyfikuj innych plików w instancji testowej — to środowisko UAT, ma odzwierciedlać stan produkcyjny. grep -c "http://www.cmspro.project-dc.pl" w obu plikach → 0:0 AC-2 satisfied (część kodowa, weryfikacja UAT w Task 8) Task 3: Skrypt audit paczek aktualizacji .paul/phases/04h-hotfix-https-updates/scripts/audit-packages.ps1, .paul/phases/04h-hotfix-https-updates/audit-report.md Napisz PowerShell-owy skrypt audytujący wszystkie ZIP-y w `updates/` (rekurencyjnie), który dla każdego ZIP: 1. Wymienia pliki kandydujące: `autoload/class.S.php`, `autoload/Shared/Helpers/Helpers.php`, `autoload/admin/factory/class.Update.php` (i ich starsze warianty jak `class.Update.php`). 2. Jeśli któryś istnieje — rozpakowuje go do tempu, sprawdza zawartość `Select-String -Pattern 'http://www\.cmspro\.project-dc\.pl'`. 3. Wynik dla każdej paczki: { package, files_present, has_buggy_url, action }. Skrypt MUSI obsłużyć też `updates/cmsPro.zip` (base install). Skrypt NIE patchuje paczek — tylko raportuje. Patch w Task 4. Output do `audit-report.md` jako tabela markdown sortowana wersjami. Skrypt nie wymaga uprawnień do zapisu w paczkach. pwsh -File .paul/phases/04h-hotfix-https-updates/scripts/audit-packages.ps1 → audit-report.md powstaje i zawiera wpis dla cmsPro.zip + co najmniej ver_1.518, ver_1.620 AC-5 satisfied: pełna lista dotkniętych paczek Czy patchować WSZYSTKIE paczki z bugiem, czy tylko baseline cmsPro.zip + ver_1.519 jako kotwica? Po audycie znamy listę dotkniętych paczek. Możliwe strategie: - Patch wszystkich (pełna sanityzacja, ale każda zmieniona paczka wymaga regeneracji manifestu+checksum i upload na serwer). - Patch minimum (cmsPro.zip + ver_1.519 jako kotwica) — nowe instalacje od zera są OK, a każdy upgrade dochodząc do 1.519 dostaje fix. Decyzja zależy od liczby dotkniętych paczek z audit-report.md. Select: full-patch lub minimal-patch Task 4: Patch dotkniętych paczek (zgodnie z decyzją z Task 3.5) updates/cmsPro.zip, updates/1.50/ver_1.518.zip (jeśli buggy), updates/1.60/ver_1.620.zip (jeśli buggy), updates/**/ver_*.zip (każda inna z audit-report.md jeśli wybrano full-patch), updates/**/ver_*_manifest.json (regeneracja checksum_zip dla patched paczek z manifestem) Dla każdej paczki do patcha: 1. Skopiuj ZIP do tempu (backup) 2. Wyciągnij plik(i) zawierające http://www.cmspro.project-dc.pl 3. Zamień http:// → https:// (zachowaj BOM, encoding UTF-8 bez BOM zgodnie z konwencją projektu) 4. Wsadź spowrotem do ZIP-a (Compress-Archive -Update lub System.IO.Compression.ZipArchive) 5. Jeśli istnieje `ver_X.YYY_manifest.json` w tym samym katalogu — przelicz SHA256 całego ZIP i zaktualizuj `checksum_zip` w manifeście (format: `sha256:HEX`) 6. Zachowaj oryginał jako `.bak` w tym samym katalogu Dla cmsPro.zip nie ma manifestu (to base install) — sam ZIP wystarczy. NIE ruszaj paczek, które audit zaznaczył jako N/A (brak buggy plików). NIE zmieniaj struktury katalogów wewnątrz ZIP-ów. Powtórz audit z Task 3 — każda zmieniona paczka pokazuje `has_buggy_url: false`. Dla każdej paczki z manifestem: `(Get-FileHash -Algorithm SHA256 paczka.zip).Hash.ToLower()` równe wartości checksum_zip w manifeście. AC-3 satisfied Task 5: Wstrzyknięcie kotwicy fixa do ver_1.519.zip updates/1.50/ver_1.519.zip ver_1.519.zip oryginalnie zawiera tylko `autoload/admin/controls/class.Articles.php`. Dodać do niego (Compress-Archive -Update lub równoważne): - `autoload/class.S.php` — wersja z https:// (taka sama jaka ląduje w cmsPro.zip post-patch) - `autoload/admin/factory/class.Update.php` — wersja z https:// - `autoload/admin/controls/class.Update.php` — bez zmian (kontrola, nie ma URL) - `autoload/admin/view/class.Update.php` — bez zmian Pliki muszą mieć strukturę pasującą do legacy układu (PRZED refaktoringiem do Shared\Helpers), czyli class.S.php zawiera get_new_version() inline. Skopiuj odpowiednie wersje z post-patched `cmsPro.zip` lub z wcześniejszej paczki (np. patched ver_1.518.zip jeśli była buggy). Cel: każda instancja cmsPRO doczołgająca się do 1.519 dostaje WORKING klient HTTPS, nawet jeśli wcześniejsze paczki były buggy. Jeśli istnieje ver_1.519_manifest.json — dodaj wpisy `files.added` z nowo wstrzykniętymi plikami i przelicz checksum_zip. Jeśli nie istnieje — opcjonalnie wygeneruj go (zgodnie ze schematem z build-update.ps1). unzip -l updates/1.50/ver_1.519.zip → zawiera autoload/class.S.php oraz autoload/admin/factory/class.Update.php unzip -p updates/1.50/ver_1.519.zip autoload/class.S.php | grep -c "https://" → >=1 unzip -p updates/1.50/ver_1.519.zip autoload/class.S.php | grep -c "http://www.cmspro" → 0 AC-4 satisfied Task 6: Generacja listy plików do uploadu na serwer .paul/phases/04h-hotfix-https-updates/upload-checklist.md Wygeneruj plik z listą paczek wymagających uploadu na cmspro.project-dc.pl/updates/: - cmsPro.zip (jeśli zmieniony) - każda zmieniona ver_*.zip wraz ze swoim manifestem (jeśli istnieje) - ver_1.519.zip + ewentualny nowy ver_1.519_manifest.json Format: tabela markdown { plik, ścieżka źródłowa, ścieżka docelowa na serwerze, SHA256 }. Dodaj sekcję "Po uploadzie" z krokami: smoke-test (curl https://.../updates/versions.php?key=KLUCZ), weryfikacja że versions.php nadal zwraca poprawną listę. Plik istnieje i zawiera co najmniej cmsPro.zip + ver_1.519.zip + smoke-test command Dostarczona instrukcja uploadu dla użytkownika Zestaw spatchowanych paczek + cmsPro.zip + ver_1.519.zip kotwica fixa, gotowe do uploadu. 1. Otwórz `.paul/phases/04h-hotfix-https-updates/upload-checklist.md` 2. Wgraj wskazane pliki na serwer cmspro.project-dc.pl do katalogu updates/ (FTP/SSH/panel hostingu — wedle Twojej procedury) 3. Uruchom smoke-test: curl -sS "https://www.cmspro.project-dc.pl/updates/versions.php?key=DOWOLNY_VALID_KEY" → powinno zwrócić listę wersji bez 301 4. Pobierz testowo jedną z paczek: curl -sS -o /tmp/test.zip "https://www.cmspro.project-dc.pl/updates/1.50/ver_1.519.zip" file /tmp/test.zip → powinno być "Zip archive" Wpisz "uploaded" gdy paczki są na serwerze, lub opisz problem Hotfix instancji testowej: pliki zaktualizowane lokalnie + paczki na serwerze. 1. W instancji testowej (cmstest.pagedev.pl) wyloguj się i zaloguj ponownie do panelu (czyści sesję `new-version`). 2. Wejdź w sekcję aktualizacji (admin → Aktualizacja). 3. Sprawdź: - Pokazuje wersję 1.519 jako bieżącą - Pokazuje "Dostępna nowa wersja: X.YYY" gdzie X.YYY > 1.519 - Klik "Aktualizuj" przebiega bez błędu i zwiększa wersję 4. Powtórz update kilka razy aż dojdziesz do najnowszej dostępnej wersji. 5. Sprawdź `libraries/version.ini` w instancji — odzwierciedla najnowszą wersję. Wpisz "approved" gdy aktualizacje działają, lub opisz problem ## DO NOT CHANGE - index.php:92 (`\S::get('hash') == $settings['update_key']`) — to oddzielna funkcja (front-devel mode), nie URL - Logika parsowania wersji, manifestów, SQL — tylko URL ma się zmienić - Struktura katalogowa updates/ na serwerze — tylko zawartość plików - Inne pliki w instancji testowej cmstest.pagedev.pl — to UAT, ma odzwierciedlać prod - Roadmap Phase 5+ — to hotfix poza roadmapą, nie blokuje Phase 5 ## SCOPE LIMITS - Plan NIE refaktoryzuje update systemu do nowej architektury (to robota dla Phase 5/13) - Plan NIE wprowadza retry/cURL/stream-context — wystarczy zmiana protokołu, serwer wspiera HTTPS bezpośrednio - Plan NIE patchuje pojedynczych instancji produkcyjnych poza testową — użytkownicy końcowi dostaną fix przez kotwicę 1.519 lub baseline cmsPro.zip - Plan NIE rozwiązuje problemu "stare instancje na <1.519 zablokowane przed migracją serwera" — wymagałyby manualnego patcha (out of scope) Przed zamknięciem planu: - [ ] Task 1 verify (grep w kodzie cmsPRO) - [ ] Task 2 verify (grep w instancji testowej) - [ ] Task 3: audit-report.md istnieje i jest kompletny - [ ] Task 4: powtórzony audit pokazuje 0 buggy paczek (dla full-patch) lub tylko nie-patched paczki świadomie pominięte - [ ] Task 5: ver_1.519.zip zawiera fix files - [ ] Task 6: upload-checklist.md istnieje - [ ] Checkpoint upload: użytkownik potwierdził upload + smoke-test OK - [ ] Checkpoint UAT: instancja testowa aktualizuje się do najnowszej wersji bez błędu - [ ] Wszystkie AC spełnione - Bieżąca instancja testowa odblokowana — widzi i instaluje aktualizacje > 1.519 - Bazowy install (cmsPro.zip) na serwerze nie zawiera buggy http:// - ver_1.519.zip jest "kotwicą fixa" dla każdej nowej instalacji - Audit report dokumentuje stan wszystkich paczek - Brak regresji w innych modułach (URL change to jedyna ingerencja) Po zamknięciu utwórz `.paul/phases/04h-hotfix-https-updates/04h-01-SUMMARY.md` zawierający: - Co zmieniono (kod + paczki) - Listę paczek patched z SHA256 przed/po - Decyzję checkpoint (full-patch vs minimal-patch) i uzasadnienie - Lessons learned (np. "zawsze używać HTTPS w endpointach update", "rozważyć stream context z follow_location jako defense-in-depth") - Sugestię dla Phase 5/13 Releases+Update: rozważyć cURL z verify SSL i obsługą redirectów jako trwałe rozwiązanie