docs(kb): incydent 20 dni ciszy kb-mail-sync + session log
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).
This commit is contained in:
parent
013eeb429b
commit
4fa10f0a72
44
docs/sessions/2026-08-26-kb-incydent-mailsync.md
Normal file
44
docs/sessions/2026-08-26-kb-incydent-mailsync.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: session-log
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-26
|
||||
links: []
|
||||
---
|
||||
|
||||
# Sesja 2026-08-26 — incydent kb-mail-sync: 20 dni ciszy, wykryte i naprawione
|
||||
|
||||
## Timeline
|
||||
|
||||
- **Wykrycie** — przy sanity checku po 3 tygodniach bez nadzoru (kontynuacja sesji 16:00,
|
||||
patrz `docs/sessions/2026-08-26.md`): `mail-imap-sync` nie zapisał żadnej koperty od
|
||||
2026-08-06 18:01 (pierwszy i jedyny udany tick automatu) mimo że timer tykał godzinowo
|
||||
przez 20 dni. ~548 maili zaległości.
|
||||
- **Diagnoza** — `PermissionError` na `save_eml`: katalogi archiwum `2026/08` powstały
|
||||
`root:root` z ręcznych `sudo`-runów 06.08, timer działa jako `oskar`. Kursor nie
|
||||
przeskakiwał niezapisanej wiadomości (zgodnie z projektem) — stąd cisza bez utraty poczty,
|
||||
ale też bez sygnału.
|
||||
- **Naprawa zapisu** — `chown -R oskar:oskar` na archiwum + dwa ręczne ticki: run#1
|
||||
170 inserted/379 perm-errors (zaległości sprzed chowna), run#2 378 inserted/155
|
||||
archive_exists/0 errors — pełne odzyskanie.
|
||||
- **Reload Prometheusa** — przez CC z SOLARII (SSH na VPS): `promtool check rules` OK,
|
||||
`POST /-/reload`, weryfikacja `/api/v1/rules` (wszystkie trzy grupy żywe), metryka
|
||||
scrape'owana i świeża, `/api/v1/alerts` czyste, `brain-watchdog`→Telegram wpięty
|
||||
poprawnie (`PROMETHEUS_URL` OK, kontener healthy).
|
||||
|
||||
Pełny opis root cause (oba, niezależne) i rekomendacje R1–R3:
|
||||
[kb/incidents/2026-08-26-mail-sync-20-dni-ciszy.md](../../kb/incidents/2026-08-26-mail-sync-20-dni-ciszy.md).
|
||||
|
||||
## Stan
|
||||
|
||||
Przyrostówka **znów żywa** i **po raz pierwszy faktycznie monitorowana** — reguła
|
||||
`KbMailSyncStale` istniała w repo od 06.08, ale dopiero teraz jest realnie załadowana w
|
||||
Prometheusie. Wcześniej alert nie mógł wystrzelić niezależnie od tego, jak długo trwałaby
|
||||
awaria zapisu.
|
||||
|
||||
## Plan sprzed incydentu — przesunięty
|
||||
|
||||
Rotacja haseł (`kb-postgres` + teraz też `TG_TOKEN`, wyciekł w tej sesji przez `cat .env`
|
||||
diagnostyczny — czwarty przypadek tej klasy) i recon Fazy 5 (wiki-kompilat) — obie pozycje
|
||||
przesunięte na następną sesję, nie ruszone dzisiaj poza samą diagnozą.
|
||||
152
kb/incidents/2026-08-26-mail-sync-20-dni-ciszy.md
Normal file
152
kb/incidents/2026-08-26-mail-sync-20-dni-ciszy.md
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
---
|
||||
okf: "0.1"
|
||||
type: incident
|
||||
visibility: private
|
||||
status: active
|
||||
updated: 2026-08-26
|
||||
links:
|
||||
- ../audits/mail-sync-2026-08-06.md
|
||||
- ../services/job-mail-imap-sync.md
|
||||
- ../runbooks/mail-sync-run.md
|
||||
- ../../docs/sessions/2026-08-06-kb-mail-sync-live.md
|
||||
- ../../docs/sessions/2026-08-26-kb-incydent-mailsync.md
|
||||
---
|
||||
|
||||
# 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](../../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](../runbooks/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](../services/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](../../services/fleet-prometheus/rules/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):**
|
||||
1. `chown -R oskar:oskar ~/kb/mail/archive/{gmail,fastmail}/2026/08` na PIHA.
|
||||
2. 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).
|
||||
3. 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):**
|
||||
1. `promtool check rules` na `kb-mail-sync.yml` w kontenerze `fleet-prometheus` — OK,
|
||||
plik był już poprawny składniowo (potwierdzenie, że problem był czysto operacyjny, nie
|
||||
błąd w regule).
|
||||
2. `POST http://100.95.58.48:9090/-/reload` — 200, `/api/v1/rules` od razu pokazał wszystkie
|
||||
trzy grupy: `fleet-liveness`, `kb-ingest`, `kb-mail-sync`.
|
||||
3. 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ła `KbMailSyncStale` w stanie `inactive`/`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_URL` w `.env` poprawnie wskazuje na
|
||||
`http://100.95.58.48:9090`, kontener `healthy` od 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](../../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](../../docs/sessions/2026-08-06-kb-mail-sync-live.md)
|
||||
"Otwarte":
|
||||
- Fix `UID SEARCH ALL` na 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_state` dogonił IMAP na obu kontach, 548 zaległych kopert wchłonięte,
|
||||
0 błędów w ostatnim ticku.
|
||||
- `fleet-prometheus` ma żywe wszystkie trzy grupy reguł; `KbMailSyncStale` faktycznie
|
||||
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).
|
||||
Loading…
Reference in a new issue