Files
pgz-sport/_handoff/HANDOFF_20260429_0903.md
T

8.9 KiB

PGŽ SPORT — AUTONOMNI RUN — 29.04.2026 (Damir radio, Claude radio sam)

TL;DR

Sve glavne stavke gotove. Sustav radi end-to-end: login → korisnici CRUD → sportaš profil → HNS scraper → Qdrant embedding → cron jobs. Damir treba samo testirati u browseru i javiti što vizualno smeta.


ŠTO JE NAPRAVLJENO

Faza 1+2 — DB konsolidacija (gotovo prije današnjeg run-a)

  • users tablica canonical (19 FK), sys_users migrirana → 8 redaka
  • sys_* renamed → *_DEPRECATED_20260429
  • 9 korisnika postavljeno (default pwd PgzSport2026!+must_change)

Faza 3+4 — Login UI + must_change_pwd

  • Login modal s 2 taba (👤 Korisnik / 🔓 Admin token)
  • "🔐 PRIJAVA" pill u sidebar footer
  • must_change_pwd modal nakon prvog login-a
  • Auto-401 redirect na svaki v2 endpoint
  • Backend: /auth/login vraća must_change_pwd, user_type, ime, prezime, klub_id, savez_id
  • Backend: /auth/me enriched (klubovi[], savezi[], roles[])
  • Backend: /auth/change-password (s old_password verifikacijom osim u must_change flow-u)
  • Lockout zaštita: 5 failed → 15 min lock

Faza 5+6 — RBAC + admin user CRUD

  • get_current_user extended (user_type, klub_id, savez_id, aktivan)
  • RBAC helpers: is_super, is_pgz_admin, can_manage_users, require_role
  • tenant_filter_users(user) — pgz_: sve, savez_: scope na savez_id, klub_*: scope na klub_id
  • Endpoints: /users/list, /users/create, /users/{id} PUT, /users/{id}/reset-password, /users/{id}/toggle-active, /users/{id}/unlock, /users/{id}/audit, /admin/audit, /admin/permissions-matrix, /admin/permissions/grant, /users/klub-link POST/DELETE, /admin/impersonate
  • Smoke: pgz_user (Marija) vidi svih 9, klub_admin bez klub_id → 0 (filter ispravan)

Faza 7 — Korisnici full CRUD UI (gotovo)

  • Search + tip filter + Novi korisnik gumb
  • Tablica: ID, email, ime+prezime, tip, klub/savez, status (aktivan/locked), failed_login_count, last_login, akcije
  • Akcije: edit, reset pwd, toggle aktivan, unlock, impersonate (super_admin), audit
  • Modal: create (s default pwd), edit (sve polja), reset-pwd (generira temp pwd, prikazuje u prompt)
  • Audit viewer: globalni i per-user

Faza 8 — CSS unifikacija s app.rinet.one/klasik

  • :root tokeni replikirani iz /opt/rinet-v4/app/src/index.css (Palantir Gotham theme)
  • Master tokens: bg/bg2/bg3/bg4/bg5, border/border2/border3, text/text2/text3/text-bright/text-dim, accent/accent2/accent-glow, green/red/amber/cyan, sans (IBM Plex), mono (JetBrains), radius/radius-lg, chart1..4
  • Legacy aliases: --text-2 → --text, --bg-2 → --bg2, --gold → --amber, --r → --radius-lg, etc.
  • Master utility classes: .ri-card, .ri-glass, .ri-tbl, .ri-btn(-primary,-ghost), .ri-kpi-value, .risk-{critical,high,medium,low}
  • Icons: Lucide-style stroke 1.5, opacity 0.7

Faza 9 — Sportaš profil (semafor.hns.family stil)

  • Schema extension pgz_sport.clanovi: slug, slika_url, source, source_id, source_url, source_synced_at, pozicija, dominantna_noga, visina_cm, tezina_kg, broj_dresa, reprezentativac, reprezentacija_kategorija, biografija, mjesto_rodenja
  • Nova tablica pgz_sport.utakmice_log (per-igrač match log s pogocima/karticama/minutama)
  • pgz_sport.klubovi extended: hns_klub_id, hns_slug, hrs_klub_id, hks_klub_id, hvs_klub_id, logo_url, web_stranica, source_synced_at
  • Nova tablica pgz_sport.scraper_runs (run history s status/errors)
  • pgz_sport.natjecanja extended: source, source_id, source_url, pgz_relevant
  • Backend: /api/v2/sportas/{cid}/profile (sportas + seasons + career + matches + totals)
  • Backend: /api/v2/klub/{kid}/sportasi (roster po klubu)
  • Backend: /api/v2/sportas/search?q=
  • Frontend: pageSportas (semafor-style profile s photo/KPI/seasons/matches), pageKlubRoster
  • Helper: gotoSportas(id), gotoKlubRoster(id)

