Zakres port_range 50000-50100 rezerwowal osobny port na kazde polaczenie. Test z 200 botami wszedl dokladnie w 49, a log serwera pokazal kandydata UDP tylko przy 52 polaczeniach i TCP przy wszystkich 204: kolejni uczestnicy dostawali juz tylko TCP. Zmienna UDP_PORT z zakresem nie wlaczala muxa, bo przegrywala z zakresem z pliku. Teraz udp_port: 7882 (sprawdzone lokalnie: rtc.portUDP Start 7882, End 0), nowa zmienna LIVEKIT_UDP_PORT, zeby stara LIVEKIT_UDP_RANGE w .env nie mogla przywrocic zakresu. Automatyczne wdrozenie nie dotyka profilu livekit: kontener trzeba przeladowac recznie. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
12 KiB
Test odbiorczy po wdrozeniu
Lista do wykonania w podanej kolejnosci po uruchomieniu instancji u klienta. Kazdy punkt ma oczekiwany wynik: jesli sie nie zgadza, nie przechodz dalej, bo kolejne punkty na nim polegaja.
Czas wykonania calosci: okolo 90 minut, plus czekanie na przypomnienia i na podsumowanie (do dwoch godzin, mozna w tle).
Wszystkie punkty wykonuje sie przy WLACZONYM trybie bezpiecznym wysylki, poza sekcja I, ktora ten tryb celowo wylacza na koniec. Dzieki temu zadna wiadomosc z testow nie trafi do prawdziwych ludzi.
A. Przed uruchomieniem
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| A1 | cp .env.production.example .env.production i uzupelnic |
plik istnieje, chmod 600 |
| A2 | ./scripts/check-config.sh --skip-db |
Konfiguracja w porzadku, kod wyjscia 0 |
| A3 | Sprawdzic DNS domeny: dig +short webinary.klient.pl |
adres IP serwera |
| A4 | Sprawdzic certyfikat SSL na reverse proxy klienta | waznosc powyzej 14 dni |
| A5 | Porty otwarte na firewallu: 80, 443 | dostepne z internetu |
| A6 | Przy VIDEO_PROVIDER=LIVEKIT: dodatkowo 7880, 7881 TCP oraz port UDP 7882 (tryb mux, jeden port dla wszystkich) |
dostepne z internetu |
A6 jest najczestszym przeoczeniem. Bez otwartego zakresu UDP uczestnicy wchodza do pokoju i widza liste obecnych, ale sie nie slysza. Objaw wyglada jak awaria aplikacji, a jest regula firewalla.
B. Uruchomienie
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| B1 | docker compose -f docker-compose.prod.yml --env-file .env.production up -d |
wszystkie kontenery Started |
| B2 | docker compose -f docker-compose.prod.yml ps |
postgres i minio healthy, backend healthy (do 90 s) |
| B3 | docker compose logs backend | grep "KONFIGURACJA INSTANCJI" -A 20 |
wypis stanu, Brak ostrzezen konfiguracyjnych |
| B4 | curl -s https://webinary.klient.pl/api/health |
{"status":"UP",...} |
| B5 | ./scripts/check-config.sh (juz bez --skip-db) |
kod wyjscia 0 |
Jesli B3 pokazuje ostrzezenia, przeczytaj je: kazde nazywa skutek, nie ustawienie. Ostrzezenie o wylaczonym trybie bezpiecznym na tym etapie oznacza, ze testy ponizej wysla prawdziwe wiadomosci.
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| B6 | docker compose logs backend | grep -i "haslo administratora" |
jednorazowe haslo (gdy ADMIN_PASSWORD bylo puste) |
| B7 | Zalogowac sie na /logowanie i od razu zmienic haslo |
wejscie do /panel, haslo zmienione |
C. Konfiguracja przez panel
Poczta i bramka SMS nie sa w .env: ustawia sie je w panelu, bo zmiana nie
moze wymagac dostepu do serwera.
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| C1 | Ustawienia -> E-mail: host, port, login, haslo, nazwa nadawcy | zapisane |
| C2 | Sprawdzic, ze MAIL_SAFE_MODE jest wlaczony i ma adres zastepczy |
wlaczony, adres wlasny |
| C3 | Ustawienia -> E-mail -> Test wysylki | wiadomosc dociera na adres zastepczy |
| C4 | Ustawienia -> Aplikacja: nazwa marki, adres publiczny, strefa czasowa | zapisane |
| C5 | Ustawienia -> Grafika: logo i ikona | widoczne w panelu i na stronie glownej |
| C6 | Ustawienia -> Zgody: tresc regulaminu i zgod marketingowych | zapisane, CONSENT_VERSION ustawiona |
| C7 | Przy uzyciu SMS: Ustawienia -> SMS, klucz bramki, tryb bezpieczny wlaczony | test SMS dociera na numer zastepczy |
D. Sciezka webinarowa
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| D1 | Panel -> Webinary -> nowy: tytul, termin w przyszlosci, limit miejsc | zapisany jako DRAFT |
| D2 | Dodac tresc strony w edytorze, wgrac obrazek | obrazek widoczny w podgladzie |
| D3 | Opublikowac webinar | status PUBLISHED |
| D4 | Otworzyc /w/{slug} w oknie prywatnym |
strona z trescia i formularzem zapisu |
| D5 | Zapisac sie z wlasnego adresu, zaznaczyc zgody | ekran potwierdzenia |
| D6 | Sprawdzic skrzynke | mail potwierdzajacy z dzialajacym linkiem i zalacznikiem invite.ics |
| D7 | Otworzyc invite.ics w kalendarzu |
wydarzenie z poprawna data i strefa |
| D8 | Kliknac link z maila | strona wlasnego zapisu, widoczny przycisk rezygnacji |
| D9 | Panel -> lista zapisanych | wpis widoczny, zgody z wersja i data |
| D10 | Eksport CSV listy zapisanych | plik otwiera sie w Excelu, polskie znaki poprawne |
| D11 | Dodac regule przypomnienia na za 5 minut i odczekac | przypomnienie dociera (na adres zastepczy) |
| D12 | Wejsc na /spotkanie/{token} z linku |
przedpokoj z tytulem i imieniem do potwierdzenia |
| D13 | Wejsc na sale, wyslac wiadomosc na czacie | wiadomosc widoczna, autor jako imie i inicjal |
| D14 | Zadac pytanie i zaglosowac na nie z drugiej przegladarki | licznik glosow rosnie o 1, drugi glos tej samej osoby odrzucony |
| D15 | Panel prowadzenia: zatwierdzic pytanie | pytanie pojawia sie u uczestnika |
| D16 | Zglosic sie do zabrania glosu, przyznac glos z panelu | mikrofon uczestnika dziala |
| D17 | Zakonczyc webinar, zmienic termin na przeszly, odczekac SUMMARY_DELAY_MINUTES |
podsumowanie dociera raz, nie dwa razy |
| D18 | Wystawic certyfikat uczestnikowi z odnotowana obecnoscia | PDF z polskimi znakami w nazwisku |
| D19 | Otworzyc /certyfikat/{numer} w oknie prywatnym |
weryfikacja pokazuje numer, tytul, imie z inicjalem, bez adresu e-mail |
D18 jest krytyczny. Certyfikat z polamanym nazwiskiem jest bezuzyteczny, a blad osadzania czcionki widac wylacznie na gotowym pliku.
E. Sciezka Akademii
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| E1 | Otworzyc / w oknie prywatnym |
strona glowna Akademii, przycisk Zaloguj sie |
| E2 | Panel -> Kursy -> nowy kurs z modulem i lekcja wideo | zapisany jako DRAFT |
| E3 | Wgrac nagranie lekcji, ustawic dlugosc | plik widoczny |
| E4 | Opublikowac kurs, ustawic cene | widoczny na /kursy |
| E5 | Zarejestrowac konto kursanta na /rejestracja |
mail z linkiem potwierdzajacym |
| E6 | Potwierdzic adres z linku | konto aktywne, wejscie na /moje-konto |
| E7 | Zapisac sie na kurs darmowy | dostep od reki, kurs na pulpicie |
| E8 | Otworzyc odtwarzacz, obejrzec lekcje do konca | lekcja oznaczona jako ukonczona, postep rosnie |
| E9 | Przewinac nagranie w polowie | przewijanie dziala (naglowek Range) |
| E10 | Dodac quiz do lekcji, rozwiazac go jako kursant | wynik policzony, poprawne odpowiedzi nie sa widoczne w zrodle strony przed koncem |
| E11 | Ukonczyc wszystkie lekcje wymagane | kurs COMPLETED, certyfikat wystawiony automatycznie |
| E12 | Sprawdzic mail o ukonczeniu | zalacznik PDF, dzialajacy link do pulpitu |
| E13 | Panel -> Kursanci -> szczegoly | postep, zgody z historia, ostatnia aktywnosc |
| E14 | Zalogowac sie adresem majacym konto w obu swiatach | ekran wyboru: Moje konto i Panel |
F. Czego NIE DA SIE sprawdzic lokalnie
Te punkty musza zostac wykonane po wdrozeniu, bo lokalnie nie ma jak ich przejsc. Kazdy z nich to droga, ktora dotad nie zostala przebyta end-to-end.
F1. Notyfikacja ITN Autopay
Operator laczy sie z naszym serwerem, wiec wymaga publicznej domeny z waznym certyfikatem. Na localhost nie da sie tego wywolac.
| Krok | Oczekiwany wynik |
|---|---|
Ustawic AUTOPAY_MODE=TEST, ServiceID i klucz ze srodowiska testowego operatora |
Autopay: konfiguracja kompletna w wypisie startowym |
| Zamowic kurs platny jako kursant | przekierowanie na bramke testowa |
| Zaplacic karta testowa operatora | powrot na /kurs/{slug}/platnosc |
| Odczekac na ITN (do kilkudziesieciu sekund) | strona sama pokazuje nadany dostep |
| Panel -> Zamowienia | status PAID, w dzienniku wpis notyfikacji |
| Powtorzyc notyfikacje z panelu operatora | dostep nadany raz, drugi komunikat potwierdzony bez zmiany |
| Sprobowac zaplacic kwota inna niz w zamowieniu | notyfikacja odrzucona, wpis w dzienniku |
Dopiero po przejsciu wszystkich krokow przelaczyc AUTOPAY_MODE=PRODUCTION.
Wypis startowy pokaze wtedy ostrzezenie o prawdziwych pieniadzach: to jest
oczekiwane i ma zostac zauwazone.
F2. Nagrywanie przez Egress
Lokalnie proces zatrzymywal sie na tym, ze szablon nie subskrybowal zadnej sciezki:
do domkniecia potrzebny jest publikujacy uczestnik w tej samej sieci co Egress,
czego nie da sie zestawic na Docker Desktop przy jednym NODE_IP.
| Krok | Oczekiwany wynik |
|---|---|
docker compose ... --profile livekit up -d |
cztery kontenery wideo dzialaja |
docker compose logs livekit-egress | head -30 |
polaczenie z Redisem, brak bledow ICE |
| Zestawic spotkanie z dwoma uczestnikami, jeden publikuje obraz | obraz i dzwiek plyna w obie strony |
| Uruchomic nagrywanie z panelu prowadzenia | wpis w recordings ze statusem DOWNLOADING |
| Zakonczyc nagrywanie, odczekac | status READY, plik w MinIO |
| Odtworzyc nagranie z panelu, przewinac | odtwarza sie i przewija |
Gdy nagrywanie nie ruszy: reczne wgranie pliku dziala i jest droga awaryjna. Nie blokuje to wdrozenia.
F3. Webhook dostawcy wideo
| Krok | Oczekiwany wynik |
|---|---|
Ustawic VIDEO_WEBHOOK_SECRET w panelu i ten sam sekret u dostawcy |
zapisane |
| Wywolac zdarzenie u dostawcy (zakonczenie nagrania) | wpis w logu backendu, odpowiedz 200 |
Wyslac zadanie z blednym sekretem: curl -X POST .../api/webhooks/video/livekit -d '{}' |
404, nie 403 |
Odpowiedz 404 jest celowa: 403 pozwalalaby sprawdzic, ktore webinary istnieja.
F4. Zajawki w komunikatorach
Wymagaja publicznego adresu: robot musi pobrac strone z internetu.
| Krok | Oczekiwany wynik |
|---|---|
Wkleic https://webinary.klient.pl/w/{slug} na Slacku albo Facebooku |
zajawka z tytulem webinaru i opisem |
curl -A "facebookexternalhit/1.1" https://webinary.klient.pl/w/{slug} |
HTML z og:title zawierajacym tytul |
| To samo dla webinaru w stanie DRAFT | 404, wersje robocze nie moga wyciekac |
F5. Poczta wychodzaca do prawdziwych odbiorcow
| Krok | Oczekiwany wynik |
|---|---|
| Sprawdzic rekordy SPF i DKIM domeny nadawcy | skonfigurowane |
| Wyslac test na adres w Gmailu i w Outlooku | wiadomosc nie trafia do spamu |
| Sprawdzic naglowki dostarczonej wiadomosci | SPF pass, DKIM pass |
G. Kopia zapasowa
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| G1 | ./scripts/backup.sh |
katalog w ./backups, pliki baza.dump i minio.tar.gz niepuste |
| G2 | Sprawdzic INFO.txt w kopii |
data, nazwa bazy, wersja obrazu |
| G3 | Dodac wpis do crontab (patrz README) |
crontab -l pokazuje wpis |
| G4 | Odtworzyc kopie na maszynie testowej, nie na produkcji | dane zgodne ze stanem z chwili kopii |
G4 jest obowiazkowy. Kopia, ktorej nigdy nie odtworzono, nie jest kopia zapasowa, tylko plikiem o nieznanej zawartosci.
H. Bezpieczenstwo
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| H1 | curl -s https://webinary.klient.pl/api/admin/webinars |
401, nie lista |
| H2 | nmap -p 5432,9000,9001 webinary.klient.pl |
porty zamkniete z internetu |
| H3 | Otworzyc /swagger-ui.html |
404 albo 403 (SWAGGER_ENABLED=false) |
| H4 | Zalogowac sie 6 razy blednym haslem | blokada po 5 probie, komunikat taki sam jak przy zlym hasle |
| H5 | Sprobowac pobrac certyfikat cudzym tokenem zapisu | 404 |
| H6 | Sprawdzic /api/public/config |
wylacznie nazwa marki, adres i strefa, zadnych sekretow |
I. Przelaczenie na ruch produkcyjny
Dopiero po przejsciu wszystkich punktow powyzej.
| # | Czynnosc | Oczekiwany wynik |
|---|---|---|
| I1 | Skasowac dane testowe: webinary, kursy, zamowienia, kontakty testowe | listy puste albo z prawdziwymi danymi |
| I2 | Nie kasowac app_settings ani konta administratora |
konfiguracja zachowana |
| I3 | Ustawienia -> E-mail: wylaczyc MAIL_SAFE_MODE |
zapisane |
| I4 | Przy uzyciu SMS: wylaczyc SMS_SAFE_MODE |
zapisane |
| I5 | Zrestartowac backend i przeczytac wypis startowy | ostrzezenie o wylaczonym trybie bezpiecznym: oczekiwane |
| I6 | Wyslac jedna prawdziwa wiadomosc testowa do siebie | dociera na wlasciwy adres |
| I7 | ./scripts/backup.sh na czysto |
kopia stanu wyjsciowego |
Po I3 kazda wysylka idzie do prawdziwych odbiorcow. Od tego momentu dane testowe z terminem w przeszlosci moga uruchomic scheduler i wyslac wiadomosci do osob z bazy: dlatego I1 jest przed I3, a nie po.