Audyt pokazal rozbieznosci w obie strony: dokumenty opisywaly funkcje,
ktorych nie ma (logowanie Google/Facebook), a kod robil rzeczy, ktorych
dokumenty nie ujawnialy.
Kod:
- zgody marketingowe domyslnie WYLACZONE (byly true dla kazdego nowego
konta) + skrypt fix-marketing-consents.sql czyszczacy stare wpisy,
- usuniete tlumaczenie przez nieoficjalne API Google - przy zmianie
jezyka wysylalo do USA tresci stron, w tym wiadomosci i nazwiska,
- osadzone spacery (YouTube, Matterport, Kuula) laduja sie dopiero po
zgodzie; YouTube w trybie bez ciasteczek; mapy jak dotad,
- usuniecie konta kasuje dane osobowe (AccountErasureService), a nie
tylko wiersz app_users,
- wygasle tokeny i kody SMS kasowane po 7 dniach (ExpiredTokenCleaner),
- zapisujemy moment akceptacji regulaminu przy rejestracji.
Dokumenty: opisuja realne funkcje, wszystkich odbiorcow danych (OVH,
Autopay, SMTP, SMS, Esri, OpenStreetMap, YouTube/Matterport/Kuula, GUS),
transfery poza EOG, konkretne okresy przechowywania, procedure zgloszen
z DSA, brak profilowania i tabele pamieci przegladarki zamiast fikcyjnych
cookies analitycznych. Zakres NIS2 i DORA opisany zgodnie z prawda.
Uklad stron prawnych jak reszta serwisu: kontener 1760 px, karty,
spis tresci z boku.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Alerty liczyla dotad przegladarka, wiec dzialaly wylacznie przy otwartej
stronie, a rynek porownywaly malymi literami ("wtorny" vs "Wtórny"),
przez co alert lokalizacji z wybranym rynkiem nigdy nie mial danych.
Teraz: tabele price_alerts i price_alert_events, /api/price-alerts oraz
codzienny przeglad o 03:00 (po nocnym zapisie srednich cen). Ogloszenie -
powiadomienie przy kazdej zmianie ceny; lokalizacja - przy zmianie
sredniej o co najmniej 2%. Wynik trafia wylacznie na liste powiadomien
uzytkownika; alerty nie wysylaja zadnych e-maili.
Alerty zalozone w przegladarce przenosimy raz przy pierwszym wejsciu.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Spring Boot 3.3.5 -> 3.5.16 (linia 3.3 bez poprawek bezpieczenstwa).
- Testy zamiast H2 uzywaja tymczasowego PostgreSQL 16 (Testcontainers),
tej samej wersji co produkcja; ddl-auto update jak na produkcji.
Testcontainers 1.21 (z Boot 3.5) jest wymagany - 1.19 z Boot 3.3 nie
dziala z obecnym Docker Desktop, dlatego obie zmiany w jednym commicie.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- /api/listings/favorites i /mine/** wymagaja logowania (anonimowo byl blad 500).
- Nowa rozmowa tylko o opublikowanym ogloszeniu.
- Licznik wyswietlen: jedno wyswietlenie na IP i ogloszenie na godzine.
- Rezygnacja z mailingu: GET pyta o potwierdzenie, wypisuje dopiero POST
(tez z przycisku programu pocztowego); podpis porownywany w stalym czasie.
- Usuniecie konta usuwa jego ogloszenia.
- Haslo przy rejestracji min. 8 znakow; resend-phone-otp nie zdradza, czy konto istnieje.
- docker-compose.prod.yml bez domyslnego Admin123!; bez hasla konto admina
nie jest zakladane (blad w logu).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Zmiana tytulu, opisu, zdjec, danych kontaktowych lub linku spaceru
w ogloszeniu opublikowanym albo wstrzymanym ustawia status PENDING;
cena i parametry zmieniaja sie od razu.
- Frontend nie koduje ponownie zapisanych zdjec JPEG przy edycji (bez utraty
jakosci i bez falszywej zmiany zdjec); informacja o weryfikacji w formularzu.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Imie, tytul artykulu i powod odrzucenia oraz {{name}} w kampaniach
escapowane w HTML maili; limit dlugosci imienia.
- Kredyty promowania zuzywane i dopisywane warunkowym UPDATE, ITN blokuje
wiersz zamowienia; zakup i kredyt tylko na aktywny plan/pakiet.
- Strumien powiadomien na krotkim (60 s) tokenie ?ticket= pobieranym przez
POST /api/notifications/stream-token; token sesji nie jest przyjmowany z adresu.
- Przyblizona lokalizacja jako srodek kratki 300 m zamiast odwracalnego
przesuniecia liczonego z id.
- Propozycja spotkania respektuje blokade i moderacje, bez e-maila w nazwie.
- Zglaszajacy dostaje samo potwierdzenie; zgloszenia tylko opublikowanych
ogloszen; nie zapisujemy rozmowy przyslanej przez przegladarke.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- JwtAuthFilter bierze role i stan konta z bazy: blokada, usuniecie konta
i odebranie roli admina dzialaja od razu. Zmiana i reset hasla koncza
dotychczasowe sesje (sessionsValidFrom); zmiana hasla zwraca nowy token.
- Publiczne odpowiedzi ogloszen bez ownerEmail/contactEmail; inne oferty
sprzedajacego z GET /api/listings/{id}/seller-listings.
- Publiczny formularz reklamowy nie zmienia zgod ani nazwy istniejacego leada.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- ITN: XML w base64 (pole transactions), bezpieczny parser (bez XXE), podpis
ze stalej listy pol, zgodnosc ServiceID, kwoty i waluty, idempotencja,
podpisana odpowiedz XML CONFIRMED/NOTCONFIRMED.
- Start transakcji podpisanym formularzem POST ze strony /platnosc/:orderId
zamiast linku GET z podpisem w adresie; tytul przelewu w ASCII.
- Losowy OrderID (UUID) zamiast Math.random.
- Adres ITN do wpisania w panelu AutoPay widoczny w panelu admina.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Zdjecia ogloszen tylko jako data URL JPEG/PNG/WebP; podglad OG serwuje
wylacznie te typy z nosniff i CSP sandbox, bez przekierowania na dowolny URL.
- Zakup promowania bez skonfigurowanej bramki AutoPay zwraca 503; automatyczne
potwierdzanie tylko przy APP_PAYMENTS_AUTO_CONFIRM (lokalnie).
- ITN uznaje platnosc tylko przy jawnym statusie SUCCESS i zgodnej kwocie.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lista ostatnio sprawdzonych lokalizacji zyla w localStorage, wiec ginela
przy zmianie urzadzenia. Teraz jest polem ustawien konta
(user_settings.price_history_markets), a wpisy z przegladarki
przenosimy raz przy pierwszym wejsciu.
To historia przegladania, nie alerty - nic z niej nie wysyla powiadomien.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Outbox byl budowany, ale nic go nie przetwarzalo - kampania wchodzila
w status SENDING i tak zostawala. CampaignSender co minute bierze
kampanie gotowe do wyslania i wysyla je porcjami po 25, pilnujac
dziennego limitu kampanii.
Tuz przed wyslaniem kazdy odbiorca jest sprawdzany ponownie (zgoda
mogla zostac cofnieta po zbudowaniu outboxu) - taki dostaje OPTED_OUT.
Kazda wiadomosc ma link rezygnacji. Bez skonfigurowanej skrzynki
kolejka czeka, zamiast spalic sie na bledach.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SchemaFixer wykonuje SQL w skladni PostgreSQL (split_part, DO $$,
to_regclass), wiec kazdy @SpringBootTest wywracal sie przy starcie na
testowym H2. Teraz runner sprawdza rodzaj bazy i na innej niz PostgreSQL
nic nie robi - w testach schemat i tak tworzy Hibernate z encji.
mvn test: 22 testy, 0 bledow (bylo 3 bledy).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dotad front po kazdej zmianie dyktowal serwerowi cala liste ulubionych.
Zalogowanie sie na innym urzadzeniu wysylalo "mam zero ulubionych"
i kasowalo zapisy, przez co wlasciciel ogloszenia tracil licznik zapisan.
Teraz: GET /api/listings/favorites zwraca ulubione konta, dodanie
i usuniecie ida pojedynczo (POST/DELETE /{id}/favorite), a wpisy z
przegladarki dopisuje jednorazowy /favorites/import. Endpoint
/favorites/sync usuniety razem z jego jedynym wywolaniem.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nowa tabela meetings i /api/meetings. Termin proponuje jedna ze stron
rozmowy o ogloszeniu, druga potwierdza albo odrzuca; odwolac moze kazda
ze stron. Kalendarz konta pokazuje oba rodzaje wpisow - umowione
ogladania i wlasne notatki - i jest ten sam na kazdym urzadzeniu.
Powiadomienia: wpis w watku i dzwonek przy kazdej zmianie, e-mail
wylacznie przy potwierdzeniu terminu.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nowa tabela saved_searches i /api/saved-searches (lista, dodanie,
usuniecie, jednorazowy import wpisow z localStorage). Front czyta liste
z serwera, wiec wyszukiwania sa te same na kazdym urzadzeniu i przezywaja
wyczyszczenie danych strony. Bez powiadomien. Skrypt czyszczacy usuwa
wpisy skasowanych kont.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Strona /historia-cen pokazywala pusty wykres (wczesniej zmyslony). Teraz:
Ceny ofertowe z ogloszen:
- Tabela price_snapshots: codzienny zapis srednich cen za m2 z opublikowanych
ogloszen per miasto i dzielnica, typ (mieszkanie/dom) i rynek. Zapis co noc
(02:30) i przy starcie, gdy brakuje dzisiejszego. Historii sprzed pierwszego
zapisu nie odtwarzamy.
Ceny transakcyjne ze zrodel publicznych (porownanie, cale miasto, mieszkania):
- NBP: plik ceny_mieszkan.xlsx (baza BaRN) - 17 miast, rynek pierwotny
i wtorny, od III kw. 2006. Odczyt XLSX bez nowych zaleznosci.
- GUS: API Banku Danych Lokalnych (temat P3794) - miasta na prawach powiatu,
kwartalnie od 2010, z opoznieniem ok. roku.
- Import raz w tygodniu i przy starcie, gdy dane sa starsze niz tydzien;
blad zrodla nie kasuje poprzednich danych.
- GET /api/price-history (publiczny): historia, biezaca srednia z ogloszen,
od kiedy zbieramy dane oraz serie NBP i GUS.
Frontend:
- Okresy "Ostatnie 5 lat" (domyslny), "Od 2006 (NBP)", "2026 do dzis";
trzy serie z legenda, dymek ze wszystkimi zrodlami, statystyki i wnioski
z prawdziwych liczb, porownanie cen ofertowych z NBP i GUS oraz roznica
i srednia, gdy zrodla sie roznia. Ceny w "Porownaj lokalizacje".
- Poprawione dopasowanie lokalizacji ("Warszawa" otwierala "Warszawa,
Mokotów"), usuniete resztki zmyslonych cen i opcja "Lokal uzytkowy".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Maile:
- Logo jest zalacznikiem inline (cid:) zamiast obrazka z adresu serwisu.
Wczesniej w mailach z lokalnego srodowiska (i w programach blokujacych
obrazki z zewnatrz) w miejscu logo byla ikona bledu. Usuniety tekst
zastepczy, ktory dublowal napis "Polska Lokalnie".
Naglowek:
- Menu nie nachodzi na logo ani panel przy zadnej szerokosci 1110-1920 px.
Ponizej 1560 px "Ulubione" to samo serce (nazwa w dymku), mniejsze odstepy
i przycisk "Dodaj ogloszenie" bez sztywnej szerokosci; w 1101-1270 px
mniejszy napis logo i tekst przycisku.
Logowanie i rejestracja (standard routingu):
- Kazdy krok ma wlasny adres: /logowanie, /logowanie/nie-pamietam-hasla,
/rejestracja, /rejestracja/osoba-prywatna, /rejestracja/firma,
/rejestracja/sprawdz-poczte. Dzialaja F5, Wstecz/Dalej i nowa karta,
formularz czysci sie takze przy Wstecz/Dalej, a cel powrotu po
zalogowaniu nie ginie przy przejsciach miedzy krokami.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dotad rozmowy z kupujacymi istnialy tylko w przegladarce nadawcy: nic nie
trafialo na serwer, "odczytano" i odpowiedz sprzedajacego byly symulowane
timerem. Wzorem Gieldy Komunalnej:
Backend (/api/conversations):
- Conversation: jeden watek na pare (ogloszenie, kupujacy), sprzedajacy to
wlasciciel ogloszenia; tytul ogloszenia zapisany na wypadek jego usuniecia.
Wiadomosci w istniejacej tabeli messages z nowa kolumna conversation_id,
wiec rozmowa z administracja (conversation_id = null) dziala bez zmian.
- start/list/get/reply, blokada (UserBlock, w obu kierunkach), ukrycie
rozmowy u siebie (nowa wiadomosc przywraca ja obu stronom). Dostep tylko
dla stron rozmowy, filtr niedozwolonych slow jak w reszcie serwisu.
- Po zatwierdzeniu transakcji odbiorca dostaje powiadomienie w serwisie
i - jesli ma wlaczone powiadomienia o wiadomosciach - e-mail (w tle).
- /api/messages/unread-count wlicza rozmowy o ogloszeniach.
- Zgloszenie uzytkownika z rozmowy: zgloszonego, ogloszenie i tresc rozmowy
serwer bierze z bazy, nie z przegladarki.
Frontend:
- Adresy /wiadomosci/:conversationId, /wiadomosci/administracja
i /wiadomosci/nowa/:listingId zamiast rozmowy w location.state.
- Lista rozmow odswiezana co 30 s, otwarta rozmowa co 4 s.
- Zdjecia w wiadomosciach usuniete - serwer ich nie przyjmuje (rozmowa
z administracja i tak je gubila).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
scripts/cleanup-test-data.sql zostawia wylacznie konta zatorskipascal@gmail.com
i admin@softspm.com. Usuwa pozostale konta, ogloszenia spoza tych dwoch kont
oraz powiazane dane (wiadomosci, powiadomienia, ustawienia, leady, zamowienia
promocji, zgloszenia, poradniki), w tym sieroty po kontach usunietych wczesniej
z panelu admina. Domyslnie dziala na sucho (ROLLBACK), zapis tylko z -v apply=1;
przerywa, gdy ktoregos z zachowywanych kont nie ma w bazie.
DataSeeder nie dodaje juz ogloszen demo: robil to przy kazdym starcie z pusta
tabela ogloszen, wiec po wyczyszczeniu danych wracalyby przy kolejnym wdrozeniu.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Endpoint /api/auth/social byl atrapa bez prawdziwego OAuth: wydawal token
sesji dla dowolnego adresu e-mail podanego w zadaniu, bez hasla. Podanie
adresu administratora dawalo pelna sesje z rola ADMIN.
Na tym etapie logowanie ma byc wylacznie dla uzytkownikow systemu (e-mail
i haslo), wiec usuwam je w calosci:
- backend: endpoint, wpis permitAll w SecurityConfig, AuthService.socialLogin
z pomocnikami i DTO SocialLoginRequest. Enum AuthProvider zostaje, bo
istniejace konta moga miec GOOGLE/FACEBOOK.
- frontend: przyciski Google/Facebook w formularzach logowania i rejestracji,
socialLogin w AuthContext oraz osierocone style.
Test regresyjny AuthControllerTest nie uruchomi sie jeszcze na H2 - start
kontekstu wywraca sie na split_part w SQL naprawiajacym nicki (ten sam blad
dotyczy istniejacego contextLoads). Zweryfikowane recznie na stacku
z PostgreSQL: /api/auth/social -> 403, logowanie e-mailem -> 200.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Logowanie z https://polskalokalnie.pl konczylo sie bledem 403, a nie 401 -
zadanie w ogole nie docieralo do logiki uwierzytelniania. Nginx terminuje TLS
i przekazuje ruch do backendu po http, wiec Spring widzi schemat http, podczas
gdy przegladarka przysyla Origin z https. Schematy sie roznia, wiec zadanie
jest traktowane jako cross-origin i sprawdzane wzgledem listy dozwolonych
originow, na ktorej byly wylacznie adresy lokalne i LAN. Frontend pokazywal
przy tym generyczny komunikat, bo odpowiedz CORS nie jest JSON-em z pole
"message".
Dodanie domeny produkcyjnej do listy przywraca poprawne zachowanie: zle haslo
zwraca 401 z czytelnym komunikatem, poprawne 200.
Poza tym:
- name: polskalokalnie w obu plikach compose. Bez tego Compose wyprowadza nazwe
projektu z nazwy katalogu, a na serwerze kazda z trzech aplikacji siedzi w
katalogu "app" - komenda bez -p wchodzila w stack innej aplikacji i podmieniala
w nim serwis backend.
- restart: unless-stopped na serwisach produkcyjnych. Kontenery polskalokalnie
mialy polityke "no" i jako jedyne na serwerze nie wstawaly po reboocie.
W pliku deweloperskim swiadomie tego nie ma - lokalnie kontenery nie powinny
startowac same przy kazdym uruchomieniu Dockera.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nazwa i adres:
- marka "Mieszko" -> "Polska Lokalnie" w calym interfejsie (27 miejsc),
w tekstach zaleznych dodane slowo "serwis", zeby brzmialy poprawnie po polsku
- domena mieszko.pl -> polskalokalnie.pl (adresy kontaktowe, profil, udostepnianie)
- haslo pod logo: "mieszkania za darmo" -> "ogloszenia za darmo"
- backend: teksty powiadomien, dane demo i domyslna nazwa admina
- nazwa wyswietlana istniejacego admina zaktualizowana w bazie;
login admin@mieszko.pl celowo bez zmian
Naglowek:
- logo, nawigacja i panel zostaja widoczne przy przewijaniu (position: sticky,
warstwa 65 - nad listami rozwijanymi, pod lightboxem zdjec)
- sticky sidebary z top: 18-20px wyrownane do 96px, zeby nie wjezdzaly pod naglowek
Uklad stron konta:
- /ulubione, /wiadomosci i /powiadomienia otwieraja sie jak /konto/wyszukiwania -
wspolny layout AccountShell zamiast powielania ukladu w kazdej stronie
- /konto/porownanie mialo wlasny uklad (sidebar 300px, inny gap i padding),
przez co menu przeskakiwalo - wyrownane do .account-layout wraz z punktem
zwijania (1200px zamiast 1500px)
- narzedzia publiczne (/wycena, /historia-cen, /ranking-dzielnic, /negocjacje)
bez menu konta - dzialaja jak /kupno czy /wynajem
Naprawy regresji po zamianie przyciskow na linki:
- ikona ulubionych na kartach /kupno wracala do przeplywu (nadpisany
position: absolute) - teraz podnoszona jest tylko warstwa
- menu uzytkownika i "Zobacz wszystkie" w powiadomieniach: reguly CSS
celowaly tylko w <button>, przez co pozycje rozjezdzaly sie na dwie linie
Testy: 47 (bylo 41), w tym zabezpieczenie przed powrotem przeskoku menu
i przed rozjechaniem pozycji menu uzytkownika.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Kalkulator zdolności kredytowej: nowy widok z live-obliczeniami (rata
annuitetowa/malejąca, DTI/DSTI, rekomendacje, donut), wpięty w poradnik,
panel i stronę główną; pasek boczny konta dla zalogowanych.
- Moje oferty: prawdziwe ogłoszenia (/listings/mine) scalone z listą,
realne akcje Wstrzymaj/Wznów (PATCH /status, nowy status PAUSED),
Usuń (DELETE) z kontrolą właściciela; realne wyświetlenia (viewsCount)
i zapisane z ulubionych. Fix CHECK constraintu enuma w SchemaFixer.
- System powiadomień: encja Notification + serwis + kontroler + SSE
realtime (token w query param w JwtAuthFilter). Podpięte źródła
serwerowe (wiadomości, zmiana statusu ogłoszenia, zdarzenia konta)
i klienckie (ulubione, spadek ceny, spotkania, weryfikacja telefonu).
Centralny NotificationsProvider; dzwonek i strona bez zmian designu,
klikalne z deep-linkami i oznaczaniem jako przeczytane.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>