Přeskočit obsah

Integrace (INTEGRATIONS.md)

Tento dokument popisuje strategii integrace s externími systémy a úložištěm souborů.


1. Úložiště souborů

Aktualizace (duben 2026): Primární storage přesunuto na Supabase Storage. Škola má ~80 žáků, odhadovaný objem ~10–20 GB/rok. Supabase Pro (100 GB) stačí na roky, RLS funguje z boxu bez extra infrastruktury. GCS plán níže zůstává jako reference pro budoucí migraci, pokud objem překročí kapacitu Supabase nebo bude potřeba přímá integrace s Vertex AI.

Původní plán: GCP Cloud Storage (odloženo)

Architektonický princip: File-first, Schema-light

GCP Bucket je source of truth. Supabase drží jen AI-derived data.

Škola potřebuje ukládat soubory ke každému žákovi:

  1. Evidenční dokumenty — smlouvy, rodné listy, kartičky ZP, souhlasy GDPR. Málo souborů, vysoká citlivost, dlouhá retence.
  2. Fotky prací žáků — sešity, projekty, výkresy. Fotky věcí (ne osob). Střední objem, AI zpracování.
  3. Scany ověření — doklady o zvládnutí kompetencí. AI extrahuje strukturovaná data.
  4. Právní dokumenty — vše jde do GCP Bucket (rozhodnuto).

Každý soubor má vedle sebe .meta.json s popisem. Supabase drží jen zpracované výstupy (competency_records), které lze kdykoliv přegenerovat z raw souborů. Toto umožňuje:

  1. Periodické re-processing — až bude AI chytřejší, projdeš složku žáka znovu a vygeneruješ nové insights
  2. Disposable schema — Supabase struktury je jednodušší zahodit a přepracovat, protože soubory + metadata v bucketu jsou nezávislé
  3. Self-describing storage — i bez databáze lze procházet bucket a rozumět, co v něm je

Proč GCP Cloud Storage

Výhoda
Přímá integrace s Vertex AI / Gemini Vision (stejný projekt sofie-education, žádný data transfer)
Data v EU (europe-west1) — GDPR
Levné: Standard ~$0.02/GB/měsíc, Nearline pro archiv
Signed URLs pro bezpečné zobrazení v UI (time-limited)
Lifecycle rules (automatická archivace starších souborů)
Object Versioning (ochrana proti nechtěnému smazání + historie sidecar metadat)
Už máme GCP projekt, region, billing

Vyřazené alternativy

Alternativa Proč ne
Google Shared Drive Oddělení od Kosma — dvě místa. Žádná integrace s AI. Nemožnost kontrolovat kompletnost dokumentů v Kosmu.
Supabase Storage Data v AWS. Gemini Vision v GCP. Cross-cloud transfer = latence + náklady.
Immich Vyřazen z důvodu GDPR biometrie. Hardcodovaný Face Recognition u dětí = extrémní právní zátěž.

Bucket struktura

Dvě podsložky per žák: evidence/ (sekretářka, právní dokumenty) a portfolio/ (učitel, práce + ověření). Čitelné názvy souborů. Sidecar .meta.json vedle každého souboru.

gs://sofie-media/
└── {student_id}/
    ├── evidence/                                  # sekretářka spravuje
    │   ├── smlouva_2025.pdf
    │   ├── smlouva_2025.meta.json
    │   ├── rodny_list.pdf
    │   ├── rodny_list.meta.json
    │   ├── zp_karticka.jpg
    │   └── zp_karticka.meta.json
    ├── portfolio/                                 # učitel nahrává
    │   ├── 2026-03-15_projekt_vesmir.webp
    │   ├── 2026-03-15_projekt_vesmir.meta.json
    │   ├── 2026-03-20_overeni_zlomky.webp
    │   └── 2026-03-20_overeni_zlomky.meta.json
    └── manifest.json                              # auto-generovaný index přes obě složky
  • evidence/ = právní/administrativní dokumenty. Málo souborů, spravuje sekretářka, jiná oprávnění (admin only).
  • portfolio/ = vše co dokumentuje pokrok žáka (fotky prací + scany ověření). Spravuje učitel, AI zpracovává.
  • Manifest na root úrovni žáka — AI vidí oboje.