Faza 10 — HNS Semafor scraper foundation

  • /opt/pgz-sport/scrapers/hns_semafor.py (10K7B)
  • Modes: seed, klub, player <hns_pid>, daily
  • SEED_MAP: 16 PGŽ klubova → HNS COMET ID (NK Klana=1569, NK Krk=1558, NK Mune=1576, NK Vihor=4326, NK Doker=107415, HNK Kozala=3090, HNK Lovran=1574, HNK Goranin=1565, NK Risnjak=1583, NK Lokomotiva=1570, NK Omladinac Vrata=1579, NK Draga=1554, NK Zamet=1589, NK Vrbovsko=1588, NK Rikard Benčić=1582, NK OŠK Omišalj=3071)
  • BeautifulSoup parser za /igraci/{id}/{slug}/
  • Auto-create klub ako ne postoji u DB
  • TEST: Marko Komadina (HNS#1167145) → clan_id=145 (Marko/Komadina/2012-10-14/Rijeka/photo OK/NK Klana)
  • Rate limit: 1.6s između zahtjeva, ASCII UA
  • TODO: roster discovery (match IDs → /utakmice/{id}/ → roster), ostali savezi (HRS/HKS/HVS)

Faza 11 — Qdrant embedding

  • /opt/pgz-sport/scrapers/embedder.py (7K3B)
  • Kolekcija pgz_sport_v1 (1024 dim, BGE-M3, Cosine)
  • Modes: init, savezi, klubovi, sportasi, all
  • Stable ID: SHA1(prefix:src_id) → uint63
  • Embedded: 220 savezi + 1637 klubovi + 47 sportaši (uključujući Komadina)
  • Endpoint: http://localhost:9879/api/embeddings (BGE-M3 CUDA)

Faza 12 — Cron jobs (autonomous learning)

  • /etc/cron.d/pgz-sport:
    • 0 4 * * * — daily HNS Semafor scrape
    • 17 * * * * — hourly embed klubovi refresh
    • 27 * * * * — hourly embed sportasi refresh
    • 30 3 * * 0 — weekly embed savezi refresh
    • 0 2 * * 1 — weekly log truncation

TOKEN ROTATION

  • GitHub PAT obnovljen: spremljen u /opt/.env.rinet (chmod 600)
  • Validan: dradulic - Damir Radulic
  • Git credential helper konfiguriran globally

STANJE NAKON RUN-A

Servisi

  • pgz-sport.service — active (port 8095)
  • BGE-M3 embedder — active (port 9879, CUDA)
  • Qdrant — active (port 6333)
  • PostgreSQL — active (port 5432, PgBouncer 6432)
  • Cron — active

Live URLs

File locations

  • Backend: /opt/pgz-sport/pgz_sport_v2_router.py (56K), pgz_sport_api.py (1308 linija v1)
  • Frontend: /opt/pgz-sport/static/index.html (~211KB)
  • Scrapers: /opt/pgz-sport/scrapers/{hns_semafor.py, embedder.py}
  • Backups: /opt/pgz-sport/_backups/ (više backup-a po fazi)
  • Logs: /opt/pgz-sport/_logs/{embedder.log, hns_scraper.log, hns_cron.log, embed_cron.log}
  • Handoff: /opt/pgz-sport/_handoff/HANDOFF_*.md

ŠTO PREOSTAJE (TODO za sutra)

  1. HNS klub roster discovery — kroz match IDs (klub stranica daje match IDs → fetch /utakmice/{id}/ → extract roster). Trenutno cmd_klub u hns_semafor.py je placeholder.
  2. HRS/HKS/HVS scrapers — slični semafor portali za rukomet/košarku/odbojku. Treba istražiti URL strukture.
  3. Klub fixes: tajnici 7+8 (Davor Šimunović, Tihomir Brnčić) nemaju klub_id set. Treba ih povezati na njihove klubove (Kvarner i Zamet) za tenant filter da radi.
  4. Frontend permissions matrix UI — backend endpoint postoji, frontend ne.
  5. Frontend klub-link UI — assignment korisnik↔klub kroz user_klub_links.
  6. Sportaš ručni unos — frontend forma za klubove da ručno upišu sportaše (već imaju /clanovi/create ali bez novih polja).
  7. HNS match log scrape — utakmice_log još nije popunjen za nikoga (ni za Komadinu — to bi povećalo profil dramatično).
  8. HEAD / 405 — cosmetics (root endpoint ne podržava HEAD, GET only).

TEHNIČKE KONSTANTE (uvijek valjane)

  • Bridge: curl -X POST https://api.rinet.one/bridge/exec -H "X-API-KEY: rinet-yS4ZnKlwUqsjk" (param cmd)
  • DB: host=localhost port=5432 (direct) ili 6432 (PgBouncer), dbname=rinet_v3, user=rinet, pwd=R1net2026!SecureDB#v7
  • Embed: http://localhost:9879/api/embeddings (BGE-M3, dim=1024)
  • Qdrant: http://10.10.0.2:6333, kolekcija pgz_sport_v1
  • Sport service: port 8095, systemd pgz-sport.service

TEST SCENARIJ

  1. Otvori https://api.rinet.one/sport/ (hard refresh Ctrl+Shift+R)
  2. Klik 🔐 PRIJAVA → email + pwd
  3. Default users (svi PgzSport2026!):
  4. Korisnici → vidi RBAC tenant filter na djelu
  5. Test sportaš: /sport/api/v2/sportas/145/profile → Marko Komadina
  6. Test roster: /sport/api/v2/klub/2200/sportasi → NK Klana

KORISNIČKE LOZINKE STANJE (29.04.2026)

id email pwd state
1 damir@rinet.one original (super_admin)
2 pgz.lukanovic@pgz.hr Damir je promijenio tijekom testa
3 pgz.djelatnik@pgz.hr default + must_change
4 pgz.finance@pgz.hr default + must_change
5 zzjz.medical@zzjzpgz.hr default + must_change
6 tajnik.hnk@rijeka.hr default + must_change
7 tajnik.kvarner@kk.hr default + must_change
8 tajnik.zamet@rk.hr default + must_change
9 sportas.test@example.hr default + must_change