# task-1582.1 완료 보고서: 대시보드 시스템뷰 탭 — 디자인MD 섹션 추가

## SCQA

**S**: task-1507에서 58개 사이트의 DESIGN.md 레퍼런스 라이브러리가 `/home/jay/workspace/resources/design-md/`에 구축 완료되어 INDEX.md 기반의 카테고리별 인덱스(8개 카테고리, 58개 사이트)가 운영 중이다.

**C**: 디자인 레퍼런스를 확인하려면 CLI 또는 파일 직접 접근이 필요하여, 대시보드에서 직관적으로 탐색할 수 없었다.

**Q**: 대시보드 시스템뷰 탭 내에서 디자인MD 라이브러리를 카테고리 필터, 검색, 컬러 스와치 포함 카드 UI로 시각적으로 탐색할 수 있는가?

**A**: 시스템뷰 탭에 토글 기반 2개 섹션(시스템상태/디자인MD)을 추가하고, 백엔드 API 2개(인덱스 파싱, 사이트 상세)를 구현하여 58개 사이트를 카테고리 필터 + 텍스트 검색 + 컬러 스와치 카드 + DESIGN.md 모달로 탐색 가능하게 했다. INDEX.md 파싱은 정규식 기반 + mtime 캐싱 적용. 경로 탈출 방어도 적용.

---

## 수정 파일 목록

- `/home/jay/workspace/dashboard/server.py` — API 엔드포인트 2개 + 파싱 메서드 추가
- `/home/jay/workspace/dashboard/components/SystemView.js` — 섹션 토글 + 디자인MD UI 추가

## 구현 상세

### 백엔드 (server.py)

1. **GET /api/design-md/index** (871-878행)
   - INDEX.md를 정규식으로 파싱하여 JSON 반환
   - 8개 카테고리, 58개 사이트 정확히 파싱
   - mtime 기반 캐싱으로 반복 요청 최적화

2. **GET /api/design-md/{site}** (880-897행)
   - 특정 사이트의 DESIGN.md 전문 반환
   - 경로 탈출 방어: `urllib.parse.unquote` + `..` / `/` 차단 + `is_relative_to` 검증
   - 미존재 사이트 404 반환

3. **_parse_design_md_index 메서드** (3230-3304행)
   - DashboardHandler 클래스 내 정의
   - 카테고리 헤더 패턴: `### 카테고리명 (N개)`
   - 사이트 라인 패턴: `- **사이트명** — 설명 | colors | tags`
   - 파싱 실패 시 빈 결과 반환 (에러 안 던짐)

### 프론트엔드 (SystemView.js)

1. **섹션 토글** — pill 스타일 버튼 2개 (시스템상태 / 디자인MD), 기본값: 시스템상태
2. **검색** — 사이트명, 설명, 태그 통합 검색
3. **카테고리 필터** — 전체 + 8개 카테고리 칩, 복수 선택 가능
4. **사이트 카드 그리드** — 3컬럼 반응형, 사이트명/설명/컬러스와치/태그 표시
5. **상세 모달** — 카드 클릭 시 DESIGN.md 전문 표시, lazy fetch + useRef 캐싱
6. **기존 코드 무수정** — 시스템상태 내용은 Fragment로 감싸기만 함

## 테스트 결과

- `GET /api/design-md/index` → 8개 카테고리, 58개 사이트 정상 반환 (200)
- `GET /api/design-md/claude` → content 20,124자 정상 반환 (200)
- `GET /api/design-md/stripe` → content 20,450자 정상 반환 (200)
- `GET /api/design-md/nonexistent` → 404 "site 'nonexistent' not found"
- `GET /api/design-md/%2e%2e/...` → 400 "invalid site name" (경로 탈출 차단)
- `python3 -m py_compile server.py` → 문법 오류 없음

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **allSites useMemo 데이터 매핑 오류** — API 응답이 `{ categories: [...] }` 형태인데 `Object.entries(designMdIndex)` 사용. `designMdIndex.categories.flatMap(...)` 으로 수정 (SystemView.js:129)
2. **fetchDesignMdDetail 응답 파싱 오류** — API가 JSON `{ id, content }` 반환하지만 `r.text()` 사용. `r.json()`으로 변경 후 `data.content` 추출 (SystemView.js:56)
3. **경로 탈출(path traversal) 취약점** — `/api/design-md/../../etc/passwd` 가능. `unquote` + `..`/`/` 차단 + `is_relative_to` 검증 추가 (server.py:881-886)

## 모델 사용 기록

- 불칸(백엔드) / server.py API 엔드포인트 + 파싱 메서드 구현 / sonnet
- 이리스(프론트) / SystemView.js 섹션 토글 + 디자인MD UI 구현 / sonnet
- 헤르메스(팀장) / 통합 검토 + 버그 3건 직접 수정 + 보안 패치 / opus

## QC 체크리스트

- [x] 1. 영향 파일: server.py, SystemView.js (2개)
- [x] 2. 엣지 케이스: 빈 카테고리, 검색 결과 없음, 잘못된 사이트명, 경로 탈출
- [x] 3. 작업 지시와 정확히 일치 (토글, 카테고리 필터, 카드, 검색, 모달, API 2개)
- [x] 4. 보안: 경로 탈출 방어 적용
- [x] 5. API 테스트: 정상/에러/보안 케이스 6건 통과
- [x] 6. 발견 이슈 3건 모두 직접 해결
- [x] 7. SOLID/DRY: 파싱 로직 분리, 캐싱 적용
- [x] 8. API 인터페이스 신규 추가 — 본 보고서에 문서화
- [x] 9. 이미지/배너 작업 해당 없음
