# 아리(Ari) 운영 런북 (phase-15)

> 제3자가 이 문서만으로 기동·마이그레이션·롤백·모니터링·장애 대응을 수행할 수 있도록 작성.

## 0. 구성

- **frontend** (Next.js standalone, :3000) · **backend** (gunicorn+uvicorn, :8000) · **worker**(스케줄러 전용, `WORKER_ENABLED=true` 1개만) · **ollama**(로컬 LLM) · **db**(SQLite 볼륨 또는 Postgres) · **caddy**(리버스 프록시 + 자동 HTTPS).
- 인증: `AUTH_ENABLED=true`(운영) / `false`(데모·CI). per-user 스코프는 `user_id` 컬럼 + `auth/scope.scoped()`.

## 1. 기동 / 재기동

```bash
cd deploy
cp .env.prod.example .env.prod          # 값 채우기(아래 2. 비밀)
docker compose up -d --build                                  # dev(SQLite)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build  # prod(Postgres)
docker compose restart backend worker   # 코드/설정 변경 후
```

## 2. 비밀(필수)

```bash
docker compose run --rm backend python -m scripts.gen_secret   # SESSION_SECRET / ARI_SECRET_KEY 출력
# → .env.prod 에 기입. 기본 'insecure' 값이 남아 있으면 ARI_ENV=prod 기동을 거부하도록 운영.
```

- `password_hash`(pbkdf2)·`token_hash`(sha256)·커넥터 `token_enc`(Fernet) — 평문 저장 0건.

## 3. 마이그레이션 / 시드

```bash
docker compose run --rm backend alembic upgrade head           # 스키마 최신화
docker compose run --rm backend alembic downgrade -1           # 롤백 1단계
# 데모→실 전환: AUTH_ENABLED=true 설정 후 upgrade(=user_id 'jiwoo' 백필) + 시드로 자격 생성
docker compose run --rm backend python -m app.seed             # 데모 리셋(reset=True)
docker compose run --rm backend python -m app.seed --no-reset  # 멱등(운영 데이터 보존)
```

## 4. 백업 / 복구

```bash
docker compose exec backend scripts/backup.sh                  # → /backups/ari-<ts>.db.gz (SQLite .backup, 락 안전)
docker compose exec backend scripts/restore.sh /backups/ari-<ts>.db.gz
docker compose restart backend worker
# SQLite→Postgres 이관:
docker compose run --rm -e PG_URL=postgresql+psycopg://ari:pw@db/ari backend \
  python -m scripts.migrate-sqlite-to-postgres                 # 행 수 일치 검증
```

## 5. 모니터링

- **liveness**: `GET /api/health` → `{"status":"ok"}`
- **readiness**: `GET /api/ready` → `{ready, checks:{db,migrations,llm,worker}}` (LLM 미가용=`fallback:heuristic`, 차단 아님)
- **메트릭**: `GET /api/metrics`(내부망만 — Caddy 가 외부 404). 핵심: `ari_http_latency_seconds`, `ari_llm_calls_total`, `ari_worker_jobs_total`, `ari_approvals_total`, `ari_saved_minutes_total`.
- **로그**: `docker compose logs -f backend | jq` (JSON 한 줄/요청 — request_id·user_id·path·status·dur_ms).

## 6. 능동 레이어(worker)

```bash
# 수동 트리거(WORKER_ENABLED=false 시):
docker compose exec backend curl -X POST localhost:8000/api/worker/run/digest
docker compose exec backend curl -X POST localhost:8000/api/worker/run/proactive
# 스케줄(digest 09:00/13:00/18:30, proactive 30m, weekly 일요일 20:00) — worker 컨테이너만 1개 true.
```

## 7. 장애 대응

- **LLM 느림/다운**: 자동 `heuristic` 폴백(서비스 중단 아님). `docker compose restart ollama`.
- **DB 락(SQLite)**: WAL + busy_timeout. 지속 시 Postgres 승격(§4 이관).
- **커넥터 토큰 만료**: 라이프 "연결 안 됨"(`token_expired`) → 재인증 유도. mock 폴백으로 페이지 동작.
- **인증 사고**: 전 세션 폐기 = `auth_session.revoked=true` 일괄 UPDATE; `SESSION_SECRET` 로테이션 후 재기동(기존 쿠키 무효).
- **프롬프트 인젝션 의심**: `audit_log` `prompt_injection.suspected` 확인. 외부 행동(전송/결제)은 결재함 high-risk 게이트로만 — 자동 실행 0.

## 8. 롤백

```bash
git revert <sha> && docker compose up -d --build
# 스키마 롤백 필요 시: alembic downgrade -1 + 백업 복구(§4).
```
