# Opolska Liga Orlika — pierwsze uruchomienie

To pierwsza działająca wersja aplikacji OLO: ciemny grafit, limonka, responsywne widoki, tabela, strzelcy, terminarz, administrator i sędzia. Kod należy do tej paczki i można go rozwijać we własnym środowisku.

**Domyślnie cała aplikacja jest PRYWATNA. Nie ma żadnego domyślnego hasła.**

Osoba, która wpisze adres domeny, zobaczy tylko estetyczny ekran „Strona w przygotowaniu” i formularz logowania właściciela. Mecze, tabele, nazwiska i panele pozostaną za logowaniem. To serwerowa kontrola dostępu; ukrycie przed Google jest dodatkowym ustawieniem.

Ta paczka nie zmienia ustawień Twojej istniejącej domeny. Ochrona działa po uruchomieniu aplikacji na serwerze obsługującym domenę. W tym zadaniu niczego nie wdrażano ani nie zmieniano w DNS.

## 1. Sprawdź hosting

Potrzebujesz **Node.js 24.x i trwałego dysku** albo serwera z **Dockerem i Docker Compose**. Baza SQLite jest wbudowana — nie potrzeba osobnego MySQL, usługi chmurowej ani płatnego API.

Zwykłe wgranie plików przez FTP na hosting obsługujący wyłącznie PHP nie uruchomi tej aplikacji. Hosting typu serverless bez trwałego dysku też nie jest odpowiedni dla tej konfiguracji SQLite. W takiej sytuacji potrzebne jest dopasowanie wdrożenia do hostingu.

## 2. Uruchom na swoim komputerze

