Dwa niezalezne root cause: PermissionError na save_eml (archiwum root:root po sudo-runach 06.08) + fleet-prometheus nigdy nie dostal /-/reload po dodaniu regul kb-mail-sync.yml/kb-ingest.yml (zylo tylko fleet-liveness). Naprawa: chown archiwum + 2 tick recovery (548 kopert, 0 bledow) + reload Prometheusa z weryfikacja lancucha alertowego end-to-end (brain-watchdog->Telegram wpiety poprawnie).
8.3 KiB
| okf | type | visibility | status | updated | links | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| 0.1 | incident | private | active | 2026-08-26 |
|
Incydent: kb-mail-sync bez zapisu przez 20 dni, niewykryty — 2026-08-26
Status: oba root cause ustalone i naprawione. Przyrostówka odzyskana, alerting po raz
pierwszy realnie wpięty (wcześniej istniał tylko w repo, nie w runtime).
Dotknięty serwis: mail-imap-sync (job) @ PIHA + fleet-prometheus @ VPS.
Klasa: dwa niezależne błędy nakładające się w czasie — awaria zapisu (uprawnienia) +
martwy monitoring (config nigdy nie przeładowany). Osobno każdy byłby wykrywalny; razem
dały 20 dni ciszy bez żadnego sygnału.
1. TL;DR
kb-mail-sync.timer tykał godzinowo od uruchomienia (2026-08-06 18:01, patrz
docs/sessions/2026-08-06-kb-mail-sync-live.md)
bez ani jednego kolejnego udanego zapisu koperty aż do 2026-08-26. Poller "żył" — proces
startował, łączył się z IMAP, kursor w mail_sync_state się nie ruszał, bo save_eml dostawał
PermissionError na każdej próbie zapisu. Kursor nie przeskoczył niezapisanej wiadomości — to
zadziałało zgodnie z projektem (zero utraty poczty), ale oznaczało też, że failure był cichy: bez
crasha, bez zmiany stanu widocznej z zewnątrz poza rosnącym opóźnieniem.
Powinien to złapać alert KbMailSyncStale (reguła w repo od 2026-08-06) — ale nie złapał, bo
fleet-prometheus na VPS nigdy nie dostał /-/reload po dodaniu tego pliku reguł. Przez cały
czas żyła wyłącznie grupa fleet-liveness sprzed czerwca. Wykryto ręcznie, przy sanity checku po
3 tygodniach przerwy operatorskiej — nie przez monitoring.
2. Root cause #1 — uprawnienia katalogów archiwum
~/kb/mail/archive/{gmail,fastmail}/2026/08/ powstały jako root:root — utworzone przez
ręczne sudo-runy z 2026-08-06 (pierwsze uruchomienia przed włączeniem timera, patrz runbook
mail-sync-run.md, sekcja o sudo do odczytu .env). Timer
uruchamia job jako User=oskar (po zrzuceniu uprawnień z jednostki systemd) — save_eml w
packages/kb-mail dostawał PermissionError przy próbie zapisu .eml do katalogu należącego do
roota, na każdym z 480 ticków od 2026-08-06 18:01 do naprawy.
Design "kursor nie przeskakuje niezapisanej wiadomości" (pkg-kb-mail.md) zadziałał dokładnie tak jak zamierzono: zero utraty poczty, folder stał w miejscu zamiast przeskoczyć błąd i zostawić dziurę w korpusie. Cena tego bezpieczeństwa: bez monitoringu wygląda identycznie jak "brak nowej poczty" — legalny stan mailboxa, którego runbook świadomie nie traktuje jako alarmowy (patrz decyzja w kb-mail-sync.yml o odrzuceniu progu na "brak nowej poczty").
3. Root cause #2 — dlaczego 20 dni ciszy, nie 6 godzin
Reguła KbMailSyncStale (próg 6h, for: 5m) i kb-ingest.yml leżały w repo od 2026-08-06.
Scrape config PIHA (fleet-node/piha → 100.108.208.3:9100) był poprawny od czerwca — target
node_exportera PIHA już był zdefiniowany. Ale fleet-prometheus na VPS nigdy nie dostał
POST /-/reload po tym, jak te dwa pliki reguł wylądowały w bind mouncie rules/. W runtime
żyła wyłącznie grupa fleet-liveness, załadowana przy ostatnim restarcie kontenera (czerwiec).
Alert KbMailSyncStale nie istniał operacyjnie — mógł mieć idealną logikę i wciąż nic by nie
wysłał, bo Prometheus nie wiedział o jego istnieniu.
Dwa błędy nałożyły się: gdyby monitoring żył, alert wystrzeliłby po ~6h od pierwszego
PermissionError (2026-08-07 ok. 00:00), nie po 20 dniach. Gdyby zapis działał, martwy
monitoring nie miałby czego przegapić.
4. Naprawa
Zapis (2026-08-26, przez CC z SOLARII, worktree recon+fix na PIHA):
chown -R oskar:oskar ~/kb/mail/archive/{gmail,fastmail}/2026/08na PIHA.- Ręczny tick #1:
170 inserted / 379 perm-errors— perm-errors to zaległe próby sprzed chowna w tej samej partii (kolejka nie czyściła się między nieudanymi próbami). - Ręczny tick #2:
378 inserted / 155 archive_exists, errors=0— pełne odzyskanie, kursor dogonił IMAP. Łącznie 548 zaległych kopert wchłonięte bez strat.
Monitoring (2026-08-26, przez CC z SOLARII, SSH na VPS):
promtool check rulesnakb-mail-sync.ymlw kontenerzefleet-prometheus— OK, plik był już poprawny składniowo (potwierdzenie, że problem był czysto operacyjny, nie błąd w regule).POST http://100.95.58.48:9090/-/reload— 200,/api/v1/rulesod razu pokazał wszystkie trzy grupy:fleet-liveness,kb-ingest,kb-mail-sync.- Weryfikacja łańcucha end-to-end:
kb_mail_sync_last_success_timestamp{node="piha"}— scrape'owana, świeża (~5,8 min)./api/v1/alerts— pusto; regułaKbMailSyncStalew stanieinactive/health: ok(nigdy nie zdążyła nic zaalarmować na starych danych — pierwsza ewaluacja po reloadzie zastała już świeżą metrykę).brain-watchdog@ PIHA —PROMETHEUS_URLw.envpoprawnie wskazuje nahttp://100.95.58.48:9090, kontenerhealthyod 2 tygodni, brak wpisów o poll-failure w logach → droga do Telegrama wpięta.
Żadna zmiana w repo nie była potrzebna dla naprawy monitoringu — config rules/*.yml i
scrape_configs były poprawne od dawna, brakowało wyłącznie /-/reload w runtime.
5. Rekomendacje
R1 (proces, do CC) — utwardzić własność katalogów po ręcznym sudo-runie. Po każdym
ręcznym uruchomieniu mail-imap-sync przez sudo (np. do odczytu .env 600 root:root, patrz
runbook): albo chown -R oskar:oskar na archive/ od razu po runie, albo wariant sudo
zachowujący ownera docelowych katalogów. Docelowo save_eml/definicja jednostki systemd
powinny wymuszać poprawnego ownera tworzonych katalogów niezależnie od tego, kto je stworzył
(np. umask/chown przy starcie joba, albo katalogi tworzone z wyprzedzeniem z właściwymi
uprawnieniami zamiast mkdir -p przy pierwszym zapisie).
R2 (proces, do CC) — dopisać /-/reload do procedury deployu reguł Prometheusa. Dodanie
pliku reguł do services/fleet-prometheus/rules/ bez reloadu jest w tej chwili niewidoczne —
git diff pokazuje zmianę, deploy przechodzi zielono, a Prometheus i tak jej nie widzi aż do
następnego restartu kontenera. Brakujący krok reload trzeba dopisać do runbooka deployu
fleet-prometheus (do zlokalizowania/utworzenia: fleet-prometheus-deploy.md), najlepiej jako
automatyczny krok w scripts/deploy/deploy.sh dla tego serwisu, nie tylko jako notatka w
dokumentacji.
R3 (bezpieczeństwo, pilne) — rotacja sekretów po wycieku w transkrypcie. TG_TOKEN
brain-watchdoga wypłynął w outpucie sesji 2026-08-26 (cat .env przez SSH w celach
diagnostycznych) — czwarty udokumentowany przypadek tej klasy (poprzedni: hasło
kb-postgres, 2026-08-05/06, patrz docs/sessions/2026-08-06-kb-mail-sync-live.md
sekcja "Otwarte"). Do rotacji łącznie: TG_TOKEN (brain-watchdog) + hasło kb-postgres
(WISI) — oba są zaległe z poprzednich incydentów tej samej klasy i warto zrobić je w jednej
sesji zamiast kolejnych osobnych.
6. Nie w zakresie tej naprawy (follow-upy niezmienione z 2026-08-06)
Bez zmian względem stanu z poprzedniej sesji — patrz docs/sessions/2026-08-06-kb-mail-sync-live.md "Otwarte":
- Fix
UID SEARCH ALLna duże foldery (crash na kontach >_MAXLINE). - Załączniki PDF z maili.
- Charset/mojibake w co najmniej 12 kopertach.
- NUL w nagłówkach
jsonb(gmail-header-backfill/bulk-import).
7. Stan końcowy
- Kursor
mail_sync_statedogonił IMAP na obu kontach, 548 zaległych kopert wchłonięte, 0 błędów w ostatnim ticku. fleet-prometheusma żywe wszystkie trzy grupy reguł;KbMailSyncStalefaktycznie monitoruje po raz pierwszy od wdrożenia 2026-08-06.- Łańcuch metryka → reguła → alert →
brain-watchdog→ Telegram zweryfikowany end-to-end, bez dziur. - Otwarte: R1–R3 powyżej (poza zakresem tej sesji, do osobnych tasków).