⚠  PROJEKT — niezweryfikowany prawnie. Wymaga akceptacji przed publikacją.

Biała Księga Bezpieczeństwa

Architektura bezpieczeństwa platformy CyberZgodność EDU  ·  Ostatnia aktualizacja: 2026-10-22  ·  Wersja: 1.0

Niniejszy dokument opisuje środki techniczne i organizacyjne wdrożone przez Operatora w celu ochrony platformy i danych Dzierżawców. Uzupełnia Załącznik II do Umowy Powierzenia (DPA), który zawiera wiążący opis środków. Zawiera uczciwą sekcję „czego jeszcze nie robimy” — bezpieczeństwo jest procesem, nie stanem.

1. Izolacja Dzierżawców (RLS PostgreSQL)

Fundamentem izolacji jest FORCE ROW LEVEL SECURITY w PostgreSQL 16. Każda tabela zawierająca dane Dzierżawcy posiada kolumny tenant_id i (opcjonalnie) org_unit_id. Middleware Django ustawia zmienne sesji GUC przed każdym zapytaniem:

-- Middleware ustawia parę GUC przy każdym żądaniu:
SET LOCAL app.current_tenant_id = '<uuid>';
SET LOCAL app.current_org_unit_id = '<uuid>,<uuid>';  -- tylko użytkownik ograniczony do placówek
SET LOCAL ROLE app;  -- rola bez uprawnień superuser

-- Przykładowa polityka RLS:
CREATE POLICY tenant_isolation ON audit_log
  USING (tenant_id = current_setting('app.current_tenant_id')::uuid);

ALTER TABLE audit_log ENABLE ROW LEVEL SECURITY;
ALTER TABLE audit_log FORCE ROW LEVEL SECURITY;

Izolacja placówek w obrębie Dzierżawcy. Każda placówka ma własną jednostkę organizacyjną, nadawaną przez bazę danych. RLS egzekwuje org_unit_id na sześciu tabelach — placówki, wyjątki, przypisania zadań kontrolnych, Zadania Kontrolne NIS2, samoidentyfikacja i incydenty — a jednostkę wiersza ustawia wyzwalacz bazy danych na podstawie jego placówki, nie aplikacja. app.current_org_unit_id jest listą jednostek i jest ustawiana dla użytkownika, którego wszystkie role są ograniczone do placówek (np. dyrektor lub ITSO szkoły w Dzierżawcy JST, gdzie te role nadaje się wyłącznie per placówka); wiersze dotyczące całej organizacji, bez placówki, są widoczne w każdej jednostce. Główną kontrolą jest kod aplikacji, który ogranicza odczyty i zapisy do placówek, w których użytkownik ma uprawnienie; baza danych jest zabezpieczeniem pod nim. Ryzyka, aktywa i stany zgodności kontroli są ograniczane per placówka wyłącznie w kodzie aplikacji. Szkoła założona jako osobny Dzierżawca jest odizolowana od pozostałych przez RLS na tenant_id.

Rola app ma uprawnienia SELECT/INSERT/UPDATE/DELETE na większości tabel biznesowych — każde z nich ograniczone przez FORCE ROW LEVEL SECURITY. Nie jednolicie: od 2026-09-29 app nie może usunąć rekordu samego Dzierżawcy i może aktualizować tylko wskazane jego kolumny, a migracja odbierająca takie uprawnienie przerywa wdrożenie, jeśli uprawnienie przetrwa. Rola audit_writer ma INSERT oraz SELECT na dzienniku audytu: SELECT jest konieczny, bo wyzwalacz łańcucha musi odczytać bieżącą głowę. Brak UPDATE i DELETE utrzymuje charakter append-only. Migracje wykonuje superużytkownik bootstrap klastra (właściciel tabel) — nigdy w trakcie obsługi żądania; osobna, dedykowana rola DDL jest śledzona jako zadanie hardeningowe.

2. Integralność dziennika audytu

Każdy wpis dziennika audytu jest powiązany z poprzednim przez kryptograficzny łańcuch skrótów SHA-256:

