{"id":"c1203","filename":"c1203_offline_sigurne_sobe_spec.dok.json","weise3_id":"","tip":"spec","naziv":"ULAZ Korak 5 — Offline-sigurne sobe: definicija granice","kreator":"genesis","datum":"2026-05-31","snippet":"","status":"SPEC — nije implementirano","prev_weise3":"","bunker_l":"#00d4ff","full":{"c":1203,"tip":"spec","naziv":"ULAZ Korak 5 — Offline-sigurne sobe: definicija granice","datum":"2026-05-31","status":"SPEC — nije implementirano","naelo":"Test dolazi nakon granice, ne umjesto nje.","granica":{"pravilo":"Soba je offline-sigurna ako i samo ako sve njene operacije mogu raditi s weise3_id kao jedinom identifikacijom — bez user_id, bez DB lookupa po user_id, bez CompanyMember provjere po user_id.","dependency":"Offline-sigurna soba koristi get_current_user_tprg. Soba koja zahtijeva user_id koristi get_current_user (online, JWT).","nije_pregovaracka_stavka":"user_id=None smije doći samo u sobu koja je eksplicitno označena offline-sigurnom. Svaka druga soba mora odbaciti TPRG token s 403 (ne 401) — jer identitet je valjan, ali soba nije offline-sigurna."},"offline_sigurne_sobe":[{"soba":"POST /api/v4/tprg/verify","razlog":"Javna, offline po dizajnu — verificira token bez baze i mreže.","status":"LIVE"},{"soba":"GET /api/v4/tprg/qr/{qr_payload}","razlog":"Javna, samo generira QR PNG — nema identiteta.","status":"LIVE"},{"soba":"ALIBI /capture (budući endpoint)","razlog":"Hvatanje dokaznog atoma — weise3_id dovoljan, user_id nije potreban. Atom se veže na weise3_id, ne na interni UUID.","status":"FUTURE — blokirana dok ALIBI ne postoji"},{"soba":"GET /api/v4/borg/health","razlog":"Javni health check — bez identiteta.","status":"LIVE (javno, ne treba auth)"}],"NIJE_offline_sigurno":[{"soba":"vault/*","razlog":"FenixVaultKey.user_id == user.user_id — None u WHERE = katastrofa."},{"soba":"invoicing/*","razlog":"CompanyMember.user_id lookup — None ne odgovara nijednom članu."},{"soba":"komitenti/*","razlog":"Isti razlog kao invoicing."},{"soba":"devices/*","razlog":"_get_device_or_403 prima user_id kao UUID — None pada."},{"soba":"kanal/* (većina)","razlog":"Poruke se vežu na user_id u bazi. Iznimka: read-only prikaz po weise3_id — kandidat za budući offline-safe."},{"soba":"pos/racun (POST)","razlog":"CompanyMember lookup po user_id za company pristup. POS smjena nosi company_id ali još uvijek radi DB upis vezan na user_id."}],"mehanizam_odbijanja":{"sto":"Soba koja nije offline-sigurna mora provjeriti user_id na ulasku.","kako":"if user.user_id is None: raise HTTPException(403, 'Ova soba zahtijeva online autentikaciju.')","gdje":"Na JEDNOM centralnom mjestu — require_online() dependency, ne u svakoj sobi zasebno.","kod":"async def require_online(user: AuthenticatedUser = Depends(get_current_user)) -> AuthenticatedUser:\n    if user.user_id is None:\n        raise HTTPException(403, 'Soba nije offline-sigurna. Potrebna online autentikacija.')\n    return user"},"redoslijed_implementacije":["1. Dodati require_online() u core/middleware.py (jedan dependency, ZAKON 11)","2. Sve sobe koje koriste user.user_id mijenjaju Depends(get_current_user) → Depends(require_online)","3. ALIBI soba pri nastanku: Depends(get_current_user_tprg) — prva prava offline-sigurna mutacija","4. Test: TPRG token na offline-sigurnoj sobi prolazi; na require_online sobi dobiva 403"],"napomena":"Danas nema aktivnog kvara jer get_current_user_tprg nije ožičen ni na jedan od rizičnih routera. Latentni rizik, ne aktivan. Granica se definira sada, implementira uz ALIBI (Pčela 2)."}}