nessie

EU에서 만들어졌고, 데이터가 머무는 곳

Nessie가 어디에서 만들어지는지, 데이터가 어디에 저장되는지, 직접 호스팅할 때 무엇을 직접 관리할 수 있는지 설명합니다.

누가 만들고, 어느 나라 법을 따르는가

Nessie는 체코에 등록되어 체코 법에 따라 운영되는 회사 UnlikeOtherAI s.r.o.가 만듭니다.

이 페이지는 소프트웨어가 어떻게 만들어졌고 어디에서 실행되는지를 설명하는 글입니다. 규정 준수 확인서가 아닙니다. Nessie는 어떠한 보안 인증도 보유하고 있지 않으며, 이 페이지의 어떤 내용도 인증으로 해석해서는 안 됩니다. 어떤 개인정보를 어떤 근거로 처리하는지는 별도 페이지인 개인정보 처리방침에서 다룹니다.

호스팅 제품이 실행되는 곳

Nessie Cloud는 Scaleway, Hetzner 등 유럽의 호스팅 제공자에서 실행됩니다. 각 제공자가 내놓는 가장 좋은 서비스를 골라 쓰므로 제품의 부분마다 다른 제공자에서 실행될 수 있으며, 모두 유럽 안에 있습니다.

특정 사이트, 도시, 데이터센터처럼 이보다 더 구체적인 정보는 일부러 적지 않았습니다. 아무도 모르는 사이에 내용이 낡아 버릴 수 있기 때문입니다.

직접 호스팅하면 선택권은 여러분에게 있습니다

직접 호스팅하는 인스턴스가 어디에서 실행되는지는 제품 설정이 아니라 배포 설정입니다. 단일 머신 방식은 여러분이 고른 머신에 올리는 Docker Compose 스택입니다. 관리형 클라우드용 Terraform 구성에서는 리전이 기본값이 전혀 없는 입력값입니다. 추측할 수 있는 것이 없으니 기본값도 없으며, 데이터베이스, 오브젝트 스토리지 버킷, 서비스는 모두 여러분이 지정한 리전을 따릅니다.

같은 질문과 관련해 구조상 중요한 점이 두 가지 더 있습니다. 큐와 실시간 전송 계층은 둘 다 PostgreSQL입니다. 경로에 Redis도 메시지 브로커도 없으므로 따로 배치해야 할 세 번째 시스템이 없습니다. 그리고 오브젝트 스토리지는 특정 벤더에 묶이지 않은 S3 호환 방식입니다. 참조 배포에서는 자체 외부 진입 경로가 없는 사설 네트워크의 컨테이너에서 MinIO를 실행합니다. 어딘가에 있어야 하는 구성 요소는 데이터베이스, 오브젝트 스토어, Node 서비스 두 개이며, 모두 여러분이 둔 곳에 있습니다. 구축 방법은 설치 페이지에 있습니다.

Nessie가 보관하는 것, 그리고 일부러 보관하지 않는 것

신원 정보는 복사하지 않습니다

UnlikeOtherAI 로그인을 사용하면 사람의 신원은 ID 제공자가 관리하고 저장합니다. 인증 수단, 프로필, 조직 및 팀 구성원 정보, 초대가 여기에 해당합니다. Nessie는 두 번째 ID 시스템이 아니라 신뢰하는 당사자(relying party)입니다. 이것은 아키텍처의 결정이면서 데이터에 대한 결정이기도 합니다. Nessie가 저장하지 않는 신원 정보는 유출할 수도, 분실할 수도, 삭제를 빠뜨릴 수도 없기 때문입니다.