row_hash_n = sha256( prev_hash_(n-1) || canonical(row_n) )

Gdzie canonical = dwanaście pól składowych, zserializowanych przez Postgres do tekstu i połączonych znakiem \x1f (ASCII unit separator), w kolejności: tenant_id, actor_user_id, actor_ip, actor_user_agent, action, target_type, target_id, before, after, request_id, at, contract_version. timestamptz::text renderowany jest przy TimeZone = 'UTC' i DateStyle = 'ISO, MDY' (ustawionych na stałe w wyzwalaczu), a połączony tekst haszowany jest jako bajty UTF-8. Aby odtworzyć łańcuch zapytaniem SQL lub z danych wyeksportowanych z Postgresa, ustaw wcześniej te same TimeZone, DateStyle oraz client_encoding = 'UTF8'. Wartości NULL serializują się do pustego łańcucha znaków. Wersją listy pól jest contract_version, przechowywana w każdym wierszu i wchodząca do postaci kanonicznej jako jej dwunaste pole.

Skrót wylicza wyzwalacz Postgresa (SECURITY DEFINER), a nie aplikacja, i przechowuje go jako surowe bajty (bytea), nie jako tekst szesnastkowy. Django nie może podać prev_hash, row_hash ani chain_pos — wyzwalacz nadpisuje je po stronie serwera. Łańcuch jest wiązany i przechodzony po chain_pos, nigdy po at: wiersz z datą wsteczną nadal dopisuje się na końcu.

# Odtworzenie skrótu wiersza z danych wyeksportowanych z Postgresa.
import hashlib

SEP = "\x1f"  # ASCII unit separator

def compute_row_hash(prev_hash: bytes, fields: list[str]) -> bytes:
    """fields = dwanaście pól w kolejności z listy powyżej."""
    canonical = SEP.join(fields).encode("utf-8")
    return hashlib.sha256(prev_hash + canonical).digest()

# prev_hash pierwszego wiersza w łańcuchu to 32 bajty zerowe: bytes(32).

# Weryfikacja całego łańcucha:
# GET /api/audit/verify/ --> 200 {"ok": true, "total_rows": N}
#                        lub 422 {"ok": false, "total_rows": N,
#                                 "broken_at": "<uuid>", "reason": "..."}
# To jest całe ciało odpowiedzi. Pole chain_length należy do innego
# endpointu -- GET /api/audit/public/ -- i dotyczy łańcucha płaszczyzny
# sterującej, nie łańcucha Dzierżawcy.

Rola audit_writer ma INSERT oraz SELECT (wyzwalacz łańcucha odczytuje bieżącą głowę) — brak UPDATE ani DELETE. FORCE ROW LEVEL SECURITY obowiązuje również na dzienniku. Przerwanie łańcucha (np. przywracanie po awarii) tworzy „kotwicę nieciągłości” z dokumentacją zdarzenia — jest to celowa funkcja, nie błąd.

3. Skróty haseł

Hasła są haszowane algorytmem Argon2id. Używamy własnej podklasy hashera Django (apps.iam.hashers.ExceptaoArgon2PasswordHasher, pierwsza pozycja listy PASSWORD_HASHERS) — parametry, z którymi liczony jest każdy nowy skrót:

Nigdy nie przechowujemy hasła w postaci jawnej ani zaszyfrowanej odwracalnie — w bazie jest wyłącznie jednokierunkowy skrót. Chronią go trzy mechanizmy, wszystkie sprawdzalne w kodzie:

Do 2026-09-19 w tym miejscu stało zdanie, że skrót jest przechowywany „w kolumnie z ograniczeniami RLS — niedostępny dla roli app przez SELECT”. To nie było prawdą i nie mogło nią być: app jest rolą, która uwierzytelnia użytkownika, więc musi odczytać skrót; w bazie nie ma żadnych uprawnień ani polityk na poziomie kolumny. Zdanie zostało wycofane i zastąpione listą powyżej.

4. Uwierzytelnianie wieloskładnikowe (MFA)

