8 min

Które bramki pull requestów agentów powinny blokować scalenie?

Użyj siedmiu mierzalnych bramek pull requestów agentów, aby zatrzymać niebezpieczny kod: testów, CodeQL, zależności, sekretów, autoryzacji, migracji i wycofania.

Które bramki pull requestów agentów powinny blokować scalenie?

Agent może przygotować czysty diff, przekonujący opis i kod, który przejdzie szybką recenzję, a mimo to pozostawić aplikację podatną na atak lub niemożliwą do odzyskania. Decyzja o scaleniu powinna więc opierać się na dowodach, które repozytorium potrafi zmierzyć, a nie na tym, jak pewnie brzmi agent ani jak mała wydaje się łatka.

Stosuję siedem blokujących bramek: testy, CodeQL, przegląd zależności, skanowanie sekretów, kontrole autoryzacji, próbę migracji i weryfikację wycofania. Każda odpowiada na inne pytanie o możliwą awarię. Zielony zestaw testów nie dowodzi, że nowy pakiet jest bezpieczny, a czysty wynik analizy statycznej nie mówi nic o tym, czy migracja bazy blokuje najbardziej obciążoną tabelę.

Te bramki dotyczą tak samo zmian ludzi i agentów. Autorstwo agenta zmienia liczbę, tempo i charakter błędów, ale nie uzasadnia osobnej, słabszej ścieżki. Jeśli proponowana zmiana nie potrafi dostarczyć takich samych dowodów jak każdy inny pull request, nie jest gotowa do scalenia.

Bramka musi dawać dowód, a nie radę

Bramka scalania powinna zwracać odtwarzalny wynik zaliczenia albo niepowodzenia dla dokładnego commita, który trafi do chronionej gałęzi. Komentarz „proszę sprawdzić tę zależność” jest radą. Wymagana kontrola, która wskazuje pakiet, wersję, ostrzeżenie i próg istotności, jest dowodem.

To rozróżnienie ma znaczenie, ponieważ wiele funkcji bezpieczeństwa domyślnie zgłasza problemy dopiero po chwili, w której można było podjąć właściwą decyzję. Skaner może utworzyć alert, wysłać e-mail lub otworzyć zgłoszenie, gdy przycisk scalania nadal jest dostępny. Zespoły mówią wtedy, że skanowanie jest „włączone”, choć nie potrafi zatrzymać zmiany. Dla każdej bramki sprawdź cztery właściwości:

  • Uruchamia się na bieżącym commicie głównym pull requesta.
  • Ochrona gałęzi wymaga jej nazwanego wyniku.
  • Pominięte, przekroczone czasowo lub przerwane zadanie nie liczy się jako zaliczenie.
  • Wynik zapisuje wystarczająco dużo szczegółów, aby odtworzyć decyzję.

Trzymaj politykę w repozytorium. Mały manifest ułatwia recenzję bardziej niż zbiór ustawień znanych wyłącznie administratorom:

merge_gates:
  tests: required
  codeql: required
  dependency_review: required
  secret_scan: required
  authorization: required
  migration_rehearsal: required_when_changed
  rollback_verification: required

Wartość required_when_changed nie jest luką. Oznacza, że bramka najpierw wykrywa odpowiednie pliki, a następnie wykonuje próbę albo zapisuje czysty wynik „nie dotyczy”. Nie pozwalaj filtrom ścieżek pozostawiać wymaganej kontroli na stałe w stanie oczekiwania ani agentowi samodzielnie uznawać, że jego ryzykowna zmiana jest zwolniona.

Ogranicz uprawnienia workflow do minimum potrzebnego każdemu zadaniu. Kod pull requesta to niezaufane dane wejściowe, nawet gdy gałąź należy do Twojej organizacji. Bramka, która udostępnia token zapisu lub sekret produkcyjny kodowi, który bada, może stworzyć problem gorszy od tego, który miała wykryć.

Chroń tożsamość kontroli równie starannie jak jej logikę. Reguły gałęzi zwykle wymagają nazwy statusu, więc dwa workflow, które mogą zgłosić tę samą nazwę, mogą pozwolić słabszemu zadaniu spełnić regułę. Nadaj zadaniu polityki unikalną nazwę, ogranicz osoby mogące zmieniać jego workflow i wymagaj recenzji od właścicieli tego pliku. Gdy kolejka scalania tworzy nowy commit scalający, uruchom bramki ponownie dla tego commita albo użyj funkcji platformy, która wiąże wyniki z rewizją w kolejce. Dowód dla wczorajszego commita głównego nie jest dowodem dla dzisiejszego scalenia.

