diff --git a/docs/kb/kb-02-documents-design.md b/docs/kb/kb-02-documents-design.md new file mode 100644 index 0000000..a153c73 --- /dev/null +++ b/docs/kb/kb-02-documents-design.md @@ -0,0 +1,111 @@ +# KB filar #2 — Dokumenty (Nextcloud + Paperless) — design + +> Dokument-master filaru dokumentow. Stoi pod `kb-00-overview.md`. +> Cel: kazda sesja / Claude Code startuje z pelnym kontekstem decyzji. +> Status: ARCHITEKTURA ZAMKNIETA (2026-07-01), implementacja modulowa czeka. +> Moduly implementacyjne: `docs/kb/modules/0X-*.md` — puszczane CC jeden po drugim. + +--- + +## Kontekst — miejsce w architekturze KB + +Filar #2 z czterech (maile > **dokumenty** > zdjecia > transakcje). Reuzywa ~80% +wzorca maili (text RAG + archiwum + embeddingi na SOLARIA), dokłada OCR i wlasna +migracje Drive -> self-host. Wpina sie w te sama koperte (`id/source/ts/geo/raw_ref/ +entities[]`) i ten sam spine (Postgres+pgvector na PIHA). + +Dwa zrodla dokumentow (dwa adaptery ingest): +- **Nextcloud** — zamiennik Drive, dowolne pliki + sync (WebDAV) +- **Paperless-ngx** — skany/faktury/umowy z OCR (Paperless API) + +--- + +## Decyzje ZAMKNIETE + +### Tozsamosc / SSO = Forgejo-OIDC +Forgejo (biega na PIHA, always-on, zweryfikowane docker ps) jest IdP. Nextcloud/ +Paperless/Immich wpinaja sie przez natywny OIDC — wzorzec jak Vikunja (jedyny +dzisiejszy konsument). Authentik/forward-auth = otwarta przyszla opcja dla infra +(panele/monitoring bez OIDC), POZA zakresem KB. Spec: `modules/01-sso-forgejo-oidc.md`. + +### Ingress = LAN/Tailscale only, ZERO public +Dokumenty to dane wrazliwe (faktury/umowy/prywatne pliki) — zasada kb-00 #4 local-first. +Wpinaja sie w **npm na PIHA** (LAN ingress :80/:443), NIE w npm na VPS (public). +Dostep spoza domu = przez Tailscale mesh. Zero certow public dla tych serwisow. + +### Archiwum = HYBRYDA (kopia vs referencja per zrodlo) +- **Nextcloud -> KOPIA** do archiwum KB (pliki w Nextcloud znikaja/zmieniaja sie; + KB robi snapshot przy ingescie, wersjonowanie przez append koperty) +- **Paperless -> REFERENCJA** (jego storage = zrodlo prawdy; KB trzyma raw_ref + OCR-text) +- **WARUNEK BRZEGOWY**: backup Paperless storage OBOWIAZKOWY (bo referencja = KB zalezy + od zywotnosci Paperlessa; bez backupu = pojedynczy punkt awarii) + +### Host = SPLIT serwis/OCR (rozwiazuje kolizje moc-vs-always-on) +Zadny pojedynczy node nie jest jednoczesnie mocny I always-on: +- VPS: RAM wyczerpany (121Mi wolne) — OUT +- PIHA: always-on ale ciasno (3.1Gi available, swap juz 2G uzyty) +- SOLARIA: mocarz (62Gi RAM, GPU, 315G) ale dostepnosc sesyjna (nie 24/7) + +Rozwiazanie — rozdziel warstwy wg wymogu dostepnosci: +- **Paperless-serwis** (UI+API+Postgres+Redis) na **PIHA** — always-on, lekki w spoczynku, + dostepny 24/7 dla zapytan KB. Miesci sie w 3.1Gi available (ciasno). +- **OCR-worker** na **SOLARIA** — CPU/GPU-glodny OCR batch (70k zalacznikow), podpiety + do kolejki Redis@PIHA. 62Gi RAM stoi odlogiem. +- **FALLBACK**: SOLARIA spi -> OCR-worker na PIHA domiela wolno, ALBO zadania czekaja + w kolejce Redis az SOLARIA wstanie (dokumenty nie sa pilne w sekundach). + +Uzasadnienie splitu: OCR jest batch/async (fallback trywialny — kolejka czeka). +Stateful-serwis (baza) NIE fallbackuje latwo (replikacja pg = kruche) -> stoi w jednym +miejscu (PIHA). Wzorzec: "serwis always-on + compute-worker on-demand z fallback". + +### PREREKWIZYT: odchudzic PIHA +PIHA na styku RAM (swap 2G uzyty). Przed deployem Paperlessa — audyt 33 shadow-kontenerow +(inwentaryzacja 2026-06-30): kandydaci do usuniecia/przeniesienia (elasticsearch 1Gi? +diskover? duplikaty exporterow?). Laczy sie z backlogiem grupy C. Spec: `modules/00-piha-slim.md`. + +--- + +## Mapa modulow (kolejnosc egzekucji) + +| # | Modul | Plik | Zalezy od | +|---|---|---|---| +| 0 | Odchudzic PIHA (prerekwizyt) | `modules/00-piha-slim.md` | — | +| 1 | SSO Forgejo-OIDC (decyzja+wzorzec) | `modules/01-sso-forgejo-oidc.md` | — | +| 2 | Paperless serwis (PIHA) | `modules/02-paperless-service.md` | 0,1 | +| 3 | Paperless OCR-worker (SOLARIA+fallback) | `modules/03-paperless-ocr-worker.md` | 2 | +| 4 | Nextcloud (WebDAV+OIDC) | `modules/04-nextcloud.md` | 0,1 | +| 5 | Ingest -> koperta | `modules/05-documents-ingest.md` | 2,4 | + +Kazdy modul = samodzielny spec do puszczenia CC ("czytaj i implementuj krok po kroku"). + +--- + +## Ingest -> koperta (warstwa 2, wspolna dla obu zrodel) + +Kazdy dokument -> koperta KB: +- `source` = `nextcloud` | `paperless` +- `id` = stabilny (Paperless doc-id | Nextcloud file-id+etag) +- `ts` = data dokumentu (Paperless wykrywa z tresci! lepsze niz mtime) +- `raw_ref` = Nextcloud: sciezka do KOPII w archiwum KB | Paperless: referencja doc-id +- `entities[]` = OCR-text + correspondent + tags (z Paperless API) + +## Graf encji (warstwa 3, cienki start) +- **correspondent** (kto wystawil dokument) = encja -> link do maili (ten sam nadawca + w mailu i fakturze = ta sama encja). PIERWSZY cross-source link (dowod zasady kb-00 #7). +- data dokumentu = klucz czasowy do zlaczen spatio-temporalnych. + +## Domkniecie dlugu z maili +Faza-2-zalacznikow (70k zalacznikow / 15.4GB z importu Gmaila): faktury/umowy/PDFy +routuja do Paperless (jego OCR + correspondent-detection), NIE osobny pipeline. +Realizowane po modulach 2-3 (Paperless dziala) jako job w module 5. + +--- + +## OTWARTE kwestie + +- **Nextcloud host** — PIHA (ciasno) czy SOLARIA (drive nie musi byc 24/7 tak twardo + jak indeks KB)? Do rozstrzygniecia przy module 4. Wstepnie: rozwazyc SOLARIA, bo + Nextcloud ciezszy (PHP+baza+storage sync) niz Paperless-serwis. +- **Sizing OCR-batch** — ile trwa OCR 70k zalacznikow na SOLARIA, czy dzielic na partie. +- **Backup Paperless** — gdzie (PIHA NVMe? SOLARIA? offsite?), jaka retencja. Warunek + brzegowy hybrydy — do zaprojektowania w module 2. diff --git a/docs/kb/modules/00-piha-slim.md b/docs/kb/modules/00-piha-slim.md new file mode 100644 index 0000000..1a0f6a9 --- /dev/null +++ b/docs/kb/modules/00-piha-slim.md @@ -0,0 +1,28 @@ +# Modul 0 — Odchudzic PIHA (prerekwizyt filaru dokumentow) + +> Prerekwizyt modulow 2/4 (Paperless/Nextcloud na PIHA). Bez tego PIHA nie ma +> komfortowego zapasu RAM. Laczy sie z backlogiem grupy C (audyt shadow-kontenerow). + +## Cel +Zwolnic RAM na PIHA (dzis: 3.1Gi available, swap 2G uzyty) tak, by lekki Paperless- +serwis wszedl z zapasem, nie na styku swap. + +## Wymogi +- Audyt 33 shadow-kontenerow (lista w `docs/infra/inventory-2026-06-30.md`). +- Zidentyfikowac kandydatow do usuniecia/przeniesienia/wylaczenia: + - **elasticsearch 1Gi** — kto tego uzywa? (wikijs? diskover?) — jesli martwy, ubic + - **diskover** — jednorazowy indekser? czy chodzi ciagle bez potrzeby? + - duplikaty exporterow / stare agent-system-* kontenery + - cokolwiek Up ale bez konsumenta +- Cel: >= 1.5Gi available STABILNIE (bez swap pod presja) przed deployem Paperlessa. + +## Do zweryfikowania przez CC +- Per shadow-kontener: kto go wola (docker network, zaleznosci, porty konsumowane)? +- Czy usuniecie czegos nie zerwie dzialajacego serwisu (np. elasticsearch pod wikijs)? +- `docker stats` przed/po — realny zysk RAM. + +## Kryteria ukonczenia +- PIHA ma >= 1.5Gi available stabilnie, swap nie rosnie pod normalnym obciazeniem. +- Usuniete/przeniesione kontenery udokumentowane (co, dlaczego, dokad). +- Zmiany zgodne z GitOps (te ktore zostaja -> do hosts/piha/services.yaml). +- NIE ubijac na slepo — kazdy kandydat zweryfikowany (kto uzywa) przed usunieciem. diff --git a/docs/kb/modules/01-sso-forgejo-oidc.md b/docs/kb/modules/01-sso-forgejo-oidc.md new file mode 100644 index 0000000..3ffcac1 --- /dev/null +++ b/docs/kb/modules/01-sso-forgejo-oidc.md @@ -0,0 +1,28 @@ +# Modul 1 — SSO Forgejo-OIDC (decyzja + wzorzec wpiecia) + +> Fundament tozsamosci dla filaru dokumentow (i szerzej homelaba). Zapisuje decyzje +> (dzis zyje tylko "ustnie") + wzorzec wpiecia serwisu w Forgejo-OIDC. + +## Cel +Udokumentowac Forgejo jako IdP + dostarczyc powtarzalny wzorzec: "jak wpiac nowy +serwis (Nextcloud/Paperless/Immich) w Forgejo-OIDC", na bazie dzialajacej Vikunji. + +## Wymogi +- Zapis decyzji: Forgejo-OIDC = IdP homelaba. Always-on na PIHA. Uzasadnienie + (mniej ruchomych czesci, sprawdzone w boju, Nextcloud/Paperless/Immich maja OIDC). +- Wzorzec rejestracji OAuth2 app w Forgejo (Settings > Applications) — kroki. +- Wzorzec konfiguracji po stronie klienta (issuer `forgejo.okit.pl/.well-known/ + openid-configuration`, client_id/secret, redirect_uri, scopes). +- Odniesienie do dzialajacej Vikunji jako wzorca referencyjnego (services/vikunja/). + +## Do zweryfikowania przez CC +- Jak dokladnie Vikunja wpina sie w Forgejo (services/vikunja/config.yml, env.example, + docker-compose.yml) — wyciagnac wzorzec. +- Co Forgejo-OIDC wystawia (scopes, claims — groups? email? username?). +- Czy Nextcloud/Paperless natywny OIDC jest kompatybilny z tym co Forgejo daje. +- Gdzie trzymac client_secret (env, nie w repo — wzorzec sekretow). + +## Kryteria ukonczenia +- `docs/infra/sso-forgejo-oidc.md` (albo sekcja) z decyzja + wzorcem per-serwis. +- Wzorzec na tyle konkretny, by moduly 2/4 mogly go zastosowac bez zgadywania. +- Jasne: co idzie do env (sekrety), co do compose, co do Forgejo admin. diff --git a/docs/kb/modules/02-paperless-service.md b/docs/kb/modules/02-paperless-service.md new file mode 100644 index 0000000..a1097d6 --- /dev/null +++ b/docs/kb/modules/02-paperless-service.md @@ -0,0 +1,39 @@ +# Modul 2 — Paperless-ngx serwis (na PIHA) + +> Serwis dokumentow: UI+API+Postgres+Redis. Always-on na PIHA. OCR-worker OSOBNO +> (modul 3). Zalezy od: 0 (odchudzic PIHA), 1 (SSO). + +## Cel +Postawic Paperless-ngx jako serwis GitOps na PIHA — bez ciezkiego OCR (ten na SOLARIA, +modul 3). Serwis dostepny 24/7 dla zapytan KB + UI do przegladania. + +## Wymogi +- `services/paperless/` — docker-compose.yml + service.yaml (owner_node=piha). +- Komponenty: paperless-webserver (UI+API), postgres, redis (broker kolejki OCR). +- **OIDC** przez Forgejo (wzorzec z modulu 1). Login = konto Forgejo. +- **Ingress LAN-only** przez npm@PIHA (NIE public/VPS). Subdomena np. paper.kapala.org + lub paper.okit.pl -> A record na Tailscale/LAN, DNS Only. +- **Storage**: media + oryginaly na PIHA NVMe (/home/docker lub dedykowany volume). +- **Backup** (WARUNEK BRZEGOWY hybrydy — Paperless=referencja): storage backupowany. + Zaprojektowac: gdzie (offsite? SOLARIA? drugi dysk?), retencja, jak (paperless + document-exporter / rsync volume / borg?). +- OCR w tym module WYLACZONY lub minimalny — ciezki batch idzie na worker (modul 3). + Redis wystawiony tak, by worker na SOLARIA mogl sie podpiac (Tailscale). + +## Do zweryfikowania przez CC +- Realne zuzycie RAM Paperless-serwis bez OCR na arm64 (czy miesci sie po odchudzeniu PIHA). +- Porty — kolizje na PIHA (juz 40 kontenerow, sprawdzic wolne). +- Paperless env: PAPERLESS_REDIS, PAPERLESS_DBHOST, PAPERLESS_OCR_* , PAPERLESS_URL, + PAPERLESS_TASK_WORKERS / PAPERLESS_THREADS_PER_WORKER (pod split OCR). +- OIDC w Paperless: PAPERLESS_APPS / python-social-auth / mozilla-django-oidc — ktory + mechanizm, jak skonfigurowac przeciw Forgejo. +- arm64 image dostepny (ghcr.io/paperless-ngx/paperless-ngx). +- Jak Redis ma byc osiagalny dla worker@SOLARIA (bind Tailscale IP, nie tylko localhost). + +## Kryteria ukonczenia +- Paperless UI dziala na PIHA, login przez Forgejo-OIDC. +- Dostepny LAN/Tailscale, NIE z publicznego internetu. +- Redis broker osiagalny dla zewnetrznego workera (modul 3). +- Backup storage zaprojektowany i dzialajacy (nie "TODO"). +- W GitOps: services/paperless/ + wpis w hosts/piha/services.yaml + topology. +- Deploy przez normalny flow (nie manualnie na hoscie). diff --git a/docs/kb/modules/03-paperless-ocr-worker.md b/docs/kb/modules/03-paperless-ocr-worker.md new file mode 100644 index 0000000..c2e838b --- /dev/null +++ b/docs/kb/modules/03-paperless-ocr-worker.md @@ -0,0 +1,37 @@ +# Modul 3 — Paperless OCR-worker (SOLARIA + fallback PIHA) + +> Ciezki OCR odseparowany od serwisu. Worker na SOLARIA (moc), fallback PIHA (wolno). +> Realizuje wzorzec "compute on-demand z fallback". Zalezy od: 2 (serwis+Redis dziala). + +## Cel +Przetwarzac OCR dokumentow (w tym batch 70k zalacznikow z maili) na mocy SOLARII, +z gracefull fallback gdy SOLARIA offline — zadania czekaja w kolejce, nie gina. + +## Wymogi +- Worker Paperless (ten sam obraz, tryb worker/consumer) na SOLARIA, podpiety do + Redis@PIHA (broker z modulu 2) przez Tailscale. +- `services/paperless-worker/` — compose + service.yaml (owner_node=solaria). +- **Fallback**: gdy SOLARIA offline -> zadania OCR czekaja w Redis (naturalne dla + Celery/task queue). OPCJONALNIE: lekki worker na PIHA (male concurrency) domiela + wolno, by nie blokowac w nieskonczonosc. Decyzja: kolejka-czeka vs slaby-worker-piha. +- Worker na SOLARIA moze uzyc GPU/wielu rdzeni (PAPERLESS_TASK_WORKERS wyzsze niz na PIHA). +- Batch 70k zalacznikow (modul 5 / faza-2) routowany przez ten worker — sizing/partie. + +## Do zweryfikowania przez CC +- Czy Paperless-ngx wspiera oddzielny worker na innym hoscie dzielacy Redis+Postgres+ + storage (WSPOLNY storage to wyzwanie — worker musi widziec te same pliki!). + UWAGA: to kluczowe — OCR-worker potrzebuje dostepu do storage dokumentow. Opcje: + (a) storage na PIHA montowany przez siec (NFS/sshfs) na SOLARIA — wolne/kruche, + (b) worker wysyla wynik OCR z powrotem bez wspoldzielenia storage, + (c) inny podzial. CC musi zweryfikowac architekture Paperless consumer/worker. +- Jak Paperless dzieli prace: consumer (obserwuje folder) vs task-worker (OCR) — + ktora czesc idzie na SOLARIA. +- Latencja Tailscale PIHA<->SOLARIA dla Redis/Postgres (czy akceptowalna). +- Co sie dzieje gdy worker@SOLARIA znika w polowie zadania (retry? lost?). + +## Kryteria ukonczenia +- OCR wykonuje sie na SOLARIA gdy dostepna (weryfikowalne: obciazenie CPU tam, nie PIHA). +- SOLARIA offline -> zadania czekaja / domielane wolno, ZERO utraty zadan. +- SOLARIA wraca -> kolejka sie rozladowuje. +- Batch-mode dla 70k zalacznikow przetestowany na probce. +- W GitOps: services/paperless-worker/ + hosts/solaria/services.yaml + topology.