← 인프라·격리

격리는 주장이 아니라 증명이다

거부돼야 하는 요청을 CI가 매번 거부해 보이지 못하면 그것은 격리가 아니라 격리 주장이다.

질문

"테넌트 격리됐다"는 말을 무엇으로 증명하는가. 권한 설계 문서로 충분한가.

판정

거부돼야 하는 요청을 게이트가 매 실행마다 거부해 보여야 격리다. 문서에 적힌 권한 표는 증명이 아니다.

근거

/Users/bkan/workspace/Hindsight-Crew 는 자체 호스팅 메모리 스택에 정책 게이트웨이를 앞단에 둔
공개 MIT 레퍼런스다. 이 리포의 성공 정의는 문장이 아니라 종료코드다.
verify/verify-all.sh0 으로 종료할 때 그리고 그때만 green 이다.

왜 게이트웨이가 필요한지가 먼저 실측으로 확인됐다. Hindsight 의 기본 인증은 단일 공유 Bearer 키
하나뿐이고 identity→bank 강제가 없다. 대상 뱅크를 클라이언트 제어 입력에서 해석한다
(URL 경로 > X-Bank-Id 헤더 > env, 그리고 contract-probe 결과 본문 arguments.bank 까지).
그래서 "클라이언트를 그냥 8888 에 붙이면 된다"는 가정은 테넌트 간 데이터를 새게 만든다
(/Users/bkan/workspace/Hindsight-Crew/docs/THREAT-MODEL.md).

게이트웨이가 유일한 강제 지점이 되도록 다음을 강제한다.

무시·제거·덮어쓴다

(MCP delete_bank/clear_memories/delete_document/update_bank 와 REST DELETE/PATCH
공유 team 뱅크에서 거부. 멤버는 team 뱅크에 retain/recall 은 계속 가능)

  • 업스트림 Hindsight 키를 게이트웨이가 보유하고 클라이언트에는 절대 전달하지 않는다
  • 뱅크를 토큰→ACL 매핑에서만 해석하고, 클라이언트가 준 URL 뱅크·X-Bank-Id·본문 arguments.bank
  • 기본 거부. (method, tool_name, target_bank) 가 토큰 ACL 과 맞을 때만 통과하고 그 외는 전부 403
  • 열거용 루트 멀티뱅크 /mcp/ 를 차단하고, 파괴적 연산은 소유자의 personal 뱅크로 제한한다
  • team retain 의 귀속 필드를 토큰 신원으로 덮어쓴다. 멤버가 귀속을 위조할 수 없다

그리고 그 거부를 게이트가 매번 실행해 보인다.
/Users/bkan/workspace/Hindsight-Crew/verify/gate5_adversarial.sh 는 6개 부정 케이스에 전부 403
요구하고, 하나라도 다르면 실패로 종료한다.

  • 토큰 없음 / 미상 토큰의 recall
  • A 토큰으로 B 의 personal 뱅크 recall (cross-tenant)
  • 뱅크 컬렉션 열거 GET /v1/<tenant>/banks
  • 경로 traversal %2e%2e
  • 공유 team 뱅크에 대한 파괴적 DELETE

verify-all.sh 는 이 게이트를 9엔트리 오케스트레이터의 한 칸으로 돌린다(① health ② banks
③ roundtrip ④ isolation+attribution ⑤ adversarial ✦ contract-drift ⑦ MCP enforcement
⑧ rerank provider ⑥ restore). 어느 하나가 FAIL 이거나 NOT_IMPLEMENTED 면 전체가 비영 종료다.
2026-07-26 ko-full-mac-mps 구성에서 9/9 GREEN 을 재확인했다
(근거 아티팩트: artifacts/verify-all-9gates-20260726.out).

증명의 반대편, 즉 증명하지 못하는 것도 문서에 박아뒀다. 자세는
honest-but-curious 로 명시하고 잔여 위험을 나열한다. 호스트 로컬 8888 우회, 클라이언트-게이트웨이
구간 전송 암호화 부재, 애플리케이션 레이어 append-only 감사 로그(변조 방지 저장소 아님),
그리고 2026-07-26 리랭커 사이드카 도입으로 생긴 host-local 평문 채널이다.
그 무인증 사이드카는 loopback 단독 바인드이고 비루프백 기동 자체를 거부하며,
컨테이너에서는 200, 호스트 en0(172.30.1.14)에서는 거부됨을 실측했다(AC-B2).
로컬 DoS 봉투도 코드 기본값으로 고정했다(MAX_QUEUE_DEPTH=3, RERANK_MAX_TEXTS=256,
RERANK_TOTAL_DEADLINE_SECONDS=7.5, 사이드카 테스트 35건 GREEN).

요구사항 수치도 추정이 아니라 실측이다. ko-full 프로파일 런타임 RAM 약 1.5~2.1 GB(hindsight)
+ 약 59 MB(gateway), 디스크 약 14 GB, 필요 RAM 약 4 GB 이상. 경량 cpu-en 은 런타임 약 0.85 GB RAM,
디스크 약 7 GB 로 2 GB Docker VM 에서 구동된다.

같은 요건을 실무에서도 통과했다. 보안 요건상 외부 클라우드 LLM API 를 쓸 수 없는 고객사 환경에서
Mac Studio 15대에 역할을 나눠 배정하고 Tailscale 독립망으로 묶어 외부 노출 없이 LLM 을 자체 서빙했다.
격리를 주장으로 파는 대신 도달 불가를 구조로 만들었다.

공개 리포: https://github.com/Bkankim/Hindsight-Crew

한계·재검토 트리거

게이트웨이가 "유일한 강제 지점"인 것은 네트워크 노출 경계에서만 참이다. 호스트에서 내부 도커
네트워크나 업스트림 키에 닿을 수 있는 프로세스·사용자는 게이트웨이를 우회한다.
이것은 honest-but-curious 자세에서 수용한 v1 범위이고, 악의적 행위자에 대한 방어를 주장하지 않는다.
9/9 GREEN 은 ko-full-mac-mps 구성의 관측이며, cpu-en 은 게이트 ⑦⑧ 추가 이후 재측정하지 않았다.

2026-08 기준 / 재검토 트리거: (1) mTLS 또는 뱅크별 업스트림 키가 들어가면 위협 등급이 올라가
이 판정의 범위 문장을 다시 쓴다. (2) verify-all.sh 게이트 수가 바뀌거나 어느 게이트가
NOT_IMPLEMENTED 로 내려가면 위 9/9 인용을 폐기한다. (3) 사이드카가 loopback 밖으로 나가면
잔여 위험 목록을 재작성한다.