docs(history): расширенный прогон PASS=49 KNOWN=1 — дедуп по содержимому, валидация namespace только в POST
This commit is contained in:
@@ -227,3 +227,38 @@ consumer → per-tenant PostgreSQL → HTTP API.
|
||||
|
||||
Вывод: auth (bcrypt из PG), ACL (own-topic only, disconnect на нарушение), tenant-изоляция API
|
||||
(`namespace == sub`), проверка подписи JWT и дедуп повторов — работают на развёрнутом стенде.
|
||||
|
||||
## 10. Расширенный прогон — PASS=49 FAIL=0 KNOWN=1 (2026-10-11)
|
||||
|
||||
Скрипт `/tmp/e2e_suite.py` (~50 проверок на развёрнутом стенде).
|
||||
|
||||
**Что покрыто:** CRUD устройств (201/409/400/404/204) · лимиты идентификаторов
|
||||
(name/device_id 64 → 201, 65 → 400; namespace 56 → 201, 57 → 400) · пагинация
|
||||
(limit/offset, потолок 1000) · JWT (без токена 401, `sub`≠namespace 403, чужой
|
||||
ключ 401, истёкший 401, не-HS256 401) · MQTT (SUBACK на свой топик, round-trip,
|
||||
QoS1 → PUBACK, PINGRESP) · ACL-отказы с разрывом соединения (чужое устройство,
|
||||
wildcard, чужой namespace, 11 уровней топика при `max_topic_levels=10`, retained
|
||||
при `retain_available=false`, subscribe на `+/telemetry/+` и чужой ns) ·
|
||||
payload (не-JSON → строка, 200 КБ → доставлен, 20 сообщений подряд → 20/20) ·
|
||||
служебное (`/health`, `/healthz`, `/ready`, `/console`, `/iot-admin`, `/` = 200;
|
||||
`POST /health` = 405; `/iot-admin/stats` без токена 401).
|
||||
|
||||
**Найдено/подтверждено (требует решения):**
|
||||
|
||||
1. 🟡 **Дедуп — по СОДЕРЖИМОМУ.** `message_id = SHA256(ns|device_id|topic|payload)`
|
||||
(`bridge/handler.go:73`), поэтому два одинаковых payload подряд дают +1 строку
|
||||
(проверено: 49→50). Для реальных устройств это значит: если payload не содержит
|
||||
timestamp/счётчика, легитимные повторные одинаковые показания будут отброшены.
|
||||
Надо предупредить в документации для устройств (или включать ts в payload).
|
||||
2. 🟡 **Валидация namespace только в POST.** `validateIdentifier(ns, "namespace", 56)`
|
||||
вызывается только в `CreateIoTDevice` (`devices.go:168`); `GET/DELETE/PATCH`
|
||||
принимают любой ns → `200` (проверено: `GET /v1/namespaces/bad_ns/iot/devices` → 200).
|
||||
Хранилище такой ns отсекает (`safeNamespaceRe`), поэтому чтение телеметрии
|
||||
отдаёт `500` вместо `400`. Утечки нет (изоляция по `sub`), но реакция
|
||||
несогласованная — вынести проверку в общий middleware/хелпер.
|
||||
3. ⚪ `Dockerfile` (комментарий) обещает `/metrics` на порту API — маршрута нет (404).
|
||||
4. ⚪ Чтение телеметрии `?limit=200` возвращает payload'ы целиком (в тесте — 200 КБ
|
||||
на запись); при массовом опросе API ощутимо тормозит (наблюдалось на 200m CPU).
|
||||
|
||||
Методическая заметка: при повторных прогонах тесты «доставки» надо делать с
|
||||
уникальным payload, иначе срабатывает дедуп и тест ложно падает.
|
||||
|
||||
Reference in New Issue
Block a user