nessie

Laget i EU, og der dataene dine lagres

Hvor Nessie er bygget, hvor dataene dine lagres, og hva du kontrollerer når du er vert selv.

Hvem som bygger det, og under hvilken lov

Nessie bygges av UnlikeOtherAI s.r.o., et selskap registrert i Tsjekkia som opererer under tsjekkisk lov.

Denne siden beskriver hvordan programvaren er bygget og hvor den kjører. Den er ikke en samsvarserklæring: Nessie har ingen sikkerhetssertifisering, og ingenting her skal leses som det. Hvilke personopplysninger som behandles, og på hvilket grunnlag, står i personvernerklæringen, som er en egen side.

Hvor den driftede tjenesten kjører

Nessie Cloud kjører hos europeiske driftsleverandører – Scaleway, Hetzner og andre. Vi velger den beste tjenesten hver leverandør tilbyr, så ulike deler av produktet kan kjøre hos ulike leverandører, alle sammen i Europa.

Noe mer presist enn det – et bestemt sted, en by eller et datasenter – oppgir vi bevisst ikke her, fordi det ville bli utdatert uten at noen la merke til det.

Ved egendrift er valget ditt

Hvor en egendrevet instans kjører, er en driftsinnstilling, ikke en produktinnstilling. Veien for én enkelt maskin er en Docker Compose-stack du plasserer på en maskin du selv velger. I Terraform-treet for en administrert sky er regionen en inndata uten noen standardverdi i det hele tatt: ingenting der kan gjettes, så ingenting der har en standardverdi, og databasen, objektlagringsbøtten og tjenestene følger alle regionen du oppgir.

To strukturelle detaljer er viktige for det samme spørsmålet. Køen og sanntidstransporten er begge PostgreSQL – det finnes ingen Redis og ingen meldingsmegler i løypa, så det er ikke et tredje system å plassere. Og objektlagringen er S3-kompatibel i stedet for knyttet til én leverandør; referanseoppsettet kjører MinIO i en container på et privat nettverk uten egen inngang utenfra. Delene som må ligge et sted, er databasen, objektlageret og de to Node-tjenestene, og de ligger alle der du plasserer dem. Hvordan du setter det opp, står på installasjonssiden.

Hva Nessie lagrer – og hva den bevisst ikke lagrer

Identitet kopieres ikke

Med UnlikeOtherAI-innlogging er det identitetsleverandøren som håndterer og lagrer menneskelig identitet – autentiseringsfaktorer, profiler, medlemskap i organisasjoner og team, og invitasjoner. Nessie er en relying party, ikke et ekstra identitetssystem. Dette er like mye en datamessig som en arkitektonisk beslutning: en identitet Nessie aldri lagrer, er en Nessie ikke kan lekke, miste eller glemme å slette.

Det users-tabellen faktisk inneholder, er leverandørens stabile brukeridentifikator – nøkkelen alt annet slås opp gjennom –, e-postadressen, et ikke-autoritativt speil av visningsnavn og avatar, og produktlokale felt (preferanser, pronomen, en tokenversjon som brukes til å tilbakekalle økter). Speilet finnes bare for at et navn og et bilde skal kunne vises uten en forespørsel per rad, og det synkroniseres på nytt fra leverandørens verifiserte claims ved innlogging, ved bytte av team og ved fornyelse av økten. Ingenting finner på en verdi: en person leverandøren ikke har navngitt, vises med e-postadressen sin til det skjer. En passordhash finnes bare for oppstartseieren av en installasjon helt uten identitetsleverandør.

Det samme gjelder strukturen. Én organisasjon hos leverandøren er én Nessie-organisasjon, bundet av leverandørens organisasjons-id. Et team uten kobling oppstrøms svarer 404 TEAM_NOT_LINKED i stedet for å falle tilbake på et lokalt gjett, og en live henting av medlemslisten går til identitetsleverandøren og lagrer ingenting.

To speil er ikke borte ennå, og det ville være uærlig å antyde noe annet. Navn på organisasjoner og team lagres fortsatt lokalt ved siden av bindings-id-ene, og lokale medlemsrader godkjenner fortsatt vanlige forespørsler mellom synkroniseringene. Å fjerne begge er registrert, åpent arbeid i repoet, ikke noe som allerede er ferdig.

Ingenting kommersielt