Pojmenování souborů

Čitelné názvy, ne UUID. Učitel/sekretářka zadá krátký popis při uploadu, systém vygeneruje filename:

  • Evidenční: {typ_dokumentu}_{rok}.{ext}smlouva_2025.pdf, zp_karticka.jpg
  • Portfolio: {datum}_{popis}.{ext}2026-03-15_projekt_vesmir.webp, 2026-03-20_overeni_zlomky.webp

Duplicity

Soubor, který se týká více žáků (skupinový projekt), se nahraje duplicitně do složky každého žáka. Storage je levný ($0.02/GB/měsíc), konzistence a jednoduchost dotazování je cennější.

Sidecar .meta.json

Každý soubor má vedle sebe {filename}.meta.json se strukturovanými metadaty. Pole jsou volitelná dle type.

{
  "type": "work | document | assessment",
  "original_name": "IMG_4521.jpg",
  "uploaded_by": "ucitel@zs-sofie.cz",
  "uploaded_at": "2026-03-15T10:30:00Z",
  "school_year": "2025/2026",

  "teacher_note": "Projekt o vesmíru — korálkový materiál",
  "tags": ["projekt", "vesmír", "matematika"],
  "subject": "přírodověda",

  "document_type": "smlouva",
  "valid_until": "2027-06-30"
}

Pole dle typu

Pole document work assessment
type
original_name
uploaded_by
uploaded_at
school_year
document_type
valid_until ✅ (volitelné)
teacher_note
tags
subject
assessment_date

manifest.json

Auto-generovaný index všech souborů žáka. Regeneruje se po každém uploadu/smazání. Slouží jako rychlý vstup pro AI — místo listování bucketu AI dostane jeden JSON.

{
  "student_id": "uuid",
  "generated_at": "2026-03-24T12:00:00Z",
  "file_count": 8,
  "evidence": [
    {"name": "smlouva_2025.pdf", "document_type": "smlouva", "uploaded_at": "2026-03-15"},
    {"name": "rodny_list.pdf", "document_type": "rodny_list", "uploaded_at": "2026-03-15"},
    {"name": "zp_karticka.jpg", "document_type": "zp_karticka", "uploaded_at": "2026-03-15"}
  ],
  "portfolio": [
    {"name": "2026-03-15_projekt_vesmir.webp", "type": "work", "subject": "přírodověda", "uploaded_at": "2026-03-15"},
    {"name": "2026-03-20_overeni_zlomky.webp", "type": "assessment", "subject": "matematika", "uploaded_at": "2026-03-20"}
  ]
}

Supabase — minimální, disposable schema

Supabase drží jen to, co je AI-derived a slouží pro dotazování v UI. Vše je regenerovatelné z bucket souborů.

student_files — cache/index souborů

Lightweight cache pro UI listing bez GCS API volání. Regenerovatelné z manifest.json.

Sloupec Typ Popis
id UUID PK
student_id UUID FK → students
file_name TEXT Čitelný název souboru
storage_path TEXT Plná cesta v GCS
folder TEXT evidence nebo portfolio
type TEXT document, work, assessment
document_type TEXT Pro evidence: smlouva, rodny_list, zp_karticka, souhlas_gdpr...
subject TEXT Pro portfolio: předmět
uploaded_at TIMESTAMPTZ
created_at TIMESTAMPTZ

competency_records — AI-extrahované záznamy kompetencí

Centrální tabulka pro AI metodické listy. Plněna z AI zpracování fotek prací a scanů ověření.