users 테이블에 실제로 남는 것은 제공자의 고정 사용자 식별자(다른 모든 정보를 찾아가는 키), 이메일 주소, 공식 기준이 아닌 표시 이름과 아바타 사본, 그리고 제품 내부 필드(환경설정, 호칭 대명사, 세션을 폐기하는 데 쓰는 토큰 버전)입니다. 이 사본은 행마다 요청하지 않고도 이름과 사진을 표시하기 위한 것일 뿐이며, 로그인할 때, 팀을 전환할 때, 세션을 갱신할 때 제공자가 검증한 클레임으로 다시 동기화됩니다. 값을 임의로 만들어 내지 않습니다. 제공자에 이름이 등록되지 않은 사람은 등록될 때까지 이메일 주소로 표시됩니다. 비밀번호 해시는 ID 제공자가 전혀 없는 설치본의 초기 소유자에게만 존재합니다.

구조도 마찬가지입니다. 제공자의 조직 하나는 Nessie의 조직 하나이며, 제공자의 조직 ID로 연결됩니다. 상위 연결이 없는 팀은 로컬에서 추측해 대신하지 않고 404 TEAM_NOT_LINKED로 응답하며, 실시간 명단 조회는 ID 제공자로 보내질 뿐 아무것도 저장하지 않습니다.

아직 없애지 못한 사본이 두 가지 있으며, 그렇지 않은 것처럼 말하면 정직하지 못한 일입니다. 조직과 팀의 이름은 연결 ID와 함께 아직 로컬에 저장되어 있고, 로컬 구성원 행이 동기화 사이에 일반 요청의 권한을 아직 결정합니다. 두 가지를 제거하는 일은 이미 끝난 일이 아니라 저장소에서 추적 중인 진행 예정 작업입니다.

결제 관련 정보는 없습니다

결제는 중앙 결제 서비스가 관리합니다. Nessie는 결제 업체의 고객, 구독, 청구서, 가격, 크레딧 잔액, 충전 정책, 결제 동의, 명세서, 해지 상태를 저장하지 않으며 요금도 계산하지 않습니다. 표시용으로 준비된 값을 받아 보여 줄 뿐입니다.

시크릿

시크릿을 저장하려면 설정된 볼트가 반드시 필요합니다. 데이터베이스 대체 경로도, 평문 경로도 일부러 두지 않았습니다. 볼트가 없으면 시크릿을 저장하거나 교체하거나 폐기할 때 덜 안전한 방식으로 처리하는 대신 오류가 반환됩니다. 시크릿에 대한 Nessie 자체 기록에는 값도, 암호문도, 키도, 볼트 토큰도 없고 불투명한 참조와 메타데이터만 있습니다. 볼트 경로는 구조적 식별자만으로 만들어지며 조직, 팀, 프로젝트, 개인의 이름은 쓰이지 않습니다.

OAuth 클라이언트로 동작하기 위해 Nessie가 직접 보관해야 하는 자격 증명(커넥터와 메일함 자격 증명, 웹훅 시크릿, 세션 갱신 자료, 실행기 페이로드)은 용도별로 구분된 AES-256-GCM 봉투로 봉인되며, 세션 서명 시크릿과는 별개의 루트인 버전 관리 키 링을 사용하고 문서화된 교체 절차가 있습니다.

모델에 관한 규칙도 있습니다. 시크릿이 존재한다는 사실을 알 수 있고 사용이 승인될 수는 있지만, 시크릿 자체는 모델 컨텍스트, 프롬프트, 도구 인수, 도구 결과, 메모리, 임베딩, 검색, 로그, 메시지에 들어가서는 안 됩니다. 에이전트에게는 시크릿을 사용할 권한을 줄 수 있어도, 시크릿을 공개할 권한은 줄 수 없습니다.

기반 디스크가 암호화되어 있는지는 배포가 실행되는 머신의 특성입니다. 저장소는 데이터베이스와 오브젝트 스토리지 볼륨의 볼륨 수준 암호화를 보장하지 않으므로, 이 페이지에서도 그렇다고 주장하지 않습니다.

테넌트 격리