Traktuj konfigurację bramek jako wrażliwy kod. Pull request, który zmienia próg, usuwa ścieżkę, obniża wersję pakietu zapytań lub dodaje wyjątek, zmienia znaczenie każdego późniejszego zielonego wyniku. Wyraźnie pokazuj diffy polityki i wymagaj opiekuna, który rozumie daną kontrolę. Agent może zaproponować taką zmianę, lecz nie powinien otrzymać łatwiejszego przejścia tylko dlatego, że edytuje mechanizm, który go ocenia.

Testy blokują widoczne regresje

Bramka testów powinna blokować każdą zmianę, która psuje określone zachowanie w obsługiwanych wersjach środowiska uruchomieniowego i bazy danych. Musi używać tych samych danych wejściowych kompilacji co commit scalający, w tym zablokowanych zależności, wygenerowanych plików, flag funkcji i stanu schematu.

Agenci szczególnie dobrze potrafią spełnić najbliższe asercje. Mogą dodać obejście, które zazieleni jeden test, jednocześnie psując obsługę błędów, stronicowanie, współbieżność lub sąsiedni kontrakt API. Wymagaj, aby PR dodawał lub zmieniał testy, gdy zmienia zachowanie, lecz nie oceniaj jakości liczbą nowych linii testów. Sprawdź, czy test zakończyłby się błędem, gdyby implementację usunięto lub cofnięto.

Przydatna bramka testów ma warstwy o osobnych nazwach:

  • Testy jednostkowe dla lokalnej logiki i przypadków brzegowych.
  • Testy integracyjne dla kontraktów bazy danych, kolejki, pamięci podręcznej i usług zewnętrznych.
  • Testy kontraktowe dla publicznych kształtów żądań i odpowiedzi.
  • Krótki test smoke dla zbudowanego artefaktu.

Doprowadzaj niestabilne testy do stabilności, zamiast automatycznie ponawiać je aż do zielonego wyniku. Jedna próba ponowienia może zebrać dane diagnostyczne, lecz końcowy status powinien pokazywać początkową porażkę. W przeciwnym razie agent może scalić kod, którego jedyną udowodnioną cechą jest to, że czasami działa.

Test smoke powinien uruchomić artefakt, sprawdzić endpoint zdrowia i jedną istotną ścieżkę zapisu, a potem czysto go zatrzymać. Testowanie kodu źródłowego bez uruchomienia spakowanej aplikacji nie wykryje brakujących plików, złych domyślnych wartości środowiska, uszkodzonych migracji i panik podczas startu. W usłudze internetowej wynik można zapisać w zwartej postaci:

{"commit":"abc123","build":"pass","startup_ms":842,"health":200,"write_read_cycle":"pass"}

Nie ustawiaj uniwersalnego procentu pokrycia jako głównej bramki. Pokrycie może ujawnić nieprzetestowaną zmianę, ale repozytorium może osiągnąć wysoki procent przy słabych asercjach. Blokuj na podstawie wymaganych zestawów i zmienionego zachowania, a zmianę pokrycia wykorzystuj jako dowód podczas recenzji.

Chroń testy przed implementacją, którą oceniają. Jeśli pull request jednocześnie zmienia regułę i przepisuje asercje tak, aby akceptowały nowy wynik, zestaw może przejść, podczas gdy kontrakt po cichu się zmieni. Wymagaj od recenzenta porównania zmienionych testów z publicznym API, zgłoszeniem lub regułą akceptacji. Dla parserów, walidatorów, logiki rozliczeń i kontroli dostępu dodaj testowanie mutacyjne albo mały zestaw celowo błędnych danych wejściowych. Ważne pytanie brzmi, czy zestaw odrzuca prawdopodobnie błędną implementację, a nie czy agent potrafi sprawić, by jego implementacja spełniła asercje, które sam napisał.

Zachowuj artefakty testowe, gdy bramka kończy się niepowodzeniem. Zapisz ziarno nieudanego testu losowego, dokładny obraz bazy danych, logi usługi po usunięciu sekretów oraz polecenie odtwarzające przebieg. Status bez danych do odtworzenia zmusza kolejnego agenta lub inżyniera do zgadywania. Ogranicz czas przechowywania artefaktów zgodnie z zasadami danych repozytorium i nigdy nie przesyłaj migawki produkcyjnej tylko dlatego, że ułatwia odtworzenie błędu.

CodeQL blokuje znane ścieżki kodu prowadzące do podatności

Bramka CodeQL powinna blokować nowe ustalenia o wysokiej pewności w językach i wygenerowanych artefaktach, które CodeQL rzeczywiście analizuje. Nie powinna sugerować, że czysty wynik dowodzi bezpieczeństwa całej aplikacji.

