SHiNE-server/shine-solana/shine/doc/programs/shine_login_guard.md

147 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Программа `shine_login_guard`
Документ описывает целевое поведение программы классификации логинов SHiNE.
Задача программы:
- по логину определить класс регистрации;
- вернуть результат в `return_data`;
- не хранить PDA и не вести собственное состояние.
## 1. Назначение
`shine_login_guard` — маленькая служебная программа, которую вызывает `shine_users` через CPI до регистрации пользователя.
Она отвечает только на вопрос:
- можно ли зарегистрировать логин автоматически;
- является ли логин premium;
- является ли логин trademark/company.
## 2. Program ID
Текущий program id:
- `3xkopA7cXagxzMFrKdv3NCBfV6BKiRJCk69kr27M2sRo`
## 3. Состояние
У программы нет PDA-состояний и persistent storage.
Она опирается на статически сгенерированные словари, встроенные в бинарник на этапе сборки.
## 4. Внешние артефакты
Словари хранятся в:
- `src/dictionaries/premium/**/*.txt`
- `src/dictionaries/trademarks/**/*.txt`
На этапе build:
- все `.txt` файлы рекурсивно собираются;
- слова нормализуются;
- дубль-слова детектятся и логируются как warning;
- итоговые массивы слов вшиваются в generated Rust file.
## 5. Нормализация словаря
Слово словаря считается валидным, если:
- не пустое;
- длина не больше `20`;
- содержит только ASCII-буквы и цифры;
- после `trim()` и `lowercase()` остаётся валидным.
Символ `_` в словарных словах не допускается.
## 6. Единственная инструкция
Инструкция:
- `classify_login(login: String)`
Бинарный ABI инструкции:
```text
- tag: u8 = 1
- login_len: u32 LE
- login_bytes[login_len]: UTF-8
```
Аккаунты:
- аккаунты не требуются
Подпись транзакции для самой классификации не имеет бизнес-смысла. Если вызов идёт через CPI из `shine_users`, программа `shine_login_guard` не требует signer-аккаунтов вообще.
## 7. Выходные классы
Программа возвращает `u32` через `set_return_data`:
- `0``CLASS_FREE`
- `1``CLASS_PREMIUM`
- `2``CLASS_TRADEMARK`
## 8. Правила нормализации логина
Перед классификацией логин нормализуется:
- пустой логин запрещён;
- длина исходного логина не больше `20`;
- символ `_` удаляется;
- остальные символы обязаны быть ASCII alnum;
- буквы приводятся к нижнему регистру.
Если нормализация не удалась:
- логин считается `CLASS_PREMIUM`.
Это намеренно жёсткое поведение: сомнительный логин не должен автоматически попадать в free-класс.
## 9. Правила классификации
Алгоритм:
1. Нормализовать логин.
2. Попробовать разрезать его на `1..3` слов из словарей.
3. Если среди найденных частей есть trademark-слово, вернуть `CLASS_TRADEMARK`.
4. Если есть только premium-слова, вернуть `CLASS_PREMIUM`.
5. Если словарное совпадение не найдено и длина нормализованного логина `<= 7`, вернуть `CLASS_PREMIUM`.
6. Иначе вернуть `CLASS_FREE`.
## 10. Разбиение на слова
Максимум слов в логине:
- `3`
Алгоритм разбиения:
- DFS/backtracking по префиксам строки;
- на каждом шаге берётся префикс длиной `1..20`;
- если префикс найден в premium или trademark словаре, поиск продолжается на остатке строки;
- если найден хотя бы один путь с trademark-словом, итог = `CLASS_TRADEMARK`;
- если найден путь только с premium-словами, итог = `CLASS_PREMIUM`.
## 11. Инварианты
Должно быть сохранено при переписи:
- тот же способ нормализации логина;
- та же семантика классов `0/1/2`;
- тот же лимит `MAX_WORDS_PER_LOGIN = 3`;
- тот же fallback `len <= 7 => premium`, если словарь ничего не нашёл;
- тот же порядок приоритета `TRADEMARK > PREMIUM > FREE`.
## 12. Что не обязано сохраниться при переписи
Можно менять без изменения бизнес-логики:
- build pipeline словарей;
- структуру хранения слов внутри бинарника;
- способ поиска слов, если сохраняется тот же результат;
- техническую форму возврата, если внешний контракт для `shine_users` останется совместимым.
Но если меняется именно интерфейс `return_data` или классы, это уже требует обновления `shine_users` и документации.