Sloupec Typ Popis
id UUID PK
student_id UUID FK → students
competency_code TEXT Kód kompetence (RVP nebo vlastní školy)
competency_name TEXT Lidsky čitelný název: "Sčítání zlomků"
subject_area TEXT "Matematika", "Český jazyk"...
evidence_source TEXT assessment, work, teacher_manual
source_file TEXT Název souboru v bucketu (ne FK, jen reference)
level TEXT "zvládá samostatně", "zvládá s podporou", "rozvíjí se"
observed_at DATE Kdy kompetence pozorována
school_year TEXT "2025/2026"
ai_generated BOOLEAN Zda to generovala AI
teacher_confirmed BOOLEAN Zda učitel potvrdil
processing_model TEXT Jaký model generoval (pro re-processing)
processing_date TIMESTAMPTZ Kdy zpracováno
created_at TIMESTAMPTZ

ai_processing_runs — log zpracování

Audit log pro tracking AI zpracování a re-processing.

Sloupec Typ Popis
id UUID PK
student_id UUID FK → students
run_type TEXT single_file, full_portfolio
model_used TEXT "gemini-2.0-flash", "gemini-2.5-pro"...
started_at TIMESTAMPTZ
completed_at TIMESTAMPTZ
files_processed INTEGER
records_generated INTEGER
status TEXT running, completed, failed
error_message TEXT Při selhání

Upload flow

sequenceDiagram
    participant U as Učitel/Sekretářka
    participant K as Kosmo (Next.js)
    participant B as GCP Bucket
    participant G as Gemini Vision
    participant DB as Supabase

    U->>K: Nahraje soubor + vyplní popis
    Note over K: Client-side resize fotek (2048px, WebP)
    K->>K: Vygeneruje čitelný filename + .meta.json
    K->>B: Upload soubor přes signed URL
    K->>B: Upload .meta.json přes signed URL
    K->>B: Regeneruje manifest.json
    K->>DB: Upsert student_files (cache)

    alt Portfolio soubor (work/assessment)
        K->>G: Analyze image
        G-->>K: Popis, předmět, štítky, kompetence
        K->>DB: Insert competency_records
        K->>DB: Insert ai_processing_runs
    end

    K->>U: Hotovo

Evidence upload (sekretářka)

  1. Otevře kartu žáka → záložka "Soubory" → sekce "Evidence"
  2. Vidí checklist povinných dokumentů (smlouva, GDPR souhlas, rodný list, ZP kartička)
  3. Chybějící = červený badge, nahráno = zelený check
  4. Klikne "Nahrát" u konkrétního typu → file picker (PDF/JPG/PNG)
  5. Systém automaticky pojmenuje dle typu + roku
  6. Upload do {student_id}/evidence/

Portfolio upload (učitel)

  1. Otevře kartu žáka → záložka "Soubory" → sekce "Portfolio"
  2. Klikne "Přidat" → vybere typ (fotka práce / scan ověření)
  3. Na mobilu: camera capture, na desktopu: file picker
  4. Vyplní krátký popis + předmět (volitelně)
  5. Client-side resize na 2048px + WebP konverze
  6. Upload do {student_id}/portfolio/
  7. AI zpracování na pozadí (Gemini Vision → competency_records)

AI zpracování

Při uploadu (single file)

Typ souboru AI vstup AI výstup
Fotka práce (work) Obrázek + teacher_note + subject Popis scény, identifikované kompetence, štítky
Scan ověření (assessment) Obrázek Strukturovaná extrakce: úlohy, výsledky, kompetence, chyby
Evidenční dokument Žádné AI zpracování (MVP)

Scan ověření — příklad AI extrakce

Vstup: Scan papírového ověření z matematiky. Gemini Vision výstup:

{
  "assessment_title": "Ověření — Zlomky",
  "tasks": [
    {"number": 1, "description": "Sečti zlomky", "result": "correct", "competency": "M-5-1-01"},
    {"number": 2, "description": "Odečti zlomky", "result": "partial", "competency": "M-5-1-02"},
    {"number": 3, "description": "Slovní úloha", "result": "correct", "competency": "M-5-1-03"}
  ],
  "teacher_comment": "Výborně, jen pozor na společný jmenovatel",
  "competencies_demonstrated": ["M-5-1-01", "M-5-1-03"],
  "confidence": 0.87
}