Den sentrale faktureringstjenesten håndterer betalinger. Nessie lagrer ingen kunde, abonnement, faktura, pris, kredittsaldo, påfyllingsregel, betalingssamtykke, kontoutskrift eller oppsigelsestilstand hos betalingsleverandøren, og beregner ikke priser. Den leser ferdige visningsverdier og viser dem.

Hemmeligheter

Det kreves et konfigurert hvelv for å lagre en hemmelighet i det hele tatt. Det finnes bevisst ingen reserveløsning i databasen og ingen klartekststi: uten hvelv gir lagring, rotasjon og tilbakekalling av en hemmelighet en feil i stedet for å forringes til noe mindre trygt. Nessies egne poster for en hemmelighet inneholder ingen verdi, ingen chiffertekst, ingen nøkkel og ingen hvelvtoken – bare en ugjennomsiktig referanse og metadata – og hvelvstier bygges kun av strukturelle identifikatorer, aldri av navnet på en organisasjon, et team, et prosjekt eller en person.

Legitimasjon Nessie selv må ha for å opptre som OAuth-klient – koblings- og postboksopplysninger, webhook-hemmeligheter, fornyelsesmateriale for økter, executor-data – er forseglet i formålsbundne AES-256-GCM-konvolutter under en versjonert nøkkelring som er en egen rot, atskilt fra signeringshemmeligheten for økter, med en dokumentert rotasjonsprosedyre.

Det finnes også en regel om modeller: en hemmelighet kan være kjent å eksistere og kan være godkjent for bruk, men hemmelig materiale skal ikke komme inn i modellkontekst, prompter, verktøyargumenter, verktøyresultater, minne, embeddings, søk, logger eller meldinger. En agent kan få evnen til å bruke en hemmelighet. Den kan aldri få evnen til å avsløre en.

Om diskene under er kryptert, er en egenskap ved maskinen en installasjon kjører på. Repoet fastslår ikke kryptering på volumnivå for database- og objektlagringsvolumene, så denne siden påstår det ikke.

Isolasjon mellom organisasjoner (tenants)

Nessie er multi-tenant fra grunnen av: én database der hver rad tilhører nøyaktig én organisasjon, og hver underordnede tabell har en organization_id. Isolasjonen håndheves to steder – avgrensningsleddet hver spørring har med seg, og ekte fremmednøkler på den kolonnen, som ble lagt til gjennom førtito begrensninger etter at en intern revisjon fant at kolonnen fantes, men var uten begrensninger i dusinvis av tabeller.

En samsvarstest holder denne invarianten på plass ved HTTP-grensen. Den setter opp en angriper med maksimale rettigheter – full eier av sin egen organisasjon – og kontrollerer at hver kanoniske lesing av en annen organisasjons ressurser gir 403, 404 eller tomt svar, og at hver kanoniske endring avvises uten at den andre organisasjonens rad røres. Den dekker kanaler, godkjenninger, revisjonsloggen, triggere, agenter og deres bindinger, kjøringer, prosjekter, oppgaver, tråder, tilkoblinger, arbeidsflytinstallasjoner, MCP-instanser, kunnskapsbasen og varsler.

For å være presis om mekanismen: dette er håndheving på applikasjonsnivå pluss fremmednøkler, ikke radnivåsikkerhet (row-level security) i PostgreSQL. Det finnes ingen RLS-policy og ingen sikring på databasesiden, og samsvarstesten kjører mot et trofast minnelager i stedet for en live database, så den beviser avgrensningsleddene koden skriver, ikke SQL-en en server kjører. Repoet sier det i testens egen dokumentasjon, og det gjør denne siden også.

Revisjonssporet

Hver handling av betydning registreres: hvem som handlet og som hva – en person, en agent, en tjeneste –, hva de gjorde, med hvilken ressurs, i hvilken organisasjon, hvilket prosjekt, team eller kanal, om det lyktes eller ble avslått, hvorfor, og forespørsels-id-en, adressen og user agent som fulgte med.

Loggen er bevisst kun-tillegg, og det finnes ingen måte å skrive til den utenfra: POST /api/audit-log finnes ikke, og det er med vilje. Oppføringene er kjedet – hver av dem har en SHA-256-sjekksum av sine egne kanoniske felt pluss sjekksummen til forrige oppføring for den organisasjonen – slik at en endret eller fjernet rad bryter kjeden og kan oppdages. En eier eller administrator i organisasjonen kan gå gjennom kjeden når som helst og får vite hvor den først ble brutt, hvis den ble det.

