Gmail 아이템 구현 계획 수립
- Gmail passport 아이템 시스템 설계 - 작업 분담: 종태(프론트), 희재(통합), 서버관리자(인프라) - robeing_id로 컬럼명 통일 - 레벨 5 제한, passport 슬롯 정의 - DB 테이블 구조 수정 (robing_id → robeing_id)
This commit is contained in:
parent
d8d2948c36
commit
d79b55ef45
@ -22,7 +22,7 @@ Password: robeings
|
|||||||
CREATE TABLE gmail_tokens (
|
CREATE TABLE gmail_tokens (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
user_id VARCHAR(100) UNIQUE NOT NULL,
|
user_id VARCHAR(100) UNIQUE NOT NULL,
|
||||||
robing_id VARCHAR(50),
|
robeing_id VARCHAR(50),
|
||||||
token_data JSONB NOT NULL,
|
token_data JSONB NOT NULL,
|
||||||
oauth_config JSONB,
|
oauth_config JSONB,
|
||||||
scopes JSONB,
|
scopes JSONB,
|
||||||
@ -84,7 +84,7 @@ CREATE TABLE gmail_tokens (
|
|||||||
```sql
|
```sql
|
||||||
-- 기본 인덱스
|
-- 기본 인덱스
|
||||||
CREATE INDEX idx_gmail_tokens_user_id ON gmail_tokens(user_id);
|
CREATE INDEX idx_gmail_tokens_user_id ON gmail_tokens(user_id);
|
||||||
CREATE INDEX idx_gmail_tokens_robing_id ON gmail_tokens(robing_id);
|
CREATE INDEX idx_gmail_tokens_robeing_id ON gmail_tokens(robeing_id);
|
||||||
|
|
||||||
-- JSON 검색용 GIN 인덱스
|
-- JSON 검색용 GIN 인덱스
|
||||||
CREATE INDEX idx_gmail_tokens_token_data ON gmail_tokens USING GIN (token_data);
|
CREATE INDEX idx_gmail_tokens_token_data ON gmail_tokens USING GIN (token_data);
|
||||||
@ -125,7 +125,7 @@ EXECUTE FUNCTION update_updated_at_column();
|
|||||||
```
|
```
|
||||||
|
|
||||||
### 5.2 현재 저장된 데이터
|
### 5.2 현재 저장된 데이터
|
||||||
| user_id | robing_id | 권한 상태 | 이메일 발송 가능 |
|
| user_id | robeing_id | 권한 상태 | 이메일 발송 가능 |
|
||||||
|---------|-----------|-----------|-----------------|
|
|---------|-----------|-----------|-----------------|
|
||||||
| heejae | rb8001 | gmail.modify만 있음 | ❌ 불가능 |
|
| heejae | rb8001 | gmail.modify만 있음 | ❌ 불가능 |
|
||||||
| test | rb8001 | gmail.send + modify | ✅ 가능 |
|
| test | rb8001 | gmail.send + modify | ✅ 가능 |
|
||||||
@ -148,7 +148,7 @@ FROM gmail_tokens
|
|||||||
WHERE user_id = 'test';
|
WHERE user_id = 'test';
|
||||||
|
|
||||||
-- 이메일 발송 가능한 사용자 찾기
|
-- 이메일 발송 가능한 사용자 찾기
|
||||||
SELECT user_id, robing_id
|
SELECT user_id, robeing_id
|
||||||
FROM gmail_tokens
|
FROM gmail_tokens
|
||||||
WHERE scopes @> '["https://www.googleapis.com/auth/gmail.send"]';
|
WHERE scopes @> '["https://www.googleapis.com/auth/gmail.send"]';
|
||||||
```
|
```
|
||||||
@ -179,7 +179,7 @@ WHERE metadata->>'slack_user_id' = 'U091UNVE41M';
|
|||||||
-- 특정 로빙의 Gmail 계정 찾기
|
-- 특정 로빙의 Gmail 계정 찾기
|
||||||
SELECT user_id, metadata->>'email' as gmail_account
|
SELECT user_id, metadata->>'email' as gmail_account
|
||||||
FROM gmail_tokens
|
FROM gmail_tokens
|
||||||
WHERE robing_id = 'rb8001';
|
WHERE robeing_id = 'rb8001';
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
372
plans/250819_gmail_item_implementation_plan.md
Normal file
372
plans/250819_gmail_item_implementation_plan.md
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
# Gmail 아이템 구현 계획
|
||||||
|
|
||||||
|
## 작성일: 2025-08-19
|
||||||
|
## 작성자: Claude (with 종태)
|
||||||
|
## 상태: 계획 수립
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 개요
|
||||||
|
|
||||||
|
### 목적
|
||||||
|
Gmail 자격증명을 "API 아이템"으로 정의하고, robeing의 장착형 아이템 시스템에 통합
|
||||||
|
|
||||||
|
### 핵심 원칙
|
||||||
|
- Gmail OAuth 토큰을 극비 데이터로 취급
|
||||||
|
- 아이템 장착/해제 메타포로 권한 관리
|
||||||
|
- RBAC+ABAC 하이브리드 접근 제어
|
||||||
|
- 레벨 5 이상에서 사용 가능
|
||||||
|
|
||||||
|
### 관련 문서
|
||||||
|
- `/250817_email_skill_integration_status.md` - 현황 분석
|
||||||
|
- `/250818_gmail_tokens_database_setup.md` - DB 구성 완료
|
||||||
|
- `/ideas/250818_claude_robeing_레벨업_체감_시스템_설계.md` - 아이템 시스템 설계
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 아이템 정의
|
||||||
|
|
||||||
|
### 기본 속성
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
type: 'accessory',
|
||||||
|
slot: 'passport_gmail',
|
||||||
|
name: 'Gmail Passport',
|
||||||
|
level_requirement: 5
|
||||||
|
// rarity 제거 - 불필요
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 데이터 모델
|
||||||
|
```typescript
|
||||||
|
type GmailCredentialItem = {
|
||||||
|
id: string; // gmail_tokens.id
|
||||||
|
userId: string; // gmail_tokens.user_id
|
||||||
|
robeing_id?: string; // gmail_tokens.robeing_id (통일)
|
||||||
|
type: 'accessory';
|
||||||
|
slot: 'passport_gmail';
|
||||||
|
name: string; // metadata.display_name || email
|
||||||
|
email: string; // metadata.email
|
||||||
|
scopes: string[]; // scopes 배열
|
||||||
|
status: 'ready' | 'reauth_required' | 'insufficient_scope';
|
||||||
|
capabilities: {
|
||||||
|
send: boolean; // gmail.send 스코프 존재 여부
|
||||||
|
read: boolean; // gmail.readonly 스코프 존재 여부
|
||||||
|
modify: boolean; // gmail.modify 스코프 존재 여부
|
||||||
|
};
|
||||||
|
expiry?: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 아키텍처
|
||||||
|
|
||||||
|
### 서비스 구조
|
||||||
|
```
|
||||||
|
프론트엔드 (React)
|
||||||
|
↓
|
||||||
|
robeing-gateway (인증/라우팅)
|
||||||
|
↓
|
||||||
|
rb8001:8001 (메인 robeing)
|
||||||
|
↓ ↓
|
||||||
|
skill-email:8501 robeing-monitor:9024
|
||||||
|
(이메일 발송) (아이템 상태 관리)
|
||||||
|
↓ ↓
|
||||||
|
PostgreSQL (gmail_tokens 테이블)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 서비스별 역할
|
||||||
|
|
||||||
|
#### auth-server
|
||||||
|
- Gmail OAuth 플로우 처리
|
||||||
|
- gmail_tokens 테이블 관리
|
||||||
|
- 토큰 갱신 로직
|
||||||
|
|
||||||
|
#### robeing-monitor (9024)
|
||||||
|
- 아이템 상태 관리
|
||||||
|
- 장착/해제 로직
|
||||||
|
- 레벨 요구사항 체크
|
||||||
|
- 아이템 인벤토리 조회
|
||||||
|
|
||||||
|
#### rb8001
|
||||||
|
- 아이템 사용 로직
|
||||||
|
- skill-email 호출
|
||||||
|
- 사용자 컨텍스트 관리
|
||||||
|
|
||||||
|
#### skill-email (8501)
|
||||||
|
- Gmail API 실제 호출
|
||||||
|
- 이메일 작성/발송
|
||||||
|
- DB 기반 토큰 조회
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. API 설계
|
||||||
|
|
||||||
|
### robeing-monitor (9024) 엔드포인트
|
||||||
|
|
||||||
|
#### 아이템 목록 조회
|
||||||
|
```
|
||||||
|
GET /api/items/gmail
|
||||||
|
Response: {
|
||||||
|
equipped: GmailCredentialItem | null,
|
||||||
|
available: GmailCredentialItem[]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 아이템 장착
|
||||||
|
```
|
||||||
|
POST /api/items/gmail/:userId/equip
|
||||||
|
Body: { robeing_id: string }
|
||||||
|
Response: {
|
||||||
|
success: boolean,
|
||||||
|
message: string,
|
||||||
|
audit_id: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 재인증 시작
|
||||||
|
```
|
||||||
|
POST /api/items/gmail/:userId/reauth
|
||||||
|
Response: {
|
||||||
|
auth_url: string,
|
||||||
|
state: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 아이템 철회
|
||||||
|
```
|
||||||
|
DELETE /api/items/gmail/:userId
|
||||||
|
Response: {
|
||||||
|
success: boolean,
|
||||||
|
audit_id: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 권한 체크 플로우
|
||||||
|
1. Gateway: JWT 토큰 검증
|
||||||
|
2. robeing-monitor: 레벨 5 이상 확인
|
||||||
|
3. robeing-monitor: 아이템 소유권 확인
|
||||||
|
4. rb8001: 최종 사용 권한 확인
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 보안 정책
|
||||||
|
|
||||||
|
### 데이터 등급
|
||||||
|
- **극비**: access_token, refresh_token, client_secret
|
||||||
|
- **기밀**: oauth_config, scopes
|
||||||
|
- **일반**: email, display_name, status
|
||||||
|
|
||||||
|
### 접근 제어
|
||||||
|
- 토큰 본문은 절대 프론트엔드 노출 금지
|
||||||
|
- capabilities는 scopes에서 파생하여 표시
|
||||||
|
- 모든 민감 작업 감사 로그 기록
|
||||||
|
|
||||||
|
### 감사 로그
|
||||||
|
```sql
|
||||||
|
CREATE TABLE gmail_audit_logs (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id VARCHAR(100),
|
||||||
|
robeing_id VARCHAR(50),
|
||||||
|
action VARCHAR(50), -- equip, reauth, revoke
|
||||||
|
success BOOLEAN,
|
||||||
|
details JSONB,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 구현 단계
|
||||||
|
|
||||||
|
### Phase 1: 백엔드 기초
|
||||||
|
- [ ] 필요 테이블 생성
|
||||||
|
- robeing_stats 테이블 (레벨 관리)
|
||||||
|
- gmail_audit_logs 테이블 (감사 로그)
|
||||||
|
- gmail_tokens에 is_equipped, equipped_to 컬럼 추가
|
||||||
|
- [ ] skill-email DB 연결 코드 작성
|
||||||
|
- FileCredentialsProvider → DBCredentialsProvider 전환
|
||||||
|
- PostgreSQL 연결 설정 추가 (192.168.219.45)
|
||||||
|
- [ ] robeing-monitor 서비스 구축
|
||||||
|
- 기존 robeing-state-service 확장
|
||||||
|
- 포트 9024로 변경
|
||||||
|
- 아이템 관리 API 추가
|
||||||
|
|
||||||
|
### Phase 2: 통합 연결
|
||||||
|
- [ ] rb8001 환경변수 설정
|
||||||
|
```bash
|
||||||
|
SKILL_EMAIL_URL=http://localhost:8501
|
||||||
|
STATE_SERVICE_URL=http://localhost:9024
|
||||||
|
```
|
||||||
|
- [ ] rb8001 ↔ skill-email 연결 테스트
|
||||||
|
- [ ] rb8001 ↔ robeing-monitor 연결 테스트
|
||||||
|
|
||||||
|
### Phase 3: 프론트엔드
|
||||||
|
- [ ] 인벤토리 UI 컴포넌트 개발
|
||||||
|
- 아이템 카드 리스트
|
||||||
|
- 장착 상태 표시
|
||||||
|
- 재인증 버튼
|
||||||
|
- [ ] robeing-api.ts 확장
|
||||||
|
- Gmail 아이템 API 호출 함수
|
||||||
|
- 에러 핸들링
|
||||||
|
|
||||||
|
### Phase 4: 테스트 및 검증
|
||||||
|
- [ ] 장착/해제 플로우 테스트
|
||||||
|
- [ ] 재인증 플로우 테스트
|
||||||
|
- [ ] 권한 부족 시나리오 테스트
|
||||||
|
- [ ] 감사 로그 확인
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 환경변수 표준
|
||||||
|
|
||||||
|
### 공통 PostgreSQL 설정
|
||||||
|
```bash
|
||||||
|
# 51123 서버에서
|
||||||
|
POSTGRES_HOST=localhost
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
# 51124 서버에서
|
||||||
|
POSTGRES_HOST=192.168.219.45
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
# 공통
|
||||||
|
POSTGRES_DB=auth_db
|
||||||
|
POSTGRES_USER=robeings
|
||||||
|
POSTGRES_PASSWORD=robeings
|
||||||
|
```
|
||||||
|
|
||||||
|
### 서비스별 설정
|
||||||
|
```bash
|
||||||
|
# rb8001 (51124 서버)
|
||||||
|
SKILL_EMAIL_URL=http://localhost:8501 # host 모드이므로 localhost
|
||||||
|
STATE_SERVICE_URL=http://localhost:9024
|
||||||
|
DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/auth_db
|
||||||
|
|
||||||
|
# skill-email (51124 서버)
|
||||||
|
TOKEN_PROVIDER=database # file → database
|
||||||
|
POSTGRES_CONNECTION_STRING=postgresql://robeings:robeings@192.168.219.45:5432/auth_db
|
||||||
|
|
||||||
|
# robeing-monitor (51124 서버)
|
||||||
|
PORT=9024
|
||||||
|
SERVICE_NAME=robeing-monitor
|
||||||
|
DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/auth_db
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 데이터 매핑 (추후 구현)
|
||||||
|
|
||||||
|
### Slack User ID ↔ Gmail 계정 매핑
|
||||||
|
- 위치: 추후 결정 (workspace_members 또는 별도 테이블)
|
||||||
|
- 구조:
|
||||||
|
```sql
|
||||||
|
-- 옵션 1: workspace_members 확장
|
||||||
|
ALTER TABLE workspace_members
|
||||||
|
ADD COLUMN gmail_account VARCHAR(255);
|
||||||
|
|
||||||
|
-- 옵션 2: 별도 매핑 테이블
|
||||||
|
CREATE TABLE user_gmail_mapping (
|
||||||
|
slack_user_id VARCHAR(100) PRIMARY KEY,
|
||||||
|
gmail_account VARCHAR(255),
|
||||||
|
robeing_id VARCHAR(50)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 성공 지표
|
||||||
|
|
||||||
|
### 기능적 요구사항
|
||||||
|
- [ ] 레벨 5 이상 사용자만 Gmail 아이템 장착 가능
|
||||||
|
- [ ] 토큰 만료 시 자동 재인증 안내
|
||||||
|
- [ ] 권한 부족(gmail.send 없음) 시 명확한 안내
|
||||||
|
|
||||||
|
### 비기능적 요구사항
|
||||||
|
- [ ] 토큰 정보 프론트엔드 미노출
|
||||||
|
- [ ] 모든 민감 작업 감사 로그 기록
|
||||||
|
- [ ] 서비스 간 통신 안정성 확보
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 리스크 및 대응
|
||||||
|
|
||||||
|
### 리스크 1: 토큰 노출
|
||||||
|
- 대응: 모든 API에서 토큰 필드 제거, capabilities만 반환
|
||||||
|
|
||||||
|
### 리스크 2: 서비스 간 통신 실패
|
||||||
|
- 대응: 재시도 로직, Circuit Breaker 패턴 적용
|
||||||
|
|
||||||
|
### 리스크 3: 레벨 체크 우회
|
||||||
|
- 대응: 다층 검증 (Gateway → Monitor → rb8001)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 결정된 표준
|
||||||
|
|
||||||
|
### 에러 메시지
|
||||||
|
- **형식**: 개발 친화적 에러 코드
|
||||||
|
```
|
||||||
|
GMAIL_AUTH_FAILED
|
||||||
|
INSUFFICIENT_LEVEL
|
||||||
|
TOKEN_EXPIRED
|
||||||
|
PASSPORT_REJECTED
|
||||||
|
```
|
||||||
|
|
||||||
|
### 응답 형식
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
status: "success" | "error",
|
||||||
|
data?: any,
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### UI/UX
|
||||||
|
- **아이콘**: Gmail 로고 사용
|
||||||
|
- **애니메이션**: 매우 간단한 페이드인/아웃
|
||||||
|
- **메시지 톤**: 친근한 안내
|
||||||
|
- "레벨 5가 되면 사용 가능해요!"
|
||||||
|
- "Gmail 재인증이 필요해요"
|
||||||
|
|
||||||
|
### 정책
|
||||||
|
- **캐싱**: 필요시에만 적용 (기본적으로 실시간)
|
||||||
|
- **재시도**: 3회, 지수 백오프
|
||||||
|
- **감사 로그**: 외부 백업 연동 (이미 구축됨)
|
||||||
|
- **장착 제한**: 계정당 1개 Gmail passport만 허용
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 참고사항
|
||||||
|
|
||||||
|
### 현재 상태 (2025-08-19)
|
||||||
|
- gmail_tokens 테이블 생성 완료
|
||||||
|
- rb8001 정상 작동 (GEMINI_USE_CLI=false)
|
||||||
|
- skill-email 파일 기반 동작 중 (DB 전환 필요)
|
||||||
|
- 프론트 인벤토리 UI 미구현
|
||||||
|
|
||||||
|
### 주요 결정사항
|
||||||
|
- 아이템 슬롯: `passport_gmail` (패스포트 슬롯)
|
||||||
|
- 레벨 제한: 5 (robeing_stats 테이블 생성 필요)
|
||||||
|
- 서비스 포트: skill-email(8501), robeing-monitor(9024)
|
||||||
|
- 컬럼명: robeing_id로 통일 (DB 수정 완료)
|
||||||
|
- Gateway 포트: 8100 (추후 8000으로 변경 예정)
|
||||||
|
- 소유 구조: User가 아이템 소유 → Robeing에게 장착
|
||||||
|
|
||||||
|
### 다음 액션
|
||||||
|
1. skill-email DB 연결 코드 작성
|
||||||
|
2. robeing-monitor 서비스 구축
|
||||||
|
3. 프론트 인벤토리 UI 개발
|
||||||
|
4. 전체 통합 테스트
|
||||||
|
|
||||||
|
### 작업 분담
|
||||||
|
- **종태**: 프론트엔드 (인벤토리 UI, robeing-api.ts, Context 상태)
|
||||||
|
- **희재**: rb8001 통합, skill-email DB 연결
|
||||||
|
- **서버 관리자**: 테이블 생성, robeing-monitor(9024) 구축, Gateway 설정
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**문서 끝**
|
||||||
Loading…
x
Reference in New Issue
Block a user