---
convoy: scan-visual-catalog-search
brief_number: 3
depends_on: [1]
recommended_model: composer-2.5-fast
model_tier: fast
files:
  - lib/card-visual-match.js
  - pages/api/scan/identify-by-image.js
  - lib/scanner-card-identify.js
  - lib/use-scanner-identification.js
  - test/lib/card-visual-match.test.js
---

# Brief 3: Layer-0 identify route + client orchestration

## Goal

kNN visual match before L1/L2; log `scan_attempts.layer = 0`.

## Acceptance criteria

- [ ] `POST /api/scan/identify-by-image` — auth + `checkScanRateLimit` + embed + kNN
- [ ] `identifyTrackedCardCapture` order: L0 → L1 → L2
- [ ] Gallery path runs L0 → L1 → L2
- [ ] Skip auto Gemini refine when disambiguation from L0 (same as L1)
- [ ] Thresholds: match 0.82, disambiguation 0.58