GitHub opisuje CodeQL jako kompilowanie kodu do bazy danych, którą można odpytywać, oraz uruchamianie na niej zapytań. Ten model jest użyteczny, ponieważ śledzi przepływ danych przez kod, zamiast dopasowywać jedynie podejrzany tekst. Jego zakres ograniczają obsługiwane języki, powodzenie kompilacji, wybór zapytań i kod obecny podczas analizy. Jeśli kompilacja bazy po cichu wykluczy usługę, zielony wynik obejmuje mniej, niż sądzą recenzenci.

Użyj workflow z jawnymi językami i stałą polityką zapytań:

name: codeql
on: [pull_request]
permissions:
  contents: read
  security-events: write
jobs:
  analyze:
    strategy:
      matrix:
        language: [javascript-typescript, go]
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          queries: security-extended
      - uses: github/codeql-action/autobuild@v3
      - uses: github/codeql-action/analyze@v3

W prawdziwym repozytorium przypinaj zewnętrzne akcje do sprawdzonych skrótów commitów. Tagi ułatwiają czytanie przykładu, lecz zmienny tag poszerza granicę zaufania wymaganej kontroli bezpieczeństwa.

Ustal, co blokuje, zanim pojawi się pierwszy alert. Zwykle blokuję nowe ustalenia na uzgodnionym w repozytorium progu istotności i precyzji, a istniejący dług pozostawiam widoczny w bazie odniesienia. Blokowanie każdego historycznego wyniku pierwszego dnia zachęca do masowego odrzucania. Ignorowanie wszystkich istniejących wyników na zawsze tworzy trwały martwy punkt. Zamiast tego przypisz właścicieli i terminy do bazy odniesienia.

Sprawdzaj zbiór analizowanych plików, gdy zmieniają się usługi, języki lub polecenia kompilacji. Pull request wprowadzający nowego klienta mobilnego, wygenerowany resolver lub osobny backend może potrzebować kolejnego analizatora albo kroku kompilacji. Stwierdzenie „CodeQL przeszedł” ma sens tylko wtedy, gdy recenzenci potrafią powiedzieć, co CodeQL zbadał.

Oddzielaj niepowodzenia analizy od czystych analiz. Jeśli autobuild nie potrafi skompilować pakietu, zadanie musi zgłosić błąd infrastruktury lub konfiguracji, a nie zero ustaleń. Zapisuj log tworzenia bazy oraz liczbę analizowanych plików źródłowych według języka. Porównuj te liczby z gałęzią bazową i oznaczaj duży, niewyjaśniony spadek. Wykrywa to zwykłą awarię: zmiana kompilacji wyklucza podatny moduł, analiza staje się szybsza, a kontrola bezpieczeństwa świeci na zielono, bo zobaczyła mniej kodu.

Traktuj odrzucenia wyników jako zmiany polityki, a nie porządki. Fałszywy alarm wymaga konkretnego wyjaśnienia powiązanego ze ścieżką kodu i zapytaniem. Komentarze wyciszające powinny być wąskie, mieć właściciela i być widoczne w diffie pull requesta. Wykluczenie całego repozytorium dla wygenerowanych plików może być właściwe, lecz najpierw upewnij się, że w tym katalogu nie ma ręcznie utrzymywanych szablonów ani danych wejściowych generatora.

Przegląd zależności zatrzymuje ryzyko przed instalacją

Przegląd zależności powinien blokować pull request, gdy jego diff zależności wprowadza pakiet albo wersję naruszającą jawną politykę. Polityka może obejmować znaną istotność ostrzeżenia, zakazane licencje, nieoczekiwane źródła pakietów i zależności bezpośrednie dodane bez właściciela.

Ta bramka różni się od alertu o podatności w repozytorium. Alert mówi, że podatna zależność istnieje w gałęzi. Przegląd zależności pyta, czy ten pull request pogarsza graf zależności. Przegląd zależności GitHub porównuje manifesty i pliki blokady między wersjami pull requesta, dzięki czemu decyzja zapada w odpowiednim momencie i można ją przypisać do zmiany.

Wymagaj spójności pliku blokady. Jeśli agent zmienia package.json, lecz nie plik blokady, albo zmienia plik blokady bez odpowiadającej zmiany manifestu, zadanie powinno zakończyć się błędem. Polecenia instalacji, które podczas CI rozwiązują świeże wersje, czynią wynik niedeterministycznym i mogą testować graf inny niż ten, który zobaczyli recenzenci.

Zwięzła polityka może wyglądać tak:

dependency_policy:
  fail_on_severity: high
  deny_licenses:
    - AGPL-3.0
  allow_sources:
    - registry.npmjs.org
    - proxy.golang.org
  require_owner_for_direct_additions: true

Dokładna lista licencji to decyzja prawna i produktowa, a nie wartość do bezmyślnego kopiowania. Ważne jest, aby repozytorium ją deklarowało, a kontrola wypisywała pakiet, który ją uruchomił.

