docs: TODO + CLAUDE.md notes + locale keys for new features

TODO.md grows the device-support follow-up roadmap. CLAUDE.md trims a
stale section. en/ru/zh locales add the strings used by the new
HTTP-endpoint editor, MiniSelect labels, automations expansion, and
value-source kinds. Ru/zh parity for the older keys is tracked
separately in REVIEW_TODO.md.
This commit is contained in:
2026-05-23 00:50:31 +03:00
parent ddae5719cf
commit fd46c51dba
5 changed files with 436 additions and 23 deletions
+165
View File
@@ -1,5 +1,170 @@
# LedGrab TODO
## HTTP polling automation trigger
Goal: a new automation trigger that periodically polls an HTTP endpoint
and activates a scene when the response matches a condition. Split into
three single-responsibility entities so the endpoint can be reused
beyond automations (e.g. as a value-source driving brightness/color):
- `HTTPEndpoint` (storage/http_endpoint.py) — connection definition:
URL + auth + headers + timeout. NO polling cadence; NO extraction.
- `HTTPValueSource` (storage/value_source.py, source_type='http') —
references an endpoint + owns json_path + interval + min/max + EMA
smoothing. Backed by `HTTPValueStream` (core/processing/value_stream.py)
which lives under the existing `ValueStreamManager` (ref-counted,
one poll task per unique value source).
- `HTTPPollRule` (storage/automation.py) — thin: `{value_source_id,
operator, value}`. Reads `stream.get_raw_value()` from the value
source and compares with `_apply_operator`.
Pivoted from a 2-entity shape mid-build (was: HTTPSource+rule with
interval+json_path mushed). The 3-entity shape mirrors HA's pattern
(HomeAssistantSource → HAEntityValueSource → rule).
### Phase 1 — endpoint + value source + thin rule (backend) ✅
- [x] `storage/http_endpoint.py` — `HTTPEndpoint` dataclass with
secret_box auth_token encryption + `__post_init__` plaintext
invariant. NO `default_interval_s` (moved to value source).
- [x] `storage/http_endpoint_store.py` — `HTTPEndpointStore` with
`_migrate_plaintext_tokens()`. ID prefix `htep_`.
- [x] `storage/database.py` — `"http_endpoints"` in `_ENTITY_TABLES`
(replaces the old `"http_sources"`).
- [x] `storage/value_source.py` — added `HTTPValueSource` alongside
`HAEntityValueSource` (endpoint_id, json_path, interval_s,
min/max, smoothing). Registered in `_VALUE_SOURCE_MAP`.
- [x] `storage/value_source_store.py` — CRUD branch for `source_type =
"http"` + new kwargs on create/update.
- [x] `core/processing/value_stream.py` — `HTTPValueStream` with poll
task + `get_value()` (normalized 0-1) + `get_raw_value()` (raw
extracted value). Dispatched in `ValueStreamManager._create_stream`.
Manager now takes `http_endpoint_store` so the stream can resolve
endpoints at fetch time.
### Phase 2 — rule + engine wiring ✅
- [x] `storage/automation.py` — `HTTPPollRule` is now thin: just
`{value_source_id, operator, value}` (no http_source_id, no
json_path on the rule). Legacy keys silently dropped on load.
- [x] `core/automations/automation_engine.py` — drops the standalone
http_poll_manager; takes `value_stream_manager`. Engine
`_sync_value_stream_refs` acquires/releases value streams for
every enabled HTTPPollRule, mirroring the HA/MQTT sync pattern.
`_evaluate_http_poll` reads `stream.get_raw_value()` and applies
the operator. `_apply_operator` kept at module top.
- [x] `api/schemas/automations.py` — RuleSchema fields are now
`value_source_id + operator + value` (dropped http_source_id +
json_path).
- [x] `api/routes/automations.py` — `http_poll` factory updated.
### Phase 3 — CRUD endpoints + wiring ✅
- [x] `api/schemas/http_endpoints.py` — Create/Update/Response/List/Test
(no interval field; that's on the value source).
- [x] `api/routes/http_endpoints.py` — full CRUD + `/test` +
plaintext-http-token warning.
- [x] `api/schemas/value_sources.py` — `HTTPValueSource{Create,Update,Response}`
added to the discriminated unions.
- [x] `api/routes/value_sources.py` — `_RESPONSE_MAP` entry for
`HTTPValueSource`.
- [x] `api/__init__.py` — `http_endpoints_router` registered.
- [x] `api/dependencies.py` — `get_http_endpoint_store` (dropped the
http_poll_manager getter).
- [x] `main.py` — instantiate `HTTPEndpointStore`, pass it through
`ProcessorDependencies`, wire `value_stream_manager` +
`value_source_store` into `AutomationEngine`.
- [x] `core/processing/processor_manager.py` — `ProcessorDependencies`
gains `http_endpoint_store`; threaded into `ValueStreamManager`.
### Phase 4 — tests ✅
- [x] `tests/storage/test_http_endpoint_store.py` — 14 tests (CRUD +
auth_token encryption + headers + case-insensitive Authorization).
- [x] `tests/core/test_automation_engine.py` — `TestApplyOperator` +
`TestHTTPPollRuleEvaluation` (new shape: mock ValueStreamManager
with `_streams` dict) + `TestSyncValueStreamRefs` (acquire /
release / disabled-ignored) + `TestHTTPValueStreamExtraction`
(`_extract_simple_path` now lives in value_stream.py).
- [x] `tests/api/routes/test_http_endpoints_routes.py` — CRUD shape, no
auth_token leak in responses, schema-layer method allowlist,
CRLF / invalid header rejection, `/test` endpoint, LAN policy.
- [x] Removed: `tests/core/test_http_poll_manager.py` (manager deleted —
polling now lives inside `HTTPValueStream`).
- [x] Full suite: 1426 passed, ruff clean.
### Phase 5 — frontend ✅
- [x] `static/js/features/http-endpoints.ts` (new, ~540 LOC) — endpoint
CRUD, modal subclass with dirty-check, headers row editor, test
result rendering, card builder, event delegation. Mirrors
`home-assistant-sources.ts`.
- [x] `templates/modals/http-endpoint-editor.html` (new) — sectioned
rack-panel modal (Identity / Request / Headers / Notes) with
IconSelect method picker, password-toggle on auth token, inline
Test button + result block.
- [x] `static/js/features/value-sources.ts` — added `http` branch with
EntitySelect over `httpEndpointsCache`, edit-data/defaults,
`onValueSourceTypeChange` section toggle, save-payload assembly
+ required-field validation.
- [x] `templates/modals/value-source-editor.html` — new
`#value-source-http-section` with endpoint picker + json_path +
interval + min/max + smoothing.
- [x] `static/js/features/automations.ts` — `http_poll` rule type with
operator IconSelect + value-source EntitySelect; hides Value
field when operator is `exists`.
- [x] `static/js/features/integrations.ts` — `csHTTPEndpoints` section,
tree/tab entry, render + reconcile + delegation paths.
- [x] `static/js/types.ts` — `HTTPEndpoint`, `HTTPMethod`,
`HTTPEndpointListResponse`, `HTTPTestRequest/Response`,
`HTTPValueSource`, `HTTPPollOperator`; extended `RuleType` +
`AutomationRule`.
- [x] `static/js/core/state.ts` — `httpEndpointsCache` (`/http/endpoints`).
- [x] `static/js/core/icons.ts` — `http: P.globe` in
`_valueSourceTypeIcons`.
- [x] `templates/index.html` — includes
`modals/http-endpoint-editor.html`.
- [x] Locales: 77 new keys per file in `en.json` / `ru.json` /
`zh.json` (parity confirmed).
- [x] Verification: `npx tsc --noEmit` clean; `npm run build` clean
(app.bundle.css 366.6kb, app.bundle.js 2.7mb).
### Follow-ups (out of scope for initial PR)
- [ ] **Global concurrency cap / minimum interval.** Each
`HTTPValueStream` runs its own task at `interval_s` (min 1s); no
project-wide cap. Reviewer flagged: pick a min (e.g. 5s) + max
active runtimes (e.g. 32) + shared `httpx.AsyncClient` with
`limits=httpx.Limits(max_connections=N)`.
- [ ] **DNS-rebinding hardening.** `safe_request_bounded` validates
the URL hostname's resolved IPs once; httpx independently
re-resolves. The window is short but not zero. True fix: pin
to the validated IP + set Host header (and SNI for HTTPS). This
affects every outbound caller (`safe_fetch`, weather, image
sources) — handle as a project-wide hardening, not local to
this feature.
- [ ] **`delete_http_endpoint` orphan refs.** When an admin deletes an
endpoint referenced by N value sources, the value-stream task
keeps polling until its source is also deleted. Same shape as
the MQTT defect — fix both together (refuse-with-409 when in
use, or cascade value-source deletion).
- [ ] **Per-endpoint `connected` / last-poll status on the response**
(frontend agent flagged). `HTTPEndpointResponse` has no live
status, unlike HA/MQTT sources. Card LEDs default to "on".
Could aggregate `last_status_code` / `last_error` from all
`HTTPValueStream` instances referencing the endpoint and surface
on `GET /http/endpoints/{id}`.
- [x] **Per-endpoint live `/test` after save** — added `POST
/http/endpoints/{id}/test` (runs stored config server-side so the
auth token never round-trips) and wired a flask-icon test action
on the endpoint card (toasts the result). Custom-headers section
and inline test-result UI in the editor modal also restyled to
match the `.group-child-row` and result-card vocabulary.
- [ ] **Dedicated icon for HTTP value source / endpoint** (frontend
agent flagged). Both use `P.globe` — visually fine in practice
but adding a `cable`/`webhook` glyph in `icon-paths.ts` would
improve differentiation.
## Multi-broker MQTT refactor
Goal: drop the global `MQTTService` / `MQTTConfig`. Every MQTT consumer