Хранилище и KYC¶
На какие вопросы отвечает¶
- Где OneWallet хранит файлы (документы KYC, медиа мини-аппов)?
- Что такое Garage и какие у нас бакеты?
- Как устроена автоматическая проверка KYC: OCR, сравнение лиц?
- Что делает
kyc-serviceи какие AI-движки он использует? - Почему лицо сверяет CompreFace, а не Gemini?
- Что происходит, если фото нечитаемо или лица не совпали?
- Как оператор и tier (уровень) вписываются в поток?
Хранилище: Garage (S3-совместимое)¶
Файлы лежат не в БД, а в объектном хранилище Garage (dxflrs/garage v2.2.0,
профиль compose s3). API совместим с S3, поэтому используется обычный AWS SDK
с forcePathStyle: true (см. projects/kyc-service/src/services/s3.js).
| Бакет | Назначение |
|---|---|
kyc-prod-data |
паспорта, селфи, штампы для KYC |
miniapps-media |
картинки/ассеты мини-аппов и баннеров |
Порты Garage (см. projects/deploy): S3 API 3900, admin 3902/3903,
web-UI 2080 (garage-ui).
Доступ к KYC-файлам — только через presigned URL с коротким TTL (5 минут,
EXPIRES_IN = 300). Воркер генерирует свежий URL на каждый запуск джобы;
сами байты по сети между сервисами не гоняются как вложения.
Сервис kyc-service¶
Node + BullMQ, профиль compose kyc (порт 3003, Redis DB 9). Это
worker-сервис: он потребляет джобы из очереди kyc-jobs, которые ставит
Auth Center после загрузки документов пользователем.
Payload джобы (контракт с Serverpod, не менять в одиночку):
{ userId, kycId, passportKey, selfieKey, stampKey? }.
Движки:
- OCR — Google Gemini (по умолчанию) или локальный Ollama.
Выбор через KYC_PROVIDER=gemini|ollama (src/services/ai.js).
- Сравнение лиц — CompreFace (модель ArcFace, профиль compose
compreface). LLM для матчинга лиц НЕ используется: эмбеддинги ArcFace
надёжно различают разных людей, а «визуальное впечатление» модели — нет.
Порог совпадения: FACE_MATCH_THRESHOLD (по умолчанию 0.75).
Параметры воркера: concurrency=3, до 5 попыток с backoff (rate-limit от
Gemini 429 переводится в отложенный ретрай).
Поток KYC¶
- Пользователь в приложении загружает паспорт + селфи (опционально штамп) →
файлы кладутся в
kyc-prod-data, Auth Center ставит джобу вkyc-jobs. - Воркер берёт presigned URL’ы и прогоняет OCR паспорта. Если все поля
пустые →
INVALID_PHOTO:passport(нечитаемо, без ретраев). - Face match через CompreFace. Нет лица на паспорте →
INVALID_PHOTO:passport, нет на селфи →INVALID_PHOTO:selfie. Score ниже порога →FACE_MISMATCH. - Результат (OCR-данные +
faceMatchScore) пишется вpublic.*черезupdateKycResult. Дальше — операторская проверка в admin-panel и присвоение tier (уровня лимитов).
Автоматика — только сигнал; финальное решение о повышении tier принимает оператор. Бизнес-описание уровней и сценариев см. в business-доке (ссылка ниже).
sequenceDiagram
participant App as Flutter App
participant AC as Auth Center
participant G as Garage (kyc-prod-data)
participant Q as BullMQ kyc-jobs
participant W as kyc-service worker
participant OCR as Gemini/Ollama
participant CF as CompreFace
participant Op as Оператор (admin-panel)
App->>G: upload паспорт + селфи
App->>AC: submit KYC
AC->>Q: enqueue {userId, kycId, keys}
Q->>W: job
W->>G: presigned URLs (TTL 5 мин)
W->>OCR: extractOcr(passport)
OCR-->>W: поля документа
W->>CF: verify(passport, selfie)
CF-->>W: similarity score
alt score >= threshold (0.75)
W->>AC: updateKycResult (OCR + score)
Op->>AC: проверка → присвоить tier
else нечитаемо / лица не совпали
W->>AC: updateKycFailed (INVALID_PHOTO / FACE_MISMATCH)
end
Пример¶
Загрузка с faceMatchScore = 0.83 (≥ 0.75): джоба завершается успехом,
в БД пишется OCR + score, статус идёт на операторскую проверку. При
score = 0.61 воркер бросает FACE_MISMATCH:0.61:... и помечает заявку
ocr_failed — повышение tier невозможно без переотправки документов.
Смежные материалы¶
- 02-services.md — карта сервисов и портов
- 03-data-and-schemas.md — схемы БД и cross-schema views
- 05-security-and-auth.md — PII-шифрование, step-up
- 07-deployment.md — профили compose, Garage/CompreFace
- Бизнес-поток KYC и уровни (tier): 05-kyc-flow.md
- Код и интеграции воркера:
../../projects/kyc-service/(docs/INTEGRATIONS.md,docs/DEPLOYMENT.md,docs/TESTING.md)