Učitel vidí extrakci v UI → potvrdí nebo upraví → teacher_confirmed = true.

Periodické re-processing (budoucí)

n8n workflow "Portfolio Re-processing": 1. Vezme manifest.json žáka 2. Pošle Gemini Pro s celým kontextem portfolia (všechny soubory za školní rok) 3. Přegeneruje competency_records s novým modelem 4. Zaloguje do ai_processing_runs

Spouštěno on-demand nebo měsíčně. Umožňuje využít nové AI modely s lepším porozuměním bez změny dat.

[!IMPORTANT] Žádné face recognition. Gemini Vision popisuje scénu a aktivitu, ne osoby. Přiřazení fotky ke konkrétnímu žákovi dělá učitel při uploadu. Biometrie dětí je zvláštní kategorie pod GDPR.

n8n workflows

Workflow Trigger Popis
Work/Assessment Processing Webhook po uploadu Gemini Vision analýza → upsert competency_records
Portfolio Re-processing On-demand / měsíčně Projde manifest.json → Gemini Pro s celým kontextem → přegeneruje competency_records
Methodology Sheet Generator On-demand (budoucí) Čte competency_records + manifest → Gemini Pro → Typst PDF

Document completeness

Jednoduché řešení bez cronu: UI na kartě žáka zobrazí checklist povinných typů dokumentů. Stav se derivuje z manifest.json / student_files cache.

Povinné typy (konfigurovatelné): - smlouva — Smlouva o vzdělávání - souhlas_gdpr — Souhlas se zpracováním osobních údajů - rodny_list — Rodný list (kopie) - zp_karticka — Kartička zdravotní pojišťovny

Chybí soubor s daným document_type? → červený badge. Sekretářka vidí stav přímo na kartě žáka.

Přístupová matice

Role evidence/ portfolio/
Ředitel ✅ čtení + upload ✅ čtení + upload
Sekretářka ✅ čtení + upload ✅ čtení
Třídní učitel ❌ (výjimka: ZP kartička na výletě) ✅ všech žáků — čtení + upload
Rodič ✅ svého dítěte — pouze čtení

Rozhodnuto: Učitel má read-only přístup k portfoliím všech žáků napříč třídami (nejen svých).

Implementováno přes Kosmo auth + signed URLs (server generuje URL jen pokud uživatel má oprávnění).

Fotky — rozhodnuté otázky

  • Retence fotek: 3 roky po odchodu žáka ze školy.
  • Souhlas: Obecný souhlas při zápisu (ne per-soubor).
  • Tagování fotek: Automaticky dle data, učitel potvrdí. Žádné biometrické rozpoznávání.

Lifecycle rules (GCS)

Prefix Standard Nearline (2 roky) Coldline (5 let) Archive
*/evidence/ po 5 letech
*/portfolio/ po 2 letech po 5 letech
  • Object Versioning zapnutý — ochrana proti nechtěnému smazání + historie sidecar metadat při re-processingu.
  • Retence po odchodu žáka: 3 roky, poté smazání (v souladu s GDPR).

Optimalizace

Technika Účel
Client-side resize (před uploadem) Fotky max 2048px + WebP konverze → úspora storage i bandwidth
Thumbnaily Generování náhledů (300px) při uploadu pro rychlé zobrazení v UI
Batch upload Učitel nahraje 10 prací najednou → hromadný upload s AI taggingem na pozadí
manifest.json cache student_files tabulka v Supabase = rychlý listing bez GCS API

Náklady

Položka Odhad
Storage (~5 GB/rok) ~$0.10/měsíc
Gemini Vision (~500 fotek+scanů/rok) ~$1.25/rok
Speech-to-Text (budoucí, nahrávky) ~$20/rok
Signed URL generování Zanedbatelné (API volání)
Celkem < $5/rok

Implementační fáze

Fáze 1: GCS infrastruktura + evidenční dokumenty - GCP: vytvořit bucket sofie-media v europe-west1, CORS, Object Versioning - Next.js: API routes pro signed URL generování (upload + download) - Next.js: helper pro generování čitelných filenames + .meta.json - Next.js: helper pro regeneraci manifest.json po uploadu - Supabase migrace: student_files tabulka - UI: záložka "Soubory" na kartě žáka — evidence upload + completeness checklist

