refactor: comprehensive code quality, security, and release readiness improvements
Some checks failed
Lint & Test / test (push) Failing after 48s

Security: tighten CORS defaults, add webhook rate limiting, fix XSS in
automations, guard WebSocket JSON.parse, validate ADB address input,
seal debug exception leak, URL-encode WS tokens, CSS.escape in selectors.

Code quality: add Pydantic models for brightness/power endpoints, fix
thread safety and name uniqueness in DeviceStore, immutable update
pattern, split 6 oversized files into 16 focused modules, enable
TypeScript strictNullChecks (741→102 errors), type state variables,
add dom-utils helper, migrate 3 modules from inline onclick to event
delegation, ProcessorDependencies dataclass.

Performance: async store saves, health endpoint log level, command
palette debounce, optimized entity-events comparison, fix service
worker precache list.

Testing: expand from 45 to 293 passing tests — add store tests (141),
route tests (25), core logic tests (42), E2E flow tests (33), organize
into tests/api/, tests/storage/, tests/core/, tests/e2e/.

DevOps: CI test pipeline, pre-commit config, Dockerfile multi-stage
build with non-root user and health check, docker-compose improvements,
version bump to 0.2.0.

Docs: rewrite CLAUDE.md (202→56 lines), server/CLAUDE.md (212→76),
create contexts/server-operations.md, fix .js→.ts references, fix env
var prefix in README, rewrite INSTALLATION.md, add CONTRIBUTING.md and
.env.example.
This commit is contained in:
2026-03-22 00:38:28 +03:00
parent 07bb89e9b7
commit f2871319cb
115 changed files with 9808 additions and 5818 deletions

View File

@@ -532,7 +532,6 @@ input:-webkit-autofill:focus {
}
.tag-input-dropdown {
display: none;
position: absolute;
top: 100%;
left: 0;
@@ -545,6 +544,16 @@ input:-webkit-autofill:focus {
margin-top: 4px;
max-height: 200px;
overflow-y: auto;
opacity: 0;
transform: translateY(-4px);
pointer-events: none;
transition: opacity var(--duration-fast) ease-out,
transform var(--duration-fast) var(--ease-out);
}
.tag-input-dropdown.open {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
.tag-dropdown-item {
@@ -668,11 +677,14 @@ textarea:focus-visible {
z-index: var(--z-lightbox);
overflow: hidden;
opacity: 0;
transition: opacity 0.15s ease;
transform: translateY(-6px) scale(0.97);
transition: opacity var(--duration-fast) ease-out,
transform var(--duration-normal) var(--ease-out);
pointer-events: none;
}
.icon-select-popup.open {
opacity: 1;
transform: translateY(0) scale(1);
overflow-y: auto;
pointer-events: auto;
}
@@ -816,17 +828,26 @@ textarea:focus-visible {
/* ── Entity Palette (command-palette style selector) ─────── */
.entity-palette-overlay {
display: none;
display: flex;
position: fixed;
inset: 0;
z-index: var(--z-lightbox);
background: rgba(0, 0, 0, 0.5);
background: rgba(0, 0, 0, 0);
justify-content: center;
align-items: flex-start;
padding-top: min(20vh, 120px);
pointer-events: none;
opacity: 0;
backdrop-filter: blur(0px);
transition: background var(--duration-fast) ease-out,
opacity var(--duration-fast) ease-out,
backdrop-filter var(--duration-fast) ease-out;
}
.entity-palette-overlay.open {
display: flex;
opacity: 1;
pointer-events: auto;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px);
}
.entity-palette {
width: min(500px, 90vw);
@@ -838,6 +859,14 @@ textarea:focus-visible {
display: flex;
flex-direction: column;
overflow: hidden;
opacity: 0;
transform: translateY(-12px) scale(0.98);
transition: opacity var(--duration-normal) var(--ease-out),
transform var(--duration-normal) var(--ease-out);
}
.entity-palette-overlay.open .entity-palette {
opacity: 1;
transform: translateY(0) scale(1);
}
.entity-palette-search-row {
display: flex;