{"id":"c1262","filename":"c1262_zakon45_portal_token_ttl_opoziv.dok.json","weise3_id":"WEISE3::zakon45_portal_token::fenix-v4::invoice::FENIX2026","tip":"zakon_implementacija","naziv":"ZAKON 45 — Portal token TTL + opoziv (token_is_live)","kreator":"genesis","datum":"2026-06-05","snippet":"","status":"","prev_weise3":"","bunker_l":"#00d4ff","full":{"tip":"zakon_implementacija","naziv":"ZAKON 45 — Portal token TTL + opoziv (token_is_live)","weise3_id":"WEISE3::zakon45_portal_token::fenix-v4::invoice::FENIX2026","datum":"2026-06-05","commit":"4271e0b","sto_je_napravljeno":{"model":"Invoice.token_expires_at (TTL 365d) + token_revoked_at (opoziv) — ZAKON 27 polje","migracija":"0031 — ADD COLUMN x2, backfill created_at+365d, indeks ix_inv_token_expires_at","token_is_live":"jedina funkcija odluke: fail-closed, NULL expires = mrtav, revoked = mrtav","portal_endpointi":"3x HTTPException(410) ako !token_is_live() — GET/PDF/acknowledge","opoziv_endpoint":"POST /portal/{token}/revoke — owner-only, InvoiceEvent tracing","scope_potvrda":"UUID unique constraint na client_token: WHERE token=X tocno 1 resurs","entropija":"uuid4() = os.urandom(16) = 122-bit efektivne slucajnosti"},"zakon_45_p5b_tekst":"portal token-izoliran: TTL (365d, produzivo) + opoziv (revoke endpoint) obvezni, provjera kroz token_is_live(). UUID unique: 1 token = 1 resurs. Entropija: 122-bit os.urandom. fail-closed: NULL expires = odbijeno.","gdpr_daphne":"Vjecni javni link s ime+OIB+iznosom eliminiran. Token ima rok i moze biti opozvan.","verifikacija_db":{"token_expires_at_kolona":"timestamp with time zone NOT NULL (backfillana)","token_revoked_at_kolona":"timestamp with time zone NULL","uuid_unique_index":"invoicing_invoice_client_token_key UNIQUE"}}}