Część A (co budujemy — język wartości) i część B (jak). Wymagania FR mają priorytet MoSCoW i kryterium akceptacji „do wyklikania”.
CZĘŚĆ A — CO BUDUJEMY (dla akceptującego — język wartości)
A1. Po co ten produkt — kontekst i cel
Iskra operatora (verbatim, Cze 2026-09-07, tura 1)
„pomożesz mi zrobić nową, lepszą weliskę [...] powinienem mieć interfejs, w który mogę sobie wkładać swoje wyniki na przykład z poboru krwi [...] jebutną bazkę danych w którą mogę lądować swoje dowolne dokument medyczne z dowolnych źródeł, podstawowe to takie z ręki, dalej z labów (to trzeba przez RPA) jak na przykład synevo ale też z NFZtu (spięcie z P1) i też z zegarków, apek [...] na pewno na razie z apple watcha bo to mam i apki zdrowie ios [...] za ZT-cf schowany portalik webowy no i jakieś histogramy, trendy per pomiar/odczyt, docelowo również algorytmy medyczne po interfejsie wystawionym przez silnik algorytmów Wellysy [...] udostępniać moje wybrane wyniki wybranym userkom [...] scope jaki kto ma widzieć [...] apka webowa+telegram, tę telegramową osadź sobie jako swojemu Snow-tg-botowi [...] przyjmij zasadę, że 90% rzeczy już jest dostępne [...] chcę jeszcze móc zdjęcia wgrywać, żeby mi to OCRowało"
Iskra operatora (verbatim, tura 2 — po v0.1)
<b>Zdanie, które wyznacza sukces:</b> <i>„aplikacja ciągle sprawdza where im at i faktycznie mnie popycha"</i>. Bazka jest fundamentem, ale produkt jest udany dopiero wtedy, gdy operator <b>przestaje przepisywać wyniki</b> i <b>nie musi pamiętać, jakie badanie mu się należy</b> — aplikacja wie i mówi pierwsza.
<b>Dlaczego to jest „nowa Wellysa":</b> dzisiejsza <code>wellysa-app</code> zaczyna od ekranów (ankieta → zakup → wizyta). WELISKA zaczyna od <b>danych osoby</b> i od <b>reguł profilaktyki</b>: co mam → co z tego wynika → co dalej (v1) → gdzie (v2) → za co (v3). Pierwszy użytkownik = operator (dogfood, jak Snow z mapą Soho); po dowodzie produkt wchodzi pod P1 PHA dla użytkowników Wellysy.
A2. Słownik pojęć
| pojęcie | znaczenie w WELISCE |
|---|
| obserwacja | jeden odczyt: parametr (LOINC) + wartość + jednostka (UCUM) + czas + zakres referencyjny + źródło + proweniencja; kształt FHIR R4 Observation (profil HL7 EU Lab); ontologia Wellysy: pomiar+metryka+norma |
| raport | zbiór obserwacji z jednego zlecenia/wizyty/eksportu (DiagnosticReport) |
| dokument | plik źródłowy (zdjęcie, PDF, XML, CDA) w magazynie z proweniencją |
| zdarzenie zdrowotne | nie-pomiar: wizyta, procedura, szczepienie, recepta, rozpoznanie (z P1 ZM/IKP/ręki) — wejście do CO DALEJ |
| źródło | manual, ocr, lab:synevo, lab:diagnostyka, lab:alab, ikp-pdf, p1-edm, apple-health, health-connect, export-xml; każde ma tryb: ręka / intent (użytkownik wyzwala, np. Synevo z kodem) / cron / push |
| proweniencja | kto/co/kiedy wprowadził + odnośnik do dokumentu; bez niej rekord nie istnieje |
| trend | wykres jednego parametru w czasie, wiele źródeł, z zakresem ref.; wartości sprowadzone do jednostki kanonicznej |
| reguła profilaktyczna | (kryteria wejścia z profilu, badanie/procedura z kodem, interwał, źródło + data pomiaru, siła zalecenia, ważność) — z NFZ/PZH/PTD/PTL/ESC; ontologia Wellysy: wskazanie |
| temat (topic) | jedna rzecz do pilnowania (np. „kolonoskopia przesiewowa"); stan: nie dotyczy / do zrobienia / po terminie / zrobione / odłożone / zrezygnowano |
| CO DALEJ | lista tematów ze stanem + aktywne popychanie (TG/push) — rdzeń v1 |
| zakres udostępnienia (scope) | (odbiorca, parametry, okres, źródła, dokumenty?, ważność) — co druga osoba widzi |
| wskaźnik (algorytm) | wielkość liczona z obserwacji przez silnik algorytmów Wellysy (HOMA-IR, SCORE2…) — informacja z proweniencją, nie wyrok |
| HITL | człowiek zatwierdza: OCR przed zapisem, użytkownik decyzję „zrobione/odkładam", lekarz interpretację |
A3. Ludzie i role
| rola | kto | co robi |
|---|
| operator / pierwszy użytkownik | Cze | wkłada wyniki, wyzwala pobrania (Synevo), ogląda trendy i CO DALEJ, udostępnia; akceptuje SPEC i etapy |
| CTO-czak (buduje) | Snow | architektura, kod, testy, ops, zgłoszenie; nie ogląda danych bez potrzeby (audit) |
| odbiorca udostępnienia | osoby wskazane przez operatora (email w CF Access); docelowo lekarz | widzą TYLKO scope |
| silnik algorytmów | silnik algorytmów Wellysy (wsa/silnik) | liczy wskaźniki; kontrakt |
| słowniki | słownik medyczny | LOINC/UCUM/ICD-9-PL przez slownik_lookup |
| podmiot leczniczy dla P1 | Wellysa (Wellysa/p1, wellysa-api) | EDM/ZM pacjenta za zgodą — jako usługodawca (cert PROD) |
| platforma | platforma | tunel, CF Access, bot TG, magazyn plików, spec-sajt (//) |
| compliance | zespół compliance | przegląd Art. 9 przed drugim użytkownikiem |
| orzekanie | lekarz | poza produktem — produkt umożliwia, nie orzeka |
A4. Granice i etapy
A4.1 Kontekst — z czym produkt się łączy (→ C4 L1, docs WELISKA C4-DEPLOYMENT)
- Wewnątrz środowisko Wellysy (serwer platformy): API + bazka (SQLite WAL, szyfrowany wolumen), portal (panel), magazyn plików (magazyn plików R2
czak-wsa), silnik CO DALEJ (reguły YAML), sejf poświadczeń (kredki). - Usługi platforma: słownik medyczny, silnik algorytmów Wellysy, bramka komunikatorów (TG), cf_access, traceability.
- Na zewnątrz: Cloudflare (tunel + Access + Pages spec-sajt), Telegram, Apple (TestFlight), Google Play (internal), opcjonalnie Azure DI West Europe (OCR fallback, tylko po).
A4.2 Etapy budowy (po ludzku; taski powstaną pod epikami po akcepcie)
| etap | co operator ZOBACZY | moduły / idee |
|---|
| 1. Bazka + ręka + trend (web) | wpisuję glukozę, widzę trend z zakresem; portal za CF Access | BAZ, REK, POR · |
| 2. Zdjęcie → tabela → zatwierdź | wrzucam zdjęcie wydruku, poprawiam tabelę, klik = w bazce, oryginał w magazynie | OCR, MAG · |
| 3. CO DALEJ (v1 rdzeń) | lista „do zrobienia" z powodem i źródłem reguły; TG mnie popycha; „zrobione/odkładam" | COD · |
| 4. Apka TG | to samo z telefonu: wpis, zdjęcie, trend, CO DALEJ, powiadomienia | TG · |
| 6. P1 przez Wellysę | zgoda → moje dokumenty z EDM (wyniki, wypisy) lądują w bazce; IKP = drop PDF | P1 · |
| 7. Udostępniam zakres | wskazuję osobę i co widzi; test negatywny: reszta niewidoczna | UDO · |
| 8. Apka iOS (Ionic) + Watch w tle | tętno/HRV/sen/kroki/SpO2/waga wpadają same; potem Android (Health Connect) | WATCH, APP · |
| 9. Wskaźniki z silnika | HOMA-IR / SCORE2 z proweniencją, lista brakujących wejść | ALG · |
| 10. Art. 9 domknięte | szyfrowanie, audit, eksport/usuń, 0 findingów PII — brama przed drugim użytkownikiem | ART9 · |
Kolejność 1→2→3→4 jest twarda (operator: web → TG → Ionic); 5–9 równolegle po decyzjach z ; 10 przed multi-user.
A4.3 Poza zakresem (świadomie NIE robimy) — z powodem
- Orzekanie medyczne — wyrok = lekarz; CO DALEJ i wskaźniki = informacja z proweniencją i źródłem reguły.
- GDZIE robić badania (placówki, kolejki, e-Rejestracja) → v2, krowa ; JAK FINANSOWAĆ (Wallet) → v3, krowa . W v1 tylko link do programu NFZ przy temacie.
- Apka-most Health Auto Export — odrzucona przez operatora (własna apka iOS).
- RPA bez człowieka na Synevo — kod jednorazowy per zlecenie; robimy RPA na intent (użytkownik wyzwala i podaje kod). Cron zostaje dla kont stałych Diagnostyka/ALAB (opcja).
- P1 jako pacjent (IKP API) — nie istnieje; P1 jako usługodawca przez Wellysę JEST w zakresie (etap 6).
- CQL / FHIR-CPG jako silnik reguł v1 — za ciężkie; własne reguły YAML (recon). Migracja, gdy pojawi się wymiana reguł z EHR.
- Postgres/Medplum od dnia 1 — jeden użytkownik; SQLite WAL w pudełku; Medplum = plan B.
- Przepisywanie
wellysa-app/wellysa-api — WELISKA rośnie obok; wellysa-api dostaje TYLKO rozszerzenie P1-EDM (etap 6). Spięcie z produktem = osobna krowa po dogfoodzie. - Multi-tenant od dnia 1 — po etapie 10 i przeglądzie zespół compliance.
- EKG z Watcha — żaden plugin, decyzja produktowa później (poczekalnia).
A5. Wymagania funkcjonalne (FR)
<i>ID stabilne, MoSCoW (M/S/C/W), kryterium akceptacji „do wyklikania" na żywych danych operatora, trace do artefaktów fazy D (<code>[dbml: tabela]</code> <code>[api: ścieżka]</code> <code>[ekran: SCR-x]</code> <code>[test: T-…]</code>).</i>
Moduł BAZ — bazka obserwacji (etap 1)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-BAZ-1 | Każda obserwacja MUSI mieć kod LOINC, jednostkę UCUM, czas, źródło i proweniencję (kto/co/kiedy + odnośnik do dokumentu); rekord bez tych pól nie istnieje. | M | ✅ SELECT 100% wierszy z 5 polami; wpis bez jednostki = odmowa | [dbml: observation] [api: POST /observations] |
| FR-BAZ-2 | Duplikat (to samo źródło + kod + czas + wartość) NIE tworzy drugiego rekordu — ponowny import tego samego PDF/partii = 0 nowych wierszy. | M | ✅ import tego samego pliku 2× → licznik bez zmian | [dbml: observation.hash_dedup] [test: T-BAZ-2] |
| FR-BAZ-3 | Wartości w różnych jednostkach MUSZĄ być sprowadzane do jednostki kanonicznej parametru (mg/dL↔mmol/L) — trend nie może mieszać jednostek. | M | ✅ glukoza 5.0 mmol/L i 90 mg/dL na jednym wykresie w jednej skali | [dbml: unit_conversion, observation.value_canon] |
| FR-BAZ-4 | Kody i jednostki POWINNY pochodzić ze słownika słownik medyczny (slownik_lookup), nie z własnej kopii LOINC; brak route → lokalny subset TYLKO obserwacji labowych, oznaczony jako tymczasowy. | S | ✅ podpowiedź parametru zwraca kod z proweniencją słownik medyczny:… | [dbml: metric.provenance] [api: GET /metrics/search] |
| FR-BAZ-5 | Bazka MUSI trzymać zdarzenia zdrowotne (wizyta, procedura, szczepienie, recepta, rozpoznanie) obok pomiarów — bo CO DALEJ liczy interwały od nich. | M | ✅ szczepienie Tdap z datą widoczne i użyte przez temat „tężec/krztusiec" | [dbml: health_event] |
Moduł REK — wpis z ręki (etap 1, TG etap 4)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-REK-1 | Użytkownik MUSI móc wpisać wynik w web i w TG (/wynik glukoza 92 mg/dL 2026-09-07) z podpowiedzią parametru i walidacją jednostki. | M | ✅ zła jednostka = odmowa z podpowiedzią; poprawny wpis w trendzie < 5 s | [ekran: SCR-WPIS] [api: POST /observations] |
| FR-REK-2 | Wpis ręczny MUSI móc nieść zakres referencyjny i nazwę labu (jak na wydruku). | S | ✅ flaga poza-zakresem liczona z wpisanego zakresu | [dbml: observation.ref_*] |
| FR-REK-3 | Użytkownik POWINIEN móc poprawić/usunąć własny wpis; poprawka zostawia ślad w audicie. | S | ✅ edycja widoczna w access_log | [dbml: access_log] |
Moduł OCR — zdjęcie/PDF → tabela → zatwierdź (etap 2)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-OCR-1 | System MUSI przyjąć zdjęcie (JPG/HEIC/PNG) i PDF z web/TG/apki, zapisać oryginał z proweniencją i uruchomić OCR z rozpoznaniem TABELI. | M | ✅ zdjęcie z telefonu → oryginał w magazynie + propozycja tabeli | [api: POST /documents] [ekran: SCR-WGRAJ] |
| FR-OCR-2 | Propozycja MUSI pokazać per wiersz: nazwę z wydruku, dopasowany parametr (LOINC), wartość, jednostkę, zakres i pewność; niepewne wiersze oznaczone. | M | ✅ wiersz z pewnością < 0.8 podświetlony do sprawdzenia | [api: GET /documents/{id}/ocr] |
| FR-OCR-3 | NIC nie trafia do bazki bez zatwierdzenia użytkownika; użytkownik poprawia wiersze, może zapamiętać mapowanie nazwa-lab → LOINC. | M | ✅ 0 rekordów bez kliku; drugi wydruk tego samego labu mapuje się sam | [api: POST /documents/{id}/confirm] [dbml: lab_name_map] |
| FR-OCR-4 | Jakość: na 10–20 żywych wydrukach operatora ≥ 90% komórek poprawnych PRZED poprawką (miara KR1). | M | ✅ macierz w TEST-DESIGN, wynik w kwicie | [test: T-OCR-4] |
| FR-OCR-5 | OCR domyślnie self-host (PaddleOCR PP-StructureV3, CPU, dane nie opuszczają boxa); fallback płatny TYLKO w regionie EU i TYLKO po decyzji . | M | ✅ konfiguracja bez fallbacku działa; wyjście poza EU niemożliwe z konfiguracji | [c4: api.ocr] |
Moduł COD — CO DALEJ (etap 3, rdzeń v1)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-COD-1 | System MUSI prowadzić profil (płeć, data ur., palenie z paczkolatami, wzrost/waga, wywiad rodzinny, choroby przewlekłe, ciąża) z historią zmian — wejście reguł. | M | ✅ zmiana „palę → rzuciłem 2024" widoczna w historii i zmienia listę | [dbml: person.profile_json, profile_history] [ekran: SCR-PROFIL] |
| FR-COD-2 | System MUSI trzymać reguły profilaktyczne jako dane (nie kod): kryteria wejścia, badanie/procedura z kodem, interwał, źródło + data pomiaru, siła zalecenia, valid_from/review_by. Zestaw v1 = programy NFZ (Moje Zdrowie, mammografia, szyjka/HPV, kolonoskopia, ChUK, LDCT od 2026-10), szczepienia PSO, PTD (glukoza), PTL (lipidogram), ESC SCORE2. | M | ✅ ≥20 reguł z URL-em źródła i datą; reguła po review_by = flaga „do przeglądu" | [dbml: rule] |
| FR-COD-3 | Dla każdego tematu system MUSI wyliczać stan: nie dotyczy / do zrobienia / po terminie / zrobione / odłożone / zrezygnowano — z dowodem (obserwacja/zdarzenie), datą następnego terminu i powodem („M, 44 lata, 20 paczkolat → LDCT co 12 mies."). | M | ✅ operator widzi swoją listę z powodem i źródłem przy każdej pozycji | [dbml: maintenance_state] [api: GET /codalej] [ekran: SCR-COD] |
| FR-COD-4 | Ewaluacja MUSI odpalać się po każdym imporcie/wpisie i raz dziennie; nowy wynik (np. lipidogram) automatycznie zamyka temat i wylicza następny termin. | M | ✅ import lipidogramu → temat „lipidogram" = zrobione, next_due = +3 lata (50+) | [c4: api.rules] [test: T-COD-4] |
| FR-COD-5 | System MUSI popychać: powiadomienie TG (etap 4) / push (etap 8) gdy temat staje się „do zrobienia"/„po terminie", z rosnącą przerwą (nie spam) i możliwością „odłóż do…". | M | ✅ powiadomienie ≤ 24 h od zmiany stanu; „odłóż" wycisza do daty | [dbml: nudge] [api: POST /codalej/{topic}/action] |
| FR-COD-6 | Użytkownik MUSI móc oznaczyć „zrobione" (z datą, opcjonalnie dowodem), „odkładam" (do kiedy, powód), „nie dotyczy" — decyzja jest jego, z audit-śladem. | M | ✅ „zrobione 2026-08" bez wyniku w bazce = stan done z last_completed_ref=user | [api: POST /codalej/{topic}/action] |
| FR-COD-7 | Wskaźnik ryzyka SCORE2/SCORE2-OP POWINIEN być liczony modelem (region high, PL) z obserwacji (cholesterol, RR, palenie) — i wchodzić do reguł (Moje Zdrowie ≥40). | S | ✅ SCORE2 dla operatora zgodny z kalkulatorem ESC na 10 przypadkach testowych | [api: /algorithms] [test: T-COD-7] |
| FR-COD-8 | Każda pozycja MUSI mieć link do źródła (program NFZ/PZH/PTD…) i zdanie, że to informacja, nie zalecenie lekarskie. | M | ✅ klik w źródło otwiera stronę programu | [ekran: SCR-COD] |
Moduł POR — portal (panel) (etap 1)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-POR-1 | Portal MUSI być za Cloudflare Access (email); anonim nie widzi nic (302 na login). | M | ✅ curl bez tokenu → 302; z tokenem → 200 | [c4: cf] |
| FR-POR-2 | Panel MUSI pokazać ostatnie wyniki z flagą poza zakresem, skrót CO DALEJ (ile do zrobienia/po terminie) i stan źródeł. | M | ✅ wynik poza zakresem = wyróżniony; licznik CO DALEJ zgodny z listą | [ekran: SCR-PANEL] |
| FR-POR-3 | Trend parametru MUSI pokazać punkty ze WSZYSTKICH źródeł w jednej skali, zakres ref., histogram, filtr okresu/źródła; ≤ 10 s. | M | ✅ trend glukozy z ręki + OCR + labu na jednym wykresie | [ekran: SCR-TREND] [api: GET /trends/{loinc}] |
| FR-POR-4 | Każde źródło MUSI mieć freshness-badge (ostatni tick, ostatni sukces, błąd) i trzeci stan „nie zmierzono". | M | ✅ padnięty wafel widoczny jako błąd, nie jako „brak nowych" | [dbml: source] [api: GET /sources] |
| FR-POR-5 | Portal POWINIEN być zarejestrowany jako okno środowisko Wellysy (panel) z probe „rows>0 z żywej bazki". | S | ✅ wpis w rejestrze okna + zielony probe | [c4: web] |
Moduł TG — apka Telegram w bocie snowa (etap 4)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-TG-1 | Bot MUSI obsłużyć: /wynik, zdjęcie → OCR → potwierdzenie inline, /trend <parametr> (obraz), /codalej, /synevo (intent + kod), /zrodla. | M | ✅ każda komenda działa na żywym koncie operatora | [ekran: TG-*] |
| FR-TG-2 | Bot MUSI wysyłać powiadomienia: nowy import, wynik poza zakresem, zmiana stanu CO DALEJ; z przyciskami „zrobione/odłóż". | M | ✅ powiadomienie ≤ 1 min od importu | [dbml: nudge] |
| FR-TG-3 | Bot MUSI rozmawiać TYLKO z tożsamościami dopiętymi do konta (operator); obcy chat = odmowa. | M | ✅ inny użytkownik TG dostaje odmowę | [c4: tg] |
Moduł LAB — laby na intent i cron (etap 5)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-LAB-2 | Diagnostyka/ALAB: to samo wejście (nr zlecenia / kod) oraz opcjonalnie konto stałe → cron; regulaminowo tylko własne konto, rate-limit. | S | ✅ nowy wynik pojawia się po ticku albo po intencie | [c4: robot pobierający] |
| FR-LAB-3 | Nazwy badań z PDF MUSZĄ mapować się na LOINC przez lab_name_map; nieznana nazwa = kolejka „do zmapowania", nie cichy odrzut. | M | ✅ kolejka pokazuje nieznaną nazwę z propozycją | [dbml: lab_name_map] |
| FR-LAB-4 | Każdy pobrany PDF MUSI trafić do magazynu z proweniencją (nr zlecenia, data). | M | ✅ art_list pokazuje PDF per zlecenie | [dbml: document] |
Moduł P1 — dane pacjenta z P1 przez Wellysę (etap 6)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-P1-1 | System MUSI umieć — po zgodzie pacjenta zarejestrowanej w P1 (moduł Zgody) — pobrać indeks dokumentów EDM pacjenta (IHE XDS.b ITI-18) i dokumenty (ITI-43) przez Wellysę jako usługodawcę (cert PROD, mTLS TLS 1.2). | M | ✅ realny dokument operatora z EDM w bazce jako raport + oryginał CDA w magazynie | [c4: wellysa_api→p1] [dbml: document.kind=cda] |
| FR-P1-2 | wellysa-api MUSI dostać rozszerzenie o EDM/Zgody (dziś tylko e-Rejestracja); WELISKA woła API Wellysy, nie P1 wprost. | M | ✅ endpointy EDM w wellysa-api z testami; WELISKA nie ma certu P1 | [api: robot pobierający→wellysa_api] |
| FR-P1-3 | Zdarzenia Medyczne (wizyty, procedury, recepty) POWINNY lądować jako health_event — wejście CO DALEJ (np. kolonoskopia wykonana w szpitalu zamyka temat). | S | ✅ ZM „kolonoskopia" → temat = zrobione | [dbml: health_event] |
| FR-P1-4 | Drop PDF z IKP (ręczny) zostaje jako fallback przez ten sam parser co laby. | S | ✅ PDF z IKP → tabela do zatwierdzenia | [api: POST /documents] |
Moduł UDO — udostępnianie zakresem (etap 7)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-UDO-1 | Operator MUSI móc utworzyć udostępnienie: odbiorca (email), parametry (lista lub wszystkie), okres, źródła, czy z dokumentami, ważność. | M | ✅ grant widoczny na liście z zakresem | [dbml: share_grant] [api: POST /shares] [ekran: SCR-UDO] |
| FR-UDO-2 | Odbiorca po CF Access widzi TYLKO scope; parametr spoza scope → 403/pusto; każdy odczyt w audicie. | M | ✅ test negatywny zielony; access_log ma wpis per odczyt | [c4: api.share] [test: T-UDO-2] |
| FR-UDO-3 | Odwołanie MUSI działać natychmiast; wygaśnięcie automatycznie. | M | ✅ po odwołaniu odbiorca dostaje 403 w ≤ 1 s | [api: DELETE /shares/{id}] |
| FR-UDO-4 | Operator POWINIEN widzieć, kto i kiedy oglądał. | S | ✅ licznik i lista odczytów przy grancie | [dbml: access_log] |
Moduł WATCH + APP — apka iOS/Android i zegarek (etap 8)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-APP-1 | Apka mobilna MUSI być skorupą Ionic/Capacitor nad webem (te same ekrany), z natywnym modułem HealthSync (Swift) i HealthWorker (Kotlin). | M | ✅ ten sam build web działa w web i w apce | [c4: app] |
| FR-WATCH-1 | iOS: HealthKit w tle (entitlement background-delivery, observer + anchored query w didFinishLaunching, background URLSession, completion handler) dla: tętno, tętno spoczynkowe, HRV, sen, kroki, SpO2, waga, ciśnienie; upload partiami, idempotentnie. | M | ✅ próbki z Watcha widoczne w portalu bez otwierania apki (po odblokowaniu telefonu) | [api: POST /healthkit/batch] [test: T-WATCH-1] |
| FR-WATCH-2 | Android: Health Connect z READ_HEALTH_DATA_IN_BACKGROUND + WorkManager + Changes API; te same typy. | S | ✅ próbki z telefonu Android w portalu | [c4: app] |
| FR-WATCH-3 | Jednorazowy backfill z export.xml apki Zdrowie (strumieniowo, dedup). | S | ✅ historia z 3 lat w trendzie bez duplikatów | [api: POST /documents kind=xml] |
| FR-APP-2 | Dystrybucja: iOS TestFlight internal (konto Apple Wellysy), Android internal testing; polityka prywatności i zgoda na transmisję (Apple 5.1.3, Play Health declaration przy closed/prod). | M | ✅ build na iPhonie operatora z TestFlight | [test: T-APP-2] |
Moduł ALG — wskaźniki z silnik algorytmów Wellysy (etap 9)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-ALG-1 | System MUSI pokazać, które wskaźniki z katalogu silnika da się policzyć z moich danych i czego brakuje (LOINC). | M | ✅ HOMA-IR: „brakuje insulina (LOINC 20448-7)" | [api: GET /algorithms] |
| FR-ALG-2 | Wynik MUSI nieść wartość, jednostkę, wzór, użyte wejścia, proweniencję i ostrzeżenia — i zdanie „to nie jest diagnoza". | M | ✅ HOMA-IR zgodny z ręcznym przeliczeniem | [dbml: algorithm_run] [api: POST /algorithms/{id}/run] |
| FR-ALG-3 | Rozjazd jednostek rozwiązuje WELISKA przed wysłaniem (kanoniczne UCUM) — kontrakt z silnikiem mówi, czy silnik konwertuje sam. | M | ✅ wejście w mmol/L i mg/dL daje ten sam wynik | [dbml: unit_conversion] |
Moduł MAG — magazyn plików (etap 2)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-MAG-1 | Każdy import MUSI trzymać oryginał (sha256, mime, proweniencja, tagi) w magazyn plików środowisko Wellysy; do fixu — lokalny wolumen z automatyczną dogrywką. | M | ✅ art_list (albo lokalny indeks) pokazuje plik per import | [dbml: document] |
| FR-MAG-2 | Obserwacja bez oryginału MUSI być oznaczona „bez oryginału" (nie ukryta). | S | ✅ flaga w trendzie/tabeli | [ekran: SCR-TREND] |
Moduł ART9 — bezpieczeństwo danych zdrowotnych (etap 10, brama)
| ID | Wymaganie | Prio | Kryterium akceptacji | Trace |
|---|
| FR-ART9-1 | Dane wyłącznie w środowisko Wellysy (serwer platformy): bazka na szyfrowanym wolumenie, pliki w bucket lore; zero danych w RAG-u snowa. | M | ✅ audit ścieżek + audit_secrets = 0 findingów | [c4: db, store] |
| FR-ART9-2 | Logi bez PII (redact_pii), kredki wyłącznie w sejf poświadczeń, kod jednorazowy Synevo nigdy na dysku. | M | ✅ grep logów po PESEL/kodzie = 0 | [c4: sejf poświadczeń] |
| FR-ART9-3 | Każdy odczyt przez odbiorcę i każda operacja na danych w access_log (traceability). | M | ✅ wpis per odczyt | [dbml: access_log] |
| FR-ART9-4 | Eksport całości (JSON + CSV + oryginały) na żądanie — RODO art. 20. | M | ✅ ZIP odtwarza bazkę na czystej instancji | [api: GET /me/export] |
| FR-ART9-5 | Twarde usunięcie wszystkiego po potwierdzeniu (bazka + magazyn + kopie). | M | ✅ po usunięciu count(*)=0, pliki zniknęły | [api: DELETE /me] |
| FR-ART9-6 | Przed drugim użytkownikiem: przegląd zespół compliance, DPA dla OCR-fallbacku, polityka prywatności apki (Apple 5.1.1/5.1.3, Play). | M | ✅ dokument przeglądu zamknięty | [test: T-ART9-6] |
A6. Ekrany i przepływy (→ docs WELISKA MOCKUP, docs WELISKA SEKWENCJE)
<b>Ekrany web/apka (8):</b> SCR-PANEL (ostatnie wyniki, flagi, skrót CO DALEJ, źródła) · SCR-TREND (wykres + histogram + tabela punktów ze źródłem) · SCR-WPIS (wpis z ręki) · SCR-WGRAJ (zdjęcie/PDF → tabela do zatwierdzenia) · SCR-COD (lista tematów ze stanem, powodem, źródłem, akcje) · SCR-ZRODLA (stan źródeł, intent Synevo z kodem/QR, kolejka niezmapowanych nazw) · SCR-UDO (udostępnienia + tworzenie) · SCR-PROFIL (profil + historia). <b>TG (6 komend + powiadomienia):</b> <code>/wynik</code>, zdjęcie, <code>/trend</code>, <code>/codalej</code>, <code>/synevo</code>, <code>/zrodla</code>. <b>Apka:</b> ekran zgody HealthKit/Health Connect + wskaźnik synchronizacji.
<b>Przepływy kluczowe (sekwencje):</b> (a) ręka → walidacja → zapis → ewaluacja COD → trend; (b) zdjęcie → OCR → HITL → zapis + magazyn → ewaluacja; (c) Synevo: intent → kod/QR → wafel → PDF → parser → mapowanie → zapis → powiadomienie; (d) HealthKit: wybudzenie w tle → anchored query → batch → dedup → zapis; (e) P1: zgoda → ITI-18 → ITI-43 → CDA parser → raport/zdarzenia; (f) CO DALEJ: zmiana profilu/import → ewaluacja → stan → nudge → decyzja użytkownika; (g) udostępnienie: grant → CF Access (email) → odczyt w scope → audit; (h) wskaźnik: dostępność → wejścia → silnik → wynik z proweniencją.
A7. Czego potrzebujemy od akceptującego (Cze) — z terminami
| co | po co | kanał | termin |
|---|
| ACCEPT SPEC v0.2 (albo odbicie) | zamrożenie CO; flip krowy ; promocja idei do epików | komentarz w | przed etapem 1 |
| Ratyfikacja WELISKA pod P1 PHA w PRODUCT-LINES wsa | linia-gate | komentarz w / dokument consigliere | z akceptem |
| Przejścia artefaktów fazy D one-by-one (DBML → C4 → sekwencje → ekrany → testy) | wzorzec ROD: wartość powstaje w przejściach | komentarze w – | przed etapem 1 |
| Bot TG (BotFather → sejf poświadczeń) | etap 4 | | etap 4 |
| Hostname portalu + spec-sajtu | etap 1, akceptacja w spec-sajcie | | etap 1 |
| Koszty/konta: Azure DI (fallback), konta stałe Diagnostyka/ALAB (opcja), LabExtract (cennik), cert PROD P1 Wellysy (kto trzyma, czy dogfood może użyć), dostęp Snow do konta Apple/TestFlight | etapy 2, 5, 6, 8 | | przed tymi etapami |
| Profil (płeć, ur., palenie, wywiad, choroby) | CO DALEJ | SCR-PROFIL po etapie 1 | etap 3 |
| Zgoda w P1 na dostęp Wellysy do EDM | etap 6 | IKP / placówka | etap 6 |
Jednorazowy export.xml z apki Zdrowie | backfill Watcha | upload | etap 8 |
A8. Procedura akceptacji i zmian
A8.1 Co oznacza akcept tej specyfikacji
A8.2 Odbiór etapu (→ TEST-DESIGN)
Każdy etap odbierany na <b>żywych danych operatora</b>: dowód = zapis w bazce + widok w oknie + wpis w audicie + (od etapu 3) zmiana stanu CO DALEJ. Zielone testy ≠ odebrane; odebrane = operator zobaczył swój wynik i swoją listę.
A8.3 Zmiany po akcepcie
Nowy pomysł w trakcie = zgłoszenie do briefu (nie cicha rozbudowa zakresu); zmiana granic = nowa wersja SPEC + ponowny akcept. Uwagi w spec-sajcie (hejty inline, po) lądują jako komentarze w .
CZĘŚĆ B — JAK TO ZBUDUJEMY (techniczna; szczegóły w artefaktach fazy D)
B1. Wymagania jakościowe (NFR)
| ID | wymaganie |
|---|
| NFR-1 | Prywatność: dane wyłącznie w środowisko Wellysy ; zero danych pacjenta w RAG snowa; logi bez PII |
| NFR-2 | Proweniencja 100% rekordów; brak oryginału = flaga |
| NFR-3 | Wydajność: trend ≤ 10 s przy 100 k obserwacji (Watch: dziesiątki tysięcy/mies.); ewaluacja CO DALEJ ≤ 5 s |
| NFR-4 | Idempotencja: każdy import/webhook/wafel wznawialny bez duplikatów |
| NFR-5 | Pomiar zamiast deklaracji: freshness-badge per źródło; trzeci stan widoczny w oknie |
| NFR-6 | Reguły profilaktyczne wersjonowane z datą pomiaru i review_by; reguła po terminie = flaga, nie cicha prawda |
| NFR-7 | Dostępność „wystarczająco" dla 1 użytkownika; backup dobowy bazki + magazynu poza git-tree |
B2. Model danych → docs WELISKA DB-SCHEMA
17 tabel (DBML, parse round-trip zielony): <code>person</code>, <code>profile_history</code>, <code>metric</code>, <code>unit_conversion</code>, <code>source</code>, <code>document</code>, <code>report</code>, <code>observation</code>, <code>lab_name_map</code>, <code>intent_job</code>, <code>share_grant</code>, <code>access_log</code>, <code>rule</code>, <code>maintenance_state</code>, <code>nudge</code>, <code>algorithm_run</code>, <code>health_event</code>. Silnik: SQLite WAL na szyfrowanym wolumenie. Nazwy semantyczne ↔ <code>wellysa-ontology.dbml</code> (person/metryka/pomiar/norma/wskazanie/source/consent).
B3. Integracje zewnętrzne (decyzje z reconów)
| integracja | decyzja v0.2 | odrzucone (powód) | źródło |
|---|
| OCR | PaddleOCR 3.x PP-StructureV3 (latin_PP-OCRv5, CPU) + normalizacja LLM → fallback Azure DI West Europe po | Textract (brak pl), Surya/marker (licencja wag), MinerU (wzmianka w UI), olmOCR (en) | Recon OCR |
| Apple Watch | własna apka iOS (Ionic + Swift HealthSync w tle), @capgo/capacitor-health do uprawnień | Health Auto Export (decyzja operatora), perfood (Cap 4), cordova-plugin-health (bez anchora/entitlementu) | Recon Ionic |
| Android | Health Connect + WorkManager + READ_HEALTH_DATA_IN_BACKGROUND | — | Recon Ionic |
| Diagnostyka/ALAB | intent (nr zlecenia/kod) + opcjonalnie konto stałe (cron) | — | Recon źródła |
| P1 | przez Wellysę jako usługodawcę: Zgody → ITI-18 → ITI-43 (EDM), ZM; wellysa-api + EDM | P1 jako pacjent (nie istnieje) | Wellysa/p1 spec, Recon źródła |
| IKP | drop PDF | RPA z 2FA PZ | Recon źródła |
| reguły | własny silnik YAML (~20 reguł PL) + SCORE2 model; USPSTF API jako strength | CQL/CPG/OpenCDS (ciężar) | Recon algorytmy |
B4. Migracja danych
Backfill: <code>export.xml</code> (Apple), istniejące PDF-y operatora (drop), EDM z P1 po zgodzie (historia), ewentualnie RODO art. 20 z labów. Brak systemu poprzedniego.
B5. Środowiska i utrzymanie → docs WELISKA C4-DEPLOYMENT
dev: serwer platformy, workspace środowisko Wellysy, <code>czak-Snow-weliska.service</code> (API + portal statyczny), robot pobierający jako timery systemd, tunel cloudflared → hostname z, CF Access policy per email; prod: ta sama topologia, osobny wolumen i hostname. Gitflow: branch z tasku → PR → merge (operator) → deploy dev; prod = tag. iOS: TestFlight internal (re-upload ≤ 90 dni); Android: internal testing.
B6. Bezpieczeństwo / RODO (Art. 9)
Jak FR-ART9-1…6. Dodatkowo: kod jednorazowy Synevo tylko w pamięci robot pobierający; cert P1 zostaje u Wellysy (WELISKA nie trzyma certu); OCR-fallback poza EU = zakaz z konfiguracji; apka: zgoda przed transmisją, polityka prywatności, brak iCloud dla PHI.
B7. Ryzyka, założenia, otwarte kwestie
| # | ryzyko / pytanie | plan |
|---|
| R1 | jakość OCR na polskich wydrukach niezmierzona | macierz 10–20 własnych wydruków (etap 2) = KR1 |
| R2 | HealthKit budzi apkę „at most once per period"; częstość realna niezmierzona | pomiar na urządzeniu w etapie 8; freshness-badge |
| R3 | rejestr artefaktów środowisko Wellysy read-only | lokalny wolumen z dogrywką |
| R4 | słownik medyczny niewidoczny dla ext lore | tymczasowy subset LOINC labowy (oznaczony) |
| R5 | regulamin Diagnostyki (scraping własnych wyników = szara strefa) | tylko intent/konto operatora, rate-limit; decyzja |
| R6 | silnik algorytmów Wellysy nie wystawi kontraktu w czasie | etap 9 na końcu; bez własnych wzorów |
| R7 | reguły NFZ zmieniają się (3 zmiany w 16 mies.) | review_by + flaga; źródła z datą pomiaru |
| R8 | cert PROD P1 Wellysy — kto trzyma, czy dogfood może użyć | pkt 5; do decyzji etap 6 = INT (testy) → PROD |
| R9 | Play Health declaration na internal testing — niezmierzone | Android po iOS; sprawdzić przy publikacji |
| R10 | format QR na karteczce Synevo — niezmierzony | pomiar na żywej karteczce operatora (etap 5); fallback = wpis ręczny kodu |
B8. Poczekalnia (poza tą specyfikacją)
EKG z Watcha; Medplum jako FHIR-API dla lekarzy; drugi użytkownik (rodzina) i multi-tenant; spięcie z <code>wellysa-app</code> (profil zdrowotny z bazki); LabExtract (Medalion) jako OCR domenowy; import z apki Diagnostyki (mojeID); RODO-eksport z IKP w formacie maszynowym; półautomat IKP (sesja PZ operatora); <b>v2 GDZIE </b> i <b>v3 WALLET </b> jako osobne SPEC-rozszerzenia po dowodzie v1.