# Checklista wdrożeniowa — Backend Piekarnia Jędryka

Dokument opisuje kroki niezbędne do bezpiecznego wystawienia backendu
(Slim 4 / PHP / MySQL) na hosting klienta. Migracje bazy danych są
wykonywane samodzielnie przez developera — poniżej jest tylko **lista
kontrolna**, jakie tabele/kolumny muszą istnieć (patrz sekcja 4).

---

## 1. DocumentRoot / webroot

⚠️ **Najważniejszy punkt.** DocumentRoot domeny/subdomeny na hostingu
**musi** wskazywać na katalog `backend/public/`, a NIE na `backend/`.

Jeśli hosting nie pozwala ustawić DocumentRoot na podkatalog (częste przy
hostingach współdzielonych, gdzie root to zawsze `public_html/`), wgraj
zawartość `backend/public/` do `public_html/`, a resztę backendu
(`src/`, `vendor/`, `.env`, `migrations/`, `dev-tools/`, `composer.json`)
**poza** `public_html/` (np. jeden katalog wyżej) i zmodyfikuj ścieżki
`require` w `public/index.php` odpowiednio (obecnie `__DIR__ . '/../vendor/autoload.php'`
itd. — zależne od finalnej struktury katalogów na hostingu).

Dodatkowa warstwa ochrony: `public/.htaccess` blokuje dostęp HTTP do
katalogów `vendor/`, `src/`, `dev-tools/`, `migrations/`, `storage/`
oraz do plików `.env`, `.git*`, `*.sql`, `*.log`, `*.lock`, gdyby
znalazły się przypadkiem pod webrootem.

## 2. Pliki, które NIE powinny trafić na serwer produkcyjny

Nie wgrywaj na hosting (albo usuń po wgraniu, jeśli transferujesz cały
katalog `backend/`):

- `.git/` — historia repozytorium, może zawierać stare sekrety
- `AUDYT_BACKEND.md` — dokument wewnętrzny, nieistotny dla produkcji
- `dev-tools/` — skrypty CLI (migracje, scraping, testy) — nie są częścią
  aplikacji HTTP, ale trzymaj je poza webrootem; jeśli nie są potrzebne
  na produkcji, można je pominąć przy wgrywaniu
- `.env.example` — wzorzec, prawdziwy `.env` twórz ręcznie na serwerze
- `composer.lock` — można wgrać (zalecane, zapewnia identyczne wersje
  zależności), ale nie jest wymagany do działania

Pliki/katalogi **wymagane** na produkcji:

- `public/` (cała zawartość — to jest webroot)
- `src/`
- `vendor/` (wygenerowane przez `composer install`, patrz pkt 5)
- `.env` (utworzony ręcznie na serwerze, patrz pkt 3)
- `composer.json`

## 3. Plik `.env` na produkcji

Skopiuj `.env.example` → `.env` na serwerze (NIE commituj `.env` do
repo) i uzupełnij:

```
APP_ENV=production
JWT_SECRET=<wygenerowany losowy ciąg min. 32 znaki>
DB_HOST=<host bazy danych klienta>
DB_NAME=<nazwa bazy>
DB_USER=<user>
DB_PASS=<hasło>
CORS_ALLOWED_ORIGINS=https://domena-klienta.pl,https://www.domena-klienta.pl
TRUSTED_PROXY_IPS=<uzupełnij TYLKO jeśli hosting stoi za reverse proxy/load balancerem>
MAIL_DRIVER=smtp
MAIL_HOST=...
MAIL_PORT=587
MAIL_USERNAME=...
MAIL_PASSWORD=...
MAIL_FROM_ADDRESS=noreply@domena-klienta.pl
MAIL_FROM_NAME="Formularz kontaktowy"
MAIL_TO_ADDRESS=<adres odbiorczy klienta>
```

Wygenerowanie `JWT_SECRET`:

```bash
openssl rand -hex 32
```

**Uwaga do `CORS_ALLOWED_ORIGINS`:** wpisz dokładne originy frontendu
(z `https://`, bez końcowego `/`), włącznie z wersją `www.` jeśli
klient używa obu. Panel administracyjny (`/admin`) jest serwowany
przez ten sam backend, więc nie wymaga osobnego wpisu w CORS.

## 4. Baza danych (wykonujesz samodzielnie — tylko lista kontrolna)

