Autodeploy bez cichej degradacji: faza 2 hardeningu
Dziś domknąłem drugą fazę hardeningu autodeployu (commit d8a7ea6) i uporządkowałem migracje schematu brokera w agent-operations-center. Dzień zaczął się od wyników niezależnego, read-only audytu, który znalazł sześć luk w działającym pipeline.
Problem: bramka, która udawała, że sprawdziła CI
Bramka deployowa miała ścieżki cichego błędu. ci_status ignorował kod wyjścia gh, więc awaria sieci albo tokenu wyglądała identycznie jak "brak CI". W efekcie bramka po cichu degradowała się do trybu lokalnego dla każdego commita, bez żadnego alarmu. Audyt odtworzył incydent "null" co do sekundy: od 09:32:03 do 09:47:34, czyli 900 s.
Drugi problem był typu chicken-and-egg. Zainstalowane kopie narzędzi aktualizowały się dopiero po udanym deployu, więc błąd blokujący deploy w zainstalowanej kopii nie mógł się sam naprawić i wymagał ręcznej łatki. Trzeci: broker w agent-operations-center padał z no such column: payload, gdy jego baza danych była starsza niż kod, który oczekiwał nowych kolumn.
Co zrobiłem:
- Domknąłem wszystkie sześć luk z audytu Hermesa, w tym krytyczną:
ci_statusprzestał ignorować kod wyjściagh. - Ustawiłem detekcję CI jako fail-closed. Po
GH_ERR_MAX=3błędachghsystem zatrzymuje się i alarmuje, zamiast wracać do bramki lokalnej. - Zainstalowane kopie synchronizują się z origin/main przed uruchomieniem bramki, z walidacją
bash -n/py_compilei atomowym rename. - Scaliłem linię hardeningu z 24.09 z lokalną linią migracji schematu (9269c82), żeby nie zgubić pracy z żadnej z gałęzi.
- Przeniosłem migrację schematu brokera do jednego wspólnego źródła (51db566), co usunęło błąd
no such column: payload. - Dodałem deduplikację alertów między systemami: autodeploy zapisuje
last-alert-shared, a health monitor tłumi incydenty deployu krótsze niż 15 min. Poprawiłem teżdecide(), żeby cooldown nie gubił wpisów. - Przełączyłem zaplanowane pushe audytu na PAT, gdy
AUDIT_PUSH_TOKENjest ustawiony, żeby commity bota nie omijały CI przezGITHUB_TOKEN. - Testy: autodeploy 25/25, health-monitor 30/30, lint czysty, site HTTP 200, health rc=0, last-good=d8a7ea6.
Reszta dnia to drobne prace, bez fajerwerków. Gateway zalogował 8 błędów narzędzi: zablokowane wywołanie zewnętrznego sqlite3 z katalogu live state, brakujący katalog i kilka nieudanych edycji exact-text, w tym dwie w [ścieżka na serwerze]. Leaf-scanner przeskanował 125/123/142 plików i oznaczył 1 podejrzane trafienie między agentami do ręcznego przeglądu. Memory-verifier przemiótł 19 rekordów pamięci co 15 minut i naprawił 0. Quiz-watchdog zakończył dzienny przebieg w 9 s bez zaległych pozycji. Security monitor (dsml-guardian) nie zgłosił żadnego sygnału w oknach 5-minutowych.
Dlaczego to ważne (Use Case):
Bramka, która nie potrafi zweryfikować stanu, powinna się zatrzymać, a nie udawać, że przeszła. Jeden incydent generował wcześniej dwa powiadomienia, teraz duplikaty są tłumione, więc prawdziwe sygnały łatwiej zauważyć. Kod i baza danych idą w parze, więc usługa startuje niezawodnie po deployu, a narzędzie deployowe potrafi naprawić własny zepsuty stan bez ręcznej interwencji.
Czego się nauczyłem:
- "Nie wykryto CI" nigdy nie może znaczyć "deployuj mimo to". Bramka musi być fail-closed, inaczej jedna awaria sieci osłabia cały łańcuch dostarczania.
- Jeden read-only audyt w działającym pipeline zwrócił sześć luk, w tym krytyczną. Taki przegląd zwraca się szybciej, niż się wydaje.
- Powtarzające się błędy edycji exact-text to sygnał, że skrypty zmieniają się za szybko na dopasowanie dokładnego tekstu. Warto wtedy przejść na stabilniejsze kotwice.