alexei.dolgolyov
77284e8e7b
fix(activity-log): dashboard section reconciliation + activity column alignment
...
- dashboard full re-render now reconciles sections (only replaces changed ones) instead of wholesale .dashboard-dynamic innerHTML swap -> editing an entity no longer jumps the whole dashboard
- Recent Activity widget live DOM + perf strip preserved across re-renders; widget skips re-fetch when already populated (no flash)
- sweep stray non-section nodes so empty->populated doesn't leave an orphan 'no targets' banner (review-caught regression)
- Activity list rows use a CSS grid (fixed badge/actor columns) so message column aligns consistently across rows
2026-06-10 12:28:13 +03:00
alexei.dolgolyov
ff1ff06cb5
fix(activity-log): post-test polish - localize descriptions, dashboard widget, ticking time
...
- localize entry descriptions client-side via localizeMessage (activity_log.msg.* + entity_type.* templates x3 locales); server message kept as fallback/export/search
- remove redundant Activity header banner from tab
- Recent Activity widget is now a first-class dashboard section (Customize Dashboard show/hide/reorder; pre-existing layouts preserved)
- live activity event updates the widget surgically (no full dashboard rebuild); single listener with teardown
- relative-time labels tick via shared ensureRelativeTimeTicker (single 30s interval, visibility-aware)
2026-06-10 12:03:18 +03:00
alexei.dolgolyov
3dd1ac3f0d
fix(activity-log): final-review fixes - crosslink keys + sanitize parity
...
- _ENTITY_NAV map keys corrected to match backend entity_type (device, color_strip_source, audio_source data-id) + scene_playlist crosslink added
- sanitize_display applied uniformly to owner-authored names at remaining record sites (dependencies entity_name, device_health, automation_engine, output_targets_control, scene_presets, scene_playlists)
2026-06-09 21:23:22 +03:00
alexei.dolgolyov
6e1dd2111d
feat(activity-log): phase 6 - dashboard widget + settings panel + docs
...
- Dashboard 'Recent Activity' widget: latest 5 entries, live prepend, 'View all' -> Activity tab
- Settings 'Activity Log' panel: retention (enabled/max_days/max_entries) GET/PUT, clear (confirm + auth-required toast), CSV/JSON export
- audit-log vs ephemeral debug Log Viewer distinction note + cross-links
- public helpers fetchRecentEntries/renderCompactEntry on activity-log.ts (reused, no dup markup)
- README Activity Log section; i18n across en/ru/zh
- review fixes: clear 401 surfaces toast; empty widget transitions on first live event
2026-06-09 21:05:40 +03:00
alexei.dolgolyov
9a0137fa4c
feat(activity-log): phase 5 - Activity tab (smart filtering, live updates, export)
...
- new top-level Activity tab: filter toolbar (category/severity chips, presets, debounced search, actor/entity/date), keyset load-more, expandable detail
- live prepend via server:activity_logged; authed CSV/JSON blob export
- formatTimestamp/formatRelativeTime in core/ui.ts; history+severity SVG icons; Ctrl+7 shortcut
- i18n activity_log.* across en/ru/zh; getting-started tutorial step; activity-log.css (themed)
- review fixes: newest-first ordering, attribute-context XSS hardening (_escapeAttr + event delegation)
2026-06-09 20:42:44 +03:00
alexei.dolgolyov
4a0927521a
feat(activity-log): phase 4 - REST API (list/export/settings/clear)
...
- GET /activity-log: filtered, keyset-paginated list (categories/severities/actor/entity/date/q)
- GET /activity-log/export: streaming CSV/JSON, chunked keyset (releases DB lock per batch), CSV formula-injection guard
- GET/PUT /activity-log/settings: retention config (PUT require_authenticated)
- DELETE /activity-log: clear (require_authenticated, self-audited)
- security: export DoS fix, settings-PUT auth gate, CSV \t/\r guard, metadata-as-JSON
- 122 API tests (auth posture, CSV injection, pagination integrity, filters, settings bounds, clear-audited)
2026-06-09 20:09:46 +03:00
alexei.dolgolyov
25c613c5cb
feat(activity-log): phase 3 - event instrumentation (4 categories)
...
- entity CRUD via fire_entity_event choke point (name resolved/sanitized; deletes pass name explicitly)
- auth: failures + WS session establishment (no tokens logged); per-IP audit-record throttle
- device: online/offline (health), discovered/lost (zeroconf), ADB connect/disconnect
- capture/system: target start-stop, scenes, playlists, automations, backup/restore, update, restart, calibration, settings
- security hardening: sanitize_display strips control/NUL/ANSI/newlines from untrusted strings; malformed-IPv6 origin guard
- 129 instrumentation tests (incl. secret-leak, log-injection, throttle, best-effort) + autouse throttle-reset fixture
2026-06-09 19:20:57 +03:00
alexei.dolgolyov
726f39e2ba
feat(activity-log): phase 2 - recorder, actor context, retention, lifecycle
...
- ActivityRecorder: thread-safe record() (inline on loop, call_soon_threadsafe off-loop), best-effort, fires activity_logged event
- current_actor ContextVar set in verify_api_key (both branches), default system
- ActivityLogRetentionEngine: prune loop (max_days+max_entries), settings persistence, rehydrates recorder.enabled on startup
- lifespan wiring: server.shutting_down recorded first on shutdown, retention stop before db.close
- events-ws.ts allowlist + parity; DI getters + module accessor; 62 new tests
2026-06-09 18:10:27 +03:00
alexei.dolgolyov
1ac4a0f66d
feat(activity-log): phase 1 - storage model, migration, repository
...
- ActivityLogEntry dataclass + ActivityCategory/ActivitySeverity + ActivityLogFilters
- additive idempotent migration 002_add_activity_log (indexed activity_log table, seq keyset tiebreaker)
- ActivityLogRepository (record/query/count/prune/clear/iter_export), keyset pagination, parameterized SQL
- 102 unit + adversarial tests (SQL-injection, pagination, prune, codec, migration idempotency)
2026-06-09 17:40:37 +03:00
alexei.dolgolyov
1afe7d6fcc
chore(activity-log): scaffold feature plan and phase subplans
2026-06-09 17:14:50 +03:00