ARCHITECTURE · brain

brain architecture

brain은 SpiceDB·RDB를 대체하는 온프렘 시큐어 데이터 레이어이자 neunexus 생태계의 RAG(검색 증강 생성) + 온톨로지 서비스입니다 — 문서를 청크·임베딩해 벡터+그래프+전문검색을 임베디드 SurrealDB 하나에 담는 Rust gRPC 서비스로, whoami·cogito 등 내부 서비스가 근거 검색(RAG)과 엔티티 간 관계(assigned_to/child_of/blocks/depends_on 등, 온톨로지형 그래프)의 동기화에 씁니다. dense(usearch)+sparse(BM25) 하이브리드 검색을 RRF로 융합하고, 코드 저장소 인덱싱과 문서 간 연계 추적까지 겸합니다.

왜 필요한가

OKMART 작업 당시 내부 데이터 관리를 위키만으로 하기엔 검색에 한계를 느껴 찾아본 RAG·온톨로지 결합형 프로젝트입니다. 온톨로지(데이터 링크)를 통해 데이터 추적과 관리가 쉬워질 수 있다고 봤습니다.

00

이 프로젝트는 무엇이고 왜 존재하는가

authored from source

brain은 SpiceDB·RDB를 대체하는 온프렘 시큐어 데이터 레이어입니다. 클라이언트가 gRPC로 문서를 넣으면(ingest) SurrealDB(임베디드, vector+graph+FTS 멀티모델)에 저장하고, 임베딩은 in-cluster Ollama(bge-m3)를 호출합니다.

brain overview: client calls brain via gRPC, brain embeds via Ollama and reads/writes SurrealDB

brain / overview.yaml

01

누가, 어떻게 brain에 닿는가

deploy/k8s/deployment.yaml → BRAIN_AUTH_SERVICE_SUBS

실제 호출 주체는 배포 매니페스트의 BRAIN_AUTH_SERVICE_SUBS(신뢰 서비스 목록)로 확인했습니다 — brain-iim, cogito-svc(jaso 근거검색), whoami-svc(entity sync), brain-viewer(metaviewer proxy), oikonomos-session(asset-registry ingest) 5개입니다.

brain context: 5 real callers (brain-iim, cogito-svc, whoami-svc, brain-viewer, oikonomos-session) call brain via gRPC; brain calls Ollama for embedding and an IdP for JWKS

brain / context.yaml

02

Rust 모듈 내부는 어떻게 나뉘는가

src/lib.rs + main.rs

src/lib.rs의 flat mod 목록과 main.rs의 실제 서비스 등록 순서를 그대로 반영했습니다. auth(JWT/JWKS 인터셉터)가 4개 서비스(ingest/search/access/graph)를 게이트하고, extraction만 인터셉터 없이 직결됩니다.

brain component structure: main gRPC server routes through an auth interceptor to ingest/search/access/graph services, extraction bypasses auth, all converging on tenant/authz/vector/SurrealDB

brain / structure.yaml

03

어느 클러스터, 어느 경로로 뜨는가

deploy/k8s/*.yaml

goquest와의 핵심 차이 — deploy/k8s/에 Ingress가 없습니다. brain은 클러스터 내부 전용(gRPC, in-cluster DNS로만 접근)이며 외부 LB 경로가 없습니다.

brain network topology: in-cluster callers reach a ClusterIP Service routing to the brain Deployment, which persists to a PVC and mounts ConfigMaps

brain / network.yaml

04

데이터는 어떤 구조로 저장되는가

proto/brain.proto + tenant.rs (전체 확인)

brain에는 관계형 스키마가 없습니다(SurrealDB embedded, multi-model doc+graph+KV) — tenant.rs(2183줄) 전체와 테스트 코드를 통독해 실제 테이블 15개와 엣지 7종(from/to 확정)을 찾아 논리적 노드/엣지 다이어그램으로 그렸습니다. assigned_to/child_of/blocks/depends_on/duplicates 5종은 스키마만 정의돼 있고 target 테이블이 코드에 고정돼 있지 않아(호출자가 런타임에 지정) 화살표로 그리지 않았습니다.

brain logical data model: 15 SurrealDB tables including document, chunk, term, user, query_log, repo-scoped code index tables, and dimension hub tables, connected by 7 confirmed edge types (can_view, part_of, mentions, mentions_term, references, created_by, synonym_of)

brain / erd.yaml

05

커밋이 어떻게 배포로 이어지는가

toji-ci/ci-repos/brain.yaml

toji-ci 설정에 명시된 확정 사실만 표기했습니다 — manifest writeback(toji-cd bots/brain)이 CI에 정의돼 있고, Docker 빌드 스테이지 안에서 테스트 후 빌드가 실행됩니다.

brain CI/CD pipeline: git push triggers toji-ci Tekton, which builds+tests in a Docker stage, pushes to the registry, and writes manifests back to toji-cd ArgoCD, which syncs to K8s ns:brain

brain / cicd.yaml

06

시크릿은 어디서 와서 어떻게 파드에 들어가는가

deploy/k8s + Tekton

goquest와 달리 앱 레벨 시크릿(DB 비밀번호, 임베딩 API 키)이 없습니다 — SurrealDB는 embedded이고 Ollama 호출도 인증이 없습니다. Vault로 동기화되는 건 레지스트리 pull 자격증명과 Tekton geneso read token 두 가지뿐입니다.

brain secrets flow: a ServiceAccount authenticates to VSO which syncs Vault registry credentials into an image pull secret, and a separate Tekton secret carries a geneso read token

brain / secrets.yaml

07

요청 하나가 어떤 계층을 통과하는가

main.rs (tonic Server builder)

main.rs의 실제 tonic Server 배선 그대로 — 4개 서비스는 gRPC-Web + JWT 인터셉터를 거치고, ExtractionService만 인터셉터를 완전히 우회합니다(비인증, startup 로그에 명시).

brain API request pipeline: gRPC request passes through a JWT interceptor to a handler, tenant resolution, and SurrealDB; ExtractionService bypasses the interceptor entirely

brain / api-layers.yaml

08

gRPC 서비스는 어떤 그룹으로 나뉘는가

proto/brain.proto

proto/brain.proto의 실제 6개 service 블록 그대로입니다 — IngestService, SearchService, AccessService, GraphService, ExtractionService. 각 rpc 이름은 코드에서 직접 확인했습니다.

brain gRPC service groups: brain.proto branches into IngestService, SearchService, AccessService, GraphService, and ExtractionService, each listing its real rpc names

brain / api-endpoints.yaml

09

문서 수집(ingest) 요청은 어디를 거치는가

src/ingest.rs → IngestDocument

src/ingest.rs의 IngestDocument RPC 실제 코드 흐름을 요약했습니다. archview에 도형 개념이 없어 색상 카테고리 박스로 근사했고, 원본 11단계를 핵심 7단계로 접었습니다.

brain ingest dataflow: an IngestDocument request flows through chunking, embedding, and extraction before being written to SurrealDB

brain / dataflow-ingest.yaml

rendered via archview · d2lang/d2 · ELK layout