# Release Checklist (Norsk) 🌐 **Languages:** 🇺🇸 [English](../../../../ops/RELEASE_CHECKLIST.md) · 🇪🇹 [am](../../../am/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../../ar/docs/ops/RELEASE_CHECKLIST.md) · 🇦🇿 [az](../../../az/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../../bg/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇩 [bn](../../../bn/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇦 [bs](../../../bs/docs/ops/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../../cs/docs/ops/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../../da/docs/ops/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../../de/docs/ops/RELEASE_CHECKLIST.md) · 🇬🇷 [el](../../../el/docs/ops/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../../es/docs/ops/RELEASE_CHECKLIST.md) · 🇪🇪 [et](../../../et/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇷 [fa](../../../fa/docs/ops/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../../fi/docs/ops/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../../fr/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇪 [ga](../../../ga/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [gu](../../../gu/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇬 [ha](../../../ha/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../../he/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [hi](../../../hi/docs/ops/RELEASE_CHECKLIST.md) · 🇭🇷 [hr](../../../hr/docs/ops/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../../hu/docs/ops/RELEASE_CHECKLIST.md) · 🇦🇲 [hy](../../../hy/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../../id/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇬 [ig](../../../ig/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../../it/docs/ops/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../../ja/docs/ops/RELEASE_CHECKLIST.md) · 🇬🇪 [ka](../../../ka/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇭 [km](../../../km/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [kn](../../../kn/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../../ko/docs/ops/RELEASE_CHECKLIST.md) · 🇱🇹 [lt](../../../lt/docs/ops/RELEASE_CHECKLIST.md) · 🇱🇻 [lv](../../../lv/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [ml](../../../ml/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [mr](../../../mr/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../../ms/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇹 [mt](../../../mt/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇲 [my](../../../my/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇵 [ne](../../../ne/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../../nl/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [or](../../../or/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [pa](../../../pa/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../../phi/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../../pl/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../../pt/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../../ro/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../../ru/docs/ops/RELEASE_CHECKLIST.md) · 🇱🇰 [si](../../../si/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../../sk/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇮 [sl](../../../sl/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇸 [sr](../../../sr/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../../sv/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇪 [sw](../../../sw/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [ta](../../../ta/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [te](../../../te/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../../th/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇷 [tr](../../../tr/docs/ops/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇰 [ur](../../../ur/docs/ops/RELEASE_CHECKLIST.md) · 🇺🇿 [uz](../../../uz/docs/ops/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../../vi/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇬 [yo](../../../yo/docs/ops/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/ops/RELEASE_CHECKLIST.md) --- > **Sist oppdatert:** 2026-08-28 — v3.8.51 > Effektivisert utgivelsesflyt som bruker Claude Code-ferdigheter til automatisering. > > **Hold køen/grenen grønn mellom utgivelser:** se [RELEASE_GREEN.md](./RELEASE_GREEN.md) > (`/green-prs`-familien + `npm run check:release-green` + `/babysit` + nattlig kjøring). Å kjøre > dette regelmessig — og spesielt **før** denne sjekklisten — gjør at utgivelses-PR-en starter grønn. ## Kort fortalt ```bash # 1. Oppdater versjonen + generer CHANGELOG (ferdighet) /version-bump-cc patch # eller minor/major # 2. Kjør kvalitetskontrollen lokalt npm run check # linting + tester npm run test:coverage # full dekningskontroll (60/60/60/60) # 3. Bygg og utfør en enkel funksjonstest npm run build npm run test:e2e # valgfritt, men anbefalt # 4. Generer utgivelsen (ferdighet) /generate-release-cc # 5. Distribuer (ferdighet) /deploy-vps-both-cc # eller akamai-cc / local-cc # 6. Samle inn utgivelsesbevis (ferdighet) /capture-release-evidences-cc ``` ## npm Trusted Publishing (standard siden v3.8.51) — klargjort ved forespørsel, direkte som reserveløsning `npm-publish.yml` publiserer som standard via **npm Trusted Publishing (OIDC)**: `stage-npm`-jobben (GitHub-driftet) utveksler GitHubs id-token mot en kortvarig npm- legitimasjon for den kjøringen — ingen langvarig npm-token i repositoriets hemmeligheter, ingen 2FA-forespørsel, proveniens vedlagt. Dette er omgåelsen npm nå godkjenner etter hvert som tokener som hopper over 2FA, fases ut; den gjenoppretter den helautomatiske flyten prosjektet hadde frem til v3.8.48, samtidig som WS1.3-garantien opprettholdes (et lekket token kan ikke publisere alene — det finnes ikke noe token). **Engangsoppsett (eier):** npmjs.com → pakken `omniroute` → Settings → _Trusted Publisher_ → GitHub: eier `diegosouzapw`, repo `OmniRoute`, arbeidsflyt `npm-publish.yml` (miljø: ingen). Frem til dette finnes, mislykkes det automatiske trinnet med `ENEEDAUTH`: start arbeidsflyten på nytt med `publish_mode=staged` (nedenfor) eller `direct`. ### Trinnvis publisering (ved forespørsel — `publish_mode=staged`) Arbeidsflyten npm-publish publiserer ikke lenger direkte: den starter den pakkede tarball-filen (`check:pack-boot`) og kjører deretter `npm stage publish` — de nøyaktige bytene parkeres i registeret og er **ikke installerbare** før eieren godkjenner dem. Den menneskelige 2FA-kontrollen er flyttet til ETTER verifiseringen, ikke før den. **Eierens flyt etter at arbeidsflyten blir grønn:** 1. `npm stage list omniroute` — finn trinn-ID-en (vises også i arbeidsflytsammendraget). 2. Verifiser de klargjorte bytene (anbefalt): `npm stage download `, installer deretter den nedlastede tarball-filen i et midlertidig prefiks og start den (`npm run check:pack-boot` automatiserer den samme pakk→installer→start-vurderingen i CI). 3. `npm stage approve ` — 2FA-forespørselen ER publiseringen. `npm stage reject ` forkaster den. 4. Sikkerhetsnett etter publisering: verifikatoren etter publisering (WS1.4 i planen for v3.8.49) installerer den publiserte versjonen fra det offentlige registeret i en ren container og starter den. **Reserveløsning for nødstilfeller:** `workflow_dispatch` med `publish_mode=direct` gjenoppretter den eldre umiddelbare `npm publish`-flyten (brukes bare hvis selve klargjøringen ikke fungerer; dokumenter hvorfor). **Engangsherding (eier, npmjs.com):** konfigurer Trusted Publisher for `omniroute` i kun-klargjøringsmodus, slik at et lekket langvarig token ikke kan kjøre `npm publish` direkte noe sted fra — CI kan bare klargjøre; bare eierens 2FA kan utgi. **Prosedyre for ødelagte artefakter (uendret):** `npm deprecate omniroute@ " — use "` som standardreaksjon (minutter, reversibelt); `npm unpublish` kun innenfor vinduet på 72 timer/ingen avhengige og aldri som første tiltak. Docker: aldri overskriv en versjonstagg — tilbakerulling innebærer å peke `latest` til den siste fungerende digesten. **Docker Hub `latest` (påkrevd ved hver stabile SemVer-publisering):** `docker-publish`-arbeidsflyten må tagge **både** `X.Y.Z` og, når `should-promote-latest.sh` bekrefter at dette er den høyeste stabile SemVer-versjonen, `:latest` med **samme digest**. Etter jobben: Hub-digesten for `latest` er lik den nye SemVer-digesten, og `last_updated` er oppdatert. Ikke la `:latest` peke på en eldre byggversjon mens utgivelsesnotatene omtaler rettelser som bare finnes i git. Compose- hurtigstarter bruker `:latest`; GitOps bør fortsatt feste til `X.Y.Z`. Se [Docker-utgivelseskanaler](../guides/DOCKER_GUIDE.md#release-channels) og #10317. ## Hurtigspor for kritiske feilrettinger (etikett `hotfix`) En PR merket med `hotfix` hopper over den omfattende CI-matrisen (E2E med 9 deler, coverage ratchet, quality-gate, quality-extended) og beholder de raske kontrollene med høy signalverdi: bygging, enhetstestdeler, integrasjon, vitest, lint/typecheck, docs-sync, `check:pack-artifact` og oppstartstesten for tarball (`check:pack-boot`). Mål: grønt resultat på ≤15 min i stedet for ~33 min. **Kriterier for bruk — alle fire må være oppfylt (modellert etter nødsporene til Chromium/VS Code/Node):** 1. **Alvorlighetsgrad**: produksjonen er ute av drift — en publisert artefakt krasjer ved oppstart / en sikkerhetsretting / alle brukere av utgivelsen er berørt. «Viktig» er ikke det samme som «ute av drift». 2. **Myndighet**: bare eieren av repositoriet bruker etiketten `hotfix`. Etiketten ER godkjenningen — den skal aldri brukes på eget initiativ i en kampanje-PR. 3. **Dokumentasjon**: PR-beskrivelsen lenker til den forrige fullstendig grønne, omfattende kjøringen (testpakken som de hoppede jobbene ellers ville validert på nytt), samt rettingens egen test som først feilet og deretter besto. 4. **Omfang**: kun cherry-pick — den minimale rettingen, ingen refaktoreringer, ingen medfølgende endringer. Deknings-/ratchet-området som hoppes over, valideres på nytt av den neste fullstendige kjøringen på utgivelsesgrenen (kontinuerlig grønn utgivelse) — sporet hopper over VENTING, aldri validering. Endringer som kun gjelder tester (alle filer under `tests/`, ingen under `tests/e2e/`) hopper over E2E- matrisen automatisk, uten noen etikett. ## Detaljert sjekkliste ### Før utgivelse - [ ] Alle PR-er som er rettet mot denne utgivelsen, er slått sammen med `release/vX.Y.0` - [ ] Alle åpne Linear-/issue-elementer for denne versjonen er lukket eller flyttet til neste milepæl - [ ] CI er grønn på grenen `release/vX.Y.0` - [ ] Ingen `TODO(release)`-markører i koden: `grep -r "TODO(release)" src/ open-sse/` - [ ] Docker-basisimaget er oppdatert (for øyeblikket `node:24.15.0-trixie-slim`) ### Versjon og endringslogg - [ ] Kjør `/version-bump-cc ` (Claude Code-ferdighet) - Oppdaterer versjonene i `package.json`, `electron/package.json` - Regenererer `CHANGELOG.md` fra git-commits siden forrige tagg - Oppdaterer merkene i README.md - [ ] Gjennomgå CHANGELOG.md manuelt, og rydd opp i commit-meldinger ved behov - [ ] Kontroller at den nyeste semver-seksjonen i `CHANGELOG.md` samsvarer med versjonen i `package.json` - [ ] Behold `## [Unreleased]` som den første seksjonen i endringsloggen for kommende arbeid - [ ] Oppdater `docs/openapi.yaml` → `info.version` må samsvare med versjonen i `package.json` ### Kodekvalitet - [ ] `npm run lint` — 0 feil (advarsler eksisterte fra før) - [ ] `npm run typecheck:core` — uten feil - [ ] `npm run typecheck:noimplicit:core` — uten feil (streng) - [ ] `npm run check:cycles:ratchet` — innenfor det låste `metrics.cycles`-taket (`check:cycles` alene avsluttes med 1 ved enhver syklus, #15281) - [ ] `npm run check:any-budget:t11` — innenfor budsjettet - [ ] `npm run check:route-validation:t06` — uten feil - [ ] `npm run check:node-runtime` — minimumskravet for støttet kjøretidsmiljø er oppfylt (`>=22.22.2 <23`, `>=24.0.0 <27`, i henhold til `SUPPORTED_NODE_RANGE` i `src/shared/utils/nodeRuntimeSupport.ts`; samstemt med `engines` i `package.json`) ### Testing - [ ] `npm run test:unit` — bestått - [ ] `npm run test:vitest` — bestått (MCP-server, autoCombo, hurtigbuffer) - [ ] `npm run test:coverage` — kravet på 60/60/60/60 er oppfylt (setninger/linjer/funksjoner/grener) - [ ] `npm run test:integration` — bestått (hvis endringene berører DB/behandlere) - [ ] `npm run test:combo:matrix` — bestått (matrise for combo-strategier: beviser deterministisk valgene til alle de 19 offentlige rutingsstrategiene; kjøres ved endringer i combo-ruting, strategioppløsning eller reservelogikk) - [ ] `RUN_COMBO_LIVE=1 npm run test:combo:live` — **valgfri/manuell** (betinget røyktest mot reelle oppstrømstjenester; henter et skrivebeskyttet DB-øyeblikksbilde fra VPS-en `root@192.168.0.15`; bruker reelle leverandører og koster kreditter; kjøres aldri i CI; hoppes over uten feil når betingelsen ikke er aktivert) - [ ] `npm run test:combo:live:vps` — **valgfri/manuell** (fase 3-røyktest på aktiv VPS: 7 HTTP-scenarioer mot den aktive `.15`-serveren via vanlig Node ESM; krever `ssh root@192.168.0.15`; oppretter/sletter bare `__live_test__*`-comboer; bruker reelle leverandører; kjøres aldri i CI) - [ ] `npm run test:e2e` — bestått (UI-endringer) - [ ] `npm run test:protocols:e2e` — bestått (MCP-/A2A-endringer) - [ ] `npm run test:ecosystem` — bestått ### Hooks (validert av Husky) Husky-hooks ligger i `.husky/` og kjøres automatisk ved git-operasjoner. - **pre-commit:** `npx lint-staged + node scripts/check/check-docs-sync.mjs + npm run check:any-budget:t11` - **pre-push:** raske, deterministiske kontrollporter — `npm run check:any-budget:t11 && npm run check:tracked-artifacts` (aktivert 2026-06-13). Utelater bevisst `test:unit` (treg; dekkes av CI-jobben `test-unit`). - Kjør `npm run test:unit` manuelt før utgivelsesgrener pushes. Hvis en hook feiler: rett det underliggende problemet, ikke omgå den med `--no-verify`. ### Konvensjonelle commits Alle commits som skal inngå i utgivelsen, må følge formatet `type(scope): subject`. **Gyldige typer:** `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `style`, `ci` **Gyldige scopes:** `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`, `cloud-agent`, `guardrails`, `compression`, `auto-combo`, `resilience`, `providers`, `executors`, `translator`, `domain`, `authz` Brytende endringer: legg til bunnteksten `BREAKING CHANGE:` eller `!` etter scopet (f.eks. `feat(api)!: drop /v0`). ### Dokumentasjon - [ ] `npm run check:docs-sync` består (kjøres automatisk av pre-commit) - [ ] `npm run check:docs-all` består (samlekontroll: docs-sync + docs-counts + env-doc-sync + deprecated-versions + doc-links) - [ ] `npm run check:env-doc-sync` avsluttes med 0 — kontrakten for miljøvariabler mellom kode ↔ `.env.example` ↔ `docs/reference/ENVIRONMENT.md` er intakt - [ ] `npm run check:doc-links` avsluttes med 0 — ingen brutte interne markdown-referanser etter omstrukturering - [ ] `docs/architecture/ARCHITECTURE.md` er gjennomgått for avvik i lagring/kjøretidsmiljø - [ ] `docs/guides/TROUBLESHOOTING.md` er gjennomgått for avvik i miljøvariabler og drift - [ ] Hvis `.env.example` er endret: `docs/reference/ENVIRONMENT.md` er oppdatert - [ ] Hvis en ny funksjon har et brukergrensesnitt: `docs/guides/USER_GUIDE.md` omtaler den - [ ] Hvis en ny funksjon har et API: `docs/reference/API_REFERENCE.md` + `docs/openapi.yaml` er oppdatert - [ ] Hvis en ny funksjon er en modul: dedikert `docs/.md` finnes - [ ] Ved brytende endring: `docs/guides/TROUBLESHOOTING.md` har et migreringsnotat ### i18n - [ ] `npm run i18n:check` avsluttes med 0 — oversettelsestilstanden (`.i18n-state.json`) er synkronisert med kildedokumentene (ingen avvikende kilder i streng modus; veiledende advarsler er akseptable for dokumentasjonsendringer i siste liten, men resultatet bør være 0 før tagging) - [ ] `npm run i18n:check-ui-coverage` avsluttes med 0 — alle UI-lokaler ligger på eller over minimumsgrensen på 80 % dekning - [ ] `npm run i18n:sync-ui:dry` rapporterer 0 manglende nøkler på tvers av alle de 66 mållokalene (alle lokaler unntatt kilden `en`) - [ ] Hvis engelske kildedokumenter er endret, kjør `npm run i18n:run` (krever `OMNIROUTE_TRANSLATION_API_KEY` i `.env`) før tagging - [ ] Oversettelsesbidrag kan utsettes til neste utgivelse hvis de er mindre omfattende (registrer i CHANGELOG) ### Databasemigreringer - [ ] Hvis `src/lib/db/migrations/` har nye filer: - [ ] Hver migrering er idempotent (`CREATE TABLE IF NOT EXISTS` osv.) - [ ] Migreringer er pakket inn i transaksjoner - [ ] Riktig nummerert (ingen hull i sekvensen) - [ ] Test på en ny installasjon: slett `~/.omniroute/omniroute.db` og kjør `npm run dev` - [ ] Test på en eksisterende installasjon: sikkerhetskopier DB-en, kjør migreringen, verifiser skjemaet - [ ] WAL-filer (`-wal`, `-shm`) håndteres riktig hvis migreringen skriver tabeller på nytt ### Leverandørkatalog (Zod-validert) - [ ] `src/shared/constants/providers.ts` har et Zod-skjema som er gyldig ved innlasting - [ ] Alle leverandører har obligatoriske felt (`id`, `label`, `kind` osv.) - [ ] `freeNote` er angitt for nye gratisleverandører - [ ] OAuth-leverandører har `oauthConfig` registrert i `src/lib/oauth/constants/oauth.ts` - [ ] Hvis en ny leverandør er lagt til: tilsvarende eksekutor i `open-sse/executors/` - [ ] Hvis formatet ikke er OpenAI: oversetter i `open-sse/translator/` - [ ] Modeller er registrert i `open-sse/config/providerRegistry.ts` - [ ] Enhetstester i `tests/unit/` dekker klassifisering og ruting av leverandører ### Skrivebord (Electron) Hvis `electron/` er endret: - [ ] `npm run electron:smoke:packaged` består - [ ] Bygg er testet for minst én av `:win`, `:mac`, `:linux` - [ ] Sertifikater for kodesignering er ikke utløpt (hvis signering brukes) - [ ] Versjonen i `electron/package.json` samsvarer med rotens `package.json` - [ ] Pekeren for kanalen for automatiske oppdateringer er oppdatert ved utgivelse til `stable` ### Byggoppsett Repoet bruker tre separate utdatakataloger — bland dem aldri: | Katalog | Formål | Versjonssporet? | | --------- | ------------------------------------------------------------------ | ---------------- | | `src/` | Applikasjonskilde (TypeScript / TSX) | Ja | | `.build/` | Mellomresultater fra bygging — utdata fra `next build` (`distDir`) | Nei (gitignored) | | `dist/` | Distribuerbar npm-pakke — satt sammen av `assembleStandalone` | Nei (gitignored) | > **Operatørmerknad:** katalogen for det eksterne VPS-avbildet forblir `/usr/lib/node_modules/omniroute/app/`. > Bare byggutdataene **i repoet** ble flyttet (`app/` → `dist/`). Distribusjonsverktøyene bruker rsync til å > overføre innholdet i `dist/` til den eksterne `app/`-katalogen — ingen endringer av VPS-baner er nødvendige. **Flyt med ett enkelt bygg:** ``` npm run build:release └─ rm -rf .build dist (opprydding) └─ next build → .build/next/ (mellomresultater) └─ assembleStandalone (kopierer standalone + static + public + natives → dist/) └─ skriver dist/BUILD_SHA (HEAD-kontrollverdi) ``` IKKE kjør `npm run build` etterfulgt av en separat `npm run build:cli` for distribusjon — bruk `npm run build:release`, som utfører en ren ombygging og oppretter kontrollverdien i én kommando. ### Validering av artefakter - [ ] `npm run build:release` fullføres, og `dist/BUILD_SHA` == `git rev-parse --short HEAD` - [ ] `npm run check:pack-artifact` er ren — ingen `app.__qa_backup`, `scripts/scratch`, `package-lock.json` eller andre lokale rester - [ ] `dist/server.js` finnes etter bygging - [ ] Valgfri lokal røyktest av pakket kjøretidsmiljø: `npm run dev:candidate -- validate` etter `npm run dev:candidate -- build` starter den pakkede tarball-filen med en isolert `DATA_DIR` og kontrollerer `/api/health` + `/v1/models` (se [anbefalt arbeidsflyt for bidrag](CONTRIBUTION_GOLDEN_PATH.md#local-candidate-loop)) ### Merking og utgivelse - [ ] Kjør `/generate-release-cc` (Claude Code-verktøy): - Oppretter taggen `vX.Y.Z` - Pusher tagg og gren - Oppretter en GitHub-utgivelse med endringsloggen som beskrivelse - Legger ved Electron-installasjonsprogrammer (hvis de er bygget) - [ ] Eller gjør det manuelt: ```bash git tag -a vX.Y.Z -m "Release vX.Y.Z" git push origin vX.Y.Z gh release create vX.Y.Z --notes-from-tag ``` ### Distribusjon Distribusjonsverktøyene bruker den lette rsync-flyten — ingen `npm pack`, ingen `npm i -g`: - [ ] Bruk distribusjonsverktøyet som samsvarer med målet: - `/deploy-vps-local-cc` — lokal VPS (192.168.0.15) - `/deploy-vps-akamai-cc` — Akamai-VPS (69.164.221.35) - `/deploy-vps-both-cc` — begge - [ ] Før distribusjon må du bekrefte at `dist/BUILD_SHA` == `git rev-parse --short HEAD` - [ ] Bygget må kjøres der `node_modules` er reell (hovedutsjekkingen eller et worktree der `npm ci` er kjørt — IKKE et worktree med symbolske lenker) - [ ] Røyktest den distribuerte instansen: - Åpne `/dashboard/health` → kontroller at versjonsstrengen samsvarer med utgivelsen - Kjør en `/v1/chat/completions`-forespørsel mot en kjent leverandør - Bekreft at `/api/monitoring/health` returnerer effektbrytere med statusen `CLOSED` - Bekreft at MCP-transporter svarer (`/mcp` HTTP, `/mcp-sse` SSE) ### Etter utgivelsen - [ ] Kjør `/capture-release-evidences-cc` (Claude Code-verktøy) - Tar WebP-skjermbilder/opptak av nye funksjoner - Legger dem ved utgivelsesmerknadene/blogginnlegget - [ ] Oppdater GitHub Discussions / Discord med kunngjøringen om utgivelsen - [ ] Opprett en milepæl for neste versjon - [ ] Hvis kritisk: fest diskusjonen eller publiser i `news.json` for et banner i appen ### Offentlig lanseringsport for Radar Radar-kunngjøringen er med hensikt lagt inn med `active: false`. Aktivering er en separat endring etter at det foreligger dokumentasjon for hvert punkt nedenfor: - [ ] Alle stablede Radar-PR-er er slått sammen, og CI for utgivelsestoppen er grønn - [ ] Distribuer og røyktest OSS Radar-rutene mens `RADAR_ENABLED` fortsatt er av som standard - [ ] Røyktest `GET /planos`, `/termos`, `/privacidade` og `/reembolso` på det angitte Radar-vertsnavnet - [ ] Registrer operatørens identitet/kontaktinformasjon/adresse og en eiergodkjent juridisk gjennomgang i den private tjenesten - [ ] Test Stripe Checkout og den signerte webhooken kun i testmodus - [ ] Test én kryptert levering av transaksjons-e-post med den godkjente avsenderen/domenet - [ ] Dokumenter gjenoppretting fra sikkerhetskopi og én overvåket forskningskjøring med et fastsatt kostnadstak - [ ] Godkjenn gjennomgangspolicyen for BRL/PIX før dokumentasjon på donasjoner godtas - [ ] Aktiver offentlig Checkout først etter at de foregående portene er passert, og aktiver deretter den nye `news.json`-ID-en - [ ] Bekreft at Hjem-banneret bruker lokalisert tekst, og at en ny ID vises igjen etter at en eldre ID er avvist ## Røyktest for innebygde tjenester (v3.8.4+) Før en versjon som inneholder endringer i innebygde tjenester, utgis, må følgende verifiseres: ### Oppstart med ny database (oppdager migreringskollisjoner — lagt til etter hurtigreparasjonen i v3.8.4) - [ ] `DATA_DIR=$(mktemp -d) npm start &` — vent 10 s på oppstart - [ ] `curl -s http://127.0.0.1:20128/api/services/9router/status | jq '.tool'` returnerer `"9router"` (IKKE 404, IKKE 500). Bekrefter at migreringen `071_services.sql` er kjørt, og at raden er opprettet. - [ ] `sqlite3 $DATA_DIR/storage.sqlite "PRAGMA table_info(version_manager);" | grep -E "provider_expose|logs_buffer_path|last_sync_at"` returnerer 3 rader. - [ ] `sqlite3 $DATA_DIR/storage.sqlite "PRAGMA table_info(webhooks);" | grep -E "kind|metadata_encrypted"` returnerer 2 rader (bekrefter at `070_webhooks_kind_metadata.sql` er kjørt). - [ ] `node --import tsx/esm --test tests/unit/db/no-migration-collisions.test.ts` består — beskytter mot fremtidige kollisjoner. ### 9Router - [ ] `POST /api/services/9router/install` returnerer 200 med `installedVersion` innen 2 min - [ ] `POST /api/services/9router/start` returnerer 200 og `state: "running"` innen 30 s - [ ] `GET /api/services/9router/status` rapporterer `health: "healthy"` - [ ] `POST /v1/chat/completions` med `"model": "9router/auto/..."` returnerer 200 (ende-til-ende-ruting gjennom 9Router) - [ ] `GET /dashboard/providers/services/9router/embed/dashboard` gjengir det innebygde 9Router-grensesnittet i proxyen (ingen direkte `127.0.0.1:port`-iframe) - [ ] `POST /api/services/9router/rotate-key` returnerer `{ keyRotated: true }`, og tjenesten starter på nytt uten problemer - [ ] `POST /api/services/9router/stop` returnerer 200 og `state: "stopped"` - [ ] `GET /api/services/9router/logs?tail=50` returnerer en SSE-strøm med en `snapshot`-hendelse som inneholder nylige linjer - [ ] Installasjon i et miljø uten `npm` i PATH returnerer 500 med en brukervennlig feilmelding (uten stakksporing) ### CLIProxyAPI - [ ] `POST /api/services/cliproxy/install` returnerer 200 innen 2 min - [ ] `POST /api/services/cliproxy/start` returnerer 200 og `state: "running"` innen 30 s - [ ] `GET /api/services/cliproxy/status` rapporterer `health: "healthy"` - [ ] `POST /api/services/cliproxy/stop` returnerer 200 og `state: "stopped"` - [ ] `GET /api/services/cliproxy/logs?tail=50` returnerer en SSE-strøm ### Sikkerhetsregresjon - [ ] `curl -H "X-Forwarded-For: 1.2.3.4" http://localhost:20128/api/services/9router/start` returnerer `403 LOCAL_ONLY` - [ ] `curl -H "X-Forwarded-For: 1.2.3.4" http://localhost:20128/api/services/cliproxy/start` returnerer `403 LOCAL_ONLY` - [ ] Feilsvar fra `/api/services/*` inneholder ikke `err.stack` eller absolutte filbaner ## Kontroller for v3.8.0+ Før en v3.8.x-versjon utgis, må disse tilleggspunktene verifiseres: - [ ] `omniroute --tray` starter på macOS (systray2 installert i `~/.omniroute/runtime/`) - [ ] `omniroute --tray` starter på Linux (krever DISPLAY; gir en kontrollert feilmelding hvis den ikke er angitt) - [ ] `omniroute --tray` starter på Windows (PowerShell NotifyIcon, ingen ekstra binærfiler) - [ ] `omniroute config tray enable` oppretter en autostartoppføring; deaktivering fjerner den - [ ] `npm install -g omniroute@` kjører etterinstallasjonen uten kritisk avslutning - [ ] Oppdateringsprosessen beholder valgfrie avhengigheter: `omniroute update --apply` og den automatiske oppdatereren kjører `npm install -g … --include=optional`, slik at `optionalDependencies` (better-sqlite3, keytar, tls-client og llmlingua SLM-stakken: `@atjsh/llmlingua-2@2.0.5`, `js-tiktoken`) beholdes etter en oppdatering. SLM-nivået ultra `modelPath` trenger også tinybert-modellen, som lastes ned automatisk til `${DATA_DIR}/models/llmlingua` ved første bruk. Etterinstallasjonen (`scripts/build/colocateOptionals.mjs`) samlokaliserer deretter den valgfrie SLM-avhengighetskjeden i `dist/node_modules`, slik at workeren bruker ÉN forekomst av `@huggingface/transformers` ^4.2.0 — den frittstående sporingen pakker bare transformers, ikke de dynamisk importerte valgfrie avhengighetene, så uten dette ville workeren laste llmlingua-2 mot transformers i roten, og SLM-nivået ville stille ha gått over til fail-open. - [ ] `omniroute status` fungerer uten `.env` (CLI-tokenbane, kun loopback) - [ ] `curl http://localhost:20128/api/shutdown` returnerer 401 (alltid beskyttet rute) - [ ] `curl -H "host: evil.com" http://localhost:20128/api/mcp/sse` returnerer 401 (loopback-beskyttelse) - [ ] SQLite-kjøremiljøet løses til `bundled` ved første kjøring (den medfølgende binærfilen er gyldig for plattformen) - [ ] SQLite-kjøremiljøet faller tilbake til `runtime` når `node_modules/better-sqlite3` slettes - [ ] Smart MCP-filter komprimerer reelle utdata fra `playwright-mcp browser_snapshot` (≥50 % reduksjon) - [ ] Alle de 10 `skills/omniroute*/SKILL.md`-filene er offentlig tilgjengelige via en rå GitHub-URL - [ ] Innføringsveiviseren viser nivåomvisningstrinnet «Slik fungerer det» ved nytt oppsett - [ ] Nivådekningswidgeten på startkontrollpanelet viser antall konfigurerte/aktive --- ## 3.9.0 LTS-forgrening (øvd inn i 3.8.58) Etter v3.8.59 er neste versjon 3.9.0, og dens spiss blir til to langsiktige grener: `stable/v3` (v3 LTS-linjen, npm `latest`) og `develop` (v4, oppjustert til 4.0.0, npm `nightly`). Gren-/kanalmodellen, fremoverportering og etiketter er beskrevet i [RELEASE_STRATEGY.md](./RELEASE_STRATEGY.md); planen finnes i [ROADMAP](../../ROADMAP.md) (fase 3). Forgreningen kjøres én gang; 3.8.58 øver inn hele prosessen på en fork, og 3.8.59 avsluttes med [GO/NO-GO-sjekklisten](./LTS_GO_NO_GO.md). ### Prøvekjøring (skrivebeskyttet, trygg når som helst) ```bash npm run release:dry-run-lts-cut # den virkelige forgreningen: 3.9.0 fra HEAD, forrige tagg v3.8.59 npm run release:dry-run-lts-cut -- --from <3.9.0-tip> # fest kilde-commiten ``` `scripts/release/dry-run-lts-cut.mjs` utfører ingenting: skriptet leser git og `gh` og skriver ut hele sekvensen — forhåndsbetingelser (kilden kan slås opp, kilderepositoriet har full historikk — en grunn klone kan ikke pushe `stable/v3`, mottakersiden avviser pakken ved den første innskjøtede forelderen, så forgren fra en full klone eller kjør `git fetch --unshallow origin` først — forrige tagg finnes, `package.json` har målversjonen, en `release-freeze`-sak er åpen, ingen åpen `Release branch not green`-sak på en eksisterende utgivelsesgren — en gren som ikke finnes, rapporterer `?` ukjent, aldri grønn — Mergify-køen `release` er konfigurert (G11: `queue_rules`, `checks_timeout`, etiketten `queue`), regelsettet `release/*` blokkerer fortsatt sletting og tvangspushing, og `stable/v3` og `develop` finnes ikke ennå), de to grentrinnene, hvilke utløsere og `if:`-betingelser for inaktive arbeidsflyter som blir sanne (og hvilke som fortsatt er sperret av en repositorievariabel eller festet til det kanoniske repositoriet), de forventede dist-taggene (`latest` → 3.9.0, `next` og `nightly` tomme) og tilbakerullingen. Avslutningskode `0` = `RESULT: READY`, `1` = en blokkerende forhåndsbetingelse mislyktes (`✗`), `2` = bruksfeil. `--advisory ` nedgraderer en kontroll til en advarsel (`!`) uten å skjule den. Kjør prøvekjøringen for den virkelige forgreningen mens utgivelsesfrysingen for 3.9.0 fortsatt er aktiv — grenene opprettes etter taggen og før fase 12c opphever frysingen. ### 3.8.58-øvelse (kun fork) ```bash # 1. Prøvekjør på gjeldende spiss med øvelsesparametere npm run release:dry-run-lts-cut -- --target-version 3.8.58 --previous-tag v3.8.57 \ --advisory freeze,base-green # 2. Kjør mot en FORK-fjernkilde (origin, eller en hvilken som helst fjernkilde med URL-en til det kanoniske # repositoriet, avvises; hvert trinn ber om bekreftelse i terminalen) git remote add rehearsal https://github.com//OmniRoute.git node scripts/release/dry-run-lts-cut.mjs --execute --remote rehearsal \ --target-version 3.8.58 --previous-tag v3.8.57 --advisory freeze,base-green # 3. Test de inaktive arbeidsflytene i forken (workflow_dispatch der prøvekjøringen # rapporterer en binding til det kanoniske repositoriet), og rull deretter tilbake node scripts/release/dry-run-lts-cut.mjs --execute --rollback --remote rehearsal \ --target-version 3.8.58 --previous-tag v3.8.57 --advisory freeze,base-green ``` Oppjusteringscommiten for develop bygges med git plumbing (arbeidstreet berøres ikke) og oppjusterer de samme fem filene som en commit som åpner en syklus: `package.json`, `open-sse/package.json`, `electron/package.json`, `package-lock.json` og `docs/openapi.yaml`. `[4.0.0]`-delen i CHANGELOG og dens i18n-speil åpnes på `develop` etterpå, før grenens første PR. Skriptet endrer aldri npm-dist-tagger — øv på disse med en midlertidig pakke. ### Forhåndsvisningsartefakt for PR (bygg én gang, promoter de samme bytene) `.github/workflows/preview-artifact.yml` bygger én produksjonstarball fra hodet til en PR og validerer nøyaktig dette bygget (#8084 del (a)). Kun PR-er fra samme repositorium; ingenting publiseres. ```bash gh workflow run preview-artifact.yml -f pr_number= # eller legg til etiketten `preview-artifact` gh run download --name preview-artifact-pr- --dir preview cd preview && sha256sum -c SHA256SUMS gh attestation verify omniroute-*.tgz --repo diegosouzapw/OmniRoute npm install -g ./omniroute-*.tgz # installasjon av forhåndsvisning ``` Kjøringen utfører `npm ci`, `npm run build:release`, `npm run check:pack-artifact`, pakker tarballen, kjører `npm run check:pack-boot` (falske hemmeligheter, midlertidig datamappe), pakker på nytt og mislykkes med mindre kontrollsummen er identisk. Deretter registrerer den `artifact-identity.json` (hode-SHA, base-SHA, låsfilhash, plattform, arkitektur, node ABI, bundler, byggpolicy — `scripts/release/artifact-identity.mjs`) og attesterer tarballen i en separat jobb. Å promotere en forhåndsvisning betyr å installere denne tarballen: bygg aldri på nytt fra kildekoden. ### Forgreningen (3.9.0, etter GO) 1. GO er registrert i [LTS_GO_NO_GO.md](./LTS_GO_NO_GO.md). 2. `npm run release:dry-run-lts-cut -- --from v3.9.0` skriver ut `RESULT: READY`. 3. Opprett grenene på `origin` manuelt med kommandoene prøvekjøringen skriver ut — skriptet nekter å pushe til `origin`. For å gjenbruke en gjennomgått develop-commit kjører du `--execute`-øvelsen på 3.9.0-spissen mot forken din først; den skriver ut begge SHA-ene, og de samme commitene kan pushes: ```bash git push origin :refs/heads/stable/v3 :refs/heads/develop ``` 4. Beskytt `stable/v3` og `develop` (regelsett + flettingskø) før den første PR-en flettes. 5. De inaktive arbeidsflytene aktiveres når grenene finnes: `forward-port.yml` (push til `stable/v3`), `validate-stable-pr.yml` (PR-er til `stable/v3`) og `nightly-v4-build.yml` (bygger `develop`). Før produksjonssetting må repository-hemmeligheten `secrets.FORWARD_PORT_TOKEN` angis (slik at CI kjører på PR-er for fremoverportering); nattlig publisering forblir deaktivert til eieren setter repository-variabelen `vars.NIGHTLY_PUBLISH` til `true` og npm Trusted Publishing godtar `nightly-v4-build.yml`. Kanaloppløsningen håndteres av `scripts/release/dist-tag.mjs`, den samme resolveren som `npm-publish.yml` bruker. 6. Verifiser kanalene: `npm view omniroute dist-tags --json` viser `latest` = 3.9.0 og ingen `next` / `nightly` før v4 publiseres. 7. Tilbakestilling ved behov: `git push origin --delete refs/heads/stable/v3 refs/heads/develop` og `npm dist-tag add omniroute@3.8.59 latest`. --- ## Tilbakerulling Hvis utgivelsen har et kritisk problem: 1. `gh release edit vX.Y.Z --prerelease` (markerer den som ikke nyeste) 2. `git tag -d vX.Y.Z && git push --delete origin vX.Y.Z` (bare hvis den ennå ikke er tatt i bruk av brukere) 3. Eller: hurtigretting på `release/vX.Y.0` → feilrettingsutgivelse `vX.Y.(Z+1)` 4. Kommuniser umiddelbart i GitHub Discussions og Discord ## Ufravikelige regler - Aldri commit direkte til `main` - Aldri bruk `git push --force` til `main`- eller `release/*`-grener - Aldri hopp over Husky-hooks (`--no-verify`) - Aldri commit hemmeligheter, påloggingsopplysninger eller `.env`-filer - Kodedekningen må holde seg på ≥60/60/60/60 (setninger/linjer/funksjoner/grener) - Inkluder eller oppdater alltid tester når du endrer produksjonskode i `src/`, `open-sse/`, `electron/` eller `bin/` ## Automatisk synkroniseringskontroll Kjør synkroniseringskontrollen for dokumentasjon lokalt før du åpner en PR: ```bash npm run check:docs-sync ``` CI kjører også denne kontrollen i `.github/workflows/ci.yml` (lint-jobben).