MFA jest obowiązkowe dla każdego konta z hasłem lokalnym — platforma odrzuca żądania z takiego konta do czasu rejestracji drugiego składnika. Konta logujące się przez dostawcę tożsamości Dzierżawcy nie mają u nas hasła i podlegają temu dostawcy; publiczne demo jest wyłączone (opublikowane poświadczenia, brak danych klientów, nocny reset). Dostępne metody:

5. Zarządzanie kluczami (HashiCorp Vault)

Vault obsługuje envelope encryption per Dzierżawca od 2026-10-10 (P0-1, wydanie R2) dla poświadczeń Dzierżawców; od 2026-10-11 (wydanie R3b) jest to ich jedyna ochrona — zob. sekcję 14:

6. Transport danych — TLS

Cała komunikacja sieciowa z klientem odbywa się przez TLS terminowany przez Cloudflare. Minimalna wersja TLS jest ustawieniem strefy w Cloudflare, przechowywanym w konfiguracji panelu, a nie w repozytorium; aktualne ustawienie udostępniamy klientom na żądanie. VPS nie ma otwartych portów na zewnątrz — cały ruch HTTP/HTTPS trafia przez Cloudflare Tunnel (mTLS wewnętrznie). Nagłówki HSTS na odpowiedziach API: Strict-Transport-Security: max-age=31536000; includeSubDomains. Domena nie jest zgłoszona na listę preload przeglądarek, a strony statyczne na Cloudflare Pages nie niosą tego nagłówka.

7. Kopie zapasowe (polityka 3-2-1)

KopiaLokalizacjaSzyfrowanieCzęstotliwość
PodstawowaCloudflare R2 (EU)Kopertowo: AES-256-GCM na archiwum, klucz opakowany RSA-OAEP (RSA-4096); klucz prywatny nieeksportowalny w Microsoft Azure Key VaultCodzienna
DrugorzędnaBackblaze B2 (Amsterdam, EU)Kopertowo: AES-256-GCM na archiwum, klucz opakowany RSA-OAEP (RSA-4096); klucz prywatny nieeksportowalny w Microsoft Azure Key VaultCodzienna

Testy przywracania — są dwa i nie są równoważne:

Do 2026-09-19 w tym miejscu stało zdanie, że „testy przywracania są wykonywane automatycznie co 90 dni” i rejestrowane pod kodem backup.restore_drill.complete. Kwartalny harmonogram istnieje (pierwsze zaplanowane uruchomienie 2026-10-01, wynik powyżej); test zrzutu logicznego nie ma harmonogramu w ogóle; a kod backup.restore_drill.complete nie występuje nigdzie w systemie.

8. Kontrola dostępu pracowników Operatora

Dostęp do infrastruktury produkcyjnej jest ograniczony do minimum niezbędnych osób. Każde połączenie z VPS odbywa się przez Cloudflare Access (SSO + MFA), a SSH przez Cloudflare Tunnel — nie przez otwarty port 22.

Rola PostgreSQLUprawnieniaUżywana przez
appSELECT, INSERT, UPDATE, DELETE na większości tabel biznesowych (z FORCE RLS); bez DELETE na rekordzie DzierżawcyDjango runtime (każde żądanie HTTP)
audit_writerINSERT i SELECT na audit_log; brak UPDATE i DELETERuntime Django, synchroniczna ścieżka żądania (apps/audit/services.py)
superadminBYPASSRLS NOSUPERUSER NOLOGIN; SELECT na wyselekcjonowanej liście tabel, bez INSERT, UPDATE, DELETE i TRUNCATE — wyłącznie odczytyOdczyty międzydzierżawcze konsoli operatora i endpoint weryfikacji łańcucha
platform_writerBYPASSRLS NOSUPERUSER NOLOGIN; INSERT/UPDATE na wyselekcjonowanej liście tabel; żadnych uprawnień do audit_logZapisy konsoli operatora
iam_definerBYPASSRLS NOSUPERUSER NOINHERIT NOLOGIN; właściciel dwóch funkcji wyszukiwania między Dzierżawcami (SECURITY DEFINER); SELECT na tenant_membership oraz SELECT/UPDATE na poziomie kolumn (trzy/jedna kolumna) w iam_password_reset_tokenNigdy nie jest przyjmowana przez sesję: osiągalna wyłącznie jako właściciel tych dwóch funkcji
app_privRola logowania, bez uprawnień superużytkownika, NOBYPASSRLS; dziedziczy app i może przechodzić (wyłącznie SET ROLE) do superadmin, platform_writer i audit_writer; bez własnych uprawnień poza tymiWorker zadań w tle i konsola operatora — nigdy backend obsługujący żądania
app_roNOLOGIN NOSUPERUSER NOBYPASSRLS; wyłącznie SELECT i tylko na tabelach, które czyta sama rola app; nie należy do żadnej roli; podlega tym samym politykom wierszowym, w tym FORCEOdczyty tylko do odczytu w układzie federacji (nadzorca JST); osiągana wyłącznie przez SET ROLE z app
superużytkownik bootstrap (właściciel)Superużytkownik klastra; DDLMigracje Django — tylko w oknie deploy; nigdy w ścieżce żądania

