From 4769741989db55897c990977d7ac6b875b0170c0 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Mon, 16 Mar 2026 13:34:32 +0900 Subject: [PATCH] docs: add workspace-team-project transition plan --- journey/README.md | 2 + ...m_project_계층_재정의_아이디어.md | 1 + ...m_project_계층_재정의_전환계획.md | 256 ++++++++++++++++++ journey/plans/README.md | 5 + ...계층_재정의_영향범위_리서치.md | 1 + 5 files changed, 265 insertions(+) create mode 100644 journey/plans/260316_workspace_team_project_계층_재정의_전환계획.md diff --git a/journey/README.md b/journey/README.md index 2cc47f5..bd1ce94 100644 --- a/journey/README.md +++ b/journey/README.md @@ -11,6 +11,7 @@ - ssot: `../book/300_architecture/390_workspace_team_project_도메인_모델.md` - ideas: `ideas/260316_workspace_team_project_계층_재정의_아이디어.md` - research: `research/260316_workspace_team_project_계층_재정의_영향범위_리서치.md` + - plans: `plans/260316_workspace_team_project_계층_재정의_전환계획.md` ### 닫힌 문제 @@ -64,6 +65,7 @@ - OpenClaw 기반 로빙 개선 아이디어 – `ideas/260309_openclaw_기반_로빙_개선_아이디어.md` - 로빙 에이전트 루프와 스킬 훅 구조 아이디어 – `ideas/260312_로빙_에이전트루프와_스킬훅_구조_아이디어.md` - workspace-team-project 계층 재정의 아이디어 – `ideas/260316_workspace_team_project_계층_재정의_아이디어.md` +- workspace-team-project 계층 재정의 전환계획 – `plans/260316_workspace_team_project_계층_재정의_전환계획.md` ### Intent 리뷰 / 의도 학습 diff --git a/journey/ideas/260316_workspace_team_project_계층_재정의_아이디어.md b/journey/ideas/260316_workspace_team_project_계층_재정의_아이디어.md index d794975..b93efa3 100644 --- a/journey/ideas/260316_workspace_team_project_계층_재정의_아이디어.md +++ b/journey/ideas/260316_workspace_team_project_계층_재정의_아이디어.md @@ -41,6 +41,7 @@ tags: [workspace, team, project, database, slack, ideas] ## 관련 문서 - [Workspace-Team-Project 도메인 모델](../../book/300_architecture/390_workspace_team_project_%EB%8F%84%EB%A9%94%EC%9D%B8_%EB%AA%A8%EB%8D%B8.md) - [workspace-team-project 계층 재정의 영향범위 리서치](../research/260316_workspace_team_project_%EA%B3%84%EC%B8%B5_%EC%9E%AC%EC%A0%95%EC%9D%98_%EC%98%81%ED%96%A5%EB%B2%94%EC%9C%84_%EB%A6%AC%EC%84%9C%EC%B9%98.md) +- [workspace-team-project 계층 재정의 전환계획](../plans/260316_workspace_team_project_%EA%B3%84%EC%B8%B5_%EC%9E%AC%EC%A0%95%EC%9D%98_%EC%A0%84%ED%99%98%EA%B3%84%ED%9A%8D.md) - [database/tables.md](../../book/300_architecture/database/tables.md) - [380_authentication_system.md](../../book/300_architecture/380_authentication_system.md) - [journey/README.md](../README.md) diff --git a/journey/plans/260316_workspace_team_project_계층_재정의_전환계획.md b/journey/plans/260316_workspace_team_project_계층_재정의_전환계획.md new file mode 100644 index 0000000..7ccd3a2 --- /dev/null +++ b/journey/plans/260316_workspace_team_project_계층_재정의_전환계획.md @@ -0,0 +1,256 @@ +tags: [workspace, team, project, database, slack, auth, gateway, rag, migration, plans] + +# workspace-team-project 계층 재정의 전환계획 + +상위 원칙: +- [0_VALUE Writing Principles](../../../../0_VALUE/02_Governance/writing-principles.md) +- [Workspace-Team-Project 도메인 모델](../../book/300_architecture/390_workspace_team_project_%EB%8F%84%EB%A9%94%EC%9D%B8_%EB%AA%A8%EB%8D%B8.md) +- [database/tables.md](../../book/300_architecture/database/tables.md) + +관련 문서: +- [workspace-team-project 계층 재정의 아이디어](../ideas/260316_workspace_team_project_%EA%B3%84%EC%B8%B5_%EC%9E%AC%EC%A0%95%EC%9D%98_%EC%95%84%EC%9D%B4%EB%94%94%EC%96%B4.md) +- [workspace-team-project 계층 재정의 영향범위 리서치](../research/260316_workspace_team_project_%EA%B3%84%EC%B8%B5_%EC%9E%AC%EC%A0%95%EC%9D%98_%EC%98%81%ED%96%A5%EB%B2%94%EC%9C%84_%EB%A6%AC%EC%84%9C%EC%B9%98.md) +- [통합 인증 시스템 아키텍처](../../book/300_architecture/380_authentication_system.md) +- [테이블 관계도](../../book/300_architecture/database/relationships.md) + +## 목적 +- `team`이 상위 조직과 실행 조직 의미를 동시에 갖는 현재 구조를 종료합니다. +- 운영 중인 `auth-server`, `robeing-gateway`, `rb8001`, `skill-rag-file`, `skill-slack`, `admin-dashboard`를 한 번에 깨지 않도록 병행 지원 순서로 전환합니다. +- 최종적으로 `workspace > team`, `team owns project`를 운영 DB와 코드 SSOT에 맞춰 고정합니다. + +## 범위 +- 포함: + - 새 조직 모델 정의와 목표 ERD 고정 + - 운영 DB의 병행 지원용 컬럼/테이블 추가 + - Slack/Auth/RAG 경로의 단계별 전환 + - Company-X와 Robeing의 초기 매핑 규칙 확정 + - 검증 체크리스트와 롤백 기준 고정 +- 제외: + - 모든 고객사의 조직 구조 일괄 정리 + - 실제 개별 프로젝트 팀 구조의 최종 업무 운영 정책 확정 + - 오래된 문서 전체 아카이브 정리 + +## 목표 모델 + +### 1. 도메인 해석 +- `workspace`: Company-X, Goosefarm 같은 상위 조직 단위 +- `team`: workspace 소속 실행 조직 +- `project`: team이 담당하는 대상/업무 단위 + +### 2. 목표 관계 +- `workspace has many teams` +- `team belongs to one workspace` +- `team owns many projects` +- `slack_workspace belongs to one workspace` +- `slack_channel`은 `workspace` 소속을 기본으로 하고, 필요 시 `project`를 선택적으로 참조 + +### 3. 초기 운영 매핑 +- `Company-X`는 `workspace`로 승격 +- 현재 `Company-X Team`은 임시로 `Company-X 실행팀` 성격의 `team`으로 재정의 +- `xvaluelab`은 `project`로 등록 +- `Robeing`도 같은 기준으로 `workspace`와 하위 `team`을 분리할 수 있게 설계 + +## 목표 ERD 초안 + +### 1. 신규/재정의 엔터티 +- `workspace` + - `id` + - `name` + - `slug` + - `is_active` + - `created_at` + - `updated_at` +- `team` + - `id` + - `workspace_id` + - `name` + - `slug` + - `role_type` + - `is_active` + - `created_at` + - `updated_at` +- `project` + - `id` + - `team_id` + - `name` + - `slug` + - `status` + - `created_at` + - `updated_at` + +### 2. 기존 테이블의 목표 참조 +- `user.team_id`는 유지하되 전환 완료 전까지 `team`만 참조 +- `workspace_member`는 `workspace_id`를 추가해 이름과 구조를 일치시킴 +- `slack_workspace.team_id`는 최종적으로 `workspace_id`로 전환 +- `slack_channel`은 `workspace_id`와 `project_id`를 병행 지원 +- `slack_canvas`는 기존 `slack_channel_id`를 유지 +- `team_document`, `startup_valuation`은 우선 기존 `team_id` 유지 후 필요 시 후속 분리 +- `coldmail_list_config`는 `slack_workspace_id` 유지 + +## 전환 원칙 + +### 1. 레거시 `team_id` 경로를 바로 제거하지 않습니다. +- 새 축을 먼저 추가합니다. +- 읽기는 `신규 필드 우선 + 레거시 fallback`으로 갑니다. +- 쓰기는 이행 기간 동안 dual-write를 허용합니다. + +### 2. Slack/Auth 경로를 최우선 보호합니다. +- Slack OIDC 로그인 +- Slack passport install/callback/status/token +- gateway Slack token lookup / user uuid mapping +- rb8001 Slack event/file/message 처리 +- skill-slack Lists API + +### 3. Company-X RAG 경로를 두 번째 보호 축으로 둡니다. +- `team_document` +- `skill-rag-file` 업로드/검색 +- `companyx_grounding_service` +- IR 채널/Canvas 처리 + +### 4. 문서 SSOT를 코드 전환과 같은 묶음으로 처리합니다. +- 구조를 바꾸고 문서를 나중에 맞추는 방식은 금지합니다. +- 최소 `tables.md`, `relationships.md`, `380_authentication_system.md`는 같은 단계에서 갱신합니다. + +## 작업 단계 + +### Phase 0. 사전 고정 +- `workspace`, `team`, `project` 정의를 본 문서 기준으로 동결 +- Company-X, Robeing 초기 매핑을 표로 확정 +- `workspace_member`를 계속 쓸지 대체할지 결정하지 말고, 우선 `workspace_id` 추가를 기준안으로 둠 + +### Phase 1. DB 병행 지원 준비 +- `workspace` 테이블 신설 +- `project` 테이블 신설 +- `team.workspace_id` 추가 +- `workspace_member.workspace_id` 추가 +- `slack_workspace.workspace_id` 추가 +- `slack_channel.workspace_id`, `slack_channel.project_id` 추가 +- 필요 시 `project_name`은 유지하되 FK 전환 완료 후 보조 메타 필드로만 사용 + +### Phase 2. 기초 데이터 이관 +- 기존 `company` 레코드를 기준으로 `workspace` 생성 +- `team.company_id`를 해석해 각 `team.workspace_id` 채움 +- Company-X용 `project(xvaluelab)` 생성 +- `slack_workspace.workspace_id`를 채우고 기존 `team_id`는 유지 +- `slack_channel.workspace_id`를 채우고, `xvaluelab` 채널에 `project_id` 연결 +- `workspace_member.workspace_id`를 사용자 소속 기준으로 채움 + +### Phase 3. 읽기 경로 병행 지원 +- `auth-server` + - `Workspace = Team` alias 제거 준비 + - Slack OAuth/passport 경로를 `workspace_id` 중심으로 병행 조회 + - `workspace_member` 조회를 실제 `workspace_id` 구조로 정합화 +- `robeing-gateway` + - `get_user_workspace`, `assign_user_to_workspace`, `slack_user_to_uuid` 병행 지원 + - Slack `team_id(T...) -> slack_workspace -> workspace/team` 매핑 명확화 +- `rb8001` + - Slack repository에서 `slack_team_id -> workspace/team` 해석 병행 지원 + - Company-X 전용 상수는 `workspace`/`project` 기반 식별자로 치환 준비 +- `skill-slack` + - `X-Team-Id` 계약을 유지하되 내부에서 workspace-aware lookup 지원 +- `admin-dashboard` + - `workspace + team` 통계 병행 노출 준비 + +### Phase 4. 쓰기 경로 dual-write +- 새 사용자/조직 연결 시 `team_id`와 `workspace_id`를 함께 기록 +- Slack 설치/재설치 시 `slack_workspace.workspace_id`와 레거시 `team_id`를 함께 채움 +- 새 채널/Canvas/프로젝트 연결 시 `project_id` 우선 기록 +- 운영 로그에 `workspace_id`, `team_id`, `project_id`를 함께 남겨 비교 가능하게 함 + +### Phase 5. 서비스별 전환 +- `auth-server`에서 `workspace`를 실제 `workspace` 엔터티로 전환 +- `robeing-gateway`에서 사용자 컨텍스트 기본 축을 `workspace + team`으로 변경 +- `rb8001`에서 Company-X 전용 로직을 `workspace/project` 기반으로 재작성 +- `skill-rag-file`는 현 단계에서는 `team_document.team_id`를 유지하되, API 계약과 내부 검색 필터에서 `workspace/project` 메타를 병행 지원 +- `admin-dashboard`는 기존 팀 통계와 새 워크스페이스 통계를 함께 검증 + +### Phase 6. 정리 단계 +- 더 이상 사용하지 않는 `Workspace = Team` alias 제거 +- `workspace_member` 레거시 해석 제거 +- `slack_workspace.team_id` 사용처 제거 또는 보조 참조로 축소 +- `project_name` 문자열 의존 경로 제거 +- 필요 시 `company`의 역할을 archive/legacy 참조로 축소 + +## 데이터 이관 규칙 + +### 1. Company-X +- `company.name='Company-X'` 기준 `workspace` 1건 생성 +- 현재 `team.id=79441171-3951-4870-beb8-916d07fe8be5`는 같은 workspace 하위 team으로 유지 +- `project.name='xvaluelab'` 생성 +- `slack_workspace.slack_team_id='T09C98KB933'`는 새 Company-X workspace에 연결 +- `slack_channel.channel_id='C0ALCV5S0FL'`는 Company-X workspace + `xvaluelab` project에 연결 + +### 2. Robeing +- `company.name='Robeing'` 기준 `workspace` 1건 생성 +- 기존 `Robeing` team은 해당 workspace 하위 team으로 유지 +- 하위 project는 후속 운영 구조 확정 후 추가 + +### 3. 레거시 보존 +- 이행 기간 동안 기존 UUID는 가능한 한 재사용합니다. +- 신규 엔터티 추가 때문에 기존 `team.id`를 바꾸지 않습니다. +- old/new 매핑 테이블 또는 migration note를 남겨 추적성을 확보합니다. + +## 서비스별 검증 체크리스트 + +### 1. auth-server +- Slack OIDC 로그인 성공 +- Slack passport install/callback/status/token 성공 +- Slack uninstall 경로에서 잘못된 `workspace_id` 참조 제거 확인 +- `workspace_member` 조회가 실제 `workspace_id`를 사용해도 정상 동작 + +### 2. robeing-gateway +- Slack event 요청에서 bot token 조회 성공 +- Slack user -> internal UUID 변환 성공 +- 사용자 소속 조회에서 `workspace`, `team`이 모두 기대값으로 반환 + +### 3. rb8001 +- Slack message/file/event 처리 성공 +- Company-X grounding 성공 +- IR 채널 `C0ALCV5S0FL` 읽기/전송 성공 +- Canvas 조회 성공 + +### 4. skill-rag-file +- 업로드 API 성공 +- 기존 Company-X 문서 검색 성공 +- 재인덱싱 없이도 기존 컬렉션 fallback이 동작 + +### 5. skill-slack +- Lists 조회/동기화 성공 +- 내부 팀 식별자와 workspace 매핑이 모두 로그에 남음 + +### 6. admin-dashboard +- `total_workspaces`, `total_teams` 통계 비교 +- 사용자 상세 응답에 `workspace_id`, `team_id` 병행 노출 확인 + +## 롤백 기준 +- Slack 로그인 또는 Slack 이벤트 처리 실패가 1건이라도 재현되면 즉시 롤백 +- Company-X RAG 검색 0건 회귀가 발생하면 즉시 롤백 +- Company-X IR 채널 읽기/전송 또는 Canvas 조회 실패 시 즉시 롤백 +- dual-write 비교에서 `workspace_id`와 `team_id` 해석이 어긋나는 데이터가 발견되면 해당 단계는 닫지 않음 + +## 예상 리스크와 대응 + +### 1. `workspace_member` 정합화 실패 +- 대응: Phase 1에서 실제 컬럼 추가 후 읽기 경로를 명시적으로 분리 + +### 2. Slack payload의 `team_id(T...)`와 내부 UUID 혼선 재발 +- 대응: Slack 외부 식별자와 내부 식별자를 함수/컬럼명 단계에서 분리 + +### 3. Company-X 전용 상수로 인한 부분 회귀 +- 대응: 상수 제거 전까지는 `workspace_id`, `team_id`, `project_id`를 모두 로그로 남김 + +### 4. 기존 RAG 컬렉션명과 새 메타 모델 충돌 +- 대응: `team_document`와 컬렉션명은 후속 단계까지 유지하고, 이번 계획에서는 metadata bridge만 추가 + +## 완료 판정 +- 계획 문서 단계의 완료는 구현 완료가 아닙니다. +- 아래 조건이 채워지면 이 계획 문서는 닫을 수 있습니다. + - 목표 ERD 확정 + - 단계별 DB 변경 순서 확정 + - 서비스별 병행 지원 범위 확정 + - 검증 체크리스트와 롤백 기준 확정 + +## 다음 단계 +- 이 문서를 기준으로 DB 마이그레이션 초안 문서를 별도로 작성 +- `auth-server`, `robeing-gateway`, `rb8001`, `skill-rag-file`, `skill-slack`, `admin-dashboard`별 세부 구현 작업을 worklog로 분리 +- 전환 시작 전 `tables.md`, `relationships.md`, `380_authentication_system.md` 갱신 순서를 먼저 잡음 diff --git a/journey/plans/README.md b/journey/plans/README.md index 454beb0..8f37296 100644 --- a/journey/plans/README.md +++ b/journey/plans/README.md @@ -40,6 +40,11 @@ **목표**: NAS RAG·Company X RAG에 Gemini Embedding 2 부분/하이브리드 도입, 멀티모달 직접 임베딩 **참고**: `plans/260316_임베딩_Gemini_Embedding_2_전환_계획.md` +### 6. workspace-team-project 계층 재정의 전환 (260316) +**상태**: planned +**목표**: `team`에 겹쳐 있는 상위 조직/실행 조직 의미를 분리해 `workspace > team`, `team owns project` 구조로 병행 전환 +**참고**: `plans/260316_workspace_team_project_계층_재정의_전환계획.md` + ## ✅ 완료된 항목 (archive 이동 완료) 1. **admin_dashboard_business_integration (251204)** - 완료 → archive 이동 diff --git a/journey/research/260316_workspace_team_project_계층_재정의_영향범위_리서치.md b/journey/research/260316_workspace_team_project_계층_재정의_영향범위_리서치.md index 3eb974f..60e32a4 100644 --- a/journey/research/260316_workspace_team_project_계층_재정의_영향범위_리서치.md +++ b/journey/research/260316_workspace_team_project_계층_재정의_영향범위_리서치.md @@ -9,6 +9,7 @@ tags: [workspace, team, project, database, slack, auth, gateway, rag, research] 관련 문서: - [workspace-team-project 계층 재정의 아이디어](../ideas/260316_workspace_team_project_%EA%B3%84%EC%B8%B5_%EC%9E%AC%EC%A0%95%EC%9D%98_%EC%95%84%EC%9D%B4%EB%94%94%EC%96%B4.md) +- [workspace-team-project 계층 재정의 전환계획](../plans/260316_workspace_team_project_%EA%B3%84%EC%B8%B5_%EC%9E%AC%EC%A0%95%EC%9D%98_%EC%A0%84%ED%99%98%EA%B3%84%ED%9A%8D.md) - [통합 인증 시스템 아키텍처](../../book/300_architecture/380_authentication_system.md) - [테이블 관계도](../../book/300_architecture/database/relationships.md) - [Slack install workspace_id error](../troubleshooting/251015_slack_install_workspace_id_error.md)