Nie zatwierdzaj automatycznie pakietu tylko dlatego, że jego nazwa przypomina sugerowaną bibliotekę. Agenci mogą wymyślać nazwy pakietów, wybierać porzucone forki albo dodawać dużego klienta dla jednej drobnej funkcji pomocniczej. Wynik recenzji powinien pokazywać nowe pakiety bezpośrednie i przechodnie, rejestr źródłowy, rozwiązaną wersję, licencję i status ostrzeżeń. Recenzent może wtedy sprawdzić, czy istniejący kod albo mniejsza zależność nie rozwiązują już problemu.

Kończ blokadą, jeśli usługa zależności nie potrafi przygotować diffu. Niedostępny kanał ostrzeżeń może uzasadniać wstrzymanie scalenia, a nie zamianę niepewności w zieloną kontrolę. Procedury awaryjne mogą dopuścić udokumentowane nadpisanie przez nazwanego opiekuna wraz z uzasadnieniem dołączonym do commita.

Sprawdzaj zachowanie instalacji w odizolowanym zadaniu z dostępem sieciowym ograniczonym do zatwierdzonych rejestrów. Skrypty cyklu życia i wtyczki kompilacji wykonują kod podczas instalacji, więc pakiet może być niebezpieczny, nawet gdy aplikacja nigdy go nie importuje. Zapisuj, czy nowa zależność dodaje skrypty instalacyjne, binaria natywne lub nieznany rejestr. Nie uruchamiaj tego zadania z poświadczeniami publikowania, tokenami chmurowymi ani zapisywalną pamięcią podręczną pakietów współdzieloną z zaufanymi kompilacjami.

Kod dostarczony wraz z projektem i obrazy kontenerów należą do tej samej decyzji, choć zwykły przegląd manifestu może ich nie wykryć. Porównuj skróty obrazów, nazwy obrazów bazowych, submoduły Git i archiwa dodane do repozytorium. Wymagaj niezmiennych skrótów dla danych wejściowych wydania. Przyjazny tag, taki jak latest, uniemożliwia późniejsze odtworzenie pull requesta, ponieważ bajty mogą się zmienić bez kolejnego diffu.

Skanowanie sekretów musi sprawdzać diff i historię

Twórz z dowodem możliwości wycofania
Twórz przez czat, a potem użyj wdrożeń i migawek, aby dowieść, że można przywrócić poprzedni stan aplikacji.

Skanowanie sekretów powinno blokować, gdy pull request wprowadza wzorzec poświadczenia lub zweryfikowany aktywny sekret, nawet jeśli ciąg występuje w danych testowych, usuniętym pliku, wygenerowanym pakiecie albo wcześniejszym commicie pull requesta.

Ochrona podczas wysyłania zmian i skanowanie pull requestów rozwiązują powiązane, lecz różne problemy. Ochrona podczas wysyłania może zatrzymać rozpoznany sekret, zanim trafi do zdalnego repozytorium. Bramka pull requesta bada to, co już dotarło, i może objąć współtwórców albo typy tokenów pominięte przez tę ochronę. Alert bez ochrony gałęzi nie blokuje scalenia.

Skanuj pełny zakres commitów względem gałęzi bazowej, a nie tylko końcowy stan plików. Agent może dodać token w jednym commicie i usunąć go w następnym, ale token pozostaje w historii Git i mógł już trafić do logów lub pamięci podręcznych. Traktuj wynik jako ujawnienie. Unieważnij lub obróć poświadczenie, usuń je z proponowanej historii i uruchom kontrolę ponownie.

Używaj syntetycznych danych testowych, które nie potrafią się uwierzytelnić. Taka dana powinna wyraźnie wskazywać, że jest testowa, i pasować do lokalnie zdefiniowanego wzorca testowego zamiast kopiować format prawdziwego klucza chmurowego. Szerokie listy dozwolonych są niebezpieczne, ponieważ atakujący i wypadki w końcu trafią do ignorowanego katalogu. Wyjątki utrzymuj dokładne, sprawdzone i blisko konfiguracji detektora.

Łącz detektory wzorców z kontrolami entropii oraz, tam gdzie dostawca bezpiecznie to obsługuje, z weryfikacją poświadczeń. Dopasowanie wzorca stwarza mniej ryzyka sieciowego i ujawnienia, lecz pomija niestandardowe tokeny. Weryfikacja może zmniejszyć niepewność, ale wysyła część kandydata na sekret do innej usługi i nigdy nie może działać względem niezaufanego endpointu podanego przez pull request. Udokumentuj, które detektory weryfikują, które pozostają lokalne i jakie dane opuszczają CI.

