homelab-codex-ws/docs/kb/kb-00-overview.md

147 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Baza wiedzy — przegląd i log decyzji (homelab-codex · KB)
> Master-dokument inicjatywy. Stoi ponad dokumentami per-projekt (`kb-01-email-design.md`, …).
> Cel: każda kolejna sesja / Claude Code startuje z pełnym kontekstem ustaleń.
> Status: implementacja ruszyła. Etap 1 (fundament) done; spine Postgres+pgvector stoi na **PIHA** (always-on); bulk importer Gmaila następny.
---
## Czym to jest
Nie sama „baza wiedzy" — **de-Google'izacja życia + warstwa wiedzy na wierzchu.**
Każde źródło ma dwie twarze:
- **migracja off-cloud** — gdzie dane fizycznie lądują u Ciebie,
- **archiwum + ingest** — warstwa wiedzy.
---
## Architektura: 4 warstwy × 4 filary + rdzeń
Dwa spojrzenia, ta sama rzecz:
- **Pionowo — 4 filary źródeł**, każdy = `ingest + index` (per-filar, wymienny): maile · dokumenty · zdjęcia · transakcje.
- **Poziomo — 4 warstwy** przepływu:
1. **Ingest** — per filar (adaptery przeciw protokołom).
2. **Preprocess + Index** — per filar (parse/chunk/embed → pgvector; transakcje → SQL).
3. **Join + Enrich****wspólny rdzeń**: entity resolution, graf encji, klucz czasoprzestrzenny.
4. **Advanced analytics + NL query****wspólny**: agent interdyscyplinarny, zapytania w języku naturalnym, analityka LLM.
Dwa dolne tiery są per-filar i neutralne. Dwa górne są wspólne dla wszystkich źródeł.
**OwnTracks = nie piąty filar, lecz klucz czasoprzestrzenny w warstwie 3** (ciągła funkcja czas→miejsce, bez własnego ingestu/agenta).
```
[ 4. Agent interdyscyplinarny ] NL query + analityka (LLM)
↑ (wspólne)
[ 3. Join + Enrich ] entity resolution · graf · OwnTracks (czas+miejsce)
↑ ↑ ↑ ↑ (wspólne)
[ 2. Preprocess + Index ] → pgvector / → SQL
↑ ↑ ↑ ↑ (per filar)
[ 1. Ingest ]
Maile Dokumenty Zdjęcia Transakcje
```
---
## Zasady przekrojowe (obowiązują każdy projekt)
1. **Archiwum ≠ indeks.** Archiwum surowe/niezmienne (asset, wieczne); indeks pochodny i odtwarzalny (wyrzucalny). Re-indeks z archiwum przy lepszym modelu.
2. **Koperta = jedyny kontrakt zamrożony z góry.** Addytywna. Zamrożone: `id · source · ts(UTC) · geo · raw_ref` + otwarte pole `entities[]`. Cała semantyka (typy encji, resolution, graf) **płynie** — rośnie z danych.
3. **Czas + miejsce jako byty pierwszej klasy od dnia zero.** Uniwersalny klucz złączeń między źródłami, karmiony OwnTracks. Nie da się retrofitować bez re-ingestu — stąd w kopercie od startu.
4. **Local-first / privacy.** Korpus (bank + prywatne zdjęcia + maile) → wszystko lokalnie. Embeddingi i modele na SOLARIA (GPU + ollama). Zero chmury dla danych wrażliwych.
5. **Protokół, nie provider.** Ingest pisany przeciw standardom (JMAP, IMAP, WebDAV), nie przeciw firmie → przenośność.
6. **Jeden spine: Postgres + pgvector.** Koperta + wektory (+ później encje + punkty OwnTracks) w jednym store. Mniej ruchomych części. Spine stoi na **PIHA** (Raspberry Pi 5, always-on) — zapytania KB muszą działać 24/7, a SOLARIA bywa offline. SOLARIA zostaje do GPU/embeddingów (bge-m3) i indexera.
7. **Warstwa 4 nie jest waterfallem.** Kontrakt encji (warstwa 3) definiujemy wcześnie — przy 2 źródłach; po drugim źródle stawiamy *cienką* wersję warstwy 4, by udowodnić cross-source linking; dopiero potem dokładamy resztę.
---
## Kolejność projektów (z uzasadnieniem)
1. **Maile** — urgency historyczna (Gmail), czysty text RAG (najprostszy), stawia wzorce reużywalne przez resztę (archiwum, embeddingi na SOLARIA, szkielet agenta, deploy). Wzorzec referencyjny.
2. **Dokumenty** — reużywają ~80% maili (text RAG + OCR), niosą własną migrację Drive → self-host.
3. **Zdjęcia** — silnie zde-ryzykowane: Immich już robi multimodal. Projekt = cienki agent nad API Immicha. Może iść w parze z dokumentami.
4. **Transakcje** — inny paradygmat (strukturalny/analityka, *nie* RAG); najmniej danych, najtrudniejszy acquisition. Na koniec.
5. **Interdyscyplinarny** — capstone; ale jego *szkielet* (schema encji) powstaje już przy 12.
---
## Stan per źródło
- **Maile** — **dwa żywe źródła:** Fastmail (JMAP, primary) + Gmail (IMAP, bo konto **zostaje** jako śmieciowe/loginy/2FA). Plus jednorazowy bulk historyczny Gmaila. Reguła: **archiwizuj wszystko, indeksuj selektywnie** (filtr odrzuca login/2FA/notyfikacje z wektorów). Design: `kb-01-email-design.md`. **Następny do realizacji.**
- **Dokumenty** — **zdecydowane:** Nextcloud (zamiennik Drive, dowolne pliki + sync) **i** Paperless-ngx (podzbiór: skany/faktury/umowy z OCR). Dwa deploye; w ingeście jeden adapter na każdy (Nextcloud WebDAV + Paperless API).
- **Zdjęcia** — **Immich już działa** (storage + sync z telefonu + CLIP + twarze + EXIF). Projekt = cienki agent nad API Immicha + job: twarze→osoby, EXIF→miejsca do warstwy encji.
- **Transakcje** — **OPEN ISSUE.** Banki: gł. mBank + Revolut (+ reszta PL). Cel: maks automatyzacja. Kandydat: **agregator PSD2** (GoCardless Bank Account Data / Tink) — jedno wejście zamiast N adapterów. Ograniczenie regulacyjne: **zgoda PSD2 wygasa co 90 dni (SCA)** — pełnego bezobsługowego sync nie da się zrobić legalnie. Fallback zero-API: import CSV/MT940. Pokrycie mBanku, koszt agregatora, Revolut → do weryfikacji przy starcie filaru #4.
- **OwnTracks** — **działa**; feed do middleware jako warstwa spatio-temporalna (warstwa 3).
---
## Middleware — co zamrożone, co płynne
- **Zamrożone (cienkie, addytywne):** koperta (`id/source/ts/geo/raw_ref`) + mechanizm `entities[]`.
- **Płynne (rośnie z danych):** typy encji, entity resolution, graf tożsamości, linki cross-source.
- Powód: koperta jest retrofit-hostile ale data-independent (można ustalić „na ślepo"); semantyka odwrotnie — wymaga prawdziwych danych, więc jej nie usztywniamy.
---
## Decyzje — zamknięte vs otwarte
**Zamknięte:**
- Spine: Postgres + pgvector (nie Qdrant).
- Embed: **bge-m3** (multilingual, długi kontekst — pod polski lepszy niż multilingual-e5).
- Załączniki: indeksowane w **II turze** (MVP najpierw czysty tekst).
- Warstwa 3 startuje jako **cienki graf encji**; federacja przy zapytaniu dochodzi później (docelowo hybryda).
- Dokumenty: Nextcloud + Paperless-ngx.
**Otwarte:**
- **Transakcje:** agregator vs CSV, pokrycie mBanku, Revolut, koszt (filar #4).
- **Maile §design:** sizing archiwum / node (ile waży Gmail), unifikacja adaptera (jeden IMAP dla obu vs JMAP+IMAP osobno).
---
## Tor równoległy (nie tutaj)
Hardening homelabu / stabilizacja control-plane — osobny wątek.
---
## Konwencje katalogów Python
| Katalog | Co tu trafia |
|---------|-------------|
| `packages/<lib>/` | Reużywalne biblioteki (nie deployowane samodzielnie). Instalacja: `pip install /repo/packages/<lib>/`. Nie mają `docker-compose.yml` ani `service.yaml`. |
| `services/<svc>/` | Długo żyjące serwisy Docker z `docker-compose.yml` + `service.yaml`. |
| `jobs/<job>/` | Jednorazowe i periodyczne joby CLI — bez Dockera, odpalane bezpośrednio na węźle (`pip install -e`). |
Pierwsza biblioteka: `packages/kb-mail/` — model koperty, helpery DB (asyncpg), helper archiwum.
Pierwszy job: `jobs/gmail-bulk-import/` — jednorazowy bulk importer Gmail Takeout.
---
## Stan etapów
~~Etap 1 maili: zamroź kopertę + postaw Postgres+pgvector + szkielet repo.~~ **ZROBIONE** (2026-06-17).
-`services/kb-postgres` — pgvector/pgvector:pg16 na **PIHA** (:5433, always-on), `init/001_envelope.sql`
- ✅ Zamrożona koperta — tabela `envelope` + `@dataclass Envelope` (tz-aware)
-`packages/kb-mail``envelope` / `db` (asyncpg) / `archive` (append-only .eml)
- ✅ 15 testów unit + 5 integration (mark `integration`, wymaga `KB_TEST_DSN`)
**Etap 2a: relokacja spine SOLARIA→PIHA + deploy** — ZROBIONE (2026-06-22).
- ✅ override SOLARIA usunięty; `hosts/piha/runtime/kb-postgres/docker-compose.override.yml` (mem_limit 1g, tuning pod małą maszynę), obraz `pgvector/pgvector:pg16` arm64
- ✅ PIHA przygotowany: 4GB swap + `cgroup_enable=memory` (mem_limit działa), volume `kb_postgres_data` na NVMe
- ✅ deploy na PIHA: kontener healthy, schemat `envelope` + extension `vector` zweryfikowane
- ⏳ zostaje: transfer archiwum/.eml na PIHA NVMe (docelowo), poprawka `KB_TEST_DSN` (solaria→piha) w testach
~~Etap 2b: jednorazowy bulk importer Gmail (mbox/Takeout → archiwum).~~ **URUCHOMIONY** (2026-06-25).
-`jobs/gmail-bulk-import/` — CLI importer bez Dockera (pip install -e na PIHA)
- ✅ entities[]: manifest załączników (filename, content_type, size, sha256) od dnia zero
- ✅ batch inserty, idempotentny, --limit, epoch_fallback, statystyki załączników
- ✅ 24 testy jednostkowe, wszystkie zielone
- ✅ Pełny import uruchomiony na PIHA (~29 min): **225 030 unikalnych kopert**, **27 GB archiwum .eml**, manifest **70 193 załączników**
**Backlog / następne kroki**:
- Faza 2 załączników: ekstrakcja/OCR (PDF/skany → Paperless lub dedykowany job)
- Odzysk 2559 dat epoch-fallback z nagłówków `Received:`/`X-GM-RECEIVED`
- Etap 3: Fastmail JMAP live ingest → `jobs/fastmail-poller/`
- Etap 4: Gmail IMAP live sync → `jobs/gmail-imap-poller/`