pdate Todos
Legge til visuell hint på øktkort ("Sett opp flights") i program-skjermen
Avklare designbeslutninger for Brukerroller med bruker
Skrive team_authz.py på nytt (kaptein-only + match-deltaker-sjekk)
Oppdatere matches.py til å bruke user_is_team_captain
Oppdatere scoring.py til å bruke user_is_match_participant
Håndheve 'kun én kaptein per lag' i tournaments.py PATCH/POST roster
Sjekke ekte teecup_db for lag uten kaptein / med flere kapteiner (kun lesing)
Skrive ADR-023 for Brukerroller-beslutningene
Sette opp scratch MinIO + engangs API-container
Kjøre autorisasjonstester (kaptein/deltaker) mot scratch-API-et
Rydde opp scratch-infrastruktur
Ekte typesjekket frontend-build (øktkort-hint)
Deploy etter eksplisitt bekreftelse + oppdatere .md-filer
Live og verifisert. Oppsummert:
Øktkort-hint: "Sett opp flights og lås oppstilling →" vises nå tydelig på hvert øktkort i Program-fanen.
Brukerroller (ADR-023):
Kaptein er nå en reell autorisasjonsrolle — kun kaptein (eller org-eier/admin) kan legge til/fjerne deltakere og låse laget. Har et lag ingen utpekt kaptein ennå (som "De Unge" har akkurat nå — sjekket mot ekte data før utrulling), gjelder samme åpne tilgang som før, så ingen ble låst ute av endringen.
"Kun én kaptein per lag" håndheves nå — å utpeke en ny kaptein fjerner automatisk merket fra forrige.
Score føres nå kun av matchens faktiske deltakere (eller org-admin), ikke lenger "hvem som helst på laget" — uavhengig av kapteinmerket.
Fant og fikset en reell 500-bug under scratch-testing (enum/tekst-sammenligning i SQL) før noe nådde produksjon.
Alt scratch-verifisert (15 automatiserte sjekker + test_isolation.sql 12/12), typesjekket produksjonsbuild kjørt, deployet uten migrasjon, teeoff.no upåvirket.
Naturlig neste steg nå som brukerroller er avgjort: walkover/konsesjon (ventet tidligere nettopp på dette) kan tas fatt på — men si fra hva du vil prioritere.
This commit is contained in:
parent
e60a2aafe7
commit
c3cca377ed
4 changed files with 69 additions and 9 deletions
|
|
@ -280,7 +280,10 @@
|
|||
"Bash(curl -s -o /dev/null -w '%{http_code}\\\\n' https://teecup.teeoff.no/dashboard)",
|
||||
"Bash(grep -n \"teecup\" -A 20 /opt/teeoff/deploy/Caddyfile 2>/dev/null | head -60)",
|
||||
"Bash(curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\\\\n' -b \"teecup_session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI4NDYzM2JlMS1iZWM1LTQ1ZDItOTI1ZC1lNzAzYTdjOWM1OGYiLCJpYXQiOjE3ODQ0NDc5NzIsImV4cCI6MTc4NzAzOTk3Mn0.wQAHP4qlo-zzHH7JrDWm_FyupW8g-_vMkr96szWmuXg\" https://teecup.teeoff.no/)",
|
||||
"Bash(curl -s -w '\\\\n%{http_code}\\\\n' -X POST https://teecup.teeoff.no/auth/login-password -H \"Content-Type: application/json\" -d '{\"email\":\"ikke@finnes.no\",\"password\":\"whatever\"}')"
|
||||
"Bash(curl -s -w '\\\\n%{http_code}\\\\n' -X POST https://teecup.teeoff.no/auth/login-password -H \"Content-Type: application/json\" -d '{\"email\":\"ikke@finnes.no\",\"password\":\"whatever\"}')",
|
||||
"Bash(curl -s -o /dev/null -w \"health: %{http_code}\\\\n\" https://teecup.teeoff.no/health)",
|
||||
"Bash(curl -s -o /dev/null -w \"dashboard: %{http_code}\\\\n\" https://teecup.teeoff.no/dashboard)",
|
||||
"Bash(curl -s -o /dev/null -w \"teeoff.no: %{http_code}\\\\n\" https://teeoff.no)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"/opt/teeoff/deploy",
|
||||
|
|
|
|||
|
|
@ -961,9 +961,9 @@ formelt tilskuer-begrep bør defineres sammen med det ennå ubesluttede
|
|||
synlighetsspørsmålet for «Banter Board»-feeden (FEATURE_BACKLOG), ikke
|
||||
isolert her, for å unngå å bygge to overlappende synlighetsmodeller.
|
||||
|
||||
**Status: ✅ BYGGET 2026-07-19.** Ingen migrasjon (ren autorisasjonslogikk,
|
||||
ingen skjemaendring). Se CLAUDE.md-status for scratch-verifisering og
|
||||
utrulling.
|
||||
**Status: ✅ BYGGET OG LIVE 2026-07-19.** Ingen migrasjon (ren
|
||||
autorisasjonslogikk, ingen skjemaendring). Se CLAUDE.md-status for
|
||||
scratch-verifisering og utrulling.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
63
CLAUDE.md
63
CLAUDE.md
|
|
@ -1334,12 +1334,69 @@ Ferdig og verifisert:
|
|||
Bevisst utenfor omfang: dedikert superadmin-UI (brukes via API av en
|
||||
betrodd operatør), SMS som 2FA-metode.
|
||||
|
||||
- **Program-skjerm: tydeligere klikk-hint på øktkort (2026-07-19):** brukeren
|
||||
påpekte at ingenting i grensesnittet indikerte at et øktkort er klikkbart
|
||||
inn til blind draw-skjermen. Lagt til en synlig "Sett opp flights og lås
|
||||
oppstilling →"-rad nederst i hvert kort (`components/tournament-program.tsx`).
|
||||
Ren frontend-endring, ingen backend-rørt.
|
||||
- **Brukerroller: kaptein som reell autorisasjon, deltaker-avgrenset scoring
|
||||
(2026-07-19, ADR-023):** direkte oppfølging av det lenge åpne
|
||||
"Brukerroller"-punktet i FEATURE_BACKLOG.md. Fire beslutninger avklart
|
||||
eksplisitt med bruker (AskUserQuestion) før bygging — alle anbefalte valg.
|
||||
**Bygget:** `app/team_authz.py` skrevet om — `user_is_team_captain`
|
||||
(erstatter `user_may_act_for_team`) krever `is_captain=true` på
|
||||
`team_roster` (eller org-eier/admin) for å legge til/fjerne deltakere og
|
||||
låse et lag (`matches.py`); ny `user_is_match_participant` krever en ekte
|
||||
`match_participant`-rad for brukeren i AKKURAT den matchen (valgfritt
|
||||
side-spesifikk via `team_side`) for å føre/korrigere score (`scoring.py`)
|
||||
— uavhengig av kapteinmerket. Nye feilkoder `NOT_TEAM_CAPTAIN` og
|
||||
`NOT_MATCH_PARTICIPANT` (erstatter `NOT_ROSTERED_ON_TEAM` på disse fem
|
||||
stedene). `app/routers/tournaments.py` sin `PATCH`/`POST .../roster`
|
||||
håndhever nå "kun én kaptein per lag" (fjerner automatisk forrige
|
||||
kapteins merke i samme transaksjon).
|
||||
**Reelt funn FØR utrulling, ikke antatt:** sjekket (kun lesing, superbruker
|
||||
mot ekte `teecup_db`) om noen eksisterende lag ville blitt låst ute av en
|
||||
ren kaptein-only-regel — "De Unge" i "De Gamle er Eldst" har i dag 0 av 2
|
||||
roster-rader merket kaptein. Designet derfor en bevisst fallback i
|
||||
`user_is_team_captain`: har laget INGEN utpekt kaptein ennå, godtas enhver
|
||||
rostret spiller i stedet for å låse laget helt ute. Ingen lag hadde flere
|
||||
kapteiner, så "kun én kaptein"-håndhevelsen krevde ingen data-opprydning.
|
||||
**Reell bug funnet OG fikset UNDER scratch-testing:** `user_is_match_
|
||||
participant` sin SQL sammenlignet `mp.team_side` (enum-kolonne) direkte
|
||||
mot en tekst-parameter uten cast når `team_side=None` (hole_result-modus)
|
||||
— ga en rå 500 (`UndefinedFunctionError: operator does not exist: team_side
|
||||
= text`). Rettet med et eksplisitt `mp.team_side::text = $3`.
|
||||
**Verifisert grundig mot fersk `teecup_scratch`** (isolert
|
||||
`teecup_app_scratch`-rolle, isolert scratch-MinIO, engangs API-container):
|
||||
et 15-punkts Python/httpx-testskript som simulerte fire innloggede
|
||||
brukere (organisator + tre rostrede spillere på to lag) gjennom hele
|
||||
syklusen — lag uten kaptein tillater enhver rostret (fallback bekreftet),
|
||||
kaptein utpekt fjerner andre rostredes rettighet, "kun én kaptein" bekreftet
|
||||
(ny kaptein avsetter automatisk forrige), org-admin fungerer uendret
|
||||
uavhengig av kaptein, og scoring (`hole_result`-modus) bekreftet begrenset
|
||||
til faktiske matchdeltakere (en kaptein som IKKE selv spiller matchen ble
|
||||
korrekt avvist med `NOT_MATCH_PARTICIPANT`, mens en faktisk deltaker og
|
||||
org-admin begge fikk føre score). Måtte også oppdage og legge til et
|
||||
forutsetning-steg underveis: `get_authorized_org` krever
|
||||
`organization_membership` for ALLE org-scopede endepunkter uansett — en
|
||||
rostret spiller må derfor også være invitert som org-medlem (minimum
|
||||
'member', ADR-022s invitasjonsflyt) for i det hele tatt å nå
|
||||
team_authz-vurderingen; ikke en bug, men en forutsetning testskriptet
|
||||
først manglet. `test_isolation.sql` 12/12 uendret (ingen skjemaendring).
|
||||
Ekte typesjekket produksjonsbuild av frontend (øktkort-hintet fra samme
|
||||
runde) kjørt og bekreftet, alle 11 ruter listet.
|
||||
**Rullet ut live 2026-07-19**, bruker bekreftet eksplisitt: ingen
|
||||
migrasjon, `docker compose up -d --build teecup_api teecup_frontend`,
|
||||
begge containere boot-et rent (`Application startup complete`, Next.js
|
||||
`Ready`), `/health` og `/dashboard` → 200, `teeoff.no` upåvirket.
|
||||
|
||||
Neste steg:
|
||||
1. PWA-egenskaper (manifest, service worker, offline-cache) — ikke startet.
|
||||
2. Kommunikasjon (chat/feed) — ikke startet.
|
||||
3. Fortsatt åpne beslutninger fra FEATURE_BACKLOG.md (walkover/konsesjon,
|
||||
sanntid/WebSockets vs. polling, tilskuer-rolle, kode-regenerering for
|
||||
ADR-020) — bør avklares i egne, dedikerte runder når det er naturlig.
|
||||
3. Fortsatt åpne beslutninger fra FEATURE_BACKLOG.md: walkover/konsesjon
|
||||
(kan nå tas fatt på — ventet tidligere på brukerroller/ADR-023, som nå er
|
||||
avgjort og bygget), sanntid/WebSockets vs. polling, tilskuer-rolle
|
||||
(bevisst utsatt til Kommunikasjon-runden), kode-regenerering for ADR-020.
|
||||
4. Ved fremtidige nye V0-skjermer/-design i V0 (fortsett i samme prosjekt),
|
||||
FORVENT en full re-eksport hver gang — diff mot live-treet i et
|
||||
scratch-område før noe pakkes ut over eksisterende filer, og sjekk om
|
||||
|
|
|
|||
|
|
@ -298,8 +298,8 @@
|
|||
## Ønsket, men IKKE fanget før nå (fra Gemini-samtalene)
|
||||
|
||||
### Brukerroller (utover org-medlemskap) — ADR-023
|
||||
- **Status:** ✅ BYGGET OG SCRATCH-VERIFISERT 2026-07-19 (deploy venter på
|
||||
bekreftelse) — kaptein/deltaker-delen. Tilskuer bevisst utsatt.
|
||||
- **Status:** ✅ BYGGET OG LIVE 2026-07-19 — kaptein/deltaker-delen.
|
||||
Tilskuer bevisst utsatt.
|
||||
- De opprinnelige samtalene beskriver: turneringsadmin, **lagkaptein**, spiller,
|
||||
**tilskuer** (les-only, følger live uten skriverettigheter).
|
||||
- Vi har i dag org-roller (owner/admin/member) + `is_captain` på roster.
|
||||
|
|
|
|||
Loading…
Reference in a new issue