refactor: comprehensive code quality, security, and release readiness improvements
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
@@ -280,7 +280,7 @@ export function selectCalibrationLine(idx: number): void {
const prev = _state.selectedLine;
_state.selectedLine = idx;
// Update selection in-place without rebuilding the list DOM
const container = document.getElementById('advcal-line-list');
const container = document.getElementById('advcal-line-list')!;
const items = container.querySelectorAll('.advcal-line-item');
if (prev >= 0 && prev < items.length) items[prev].classList.remove('selected');
if (idx >= 0 && idx < items.length) items[idx].classList.add('selected');
@@ -361,14 +361,14 @@ function _buildMonitorLayout(psList: any[], cssId: string | null): void {
// Load saved positions from localStorage
const savedKey = `advcal_positions_${cssId}`;
let saved = {};
try { saved = JSON.parse(localStorage.getItem(savedKey)) || {}; } catch { /* ignore */ }
try { saved = JSON.parse(localStorage.getItem(savedKey) ?? '{}') || {}; } catch { /* ignore */ }
const canvas = document.getElementById('advcal-canvas') as HTMLCanvasElement;
const canvasW = canvas.width;
const canvasH = canvas.height;
// Default layout: arrange monitors in a row
const monitors = [];
const monitors: any[] = [];
const padding = 20;
const maxMonW = (canvasW - padding * 2) / Math.max(psList.length, 1) - 10;
const monH = canvasH * 0.6;
@@ -423,7 +423,7 @@ function _placeNewMonitor(): void {
function _updateTotalLeds(): void {
const used = _state.lines.reduce((s, l) => s + l.led_count, 0);
const el = document.getElementById('advcal-total-leds');
const el = document.getElementById('advcal-total-leds')!;
if (_state.totalLedCount > 0) {
el.textContent = `${used}/${_state.totalLedCount}`;
el.style.color = used > _state.totalLedCount ? 'var(--danger-color, #ff5555)' : '';
@@ -436,7 +436,7 @@ function _updateTotalLeds(): void {
/* ── Line list rendering ────────────────────────────────────── */
function _renderLineList(): void {
const container = document.getElementById('advcal-line-list');
const container = document.getElementById('advcal-line-list')!;
container.innerHTML = '';
_state.lines.forEach((line, i) => {
@@ -470,7 +470,7 @@ function _renderLineList(): void {
}
function _showLineProps(): void {
const propsEl = document.getElementById('advcal-line-props');
const propsEl = document.getElementById('advcal-line-props')!;
const idx = _state.selectedLine;
if (idx < 0 || idx >= _state.lines.length) {
propsEl.style.display = 'none';
@@ -553,7 +553,7 @@ function _fitView(): void {
function _renderCanvas(): void {
const canvas = document.getElementById('advcal-canvas') as HTMLCanvasElement | null;
if (!canvas) return;
const ctx = canvas.getContext('2d');
const ctx = canvas.getContext('2d')!;
const W = canvas.width;
const H = canvas.height;
@@ -679,7 +679,7 @@ function _drawLineTicks(ctx: CanvasRenderingContext2D, line: CalibrationLine, x1
return (line.reverse ? (1 - f) : f) * edgeLen;
};
const placed = [];
const placed: number[] = [];
// Place intermediate labels at nice steps
for (let i = 0; i < count; i++) {