Skanuj typowe formy zakodowane i wygenerowane wyniki, nie udając przy tym, że każdy losowy ciąg jest poświadczeniem. Base64, kodowanie URL i zminimalizowane pakiety mogą ukryć sekret, który w kroku źródłowym pojawił się jawnie. Ustal próg blokowania na podstawie przetestowanych danych testowych, a aktualizacje detektora oceniaj jak inne zmiany polityki. Hałaśliwy skaner uczy opiekunów odrzucać wyniki, a milczący tworzy fałszywą pewność.

Wynik bramki musi wskazywać lokalizację bez ujawniania sekretu:

{"result":"fail","detector":"generic-api-token","commit":"abc123","path":"config/dev.env","line":7,"fingerprint":"sha256:8f2c..."}

Nigdy nie wypisuj pełnego dopasowania w logach CI ani komentarzu pull requesta. Maskowanie po tym, jak skaner wyemituje wynik, może nastąpić za późno, ponieważ systemy logów, powiadomienia i artefakty zadań mogą go skopiować.

Skanowanie sekretów nie zastępuje przeglądu uprawnień repozytorium. Workflow może odczytać poświadczenie produkcyjne bez umieszczania go w diffie, a agent może zmienić zadanie wdrożeniowe, by je wyprowadzić. Trzymaj sekrety z dala od zadań pull requestów, ogranicz uprawnienia workflow i wymagaj ludzkiej recenzji zmian w definicjach CI.

Kontrole autoryzacji dowodzą, że zakazane działania pozostają zakazane

Bramka autoryzacji powinna dowodzić, że każda chroniona operacja odrzuca niewłaściwego aktora i zezwala właściwemu aktorowi na granicy usługi. Same testy logowania nie testują autoryzacji.

Zespoły regularnie mieszają uwierzytelnianie, autoryzację i widoczność w interfejsie. Uwierzytelnianie ustala, kto wysłał żądanie. Autoryzacja decyduje, czy ta tożsamość może wykonać dane działanie na tym obiekcie. Ukrycie przycisku administratora w React nie zmienia żadnej z tych decyzji w API Go. Jeśli backend przyjmuje żądanie, aplikacja nadal jest narażona.

Zbuduj macierz uprawnień dla zmienionych endpointów i działań biznesowych. Zachowaj ją na tyle małą, by dało się ją zrecenzować, ale uwzględnij granice własności i dzierżaw:

read_private_project:
  anonymous: deny
  member: deny
  other_tenant: deny
  owner: allow
  admin: allow
update_project:
  anonymous: deny
  other_tenant: deny
  owner: allow

Generuj testy z tej macierzy albo zakoduj równoważne przypadki sterowane tabelą w języku usługi. Każdy przypadek odmowy powinien wywoływać prawdziwy handler z realistycznymi identyfikatorami. Mocki zastępujące middleware autoryzacji mogą dowieść, że trasa działa, jednocześnie pomijając badaną kontrolę.

Testuj dostęp na poziomie obiektu, a nie wyłącznie role. Dwaj użytkownicy mogą mieć rolę member, należąc przy tym do różnych organizacji. Zmieniaj niezależnie identyfikator zasobu i identyfikator dzierżawy, aby wykryć niebezpieczne bezpośrednie odwołania do obiektów. Testuj także endpointy masowe, eksporty, zadania w tle i resolvery GraphQL, które często omijają kontrole napisane dla zwykłych handlerów REST.

Kończ bramkę błędem, gdy nowa chroniona trasa nie ma mapowania polityki. W ten sposób brak autoryzacji przestaje być przeczuciem recenzenta i staje się mierzalną wadą. Na serwerze domyślnie odmawiaj. Jawna reguła zezwolenia jest łatwiejsza do audytu niż rozproszony kod odmawiający kilku znanym złym przypadkom.

Agenci często ponownie wykorzystują pobliski handler i zachowują jego szczęśliwą ścieżkę, gubiąc kontrolę własności. Macierz uprawnień pokazuje to pominięcie. Daje też recenzentom stały kontrakt, gdy później zmieniają się role lub zasady dzierżaw.

Ćwicz autoryzację po normalizacji danych wejściowych. Zamiana wielkości liter, alternatywne formaty identyfikatorów, zduplikowane parametry zapytania i zagnieżdżone odwołania do obiektów mogą wysyłać równoważne żądania różnymi ścieżkami kodu. Testuj bezpośredni endpoint oraz każdą trasę wsadową lub importu, która dociera do tej samej operacji. Jeśli pracownik w tle wykonuje końcowy zapis, przekaż do zadania kontekst aktora i dzierżawy, zamiast traktować pracownika jak wszechmocnego zaufanego użytkownika.

