Made in de EU, en waar je data staat
Waar Nessie wordt gebouwd, waar je data staat en wat jij beheert als je het zelf hostt.
Wie het bouwt, en onder welk recht
Nessie wordt gebouwd door UnlikeOtherAI s.r.o., een bedrijf dat is geregistreerd in Tsjechië en werkt onder Tsjechisch recht.
Deze pagina beschrijft hoe de software is gebouwd en waar die draait. Het is geen compliance-verklaring: Nessie heeft geen beveiligingscertificering en niets op deze pagina mag als zodanig worden gelezen. Welke persoonsgegevens worden verwerkt en op welke grondslag, staat in het privacybeleid, een aparte pagina.
Waar het gehoste product draait
Nessie Cloud draait op Europese hostingproviders — Scaleway, Hetzner en andere. We kiezen bij elke provider de beste dienst die zij biedt, dus verschillende onderdelen van het product kunnen bij verschillende providers draaien, allemaal in Europa.
Alles wat preciezer is dan dat – een specifieke locatie, stad of datacenter – wordt hier bewust niet genoemd, omdat het zou verouderen zonder dat iemand het merkt.
Zelf hosten legt de keuze bij jou
Waar een zelfgehoste instantie draait, is een instelling van de implementatie, geen instelling van het product. Het pad voor één machine is een Docker Compose-stack die je op een machine naar keuze zet. In de Terraform-structuur voor een beheerde cloud is de regio een invoerwaarde zonder enige standaardwaarde: niets daarvan valt te raden, dus niets daarvan heeft een standaard, en de database, de objectopslag-bucket en de services volgen allemaal de regio die je opgeeft.
Voor dezelfde vraag zijn twee structurele details van belang. De wachtrij en het realtime-transport zijn allebei PostgreSQL – er is geen Redis en geen message broker in het pad, dus er is geen derde systeem om te plaatsen. En objectopslag is S3-compatibel in plaats van aan één leverancier gebonden; de referentie-implementatie draait MinIO in een container op een privénetwerk zonder eigen ingress. De onderdelen die ergens moeten draaien zijn de database, de objectopslag en de twee Node-services, en ze draaien allemaal waar jij ze neerzet. Hoe je dat opzet, staat op de installatiepagina.
Wat Nessie bewaart – en wat bewust niet
Identiteit wordt niet gekopieerd
Bij inloggen met UnlikeOtherAI beheert en bewaart de identiteitsprovider de menselijke identiteit – authenticatiefactoren, profielen, lidmaatschap van organisaties en teams, en uitnodigingen. Nessie is een relying party, geen tweede identiteitssysteem. Dat is evengoed een beslissing over data als over architectuur: een identiteit die Nessie nooit opslaat, kan Nessie niet lekken, kwijtraken of vergeten te verwijderen.
Wat de tabel users werkelijk bewaart, is de stabiele gebruikers-ID van de provider – de sleutel waarlangs al het andere wordt opgelost –, het e-mailadres, een niet-gezaghebbende kopie van weergavenaam en avatar, en productlokale velden (voorkeuren, voornaamwoorden, een tokenversie waarmee sessies worden ingetrokken). De kopie bestaat alleen zodat een naam en een afbeelding kunnen worden getoond zonder een verzoek per rij, en wordt bij het inloggen, bij het wisselen van team en bij het vernieuwen van de sessie opnieuw gesynchroniseerd met de geverifieerde claims van de provider. Er wordt nooit een waarde verzonnen: iemand die de provider niet bij naam kent, draagt zijn of haar e-mailadres totdat dat wel zo is. Een wachtwoordhash bestaat alleen voor de bootstrap-eigenaar van een installatie zonder enige identiteitsprovider.
Hetzelfde geldt voor de structuur. Eén organisatie bij de provider is één Nessie-organisatie, gekoppeld via de organisatie-ID van de provider; een team zonder koppeling stroomopwaarts antwoordt met 404 TEAM_NOT_LINKED in plaats van terug te vallen op een lokale gok, en een live ledenlijst wordt bij de identiteitsprovider opgehaald en nergens bewaard.
Twee kopieën zijn er nog niet uit, en het zou oneerlijk zijn om anders te suggereren. De namen van organisaties en teams worden nog lokaal bewaard naast de koppelings-ID’s, en lokale lidmaatschapsrijen autoriseren gewone verzoeken nog steeds tussen synchronisaties door. Beide verwijderen is openstaand werk dat in de repository wordt bijgehouden, en nog niet af.
Niets commercieels
De centrale factureringsdienst beheert de betalingen. Nessie bewaart geen klant, abonnement, factuur, prijs, tegoedsaldo, opwaardeerbeleid, betalingstoestemming, afrekening of opzegstatus van een betalingsprovider, en berekent geen tarieven. Het leest weergaveklare waarden en toont ze.
Geheimen
Om een geheim op te slaan is een geconfigureerde kluis vereist. Er is bewust geen terugval op de database en geen pad met leesbare tekst: zonder kluis geven het opslaan, roteren en intrekken van een geheim een foutmelding in plaats van terug te vallen op iets minder veiligs. De eigen gegevens van Nessie over een geheim bevatten geen waarde, geen versleutelde tekst, geen sleutel en geen kluistoken – alleen een ondoorzichtige verwijzing en de bijbehorende metadata – en kluispaden worden uitsluitend uit structurele identificatoren opgebouwd, nooit uit de naam van een organisatie, team, project of persoon.
Inloggegevens die Nessie zelf moet bewaren om als OAuth-client te kunnen handelen – inloggegevens voor connectoren en mailboxen, webhook-geheimen, materiaal voor het vernieuwen van sessies, executor-payloads – worden verzegeld in doelgebonden AES-256-GCM-enveloppen onder een sleutelring met versies, die een aparte root vormt naast het geheim waarmee sessies worden ondertekend, met een gedocumenteerde rotatieprocedure.
Er is ook een regel over modellen: van een geheim mag bekend zijn dat het bestaat en mag het zijn toegestaan om het te gebruiken, maar geheim materiaal mag niet in de modelcontext, prompts, toolargumenten, toolresultaten, geheugen, embeddings, zoekopdrachten, logs of berichten terechtkomen. Een agent kan het recht krijgen om een geheim te gebruiken. Het recht om er een te onthullen krijgt een agent nooit.
Of de onderliggende schijven zijn versleuteld, is een eigenschap van de machine waarop een implementatie draait. De repository stelt versleuteling op volumeniveau voor de database- en objectopslagvolumes niet vast, dus deze pagina beweert dat ook niet.
Isolatie van tenants
Nessie is van nature multi-tenant: één database waarin elke rij bij precies één organisatie hoort en elke onderliggende tabel een organization_id heeft. De isolatie wordt op twee plekken afgedwongen: in de scope-clausule die elke query meekrijgt, en in echte foreign keys op die kolom, die zijn toegevoegd als tweeënveertig constraints nadat een interne audit had vastgesteld dat de kolom op tientallen tabellen wel bestond maar niet was afgedwongen.
Een conformiteitssuite houdt die invariant op de HTTP-grens op zijn plek. Ze zet een maximaal bevoegde aanvaller klaar – een volledige eigenaar van zijn of haar eigen organisatie – en stelt vast dat elke canonieke leesactie op bronnen van een andere organisatie 403, 404 of een leeg resultaat oplevert, en dat elke canonieke wijziging wordt geweigerd terwijl de rij van die andere organisatie ongemoeid blijft. Ze dekt kanalen, goedkeuringen, het auditlogboek, triggers, agents en hun koppelingen, runs, projecten, taken, threads, verbindingen, workflowinstallaties, MCP-instanties, de kennisbank en meldingen.
Om over het mechanisme precies te zijn: dit is afdwinging op applicatieniveau plus foreign keys, geen row-level security van PostgreSQL. Er is geen RLS-beleid en geen vangnet aan de databasekant, en de conformiteitssuite draait tegen een getrouwe in-memory store in plaats van tegen een echte database, dus ze bewijst de scope-clausules die de code schrijft en niet de SQL die een server uitvoert. De repository zegt dat in de eigen documentatie van de suite, en deze pagina zegt het ook.
Het auditspoor
Elke ingrijpende handeling wordt vastgelegd: wie handelde en in welke hoedanigheid – een persoon, een agent, een dienst –, wat die deed, met welke bron, in welke organisatie, welk project, team of kanaal, of de handeling is gelukt of geweigerd, waarom, en met welke request-ID, welk adres en welke user agent het verzoek binnenkwam.
Het logboek is van nature alleen aan te vullen en er is geen manier om er van buitenaf naar te schrijven: POST /api/audit-log bestaat niet, en dat is bewust. Vermeldingen zijn aan elkaar geschakeld – elke vermelding draagt een SHA-256-digest van haar eigen canonieke velden plus de digest van de vorige vermelding van die organisatie – zodat een gewijzigde of verwijderde rij de keten breekt en dat te ontdekken is. Een eigenaar of beheerder van de organisatie kan die keten op verzoek doorlopen en krijgt te horen waar ze voor het eerst brak, als dat gebeurde.
Twee eerlijke kanttekeningen. De keten maakt manipulatie van het logboek aantoonbaar, niet onmogelijk: er is geen intrekking van schrijfrechten op databaseniveau en geen write-once-opslag achter, dus de garantie is detectie, geen preventie. En vermeldingen worden standaard onbeperkt bewaard – configureerbare bewaartermijnen met export vóór verwijdering zijn ontworpen, niet gebouwd. Vermeldingen mogen bovendien geen geheimen of volledige request bodies bevatten, en een vaste set gevoelige metadataveldnamen wordt bij binnenkomst afgeschermd.
Het kostenregister
Elke aanroep van een model wordt vastgelegd bij de organisatie, en bij de gebruiker, het team, het project, het kanaal, de agent en de run waar de aanroep vandaan kwam, met de verbruikte tokens en naast elkaar zowel de door de provider gerapporteerde kosten als de eigen schatting van Nessie. Een meetwaarde die een provider niet rapporteert, wordt als null opgeslagen en niet geraden. Rapporten kunnen worden gelezen door een eigenaar of beheerder van de organisatie.
Dit register is operationele telemetrie – wat een organisatie heeft uitgegeven en namens wie. Het is geen factuur en geen autoriteit voor facturering.
Derde partijen, wanneer je het gehoste product gebruikt
Een gehoste implementatie praat met een kleine, vaste set diensten. Modelverkeer en webzoekopdrachten gaan niet rechtstreeks naar providers: beide verlaten het systeem via één gateway van UnlikeOtherAI, en daar zitten de modelproviders en zoekproviders erachter. Inloggen en facturering gaan naar de authenticator van UnlikeOtherAI. De kluis voor geheimen wordt zelf gehost naast de applicatie. Door de server aangemaakte videogesprekslinks gebruiken standaard de openbare Jitsi-dienst.
Vrijwel al het andere staat uit tot een beheerder het configureert, en meldt dat ook in plaats van stilletjes te falen: gekoppelde Google-, Microsoft- en Slack-accounts; agent-e-mail via Amazon SES, die een implementatie in een eigen account draait zonder tussenpersoon; mobiele en browserpushmeldingen; connectoren voor onderzoek en bordbronnen; cloudbrowsers. Twee details zijn het vermelden waard, omdat ze veranderen waar data naartoe gaat:
- Gekoppelde mailboxen blijven bij je eigen provider. Mail wordt live bij je provider gelezen, via IMAP en SMTP of de eigen inlog van de provider; Nessie bewaart de verzegelde inloggegevens en verder niets over het account. Een mailbox die je aan de klantinbox koppelt, is de uitzondering: je vraagt dan om de gesprekken bij elke klant te bewaren, dus ze worden gekopieerd.
- Spraakgesprekken in de app lopen niet via Nessie. De API verzorgt een credential en de client opent zelf de audioverbinding. Dicteren en telefoongesprekken werken anders: hun audio gaat via Nessie naar de spraak- en modelproviders die haar verwerken.
Een detail bij inferentie volgt hetzelfde principe: ondertekende headers met de identiteit van de aanroeper worden alleen naar de geconfigureerde chathost gestuurd, zodat het richten van embeddings op een ander eindpunt dat eindpunt nooit een delegatieverklaring geeft over de persoon wiens tekst wordt omgezet in embeddings.
Het gehoste product gebruikt meerdere inferentieproviders en kiest daartussen op kosten en kwaliteit. Een organisatie kan straks in Admin kiezen welke providers haar agents mogen gebruiken: alleen westerse, alleen Europese, alleen Chinese, of geen voorkeur — de efficiëntste provider voor elke taak. Een zelfgehoste instantie kiest zelf.
Zelf draaien verandert dit allemaal
Elke derde partij hierboven is op een zelfgehoste instantie een configuratiekeuze. Inferentie kan worden gericht op elk OpenAI-compatibel eindpunt, ook een op je eigen hardware. De connectoren staan uit tenzij je ze aanzet. Inloggen met UnlikeOtherAI is het ondersteunde pad, en een implementatie zonder enige identiteitsprovider draait als één ongebonden organisatie met een bootstrap-eigenaar.
Dat is de bedoeling van de hele opzet: de software is dezelfde, en de beslissingen over waar ze draait en wat ze mag bereiken, zijn aan wie haar draait. Hoe, staat op de installatiepagina.