项目文件夹

文件
2026-07-13 13:39:12 +08:00

418 行
26 KiB
Markdown

# CLAUDE.md (Norsk)
🌐 **Languages:** 🇺🇸 [English](../../../CLAUDE.md) · 🇸🇦 [ar](../ar/CLAUDE.md) · 🇦🇿 [az](../az/CLAUDE.md) · 🇧🇬 [bg](../bg/CLAUDE.md) · 🇧🇩 [bn](../bn/CLAUDE.md) · 🇨🇿 [cs](../cs/CLAUDE.md) · 🇩🇰 [da](../da/CLAUDE.md) · 🇩🇪 [de](../de/CLAUDE.md) · 🇪🇸 [es](../es/CLAUDE.md) · 🇮🇷 [fa](../fa/CLAUDE.md) · 🇫🇮 [fi](../fi/CLAUDE.md) · 🇫🇷 [fr](../fr/CLAUDE.md) · 🇮🇳 [gu](../gu/CLAUDE.md) · 🇮🇱 [he](../he/CLAUDE.md) · 🇮🇳 [hi](../hi/CLAUDE.md) · 🇭🇺 [hu](../hu/CLAUDE.md) · 🇮🇩 [id](../id/CLAUDE.md) · 🇮🇩 [in](../in/CLAUDE.md) · 🇮🇹 [it](../it/CLAUDE.md) · 🇯🇵 [ja](../ja/CLAUDE.md) · 🇰🇷 [ko](../ko/CLAUDE.md) · 🇮🇳 [mr](../mr/CLAUDE.md) · 🇲🇾 [ms](../ms/CLAUDE.md) · 🇳🇱 [nl](../nl/CLAUDE.md) · 🇵🇭 [phi](../phi/CLAUDE.md) · 🇵🇱 [pl](../pl/CLAUDE.md) · 🇵🇹 [pt](../pt/CLAUDE.md) · 🇧🇷 [pt-BR](../pt-BR/CLAUDE.md) · 🇷🇴 [ro](../ro/CLAUDE.md) · 🇷🇺 [ru](../ru/CLAUDE.md) · 🇸🇰 [sk](../sk/CLAUDE.md) · 🇸🇪 [sv](../sv/CLAUDE.md) · 🇰🇪 [sw](../sw/CLAUDE.md) · 🇮🇳 [ta](../ta/CLAUDE.md) · 🇮🇳 [te](../te/CLAUDE.md) · 🇹🇭 [th](../th/CLAUDE.md) · 🇹🇷 [tr](../tr/CLAUDE.md) · 🇺🇦 [uk-UA](../uk-UA/CLAUDE.md) · 🇵🇰 [ur](../ur/CLAUDE.md) · 🇻🇳 [vi](../vi/CLAUDE.md) · 🇨🇳 [zh-CN](../zh-CN/CLAUDE.md)
---
Denne filen gir veiledning til Claude Code (claude.ai/code) når du arbeider med kode i dette depotet.
## Rask start
```bash
npm install # Installer avhengigheter (genererer automatisk .env fra .env.example)
npm run dev # Utviklingsserver på http://localhost:20128
npm run build # Produksjonsbygg (Next.js 16 standalone)
npm run lint # ESLint (0 feil forventet; advarsler er eksisterende)
npm run typecheck:core # TypeScript-sjekk (bør være ren)
npm run typecheck:noimplicit:core # Streng sjekk (ingen implicit any)
npm run test:coverage # Enhetstester + dekning (75/75/75/70 — utsagn/linjer/funksjoner/grener)
npm run check # lint + test kombinert
npm run check:cycles # Oppdag sirkulære avhengigheter
```
### Kjøring av tester
```bash
# Enkel testfil (Node.js innebygd testkjører — de fleste tester)
node --import tsx/esm --test tests/unit/your-file.test.ts
# Vitest (MCP-server, autoCombo, cache)
npm run test:vitest
# Alle suite
npm run test:all
```
For full testmatrise, se `CONTRIBUTING.md` → "Kjøring av tester". For dyp arkitektur, se `AGENTS.md`.
---
## Prosjektet i et nøtteskall
**OmniRoute** — enhetlig AI proxy/ruter. Ett endepunkt, 160+ LLM-leverandører, automatisk fallback.
| Lag | Sted | Formål |
| --------------- | ----------------------- | ----------------------------------------------------------------------- |
| API-ruter | `src/app/api/v1/` | Next.js App Router — inngangspunkter |
| Håndterere | `open-sse/handlers/` | Behandling av forespørsel (chat, embeddings, osv.) |
| Utøvere | `open-sse/executors/` | Leverandørspesifikk HTTP-dispatch |
| Oversettere | `open-sse/translator/` | Formatkonvertering (OpenAI↔Claude↔Gemini) |
| Transformer | `open-sse/transformer/` | Respons API ↔ Chat Fullføringer |
| Tjenester | `open-sse/services/` | Kombinasjonsruting, hastighetsbegrensninger, caching, osv. |
| Database | `src/lib/db/` | SQLite domene moduler (45+ filer, 55 migrasjoner) |
| Domene/Politikk | `src/domain/` | Politikkmotor, kostnadsregler, fallback-logikk |
| MCP-server | `open-sse/mcp-server/` | 37 verktøy (30 base + 3 minne + 4 ferdigheter), 3 transport, ~13 omfang |
| A2A-server | `src/lib/a2a/` | JSON-RPC 2.0 agentprotokoll |
| Ferdigheter | `src/lib/skills/` | Utvidbar ferdighetsrammeverk |
| Minne | `src/lib/memory/` | Vedvarende samtaleminne |
Monorepo: `src/` (Next.js 16 app), `open-sse/` (streaming engine arbeidsområde), `electron/` (desktop app), `tests/`, `bin/` (CLI inngangspunkt).
---
## Forespørsel Pipeline
```
Klient → /v1/chat/completions (Next.js rute)
→ CORS → Zod validering → auth? → policy sjekk → prompt injeksjonsbeskyttelse
→ handleChatCore() [open-sse/handlers/chatCore.ts]
→ cache sjekk → rate limit → combo routing?
→ resolveComboTargets() → handleSingleModel() per mål
→ translateRequest() → getExecutor() → executor.execute()
→ fetch() upstream → retry w/ backoff
→ respons oversettelse → SSE strøm eller JSON
→ Hvis Responses API: responsesTransformer.ts TransformStream
```
API-ruter følger et konsistent mønster: `Rute → CORS preflight → Zod body validering → Valgfri auth (extractApiKey/isValidApiKey) → API-nøkkel policy håndheving → Handler delegasjon (open-sse)`. Ingen global Next.js middleware — avbrudd er rute-spesifikk.
**Combo routing** (`open-sse/services/combo.ts`): 14 strategier (prioritet, vektet, fyll-først, rund-robin, P2C, tilfeldig, minst-brukt, kostnadsoptimalisert, reset-bevisst, streng-tilfeldig, auto, lkgp, kontekst-optimalisert, kontekst-rele). Hvert mål kaller `handleSingleModel()` som omslutter `handleChatCore()` med per-mål feilhåndtering og kretsbryter sjekker. Se `docs/routing/AUTO-COMBO.md` for 9-faktor Auto-Combo poengsetting og `docs/architecture/RESILIENCE_GUIDE.md` for de 3 motstandsdyktighetslagene.
---
## Motstandsdyktighet Kjøretid Tilstand
OmniRoute har tre relaterte, men distinkte mekanismer for midlertidig feil. Hold deres
omfang adskilt når du feilsøker rutingadferd. Se den
[3-lags motstandsdyktighetsdiagram](./docs/diagrams/exported/resilience-3layers.svg)
(kilde: [docs/diagrams/resilience-3layers.mmd](./docs/diagrams/resilience-3layers.mmd))
for et oversiktskart.
### Leverandør Kretsbryter
**Omfang**: hele leverandøren, f.eks. `glm`, `openai`, `anthropic`.
**Formål**: stoppe sending av trafikk til en leverandør som gjentatte ganger feiler på
upstream/tjenestenivå, slik at en usunn leverandør ikke bremser ned hver forespørsel.
**Implementering**:
- Kjerneklasse: `src/shared/utils/circuitBreaker.ts`
- Chat gate/utførelsesledninger: `src/sse/handlers/chatHelpers.ts`, `src/sse/handlers/chat.ts`
- Kjøretidsstatus API: `src/app/api/monitoring/health/route.ts`
- Delte omslag: `open-sse/services/accountFallback.ts`
- Persistert tilstandstabell: `domain_circuit_breakers`
**Stater**:
- `CLOSED`: normal trafikk er tillatt.
- `OPEN`: leverandøren er midlertidig blokkert; innringere får et provider-krets-åpen svar
eller combo routing hopper til et annet mål.
- `HALF_OPEN`: reset timeout har utløpt; tillat en probe forespørsel. Succes lukker
bryteren, feil åpner den igjen.
**Standarder** (`open-sse/config/constants.ts`):
- OAuth-leverandører: terskel `3`, reset timeout `60s`.
- API-nøkkel leverandører: terskel `5`, reset timeout `30s`.
- Lokale leverandører: terskel `2`, reset timeout `15s`.
Bare leverandør-nivå feilstater bør utløse leverandørbryteren:
```ts
(408, 500, 502, 503, 504);
```
Ikke utløse hele-leverandørbryteren for normale konto/nøkkel/modellfeil som de fleste
`401`, `403`, eller `429` tilfeller. De tilhører vanligvis tilkoblings cooldown eller modell
låsing. En generell API-nøkkel leverandør `403` bør være gjenopprettbar med mindre den er klassifisert
som en terminal leverandør/konto feil.
Bryteren bruker lat recovery, ikke en bakgrunnstimer. Når `OPEN` utløper, leser som
`getStatus()`, `canExecute()`, og `getRetryAfterMs()` oppdaterer tilstanden til
`HALF_OPEN`, slik at dashbord og combo kandidatbyggere ikke fortsetter å ekskludere en
utløpt leverandør for alltid.
### Tilkoblings Cooldown
**Omfang**: én leverandør tilkobling/konto/nøkkel.
**Formål**: midlertidig hoppe over en dårlig nøkkel/konto mens andre tilkoblinger for
den samme leverandøren kan fortsette å betjene forespørselene.
**Implementering**:
- Skriv/oppdater sti: `src/sse/services/auth.ts::markAccountUnavailable()`
- Kontoseleksjon/filtering: `src/sse/services/auth.ts::getProviderCredentials...`
- Cooldown beregning: `open-sse/services/accountFallback.ts::checkFallbackError()`
- Innstillinger: `src/lib/resilience/settings.ts`
Viktige felt på leverandørtilkoblinger:
```ts
rateLimitedUntil;
testStatus: "unavailable";
lastError;
lastErrorType;
errorCode;
backoffLevel;
```
Under kontoseleksjon, blir en tilkobling hoppet over mens:
```ts
new Date(rateLimitedUntil).getTime() > Date.now();
```
Cooldowns er også late: når `rateLimitedUntil` er i fortiden, blir tilkoblingen
berettiget igjen. Ved vellykket bruk, `clearAccountError()` fjerner `testStatus`,
`rateLimitedUntil`, feilkoder, og `backoffLevel`.
Standard tilkoblings cooldown oppførsel:
- OAuth grunn cooldown: `5s`.
- API-nøkkel grunn cooldown: `3s`.
- API-nøkkel `429` bør foretrekke upstream retry hints (`Retry-After`, reset headers, eller
parsebar reset tekst) når tilgjengelig.
- Gjentatte gjenopprettbare feil bruker eksponentiell backoff:
```ts
baseCooldownMs * 2 ** failureIndex;
```
Anti-thundering-herd beskyttelsen forhindrer samtidige feil på samme tilkobling fra
gjentatte ganger å forlenge cooldown eller doble-incrementere `backoffLevel`.
Terminalstater er ikke cooldowns. `banned`, `expired`, og `credits_exhausted` er
ment å forbli utilgjengelige inntil legitimasjon/innstillinger endres eller en operatør tilbakestiller
dem. Ikke overskriv terminalstater med midlertidig cooldown tilstand.
### Modell Låsing
**Omfang**: leverandør + tilkobling + modell.
**Formål**: unngå å deaktivere en hel tilkobling når bare én modell er utilgjengelig eller
kvote-limite for den tilkoblingen.
Eksempler:
- Per-modell kvote leverandører som returnerer `429`.
- Lokale leverandører som returnerer `404` for én manglende modell.
- Leverandør-spesifikke modus/modell tillatelsesfeil som valgte Grok-moduser.
Modell låsing lever i `open-sse/services/accountFallback.ts` og lar den samme
tilkoblingen fortsette å betjene andre modeller.
### Feilsøkingsveiledning
- Hvis alle nøkler for en leverandør blir hoppet over, inspiser både leverandørbryter tilstand og hver
tilkoblings `rateLimitedUntil`/`testStatus`.
- Hvis en leverandør ser ut til å være permanent ekskludert etter resetvinduet, sjekk om koden
leser rå `state` i stedet for å bruke `getStatus()`/`canExecute()`.
- Hvis én leverandørnøkkel feiler, men andre bør fungere, foretrekk tilkoblings cooldown over
leverandørbryteren.
- Hvis bare én modell feiler, foretrekk modell låsing over tilkoblings cooldown.
- Hvis en tilstand skal selv-gjenopprette, bør den ha et fremtidig tidsstempel/reset timeout og en
lesevei som oppdaterer utløpt tilstand. Permanente statuser krever manuelle legitimasjon
eller konfigurasjonsendringer.
## Nøkkelkonvensjoner
### Kode Stil
- **2 mellomrom**, semikolon, doble anførselstegn, 100 tegn bredde, es5 trailing commas (håndhevet av lint-staged via Prettier)
- **Imports**: ekstern → intern (`@/`, `@omniroute/open-sse`) → relativ
- **Navngivning**: filer=camelCase/kebab, komponenter=PascalCase, konstanter=UPPER_SNAKE
- **ESLint**: `no-eval`, `no-implied-eval`, `no-new-func` = feil overalt; `no-explicit-any` = advarsel i `open-sse/` og `tests/`
- **TypeScript**: `strict: false`, mål ES2022, modul esnext, oppløsning bundler. Foretrekk eksplisitte typer.
### Database
- **Alltid** gå gjennom `src/lib/db/` domenemoduler — **aldri** skriv rå SQL i ruter eller håndterere
- **Aldri** legg til logikk i `src/lib/localDb.ts` (re-export lag kun)
- **Aldri** barrel-import fra `localDb.ts` — importer spesifikke `db/` moduler i stedet
- DB singleton: `getDbInstance()` fra `src/lib/db/core.ts` (WAL journaling)
- Migrasjoner: `src/lib/db/migrations/` — versjonerte SQL-filer, idempotente, kjør i transaksjoner
### Feilhåndtering
- try/catch med spesifikke feiltyper, logg med pino kontekst
- Aldri sluk feil i SSE-strømmer — bruk abortsignaler for opprydding
- Returner riktige HTTP-statuskoder (4xx/5xx)
### Sikkerhet
- **Aldri** bruk `eval()`, `new Function()`, eller implisert eval
- Valider alle innganger med Zod-skjemaer
- Krypter legitimasjon i ro (AES-256-GCM)
- Oppstrøms header denylist: `src/shared/constants/upstreamHeaders.ts` — hold sanitere, Zod-skjemaer, og enhetstester i samsvar når du redigerer
- **Offentlige oppstrøms legitimasjoner** (Gemini/Antigravity/Windsurf-stil OAuth client_id/secret + Firebase Web-nøkler hentet fra offentlige CLI-er): **MÅ** være innebygd via `resolvePublicCred()` fra `open-sse/utils/publicCreds.ts`**aldri** som strengliteraler. Se `docs/security/PUBLIC_CREDS.md` for den obligatoriske malen.
- **Feilrespons** (HTTP / SSE / executor / MCP-håndterer): **MÅ** rutes gjennom `buildErrorBody()` eller `sanitizeErrorMessage()` fra `open-sse/utils/error.ts`**aldri** sett rå `err.stack` eller `err.message` i en responsbody. Se `docs/security/ERROR_SANITIZATION.md`.
- **Shell-kommandoer bygget fra variabler**: når du kaller `exec()`/`spawn()` med et skript som trenger kjøretidsverdier, send dem via `env`-alternativet (shell-escaped automatisk) — **aldri** string-interpoler ubetrodde/eksterne stier inn i skriptkroppen. Referanse: `src/mitm/cert/install.ts::updateNssDatabases`.
- **Sikre-bygge-biblioteker** ([tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults)): foretrekk Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink over tilpassede implementeringer når du legger til nye sikkerhetsfølsomme flater.
---
## Vanlige Modifikasjons Scenarier
### Legge til en Ny Leverandør
1. Registrer i `src/shared/constants/providers.ts` (Zod-validert ved last)
2. Legg til executor i `open-sse/executors/` hvis tilpasset logikk er nødvendig (utvid `BaseExecutor`)
3. Legg til oversetter i `open-sse/translator/` hvis ikke-OpenAI format
4. Legg til OAuth-konfigurasjon i `src/lib/oauth/constants/oauth.ts` hvis OAuth-basert — hvis den oppstrøms CLI-en leverer en offentlig client_id/secret, innebygg via `resolvePublicCred()` (se `docs/security/PUBLIC_CREDS.md`), **aldri** som en literal
5. Registrer modeller i `open-sse/config/providerRegistry.ts`
6. Skriv tester i `tests/unit/` (inkluder publicCreds formassertion hvis du la til en ny innebygd standard)
### Legge til en Ny API Rute
1. Opprett katalog under `src/app/api/v1/your-route/`
2. Opprett `route.ts` med `GET`/`POST` håndterere
3. Følg mønster: CORS → Zod body validering → valgfri autentisering → håndterer delegasjon
4. Håndterer går i `open-sse/handlers/` (importer derfra, ikke inline)
5. Feilrespons bruker `buildErrorBody()` / `errorResponse()` fra `open-sse/utils/error.ts` (auto-sanitized — aldri sett `err.stack` eller `err.message` rått i kroppen). Se `docs/security/ERROR_SANITIZATION.md`.
6. Legg til tester — inkludert minst en påstand om at feilresponsene ikke lekker stakkspor (`!body.error.message.includes("at /")`)
### Legge til en Ny DB Modul
1. Opprett `src/lib/db/yourModule.ts` — importer `getDbInstance` fra `./core.ts`
2. Eksporter CRUD-funksjoner for din domenetabell(er)
3. Legg til migrasjon i `src/lib/db/migrations/` hvis nye tabeller er nødvendige
4. Re-export fra `src/lib/localDb.ts` (legg til i re-export listen kun)
5. Skriv tester
### Legge til et Nytt MCP Verktøy
1. Legg til verktøydefinisjon i `open-sse/mcp-server/tools/` med Zod inngangsskjema + asynkron håndterer
2. Registrer i verktøysettet (koblet av `createMcpServer()`)
3. Tildel til passende omfang
4. Skriv tester (verktøyinnkalling logget til `mcp_audit` tabell)
### Legge til en Ny A2A Ferdighet
1. Opprett ferdighet i `src/lib/a2a/skills/` (5 eksisterer allerede: smart-routing, quota-management, provider-discovery, cost-analysis, health-report)
2. Ferdigheten mottar oppgavekontekst (meldinger, metadata) → returnerer strukturert resultat
3. Registrer i `A2A_SKILL_HANDLERS` i `src/lib/a2a/taskExecution.ts`
4. Eksponer i `src/app/.well-known/agent.json/route.ts` (Agent Card)
5. Skriv tester i `tests/unit/`
6. Dokumenter i `docs/frameworks/A2A-SERVER.md` ferdighetstabell
### Legge til en Ny Cloud Agent
1. Opprett agentklasse i `src/lib/cloudAgent/agents/` som utvider `CloudAgentBase` (3 eksisterer allerede: codex-cloud, devin, jules)
2. Implementer `createTask`, `getStatus`, `approvePlan`, `sendMessage`, `listSources`
3. Registrer i `src/lib/cloudAgent/registry.ts`
4. Legg til OAuth/legitimasjonshåndtering hvis nødvendig (`src/lib/oauth/providers/`)
5. Tester + dokumenter i `docs/frameworks/CLOUD_AGENT.md`
### Legge til en Ny Guardrail / Eval / Ferdighet / Webhook-hendelse
- Guardrail: `src/lib/guardrails/` → docs: `docs/security/GUARDRAILS.md`
- Eval suite: `src/lib/evals/` → docs: `docs/frameworks/EVALS.md`
- Ferdighet (sandbox): `src/lib/skills/` → docs: `docs/frameworks/SKILLS.md`
- Webhook-hendelse: `src/lib/webhookDispatcher.ts` → docs: `docs/frameworks/WEBHOOKS.md`
## Referansedokumentasjon
For enhver ikke-triviell endring, les den tilhørende dybdeanalysen først:
| Område | Dokument |
| ------------------------------------------------ | ----------------------------------------------------------------- |
| Repo-navigasjon | `docs/architecture/REPOSITORY_MAP.md` |
| Arkitektur | `docs/architecture/ARCHITECTURE.md` |
| Ingeniørreferanse | `docs/architecture/CODEBASE_DOCUMENTATION.md` |
| Auto-Combo (9-faktor poengsum, 14 strategier) | `docs/routing/AUTO-COMBO.md` |
| Motstandsdyktighet (3 mekanismer) | `docs/architecture/RESILIENCE_GUIDE.md` |
| Resonnement replay | `docs/routing/REASONING_REPLAY.md` |
| Ferdighetsramme | `docs/frameworks/SKILLS.md` |
| Minne system (FTS5 + Qdrant) | `docs/frameworks/MEMORY.md` |
| Skyagenter | `docs/frameworks/CLOUD_AGENT.md` |
| Beskyttelsesrammer (PII / injeksjon / visjon) | `docs/security/GUARDRAILS.md` |
| Offentlige upstream-legitimasjoner (Gemini/osv.) | `docs/security/PUBLIC_CREDS.md` |
| Rensing av feilmeldinger | `docs/security/ERROR_SANITIZATION.md` |
| Evalueringer | `docs/frameworks/EVALS.md` |
| Overholdelse / revisjon | `docs/security/COMPLIANCE.md` |
| Webhooks | `docs/frameworks/WEBHOOKS.md` |
| Autorisasjonspipeline | `docs/architecture/AUTHZ_GUIDE.md` |
| Stealth (TLS / fingeravtrykk) | `docs/security/STEALTH_GUIDE.md` |
| Agentprotokoller (A2A / ACP / Sky) | `docs/frameworks/AGENT_PROTOCOLS_GUIDE.md` |
| MCP-server | `docs/frameworks/MCP-SERVER.md` |
| A2A-server | `docs/frameworks/A2A-SERVER.md` |
| API-referanse + OpenAPI | `docs/reference/API_REFERENCE.md` + `docs/reference/openapi.yaml` |
| Leverandørkatalog (auto-generert) | `docs/reference/PROVIDER_REFERENCE.md` |
| Utgivelsesflyt | `docs/ops/RELEASE_CHECKLIST.md` |
---
## Testing
| Hva | Kommando |
| ----------------------- | ----------------------------------------------------------------------- |
| Enhetstester | `npm run test:unit` |
| Enkel fil | `node --import tsx/esm --test tests/unit/file.test.ts` |
| Vitest (MCP, autoCombo) | `npm run test:vitest` |
| E2E (Playwright) | `npm run test:e2e` |
| Protokoll E2E (MCP+A2A) | `npm run test:protocols:e2e` |
| Økosystem | `npm run test:ecosystem` |
| Dekningsgrense | `npm run test:coverage` (75/75/75/70 — utsagn/linjer/funksjoner/grener) |
| Dekningsrapport | `npm run coverage:report` |
**PR-regel**: Hvis du endrer produksjonskode i `src/`, `open-sse/`, `electron/`, eller `bin/`, må du inkludere eller oppdatere tester i samme PR.
**Testlagpreferanse**: enhet først → integrasjon (multi-modul eller DB-tilstand) → e2e (UI/arbeidsflyt kun). Kode feilreproduksjoner som automatiserte tester før eller sammen med fiksen.
**Copilot dekning policy**: Når en PR endrer produksjonskode og dekningen er under 75% (utsagn/linjer/funksjoner) eller 70% (grener), rapporter ikke bare — legg til eller oppdater tester, kjør dekningstesten på nytt, og be om bekreftelse. Inkluder kjørte kommandoer, endrede testfiler, og sluttresultatet for dekning i PR-rapporten.
---
## Git Workflow
```bash
# Aldri commit direkte til main
git checkout -b feat/your-feature
git commit -m "feat: beskriv endringen din"
git push -u origin feat/your-feature
```
**Grenprefikser**: `feat/`, `fix/`, `refactor/`, `docs/`, `test/`, `chore/`
**Commit-format** (Conventional Commits): `feat(db): legg til kretsbryter` — omfang: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`
**Husky hooks**:
- **pre-commit**: lint-staged + `check-docs-sync` + `check:any-budget:t11`
- **pre-push**: `npm run test:unit`
---
## Miljø
- **Kjøretid**: Node.js ≥20.20.2 <21 || ≥22.22.2 <23 || ≥24 <25, ES-moduler
- **TypeScript**: 5.9+, mål ES2022, modul esnext, oppløsning bundler
- **Sti-aliaser**: `@/*``src/`, `@omniroute/open-sse``open-sse/`, `@omniroute/open-sse/*``open-sse/*`
- **Standardport**: 20128 (API + dashboard på samme port)
- **Datakatalog**: `DATA_DIR` miljøvariabel, standard til `~/.omniroute/`
- **Nøkkel miljøvariabler**: `PORT`, `JWT_SECRET`, `API_KEY_SECRET`, `INITIAL_PASSWORD`, `REQUIRE_API_KEY`, `APP_LOG_LEVEL`
- Oppsett: `cp .env.example .env` og deretter generer `JWT_SECRET` (`openssl rand -base64 48`) og `API_KEY_SECRET` (`openssl rand -hex 32`)
---
## Harde regler
1. Aldri commit hemmeligheter eller legitimasjon
2. Aldri legg til logikk i `localDb.ts`
3. Aldri bruk `eval()` / `new Function()` / implisitt eval
4. Aldri commit direkte til `main`
5. Aldri skriv rå SQL i ruter — bruk `src/lib/db/` moduler
6. Aldri stilltiende sluk feil i SSE-strømmer
7. Alltid valider innganger med Zod-skjemaer
8. Alltid inkludere tester når du endrer produksjonskode
9. Dekningen må forbli ≥75% (utsagn, linjer, funksjoner) / ≥70% (grener). Nåværende målt: ~82%.
10. Aldri omgå Husky hooks (`--no-verify`, `--no-gpg-sign`) uten eksplisitt godkjenning fra operatøren.
11. Aldri innebygde offentlige upstream OAuth client_id/hemmelighet eller Firebase Web-nøkler som strenglitteraler — gå alltid gjennom `resolvePublicCred()` (`open-sse/utils/publicCreds.ts`). Se `docs/security/PUBLIC_CREDS.md`.
12. Aldri returner rå `err.stack` / `err.message` i HTTP / SSE / executor-responser — alltid rute gjennom `buildErrorBody()` eller `sanitizeErrorMessage()` (`open-sse/utils/error.ts`). Se `docs/security/ERROR_SANITIZATION.md`.
13. Aldri strenge-interpolere eksterne stier eller kjøretidsverdier inn i shell-skript som sendes til `exec()`/`spawn()` — send via `env`-alternativet i stedet. Referanse: `src/mitm/cert/install.ts::updateNssDatabases`.
14. Aldri avvis en CodeQL / Secret-Scanning varsling uten (a) først å sjekke mønsterdokumentene ovenfor for å se om hjelpen gjelder, og (b) registrere den tekniske begrunnelsen i avvisningskommentaren. Presedens: `js/stack-trace-exposure` hevet på kallsteder som allerede ruter gjennom `sanitizeErrorMessage()` er en kjent CodeQL-begrensning (tilpassede sanitizere ikke gjenkjent) — avvis som `false positive` med referanse til `docs/security/ERROR_SANITIZATION.md`.
15. Aldri eksponer ruter som starter barneprosesser (`/api/mcp/`, `/api/cli-tools/runtime/`) uten `isLocalOnlyPath()` klassifisering i `src/server/authz/routeGuard.ts`. Loopback-håndheving skjer ubetinget før noen autentisering sjekk — lekket JWT via tunnel kan ikke utløse prosessstart. Se `docs/security/ROUTE_GUARD_TIERS.md`.
16. Aldri inkluder `Co-Authored-By`-trailere som krediterer en AI-assistent, LLM eller automatiseringskonto (f.eks. navn som inneholder "Claude", "GPT", "Copilot", "Bot"; e-poster på `anthropic.com` / `openai.com` / bot-eide `noreply.github.com`-adresser). Slike trailere ruter commit-attribusjon til bot-kontoen på GitHub, og skjuler den virkelige forfatteren (`diegosouzapw`) i PR-historikken. Menneskelige bidragsytere — inkludert upstream PR-forfattere og issue-rapportører som blir portet til OmniRoute — KAN og BØR krediteres med standard `Co-authored-by: Name <email>`-trailere; upstream-port arbeidsflyter (`/port-upstream-features`, `/port-upstream-issues`) avhenger av dette.