Zapisuj oczekiwaną decyzję i regułę polityki, która ją wydała, ale unikaj ujawniania prywatnych danych obiektów w logach. Przydatny błąd podaje klasę aktora, działanie, klasę obiektu i oczekiwany status. Nie zrzuca tokenu dostępu ani pełnego rekordu. Taki dowód pozwala recenzentowi odróżnić uszkodzone dane testowe od rzeczywistej zmiany uprawnień.

Próba migracji mierzy blokady i odwracalność

Niech polityka gałęzi zachowa kontrolę
Eksportuj wygenerowany kod do repozytorium, w którym ostateczną decyzję podejmuje obecna polityka scalania.

Bramka migracji powinna zastosować każdą proponowaną zmianę schematu do kopii podobnej do produkcyjnej, uruchomić sondy zgodności oraz zapisać czas trwania, blokady i zachowanie wycofania przed scaleniem. Migracja, która kończy się powodzeniem na pustej testowej bazie danych, dowodzi bardzo niewiele.

Użyj oczyszczonej migawki lub wygenerowanego zbioru danych o podobnych rozmiarach tabel, indeksach, ograniczeniach i nierównomiernym rozkładzie. Dokładne dane produkcyjne nie powinny trafiać do infrastruktury pull requestów. Celem jest odtworzenie presji operacyjnej bez kopiowania danych osobowych lub poufnych.

Przećwicz prawdziwą sekwencję wdrożenia. Jeśli stare instancje aplikacji pozostają aktywne podczas migracji, testuj stary kod z nowym schematem oraz nowy kod ze schematem przejściowym. Dodanie kolumny dopuszczającej wartość null jest zwykle zgodne. Zmiana nazwy kolumny w jednym kroku może uszkodzić każdą starą instancję, która nadal obsługuje ruch.

Zapisuj dowody w wyniku odczytywalnym przez maszynę:

{"migration":"20260727_add_project_state","apply_ms":18420,"max_lock_ms":310,"old_app_probe":"pass","new_app_probe":"pass","down":"pass"}

Ustawiaj progi dla każdej bazy danych i klasy tabel. Blokada trwająca 300 milisekund może być niegroźna dla jednej tabeli, a zakłócać działanie innej. Recenzenci powinni widzieć wybrany limit obok zmierzonego wyniku oraz wersję bazy danych użytej podczas próby.

W PostgreSQL sprawdzaj operacje przepisujące tabelę, walidujące ograniczenie albo budujące indeks przy blokowaniu zapisów. Preferuj zmiany rozszerzaj i ograniczaj: dodaj nowy kształt, wdróż kod obsługujący oba kształty, uzupełniaj dane kontrolowanymi partiami, przełącz odczyty, a potem usuń stary kształt w późniejszej zmianie. Dodatkowy pull request kosztuje mniej niż improwizacja podczas awarii.

Nie każda migracja może mieć bezpieczną operację down. Usunięcie kolumny powoduje utratę danych, a odwrócenie transformacji może być niejednoznaczne. W takich przypadkach bramka powinna wymagać procedury odzyskiwania do przodu i przetestowanego punktu odtworzenia kopii zapasowej. Nazywanie nieodwracalnej migracji „bezpieczną do wycofania” tylko dlatego, że istnieje plik down, byłoby nieuczciwe.

Testuj ponowienia i częściowe niepowodzenia. Wdrożenie może zatrzymać się po utworzeniu indeksu, ale przed zapisaniem migracji jako ukończonej, a kolejna próba nie może uszkodzić stanu ani kończyć się błędem w nieskończoność. Przerwij próbę na kontrolowanej granicy, uruchom ją ponownie i sprawdź zgodność schematu z rejestrem migracji. W przypadku długiego uzupełniania danych udowodnij, że partie wznawiają się od zapisanego kursora oraz że dwukrotne uruchomienie partii nie duplikuje ani nie usuwa danych.

Sprawdzaj wpływ na dysk i replikację, nie tylko czas trwania. Przepisanie tabeli może zużyć tymczasowe miejsce, powiększyć dzienniki wyprzedzające zapisu i opóźnić repliki, choć operacja główna wygląda na zakończoną. Bramka nie musi tworzyć idealnej prognozy produkcyjnej, ale powinna zapisać te wartości dla zbioru próbnego i porównać je z limitami wybranymi przez właściciela bazy danych. Bez tych dowodów szybka lokalna migracja nadal może wyczerpać wolumin produkcyjny.

Weryfikacja wycofania musi uruchamiać ścieżkę odzyskiwania

Zaplanuj bramki przed programowaniem
W trybie planowania określ wymagania dotyczące testów, autoryzacji, migracji i odzyskiwania działania, zanim agenci wygenerują zmiany.

