refactor: comprehensive code quality, security, and release readiness improvements
Some checks failed
Lint & Test / test (push) Failing after 48s
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:
@@ -16,7 +16,7 @@ from wled_controller import __version__
|
||||
from wled_controller.api import router
|
||||
from wled_controller.api.dependencies import init_dependencies
|
||||
from wled_controller.config import get_config
|
||||
from wled_controller.core.processing.processor_manager import ProcessorManager
|
||||
from wled_controller.core.processing.processor_manager import ProcessorDependencies, ProcessorManager
|
||||
from wled_controller.storage import DeviceStore
|
||||
from wled_controller.storage.template_store import TemplateStore
|
||||
from wled_controller.storage.postprocessing_template_store import PostprocessingTemplateStore
|
||||
@@ -72,17 +72,19 @@ cspt_store = ColorStripProcessingTemplateStore(config.storage.color_strip_proces
|
||||
sync_clock_manager = SyncClockManager(sync_clock_store)
|
||||
|
||||
processor_manager = ProcessorManager(
|
||||
picture_source_store=picture_source_store,
|
||||
capture_template_store=template_store,
|
||||
pp_template_store=pp_template_store,
|
||||
pattern_template_store=pattern_template_store,
|
||||
device_store=device_store,
|
||||
color_strip_store=color_strip_store,
|
||||
audio_source_store=audio_source_store,
|
||||
value_source_store=value_source_store,
|
||||
audio_template_store=audio_template_store,
|
||||
sync_clock_manager=sync_clock_manager,
|
||||
cspt_store=cspt_store,
|
||||
ProcessorDependencies(
|
||||
picture_source_store=picture_source_store,
|
||||
capture_template_store=template_store,
|
||||
pp_template_store=pp_template_store,
|
||||
pattern_template_store=pattern_template_store,
|
||||
device_store=device_store,
|
||||
color_strip_store=color_strip_store,
|
||||
audio_source_store=audio_source_store,
|
||||
value_source_store=value_source_store,
|
||||
audio_template_store=audio_template_store,
|
||||
sync_clock_manager=sync_clock_manager,
|
||||
cspt_store=cspt_store,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -128,10 +130,12 @@ async def lifespan(app: FastAPI):
|
||||
device_store=device_store,
|
||||
)
|
||||
|
||||
# Create auto-backup engine
|
||||
# Create auto-backup engine — derive paths from storage config so that
|
||||
# demo mode auto-backups go to data/demo/ instead of data/.
|
||||
_data_dir = Path(config.storage.devices_file).parent
|
||||
auto_backup_engine = AutoBackupEngine(
|
||||
settings_path=Path("data/auto_backup_settings.json"),
|
||||
backup_dir=Path("data/backups"),
|
||||
settings_path=_data_dir / "auto_backup_settings.json",
|
||||
backup_dir=_data_dir / "backups",
|
||||
store_map=STORE_MAP,
|
||||
storage_config=config.storage,
|
||||
)
|
||||
@@ -314,14 +318,17 @@ templates = Jinja2Templates(directory=str(templates_path))
|
||||
@app.exception_handler(Exception)
|
||||
async def global_exception_handler(request, exc):
|
||||
"""Global exception handler for unhandled errors."""
|
||||
logger.error(f"Unhandled exception: {exc}", exc_info=True)
|
||||
import uuid
|
||||
|
||||
ref_id = uuid.uuid4().hex[:8]
|
||||
logger.error("Unhandled exception [ref=%s]: %s", ref_id, exc, exc_info=True)
|
||||
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={
|
||||
"error": "InternalServerError",
|
||||
"message": "An unexpected error occurred",
|
||||
"detail": str(exc) if config.server.log_level == "DEBUG" else None,
|
||||
"message": "Internal server error",
|
||||
"ref": ref_id,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user