# Task-520 완료 보고서: ThreadAuto 운영 인프라 구축

## SCQA

**S**: ThreadAuto가 온디맨드 단건 생성 파이프라인(task-516)으로 전환되어 `on_demand_runner.py`, `publish_worker.py`, `token_refresher.py`가 구현 완료된 상태이다.

**C**: 이 세 모듈을 수동으로만 실행할 수 있어 매일 빈 큐 생성, 발행 워커 상시 실행, 토큰 갱신이 자동화되지 않았다. 또한 이미지 서빙 서버(port 8080)가 systemd 미관리 상태로 재부팅 시 서비스가 중단될 수 있다.

**Q**: systemd service/timer로 자동화하여 무인 운영이 가능한가?

**A**: 4개 실행 스크립트 + 6개 systemd unit 파일 생성으로 전체 자동화 인프라 구축 완료. bash syntax 검증 4건, Python import 검증 3건, systemd verify 3건, HTTP 접근성 테스트 2건 모두 통과. 제이회장님이 `systemctl --user enable --now` 명령으로 활성화하면 즉시 운영 가능.

---

## 작업 내용

### 1. 빈 큐 자동 생성 (매일 05:00 KST)
- **신규**: `scripts/run_daily_queue.sh` — `generate_empty_daily_queue(date.today())` 호출
- **신규**: `threadauto-daily-queue.service` + `.timer` (systemd timer, 05:00 KST)
- `Persistent=true` 설정으로 서버 다운 시에도 다음 부팅 시 보상 실행

### 2. publish_worker 데몬 상시 실행
- **수정**: `scripts/run_publisher.sh` — `--systemd` 모드 추가 (foreground exec)
- **신규**: `threadauto-publisher.service` — `Restart=on-failure`, `RestartSec=30`

### 3. Tailscale Funnel 상시 실행
- **확인 완료**: 이미 Funnel 설정됨 (`/images` → 127.0.0.1:8080)
- `tailscaled.service`가 system 레벨에서 enabled 상태로 재부팅 시에도 지속
- 이미지 외부 접근 테스트: `https://aidevserver.tail2cdab6.ts.net/images/` → HTTP 200 확인

### 4. OAuth 토큰 자동 갱신
- **신규**: `scripts/run_token_refresh.sh` — `TokenRefresher().check_and_refresh()` 호출
- **신규**: `threadauto-token-refresh.service` + `.timer` (매일 03:00 KST)
- 현재 토큰 상태: valid, 잔여 52일 (만료: 2026-05-04)

### 5. 기존 스크립트 검증/수정
- **수정**: `scripts/run_daily.sh` — Step 2(배치 파이프라인) deprecated 처리, on_demand 전환
- **수정**: `scripts/run_publisher.sh` — `--systemd` foreground 모드 추가
- 이미지 서버 systemd 등록: `threadauto-image-server.service` (port 8080, WorkingDirectory=output/)

### 6. 기존 배치 cron 비활성화
- 확인: crontab에 ThreadAuto 관련 기존 cron 없음 (비활성화 불필요)

---

## 생성/수정 파일 목록

### 신규 생성
- `/home/jay/projects/ThreadAuto/scripts/run_daily_queue.sh` (chmod +x)
- `/home/jay/projects/ThreadAuto/scripts/run_token_refresh.sh` (chmod +x)
- `/home/jay/.config/systemd/user/threadauto-publisher.service`
- `/home/jay/.config/systemd/user/threadauto-daily-queue.service`
- `/home/jay/.config/systemd/user/threadauto-daily-queue.timer`
- `/home/jay/.config/systemd/user/threadauto-token-refresh.service`
- `/home/jay/.config/systemd/user/threadauto-token-refresh.timer`
- `/home/jay/.config/systemd/user/threadauto-image-server.service`

### 수정
- `/home/jay/projects/ThreadAuto/scripts/run_daily.sh` (배치→온디맨드 전환)
- `/home/jay/projects/ThreadAuto/scripts/run_publisher.sh` (--systemd 모드 추가)

---

## 테스트 결과

- bash -n syntax 검증: 4/4 통과
- Python import 검증: 3/3 통과 (on_demand_runner, token_refresher, publish_worker)
- systemd-analyze verify: 3/3 통과 (publisher, daily-queue, image-server)
- systemd unit 등록: 6/6 확인 (daemon-reload 완료)
- 이미지 서버 HTTP 응답: 200 OK (127.0.0.1:8080)
- Tailscale Funnel 이미지 접근: 200 OK (외부 URL)
- 토큰 상태: valid, 잔여 52일
- 스크립트 실행 권한: 4/4 확인 (rwxrwxr-x)

---

## 발견 이슈 및 수정

1. **import 경로 오류** (Critical): `run_token_refresh.sh`에서 `from auth.token_refresher`로 잘못 참조 → `from scheduler.token_refresher`로 수정
2. **exec+pipe 비호환** (Critical): `run_publisher.sh`의 `exec ... | tee`는 exec 후 pipe 불가 → `exec ... >> file 2>&1`로 수정
3. **set -u + PYTHONPATH** (Medium): 미설정 PYTHONPATH 참조 시 unbound variable 에러 → `${PYTHONPATH:-}` 패턴 적용
4. **이미지 서버 비관리** (Medium): bare process 실행 → systemd service 등록으로 안정성 확보

---

## sudo 필요 작업 (제이회장님 확인용)

- **sudo 불필요**: 모든 작업이 systemd user service로 구성됨
- `systemctl --user enable/start` 명령은 sudo 없이 실행 가능

---

## 활성화 명령 (제이회장님 확인 후 실행)

```bash
# 1. 이미지 서버 (현재 bare process → systemd 관리로 전환)
# 먼저 기존 프로세스 종료 필요: kill 133848
systemctl --user enable --now threadauto-image-server.service

# 2. 발행 워커 데몬
systemctl --user enable --now threadauto-publisher.service

# 3. 매일 05:00 KST 빈 큐 생성
systemctl --user enable --now threadauto-daily-queue.timer

# 4. 매일 03:00 KST 토큰 갱신
systemctl --user enable --now threadauto-token-refresh.timer

# 확인
systemctl --user status threadauto-publisher threadauto-image-server
systemctl --user list-timers
```

---

## 비고

- Tailscale Funnel 별도 systemd 불필요: `tailscaled.service`가 system 레벨 enabled 상태이며 funnel 설정이 persist됨
- `run_daily.sh`의 Step 1(auto_publisher.py)은 유지: 일부 모듈이 아직 참조할 수 있음
- 토큰 만료일(2026-05-04)까지 52일 남아 자동 갱신 타이머가 7일 전부터 갱신 시도

---

## QC 자동 검증 결과

```json
{
  "task_id": "task-520",
  "verified_at": "2026-03-13T10:03:43",
  "overall": "PASS",
  "checks": {
    "file_check": "PASS (5/5)",
    "data_integrity": "PASS",
    "tdd_check": "SKIP (인프라/설정 작업 — shell 스크립트에 TDD 미적용)",
    "pyright_check": "SKIP (Python 파일 없음)",
    "style_check": "SKIP (Python 파일 없음)"
  },
  "summary": "2 PASS, 7 SKIP"
}
```