Bramka wycofania powinna wdrożyć kandydata w odizolowanym środowisku, utworzyć reprezentatywny stan, uruchomić obsługiwaną metodę wycofania i dowieść, że poprzednia wersja nadal poprawnie obsługuje odczyty i zapisy. Pisemny plan wycofania nie jest weryfikacją.

Oddziel wycofanie aplikacji od wycofania danych. Przekierowanie ruchu do poprzedniego binarium może trwać sekundy, podczas gdy cofnięcie destrukcyjnej transformacji schematu lub danych może być niemożliwe. Bramka powinna raportować oba przypadki. Jeśli stara aplikacja nie może działać z nowym schematem, oznacz kandydata jako nieodwracalnego i wymagaj etapowego planu wdrożenia.

Praktyczna sekwencja wygląda tak:

  1. Wdróż bieżący commit z gałęzi głównej i utwórz reprezentatywne rekordy.
  2. Zaktualizuj do artefaktu pull requesta i sprawdź zmienione ścieżki.
  3. Utwórz nowe rekordy w stanie po aktualizacji.
  4. Przywróć poprzedni artefakt lub migawkę za pomocą udokumentowanej kontroli.
  5. Uruchom sondy odczytu, zapisu, kolejki i zadań w tle.

Kontrola powinna zachowywać identyfikatory artefaktów, identyfikatory migawek, znaczniki czasu i wyniki sond. Nie powinna zachowywać poświadczeń ani skopiowanych danych klientów. Mierz czas odzyskiwania jako dowód dla własnego celu operacyjnego, a nie jako uniwersalną obietnicę.

Migawki pomagają tylko wtedy, gdy ktoś udowodni, że zawierają wszystko, czego potrzebuje aplikacja. Pliki, magazyn obiektowy, stan kolejki, zmiany schematu i zewnętrzne skutki mogą znajdować się poza migawką serwera. Wymień te granice w wyniku. Płatności, wysłanego e-maila ani webhooka nie da się cofnąć przez odtworzenie bazy danych.

Uczyń sondę wycofania silniejszą niż kontrola zdrowia. Odczytaj rekord utworzony przed aktualizacją i rekord utworzony po niej, zaktualizuj oba tam, gdzie zgodność na to pozwala, oraz przetwórz zadanie w kolejce utworzone przez każdą wersję aplikacji. Porównuj widoczny dla użytkownika wynik, a nie tylko kody statusu. Serwer zwracający 200, który gubi nowe pole albo błędnie odczytuje wartość enum, nie odzyskał działania.

Testuj kontrolę używaną przez osobę dyżurującą. Jeśli wycofanie na produkcji wymaga wybrania artefaktu, odtworzenia migawki albo zmiany ruchu, odizolowana próba powinna korzystać z tego samego interfejsu i tej samej ścieżki uprawnień. Prywatny skrypt na laptopie jednego inżyniera nie jest kontrolą operacyjną. Dowód powinien pokazać, że wyznaczona rola operatora potrafi odzyskać działanie bez zdobywania stałego dostępu administratora.

Koder.ai obsługuje eksport kodu źródłowego, wdrażanie i hosting, migawki oraz wycofywanie, więc tworzone tam aplikacje mogą wykorzystać te konkretne artefakty w tej bramce zamiast traktować odzyskiwanie jako akapit w pull requeście. Ta sama zasada obowiązuje na każdej platformie: uruchom kontrolę odzyskiwania i sprawdź przywróconą aplikację.

Jedna wymagana kontrola powinna podsumowywać wszystkie siedem

Ostateczna decyzja o scaleniu powinna wymagać jednej stabilnej kontroli polityki, która weryfikuje siedem wyników składowych dla dokładnego commita głównego. Nazwy poszczególnych zadań się zmieniają, zadania macierzy się mnożą, a opcjonalne ścieżki pomijają pracę. Mały agregator zapobiega rozchodzeniu się ochrony gałęzi z polityką.

Niech każda bramka emituje podpisany albo poświadczony przez platformę wynik zawierający commit, wersję polityki, rezultat i lokalizację dowodów. Agregator odrzuca wyniki brakujące, nieaktualne, neutralne lub anulowane. Nigdy nie powinien wnioskować o powodzeniu na podstawie zadania, które nie zgłosiło wyniku.

{
  "commit": "abc123",
  "policy": "merge-gates-v3",
  "results": {
    "tests": "pass",
    "codeql": "pass",
    "dependency_review": "pass",
    "secret_scan": "pass",
    "authorization": "pass",
    "migration_rehearsal": "not_applicable",
    "rollback_verification": "pass"
  },
  "decision": "allow"
}