Fáze 2: Fotky prací žáků + AI tagging - UI: upload fotky práce (mobil: camera capture, desktop: file picker) - Client-side: resize na 2048px + WebP konverze (canvas API) - n8n: Work Processing workflow (Gemini Vision → popis, předmět, štítky) - Supabase migrace: competency_records + ai_processing_runs tabulky

Fáze 3: Scany ověření + strukturovaná AI extrakce - UI: upload scanu ověření + výběr předmětu/data - n8n: Assessment Processing workflow (Gemini Vision → strukturovaná extrakce úloh/výsledků) - UI: zobrazení AI extrakce + teacher verification - competency_records: plnění z assessment extrakcí

Budoucí fáze (mimo scope): - Audio/video nahrávky - Portfolio re-processing workflow - AI metodické listy (Gemini Pro → Typst PDF)


2. Channel Adapter Patterns

Referenční vzory pro napojování komunikačních kanálů Sofie přes n8n. Inspirováno architekturou OpenClaw.

SofieMessage — kanonické schéma zprávy

Všechny kanály normalizují příchozí zprávy do jednoho společného formátu:

{
  "senderId": "parent-uuid",
  "senderName": "Jana Nováková",
  "senderRole": "parent|teacher|admin",
  "channel": "email|webchat|whatsapp",
  "body": "text zprávy",
  "media": [{ "path": "...", "type": "image/jpeg" }],
  "childId": "student-uuid",
  "threadId": "conversation-uuid",
  "timestamp": "ISO 8601"
}

Inbound flow (příchozí zpráva)

Kanál (webhook/polling)
  → Normalizace do SofieMessage
  → Security check (allowlist / ověření rodiče)
  → Route resolution (který n8n sub-workflow)
  → Dispatch do AI agenta (Vertex AI)
  → Agent generuje odpověď

Outbound flow (odchozí zpráva)

Odpověď z agenta
  → Text chunking (respektuje limity kanálu)
  → Payload normalizace
  → Target resolution (kam poslat)
  → Delivery přes channel adapter (email / webhook / messaging API)

n8n workflow vzor

[Trigger node]  →  [Normalize node]  →  [Route node]  →  [AI node]  →  [Format node]  →  [Send node]
   (webhook,         (→ SofieMessage)    (→ správný       (Vertex AI)    (chunking,        (email,
    email,                                 sub-workflow)                   limity kanálu)     webhook)
    schedule)

Každý kanál = vlastní Trigger + Send node, ale prostřední logika je sdílená.

Klíčové vzory

Vzor Aplikace v Sofii
Faceted adapters Checklist pro nový kanál: min. trigger + normalize + send
Kanonická zpráva SofieMessage JSON schema pro n8n
Early normalize, late deliver Média normalizovat při příjmu, formátovat při odesílání
DM pairing Ověřovací flow pro nové rodiče na messaging kanálech
Tiered routing Switch node v n8n s prioritním matchingem

3. CRM & PM

  • CRM: Twenty (napojení plánováno).
  • PM: Vlastní Kanban modul v Kosmu.

4. Pohoda (Ekonomický systém)

Škola používá systém Pohoda pro účetnictví a fakturaci. Cíl: Automatizace fakturace školného/stravného a přenos plateb.

Technické možnosti

Dle příručky Ekonomický systém POHODA (2024), kapitola 16 (Datová komunikace):

  1. XML Import/Export (Kapitola 16/6, str. 498)

    • Pohoda podporuje nativní XML formát pro výměnu dat.
    • Režim: Dávkový (soubor se nahraje do složky, Pohoda ho zpracuje).
    • Využití: Generování faktur za školné (Kosmo → XML → Pohoda).
  2. POHODA mServer (Kapitola 16/10, str. 511)

    • HTTP server běžící nad Pohodou.
    • Umožňuje zasílat XML požadavky přes API (např. dotaz na stav úhrady faktury).
    • Výhoda: Online komunikace (není třeba ručně přenášet soubory).
    • Nevýhoda: Vyžaduje veřejnou IP nebo VPN do školy (běží lokálně).