Zainstaluj [Node.js 24 LTS](https://nodejs.org/en/download), rozpakuj ZIP i otwórz terminal w katalogu `opolskaligaorlika`.

```sh
npm run setup
npm start
```

Konfigurator poprosi o Twój login i własne hasło (minimum 14 znaków). Dla pracy na komputerze pozostaw adres `http://localhost:3000`. Hasło podczas wpisywania jest maskowane, a zapisywany jest jego hash. Nie wysyłaj swojego hasła w wiadomości.

Możesz wczytać przykładowe drużyny i mecze, aby od razu obejrzeć aplikację. **To fikcyjne dane demonstracyjne, nie oficjalne wyniki OLO.** Bez demonstracji startujesz z czterema pustymi ligami i edycją „Jesień 2026”.

Otwórz `http://localhost:3000`, zaloguj się i korzystaj z aplikacji. Instalacja pakietów (`npm install`) nie jest potrzebna — aplikacja nie ma zewnętrznych zależności.

## 3. Domena opolskaligaorlika.pl i HTTPS — wariant Docker/VPS

Ten wariant wymaga własnego serwera z Dockerem, dostępem do terminala i możliwością ustawienia rekordów DNS. Nie wykonano go automatycznie.

1. Skopiuj katalog aplikacji do prywatnego katalogu na serwerze, poza `public_html` i innym katalogiem udostępnianym przez serwer WWW.
2. Ustaw rekord `A` domeny `opolskaligaorlika.pl` na adres IPv4 tego serwera. Dla `www` ustaw rekord `CNAME` na `opolskaligaorlika.pl`. Jeżeli masz rekord `AAAA`, musi wskazywać działający adres IPv6 tego samego serwera; usuń nieaktualny rekord. Zachowaj rekordy poczty.
3. Udostępnij porty 80 i 443. Jeśli obsługuje je już inny serwer WWW, dostosuj reverse proxy zamiast uruchamiać drugi serwer na tych samych portach.
4. W katalogu projektu uruchom `npm run setup`. Jako adres aplikacji wpisz **`https://opolskaligaorlika.pl`**. Ustaw własne hasło i pozostaw `PRIVATE_MODE=true`.
5. Uruchom:

```sh
docker compose up -d --build
docker compose logs --tail=50
```

Jeśli na serwerze masz tylko Dockera, konfigurator można uruchomić na swoim komputerze, a wygenerowany `.env` bezpiecznie przesłać na serwer. Ustaw w nim docelowy `APP_ORIGIN=https://opolskaligaorlika.pl`, a nie localhost.

Dołączony Caddy obsługuje HTTPS i przekierowanie z HTTP po prawidłowym skierowaniu domeny. `www` przekierowuje na adres bez `www`. Sama aplikacja nie wystawia portu 3000 do internetu. Dane i certyfikaty pozostają w osobnych trwałych woluminach.

**Sprawdzenie ochrony po wdrożeniu:**

- W zwykłym oknie zaloguj się swoim hasłem: widzisz ligę i panele.
- Otwórz domenę w nowym oknie incognito: widzisz tylko ekran w przygotowaniu.
- Otwórz `/api/state` i `/assets/app.js` w incognito: dostaniesz odmowę dostępu, bez danych ligi.
- Wyloguj się: poprzednia sesja przestaje działać.

## 4. Przygotuj prawdziwe rozgrywki

Wejdź w **Panel organizatora** (na telefonie: **Więcej → Panel organizatora**).

1. Jeśli wybrałeś demonstrację, najpierw obejrzyj widoki. Następnie w **Ustawienia → Dane rozgrywek** usuń demo. To czyści wszystkie drużyny, zawodników, mecze i zdarzenia utworzone podczas demonstracji, także dodane samodzielnie. Konta, ligi i edycje zostają.
2. W **Ustawienia** dodaj potrzebną edycję i ewentualne kolejne poziomy ligowe.
3. Wybierz edycję i ligę na górze ekranu, a następnie w **Drużyny** dodaj uczestników. Istniejące drużyny możesz przypisywać do kolejnych edycji.
4. Uzupełnij **Zawodników** (nazwisko, numer i drużyna). Każdy aktywny numer jest unikalny w drużynie. Dezaktywacja zachowuje historię zawodnika.
5. W **Sędziowie** utwórz indywidualne konta i przekaż hasła właściwym osobom prywatnie.
6. W **Terminarz** dodaj mecze, boiska i obsadę. System odrzuca kolizje boiska, sędziego i drużyn. Terminy w formularzu używają strefy urządzenia, a terminarz wyświetla czas polski.
7. W **Ustawienia → Punktacja i tabela** dopasuj zasady do regulaminu OLO. Domyślne 3/1/0 i bilans bramek są konfiguracją przykładową. Nie twierdzimy, że odtwarzają pełny oficjalny regulamin.

Punktacja jest obecnie wspólna dla wszystkich edycji. Przy równych punktach można wybrać bilans bramek albo małą tabelę spotkań bezpośrednich. Dalsze kryteria to bilans ogólny, gole strzelone i nazwa. Walkowery, ujemne punkty, baraże i automatyczne awanse nie są jeszcze osobno modelowane.

## 5. Sędzia i wyniki na żywo

W trybie prywatnym **tylko konto właściciela może się zalogować**. Konta sędziów można przygotować, ale ich logowanie zostanie dopuszczone dopiero po otwarciu aplikacji. Właściciel może wcześniej sam testować wszystkie spotkania.

Sędzia po zalogowaniu wybiera swój mecz, rozpoczyna zegar i zapisuje gole ze strzelcą, gole samobójcze i kartki. Może zatrzymać czas, zakończyć pierwszą połowę, rozpocząć drugą, cofnąć ostatnie zdarzenie i zatwierdzić końcowy protokół. Może zmieniać wyłącznie przypisane mu mecze. Właściciel może ponownie otworzyć zakończony mecz do korekty.

Kibice dostają aktualizacje przez odpytywanie serwera co 5 sekund. Zegar jest oparty o czas na serwerze i działa po zamknięciu karty. Tabela i strzelcy uwzględniają dopiero zatwierdzone mecze. Gole samobójcze zmieniają wynik, ale nie klasyfikację strzelców.

**Zapis zdarzeń wymaga internetu.** Ta wersja nie ma kolejki offline ani powiadomień push. Po błędzie formularz zostaje na ekranie. Powtórzenie tego samego zapisu nie tworzy drugiego gola. Przy równoczesnej zmianie na innym urządzeniu system prosi o ponowienie po odświeżeniu danych.

## 6. Dopiero kiedy chcesz otworzyć stronę

W pliku `.env` zmień dokładnie:

```env
PRIVATE_MODE=false
```

Następnie odtwórz kontener, żeby wczytał nowe środowisko:

```sh
docker compose up -d --force-recreate app
```

Przy zwykłym `npm start` zatrzymaj proces i uruchom go ponownie. Część dla kibiców stanie się publiczna. Panel organizatora i zapisy sędziów dalej wymagają logowania i właściwej roli.

Ponowne ustawienie `PRIVATE_MODE=true` i restart zamkną aplikację. Samo usunięcie `noindex`, edycja HTML czy zmiana widoczności przycisków nie otwierają dostępu.

## 7. Kopie i zmiana hasła

**Uruchomienie bez Dockera:**

```sh
npm run backup
```

Plik powstanie w `backups/`. To spójna kopia całej bazy, również kont. W panelu można pobrać dodatkowo JSON z danymi sportowymi, ale JSON nie zastępuje pełnej kopii SQLite.

**Docker:**

```sh
docker compose exec app node scripts/backup.mjs
docker compose cp app:/app/backups ./kopie-olo
```

Przenieś kopie w bezpieczne miejsce poza serwer. Nie używaj `docker compose down -v`, bo `-v` usuwa trwałe woluminy, w tym bazę. Zwykłe przebudowanie aplikacji zachowuje woluminy.

Odtworzenie: zatrzymaj aplikację, skopiuj wybraną kopię jako `data/olo.sqlite` (w Dockerze do woluminu `olo_data`), usuń stare pliki `olo.sqlite-wal` i `olo.sqlite-shm` wyłącznie przy zatrzymanym procesie, zachowaj właściciela plików i uruchom aplikację. Kopia musi pochodzić z zaufanego źródła. Nie odtwarzaj na pracującej bazie.

**Zmiana hasła właściciela:**

```sh
npm run setup -- --reset
```

Wpisz ponownie docelowy adres aplikacji i nowe hasło, potem zrestartuj aplikację (dla Dockera: `docker compose up -d --force-recreate app`). Zmiana hasha unieważnia poprzednie sesje właściciela. Konfigurator ponownie ustawia tryb prywatny. Baza z meczami pozostaje. W tej wersji hasło sędziego wymienia się przez utworzenie nowego konta i zablokowanie poprzedniego.

## 8. Co sprawdzono i co jest dalej

Sprawdzono testami automatycznymi: hasła, domyślne zamknięcie, brak danych i kodu panelu bez logowania, Origin i CSRF, role, ograniczenie prób logowania, tworzenie danych, kolizje terminów, gole i samobóje, duplikaty zapisu, cofanie, zegar i połowy, zatwierdzanie, korekty, tabelę, strzelców, eksport i zachowanie danych po restarcie. Sprawdzono także narzędzie kopii SQLite.

W środowisku tworzenia paczki nie działał serwer podglądu przeglądarkowego. **Pełna kontrola wizualna i obsługa na fizycznym telefonie pozostają do sprawdzenia po uruchomieniu.** Wdrożenie Docker/Caddy i certyfikat na Twojej domenie nie zostały wykonane ani przetestowane na rzeczywistym serwerze.

To wersja startowa do dalszej pracy: herby mają postać kolorowych tarcz ze skrótem. Nie ma jeszcze przesyłania własnych herbów, obecności w składach meczowych, automatycznego generatora terminarza, transferów z historią przynależności, importu wyników, transmisji wideo ani resetu hasła przez e-mail. Kod nie łączy się z MOSiR i nie pobiera samodzielnie oficjalnych danych.

Materiały techniczne: [SQLite w Node.js](https://nodejs.org/docs/latest-v24.x/api/sqlite.html), [crypto w Node.js](https://nodejs.org/docs/latest-v24.x/api/crypto.html), [Caddy — HTTPS](https://caddyserver.com/docs/automatic-https).

## Pliki

```text
server.mjs           Serwer, API, logowanie i kontrola dostępu
src/                 Baza, hasła, walidacja i reguły sportowe
public/              Responsywny interfejs i lokalne zasoby
scripts/             Konfiguracja hasła i kopie zapasowe
tests/               Testy automatyczne
deploy/              Reverse proxy Caddy
compose.yaml         Aplikacja, HTTPS i trwałe woluminy
Dockerfile           Obraz aplikacji Node.js 24
.env.example         Pusta konfiguracja — bez hasła
design/              Wcześniejsze wizualizacje jako punkt odniesienia
```

Nie udostępniaj katalogu projektu jako statycznej strony. Serwer WWW ma kierować ruch do uruchomionej aplikacji. Prawdziwy `.env`, baza, kopie i pliki z hasłami nie są częścią dostarczonego ZIP-a.