Zdefiniuj wąską ścieżkę nadpisania, ponieważ zdarzają się sytuacje awaryjne. Wymagaj nazwanego opiekuna, drugiego zatwierdzającego, pisemnego uzasadnienia, daty wygaśnięcia i zgłoszenia następczego. Nie pozwalaj agentowi prosić o własny wyjątek ani go zatwierdzać. Raportuj nadpisania w tym samym miejscu co zwykłe wyniki bramek, aby pozostały widoczne po zakończeniu incydentu.

Te kontrole dodadzą minuty do części pull requestów, a znacznie więcej czasu do zmian migracyjnych. To akceptowalne, gdy ten czas kupuje konkretne dowody. Uruchamiaj najpierw tanie bramki, anuluj zastąpione commity, buforuj zaufane dane wejściowe kompilacji i rezerwuj pełną próbę środowiskową dla istotnych ścieżek. Nie osłabiaj bramki tylko po to, aby pulpit szybciej zrobił się zielony.

Zacznij od uczynienia obecnego zachowania obserwowalnym. Umieść wszystkie siedem nazw w jednym pliku polityki, połącz każdą z wymaganym wynikiem i zmuszaj pominiętą pracę do wyjaśnienia się. Pierwszy pull request agenta, który nie potrafi przygotować takiego zapisu, wykrył lukę w systemie dostarczania, zanim odkrył ją na produkcji.

Często zadawane pytania

Czy PR-y agentów powinny podlegać surowszym zasadom niż PR-y ludzi?

Stosuj te same blokujące dowody w obu przypadkach. Agenci mogą uzasadniać więcej automatycznych kontroli, ponieważ tworzą zmiany szybciej, lecz zmiana przygotowana przez człowieka może ujawnić ten sam sekret, błąd autoryzacji lub niebezpieczną migrację.

Czy recenzent może nadpisać nieudaną bramkę scalania?

Tak, lecz wyłącznie przez wąski, zapisany wyjątek z udziałem dwóch odpowiedzialnych osób, uzasadnieniem i datą wygaśnięcia. Agent, który przygotował zmianę, nigdy nie może zatwierdzić własnego wyjątku.

Czy zaliczona kontrola CodeQL oznacza, że PR jest bezpieczny?

Nie. Oznacza to, że wybrane zapytania nie znalazły blokującego wyniku w kodzie, który CodeQL zdołał przeanalizować. Zależności, autoryzacja w czasie działania, sekrety, konfiguracja i odzyskiwanie działania nadal potrzebują osobnych dowodów.

Co zrobić, gdy wymagany skaner jest niedostępny?

Kontrola powinna zakończyć się blokadą lub pozostać zablokowana. Jeśli zmiana jest pilna, skorzystaj z udokumentowanej ścieżki wyjątku, zamiast zamieniać nieznany wynik w zaliczenie.

Czy skanowanie sekretów powinno obejmować usunięte commity?

Powinno się sprawdzić cały zakres commitów PR-a. Sekret dodany, a później usunięty, nadal istnieje w historii i należy go obrócić przed przyjęciem oczyszczonej zmiany.

Jak testować autoryzację w PR-ze?

Wywołuj prawdziwe handlery usługi dla macierzy tożsamości, ról, dzierżaw, obiektów i działań. Uwzględnij przypadki odmowy oraz zmianę właściciela obiektu, ponieważ udane logowanie i ukryte kontrolki interfejsu nie dowodzą autoryzacji po stronie serwera.

Czy każda migracja bazy danych potrzebuje skryptu down?

Nie. Niektórych destrukcyjnych zmian nie da się uczciwie odwrócić. Zamiast tego wymagaj przetestowanej procedury odzyskiwania do przodu lub odtworzenia kopii zapasowej i oznacz zmianę jako nieodwracalną.

Jaka jest różnica między planowaniem wycofania a jego weryfikacją?

Planowanie opisuje zamierzone kroki odzyskiwania działania. Weryfikacja wykonuje te kroki na artefakcie kandydującym i reprezentatywnym stanie, a następnie zapisuje, czy poprzednia wersja nadal potrafi poprawnie odczytywać i zapisywać dane.

Jak zespoły mogą uniknąć spowalniania każdego PR-a przez siedem bramek?

Uruchamiaj najpierw tanie kontrole, anuluj przebiegi dla zastąpionych commitów, buforuj zaufane dane wejściowe i uruchamiaj próbę migracji tylko dla istotnych zmian. Każda bramka powinna zwracać jednoznaczny wynik: zaliczenie albo brak zastosowania.

Jakiego wyniku powinna wymagać ochrona gałęzi?

Wymagaj jednego stabilnego wyniku polityki, który agreguje wszystkie siedem bramek dla dokładnego commita głównego. Powinien odrzucać wyniki brakujące, nieaktualne, pominięte, anulowane lub neutralne, zamiast zakładać, że zostały zaliczone.

Related posts