Nessie는 설계상 멀티테넌트입니다. 데이터베이스는 하나이고, 모든 행은 정확히 하나의 조직에 속하며, 모든 하위 테이블에 organization_id가 있습니다. 격리는 두 곳에서 적용됩니다. 모든 쿼리에 붙는 범위 조건, 그리고 이 컬럼의 실제 외래 키입니다. 외래 키는 내부 감사에서 수십 개 테이블에 컬럼은 있으나 제약이 없다는 사실이 확인된 뒤 마흔두 개의 제약 조건으로 추가되었습니다.

적합성 테스트 모음이 HTTP 경계에서 이 불변 조건을 지킵니다. 이 테스트는 최대 권한을 가진 공격자, 즉 자기 조직의 완전한 소유자를 만들어, 다른 조직의 리소스에 대한 모든 표준 읽기가 403, 404 또는 빈 결과로 응답하는지, 모든 표준 변경이 거부되고 다른 조직의 행이 그대로 남는지 확인합니다. 대상은 채널, 승인, 감사 기록, 트리거, 에이전트와 그 바인딩, 실행, 프로젝트, 작업, 스레드, 연결, 워크플로 설치, MCP 인스턴스, 지식 베이스, 알림입니다.

방식을 정확히 말씀드리면, 이것은 애플리케이션 수준의 적용과 외래 키이며 PostgreSQL의 행 수준 보안(RLS)이 아닙니다. RLS 정책도 데이터베이스 측의 보완 장치도 없습니다. 또한 적합성 테스트는 실제 데이터베이스가 아니라 충실하게 만든 인메모리 저장소를 대상으로 실행되므로, 서버가 실행하는 SQL이 아니라 코드가 작성하는 범위 조건을 검증합니다. 저장소의 테스트 문서에도 이렇게 적혀 있으며, 이 페이지도 같은 내용을 밝힙니다.

감사 추적

영향이 있는 모든 작업이 기록됩니다. 누가 어떤 자격(사람, 에이전트, 서비스)으로 행동했는지, 무엇을 했는지, 어느 리소스에 했는지, 어느 조직, 프로젝트, 팀 또는 채널에서 했는지, 성공했는지 거부되었는지와 그 이유, 그리고 요청 ID, 주소, 사용자 에이전트가 함께 남습니다.

로그는 설계상 추가만 가능하며 외부에서 쓸 방법이 없습니다. POST /api/audit-log는 존재하지 않으며, 이것은 의도한 것입니다. 항목은 체인으로 연결됩니다. 각 항목에는 자신의 표준 필드에 대한 SHA-256 다이제스트와 해당 조직의 이전 항목 다이제스트가 들어 있으므로, 수정되거나 삭제된 행은 체인을 끊어 탐지할 수 있습니다. 조직의 소유자나 관리자는 언제든 이 체인을 검증할 수 있으며, 끊어졌다면 처음 끊어진 위치를 알려 줍니다.

솔직하게 밝혀야 할 단서가 두 가지 있습니다. 체인은 로그를 변조가 드러나게 할 뿐 변조를 막지는 못합니다. 그 뒤에 데이터베이스 수준의 쓰기 권한 회수나 쓰기 한 번만 가능한 저장소가 없으므로, 보장되는 것은 방지가 아니라 탐지입니다. 그리고 항목은 기본적으로 무기한 보관됩니다. 삭제 전 내보내기를 포함한 보관 기간 설정은 설계되어 있을 뿐 구현되지는 않았습니다. 항목에는 시크릿이나 요청 본문 전체를 담을 수 없으며, 정해진 민감 메타데이터 필드명은 기록 시점에 가려집니다.

비용 원장

모든 모델 호출은 조직 단위로, 그리고 그 호출을 일으킨 사용자, 팀, 프로젝트, 채널, 에이전트, 실행 단위로 기록됩니다. 소비한 토큰과 함께 제공자가 보고한 비용과 Nessie 자체 추정치를 나란히 보관합니다. 제공자가 보고하지 않는 항목은 추측하지 않고 null로 저장합니다. 보고서는 조직의 소유자나 관리자가 열람할 수 있습니다.

이 원장은 운영 텔레메트리, 즉 조직이 누구를 위해 얼마를 썼는지를 보여 주는 기록입니다. 청구서가 아니며 청구의 기준도 아닙니다.

