---
task_id: task-2483
type: plan
scope: task
created: 2026-05-07
updated: 2026-05-07
status: completed
---

# 계획서: task-2483 — BOT_GITHUB_TOKEN 갱신 사이클 복구

**task**: task-2483
**목표**: 유실된 `scripts/refresh_bot_token.py`를 GitHub App JWT → installation token 갱신 흐름으로 재작성하여 systemd timer 50분 갱신 사이클을 복구. BOT_GITHUB_TOKEN graphql 401 해소 + task-2481 dogfooding layer 5 재개 가능 상태로 박제.
**승인**: 회장 (task 발행자) 2026-05-07 "merge_automation_recovery / infrastructure hardening"
**근거**: `memory/tasks/task-2483.md` (회장 명시 11단계) + `~/.claude/.../feedback_github_app_key_location_260507.md` (영구 명세)

---

## 목표

1. `scripts/refresh_bot_token.py` 재작성 — GitHub App PEM → JWT(RS256, exp=9분) → `POST /app/installations/{id}/access_tokens` → `.env.keys` 의 `BOT_GITHUB_TOKEN=` in-place 갱신.
2. `--dry-run` 옵션 + main PEM 부재 시 백업 PEM 자동 fallback.
3. fail-closed 정책: API 401/네트워크 실패 시 구 토큰 보존, audit reject.
4. `memory/orchestration-audit/bot-token-refresh.jsonl` append (sha256 hash + expires_at, 토큰 원문 절대 X).
5. systemd `refresh-bot-token.service` Type=oneshot exit 0 호환 + `systemctl --user daemon-reload` 후 즉시 1회 PASS.
6. `gh api graphql -f query='{viewer{login}}'` 200 응답 확인 (task-2481 401 해소 evidence).
7. 회귀 테스트 신설 — JWT 정상/PEM fallback/API 401 fail-closed/토큰 미로깅/audit append-only/systemd 호환 6항목.

## 범위

### 포함
- `scripts/refresh_bot_token.py` 신규 작성 (단일 파일, 회장 박제 명세 충실 구현)
- `tests/regression/test_refresh_bot_token.py` 신규 작성
- `memory/orchestration-audit/bot-token-refresh.jsonl` (audit log 초기 1줄 발생)
- systemd unit ExecStart 경로 검증 (이미 정상이면 무수정)
- runbook: 보고서 내 수동 갱신 / PEM 분실 복구 절차 1섹션

### 제외 (다음 task에서 처리)
- task-2481 layer 5 dogfooding 재개 자체 (본 task는 인증 경로만 복구)
- bot-authored PR 실제 발행 (smoke만 수행)
- `.gitignore`에 `.secrets/` 추가 (회장 별도 승인 필요)
- workflow / branch protection / dispatch.py / finish-task.sh 변경 (forbidden_actions)

## 위임 계획

- **Lugh (백엔드)**: `scripts/refresh_bot_token.py` 구현 + systemd 검증 + smoke 실행
- **Morrigan (테스터)**: `tests/regression/test_refresh_bot_token.py` 회귀 6항목 작성 + 로컬 pytest PASS 확인
- **Brigid / Aine**: 이 task에 미참여 (UI/UX 없음)

## 검증 기준

| 완료 기준 | 검증 명령 | 기대 결과 |
|---|---|---|
| (1) 스크립트 존재 | `ls scripts/refresh_bot_token.py` | 파일 존재 |
| (2) systemd 경로 | `systemctl --user cat refresh-bot-token.service` | ExecStart 정상 |
| (3) 수동 실행 | `python3 scripts/refresh_bot_token.py` | exit 0 + JSON 출력 |
| (4) 토큰 발급 | `expires_at` 응답 필드 | 1시간 미래 |
| (5) GraphQL 401 해소 | `gh api graphql -f query='{viewer{login}}'` | 200 + `data.viewer.login` |
| (6) bot-authored PR auth smoke | `curl -H "Authorization: Bearer $TOKEN" /app` | 200 + slug `jeon-jonghyuk-taskctl-bot` |
| (7) Gemini auto-review token 경로 | 동일 토큰으로 PR review API GET | 200 또는 의존성 명확 |
| (8) task-2481 layer 5 재개 가능성 | conditions 4건 중 1번 충족 명시 | "조건 1 PASS" 보고 |
| (9) 회귀 테스트 + 3문서 | `pytest tests/regression/test_refresh_bot_token.py -v` | 6/6 PASS |
