Move inline code examples out of normative contracts

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>
This commit is contained in:
2026-06-12 10:00:02 +03:00
parent 421d004faf
commit a44133aff2
9 changed files with 201 additions and 221 deletions

View File

@@ -0,0 +1,54 @@
# Identifier Normalization Pattern Notes
This file keeps examples. The normative rules live in `contract.md`.
## Go — сравнение
```go
import "strings"
func SameIdentifier(a, b string) bool {
return strings.EqualFold(a, b)
}
```
## Go — дедупликация
```go
func deduplicateBySerial(items []Device) []Device {
seen := make(map[string]struct{})
result := items[:0]
for _, item := range items {
key := strings.ToLower(item.SerialNumber)
if _, exists := seen[key]; !exists {
seen[key] = struct{}{}
result = append(result, item)
}
}
return result
}
```
## SQL — поиск и уникальность
Поиск:
```sql
SELECT * FROM devices WHERE LOWER(serial_number) = LOWER(?);
```
Уникальный индекс (MySQL / MariaDB):
```sql
-- Collation ci обеспечивает case-insensitive уникальность
ALTER TABLE devices MODIFY serial_number VARCHAR(255)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE devices ADD UNIQUE INDEX uniq_serial (serial_number);
```
SQLite:
```sql
CREATE UNIQUE INDEX uniq_serial ON devices (LOWER(serial_number));
```

View File

@@ -1,13 +1,13 @@
# Contract: Identifier Normalization
Version: 1.0
Version: 1.1
## Purpose
Правила хранения и сравнения идентификаторов оборудования:
серийные номера, вендоры, версии прошивок, партномера, артикулы.
---
See `README.md` for Go and SQL examples.
## Правило
@@ -17,11 +17,8 @@ Version: 1.0
```
Пришло: "SN-001-ABC" → хранится: "SN-001-ABC"
Пришло: "sn-001-abc" → это тот же объект, не дубликат
Пришло: "Sn-001-Abc" → то же самое
```
---
## Применяется к полям
- Серийный номер (`serial_number`, `serial`)
@@ -30,61 +27,13 @@ Version: 1.0
- Партномер (`part_number`, `part_no`)
- Артикул (`article`, `sku`)
---
## Реализация
### Go сравнение
```go
import "strings"
func SameIdentifier(a, b string) bool {
return strings.EqualFold(a, b)
}
```
### Go — дедупликация
```go
func deduplicateBySerial(items []Device) []Device {
seen := make(map[string]struct{})
result := items[:0]
for _, item := range items {
key := strings.ToLower(item.SerialNumber)
if _, exists := seen[key]; !exists {
seen[key] = struct{}{}
result = append(result, item)
}
}
return result
}
```
Ключ в map — всегда `strings.ToLower(value)`. Сам объект сохраняется с оригинальным значением.
### SQL — поиск и уникальность
Поиск:
```sql
SELECT * FROM devices WHERE LOWER(serial_number) = LOWER(?);
```
Уникальный индекс (MySQL / MariaDB):
```sql
-- Collation ci обеспечивает case-insensitive уникальность
ALTER TABLE devices MODIFY serial_number VARCHAR(255)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE devices ADD UNIQUE INDEX uniq_serial (serial_number);
```
SQLite:
```sql
CREATE UNIQUE INDEX uniq_serial ON devices (LOWER(serial_number));
```
---
- 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))`.
## Что не делать