06 · 볼트
코어는 원본을 버립니다. 그런데 원본이 다시 필요할 때가 있습니다.
원본을 보관할 수 있는 곳은 여기 한 곳뿐이며, 쉽게 보관하지 못하도록 설계했습니다.
부딪히는 요구
둘 다 옳지만 서로 부딪히는 두 규칙
코어의 약속
매치된 평문을 한 번도 저장하지 않고 탐지하고 가립니다. 탐지 결과에는 유형과 범위만 남습니다. 남긴 것이 없으니 훔쳐 갈 것도 없습니다.
실제 요구 사항
에이전트가 고객 카드 번호를 가린 채 답을 받았는데, 이제 실제로 주문을 넣어야 합니다. 어디선가는 값을 되돌려 놓아야 합니다.
구조
영수증을 남기고 가리기
승인된 값이 승인된 목적지로
다른 곳으로는 가지 않습니다.
핵심 규칙
토큰만으로는 아무것도 할 수 없습니다
설계 전체가 이 원칙에 기대고 있습니다. 영수증을 가졌다고 원본을 찾아갈 권한이 생기지는 않습니다. 복원할 때 서버 연동은 누가 왜 요청하는지를 모델이 한 말이 아니라 신뢰할 수 있는 런타임 컨텍스트에서 판단합니다.
- 주체. 인증된 어떤 신원이 요청하는지.
- 테넌트. 다른 테넌트의 값은 조회되지 않습니다.
- 출처. 캡처가 어디서 왔는지.
- 싱크와 정확한 경로. 어느 목적지의 어느 구조 필드인지.
- 목적. 무엇에 쓰는지. 애플리케이션이 선언합니다.
- 유효성. 만료, 폐기, 사용 한도, 실제로 발급된 토큰인지.
일부러 막아 둔 함정
눈에 보이는 라벨은 열쇠가 아닙니다
코어는 안전한 메타데이터로 <JWT_1> 같은 유형별 자리표시자를 만들 수 있고, <PII_JURISDICTION_US_SSN_1> 같은 개인정보 유형도 마찬가지입니다. 이런 라벨을 보면 값을 보관했다는 증거로 여기기 쉽습니다.
권한 없음
유형별 표시용 자리표시자는 코어가 만든 것이든 <SSN_1> 같은 애플리케이션 라벨이든 표시 형식일 뿐입니다. 원본을 보관했다거나 복원할 수 있다는 뜻이 아닙니다.
복원 가능성
발급된 볼트 토큰과 함께 싱크와 정확한 경로를 지정한 애플리케이션 승인이 있어야 합니다. 복원 과정은 표시용 자리표시자를 소유권 증거로 해석하지 않습니다.
모델은 언제든 출력에 <SSN_1>을 적을 수 있으므로 이 구분이 중요합니다. 모델 출력, 도구 인자, 화면에 보이는 자리표시자로는 스스로 복원을 승인할 수 없습니다.
보관할 수 있는 것
모두 보관하지는 않습니다
- 차단
- 코어가
block으로 판정한 개인 키 자료는 어떤 경우에도 복원 가능한 항목이 될 수 없습니다. 직접 켜거나 설정으로 바꿀 수도 없습니다. - 그 밖의 탐지 결과
- 보관하려면 대상 여부를 명시적으로 정해야 합니다. 보관은 직접 켜는 기능이며 다른 동작에 딸려 일어나지 않습니다.
- 개인정보
- 애플리케이션이 캡처 허용 목록
pii: { retain: […] }에 정확한 유형을 적은 경우에만 보관합니다. 나머지 개인정보 탐지 결과는 모두 복원할 수 없는 표시용 자리표시자가 됩니다.
구성 요소
출시 둘, 연구용 하나, 문서만 있는 것 하나
@redact-secret/vault
어디서나 쓸 수 있는 부분입니다. 직접 켜야 동작하고 범위가 제한된 인메모리 캡처와 토큰 수명 주기를 제공합니다. Node.js 20/22/24와 브라우저 메인 스레드에서 검증했고, 선택 사항인 전용 Worker 모드는 따로 검증했습니다. Worker 모드로 바꾼다고 저절로 더 안전해지지는 않으며, 두 모드의 보장 범위는 문서도 따로 있습니다.
@redact-secret/vault-server
권한 계층입니다. 복원할 때마다 주체·테넌트·출처·싱크·경로·목적을 검사하며, 위 패키지를 기반으로 한 인메모리 백엔드를 제공합니다. Node.js 20/22/24에서 테스트합니다.
redact-secret-vault (Python)
연구 단계입니다. 이식용 볼트 API가 아니라 같은 서버 권한 계약을 Python으로 직접 구현했습니다. 문서화된 Node.js 서비스 경계를 거쳐 실제 코어와 함께 공용 적합성 테스트 모음을 통과합니다.
@redact-secret/store-*
영구 저장 백엔드. 계약 문서는 있지만 구현은 없습니다. 영구 저장은 저장 방식의 선택일 뿐, 세 번째 신뢰 환경이 아닙니다.
npm 패키지 이름 때문에 JavaScript 전용으로 보일 수 있지만 그렇지 않습니다. 서버 보안 계약은 언어와 무관하며, Python·Rust·Go는 각각 네이티브 배포판이나 별도로 검증한 서비스 경계가 필요합니다.
솔직하게