docs(history): расширенный прогон PASS=49 KNOWN=1 — дедуп по содержимому, валидация namespace только в POST

This commit is contained in:
Repinoid
2026-10-11 20:23:32 +03:00
parent fa16b02455
commit 4c24c6351c
+35
View File
@@ -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, иначе срабатывает дедуп и тест ложно падает.