Zweryfikuj, że baza danych klienta ma zastosowane wszystkie migracje
z katalogu `migrations/`:

- `create_contact_messages_table.sql`
- `add_type_to_contact_messages.sql`
- `create_gallery_photos_table.sql`
- `create_history_table.sql`
- `create_rate_limits_table.sql`
- `add_is_active_to_admins.sql` (kolumna `is_active` w tabeli `admins`
  — wymagana przez `AuthMiddleware`, bez niej logowanie/autoryzacja
  admina **nie zadziała**)

Upewnij się też, że tabela `admins` ma przynajmniej jednego aktywnego
użytkownika (`is_active = 1`) z hasłem zahaszowanym `password_hash()`.

## 5. Instalacja zależności (Composer)

Na serwerze (lub lokalnie i wgraj `vendor/` przez FTP/SFTP, jeśli
hosting nie ma dostępu SSH/Composera):

```bash
composer install --no-dev --optimize-autoloader
```

`--no-dev` pomija zależności deweloperskie (obecnie projekt ich nie
ma, ale to dobra praktyka na przyszłość), `--optimize-autoloader`
przyspiesza autoloading klas na produkcji.

## 6. Uprawnienia katalogów/plików

- `storage/logs/` — musi być zapisywalny przez PHP (błędy aplikacji
  logowane tu w trybie produkcyjnym): `chmod 775 storage/logs` (katalog
  tworzy się automatycznie przy pierwszym błędzie, jeśli nie istnieje —
  warto go utworzyć ręcznie z góry, żeby uniknąć problemów z
  uprawnieniami przy pierwszym zapisie)
- `public/uploads/` — musi być zapisywalny przez PHP (upload zdjęć
  produktów/galerii/hero/about): `chmod -R 775 public/uploads`
- Reszta kodu (`src/`, `vendor/`, `public/*.php`) — wystarczą
  standardowe uprawnienia do odczytu, PHP nie musi w nie zapisywać

Właściciel plików powinien być zgodny z użytkownikiem, pod którym
działa PHP-FPM/Apache na hostingu (zwykle ustawiane automatycznie przy
wgrywaniu przez panel hostingowy/FTP z odpowiednim kontem).

## 7. HTTPS / HSTS

`public/.htaccess` ma przygotowany (zakomentowany) nagłówek
`Strict-Transport-Security`. **Odkomentuj go dopiero po potwierdzeniu**,
że certyfikat SSL działa poprawnie na domenie produkcyjnej — włączenie
HSTS przy niedziałającym HTTPS może utrudnić dostęp do strony w
przeglądarkach, które go zapamiętały.

Backend (`ResponseHelper`, `public/index.php`) automatycznie dodaje
nagłówek HSTS do odpowiedzi API, gdy `APP_ENV=production` **i** żądanie
faktycznie przyszło po HTTPS (wykrywane przez `$_SERVER['HTTPS']` lub
`X-Forwarded-Proto` — to drugie tylko ma sens, jeśli hosting stoi za
reverse proxy).

## 8. Weryfikacja końcowa po wdrożeniu

- [ ] `https://api.domena-klienta.pl/api/settings` zwraca JSON (200)
- [ ] `https://api.domena-klienta.pl/dev-tools/get_schema.php` **nie
  jest dostępny** (404/403) — potwierdza poprawny DocumentRoot
- [ ] `https://api.domena-klienta.pl/.env` **nie jest dostępny**
  (403/404)
- [ ] `https://api.domena-klienta.pl/uploads/products/` **nie** pokazuje
  listy plików (directory listing wyłączony)
- [ ] Logowanie do panelu admina (`/api/login`) działa i zwraca token
- [ ] Upload zdjęcia (np. w Galerii) w panelu admina działa poprawnie
- [ ] Formularz kontaktowy na froncie wysyła zgłoszenie (sprawdź
  `storage/logs/mail.log` jeśli `MAIL_DRIVER=log`, lub realną skrzynkę
  jeśli `MAIL_DRIVER=smtp`)
- [ ] Nagłówki odpowiedzi API zawierają `Access-Control-Allow-Origin`
  z prawidłową domeną frontendu (sprawdź w DevTools → Network)
- [ ] Błąd 500 (np. przez chwilowe wyłączenie bazy) **nie** pokazuje
  stack trace'u klientowi — tylko generyczny komunikat JSON
