ADR 0015 — Tenant 격리 AI 학습 · Phase 1b 레이어 적층
결정문
Phase 1b (사무실 기억 · 종이 스캔 업로드) 를 Phase 1 S2 (7~10M) 에 착수한다. 세 원칙을 지키며 PR-1~8 순차 머지:
- Tenant 격리 AI 학습: 각 사무소 데이터로 그 사무소 AI 가 학습·활용. "학습" 의 실체는 fine-tuning 이 아닌 tenant-isolated 임베딩 + RAG (
tenants/{tid}/legacyDocs.embedding+ Firestore Vector SearchfindNearest). cross-tenant 유통·교차 학습은 절대 금지. - 출시 우선: 기능 Go 게이트는 "지금 없으면 법적으로 출시 불가"만 통과. 나머지는 레이어로 이동.
- 레이어 적층: S2 → S3 → S4 순차 강화. 박스 대량 UX · 비식별화 고도화 · 법무 자문 서면 회신은 S3 이후.
기존 ADR 0011 S2 범위 (어댑터 레이어 · DPIA 기술 작업) 는 유지하되, 본 ADR 이 Phase 1b 레이어 적층 을 추가한다 (충돌 없음).
배경
- ideations/014 R1~R3 3회차 회의 산출물.
- R2 과정에서 Chair 피드백 2회 개입:
- 1차: "출시 우선, 보안·규제는 레이어 적층" → Go 게이트 3항목 (1a 텔레메트리 14일 실측 · 법무 서면 회신 · 비식별화 선행) 과적으로 판정, 회귀 테스트만 선행으로 완화.
- 2차: "AI 학습은 당연, tenant 별 완전 격리" → "AI 학습" 의 기술 정의를 fine-tuning 배제 + tenant-isolated 임베딩 + RAG 로 확정.
- 기존 구조 재사용:
tenants/{tid}/legacyDocuments/*컬렉션 (Phase 0 정체성 리브랜딩 후 유지)guardedAdminCollectionGroup/guardedClientCollectionGroupcreateScannedLegacyDocAction·legacy-scanned-trigger.ts·ScannedLegacyMetaSchemafindRelatedMemoriesForDocGenAction(메타 매칭 1세대, S3 에 임베딩 2세대로 업그레이드)
대안 검토
A — Phase 1b 를 S3 로 미루기 (P3 R1 원안)
1a 텔레메트리 14일 실측 후 hit rate < 5% 이면 1b 저장량 증대 ROI 역전. 출시 지연 리스크 + 저장량 확보 없이 hit rate 개선은 메타 매칭 한계에 부딪힘. 기각.
B — Phase 1b 단독 착수, 1a 병행 금지 (P5 R1 원안)
1a 관측 대시보드 없이 1b 만 밀면 도메인 레버 식별 어려움. S2 에 관측 대시보드 병행으로 절충. 부분 채택.
C — Fine-tuning 으로 tenant 전용 LLM (Chair 2차 피드백 1안)
Gemini/Vertex 기준 tenant 당 파인튜닝 비용·관리·지연 비현실적. 체감 효과는 RAG 로 동등 달성. 기각.
D — 전면 Go 게이트 (R1 원안, 법무 서면 회신 + 비식별화 선행)
출시 수 개월 지연 가능. cross-tenant 학습 없는 내부 재활용은 수임계약서 "업무 수행 보조 + 데이터 보관" 범위 내로 해석 가능. 기각 → 레이어로 분산.
E — Tenant-isolated 임베딩 + RAG 스캐폴드 + 단건~5건 업로드 UX (R2 수렴안)
S2 범위 균형 · 회귀 테스트로 격리 회귀 방지 · 박스 UX 는 S3. 채택.
결정 + 근거
3대 원칙
1. Tenant 격리 AI 학습
| 허용 | 금지 |
|---|---|
tenants/{tid}/legacyDocs 내부 읽기·검색·임베딩 인덱스 | cross-tenant 쿼리·벡터 검색 |
findNearest(queryEmbedding, k=5) tenant path 내부 | collectionGroup("legacyDocuments") tenantId 필터 누락 |
| tenant 내부 집계·트렌드 | 원문·임베딩의 외부 반출 (모델 파인튜닝 포함) |
originalText Cloud Storage 저장 | originalText Firestore 저장 (기존 금지 재확인) |
기술 정의:
- 벡터 생성: Gemini
text-embedding-004(Firebase AI Logic) → 768-dim float array - 저장: Firestore
legacyDocuments/{docId}.embedding필드 (tenant path 하위) - 검색: Firestore Vector Search
findNearest(fieldPath, queryVector, options)— collection path 자체가 tenant scoped - 생성 시점:
legacy-scanned-trigger.tsOCR 성공 후 자동 (추가 eng-day 0.5)
2. 출시 우선
S2 진입 선행 필수 (Go 게이트 축소):
- cross-tenant 격리 자동 테스트 통과 (
guardedQuery+ 벡터 경계 계약 테스트) -
originalTextFirestore 미저장 재확인 (기존 정책) - Signed URL 15분 만료 재확인 (기존 정책)
제거된 선행 조건 (→ 레이어로 이동):
1a 텔레메트리 14일 실측→ S2 병행 관측 대시보드 (차단 아님)법무 자문 서면 회신→ S3 파일럿 확대 시비식별화 파이프라인 고도화→ S3
3. 레이어 적층
S2 (46주 · PR-18) — 지금 착수
| PR | 항목 | 주 변경 |
|---|---|---|
| 1 | cross-tenant + 벡터 경계 자동 테스트 | apps/web/lib/firebase/__tests__/tenant-vector-boundary-contract.test.ts |
| 2 | ocrStatus state machine 확장 | queued | processing | awaiting_paralegal | awaiting_lawyer | approved | failed |
| 3 | uploadBatches/{batchId} roll-up 문서 | writer + onSnapshot 1건 구독 |
| 4 | legacyAuditLogs/* 스캐폴드 | 업로드자·승인자·confidence·retryCount |
| 5 | 임베딩 자동 생성 파이프라인 | legacy-scanned-trigger.ts 확장 + text-embedding-004 |
| 6 | 리스크 차등 승인 | confidence ≥ 80% + 사건번호 정규식/파일명/바디 교차 → 사무장 단독 |
| 7 | 단건~5건 업로드 UX | Dialog + Progress |
| 8 | 1a 관측 대시보드 | relatedMemoriesEvents shown/clicked 비율 관측용 |
S3 (S2 출시 후)
findRelatedMemoriesForDocGenAction임베딩 기반 2세대 (findNearest)- 박스 대량 업로드 UX (파일럿 실측 기반 설계)
- 비식별화 파이프라인 강화 (
searchable필드 분리 · 마스킹 고도화) - 수임계약서 템플릿 업데이트 + 법무 자문 서면 회신
- Signed URL · 다운로드 텔레메트리
S4 이후
- 사무실 전역 의미 검색 독립 UX
- 요약·트렌드 집계 (tenant 내부)
- 임베딩 역공학 리스크 법적 문서화
- confidence 머신러닝 모델 교체 검토
양보 불가 선 (정책 전반)
| 역할 | 선 | 근거 |
|---|---|---|
| P5 | 자동 재시도 금지 | 중복 write 방지 · 비용 보호 |
| P5 | 벡터 쿼리 collection path scoped | 아키텍처상 cross-tenant 불가능 |
| P3 | cross-tenant 격리 + 벡터 경계 자동 테스트 | 회귀 방지 |
| 베이스라인 | originalText Firestore 금지 | PII 보호 (기존 정책 재확인) |
| 베이스라인 | Signed URL 15분 만료 | PII 보호 (기존 정책 재확인) |
| 베이스라인 | 임베딩 tenant path 외 저장 금지 | 격리 |
Minority Report
P3 PM (초기 강한 반대, 부분 관철)
"1a 텔레메트리 14일 실측 + Go 게이트 3항목 선행. 1b 단독 착수 반대." 처리: Chair 2차 피드백 "출시 우선" 에 따라 Go 게이트 완화. 1a 관측 대시보드를 S2 PR-8 로 유지하되 차단 조건 아님. 1b 단독이 아닌 병행으로 절충.
P7 보안 (초기 강한 선행 요구, 레이어로 이동)
"비식별화 파이프라인 강화 + 법무 자문 서면 회신 선행. 이게 없으면 PII 유출 리스크." 처리: 기존 베이스라인 정책 (
originalText금지 · Signed URL 15분) 이 이미 회귀 테스트로 박혀 있음. 추가 고도화는 S3 레이어로 분산. Chair 피드백 "출시 우선 · 레이어 적층" 에 정합.
P2 사무장 (초기 강한 요구, 차등 수용)
"전건 2단 승인 (사무장 + 변호사) 필수. 비밀유지 책임은 변호사 귀속." 처리: 리스크 기반 차등 채택 — confidence ≥ 80% + 사건번호 교차 매칭 성공 시 사무장 단독. 그 외 변호사 승인 유지. confidence 임계값은 본 ADR 에 명시 (변경 시 ADR 개정).
P5 개발자 (초기 부분 반대, 절충)
"1b 단독 착수, 1a 병행 금지." 처리: S2 에 1a 관측 대시보드 포함으로 부분 양보. 관측만이지 1a 기능 개선 아님.
구현 PR 계획 (S2 착수 순서)
| PR | 제목 | 의존성 | eng-day |
|---|---|---|---|
| 1 | test(firebase): cross-tenant + 벡터 경계 계약 테스트 | 없음 (방어선) | 0.5 |
| 2 | feat(legacy): ocrStatus state machine 확장 + 단위 테스트 | PR-1 | 1.0 |
| 3 | feat(legacy): uploadBatches/{batchId} roll-up 스키마 + writer | PR-2 | 1.0 |
| 4 | feat(legacy): legacyAuditLogs/* 스캐폴드 | PR-3 | 0.5 |
| 5 | feat(legacy): 임베딩 자동 생성 파이프라인 | PR-4 | 1.5 |
| 6 | feat(legacy): 리스크 차등 승인 (confidence 임계값) | PR-5 | 1.0 |
| 7 | feat(legacy): 단건~5건 업로드 UX (Dialog) | PR-6 | 2.0 |
| 8 | feat(ops): 1a 관측 대시보드 | 병행 가능 | 1.0 |
총 8.5 eng-day · 버퍼 50% = 약 13 eng-day → 4~6주 일정 적합.
성공 지표
- S2 종료 시점:
- 파일럿 사무소 1곳 단건 업로드 ≥ 50건
- OCR 성공률 ≥ 85% (팩스·오래된 복사본 제외)
- cross-tenant 격리 자동 테스트 100% pass · 프로덕션 격리 위반 0건
- 임베딩 생성 tenant 당 월 비용 < 10원 (텍스트 기반 산정)
- S3 진입 트리거:
findRelatedMemoriesForDocGenActionshown → clicked 기초치 확보
후속 과제
- 파일럿 유치: P1 변호사가 지방 사무소 1곳 박스 실측 (3주 내)
- CLAUDE.md 반영: "AI 파이프라인" 섹션에 tenant-isolated RAG 원칙 추가 (S2 중)
- appMetadata 필드:
features.ai.tenantEmbeddingkill switch ·planLimits.registered.embeddingTokens월간 카운터 (S2 PR-5 와 동시) seed 스크립트:— ADR 0017 에서 기본값 true 로 단순화하며 제거됨 (Firestore 초기화 시 defaults 반영).scripts/seed-tenant-embedding.ts작성 + 머지 전--dry-run검증- ADR 개정 조건: confidence 임계값 80% 를 파일럿 실측 후 조정 시 본 ADR 개정