9. OIDC / SAML SSO per Dzierżawca

Platforma obsługuje federację tożsamości per Dzierżawca:

Konfiguracja IdP jest per Dzierżawca — jeden Dzierżawca nie może wpłynąć na konfigurację innego.

10. Zarządzanie podatnościami

11. Monitoring i reagowanie na incydenty

12. Bezpieczeństwo fizyczne

VPS jest hostowany w centrum danych OVHcloud (Warszawa, Polska) posiadającym certyfikat ISO/IEC 27001. Dane są przechowywane w UE; produkcja działa w Polsce, a kwartalny test odtworzenia odbywa się w Austrii (UE) — zob. listę podwykonawców. Operator nie posiada własnej infrastruktury fizycznej. Fizyczny dostęp do serwerów jest wyłączną kompetencją OVHcloud.

13. Zgodność z NIS2 / KSC

Architektura bezpieczeństwa platformy jest zaprojektowana tak, aby same środki techniczne spełniały wymagania art. 21 §2 NIS2 (szyfrowanie, MFA, kontrola dostępu, ciągłość działania, zarządzanie incydentami, bezpieczeństwo łańcucha dostaw). Szczegółowe mapowanie: Nota zgodności z NIS2/KSC.

14. Czego jeszcze nie robimy

Uczciwa lista ograniczeń (stan na 2026-05-15):

Obszar Status Plan
Certyfikacja ISO 27001 platformy Brak — architektura jest zgodna z wymaganiami Ocena po 12 miesiącach produkcji
Niezależny audyt penetracyjny Brak (planowany Q4 2026) Wyniki zostaną opublikowane (streszczenie)
SOC 2 Type II Brak — roadmap po skalowaniu 2027+
SIEM / SOC dla infrastruktury Dzierżawcy Poza zakresem platformy Integracja przez API (planowana)
Redundancja multi-region Single-VPS; backup w 2 lokalizacjach Drugi region UE przy większej skali

Klucze Dzierżawców i kryptograficzne usuwanie: obowiązuje od 2026-10-11

Stan na 2026-10-11. Klucze szyfrowania danych (DEK) przypisane do poszczególnych Dzierżawców są używane w obu wdrożeniach produkcyjnych od 2026-10-10 (wydanie R2 w ramach P0-1): każdy aktywny Dzierżawca ma własny klucz, opakowany kluczem przypisanym mu w silniku tranzytowym Vault, a poświadczenie Dzierżawcy zapisane od tego dnia jest szyfrowane tym kluczem. W chwili włączenia kluczy żaden Dzierżawca nie miał zapisanego poświadczenia integracji ani logowania, więc nie było czego migrować. Od 2026-10-11 (wydanie R3b, oba wdrożenia produkcyjne) klucz Dzierżawcy jest jedyną ochroną jego poświadczeń: kopie pod kluczem ogólnoplatformowym, zachowywane do tego dnia, zostały usunięte, a klucz ogólnoplatformowy, który je szyfrował, nie jest już ładowany przez aplikację ani przechowywany w bieżących sekretach Vault. Kryptograficzne usuwanie („crypto-shredding”) poświadczeń Dzierżawców obowiązuje zatem od 2026-10-11, w granicach opisanych poniżej. Sekrety TOTP nie są objęte kluczami Dzierżawców (ograniczenie 5).

