# 작업 계획서: task-104.1 (대시보드 개선 M2+L2)

**팀장:** 라(Ra) - 개발3팀장
**작성일:** 2026-03-02
**작업 ID:** task-104.1
**근거:** task-100.3 (아누 지시), improvement-plan.md M2+L2

---

## 1. 서브태스크 분해

### Sub-1: M2 — 횡단조직 memberStatus 전달 (`index.html`)
- CenterCard 컴포넌트(167행)에 `memberStatus={}` prop 추가
- CenterCard 내부에서 lead ID로 memberStatus 조회하여 실시간 상태 반영
- 레드팀 섹션(534~548행) 인라인 코드에서도 memberStatus 조회 후 StatusDot 상태 반영
- 활성화 렌더링 위치(551행): `<CenterCard>` 호출 시 `memberStatus={memberStatus}` 전달
- 레드팀 렌더링(534행) JSX에 `memberStatus` 기반 동적 상태 적용

### Sub-2: L2 — 패스워드 하드코딩 제거 (`server.py`)
- 545행 `DASHBOARD_PASS` 환경변수 미설정 시 `sys.stderr`에 경고 출력
- 기존 "changeme" 기본값 유지 (서비스 중단 방지)
- 경고 메시지: `[WARN] DASHBOARD_PASSWORD 환경변수가 설정되지 않았습니다. 기본 패스워드 사용 중 - 보안 위험!`

---

## 2. 팀원 배정

- **오픈클로(GLM-5)**: Sub-1 및 Sub-2 순차 실행
- 작업 경로: `/home/jay/workspace/dashboard/`

---

## 3. 예상 위험 및 대안

| 위험 | 확률 | 대안 |
|------|------|------|
| CenterCard에 lead.id 없을 경우 조회 실패 | 중 | `lead?.id` 옵셔널 체이닝으로 방어 처리 |
| 레드팀 lead.id가 memberStatus에 없을 경우 | 중 | fallback: `lead.status || 'active'` 유지 |
| server.py에서 import sys 누락 | 낮 | 이미 import되어 있으면 생략, 없으면 추가 |
| MemberRow 패턴과 불일치 구현 | 중 | `const msEntry = memberStatus?.members?.[lead.id]` 패턴 사용 (MemberRow와 동일 방식) |

### 검토한 대안 및 기각 사유
- **대안 A: CenterCard에서 전역 state 직접 접근** → 기각: prop drilling이 React 컨벤션에 맞으며 테스트 가능성 확보
- **대안 B: 별도 CenterMemberRow 컴포넌트 생성** → 기각: CenterCard가 단순 구조이므로 과잉설계. 인라인으로 충분
- **대안 C: 패스워드 미설정 시 서버 시작 중단** → 기각: 서비스 중단 방지를 위해 경고만 출력 (task-103.1 지시사항)

---

## 4. 실행 순서

1. `index.html` 수정 (M2: CenterCard + 레드팀 memberStatus)
2. `server.py` 수정 (L2: 패스워드 경고)
3. 테스트 시나리오 기술 (브라우저/서버 동작 확인)
4. done 시그널 생성

---

## 5. 수정 금지 영역 확인

- dispatch.py ✅ 건드리지 않음
- team_prompts.py ✅ 건드리지 않음
- hooks 파일 ✅ 건드리지 않음
- server.py의 SSE/API 로직 ✅ 패스워드 부분만 수정
