# task-1191.1 완료 보고서: 대시보드 파일 뷰어 — /home/jay/projects/ 경로 접근 허용

## SCQA

**S**: 대시보드 파일 뷰어는 보고서 내 산출물 파일 클릭 시 `/api/file` 엔드포인트를 통해 파일을 로드한다. `ALLOWED_PREFIXES`에 12개 workspace 상대경로가 등록되어 있다.

**C**: `/home/jay/projects/` 하위 파일(ThreadAuto 카드뉴스 이미지 등)은 workspace 밖 절대경로이므로 `ALLOWED_PREFIXES` 매칭 실패 → "Access denied: path not in allowed directories" 에러 발생.

**Q**: 보안을 유지하면서 `/home/jay/projects/` 절대경로 접근을 허용할 수 있는가?

**A**: `server.py`의 `/api/file` 엔드포인트에 절대경로 전용 처리 블록을 기존 로직 앞에 삽입. `ALLOWED_ABSOLUTE_PATHS = ("/home/jay/projects/",)` 화이트리스트 + `Path.resolve()` 후 재확인으로 보안 확보. 테스트 11건 전체 통과(0.07s), 기존 테스트 161건 회귀 없음.

## 수정 내용

### 1. server.py — `/api/file` 엔드포인트 (라인 3125-3176)
- `ALLOWED_ABSOLUTE_PATHS = ("/home/jay/projects/",)` 상수 추가
- 절대경로(`/`로 시작) 감지 시 별도 코드 경로 진입:
  - 1차 확인: `rel_path.startswith(allowed_path)` — 허용 목록 매칭
  - 2차 확인: `Path.resolve()` 후 재확인 — symlink/`..` 우회 방지
  - 확장자 화이트리스트(18종) 및 민감파일(.env 등) 차단
  - 이미지는 base64 data URI, 텍스트는 UTF-8로 응답
- 블록 끝 `return`으로 기존 workspace 상대경로 로직과 완전 분리
- 기존 `ALLOWED_PREFIXES`, `normalize_file_path()`, workspace 범위 체크 — 변경 없음

### 2. 프론트엔드 확인 결과
- `dashboard/components/utils.js`의 `FileViewerModal` (라인 734-750): `encodeURIComponent(path)`로 절대경로를 그대로 전송 → 수정 불필요

## 산출물 파일

- `/home/jay/workspace/dashboard/server.py` (수정)
- `/home/jay/workspace/dashboard/tests/test_file_api.py` (신규)

## 테스트 결과

- `dashboard/tests/test_file_api.py`: 11/11 PASSED (0.07s)
  - TestNormalizeFilePath (5건): 상대경로, workspace 절대경로, `./` 제거, projects 절대경로, 축약경로
  - TestAllowedAbsolutePaths (6건): projects 허용, `/etc/` 차단, `/home/jay/` 차단, `..` 탈출 방지, 확장자, 민감파일
- 기존 dashboard 테스트: 161 passed, 4 failed
  - ⚠️ 기존 테스트 실패 4건 (본 작업 범위 외): `test_composite_status.py` — composite_teams 기능 관련

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **test_file_api.py 미사용 import (os, pytest)** — pyright 경고 대응으로 직접 제거
   - 상세: `/home/jay/workspace/dashboard/tests/test_file_api.py` 라인 2, 6 삭제
2. **ALLOWED_EXTENSIONS/BLOCKED_EXTENSIONS 상수 중복** — 절대경로 블록과 기존 블록에 동일 상수 존재. 기존 코드 수정 최소화 원칙에 따라 의도적으로 유지 (향후 공통 함수 추출 가능)
3. **`..` 체크 순서 확인** — `normalize_file_path` 후 `..` 체크(3122) → 절대경로 체크(3127) 순서가 올바른지 검증. `/home/jay/projects/foo/../bar` 같은 경로는 `..` 체크에서 먼저 차단되므로 안전

### 범위 외 미해결 (1건)
1. **test_composite_status.py 4건 실패** — 범위 외 사유: composite_teams 기능 관련 기존 실패, 파일 API 수정과 무관

## 보안 검증 요약

- `/home/jay/projects/ThreadAuto/output/foo.png` → ✅ 허용
- `/etc/passwd` → ❌ 차단 (ALLOWED_ABSOLUTE_PATHS 미매칭)
- `/home/jay/.bashrc` → ❌ 차단 (ALLOWED_ABSOLUTE_PATHS 미매칭)
- `/home/jay/projects/../.bashrc` → ❌ 차단 (`..` 체크에서 먼저 차단)
- symlink `/home/jay/projects/evil` → `/etc/` → ❌ 차단 (resolve 후 재확인)