Dlaczego nie czekaliśmy 30 dni. Projekt przewidywał, że harmonogram zacznie obowiązywać 30 dni (okres retencji kopii zapasowych) po wydaniu R3, ponieważ kopia zapasowa wykonana przed R3 mogłaby zawierać kopię poświadczenia pod kluczem ogólnoplatformowym. Tu żadna jej nie zawiera, bo takiej kopii nigdy nie utworzono: w chwili włączenia kluczy każda kolumna poświadczeń była pusta, a testy odtworzenia z 2026-10-11, wykonane na ostatnich kopiach zapasowych sprzed R3b, również wykazały puste wszystkie kolumny poświadczeń. Operator uznał więc 2026-10-11 to oczekiwanie za zbędne. Gdyby takie kopie istniały, oczekiwanie obowiązywałoby.

Harmonogram usunięcia — obowiązuje od 2026-10-11. Kryptograficzne usunięcie może zostać zlecone wyłącznie dla zarchiwizowanego Dzierżawcy. Zlecenie jest wstrzymywane na 30-dniowy okres karencji, w którym można je anulować; po jego upływie klucz Dzierżawcy jest niszczony. Zaszyfrowane migawki Vault wykonane przed tą chwilą są przechowywane do 30 dni (VAULT_SNAPSHOT_RETENTION_DAYS, domyślnie 30 — to samo okno co dla kopii zapasowych bazy danych), a odtworzenie migawki w tym oknie przywróciłoby klucz. Usunięcie staje się więc po naszej stronie nieodwracalne około 60 dni od potwierdzonego zlecenia: 30 dni karencji, a następnie do 30 dni przechowywania zaszyfrowanych kopii zapasowych i migawek Vault. Obejmuje zapisane poświadczenia Dzierżawcy (sekrety logowania, poczty i integracji); nie obejmuje sekretów TOTP ani łańcucha audytowego (ograniczenia 2 i 5).

