75 lines
4.1 KiB
Markdown
75 lines
4.1 KiB
Markdown
# CLAUDE.md — arbeidsinstruks for TeeCup
|
|
|
|
Les dette først i hver økt. Det koder hva vi har bestemt og hvordan vi jobber.
|
|
|
|
## Autoritative kilder (les før du gjør noe)
|
|
- `ARCHITECTURE_DECISIONS.md` — hva som er bestemt og hvorfor (ADR-001…013). Fasit.
|
|
- `FEATURE_BACKLOG.md` — hva som gjenstår, hva som er utsatt, hva som mangler.
|
|
- Endres en beslutning: legg til en ny ADR, ikke slett historikk. Hold begge
|
|
filene oppdatert når noe avgjøres.
|
|
|
|
## Sikkerhetsregler (ufravikelige)
|
|
- Rør ALDRI `teeoff`-databasen eller den ekte `teecup_db` uten at brukeren
|
|
eksplisitt har bekreftet det i samme økt. Test alltid migrasjoner mot en egen
|
|
scratch-database først, og rydd opp etterpå.
|
|
- Vis planen (hvilke kommandoer, mot hvilken database) FØR du kjører noe som
|
|
skriver, migrerer eller sletter. Vent på bekreftelse.
|
|
- Hemmeligheter (passord, secrets) bor i `.env` (filrettigheter 600), dekkes av
|
|
`.gitignore`, committes aldri, og skrives aldri i klartekst i chatten eller i
|
|
SQL-filer. Generer dem på serveren (`openssl rand -base64 32`).
|
|
- Kjør appen som databaserollen `teecup_app` (NOSUPERUSER, NOBYPASSRLS) — aldri
|
|
som `teeoff_admin`/superuser i runtime.
|
|
|
|
## Arkitektur-invarianter (ikke bryt uten en ny ADR)
|
|
- Tenant = organisasjon. `organization_id` på alle domenetabeller, håndhevet av
|
|
RLS. App-koden setter `app.current_org` med `SET LOCAL` per transaksjon.
|
|
- Verifiser at brukeren er medlem av organisasjonen FØR org-konteksten settes.
|
|
RLS stoler blindt på `app.current_org`.
|
|
- Egen innlogging (uavhengig av teeoff). Banedata hentes fra teeoff via lesende
|
|
API, ikke delt database.
|
|
- v1 = nøyaktig to lag (Ryder Cup-format), håndhevet i app-laget. Match-modellen
|
|
holdes generell (to sider) så knockout/flere lag kan komme senere.
|
|
- Handicap-/matchlogikk skal ligge i `handicap_engine.py` (rent, testet, uten
|
|
db/API-avhengigheter). Allowances er konfig, ikke hardkodet.
|
|
- Media (bilder/video) skal i objektlagring (MinIO), ikke i Postgres. Postgres
|
|
holder bare metadata + nøkkel.
|
|
|
|
## Arbeidsmåte
|
|
- Inkrementelt. Ingenting tas for gitt før det er testet. Bekreft hvert steg før
|
|
du går videre.
|
|
- Bruk git (remote: brukerens Forgejo). Commit i logiske steg med tydelige
|
|
meldinger.
|
|
- Er du usikker på omfang eller en beslutning: spør heller enn å gjette.
|
|
|
|
## Status (oppdater denne når ting endres)
|
|
Ferdig og verifisert:
|
|
- Handicap-motor + tester (24/24, R&A-verifisert).
|
|
- Skjema `001` + roller `002` + scoring/blind draw `003`. Isolasjon bevist med
|
|
`test_isolation.sql` (RLS-oppførsel, ikke bare at skjemaet kjører).
|
|
- 002 hadde en reell bug (psql interpolerer ikke `:'var'` inne i `DO $$...$$`)
|
|
— permanent fikset, verifisert mot scratch to ganger.
|
|
- API-et kjørt for ekte (ikke bare syntaks-sjekket) i en engangs Docker-
|
|
container mot en scratch-database, RLS bevist gjennom hele
|
|
asyncpg-pool-stacken (ikke bare i rå SQL).
|
|
- Oppsett-endepunktene er bygget og verifisert: `app/routers/players.py`
|
|
(spillerpool), `tournaments.py` (turnering/lag/roster/økter, ADR-011
|
|
to-lags-grense håndhevet med `FOR UPDATE`-lås), `matches.py` (matcher/
|
|
deltakere/blind draw-lås, ADR-013-synlighet push-down i SQL). Delt
|
|
feiloversettelse i `app/errors.py`, delte synlighetsspørringer i
|
|
`app/blind_draw.py`. `main.py` er nå bare app-factory + `include_router`.
|
|
**Bevisst utelatt:** `course_handicap`/`playing_handicap` på
|
|
`match_participant` beregnes IKKE ennå (venter på motor-integrasjon i
|
|
scoring-runden — flerspillerformater trenger hele sidens spillere samtidig).
|
|
**Bevisst minimal autorisasjon:** kapteins-only er ikke bygget (se
|
|
FEATURE_BACKLOG ❓); bar er i dag org-medlemskap for oppsett, og
|
|
"rostret på laget" for deltaker-/lås-handlinger.
|
|
|
|
Neste steg:
|
|
1. Scoring-endepunkter: `hole_score`/`match_hole_result`-skriving,
|
|
matchstatus fra `handicap_engine.compute_match_state`, og
|
|
handicap-beregning (`course_handicap`/`playing_handicap`) for
|
|
`match_participant` via motoren.
|
|
2. Containerisere TeeCup-API-et (Dockerfile + compose-tjeneste), koble mot
|
|
`teecup_db` med `teecup_app`, rute via eksisterende Caddy til
|
|
`teecup.teeoff.no`.
|
|
3. Deretter frontend (PWA, offline-first) og kommunikasjon (migrasjon 004).
|