identifier-normalization, no-hardcoded-vendors, vendor-installer-verification, and build-version-display follow the go-database split: rules in contract.md, snippets in README.md. Routed contract reads get cheaper; examples stay available on demand. Lint now also rejects stale kit/patterns references. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
43 lines
1.9 KiB
Markdown
43 lines
1.9 KiB
Markdown
# Contract: Identifier Normalization
|
||
|
||
Version: 1.1
|
||
|
||
## Purpose
|
||
|
||
Правила хранения и сравнения идентификаторов оборудования:
|
||
серийные номера, вендоры, версии прошивок, партномера, артикулы.
|
||
|
||
See `README.md` for Go and SQL examples.
|
||
|
||
## Правило
|
||
|
||
Оригинальное значение **сохраняется как пришло** — регистр не меняется.
|
||
Все сравнения, поиск и дедупликация выполняются **без учёта регистра**.
|
||
|
||
```
|
||
Пришло: "SN-001-ABC" → хранится: "SN-001-ABC"
|
||
Пришло: "sn-001-abc" → это тот же объект, не дубликат
|
||
```
|
||
|
||
## Применяется к полям
|
||
|
||
- Серийный номер (`serial_number`, `serial`)
|
||
- Вендор / производитель (`vendor`, `manufacturer`)
|
||
- Версия прошивки (`firmware_version`, `fw_version`)
|
||
- Партномер (`part_number`, `part_no`)
|
||
- Артикул (`article`, `sku`)
|
||
|
||
## Реализация
|
||
|
||
- Go: сравнение только через `strings.EqualFold`, никогда `==`.
|
||
- Go: ключ дедупликации в map — `strings.ToLower(value)`; сам объект хранит оригинал.
|
||
- SQL-поиск: `WHERE LOWER(col) = LOWER(?)`.
|
||
- Уникальность: MySQL/MariaDB — case-insensitive collation (`utf8mb4_unicode_ci`) +
|
||
unique index; SQLite — `CREATE UNIQUE INDEX ... ON t (LOWER(col))`.
|
||
|
||
## Что не делать
|
||
|
||
- Не приводить значение к нижнему или верхнему регистру перед сохранением.
|
||
- Не считать `"SN-001"` и `"sn-001"` разными объектами.
|
||
- Не использовать `==` для сравнения идентификаторов в Go — только `strings.EqualFold`.
|