Dziesięć ograniczeń, które publikujemy, aby nikt nie przypisywał kryptograficznemu usuwaniu więcej, niż ono zapewnia:

  1. Kryptograficzne usunięcie nie przetrwa odtworzenia migawki Vault wykonanej przed nim. Odtworzenie takiej migawki przywraca klucz. Ograniczają to 30-dniowa retencja migawek oraz obowiązkowy krok procedury odtwarzania, który ponawia każde usunięcie zarejestrowane po wykonaniu migawki. Właściwe sformułowanie brzmi „w oknie retencji kopii zapasowych”, nigdy „natychmiast i na zawsze”.
  2. Kryptograficzne usunięcie nie usuwa łańcucha audytowego i nie może go usuwać. Łańcuch jest tylko do dopisywania; po usunięciu każdy wiersz audytu pozostaje, a /api/audit/verify nadal go weryfikuje. Zapis o usunięciu przetrwa same dane. Usunięcie danych pseudonimizuje rekord użytkownika, do którego wiersze audytu odwołują się wewnętrznym identyfikatorem; same wiersze audytu nigdy nie są przepisywane. Wiersze dziennika audytu zapisane przed wdrożeniem produkcyjnym z 2026-10-12 mogą ponadto zawierać w samym wierszu adresy e-mail: przy czynnościach (logowanie, blokada konta i reset hasła; zakładanie kont przez SSO; nadawanie uprawnień administratora platformy; zakładanie, zawieszanie i przywracanie Dzierżawców; dostęp wsparcia Operatora i wyszukiwanie w dzienniku przez Operatora; deklaracje nieciągłości łańcucha i raporty z ćwiczeń odtwarzania; delegowanie zadań przez JST; powiadomienia i przypomnienia; ocena dostawców; profil organizacji; podłączenie poczty Microsoft 365; kontrola ścieżki e-mail) — użytkownika wykonującego lub objętego czynnością, odbiorcy powiadomienia lub osoby kontaktowej Dzierżawcy albo identyfikator wpisany w formularzu logowania lub resetu hasła — a przy dowolnej czynności w tekście swobodnym, np. w komunikacie błędu lub w tekście wpisanym przez użytkownika. Pozostają one przez cały okres istnienia konta Dzierżawcy (w łańcuchu warstwy sterującej platformy — przez cały okres istnienia platformy), na tej samej podstawie prawnej co adres IP aktora: uzasadniony interes w zakresie integralności audytu (art. 6 ust. 1 lit. f RODO). Od wdrożenia produkcyjnego z 2026-10-12 w treści ani w polu obiektu docelowego wiersza audytu nie jest zapisywany żaden tekst w postaci adresu e-mail: użytkownicy są identyfikowani wewnętrznym identyfikatorem, a każdy inny adres — także w tekście swobodnym — skrótem kluczowanym (HMAC), z którego adresu nie da się odczytać. Do poprawki z 2026-10-13 obowiązywał jeden wyjątek: gdy adresy lub domeny były połączone znakiem @ bez niczego pomiędzy (x@a.com@b.org), w wierszu zostawał skrót, po nim @ i nazwa domeny — nigdy cały adres. Wiersze zapisane od wdrożenia produkcyjnego z 2026-10-12 do wdrożenia tej poprawki mogą zawierać taki fragment; są przechowywane na tej samej podstawie i ujawniane, a nie usuwane. Drugą lukę usunęła poprawka z 2026-10-14: adres zawierający łączące znaki diakrytyczne — literę z akcentem zapisaną jako litera podstawowa i osobny znak (Unicode NFD, powstający w niektórych systemach i przy kopiowaniu z niektórych dokumentów) albo pismo, w którym samogłoski zapisuje się takimi znakami, np. dewanagari lub tajskie, albo niewidoczny łącznik (ZWNJ/ZWJ) używany w nazwach perskich i indyjskich — nie był rozpoznawany i był zapisywany tak, jak go wpisano, w całości lub w części. Wiersze zapisane przed wdrożeniem tej poprawki mogą zawierać taki adres jawnym tekstem; są przechowywane na tej samej podstawie i ujawniane, a nie usuwane. Taki skrót jest pseudonimem i pozostaje daną osobową: każdy, kto może spowodować zapisanie przez platformę wybranego adresu, albo kto posiada klucz, może potwierdzić odgadnięty adres. Inne dane osobowe wpisane w pola tekstowe, np. imię i nazwisko lub numer telefonu, są zapisywane tak, jak je wpisano. Nie obejmuje to ciągu user-agent sesji wykonującej czynność: jest on zapisywany tak, jak go przesłał klient, a niektórzy klienci, zwłaszcza roboty indeksujące, umieszczają w nim adres kontaktowy.
  3. Klucz Dzierżawcy jest nieeksportowalny, co działa w obie strony. W projekcie to dzięki temu skradziona baza danych jest bezużyteczna bez Vault — i z tego samego powodu utrata magazynu Vault wraz ze wszystkimi jego migawkami uczyniłaby chronione dane nieodzyskiwalnymi. Właśnie dla tej drugiej połowy istnieje test odtworzenia migawek z depozytu.
  4. Szyfrowanie wiąże sekret z Dzierżawcą, tabelą i kolumną — nie z chwilą jego zapisu. Szyfrogram unieważnionego poświadczenia odzyskany z okna odtwarzania do punktu w czasie może zostać ponownie zapisany w miejsce nowego przez kogoś z uprawnieniem zapisu do bazy danych i da się go odszyfrować. Ryzyko zaakceptowane, nierozwiązane.
  5. Sekrety TOTP nie są chronione kluczem Dzierżawcy. Konta użytkowników nie należą do jednego Dzierżawcy, dlatego projekt chroni sekrety TOTP jednym kluczem Vault na poziomie platformy: klucz każdego użytkownika jest wyprowadzany z klucza głównego platformy opakowanego kluczem tranzytowym Vault platform-iam (sekcja 5), więc crypto-shred Dzierżawcy ich nie obejmuje; usunięcie użytkownika usuwa jego sekret.
  6. „Klucze w Vault” to twierdzenie o danych w spoczynku, a nie w czasie działania. Klucz Dzierżawcy w postaci jawnej jest przechowywany w pamięci aplikacji i ponownie używany przez najwyżej 60 sekund, a klucz TOTP platformy — przez cały czas życia procesu. Kto może odczytać pamięć działającego kontenera, może odczytać klucze, jak w każdym projekcie, który cokolwiek odszyfrowuje. Klucze Dzierżawców zmieniają to, że skradziony dysk, kopia zapasowa bazy danych, kopia do odtwarzania do punktu w czasie ani konfiguracja kontenera nie ujawniają żadnego klucza Dzierżawcy.
  7. Awaria Vault staje się awarią wszystkich zaszyfrowanych sekretów połączeń. Od włączenia kluczy Dzierżawców 2026-10-10 awaria Vault czyni szesnaście kolumn poświadczeń w dziewięciu tabelach jednocześnie nieczytelnymi dla wszystkich Dzierżawców — logowanie SSO, poczta Microsoft Graph, Slack, Teams, PagerDuty, ServiceNow, Jira i SIEM — a platforma odmawia działania (logowanie SSO odpowiada komunikatem o chwilowej niedostępności), zamiast sięgać po klucz ogólnoplatformowy. Logowanie hasłem lokalnym i TOTP zaprojektowano tak, aby nie wywoływało Vault przy każdym żądaniu.
  8. Poświadczenie operatora, które może autoryzować kryptograficzne usunięcie, jest pełnym administratorem Vault i nie może być niczym mniej. Ograniczenie jest proceduralne — domyślnie tryb próbny, najpierw wiersz audytu, poświadczenie nieprzechowywane na żadnym serwerze produkcyjnym — a nie kryptograficzne.
  9. Poświadczenie służące do tworzenia kluczy nie może niszczyć ich wersji. Musi móc rotować klucze i ustawiać minimalną wersję odszyfrowania, więc może czasowo uniemożliwić odszyfrowanie danych Dzierżawcy — to awaria, odwracalna jednym zapisem — ale Vault odmawia mu operacji, która trwale usuwa wersje klucza. Zweryfikowano na aktywnej polityce w obu wdrożeniach produkcyjnych 2026-09-22.
  10. Wycofane klucze ogólnoplatformowe przetrwały wyłącznie w zaszyfrowanych migawkach Vault, do około 2026-11-10. Klucz, którym szyfrowano kopie poświadczeń pod kluczem ogólnoplatformowym (IAM_OIDC_KEY), oraz dawny klucz sekretów TOTP (IAM_TOTP_KEY) zniknęły z aplikacji i z bieżących sekretów Vault w obu wdrożeniach (2026-10-11). Tego samego dnia wszystkie starsze wersje magazynu klucz-wartość Vault, które nadal przechowywały którykolwiek z nich, zostały trwale zniszczone, a Operator usunął swoje kopie depozytowe offline obu kluczy. Jedyne kopie, które można przywrócić, znajdują się w zaszyfrowanych nocnych migawkach Vault wykonanych wcześniej i przechowywanych przez najwyżej 30 dni, więc ostatnia z nich wygaśnie około 2026-11-10. Żaden szyfrogram pod kluczem IAM_OIDC_KEY nie istnieje, więc jego kopie niczego nie odszyfrowują. Kopie zapasowe bazy danych wykonane przed migracją klucza TOTP (P0-1, faza 6, 2026-10-11) zawierają sekrety TOTP zaszyfrowane kluczem IAM_TOTP_KEY; odtworzenie migawki Vault wykonanej przed usunięciem klucza pozwoliłoby je ponownie odczytać, dopóki same te kopie zapasowe nie wygasną po 30 dniach.