Doporučená strategie (Fáze 2/3)

  • MVP: Generování XML souborů (Faktury) v aplikaci Kosmo, které účetní ručně nahraje do Pohody.
  • Cílový stav: Využití mServeru pro automatické párování plateb (rodič vidí v aplikaci "Zaplaceno").
  • Dopad na uživatele:
    • Rodič: Vidí ve Feedu stav platby ("Školné únor: zaplaceno" / "Splatnost: 15.2.").
    • Ředitel: Dashboard s přehledem nezaplacených ("3 rodiče po splatnosti, celkem 25 500 Kč.").
    • Administrativa: Přehled faktur, automatické upomínky, export pro účetní.

5. ŠkolaOnline (Školní Matrika)

ŠkolaOnline je hlavní evidenční systém (matrika). Cíl: Synchronizace žáků a rodičů (Single Source of Truth), přenos známek/omluvenek.

Analýza dokumentace

Dokumentace naznačuje velmi komplexní datový model (tisíce polí pro MŠMT výkaznictví). - Struktura: Hierarchická (Kraje → Školy → Žáci → Vzdělávací plány). - Data: Obsahuje citlivé údaje (RČ, zdravotní znevýhodnění, IVP).

Doporučená strategie

  • Jednosměrná synchronizace (ŠkolaOnline → Kosmo):
    • ŠkolaOnline je "master" pro seznam žáků.
    • Kosmo si stahuje data (ideálně přes API nebo noční CSV export).
  • Omluvenky:
    • Rodič zadá v Kosmo → Kosmo pošle email učiteli / pokusí se zapsat do ŠOL (pokud API dovolí).

6. Google Workspace (Identita & Dokumenty)

Cíl: Single Sign-On (SSO) a úložiště. - Auth: OAuth 2.0 (přihlašování školním Google účtem). - Drive: Ukládání studentských prací (Evidence). Každý žák/třída může mít Shared Drive. - Docs/Sheets: Export reportů (vysvědčení, hodnocení).


7. Strava.cz (Školní Jídelna)

Cíl: Zobrazení jídelníčku v aplikaci (a odpovědi přes AI: "Co je dnes k obědu?").

Technické možnosti

  • XML Feed (Oficiální): Strava.cz nabízí XML feed jídelníčku pro každou jídelnu.
    • URL: https://www.strava.cz/strava/...?xml=true&cisloJidelny=XXXXX
    • Stačí znát ID jídelny školy.
  • Neoficiální API: Existují komunitní projekty (OpenStravaCZ/StravaProtocol) s dokumentací protokolu.

Doporučená strategie

  • MVP: Denní cron stáhne XML feed → uloží do DB/Knowledge Base → Sofie odpovídá.
  • TODO: Zjistit ID jídelny školy Sofie a ověřit XML feed.
  • Budoucnost: Objednávání obědů přes appku (pokud API dovolí).

8. Sofie Specifika (z Sofie - popis.pdf)

Dokument popisuje vzdělávací model, který musí Kosmo podporovat: - Slovní hodnocení: Nutnost rich-text editorů, ne jen známky 1-5. - Kompetence: Vazba na RVP (Klíčové kompetence). Evidence musí umožnit tagování ("Komunikativní", "Sociální"). - IVP: Individuální plány pro žáky se znevýhodněním (pole v databázi pro přílohy/cíle pro AI analýzu). - CLIL / Bilingvální třídy: Škola má bilingvální třídy s rodilými mluvčími i rodiče-expaty. - UI: Čeština + Angličtina (i18n od začátku — next-intl). - AI odpovědi: Sofie odpovídá v jazyce rodiče (auto-detect nebo nastavení profilu). - Reporty: Dvojjazyčné výstupy (česky pro MŠMT, anglicky pro expaty).