# Kvalitetsprinsipper — gjør det riktig, én gang

## Motivasjon

Bedre med én komponent som fungerer perfekt enn 200 som fungerer
halvveis. Gaffatape-løsninger skaper teknisk gjeld som vokser
eksponentielt. Disse prinsippene gjelder all kode og konfigurasjon
i Synops.

## 1. Ikke hardkod det som kan utledes

Hvis verdien kan leses fra konteksten (request, miljø, database),
ikke hardkod den i en konfigurasjonsfil.

**Feil:**
```
ORIGIN=https://ws.synops.no  # låser hostname
DOMAIN=sidelinja.org         # låser domene
API_URL=https://api.sidelinja.org  # hardkodet URL
```

**Riktig:**
```
AUTH_TRUST_HOST=true  # les hostname fra request
MASKINROMMET_URL=http://127.0.0.1:3100  # intern, hostname-uavhengig
```

Spørsmålet å stille: "Hvis vi legger til et subdomain eller bytter
domene i morgen, hva går i stykker?" Hvis svaret er noe — det er
hardkodet og bør utledes dynamisk.

## 2. Forstå *hvorfor* noe fungerer

Ikke bare at det fungerer. Når du setter en konfigverdi og ting
begynner å virke, forstå mekanismen. Ellers vet du ikke hva som
knekker når konteksten endres.

**Feil:** "Jeg la til ORIGIN og da fungerte det."
**Riktig:** "SvelteKit bruker ORIGIN for å bygge event.url.
AUTH_TRUST_HOST=true lar den lese fra Host-headeren i stedet.
Vi trenger ORIGIN bare hvis vi ikke stoler på proxyen — men
Caddy setter riktig Host."

## 3. Én mekanisme per problem

Ikke to løsninger som delvis overlapper. Det skaper forvirring
om hvilken som faktisk gjør jobben, og konflikter når de ikke
er enige.

**Feil:** CSRF-beskyttelse i SvelteKit *og* OIDC PKCE+state.
Når de konflikter (cross-origin POST) vet du ikke hvilken du
skal stole på.

**Riktig:** OIDC eier CSRF for auth-flyten. SvelteKit sin
origin-sjekk deaktiveres eksplisitt med dokumentert begrunnelse.

## 4. Konfigurer på lavest mulig nivå

Foretrekk infrastruktur-konfig over applikasjons-konfig.
Foretrekk konvensjon over konfigurasjon.

```
Caddy (routing, TLS, domener)
  → SvelteKit (hostname-deteksjon, roller)
    → Komponent (viser riktig innhold)
```

Ikke la SvelteKit gjøre Caddy sin jobb (ruting). Ikke la
komponenter gjøre SvelteKit sin jobb (auth-sjekk).

## 5. Wildcard over spesifikk der det er trygt

Cookie på `.synops.no` fremfor `ws.synops.no` — fordi vi eier
alle subdomener. Caddy lytter på alle domener vi konfigurerer.
Ikke begrens noe du må utvide senere.

Unntak: sikkerhet. CSRF-token er host-bound (`__Host-`).
Autentisering er domeneovergripende (`.synops.no`).

## 6. Sjekkliste for nye subdomener/domener

Før du legger til et nytt domene/subdomain, sjekk:

- [ ] Finnes det en ORIGIN-variabel som hardkoder hostname?
- [ ] Er cookie-domene kompatibelt (`.synops.no`)?
- [ ] Er OIDC redirect URI registrert i Authentik?
- [ ] Er Caddy-blokken lagt til?
- [ ] Finnes det hardkodede URLer i koden (`https://ws.synops.no/...`)?
- [ ] Bruker koden `event.url.hostname` riktig?

## 7. Test med andre øyne

Etter implementering, tenk: "Hva skjer om..."
- ...vi legger til et tredje subdomain?
- ...vi bytter fra synops.no til annet domene?
- ...en bruker har gammel cache/cookies?
- ...Caddy restarter med nytt sertifikat?

Hvis svaret er "det går i stykker" — det er hardkodet.

## 8. Dokumenter beslutninger, ikke bare kode

Ikke bare *hva* som ble gjort, men *hvorfor*. Og spesielt:
*hva vi vurderte og valgte bort*. Neste person (eller neste
Claude-sesjon) som leser koden trenger å forstå intensjonen,
ikke bare mekanismen.

## 9. Preferer fjerning over tillegg

Hvis du kan løse problemet ved å fjerne kode/konfig i stedet
for å legge til, gjør det. Fjerne ORIGIN var bedre enn å legge
til ORIGIN-liste med flere domener.

Mindre kode = færre feil = enklere å forstå.

## 10. Én fiks, ikke to workarounds

Når noe ikke fungerer, finn rotårsaken. Ikke legg på et lag
med workarounds som maskerer problemet. To workarounds er
verre enn én ufikset bug — fordi de interagerer uforutsigbart.

**Feil:**
1. ORIGIN hardkodet → fungerer for ws
2. adm fungerer ikke → legg til hostname-sjekk i hooks
3. Cookie fungerer ikke → sett wildcard-domene
4. CSRF blokkerer → deaktiver CSRF

(Fire endringer for å kompensere for én feilkonfigurert variabel)

**Riktig:**
1. Fjern ORIGIN (rotårsaken)
2. Cookie wildcard (nødvendig for multi-subdomain uansett)
3. CSRF deaktivering (riktig når OIDC eier auth-flyten)

(Tre endringer, men hver er riktig i seg selv — ikke workarounds)
