# nysky — endringslogg for agenter

Nye manifest-felter og atferdsendringer i kontrakten. Sjekk denne når du
OPPDATERER en app, så du ikke bygger på utdaterte antakelser.

Gjeldende kontraktversjon står i `X-Nysky-Contract`-headeren på alle API-svar
og i CLI-ens `--json`-konvolutt. Nyeste øverst.

**Beskriver du hvordan plattformen virker NÅ, er stedet
[https://nysky.no/agent.md](https://nysky.no/agent.md)** — denne loggen forteller bare hva som
har ENDRET seg.

---

## Kontrakt 0.2.84 — egress med port, kall-målvakt (20. september 2026)

- **`egress` tar nå `vert:port`.** Uten port er det HTTPS (:443) som før.
  `egress = ["tb.test.nhn.no:5671"]` åpner ren TCP mot AMQPS-porten til
  Norsk helsenetts test-tjenestebuss (nåbar fra internett);
  `"ocsp.buypass.no:80"` åpner OCSP over HTTP. Én nettverksregel per port,
  ingen L7-inspeksjon — TLS er appens ansvar. Langlivede forbindelser (AMQP
  med heartbeat) holdes — bevist med én forbindelse i 59 minutter gjennom
  policyen under gVisor. `:443` normaliseres bort. Krever fortsatt egen
  kapasitet (Fri stor eller container), som før.
- **Ny feil `403 kall-target-shared`:** `[[kall]]` mot en app som kjører i
  delt kjøring avvises nå ved plan/deploy. Før gikk deployen gjennom og
  kallet feilet først i kjøretid (målappen har ingen intern tjeneste i
  poolen). Sett `nivaa = "offentlig-stor"` eller `runtime = "container"`
  på målappen og deploy den først — i en monorepo-gruppe: koble målappen
  før kalleren, eller løft den i en egen push. Flytter du målappen tilbake
  til delt kjøring senere, mister kalleren tjenesten (vakten kjører ved
  kallerens deploy).
- **Dataansvarlig (HelseID) — additivt, ikke utrullet ennå (26. september 2026).**
  Kontoer som skal kalle helse-API-er med HelseID får et registrert
  dataansvarlig-organisasjonsnummer (settes av nysky etter fullmakt på
  helsenettet.no — ikke selvbetjent). `nysky plan`/`deploy` og
  `GET /v1/apps/{name}` viser da det valgfrie feltet
  `dataansvarlig: { orgnr, navn }` (menneskelinjen
  `  Dataansvarlig: <navn> (<orgnr>)`; `--json` bærer objektet uendret).
  Ren informasjon — ingen håndheving før `helseid` aktiveres i
  `[auth].methods` (fortsatt reservert). Nytt identitetshode
  `X-Nysky-Auth-Helseid-Orgnr` (dataansvarliges org.nr.) sendes av gaten
  kun til apper med nivåkrav, tomt ellers, og kan ikke forfalskes (står i
  `auth-response-headers` og pool-routerens stripping). Ny problem-type
  `helseid-data-controller-missing` (401 fra gaten når appens konto mangler
  dataansvarlig eller org.nr. avviker). Kontrakt: «Dataansvarlig (HelseID)»
  under 0.2.84. Under bygging, ikke tilgjengelig ennå: `@nysky/helseid`
  (SDK for container-apper: `client_credentials` med DPoP mot HelseID,
  bruksvilkår-feil som typede unntak) og M2M-tjenesten som utsteder client
  assertion med dataansvarliges org.nr. — annonseres når egen HelseID-klient
  er registrert og gjennomgått.

## Skyøkter: innloggingsoppskrift for agenter i sky-containere (14. september 2026, ingen kontraktbump)

- **Ny seksjon i agent.md: «Skyøkter (Claude Code på web o.l.)».** Kjører du
  i en sky-container der mennesket ikke ser terminalen din: sjekk først om
  `NYSKY_API_TOKEN` er satt i miljøet (forhåndsoppsatt token = null
  innloggingsskritt); ellers kjør device-flyten og **lim ALLTID `verifyUrl`
  og `userCode` som ren tekst i chatsvaret** — mennesket kan sitte på mobil
  og godkjenner derfra med passkey.
- **Nettverkssperre i skymiljøer:** 403 fra egress-proxyen mot
  `api.nysky.no` betyr at mennesket må åpne `api.nysky.no`, `nysky.no` og
  `git.nysky.no` i miljøets nettverkspolicy. `auth.nysky.no` trengs ikke
  fra økten.
- **Deploy fra skyøkt = push-to-deploy:** miljøer med Node < 24 mangler
  zstd og kan ikke bundle lokalt — `nysky git deploy enable` lar
  plattformen bygge. MCP-broen består som eksperimentelt alternativ som
  ikke rammes av nettverkssperren.
- **Rettelse i agent.md:** tre API-eksempler (device-flyten og
  skjema-endepunktet) viste den bokstavelige teksten `${apiUrl}` i stedet
  for API-adressen.

## Kontrakt 0.2.83 — nysky ID har flyttet til auth.nysky.no (12. september 2026)

- **Atferdsendring, ingen nye felter:** innloggingen (nysky ID) bor nå på
  `https://auth.nysky.no`. OIDC-issueren for `[auth] mode = "app"` er
  `https://auth.nysky.no/` — appen din får den i `NYSKY_AUTH_ISSUER` som før
  og rulles ut på nytt av plattformen. **Har du hardkodet
  `https://auth.nysky.app/` som issuer, må du bytte** (les alltid env-en).
  Discovery: `https://auth.nysky.no/.well-known/openid-configuration`.
- **URL-felter i API-svar** (`verifyUrl` fra `POST /auth/device/start`,
  `lenke` fra overdragelse/invitasjon, handlingslukas `url`) peker nå på
  `auth.nysky.no`. `auth.nysky.app` svarer 308 til samme sti i minst seks
  måneder, men OIDC-flyter og bearer-kall reddes ikke av redirect.
- **Egress-allowlister:** apper med `[nett] egress = ["auth.nysky.app"]`
  (JWKS-henting) må legge til `"auth.nysky.no"`.
- **Mennesker:** passkeys laget før flyttingen er bundet til nysky.app og
  brukes via «Passkey fra nysky.app» på innloggingen; deretter lages en ny
  (ett trykk). Vipps virker som før.

## Kontrakt 0.2.82 — sone FORTROLIG krever egen kapasitet (11. september 2026)

- **Atferdsendring, ingen nye felter:** et manifest med `sone = "FORTROLIG"`
  avvises nå i delt kjøring med problem-typen `sone-requires-dedicated`
  (403) — i `:plan`, `PUT`, git push og PR-previews. Naboskillet i delt
  kjøring er V8-isolatgrensen; FORTROLIG data skal ha egen kapasitet under
  gVisor-sandkassen.
- **Løsning:** sett `nivaa = "offentlig-stor"` (Fri stor) eller
  `runtime = "container"` — eller senk sonen til `ÅPEN`/`INTERN` hvis appen
  ikke behandler skjermingsverdige data. `sone` utelatt betyr `INTERN` og
  påvirkes ikke.
- Plattformen flytter aldri en FORTROLIG-app tilbake til delt kjøring, selv
  ved lav trafikk. En eksisterende FORTROLIG-app på Fri-nivået i delt
  kjøring flyttes til egen kapasitet uten prisendring; en på Personlig/
  Gruppe består i drift, men neste deploy avvises til kapasitet eller sone
  er valgt.
- `STRENGT_FORTROLIG` avvises fortsatt helt på cellen (krever hjemmekjerne).

## Kontrakt 0.2.81 — testbruker: automatisert testing bak nysky ID (11. september 2026)

- **Bots kan nå teste PR-previews bak nysky ID** uten passkey, Vipps eller
  menneske. Previews (`<app>-pr-<n>`) stoler på en EGEN test-issuer
  (`https://auth-test.nysky.app/`, egne nøkler); prod-apper gjør det aldri.
  Koblingen er avledet av at appen ER et preview — ingen manifestfelt.
- **`POST /v1/previews/{navn}/testbruker`** (deploy-scope) gir en HMAC-billett
  (1 time, bundet til previewets klient) for en deterministisk syntetisk bruker
  (`sub=u_test_…`, e-post under `.test.nysky.invalid`), valgfrie roller.
  Bruk: `POST <issuer>/billett` (cookie) eller `Authorization: Bearer` på
  `<issuer>/login`, så appens vanlige innlogging (gate: `/oauth2/start?app=…`;
  app-modus: OIDC mot previewets `NYSKY_AUTH_ISSUER`). CLI: `nysky preview
  testbruker <navn> [--rolle r]`. MCP: `preview_testbruker`.
- **Merking:** claim `nysky_test=true`/`amr=["ci"]`, gate-header
  `X-Nysky-Auth-Test: 1` (uforfalskbar — alltid satt av gaten). Appen kan nekte
  testidentiteter. Allow-listen gjelder mennesker; testidentiteter slipper inn
  på previewet, aldri på prod.
- **Mennesker logger inn på previews som før** (test-innloggingen federerer til
  ekte nysky ID). **Datavakt:** testbruker og klone av ekte data utelukker
  hverandre per preview (409 begge veier).
- **Previews-listen** (`GET /v1/apps/{app}/previews`) viser nå previewets
  faktiske URL (arvet domene) og aktive `klone`/`testbruker`.
- **Rettelse — PR-previews på eldre repoer:** Forgejo-repoer koblet før
  0.2.54 hadde webhooks med kun `push`, så en PR bygde aldri noe preview
  (stille). Plattformen reparerer nå slike hooks selv (ved oppstart og daglig),
  så `nysky git deploy enable` trenger ikke kjøres på nytt.
- **Git-tokenet følger innloggingen.** `nysky git login` gir nå et token
  per økt som utløper samtidig med login-sesjonen (`--varighet`). Flere
  økter på samme nysky ID (terminal + agent) lever side om side — før drepte
  den siste innloggingen de andres token. Utløpte tokens ryddes ved neste
  `git login` og ved `logout --overalt`.
- **Sandkasse-CI-tokens utløper etter 90 dager.** Agenten ber om nytt via
  samme underkonto-luke. Manuelt mintede CI-tokens er som før.
- **Testbruker-billett kan vare inntil 8 timer:** `timer` (1–8) i
  `preview_testbruker` / `nysky preview testbruker --timer`.
- **Bindinger til slettede repoer sovner, og vekkes av seg selv.** Er repoet
  borte i nysky Git, legges deploy-bindingen i søvn (vises som `sovende` i
  `GET /v1/gitops/bindings` / `nysky git deploy list`). Kommer repoet
  tilbake innen 30 dager, vekkes bindingen og webhooken gjenskapes automatisk
  — ingen `enable` nødvendig. Etter 30 dager slettes den. Koblet du repoet på
  nytt i mellomtiden, vinner den nye koblingen.

## Kontrakt 0.2.80 — valgfri token-varighet + GitHub-import/-synk (6. september 2026)

- **Rettelse 11. september — planlagt deploy i monorepo:** en enkeltplan
  (`deploy_planlegg` / `nysky preview planlegg` uten PR-gruppe, eller
  eksplisitt digest+repo+commit) for en app med manifest-sti i bindingen
  feilet ved utførelse med «fant ikke nysky.toml i <repo>@<commit>» — planen
  lette i repo-roten. Nå arver planen stien fra bindingen. Feilede planer må
  lages på nytt (`deploy_planlegg` igjen); ingen manifest- eller API-endring.
- **`nysky login --varighet 90d|36t|2d12t`**: token-levetiden kan settes fritt
  opptil 365 døgn (standard fortsatt 7 døgn). Varigheten VISES og godkjennes av
  mennesket på innloggingssiden; over 7 døgn vises en langlevd-advarsel der.
  API: `POST /v1/auth/device/start` tar `varighetTimer` (heltall 1–8760).
  «Logg ut overalt» (`nysky logout --overalt`) dreper også langlevde tokens —
  tilgangsepoken er uavhengig av TTL (testfestet).
- **`nysky git import <github-url> [--navn] [--pat-stdin]`**: engangs-import av
  et GitHub-repo til nysky Git (brukerens eget Forgejo-token; PAT for private
  repo leses kun fra stdin). Ingen videre kobling til GitHub etterpå.
- **`nysky git synk <github-url> [--navn] [--intervall 10m|1t|8t|24t]`**:
  LØPENDE synk fra GitHub (Forgejo pull-mirror, standard hver time). Primes av
  CLI/agent via `POST /v1/git/synk`, men godkjennes ALLTID av mennesket i
  handlingsluka (ny handlingstype `github-synk`) — med passkey og tydelig
  advarsel: nysky kan ikke garantere for hvor GitHub lagrer koden eller
  hvordan den håndteres der. GitHub-PAT for private repo limes inn I LUKA av
  mennesket (aldri via agent, aldri lagret). Kombiner med
  `nysky git deploy enable` for push-to-deploy fra GitHub-endringer.
  **`nysky git synk hent <eier>/<repo> [--branch <gren>]`** henter fra GitHub
  umiddelbart, utenom intervallet (f.eks. en deploy du vil sjekke raskt) —
  trigger mirror-sync og venter kort på at HEAD flytter seg; webhooken/
  deployen følger som ved ordinær sync. Hele kjeden GitHub-push → mirror-sync
  → webhook → deploy er E2E-verifisert i produksjon.
  **`nysky git deploy now <app>`** (og `POST /v1/apps/:name/gitops/kjor`)
  ruller ut grenens nåværende HEAD uten nytt push — første deploy etter en
  (om)kobling trenger ikke lenger en tom commit, og `--deploy-now` på
  enable virker nå også for GitHub-speil. Container-apper i monorepo bygges
  nå med appens undermappe som byggkontekst (som `docker build` lokalt) —
  standalone-Dockerfiler kan flyttes inn uendret.

## Kontrakt 0.2.79 — arv-adresser viderekobles til nyapp.no (6. september 2026)

- Eksisterende apper flyttes fra `<app>.nysky.app` til `<app>.nyapp.no`,
  og den gamle adressen **308-viderekobles** til den nye (308 bevarer
  metode og kropp — POST-er, webhooks og API-kall overlever flyttingen).
- Bedrifts-sti-adresser (`<bedrift>.nysky.app/<prosjekt>/<app>/`) og egne
  domener (`[[routes]]`) berøres **ikke** — kun de plattformgitte
  `<app>.nysky.app`-adressene flyttes.
- Appen er nåbar på begge domener gjennom hele flyttingen; ingen lenke
  brekker. `nysky.app` beholdes som viderekobling på ubestemt tid.
- Som før: **les appens faktiske adresse fra `status.url`**, ikke fra et
  antatt domene.
- **MCP-broen bor på `mcp.nysky.no`** (plattformflate — flyttet fra
  app-domenene 6. september; mcp.nyapp.no består som overgangsadresse, og
  navnet «mcp» er reservert på apps-domenene). Eksisterende tilkoblinger
  pekes om til https://mcp.nysky.no.

## Kontrakt 0.2.78 — nytt app-apex: nye apper får <app>.nyapp.no (6. september 2026)

- **Nye rutefrie apper** annonseres nå på `https://<app>.nyapp.no` (eget
  registrerbart domene for kundeinnhold — github.io-modellen).
  **Eksisterende apper beholder `<app>.nysky.app`**: adressen er
  materialisert i appens spec og STICKY — redeploys flytter aldri en app
  mellom domenene. Previews arver moderappens domene.
- **Ikke anta domenet i kode eller lenker** — les appens faktiske adresse
  fra `status.url` (API) eller `nysky status`.
- Eksplisitte `[[routes]]` under begge apps-domenene følger samme regel
  som før: kun `<app>.<domene>`; reserverte subdomener avvises.
- `nyapp.no` (apex) og `www.nyapp.no` viderekobles 301 til nysky.no.
- Alt annet er uendret: egendomener, gate/SSO, priser, kvoter.

## Kontrakt 0.2.77 — kjøpsluka: domenekjøp primes ferdig utfylt (5. september 2026)

- `nysky domene bestill <navn.no>` lager nå en FERDIG UTFYLT kjøpsluke i
  stedet for å avvise deg: nysky prefyller org.nr fra kontoens bedriftsfelt
  og e-post fra kontakten, og flaggene `--orgnr`/`--epost`/`--telefon`/
  `--ns` overstyrer. Registrant (Brreg) og ledighet (Norid) valideres ved
  priming — luka viser aldri en dødfødt bestilling.
- I luka gjenstår kun Norids egenerklæring (avhuking) og ett passkey-trykk.
  Riktig konto er alltid forhåndsvalgt (handlingen bærer den). Tom kreditt
  ved bekreftelse gir 402 og luka BLIR stående — fyll på og trykk igjen
  (TTL 1 time).
- API: `POST /v1/domene/{navn}/handlinger` med `type: "kjop"` (deploy-
  scope); poll `GET /v1/handlinger/{id}` til `utfort` —
  `resultat.bestillingId` følger bestillingen videre.

## Kontrakt 0.2.76 — hvert felt virker eller avvises (5. september 2026)

Full lovnadsrevisjon: alt dokumentert er nå enten implementert eller avvises
ærlig ved deploy. Endringene du må kjenne til når du bygger:

- **Egen kapasitet-krav (nytt):** `[[kall]]`, `[egress]`, `[http]`-verdier
  utover default (max_body_mb/response_timeout_s/sse) og
  `auth.client="confidential"` krever Fri stor eller Container. I delt
  kjøring avvises de i `nysky plan`/deploy med `*-requires-dedicated` —
  før validerte de og gjorde ingenting. `nivaa = "offentlig-stor"` (Fri
  stor) kan nå settes eksplisitt i manifestet.
- **Virker nå i delt kjøring:** `[[kv]]`-bindingen (`KV_<NAVN>_URL` var
  undefined før), `auth.mode="app"` med public-klient (issuer/client-id-
  bindingene injiseres), og `NYSKY_SLETT_SECRET` (slettekaskaden kan endelig
  verifiseres — den leveres også til apper uten egendomene nå).
- **Container-apper får `[vars]`** — de nådde aldri frem før.
- **`[limits]`-fella fikset:** `memory_mb` utelatt = 128 (workerd) / 512
  (container). Før kuttet en ren `cpu_m`-justering container-minnet til 128.
- **`[static]` + `main` avvises** — før ble `main` stille forkastet og
  alle API-ruter svarte 404. Frontend + API = worker-en server begge, eller
  to apper.
- **Strengere validering som fanger feil FØR drift:** ekte cron-schedule-
  validering (`"60 6 * * *"` avvises nå i stedet for å feile stille i
  driften), identifikatorlengde (app+datastore/bucket-navn over 63 tegn),
  reserverte `auth.methods`-verdier.
- **CLI:** `logs --limit`, `ovingsdata --antall` og `secret put --app`
  er ekte flagg (før: krasj); `nysky ci revoke <token-id>` finnes; feilende
  kommandoer viser diagnosen (CI-logg/rollout) i stedet for å kaste den;
  `secret request --json` returnerer luka umiddelbart med `dropUrl`
  (status `venter`); `nysky logs keygen` registrerer faktisk nøkkelen på
  kontoen (403-bug); `nysky tail` sier ærlig at den er avviklet.
- **API:** ukjente ruter svarer `404 not-found` (før 501 — nå betyr 501
  alltid «finnes, men ikke aktivert»); `GET /v1/konto/eksport` virker for
  `nysky login`-sesjoner (DPA §9-eksporten var 403 for alle);
  feilkatalogen i kontrakten er nå komplett.

## PostGIS er nå reelt tilgjengelig (4. september 2026)

- `extensions = ["postgis"]` i `[[datastores]]` har stått i allowlisten,
  men databaseimaget manglet PostGIS-binærene — `CREATE EXTENSION` feilet,
  og deployen med. Imaget er byttet (PostGIS 3.5), og hele allowlisten
  (pgcrypto, uuid-ossp, postgis, pg_trgm) er verifisert i produksjon,
  inkludert `geometry`/`geography`-kolonner og GiST-indekser.
- Ingen kontraktendring — feltet og allowlisten er uendret; det som var
  annonsert, virker nå.

## Kontrakt 0.2.75 — byggfeil forteller hvorfor, og hvem sin feil det er (3. september 2026)

- Feiler et container-bygg, bærer `GET /v1/apps/:name/build` nå `detail`
  (halen av byggeloggen) og `kilde` (`app` eller `plattform`).
  `kilde: "plattform"` betyr at feilen ligger hos nysky — ikke bruk tid på
  å feilsøke koden eller bytte basisimage; nysky er allerede varslet.
- `nysky deploy` viser årsaken direkte i feilmeldingen; push-to-deploy
  viser den i pipeline-status.

## Kontrakt 0.2.74 — selvbetjent container-aktivering (2. september 2026)

- Container-kjøretiden (390/790 kr/mnd) aktiveres nå selvbetjent: kjør
  `nysky container aktiver` (eller `POST /v1/konto/runtime/forslag`).
  Du får en lenke til bekreftelsesluken; kontoens menneske bekrefter med
  nysky ID (passkey), og tillegget er på — deploy appen på nytt etterpå.
- Feilmeldingen ved deploy av `runtime = "container"` uten tillegget
  peker nå på kommandoen i stedet for «kontakt eier/admin».
- Gjelder betalte kontoer; 409 hvis tillegget allerede er aktivert.

## Kontrakt 0.2.73 — kryptert logg også for container-apper (2. september 2026)

Container-apper (egen Dockerfile) har nå samme loggvei som workerd-appene:
stdout/stderr forsegles til kontoens loggnøkkel (eller `[logs].recipient`)
og leses med `nysky logs` — nysky lagrer kun chiffertekst. Apper uten
registrert nøkkel er uendret (ingen loggvei). Presist om mekanikken:
linjene går via nodens roterende kubelet-buffer (kryptert disk) før
forsegling — for apper der selv det er for mye, finnes ingen-logg-modusen
fortsatt. Kontoens loggnøkkel arves nå av ALLE runtimes ved deploy.

## Kontrakt 0.2.72 — faste jobber i delt kjøring, trinnbytte i luka, kjøreform er plattformens valg (2. september 2026)

1. **`[[crons]]` tvinger ikke lenger egen kapasitet.** Nye apper med faste
   jobber kjører på nivået sitt som alle andre (kallet går internt via
   plattformen; `X-Nysky-Cron-Key`-kontrakten er uendret). Eksisterende
   apper flyttes ikke — de kjører som før.
2. **Trinnbytte via bekreftelsesluken:** nærmer en app seg trafikkvoten,
   varsler plattformen og legger et FERDIG bytte til neste trinn i luka —
   mennesket bekrefter med nysky ID, ny sats fra neste døgntrekk. Aldri en
   stille prisendring; gjør du ingenting, gjelder 1 kr/GB over kvoten som
   før. Et bekreftet bytte huskes av plattformen og vinner over manifestets
   `nivaa` ved senere deploys (nytt bytte gjøres i luka).
3. **Boot-bevis for delte apper:** push-to-deploy avviser nå en bundel som
   krasjer ved modul-lasting (typisk nettverkskall, timere eller
   tilfeldighet i global scope — workerd forbyr det) FØR den slippes inn.
   Samme sjekk lokalt: `nysky dev --prove`.
4. **CLI-en:** nysky.no/cli publiseres nå automatisk ved hver
   kontraktutrulling (lå etter — beklager). Nytt i den: `dev --prove`,
   nettleseråpning virker på Windows, `secret put` spør etter verdien i
   interaktiv terminal (skjult), og en utløpt git-innlogging sier nå «kjør
   nysky git login på nytt» i stedet for rå 401.
5. **Kjøreformen for Fri-apper er plattformens valg innenfor trinnet:** en
   Fri-app med vedvarende høy trafikk kan flyttes til egen kapasitet — og
   tilbake — uten prisendring og uten at du gjør noe. `nysky plan` ruller
   aldri en plattform-flyttet app tilbake.

## Kontrakt 0.2.71 — posture-feltet er avviklet (2. september 2026)

`[posture]` i manifestet IGNORERES nå (godtas fortsatt, så eksisterende
manifester deployer uendret — fjern det gjerne). Loggsporet styres av
`[logs]` og kontoens loggnøkkel: appens logg krypteres til en nøkkel bare
kunden har (`nysky logs keygen` + `nysky logs`), og for apper der selv
kryptert logg er uønsket finnes ingen-logg-modusen. `audit`-posture og
`nysky tail` for apper er avviklet; plattformens egne hendelser føres
fortsatt i det hash-kjedede revisjonssporet. Vilkår og databehandleravtale
er revidert (v1.3, /v1/avtaler) og beskriver den nye loggmodellen.

## Kontrakt 0.2.70 — Fri, ingen søvn på betalte nivåer, dvale kun som livssyklus (2. september 2026)

FIRE endringer fra bunnrevisjonen, alle live:

1. **49-trinnet heter «Fri»** (149-trinnet «Fri stor»). I manifestet skriver du
   fortsatt `nivaa = "offentlig"` (eller arv-navnene) — kun visningsnavnet er
   nytt. **Gruppe-nivået er nå åpent: 29 kr/mnd** (`nivaa = "gruppe"`).
2. **Betalte apper sover aldri.** Kun gratis-appen sover ved inaktivitet
   (vekkes automatisk på sekunder). Betalt nivå = alltid klar, uten vekking —
   det er oppgraderingsgrunnen. Cron-timesregelen på personlig/gruppe består
   som produktgrense.
3. **Gate med tom allow-liste = kun kontoens utviklere — på ALLE nivåer**
   (utvider 0.2.69, som gjaldt gratis/personlig/gruppe). Regelen er én setning:
   en gatet app uten liste er din; `nysky allow add` åpner den. En gatet
   Fri-app arver dermed samme vern som personlig — ingen nedgraderingsfelle.
4. **Valgfri dvale er avviklet.** `nysky app dvale` og
   `POST /v1/apps/:name/dvale` svarer 410. Betalte apper kjører til de sies
   opp. Dvale finnes nå kun som livssyklus: gratis-løpet (2 uker varsel → 3
   uker parkert → 180 d sletting) og betalings-dvale — går kreditten tom får
   du varsel, appene kjører i 7 dager til (udekket forbruk føres som
   utestående), så parkeres de og trekkes 0. Vekking skjer når ny kreditt
   dekker det utestående. 25 %-dvale-satsen er borte.

## Kontrakt 0.2.69 — personlig betyr kun deg (2. september 2026)

VIKTIG ATFERDSENDRING for gatede apper på gratis/personlig/gruppe (og
telt-arv): en TOM allow-liste slipper ikke lenger inn enhver autentisert
nysky ID — gaten slipper nå kun inn kontoens egne utviklere. Det er selve
personlig-løftet: appen din er din. Vil du dele, er allow-listen veien
(`nysky allow add venn@eksempel.no` — live, uten redeploy) — det er
gruppe-modellen. Apper med allow-liste (i manifestet eller lagt til
selvbetjent) endrer ikke oppførsel. Offentlig-nivåets valgfrie gate beholder
«enhver autentisert»-semantikken ved tom liste.

## Kontrakt 0.2.68 — kryptert logg virker nå også i delt kjøring (2. september 2026)

Loggmangelen fra 0.2.67 er lukket: apper i delt kjøring (gratis/personlig/
gruppe/offentlig i pool) med en logg-recipient — egen `[logs]` eller
kontoens nøkkel — får nå kryptert logg. Konsollen fanges i appens EGET
isolat, forsegles av en plattform-worker i shard-podden til DIN age-nøkkel,
og lagres som chiffertekst; `nysky logs` leser som før. Apper UTEN
recipient får konsollen forkastet i isolatet (før kunne den nå shard-podens
stdout). Gjelder fra neste deploy av hver app. Container-runtime har fortsatt
ingen loggvei i v0.

## Kontrakt 0.2.67 — kontoens loggnøkkel: kryptert logg som standard (2. september 2026)

Steget mot ett loggspor: kjør `nysky logs keygen` én gang, og kontoens
workerd-apper uten eksplisitt `[logs]` får kryptert logg som standard fra
neste deploy — forseglet i podden til DIN age-nøkkel; plattformen lagrer kun
chiffertekst og kan aldri lese. Privatnøkkelen lagres i `~/.nysky/logs-key`
(ta sikkerhetskopi — mistes den, kan ingen lese loggene). `nysky logs`
dekrypterer lokalt og finner nøkkelen selv. API: `PUT/GET/DELETE
/v1/logs/nokkel` (PUT/DELETE krever secret-tilgang). `nysky plan` viser
alltid loggspor-endringer. Eksplisitt `[logs]` i manifestet vinner;
registrerer du ingen nøkkel, endres ingenting (dagens zero-knowledge-default).
Avgrensning: apper i delt kjøring har ennå ingen per-app-loggvei (kommer),
og container-runtime har ingen loggvei i v0.

## Atferdsendring — sovende nivåer sover nå, og vekkes ved bruk (2. september 2026)

Ingen ny kontraktversjon. Apper på gratis/personlig/gruppe (delte, gatede
nivåer) legges nå i søvn når de har stått ubrukt i ~15 minutter, og VEKKES
AUTOMATISK ved bruk — målt i produksjon til ~4 sekunder. Nettlesere ser en
«nysky jobber»-side som oppdaterer seg selv; API-kall holdes i inntil ~8
sekunder og fullfører vanligvis i samme forespørsel (ellers 503 med
Retry-After — prøv igjen). Prisen er uendret (søvn er plattformens
kostnadsoptimalisering, ikke en nedgradering), `[[crons]]` kjører som
planlagt uansett, og offentlig/container står alltid oppe som før. Trenger
appen din å stå oppe kontinuerlig, er `nivaa = "offentlig"` nivået for det.

## Kontrakt 0.2.66 — nivåene heter personlig/gruppe/offentlig (1. september 2026)

Nivånavnene beskriver nå PUBLIKUM, ikke infrastruktur. Tre endringer:

1. **`[nivaa]`**: kanoniske verdier er `personlig` (delt kjøring, alltid bak
   nysky ID), `gruppe` (som personlig — allow-listen er grensen; del med
   `nysky allow add`) og `offentlig` (åpen; kjøreformen delt/egen pod er
   plattformens valg). Gamle verdier godtas som aliaser og normaliseres ved
   deploy: telt→personlig, hytte→offentlig, hus→offentlig m/ egen pod. Ingen
   apps pris endres av navnebyttet. Nye apper uten `[nivaa]` er personlig.
   `GET /v1/apps` og plan-`haandhevet` svarer alltid med nye navn.
2. **`[posture]` er valgfritt (deprecated).** Utelatt = zero-knowledge —
   ingen atferdsendring. Ikke bruk feltet i nye manifester; det fjernes når
   ett-loggspor-migreringen (kryptert logg m/ kundeeid nøkkel) er fullført.
3. **`[[crons]]` er tillatt på alle betalte nivåer** (kravet om hus er
   fjernet). På personlig/gruppe må minuttfeltet i schedule være ett fast
   tall (0–59) — maks én kjøring i timen; brudd gir `manifest-invalid` med
   `cron-frequency-not-in-level`. offentlig/container har fri frekvens.
   Regelen håndheves også via git push.

MERK: deployer du manifest med nye enum-verdier og får «must NOT have
additional properties»/enum-avvisning, er bundler-imaget bak — meld fra.

## Rettelse — egne domener virker nå på delte apper (1. september 2026)

Ingen ny kontraktversjon. En delt app med `[[routes]]`-hostnavn der første
ledd ikke er appnavnet (f.eks. `dev.skjemo.no` for appen `skjemo-relay-dev`)
fikk «nysky: no app for host» — shard-routeren rutet kun på første host-ledd.
Routeren har nå et vert→app-kart bygget fra rutene dine; ingen handling kreves.

## Atferdsendring — delte apper: ærlig status, tålte secrets og pool-karantene (1. september 2026)

Ingen ny kontraktversjon, men tre synlige endringer for apper i den delte poolen:

1. **`nysky status` kan nå svare `Degraded` for en delt app** — enten
   «Shard … is not serving (pool outage …)» når shardens poder ikke står, eller
   «Quarantined from the shared pool …» (se 3). Før kunne status si «Ready —
   Serving (shared pool)» mens sharden var nede.
2. **En manglende secret tar aldri lenger ned naboene.** Deklarerte
   `[secrets]`-navn uten at `nysky secret put` er kjørt gir nå en app uten
   de miljøvariablene (den trygge feilen) — før blokkerte det oppstarten av
   HELE shard-podden. PR-previews i poolen får nå moderappens
   preview-miljøsett (`nysky secret put --preview`), aldri egne prod-secrets
   — samme regel som dedikerte previews har hatt siden 0.2.54.
3. **Pool-karantene:** krasjer en shard ved oppstart (typisk en bundle med
   fetch/timere/tilfeldighet i global scope — forbudt i workerd), settes den
   nyest deployede appen i karantene: den serveres som parkert side, naboene
   reiser seg, og appens status forklarer feilen. **Karantenen slippes ved
   neste deploy av appen** — fiks koden og deploy på nytt.

## Rettelse — soner i «venter-ns» oppdager delegeringen selv (1. september 2026)

Ingen ny kontraktversjon. En NS-tjeneste-sone som ble delegert til
ns1/ns2.nysky.no ETTER opprettelsen, ble stående som `venter-ns` til noen
leste `GET /v1/domene/<navn>/poster` — sonelisten (`domene mine`) re-sjekket
aldri. Nå re-sjekker både sonelisten og den periodiske sone-runneren (hvert
10. minutt), så aktivering skjer av seg selv når delegeringen er på plass.

## Rettelse — `gate_stier` virker nå også på egne domener for delte apper (1. september 2026)

Ingen ny kontraktversjon (dette er atferden 0.2.40 alltid har lovet): en app i
den delte poolen med `[auth] gate_stier` og eget domene fikk tidligere HELE
appen gatet på egendomenet, mens `<app>.nysky.app` var korrekt sti-scopet.
Nå håndheves samme sti-scoping på begge adressene. Fjernes `gate_stier` fra
manifestet, ryddes den ekstra gate-Ingressen automatisk. Ingen handling kreves
av deg — men har du bygget rundt at egendomenet gatet alt, må appen nå tåle
anonyme forespørsler på stiene utenfor `gate_stier` (som kontrakten alltid
har sagt).

## Kontrakt 0.2.65 — hele kontoflaten fra CLI (30. august 2026)

Alt du kan gjøre i UI-et kan nå gjøres fra CLI/API — menneskelige skritt
er passkey-bekreftelser i luka, aldri skjemaer:

- `nysky konto flytt <fra> <til> <kr>` og `nysky konto pafyll <konto>
  --under <hovedkonto> --med <kr> [--intervall dag|uke|mnd]` — kreditt-
  flytting og auto-påfyll (`POST /v1/konto/overforing[/avtale]`, admin-scope).
- `nysky app flytt <app> <tilKonto> [--plan]` — flytt en app mellom kontoer
  i familien (`POST /v1/konto/app/flytt`; `--plan` viser konsekvensene først).
- `nysky konto kvitteringer [--pdf <id> --ut fil.pdf]`, `forbruk`,
  `varsler`, `eksport --ut eksport.json` — kvitteringsrekka, posteringene og
  DPA §9-eksporten.
- `nysky konto avslutt` — oppretter avslutt-intent; mennesket bekrefter i
  luka (restkreditt på underkonto går tilbake til hovedkontoen).
- `nysky bedrift inviter --trekk <kode>` og `nysky team add --kjopsrett` —
  invitasjoner og kjøpsrett fra terminalen.
- CI-tokens er fortsatt rene lesetokens: ingen av rutene over åpnes for dem.

## Kontrakt 0.2.64 — agent-sandkasse: underkonto med budsjett (30. august 2026)

Personlige kontoer kan nå ha underkontoer — og DU kan foreslå en.

- `POST /v1/konto/underkonto/forslag` `{segment, navn?, engangsOre?,
  fast?: {belopOre, intervall: "dag"|"uke"|"mnd"}}` — lager en luke som
  mennesket bekrefter med passkey. Krever kreditt og betalt hovedkonto.
- Etter `status=utfort`: `GET /v1/handlinger/{id}` bærer
  `resultat.sandTenant` + `resultat.ciToken` ÉN gang (30 min TTL uavhentet).
  Tokenet ser KUN sandkassen — aldri hovedkontoen.
- Se seksjonen «Sandkasse» i agent.md for hele flyten.

## Kontrakt 0.2.63 — domeneoverføring fra CLI/agent (30. august 2026)

Flytt et .no-domene til nysky uten å fylle skjemaer: agenten/CLI-en
forbereder, mennesket bekrefter med passkey.

- `nysky domene overta <navn>` — authkoden fra dagens registrar på STDIN
  (aldri som argument). Svaret er en luke-URL: vis den til mennesket,
  overføringen bekreftes der med passkey. Poll `GET /v1/handlinger/{id}`
  til `status=utfort`.
- Norid sender så en engangskode til abonnentens registrerte e-post (be
  mennesket sjekke søppelposten — avsender norid.no). Fullfør med
  `nysky domene overta <navn> --kode <engangskode>` eller
  `POST /v1/domene/overta/kode` (bearer, scope deploy; CI-tokens aldri).
- API: `POST /v1/domene/{navn}/handlinger` godtar nå `{type: "overta",
  authkode}` for domener som ennå ikke er i kontoens register.
- `POST /v1/domene/{navn}/ns`, `PUT .../dnssec` og `PUT .../fornyelse`
  er åpnet for `nysky login`-sesjoner (admin-scope) — NS-bytte, DNSSEC og
  fornyelse trenger ikke lenger nettleseren.

## Kontrakt 0.2.39 — nullstilt 12. august 2026

Alt før denne datoen var utviklingsfasen: plattformen ble bygget, og
endringsloggen sporet arbeidet med den. Fra 12. august 2026 har nysky reelle
kunder, og loggen sporer noe annet — endringer som kan påvirke apper som
allerede kjører.

Historikken før nullstillingen er ikke borte; den ligger i repoets git-historie.
Den er bare ikke lenger noe du trenger å lese for å bygge riktig.

**Gjeldende kontrakt står ALLTID i `X-Nysky-Contract`-headeren og øverst i denne loggen — stol på den, ikke på et tall i løpende tekst.** Alt agent.md beskriver, gjelder — uavhengig av
hva som står her.

---

## 0.2.62 — 29. august 2026

**Flere apper kan nå deploye fra samme repo og gren.** Har du en monorepo der
to apper deler kode, koble dem begge: `nysky git deploy enable` legger appen
TIL grenens utrullingsgruppe i stedet for å overta den.

- Kjør `enable` fra hver apps egen katalog. CLI-en utleder manifest-stien
  derfra (`--sti <katalog>` overstyrer), og plattformen leser
  `<sti>/nysky.toml`. Før ble manifestet alltid hentet fra repo-roten — derfor
  kunne én gren bare beskrive én app.
- Ett push ruller ut ALLE appene på grenen, som én enhet:
  feiler ett manifest bygges ingen; feiler ett bygg konvergeres ingen; og blir
  ett medlem ikke friskt innen 10 minutter, rulles ALLE tilbake til forrige
  versjon. Bygde du grønt men gruppen ble stoppet, sier pipelinen det
  eksplisitt — «grønn» betyr aldri «er ute» i en gruppe.
- `nysky git deploy status` viser gruppen når grenen ruller ut flere apper.
  Nye endepunkter: `GET /v1/gitops/gruppe?repo=&branch=` og
  `GET /v1/gitops/grupper/:id`.
- `DELETE /v1/apps/:name/gitops` fjerner ETT medlem og svarer
  `gjenstaaende`. Webhook-URL-en bærer nå `?gren=` (gruppen deler én
  hook), og secreten roteres ALDRI når et medlem legges til.
- Én PR gir én preview per app og ÉN samlet kommentar; `nysky preview
  behold` forlenger hele settet, og lukking river det. Prisen er uendret —
  gratis-previewet er fortsatt per app.
- Planlegger du en promotering fra et preview i et PR-sett, planlegges HELE
  settet samlet. Alle previews må være grønne (`409 gruppe-ikke-groenn`);
  `gruppe: false` planlegger bare den ene.
- Container-images bygget via push-to-deploy tagges nå per commit i tillegg til
  `:latest`, så forrige versjon finnes å rulle tilbake til. Taggen beskytter
  framover — har appen aldri hatt et commit-tagget bygg, kan forrige image
  allerede være ryddet bort.

Byggejobbene er nå per kjøring, så to raske pushes på samme app ikke lenger
kan forstyrre hverandres bygg.

**Ærlig grense:** to apper er to utrullinger. Plattformen garanterer «begge
eller ingen», ikke «samtidig» — endrer du et delt protokollformat, må det
fortsatt tåle ett hopp der den ene siden er ny og den andre gammel.

Har grenen bare ÉN app, er alt som før: ingen verifiseringsvindu, ingen
automatisk tilbakerulling.

## 0.2.61 — 29. august 2026

**Sletter du én app i en monorepo, rører vi ikke lenger repoet.** Har flere
apper deploy-binding i samme repo, fjernes bare den slettede appens binding og
dens egen webhook. Før ble repoet arkivert (skrivebeskyttet!) eller slettet, og
alle nysky-webhooks i det fjernet — altså sluttet naboappen å deploye.

Repoet arkiveres/slettes fortsatt etter sone når den SISTE appen i det slettes.

## 0.2.60 — 28. august 2026

**Deploy-bindingen sier fra i stedet for å melde suksess.** Bygger du mot
push-to-deploy, er dette endringene:

- `nysky git deploy enable` mot en gren som allerede er bundet til en ANNEN
  app feiler nå med `409` (`gitops-binding-opptatt`) i stedet for å flytte
  bindingen i stillhet. Før svarte den «OK» og koblet fra den forrige appen.
  Vil du flytte den bevisst: `--force` — svaret bærer da `erstattet`.
  Én gren ruller ÉN app. (Endret i 0.2.62: én gren kan nå rulle ut flere.)
- `nysky git deploy disable <repo>` uten `--branch` slår nå opp grenen appen
  faktisk er bundet til (før: alltid `main`, med «koblet av» på en binding som
  ikke fantes). Svaret bærer `koblet_av` og `bundneGrener`. Er det ingenting
  å koble av, er det fortsatt `ok: true` — avkobling er idempotent.
- Webhook-URL-en du får av `enable` har nå `?app=…&gren=…`. Ruten er den
  samme; query-en gjør at CLI-en kan rydde bort SIN egen gamle hook uten å
  røre naboappens i et monorepo. Gamle hooks virker uendret.
- `--branch` uten verdi (og `--branch --force`) avvises nå i stedet for å
  gi en binding på feil gren.
- Bygger du på Windows eller i en minimal container: mangler `sh` på PATH,
  sier `plan`/`deploy` nå at byggkommandoen krever en POSIX-shell i stedet
  for `spawn sh ENOENT`. Byggfeil viser også stdout, så `tsc`/`vite`-feil
  ikke lenger forsvinner bak «exited with code 2».
- `nysky git login` kan kjøres om igjen uten å kollidere med seg selv, og
  credential-helperen skrives med en sti git faktisk klarer å lese (gjaldt
  Windows). Kjør den på nytt om `git fetch` spør etter brukernavn. Feiler
  `git config` (ingen git på PATH, låst config), er tokenet likevel lagret —
  du får `credentialHelper: "feilet"` og oppskriften, ikke en falsk feil.

## 0.2.59 — 26. august 2026

**«Logg ut overalt» dekker nå også git-tilgangen**, og godkjenning uten
eksplisitt kontovalg finnes ikke lenger.

- Full tilbakekalling (`nysky logout --overalt` uten `--konto`, eller
  kontosiden) sletter nå også git-tokenene (`nysky git login`-tilgangen).
  Får du 401 mot `git.nysky.no`: mennesket har logget ut overalt — be om ny
  innlogging. CI-tokens (`nskci_`) revokeres fortsatt separat.
- `POST /v1/auth/device/approve` KREVER nå `tenants[]` — «utelatt felt
  gir alle kontoer» er fjernet. Bygger du mot device-flyten: send alltid
  menneskets eksplisitte valg.

## 0.2.58 — 26. august 2026

**Færre klikk i godkjenningen.** Velger mennesket plattform-admin, kreves
fersk passkey — og kontovalget bæres nå serverside gjennom det steget, så
godkjenningen fullføres automatisk etterpå. Ingen endring for agenter utover
at flyten er kortere; `POST /v1/auth/device/valg` er intern mellom
godkjenningssiden og plattformen.

## 0.2.57 — 26. august 2026

**Ekte «logg ut overalt».** Tilgang kan nå trekkes TILBAKE, ikke bare glemmes
lokalt: `POST /v1/auth/revoker` (og `nysky logout --overalt`) gjør alle
eksisterende sesjonstokens for en nysky ID ugyldige — også kopier på andre
maskiner og i agenter. Nye tokens virker som normalt.

- **For deg som agent:** får du plutselig 401 på et token som virket, kan
  mennesket ha logget ut overalt. Be om ny tilkobling/innlogging — ikke prøv
  å gjenbruke gamle tokens.
- **Omfanget, presist:** revokeringen dekker API-sesjonstokens (også de
  avledede fra `/v1/auth/token`). Den dekker IKKE git-tilgang
  (`nysky git login` — roteres ved å logge inn på nytt) eller CI-tokens
  (`nskci_`, egen revokering). Ikke anta at «logg ut overalt» stoppet en
  push-to-deploy-tilgang.

## 0.2.56 — 26. august 2026

**Konto-scoped innlogging: mennesket velger hvilke kontoer du får.**
`nysky login` og MCP-tilkoblinger ga før tokens for ALLE kontoene brukeren
har tilgang til — inkludert plattform-admin. Nå krysser mennesket av på
godkjenningssiden hvilke kontoer tilgangen skal gjelde.

- **Du kan få FÆRRE kontoer enn mennesket har.** `hvem_er_meg` og
  `nysky konto` viser bare de valgte — ikke anta at flere finnes, og ikke be
  mennesket «logge inn på nytt for å få alt». Trenger du en bestemt konto:
  be mennesket kjøre `nysky login --konto <navn>` og krysse den av.
- **Plattform-admin gis normalt ikke til agenter.** Den er aldri
  forhåndsvalgt, krever fersk passkey, og for agent-tilkoblinger er ingenting
  forhåndsvalgt i det hele tatt. Bygg aldri en flyt som forutsetter
  admin-tilgang.
- **Ny CLI-kommando:** `nysky logout [--konto <navn>]` fjerner innlogginger
  på maskinen. (Tokens er stateless med inntil 7 dagers levetid — logout
  fjerner den lokale kopien, den tilbakekaller ikke en kopi andre har.)
- API: `POST /v1/auth/device/kontoer` (ny) og `tenants[]` i
  `/v1/auth/device/approve` — valget snittes mot medlemskap i
  kontrollplanet og kan aldri utvide tilgang.

## 0.2.55 — 26. august 2026

**Ekte ledighetssjekk for .no-domener.** `GET /v1/domene/sjekk?navn=` svarer
nå også `ledig` for gyldige navn: `true` = ikke registrert hos Norid,
`false` = opptatt, `null` = ledighetstjenesten svarte ikke (sjekken
blokkerer aldri svaret). «Ledig» betyr «ikke registrert» — reserverte navn kan
fortsatt avvises ved bestilling, og da refunderes beløpet automatisk. MCP:
`domene_sjekk` returnerer det samme; CLI `nysky domene sjekk` sier
LEDIG/opptatt. Kjøp er fortsatt en menneskeoperasjon på kontosiden.

**Onboarding-veiene er nå gratis eller Vipps** (2026-08-26): lukket beta og
agentbygger-kampanjen er avviklet, og alle invitasjonskoder er revokert —
ikke foreslå kode-veien. (Feltet finnes fortsatt på aktiveringssiden for
fremtidige kampanjer, men ingen koder er gyldige.)

Samtidig er domenevertikalen herdet etter en full gjennomgang: ny
registerstatus `overfort-ut` (domener flyttet til annen registrar tas ut av
fornyelsessporet og faktureres aldri), `POST /v1/domene/overta` godtar
restart når forrige post er død eller en engangskode aldri nådde fram
(venter-kode eldre enn 14 dager), og `PUT /v1/domene/{navn}/fornyelse`
med `autoForny: true` gir nytt fornyelsesforsøk etter et registeravslag.
Full liste i kontraktdokumentet.

## 0.2.54 — 24. august 2026

**Previews, planlagt deploy og generalprøven.** Test en gren live før reell
deploy, og promoter den om natten.

- **PR-previews er nå brukbare og prisede.** En PR mot et GitOps-koblet repo
  bygger fortsatt `<app>-pr-<n>.nysky.app` — men previewet får nå (1) egen
  datastore seedet med moderappens SKJEMA + syntetiske øvingsrader (aldri be
  mennesket om ekte data — previewet har alt testdata), og (2) appens
  **preview-miljøsett** av secrets (`nysky secret put <KEY> --preview`,
  API: `?preview=1`) — previews monterer ALDRI prod-secrets.
- **Pris:** 1 gratis preview per app i previewens første 7 dager; utover det
  halv nivåsats/30 per påbegynt døgn (vises i PR-kommentaren). Rives ved
  PR-lukking og etter 7 døgn uten push; `POST /v1/previews/{navn}/behold`
  ({dager: 1–30}, fornybar) beholder det. Gratis-nivået bygger ikke previews.
  `[[routes]]`/`[[crons]]` strippes i previews; gatede apper arver gaten.
  MCP: `preview_oversikt`. CLI: `nysky preview <app>`.
- **Planlagt deploy:** `POST /v1/apps/{navn}/planlagt-deploy`
  `{tidspunkt, fraPreview}` promoterer previewens grønne bygg på tidspunktet
  (2 min–30 dager fram). Manifestet hentes fra committen, appen verifiseres
  etter konvergering, og **rulles automatisk tilbake ved feil** — eieren får
  e-post uansett utfall. Én aktiv plan per app. FÅ MENNESKETS JA før du
  planlegger en prod-deploy. MCP: `deploy_planlegg`. CLI:
  `nysky preview planlegg|planer|avbryt`.
- **Generalprøven (ekte data i preview):** `POST /v1/previews/{navn}/klone`
  gir en passkey-luke — MENNESKET godkjenner, aldri du. Krever gatet preview;
  maks én aktiv klone per app; viskes automatisk etter 24 timer. Bruk den til
  å teste skjemamigrasjoner mot realistiske data før planlagt deploy.

## Avtale- og e-postendring — 23. august 2026 (ingen kontraktbump)

**E-postunntaket er lukket.** All transaksjonell e-post sendes nå fra nyskys
egen infrastruktur i Norge (mail.nysky.no), med ny avsenderadresse
**no-reply@nysky.no** (før: no-reply@nysky.app). Databehandleravtalen er
oppdatert til **v1.2** og bruksvilkårene til **v1.1** (`GET /v1/avtaler`
gir nye versjoner + sha256) — endringen er utelukkende til kundens fordel
(en underdatabehandler utenfor EØS er fjernet). Ingen API-endringer.

## 0.2.53 — 23. august 2026

**Dvale er kundens valg på betalte nivåer.** Betaler kunden, kjører appen.

- **Telt (og alle andre betalte nivåer) dvaler ALDRI av seg selv.** Tidligere
  parkerte Telt-apper ved inaktivitet som gratis-apper — det er slutt. Si
  dette til mennesket ditt hvis de har valgt nivå på feil grunnlag.
- **Frivillig dvale er uendret og virker på alle nivåer:** handlingsluken
  (`type: "dvale"`), `nysky app dvale <navn>` eller kontosiden. En app i
  dvale koster **25 % av månedssatsen** (minimum 1 kr) — bruk det aktivt for
  sesongapper og testmiljøer, men BARE når mennesket har bedt om det.
- **Kun gratis-appen** dvaler automatisk ved inaktivitet (~2 uker varsel,
  ~3 uker parkert). Vekking er ett klikk.
- Lav-saldo-vernet er uendret: en app uten dekning parkeres (aldri slettes),
  uansett nivå.

## 0.2.52 — 23. august 2026

**Kundevendt språk.** Plattformens interne topologi skal ikke lekke ut i
tekst kunden leser.

- `nysky plan` (`haandhevet.kjoring`) sier nå **«egen kapasitet»** /
  **«delt kapasitet»** i stedet for «egen pod» / «delt pool». Betydningen er
  uendret; trenger du å programmere mot det, bruk `tenancy` i App-ressursen.
- Pristabellen, priser.json og feilmeldingene om nivåer/`[[crons]]` er
  skrevet om på samme måte: hva appen får (innlogging, kapasitet, kvoter),
  ikke hvor prosessen bor.

## 0.2.51 — 22. august 2026

**Hele domene-livssyklusen er selvbetjent (D3–D6).** Transfer inn/ut,
auto-fornyelse, abonnentskifte, sletting og DNSSEC.

- **Transfer inn** (menneske-only, kontosiden): auth-kode fra dagens registrar
  → Norid sender engangskode til abonnentens e-post → fullføres på kontosiden.
  Gratis; fornyelse 149 kr/år fra neste forfall. Du som agent kan følge status
  i `GET /v1/domene/mine` (`innehav[]`) — aldri starte den.
- **Auth-kode ut (transfer til annen registrar):**
  `POST /v1/domene/{navn}/handlinger` `{type:"authkode"}` (deploy-scope)
  gir en luke-URL — mennesket bekrefter med passkey, og koden vises ÉN gang i
  luka. Du får ALDRI koden: `GET /v1/handlinger/{id}` viser deg kun
  `authkodeKlar`. MCP: `domene_handling`.
- **Auto-fornyelse** (default PÅ): 149 kr/år trekkes fra kreditten ~14 dager
  før utløp, varsel 30 dager før. `PUT /v1/domene/{navn}/fornyelse`
  `{autoForny}` er menneske-grad. Utilstrekkelig kreditt varsler daglig —
  et domene utløper aldri stille.
- **NS-bytte:** `POST /v1/domene/{navn}/ns` (menneske-grad; default
  plattformens navnetjenere — sonen må finnes her først: nedetidsfri flytt).
- **DNSSEC med én bryter:** `PUT /v1/domene/{navn}/dnssec` `{paa:true}`
  (menneske-grad) — sonen signeres og DS publiseres i .no automatisk (vi er
  registrar; ingen manuell DS-flytting). Av-bryteren fjerner DS og lar sonen
  stå signert — riktig margin før NS-flytt bort.
- **Sletting og abonnentskifte** går i handlingsluka med passkey; skifte
  krever ny egenerklæring (avgis i luka, føres i aksept-kjeden).
- CLI: `nysky domene mine|ns|dnssec på/av|forny auto/av|authkode`.

## 0.2.50 — 22. august 2026

**Selvbetjente DNS-soner og poster (D1+D2).** Domener på plattformens
navnetjenere forvaltes nå via API/CLI/MCP — også for domener registrert hos
andre registrarer (ren NS-tjeneste).

- `GET/PUT /v1/domene/{navn}/poster` — les/sett FULL ønsket postliste
  (A/AAAA/CNAME/ALIAS/MX/TXT/SRV/CAA), idempotent som `nysky.toml`.
  Agenter: les med read-scope, skriv med deploy-scope — men apex-endringer
  (A/AAAA/ALIAS på `@`) krever menneske-grad (innlogget CLI/kontosiden).
  SOA/NS eies av plattformen og kan aldri settes.
- **ALIAS på apex:** posttypen `ALIAS` materialiseres til A/AAAA på
  navnetjenerne. Verdi `inn.nysky.no` = plattformen (holdes i synk med
  LB-adressene av plattformen selv); eksterne mål re-resolves periodisk.
- `POST /v1/domene/sone` — opprett sone hos oss for et domene registrert
  et annet sted (admin-grad). Sonen står som `venter-ns` til delegeringen
  peker på ns1/ns2.nysky.no, og aktiveres automatisk.
- `GET /v1/domene/soner?tenant=` — kontoens soner m/ utrullingsstatus.
- CLI: `nysky domene sjekk|mine|poster|poster sett|sone-opprett`.
- MCP: `domene_sjekk`, `domene_mine`, `domene_poster`,
  `domene_poster_sett` (skriv — bekreft med mennesket; apex unntatt).
  Kjøp/overføring er aldri agent-operasjoner.

## 0.2.49 — 20. august 2026

**Domenesalget er åpent.** Forhandleravtalen med Norid er signert, og
nysky.no kjører selv på plattformens registrarkjede og navnetjenere.

- `POST /v1/domene/bestill` virker nå (mennesket bestiller fra kontosiden —
  «.no-domene»-knappen). 149 kr/år trekkes fra kreditten; avslag refunderes.
- `ns` er valgfritt: uten det får domenet plattformens navnetjenere, sonen
  provisjoneres automatisk og pekes mot plattformen — appen kobler domenet
  med `[[routes]]` som vanlig. Egne navnetjenere støttes (preflightes).
- Agenter: sjekk navn med `GET /v1/domene/sjekk`, følg bestillinger med
  `bestilling/{id}`/`mine` — selve kjøpet er fortsatt menneske-only.

---

## 0.2.48 — 20. august 2026

**Kunderevisjonsrunden — alt fra markedsføringsrevisjonen utbedret.** Det
meste er usynlig for deg; dette endrer agent-flyten:

- **Trafikk måles og prises nå reelt:** hver app har månedskvote etter nivå
  (5/20/100/500 GB), og KUN hele GB over kvoten trekkes (1 kr/GB — alltid i
  kundens favør). `GET /v1/konto/oversikt` viser `egress` per app
  (`gbBrukt`/`kvoteGb`).
- **Forbrukshistorikk:** `GET /v1/konto/posteringer?tenant=` (read-scope) —
  hver kreditering og hvert trekk, med kjede-verifikasjon (`kjedeOk`).
- **Dataeksport og konto-avslutning er selvbetjent** på kontosiden
  (menneske-flater — agenter henviser dit). Avslutning slettemerker alle apper
  med 28 dagers angrefrist; restkreditt forfaller (vises før bekreftelse).
- **`[[kall]]` er nå tilgjengelig for alle betalte kontoer** — kravet om
  arv-planene Start/Vekst er borte. Gratis-planen kjører fortsatt isolerte
  apper.
- **Domenebestilling er midlertidig stengt** (503 `domene-ikke-apnet`) til
  Norid-forhandleravtalen er signert. `sjekk` er åpen; ingenting trekkes.
- Kvitteringer utstedes nå for ALLE betalingsveier (også periodiske trekk og
  autofyll), og lav saldo varsles på e-post før parkering.
- Personlige kontoer har fått delingsflate: `GET /v1/konto/medlemmer` +
  eier-styrt legg-til/fjern. NB: fjernet medlem beholder deploy/secret-scope
  til session-tokenet utløper (inntil 7 dager) — admin-flatene stenges
  umiddelbart.

---

## 0.2.47 — 18. august 2026

**Norske domener (.no): flaten er bygget — bestilling åpner når
forhandleravtalen med Norid er signert.** Navnesjekken er åpen nå;
`bestill` svarer 503 `domene-ikke-apnet` til avtalen er på plass (ingenting
trekkes). Hele flyten går i Norge. Ny flate under `/v1/domene`:

```
GET  /v1/domene/sjekk?navn=minbedrift.no   # navneregler + LEDIGHET (RDAP) + pris (read-scope ok)
POST /v1/domene/bestill                    # KUN mennesket (konto-sesjon)
GET  /v1/domene/bestilling/{id}            # status: bestilt/behandles/registrert/feilet
GET  /v1/domene/mine?tenant=t-…            # kontoens bestillinger
```

- **Agenter kan sjekke og følge med, men aldri bestille.** Bestilling binder
  penger og en juridisk egenerklæring (Norids Vedlegg G) — den gjøres av et
  menneske i konto-sesjonen. Foreslå gjerne navn; send mennesket til konto-siden.
- `sjekk` svarer `ok` på NAVNEREGLENE (tegnsett, lengde, blokkliste) og
  oppgir årspris — den lover ALDRI at navnet er ledig; registeret er fasit.
- Bestillingen krever: gyldig org.nr (slås opp i Enhetsregisteret — enheten må
  ha registreringsberettiget org.form og ikke være under sletting), minst to
  navnetjenere som allerede svarer autoritativt for navnet, aksept av
  egenerklæringen, og dekning på kontoen. Avslås navnet av registeret,
  refunderes beløpet automatisk.
- Æøå og samiske tegn støttes (IDN → xn-- håndteres av plattformen).

---

## 0.2.46 — 18. august 2026

**Herdingsrunde — det meste er usynlig for deg, men to ting endrer agent-flyten:**

- **API-tokenet krever nå en `agentSecret`.** Bestillingssvaret
  (`POST /v1/onboard`) inneholder et nytt felt `agentSecret` ved siden av
  `orderId`. Send det med når du henter tokenet:
  `POST /v1/onboard/{orderId}/token` med header
  `X-Nysky-Onboard-Secret: <agentSecret>` (eller body `{"agentSecret":"…"}`).
  **Del ALDRI agentSecret med mennesket** — kun aktiverUrl. Grunnen: aktiverUrl
  deles bredt (chat, e-post), og skulle ikke også være nøkkelen til API-et.
- **`tilbud` valideres nå:** 1–20 tegn, bokstaver/tall/mellomrom/`. _ -`.
  Bruk et nivånavn (`gratis`/`telt`/`hytte`/`hus`). Etiketten er fortsatt
  bare kosmetikk — planen bestemmes av veien mennesket velger, aldri av `tilbud`.
- **`nysky plan` viser nå `haandhevet`:** om appen gates, om kapasiteten
  er egen eller delt, og hva den koster per måned — så en gratis/telt-app ikke
  stille havner bak innlogging uten at forhåndsvisningen sier fra.
- Betalende Vipps-kunder får nå riktig kreditt-tier (før kunne de havne i
  gratis-gaten). Ingen handling for deg.

---

## 0.2.45 — 17. august 2026

**Kvitteringer kan nå listes og lastes ned.** Nye lese-endepunkter på
konto-flaten (bearer med read-scope er nok):

```
GET /v1/konto/kvitteringer?tenant=<t-…>          # liste: id, dato, belopOre, beskrivelse
GET /v1/konto/kvittering/pdf?tenant=<t-…>&id=…   # PDF-nedlasting (application/pdf)
```

Oppslaget er tenant-scopet (en annens kvitterings-id gir 404). Mennesker
finner det samme under «Kvitteringer» på auth.nysky.no/konto — med
nedlastingsknapp per kvittering.

---

## 0.2.44 — 17. august 2026

**Kontonavn i stedet for tenant-koder — og rabatt vises ærlig.**

- `nysky login` og `nysky konto` snakker nå kontoNAVN («Personlig»,
  «nysky admin») i stedet for t-koder; `--konto` godtar navnet når det er
  entydig (t-koden virker som før). Kontoer du har fått tilgang til av andre
  merkes «tilgang fra <navn>».
- `GET /v1/onboard`-flyten er uendret — men `GET /v1/konto/oversikt` bærer
  nå `rabattProsent` (per konto) og `reellSatsOre` (per app) NÅR kontoen
  har rabatt. Har svaret disse feltene, presentér prisen som
  «sats × rabatt % = reell pris»; mangler de, vis kun `satsOre`. Ikke regn
  ut rabatt selv.
- Nedlagte kontoer forsvinner fra innlogging og kontooversikt — møter du en
  tenant-id som ikke lenger listes, er kontoen lagt ned (historikken består).

---

## 0.2.43 — 17. august 2026

**CLI-en krever nå eksplisitt kontovalg når maskinen har flere kontoer.**
Med flere kontoer i `nysky login`-credentials valgte CLI-en før stille den
FØRSTE — en agent deployet en kundeapp rett på eierens plattformkonto uten å
merke det (og advarselen var undertrykket i `--json`). Nå feiler `plan`,
`deploy`, `secret`, `app`, `allow`, `wake`, `ci`, `team`, `datastore` og
`git` hardt med `konto-ambiguous` til du velger:

```
node nysky.mjs deploy --konto t-abc123     # eller:
export NYSKY_KONTO=t-abc123                # gjelder alle kall i økten
```

Feilmeldingen lister kontoene. Én konto i credentials = uendret oppførsel.
**For deg som agent:** møter du denne feilen, IKKE gjett — spør mennesket
hvilken konto appen skal ligge på, og send valget eksplisitt. Ukjent konto i
`--konto` gir nå `konto-ukjent` i stedet for stille 401. Hent ny CLI fra
nysky.no/cli hvis din er eldre enn denne loggen.

**I samme slengen: `nysky login` plukker nå opp NYE medlemskap.** Før ble et
nytt `team add`-medlemskap kun aktivert ved brukerens aller FØRSTE innlogging
— hadde nysky ID-en alt bundne kontoer, ble nye medlemskap stående ubundet for
alltid. Nå bindes ubundne medlemskap (verifisert e-postmatch) ved hver
innlogging. Mangler en konto i `nysky login`-listen: logg inn på nytt.

---

## 0.2.42 — 17. august 2026

**Vipps-betaling i aktiveringssteget — og en gratis-vei uten kode.**
Aktiveringssiden (aktiverUrl) har nå tre veier, og mennesket velger selv:

- **Gratis (1 app):** ingen betaling. Kontoen får
  gratis-nivået — én app bak nysky ID-innlogging.
- **Betal med Vipps:** mennesket velger startkreditt (100/300/1000 kr) og
  godkjenner i Vipps. Kontoen får kreditt-tieren, og kreditten står inne når
  betalingen er bekreftet.

For deg som agent er flyten UENDRET i formen, med ett nytt statustrinn:
`GET /v1/onboard/{orderId}` kan nå svare `"status": "venter-betaling"` mens
mennesket er i Vipps — fortsett å polle; den blir `paid` når betalingen er
godkjent, eller `pending` igjen om den avbrytes/utløper. Du skal fortsatt
ALDRI be om betalingsinformasjon i samtalen — alt skjer på aktiveringssiden.
Nytt endepunkt `POST /v1/onboard/{orderId}/betal` brukes av aktiveringssiden,
ikke av deg.

---

## 0.2.41 — 15. august 2026

**Hemmelighetsluka: innsending virket ikke for apper på en annen konto enn
skaperens — fikset.** En luke laget av en admin-/plattformsesjon for en app
eid av en annen konto ga alltid 410 når mennesket limte inn verdien (luken
var bundet til feil tenant). Nå bindes luken til APPENS eier ved opprettelse.
Så du dette som «Lenken er ikke lenger gyldig» rett etter «Lagre»: lag en ny
luke — den virker nå.

**Lukas feiltilstander er skilt fra hverandre.** Før ga ukjent, brukt og
utløpt lenke samme svar (410 «brukt eller utløpt»). Nå: ukjent/avkortet lenke
= 404 `secret-drop-unknown` · allerede brukt = 410 `secret-drop-used` ·
tidsutløpt = 410 `secret-drop-expired` med utløpstidspunktet i `detail`.
Poller du statusruta er ingenting endret. Nettlesere får en lesbar feilside
med `requestId` synlig; API-kallere får problem+json som før.

**Luka varer nå 30 minutter** (før 15) — å hente en nøkkel hos en tredjepart
på mobil tok oftere enn ikke mer enn 15.

**Sikkerhetsdiffen i `deploy_via_git` rapporterer ikke lenger en falsk
«rute fjernet»** for apper uten `[[routes]]`. Plattformen materialiserer den
implisitte flate adressen (`<app>.nyapp.no`) i kjørende spec; diffen
sammenlignet den mot manifestteksten og viste adressen som fjernet enda ingen
hadde rørt den. Nå sammenlignes effektiv-mot-effektiv, og implisitte adresser
merkes «(implisitt)» når de vises. Så du en slik linje før: den var falsk —
ekte rute-endringer (egne domener) flagges som før.

---

## 0.2.40 — 13. august 2026

**[auth] gate_stier: åpen forside og innlogget admin i SAMME app.**

Fram til nå dekket `mode = "gate"` hele appen, uten unntak — også `/health`.
Mønsteret «offentlig innhold + beskyttet admin» var derfor ikke byggbart med
plattform-auth, selv om startmalen `skjema` beskrev det som om det var.
**Malen var feil, ikke plattformen** — og den er nå rettet.

Nytt felt, kun for `mode = "gate"`:

```toml
[auth]
mode = "gate"
allow = ["deg@firma.no"]
gate_stier = ["/admin"]   # kun /admin krever innlogging; resten er åpent
```

- **Utelatt felt = uendret oppførsel.** Hele appen gates, som før. Ingen
  eksisterende app endrer seg.
- Hvert element er et **prefiks**, matchet **case-insensitivt**: `/admin`
  dekker `/admin`, `/admin/brukere` og `/ADMIN`.
- `"/"` godtas ikke — det ville gatet alt, som er det samme som å utelate
  feltet.
- **Offentlige stier når appen UTEN** `X-Nysky-Auth-User`/`-Sub`. Appen må
  tåle anonyme forespørsler der, og må aldri utlede tilgang fra stien alene:
  gaten avgjør hvem som slipper inn, appen avgjør hva de får se.
- `/oauth2/*` er fortsatt reservert av plattformen.

Gjelder alle apper, og både `<app>.nyapp.no` og
bedriftens sti-adresse.

**Rettelse i samme slengen:** bundler-imaget som bygger GitOps-apper lå fire
kontraktversjoner bak, og avviste derfor `nivaa` som «ukjent felt». Feltet har
vært gyldig siden 0.2.36. Bygger du og får «must NOT have additional
properties» på et felt agent.md beskriver, er det oss — meld fra.
