165 lines
8.9 KiB
Markdown
165 lines
8.9 KiB
Markdown
# 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
|
|
- https://api.rinet.one/sport/ — frontend (211KB)
|
|
- https://api.rinet.one/sport/api/v2/auth/* — auth
|
|
- https://api.rinet.one/sport/api/v2/users/* — admin user mgmt
|
|
- https://api.rinet.one/sport/api/v2/sportas/* — sportaš profil
|
|
- https://api.rinet.one/sport/api/v2/klub/{id}/sportasi — roster
|
|
|
|
### 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!`):
|
|
- pgz.djelatnik@pgz.hr (Marija, pgz_user)
|
|
- pgz.finance@pgz.hr (pgz_finance)
|
|
- tajnik.hnk@rijeka.hr (savez_admin)
|
|
- sportas.test@example.hr (klub_clan)
|
|
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 |
|
|
|