# Ownership 검증 + 첫 승인 플레이북

IndieIndex 운영자용. Ownership proof는 **도메인 통제 확인만** 한다. editorial 승인·`link_rel=follow`와는 별개다.

## 원칙 (잠김)
- 신규 서드파티 기본값: `ownership_status=unclaimed`, `editorial_status=unreviewed`, `link_rel=nofollow` (렌더 `rel="ugc nofollow"`)
- Proof 성공 ≠ 자동 공개 ≠ follow 부여
- Utileno founding만 예외 (`verified` / `approved` / `follow`)
- 자동 공개 금지: 큐 → 리뷰 → `content/listings/` → `npm run build` → deploy

## A. Submit 큐 리뷰 (매일)

1. 서버: `ls /opt/indieindex/queue/pending/`
2. 스모크·스팸·중복 slug·죽은 URL·카테고리 밖 값 거절
3. 통과분만 로컬 `content/listings/{slug}.json`으로 승격 (submission 필드만 + ops 기본값)
4. `node scripts/submit-validate.mjs content/listings/{slug}.json` (있으면)
5. `npm run build` → `public/` tar → scp → `/var/www/indieindex` (`.well-known` 보존)
6. pending 파일은 `queue/rejected/` 또는 `queue/accepted/`로 이동(디렉터리 없으면 생성) 후 삭제하지 말고 감사 흔적 남김

### 승격 JSON ops 기본값 (서드파티)
```json
{
  "ownership_status": "unclaimed",
  "editorial_status": "unreviewed",
  "link_rel": "nofollow",
  "verification_status": "unverified",
  "founded_case": false,
  "example": false
}
```

## B. Ownership challenge E2E

### 제출자
1. `GET https://indieindex.xyz/api/v1/ownership/challenge?domain=PRODUCT_DOMAIN`
2. 응답 `token`으로 아래 **하나만** 배치
   - DNS TXT: `indieindex-verify=TOKEN` (apex 또는 product host)
   - Well-known: `https://PRODUCT/.well-known/indieindex.txt` 본문 `TOKEN` 또는 `indieindex-verify=TOKEN`
   - HTML meta: `<meta name="indieindex-verify" content="TOKEN">` on homepage
3. 운영자에게 slug + domain + 방식 알림

### 운영자 검증
1. 서버 challenge 파일: `/opt/indieindex/queue/challenges/{domain}.json` 의 `token`과 비교
2. 검증 명령 예:
   - DNS: `dig +short TXT PRODUCT_DOMAIN | grep indieindex-verify`
   - Well-known: `curl -fsS https://PRODUCT/.well-known/indieindex.txt`
   - Meta: `curl -fsS https://PRODUCT/ | grep indieindex-verify`
> DNS TXT 전파·HTTPS 점검은 공개 체커로 보조 가능: 레지스트리 검색 `q=dns` / `q=ssl` / `q=whois` (예: DNS Checker, SSL Labs). IndieIndex가 대행 검증 API를 제공하지는 않음.

3. 일치 시 listing JSON에만:
   - `ownership_status=verified`
   - `ownership_verified_at=ISO8601`
   - (레거시) `verification_status=verified`
4. **하지 말 것**: 이 단계에서 `editorial_status=approved` 또는 `link_rel=follow` 설정

챌린지 파일의 `verified: true` 표시는 선택(수동). Proof는 정적 빌드에 반영될 때까지 공개 상태에 안 보임.

## C. Editorial 승인 (별도)

Ownership과 무관하게 품질 리뷰:
- 실제 제품인지, 설명 정직성, 카테고리 적합성, 중복/스팸
- 통과 시 `editorial_status=approved`
- 홈/카테고리/에이전트 인덱스에 “unreviewed vs approved” 표시가 있으면 그에 맞춤

## D. Follow 부여 (별도, 드묾)

- Ownership verified **이후**에만 검토
- 자동·시간 경과 승격 금지
- 부여 시 `link_rel=follow` (렌더에서 ugc nofollow 제거)
- Utileno 외 follow는 운영자 명시 결정 + 사용자(키 pu) 확인 권장

## E. 첫 실전 승인 체크리스트

- [ ] pending 파일이 스모크/예시가 아님
- [ ] slug 충돌 없음 (`listings.json` / `content/listings/`)
- [ ] URL HEAD/GET 200
- [ ] submission에 operator 필드 없음
- [ ] ops 기본값 적용
- [ ] build + deploy 후 라이브 `/p/{slug}/` 확인
- [ ] (선택) ownership proof 후 verified만 갱신
- [ ] follow는 기본 보류

## F. 스모크·쓰레기 정리

- `live-api-smoke-*`, example.com 챌린지 등 운영 흔적은 큐를 오염시킴
- 사용자 확인 후 pending/challenges에서 제거 가능
- Colosseum `:80` / arena nginx는 절대 수정하지 않음

## Ops UX (locked 2026-09-13)
- Now: assistant chat-summarizes `queue/pending/`; user replies approve/reject in chat.
- Later: auth’d visual review page with click accept/reject (after process know-how).
- No public admin UI yet. Never auto-publish.
