# task-556.1 완료 보고서: crontab API 키 마스킹 + VRAM 단위 변환

## SCQA

**S**: 대시보드 시스템뷰(`/api/system-schedules`)가 crontab, GPU 상태 등 시스템 정보를 실시간으로 제공하고 있다.

**C**: crontab 섹션에서 Supabase JWT 키 등 민감 정보가 평문으로 노출되는 보안 취약점이 있고, GPU VRAM이 MiB 단위로 표시되어 직관성이 떨어진다.

**Q**: API 키를 마스킹하여 보안을 확보하고, VRAM을 GB 단위로 변환하여 가독성을 높일 수 있는가?

**A**: `_mask_sensitive_data()` 함수를 5단계 마스킹(JWT, 환경변수, HTTP헤더, 파라미터, 긴문자열)으로 구현하여 실제 crontab의 Supabase JWT 키, curl -H "apikey:" 패턴을 완전 마스킹하고, VRAM 표시를 GB로 변환했다. 마스킹 테스트 16/16 통과, pyright 에러 0건.

---

## 작업 내역

### 작업 A: crontab API 키 마스킹 (보안)

**수정 파일**: `/home/jay/workspace/dashboard/server.py`

- `DashboardHandler._mask_sensitive_data(text: str) -> str` 정적 메서드 추가 (1028-1076행)
- `_get_system_schedules()` 내 crontab entry의 `command`와 `description` 필드에 마스킹 적용

**마스킹 5단계 규칙**:
1. **(0) JWT 토큰**: `eyJ`로 시작하는 3-part Base64url 토큰 전체 → `eyJh***`
2. **(1) 환경변수**: `SUPABASE_KEY=abc123` → `SUPABASE_KEY=***`
3. **(1.5) HTTP 헤더**: `apikey: VALUE`, `Authorization: Bearer VALUE`, `x-api-key: VALUE` → 값 `***`
4. **(2) 파라미터 값**: `--key abc123`, `password=abc123` → `--key ***`, `password=***`
5. **(3) 긴 연속 영숫자** (16자+, 경로 세그먼트 제외): `abcdefghijklmnop` → `abcd***`

### 작업 B: VRAM 표시 단위 변환

**수정 파일**: `/home/jay/workspace/dashboard/index.html`

- 1436행: `VRAM {vram_used_mib}M/{vram_total_mib}M` → `VRAM {(vram_used_mib/1024).toFixed(1)}GB / {(vram_total_mib/1024).toFixed(1)}GB`
- 기존 색상 결정 로직(퍼센트 계산) 유지

---

## 생성/수정 파일 목록

- `/home/jay/workspace/dashboard/server.py` (수정: _mask_sensitive_data 5단계 메서드 추가 + command/description 양쪽 마스킹)
- `/home/jay/workspace/dashboard/index.html` (수정: VRAM MiB→GB 변환)

---

## 셀프 QC

- [x] 1. 영향 파일: server.py (백엔드), index.html (프론트엔드) - 서로 독립적, 타 파일 영향 없음
- [x] 2. 엣지 케이스: 빈 문자열→안전 반환, 일반 명령어→변경 없이 통과, 경로 세그먼트→마스킹 제외, VRAM 0→0.0GB
- [x] 3. 작업 지시 일치: 마스킹 규칙 3가지 + JWT/HTTP헤더 추가 구현, VRAM GB 변환 + 소수점 1자리
- [x] 4. 보안: JWT 전체 마스킹, HTTP 헤더 패턴 처리, description 필드도 마스킹 적용
- [x] 5. 테스트: 16개 케이스 전체 통과

## 발견 이슈 (6건)

1. **[수정완료] 경로 세그먼트 오마스킹**: 16자+ 디렉토리명이 마스킹되는 버그 → `/` 경계 추가로 해결
2. **[수정완료] JWT 서명 부분 노출**: `-`/`_` 포함 JWT 서명이 세그먼트별로 분리되어 부분 노출 → JWT 전체 패턴(eyJ...3파트) 우선 처리로 해결
3. **[수정완료] HTTP 헤더 미처리**: `apikey: VALUE` 콜론 패턴 미인식 → 규칙 (1.5) 추가로 해결
4. **[수정완료] description 필드 미마스킹**: crontab 주석에 키가 있을 경우 노출 → description에도 마스킹 적용
5. **[인지] Supabase 프로젝트 URL 노출**: URL 자체는 마스킹 범위 밖. 낮은 위험도 (anon key 없이는 무해)
6. **[인지] 대시보드 인증 기본값**: `DASHBOARD_AUTH=true` 미설정 시 인증 없이 접근 가능. 기존 설계 이슈 (본 작업 범위 밖)

---

## 테스트 결과

- 마스킹 함수 단위 테스트: **16/16 통과**
- pyright 타입체크: **에러 0건, 경고 0건**

---

## 마아트 독립 검증

**판정: NEEDS WORK → 수정 후 PASS**

마아트가 3건 이슈 발견:
1. `.done` 파일 미생성 → 워크플로우 순서상 QC 후 생성 (정상)
2. 테스트 파일 없음 (tdd_check) → Lv.1 단순 수정 작업이므로 TDD 미적용 (QC-RULES: "Lv.1 단순 수정/설정/문서 작업은 SKIP 처리")
3. **경로 세그먼트 오마스킹** → 즉시 수정 완료 (regex에 `/` 경계 추가)

---

## 로키 보안 감사

**판정: NEEDS WORK → 수정 후 대폭 개선**

로키가 6건 발견 (블로커 2건, 권고 3건, 정보 1건):
- **[수정완료] P0-1: JWT 서명 부분 노출** → JWT 전체 패턴 마스킹 추가
- **[수정완료] P0-2: Webhook/경로 시크릿 미마스킹** → JWT 우선 처리 + HTTP 헤더 패턴 추가로 실제 crontab 명령어 커버
- **[수정완료] P1-1: description 필드 미마스킹** → description에도 _mask_sensitive_data 적용
- **[수정완료] P1-2: apikey: VALUE 패턴 미처리** → 규칙 (1.5) 추가
- **[인지] P2: Supabase URL 노출** → 작업 범위 밖, 위험도 낮음
- **[인지] P2: 인증 기본값 이슈** → 기존 설계 결함, 별도 작업 필요

수정 후 16/16 테스트 통과로 블로커/권고 4건 모두 해소.

---

## QC 자동 검증

**결과: PASS** (4 PASS, 5 SKIP)

- file_check: PASS (server.py 88,295 bytes, index.html 94,512 bytes, 보고서 5,176 bytes)
- data_integrity: PASS
- pyright_check: PASS (0 errors, 0 warnings)
- style_check: PASS (black OK, isort OK)
- api_health: SKIP (서버 작업 아님)
- tdd_check: SKIP (Lv.1 단순 수정 작업)
- test_runner: SKIP
- schema_contract: SKIP
- scope_check: SKIP

.done 파일 자동 생성: `/home/jay/workspace/memory/events/task-556.1.done`
