docs(f0): define anti-cheat policy for Fup og Fakta

This commit is contained in:
2026-02-27 13:40:25 +01:00
parent e921bd6b4b
commit a2e43d79ce

View File

@@ -0,0 +1,88 @@
# F0 Anti-cheat regler — Fup og Fakta
## Formål
Fastlægge en enkel, håndterbar anti-cheat baseline for MVP, så spillet forbliver fair uden tung NLP/moderation.
## Principper (F0)
1. **Server-authoritative regler**: Alle valideringer og afvisninger sker server-side.
2. **Forudsigelige regler**: Spillere skal møde tydelige og konsistente afvisningsårsager.
3. **Lav kompleksitet i MVP**: Kun deterministiske checks i F0; semantisk lighed udskydes.
## Need-to-have regler (MVP)
### R1 — Én løgn pr. spiller pr. spørgsmål
- Spiller kan kun have ét aktivt `LieAnswer` per spørgsmål.
- Ny indsendelse før timeout overskriver tidligere svar (samme spiller/samme spørgsmål).
- Efter fase-lock (timeout eller host-advance) afvises nye indsendelser.
### R2 — Ingen tomme eller trivielt ugyldige svar
- Afvis tom streng, whitespace-only og svar uden bogstaver/tal.
- Normaliser input før validering: trim + collapse af gentagne mellemrum.
### R3 — Ingen identiske løgne internt i runden
- To spillere må ikke ende med samme normaliserede løgn på samme spørgsmål.
- Duplikatcheck bruger en deterministisk `canonical_form`, fx:
- lowercase
- trim + single-space
- fjern ledende/afsluttende tegnsætning
- Ved konflikt får den seneste indsender en valideringsfejl og skal indsende ny løgn inden tidsfristen.
### R4 — Ingen identisk løgn med korrekt svar
- Spillerløgn må ikke matche spørgsmålets korrekte svar efter samme normalisering som R3.
- Ved match afvises svaret med fejlbesked.
### R5 — Basal anti-spam og inputgrænser
- Løgn-længde begrænses (foreslået MVP: 2-120 tegn).
- Payloads over max længde afvises (ikke trunkeres silent).
- Simpelt request-throttle på submit-endpoint per spiller/session (fx 5 requests/10 sek).
### R6 — Auditérbarhed
- Afviste submit-forsøg logges med årsagskode (fx `duplicate_lie`, `matches_truth`, `phase_locked`).
- Logning må ikke gemme unødige persondata ud over det nødvendige til fejlsøgning/audit.
## Nice-to-have (efter MVP)
- Semantisk duplikatdetektion ("København" vs "kbh").
- Levenshtein/fuzzy match mod korrekt svar for næsten-identiske svar.
- Sprog-/profanitetsfilter og moderationspipeline.
- Avanceret anomaly-detektion (bot-lignende submit-mønstre).
## Implementeringsnære acceptance criteria (F0)
F0 anti-cheat anses som leveret når følgende kan verificeres i tests eller integration:
1. **Duplicate player submit**
- Givet samme spiller + samme spørgsmål, når spiller submitter to gange før lock,
- så findes kun ét aktivt svar, og sidste version er den gældende.
2. **Duplicate lie across players**
- Givet to spillere på samme spørgsmål,
- når spiller B submitter en `canonical_form` identisk med spiller A,
- så afvises spiller B med deterministisk fejl `duplicate_lie`.
3. **Lie equals truth**
- Givet korrekt svar for spørgsmålet,
- når en spiller submitter løgn med samme `canonical_form`,
- så afvises submit med fejl `matches_truth`.
4. **Phase lock enforcement**
- Når løgnefasen er låst,
- så afvises alle nye submit-forsøg med fejl `phase_locked`.
5. **Input validation boundaries**
- Svar under min-længde, over max-længde eller whitespace-only afvises med specifik fejl.
6. **Audit trail present**
- For hver afvist submit oprettes en audit/log-entry med tidsstempel og årsagskode.
## Foreslåede fejlkoder (kontrakt)
- `invalid_format`
- `too_short`
- `too_long`
- `duplicate_lie`
- `matches_truth`
- `phase_locked`
- `rate_limited`
## Noter om data/model (ikke bindende design)
- Overvej DB-constraint/unik indeks på `(question_id, canonical_form)` for aktive løgne,
suppleret med applikationsvalidering for gode fejlbeskeder.
- `canonical_form` bør beregnes ens i backend-path (API + evt. admin tooling).