호스팅 제품을 쓸 때 관여하는 외부 업체

호스팅 배포는 정해진 소수의 서비스와만 통신합니다. 모델 트래픽과 웹 검색은 제공자에게 직접 가지 않고, UnlikeOtherAI가 운영하는 하나의 게이트웨이를 거쳐 나가며 상위 모델 및 검색 제공자는 그 뒤에 있습니다. 로그인과 결제는 UnlikeOtherAI의 인증 서비스로 갑니다. 시크릿 볼트는 애플리케이션과 함께 직접 호스팅합니다. 서버가 만드는 화상 통화 링크는 기본적으로 공개 Jitsi 서비스를 사용합니다.

그 밖의 거의 모든 것은 운영자가 설정하기 전까지 꺼져 있으며, 조용히 실패하는 대신 꺼져 있다고 알려 줍니다. 연결된 Google, Microsoft, Slack 계정, 중간 업체 없이 배포 환경이 자체 계정에서 운영하는 Amazon SES 기반 에이전트 이메일, 모바일 및 브라우저 푸시, 리서치 및 보드 소스 커넥터, 클라우드 브라우저가 그렇습니다. 데이터가 가는 곳을 바꾸므로 밝혀 둘 만한 사항이 두 가지 있습니다.

  • 연결된 메일함의 데이터는 여러분의 제공자에게 남습니다. 메일은 IMAP과 SMTP, 또는 제공자 자체 로그인을 통해 제공자에서 실시간으로 읽습니다. Nessie는 봉인된 자격 증명만 저장하며 계정에 관한 다른 정보는 저장하지 않습니다. 고객 받은편지함에 연결하는 메일함은 예외입니다. 그 대화를 고객별로 함께 보관해 달라고 요청하는 것이므로 복사해 들여옵니다.
  • 앱 안의 음성 통화는 Nessie를 거치지 않습니다. API가 자격 증명을 중개하고 클라이언트가 직접 오디오 연결을 엽니다. 받아쓰기와 전화 통화는 다릅니다. 이 경우 오디오는 Nessie를 거쳐, 이를 처리하는 음성 인식 및 모델 제공자에게 전달됩니다.

추론에도 같은 원칙이 적용되는 사항이 하나 있습니다. 서명된 호출자 ID 헤더는 설정된 채팅 호스트로만 전송되므로, 임베딩을 다른 엔드포인트로 지정해도 텍스트가 임베딩되는 사람에 대한 위임 증명이 그 엔드포인트에 전달되지 않습니다.

호스팅 제품은 여러 추론 제공자를 사용하며, 비용과 품질에 따라 그중에서 고릅니다. 조직은 관리자 화면에서 에이전트가 사용할 수 있는 제공자를 선택할 수 있게 될 예정입니다. 서양 제공자만, 유럽 제공자만, 중국 제공자만, 또는 선호 없음 중에서 고를 수 있으며, 선호 없음이면 작업마다 가장 효율적인 제공자를 씁니다. 직접 호스팅하는 인스턴스는 스스로 선택합니다.

직접 운영하면 이 모든 것이 달라집니다

위에서 말한 모든 외부 업체는 직접 호스팅하는 인스턴스에서는 설정에 따른 선택입니다. 추론은 OpenAI 호환 엔드포인트라면 어디로든 지정할 수 있으며, 여러분의 자체 하드웨어에 있는 엔드포인트도 가능합니다. 커넥터는 켜지 않으면 꺼져 있습니다. UnlikeOtherAI 로그인이 지원되는 방식이며, ID 제공자가 전혀 없는 배포는 초기 소유자가 있는 연결되지 않은 단일 조직으로 실행됩니다.

이것이 이 구조의 핵심입니다. 소프트웨어는 같고, 어디에서 실행하고 무엇에 접근하게 할지는 운영하는 사람이 결정합니다. 방법은 설치 페이지에서 다룹니다.