To ærlige forbehold. Kjeden gjør loggen manipulasjonssynlig, ikke immun mot manipulasjon: det finnes ingen tilbakekalling av skrivetilgang på databasenivå og ingen skriv-én-gang-lagring bak den, så garantien er oppdagelse, ikke forhindring. Og oppføringer beholdes som standard på ubestemt tid – konfigurerbar oppbevaringstid med eksport før sletting er planlagt, ikke bygget. Oppføringer kan heller ikke inneholde hemmeligheter eller fulle forespørselsinnhold, og et fast sett med sensitive metadatafelt maskeres på vei inn.

Kostnadsregisteret

Hvert modellkall registreres mot organisasjonen, og mot brukeren, teamet, prosjektet, kanalen, agenten og kjøringen det kom fra, med tokenene det brukte og både leverandørens oppgitte kostnad og Nessies eget anslag side om side. En måling leverandøren ikke oppgir, lagres som null i stedet for å gjettes. Rapportene kan leses av en eier eller administrator i organisasjonen.

Dette registeret er driftstelemetri – hva en organisasjon brukte og på vegne av hvem. Det er ikke en faktura og ikke en faktureringsautoritet.

Tredjeparter når du bruker den driftede tjenesten

En driftet installasjon snakker med et lite, fast sett med tjenester. Modelltrafikk og nettsøk går ikke direkte til leverandørene: begge går ut gjennom én gateway drevet av UnlikeOtherAI, og det er der de underliggende modell- og søkeleverandørene ligger. Innlogging og fakturering går til UnlikeOtherAIs autentiseringstjeneste. Hemmelighetshvelvet er egendrevet ved siden av applikasjonen. Videomøtelenker som lages av serveren, bruker som standard den offentlige Jitsi-tjenesten.

Nesten alt annet er av til en operatør konfigurerer det, og sier fra om det i stedet for å feile i det stille: tilkoblede Google-, Microsoft- og Slack-kontoer, agent-e-post via Amazon SES, som en installasjon kjører i sin egen konto uten mellomledd, push på mobil og i nettleser, forskning og kildekoblinger for tavler, nettlesere i skyen. To detaljer er verdt å nevne fordi de endrer hvor dataene går:

  • Tilkoblede postbokser blir hos leverandøren din. E-post leses direkte fra leverandøren din, over IMAP og SMTP eller leverandørens egen innlogging; Nessie lagrer den forseglede legitimasjonen og ingenting annet om kontoen. En postboks du kobler til Clients-innboksen er unntaket: da ber du om at samtalene skal samles hos hver kunde, så de kopieres inn.
  • Taleanrop går ikke gjennom Nessie. API-et formidler en legitimasjon, og klienten åpner lydforbindelsen selv. Diktering og telefonsamtaler er annerledes: lyden deres går gjennom Nessie til tale- og modellleverandørene som behandler den.

En inferensdetalj følger samme prinsipp: signerte hoder med oppringerens identitet sendes bare til den konfigurerte chat-verten, så om du peker embeddings mot et annet endepunkt, får det endepunktet aldri en delegasjonspåstand om personen hvis tekst blir embedded.

Den driftede tjenesten bruker flere inferensleverandører og velger mellom dem ut fra kostnad og kvalitet. En organisasjon vil kunne velge i Admin hvilke leverandører agentene dens får bruke: bare vestlige, bare europeiske, bare kinesiske, eller ingen preferanse – den mest effektive leverandøren for hver jobb. En egendrevet instans velger selv.

Driver du den selv, endres alt dette

Hver tredjepart ovenfor er et konfigurasjonsvalg på en egendrevet instans. Inferens kan pekes mot et hvilket som helst OpenAI-kompatibelt endepunkt, også ett på din egen maskinvare. Koblingene er av med mindre du slår dem på. UnlikeOtherAI-innlogging er den støttede veien, og en installasjon helt uten identitetsleverandør kjører som én enkelt ubundet organisasjon med en oppstartseier.

Det er hele poenget med oppsettet: programvaren er den samme, og beslutningene om hvor den kjører og hva den får nå, tilhører den som driver den. Installasjonssiden forklarer hvordan.