# DB 조회 — 무엇이 열려 있고, 무엇을 어디에 물어야 하나

`af-db` MCP 서버가 **한 MongoDB 서버의 데이터베이스 넷**을 읽기 전용으로 연다.
설정은 `tools/af-data/config.json`, 강제 장치는 `.claude/hooks/enforce-db-scope.mjs`.

---

## ⚠️ 이름이 바뀌었다 (2026-09-15)

| 이전 | 현재 |
|---|---|
| MCP 서버 `scanner-db` | **`af-db`** |
| 도구 이름 `mcp__scanner-db__*` | **`mcp__af-db__*`** |
| 훅 `enforce-scanner-first.mjs` | **`enforce-db-scope.mjs`** |
| 배포 폴더 `tools/scanner-data/` | **`tools/af-data/`** |

안내서 이름(`scanner-data` · `tracker-data`)은 **바뀌지 않았다.**

**`docs/experiments/**` 의 실험 기록은 옛 이름을 그대로 쓴다.** 그건 그때 실제로 그
이름으로 실행했다는 기록이라 고치지 않는다 — 재현할 때 이 표로 바꿔 읽으면 된다.
(`Move docs` 커밋이 참조 29개 중 21개를 미아로 만든 전례가 있어, 이번에는 매핑을 남긴다.)

이름을 바꾼 이유는 단순하다. DB 가 둘에서 넷으로 늘었는데 이름이 스캐너 하나를 가리키고
있었다.

---

## 네 데이터베이스

| DB | 안내서 | 토큰 수 | 이 DB 만 답할 수 있는 것 |
|---|---|---|---|
| `af-social-scanner` | `scanner-data` | 181,410 | 링크의 **내용** — 계정·게시물·정지 여부·인용 체인 |
| `af-trade-stream` | `trade-stream-data` | **628,276** | **비율의 분모.** AF 매매량·시총·LAF 랭크 |
| `sol-af-tracker` | `tracker-data` | ~1.86M | 가격·ATH·AF 배팅 총액 |
| `sol-token-metrics-recorder` | `metrics-data` | 최근 **10일** | 신규 발행·졸업과 그 시각 |

### 모집단을 고르는 규칙

두 함정이 **서로 반대 방향**이라 하나만 기억하면 다른 쪽에 걸린다.

- **tracker 에서 시작하지 마라.** 1.86M 중 소셜 관측이 있는 건 0.5% 뿐이라,
  «수집한 적 없음» 이 «소셜이 없음» 으로 둔갑한다.
- **비율을 스캐너에서 재지 마라.** 스캐너는 AF 임계치를 넘은 것만 담는다.
  그 임계치는 관심 있는 모든 변수와 상관돼 있어서, 거기서 낸 비율은 편향된다.
  «몇 %가 소셜을 걸었나» 는 `af-trade-stream.raw_token_metas` 가 분모다.

**단, `af-trade-stream` 은 URL 칸이 `twitter`·`website` 둘뿐이다.**
텔레그램·틱톡·인스타를 담을 자리가 없어 **플랫폼별 비율은 낼 수 없다.**
그건 스캐너가 답한다 — 대신 분모가 181,410 이라는 걸 밝혀야 한다.

---

## 훅이 막는 것

`.claude/hooks/enforce-db-scope.mjs` — **화이트리스트다. 아는 DB 가 아니면 막는다.**

| DB / 컬렉션 | 규칙 |
|---|---|
| `af-social-scanner` · `sol-token-metrics-recorder` | 제한 없음 |
| `af-trade-stream.raw_token_metas` | 제한 없음 (모집단) |
| `af-trade-stream.raw_token_flows` (2,418만) · `laf_rank_records` (2,098만) | `token_address` 필수 · 200 상한 · 집계는 첫 단계가 `$match` |
| `sol-af-tracker` 전체 | 위와 같음 + DB 단위 요약(`db-stats` · `aggregate-db`) 차단 |
| 그 밖의 DB · `database` 미지정 | **거부** |

2026-09 이전 판은 tracker 만 걸러내고 나머지를 전부 통과시켰다. DB 가 넷이 되면서 그
기본값이 구멍이 됐다 — 새로 붙는 DB 가 검증 없이 열린다. 그래서 기본값을 deny 로 뒤집었다.

**크로스 DB `$lookup` 은 불가능하다.** 조합은 «주소 뽑기 → `$in` 으로 반대편 조회 → 병합»
2단계이고, 한 번에 200개까지다. 넘으면 뒤를 넓히지 말고 앞을 좁힌다.

---

## 비개발자 배포

`tools/af-data/` 폴더를 통째로 전달하고 `./af-data/install.sh` 를 실행하게 한다.
절차·주의사항은 `tools/README.md`.
