Co dokładnie monitorujecie?
Drogę zgłoszenia do osoby, a nie dostępność serwera. `GET /api/health/contact` sprawdza w jednym żądaniu dwie rzeczy: czy token kanału powiadomień jest nadal ważny — przez rzeczywiste wywołanie do dostawcy, z timeoutem 8 sekund — oraz czy dziennik zgłoszeń da się zapisać. Zwraca 200, gdy oba warunki są spełnione, i 503, gdy nie. Możesz wywołać to już teraz na tej stronie: jest publiczne właśnie dlatego, że zwraca tylko wartości logiczne.
Dlaczego formularz miałby się zepsuć, a nikt by tego nie zauważył?
Bo widoczna część nadal działa. Strona się ładuje, przycisk odpowiada, serwer zwraca 200 na wszystkich stronach — psuje się tylko ostatnie ogniwo, które nie ma interfejsu. Na tej stronie token bota powiadomień został unieważniony: dostawca odpowiadał `401 Unauthorized`, trasa zwracała 500, a zgłoszenie nie zapisywało się nigdzie. Trzy rzeczywiste awarie w około siedem godzin, widoczne tylko w dzienniku błędów procesu. Dlatego dziennik zapisuje się teraz przed dostarczeniem: nawet jeśli powiadomienie padnie, zgłoszenie istnieje.
Co się dzieje, jeśli powiadomienie nie powiedzie się po naprawie?
Zgłoszenie jest już zapisane w dzienniku z własnym identyfikatorem, a druga linia w dzienniku mówi `failed` i podaje powód. Osobie odwiedzającej odpowiada się jednoznacznie — „otrzymaliśmy zgłoszenie, ale nie mogliśmy powiadomić” — a nie fałszywym sukcesem. Kod odpowiedzi rozróżnia przyczynę: 502 oznacza, że dostawca odpowiedział źle, 503 że brakuje u nas danych uwierzytelniających. O 3 rano różnica między tymi dwoma decyduje, czy zadzwonisz do kogoś, czy nie.
Czy aktualizujecie zależności automatycznie?
Nie bez bramki. Publikacja uruchamia `npm audit` na poziomie `high` i zatrzymuje się przy podatnościach tego poziomu, jeśli kontynuacja nie zostanie wyraźnie potwierdzona; najpierw sprawdza też dostępną pamięć serwera, z progiem 500 MB, bo budowanie uruchomione na ciasnym serwerze pozostawia aplikację w stanie zatrzymania. Budowanie odbywa się od czysta: katalog budowy i zależności są usuwane, instalacja odbywa się z pliku blokady. To, co aktualizuje się automatycznie, a co przechodzi przez weryfikację człowieka, ustala się w projekcie, nie domyślnie.
Skąd wiecie, że publikacja nie zepsuła czegoś innego?
Dzięki skryptowi weryfikacyjnemu uruchamianemu po publikacji, który otwiera każdą stronę produktu i kończy się błędem, jeśli brakuje kodu 200, kotwicy pytań, kotwicy przykładu albo adresu kanonicznego. Potem sprawdza mapę witryny — czy zawiera każdy produkt i nie zawiera wersji językowych, których nie da się otworzyć — oraz `robots.txt`, żeby nie blokował zasobów renderowania. Każda weryfikacja z listy odpowiada czemuś, co już kiedyś się zepsuło. Skrypt jest przekazywany razem z projektem.
Co robicie, gdy aplikacja się zawiesza albo zużywa pamięć?
Proces uruchamia się ponownie automatycznie po przekroczeniu progu 500 MB, z 4-sekundowym opóźnieniem między próbami i wzrostem wykładniczym, ale zatrzymuje się po 10 niestabilnych restartach w krótkim czasie. To ważne: pętla awarii, która restartuje się w nieskończoność, wygląda zdrowo w panelu i po cichu zużywa serwer. Wolimy, żeby proces pozostał zatrzymany i widoczny.
Jak długo przechowujecie dane z formularza i kto może je odczytać?
24 miesiące, stosowane przez kod, a nie tylko deklarowane: próg to zmienna z domyślną wartością 730 dni, a starsze pliki są usuwane przy każdym nowym zapisie, bez harmonogramu, który można przeoczyć. Katalog ma uprawnienia `0700`, pliki `0600`, a ścieżka znajduje się poza katalogiem wersji, żeby historia przetrwała publikację. Adres IP nie jest przechowywany w całości: jest obcinany do `/24` dla IPv4 i `/48` dla IPv6, z odczytem ostatniego hopa z nagłówka, nie pierwszego — pierwszy jest wysyłany przez klienta i nic nie znaczy.
Czy znajdujecie też problemy, których nie zgłosiliśmy?
Tak się zdarza i zwykle to właśnie one są kosztowne. To samo przejście przez kod, które naprawiło formularz, wykryło dwie rzeczy, których nikt nie zgłosił: limit żądań można było całkowicie obejść, bo czytano pierwszy element z nagłówka przekierowanych adresów — dokładnie ten, który wysyła klient; oraz trasa inicjująca połączenia telefoniczne była otwarta anonimowo, na nasz koszt, choć komponent, który z niej korzystał, został zdemontowany. Obie rzeczy naprawiono i sprawdzono na produkcji. Nie możemy obiecać, że znajdziemy wszystko; możemy obiecać, że zgłosimy też to, o co nie prosiliście.
Czego nie obejmuje utrzymanie?
To nie jest usługa bezpieczeństwa z całodobowym monitoringiem ani centrum operacyjne. Nie gwarantujemy procentu dostępności bez pomiaru, który by go potwierdzał — i, żeby było jasno, w tym momencie nie publikujemy takiej liczby dla własnej strony. Nie przejmujemy odpowiedzialności za platformę zewnętrzną, do której nie mamy dostępu. I nie traktujemy strony, która odpowiada 200, jako dowodu, że wszystko działa: dokładnie to było problemem, od którego zaczęło się wszystko, co napisano wyżej.